Skip to content

Instantly share code, notes, and snippets.

@kostix
Last active September 5, 2023 09:16
Show Gist options
  • Save kostix/3c7ac9c1679c71787a272b8eed3a722b to your computer and use it in GitHub Desktop.
Save kostix/3c7ac9c1679c71787a272b8eed3a722b to your computer and use it in GitHub Desktop.
FindFirstFile/FindNextFile
#include <stdlib.h>
#include <stdio.h>
#include <locale.h>
#define WIN32_LEAN_AND_MEAN
#define _UNICODE
#include <windows.h>
int print_sys_error(DWORD last_error)
{
DWORD rc;
LPWSTR msg;
rc = FormatMessageW(
FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
last_error,
0,
(LPWSTR)&msg,
0,
NULL);
if (rc == 0) {
fputws(L"FormatMessage failed\n", stderr);
abort();
}
fputws(msg, stderr);
LocalFree(msg);
return 0;
}
DWORD print_matching(const wchar_t *pattern)
{
HANDLE hFile;
WIN32_FIND_DATAW ffd;
SetLastError(0);
hFile = FindFirstFileW(pattern, &ffd);
if (hFile == INVALID_HANDLE_VALUE) {
return GetLastError();
}
DWORD last_error = 0;
for (;;) {
if (FindNextFile(hFile, &ffd) == 0) {
DWORD rc;
rc = GetLastError();
if (rc == ERROR_NO_MORE_FILES) {
break;
}
last_error = rc;
break;
}
fputws(ffd.cFileName, stdout);
fputwc(L'\n', stdout);
}
FindClose(hFile);
return last_error;
}
wchar_t *get_pattern(const wchar_t *dirname, const size_t namelen)
{
const wchar_t wildcard[] = L"*.*";
const size_t wc_len = sizeof(wildcard)/sizeof(wildcard[0]);
size_t dstlen;
BOOL need_sep;
dstlen = namelen + wc_len;
need_sep = dirname[namelen-1] != L'\\';
if (need_sep) {
dstlen++;
}
wchar_t *pattern;
pattern = (wchar_t*)malloc(dstlen * sizeof(wchar_t));
if (pattern == NULL) {
fputws(L"out of memory\n", stderr);
abort();
}
wcscpy(pattern, dirname);
size_t wc_pos = namelen;
if (need_sep) {
pattern[wc_pos] = L'\\';
wc_pos++;
}
wcscpy(pattern + wc_pos, wildcard);
pattern[dstlen] = L'\0';
return pattern;
}
int wmain(int argc, const wchar_t **argv)
{
if (setlocale(LC_ALL, "") == NULL) {
fputws(L"setlocale failed\n", stderr);
abort();
}
wchar_t *pattern;
BOOL allocated;
switch (argc) {
case 2:
size_t namelen = wcslen(argv[1]);
if (namelen > 0) {
pattern = get_pattern(argv[1], namelen);
allocated = TRUE;
break;
}
// fall through
case 1:
pattern = L".\\*.*";
allocated = FALSE;
break;
default:
fputws(L"wrong number of arguments.\n", stderr);
return 2;
}
fputws(pattern, stdout);
fputwc(L'\n', stdout);
fflush(stdout);
DWORD rc;
rc = print_matching(pattern);
if (rc != 0) {
print_sys_error(rc);
}
if (allocated) {
free(pattern);
}
if (rc == 0) {
return 0;
}
return 1;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment