ReactOS 0.4.16-dev-980-g00983aa
findfile.cpp
Go to the documentation of this file.
1/***
2*findfile.c - C find file functions
3*
4* Copyright (c) Microsoft Corporation. All rights reserved.
5*
6*Purpose:
7* Defines _findfirst(), _findnext(), and _findclose().
8*
9*******************************************************************************/
10
11#include <corecrt_internal.h>
12#include <errno.h>
14#include <io.h>
15#include <stdlib.h>
16#include <string.h>
17#include <time.h>
19
20
21//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
22//
23// Utilities for working with the different file type and time data types
24//
25//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
26template <typename CrtTime>
27static CrtTime __cdecl convert_system_time_to_time_t(SYSTEMTIME const& st) throw();
28
29template <>
31{
32 return __loctotime32_t(st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, -1);
33}
34
35template <>
37{
38 return __loctotime64_t(st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, -1);
39}
40
41
42
43template <typename CrtTime>
44static CrtTime __cdecl convert_file_time_to_time_t(FILETIME const& ft) throw()
45{
46 // A FILETIME of 0 becomes a time_t of -1:
47 if (ft.dwLowDateTime == 0 && ft.dwHighDateTime == 0)
48 return static_cast<CrtTime>(-1);
49
50 SYSTEMTIME st_utc;
51 if (!FileTimeToSystemTime(&ft, &st_utc))
52 return static_cast<CrtTime>(-1);
53
54 SYSTEMTIME st_local;
55 if (!SystemTimeToTzSpecificLocalTime(nullptr, &st_utc, &st_local))
56 return static_cast<CrtTime>(-1);
57
58 return convert_system_time_to_time_t<CrtTime>(st_local);
59}
60
61
62
63template <typename Integer>
64static Integer convert_file_size_to_integer(DWORD const high, DWORD const low) throw();
65
66template <>
67__int64 convert_file_size_to_integer(DWORD const high, DWORD const low) throw()
68{
69 return static_cast<__int64>(high) * 0x100000000ll + static_cast<__int64>(low);
70}
71
72template <>
73unsigned long convert_file_size_to_integer(DWORD const high, DWORD const low) throw()
74{
76 return low;
77}
78
79
80
81template <typename WideFileData, typename NarrowFileData>
82_Success_(return)
83static bool __cdecl copy_wide_to_narrow_find_data(WideFileData const& wfd, _Out_ NarrowFileData& fd, unsigned int const code_page) throw()
84{
86
87 errno_t const cvt = __acrt_wcs_to_mbs_cp(wfd.name, name, code_page);
88
89 if (cvt != 0) {
90 return false;
91 }
92
93 _ERRCHECK(strcpy_s(fd.name, _countof(fd.name), name.data()));
94
95 fd.attrib = wfd.attrib;
96 fd.time_create = wfd.time_create;
97 fd.time_access = wfd.time_access;
98 fd.time_write = wfd.time_write;
99 fd.size = wfd.size;
100
101 return true;
102}
103
104
105
106//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
107//
108// The _findfirst family of functions
109//
110//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
111// These functions find the first file matching the given wildcard pattern. If a
112// file is found, information about that file is stored in the pointed-to result
113// parameter. The return value is a handle that identifies the group of files
114// that match the pattern. If no file is found, or if an error occurs, errno is
115// set and -1 is returned.
116//
117// There are eight functions in this family, combining {wide name, narrow name}
118// x {32-bit file size, 64-bit file size} x {32-bit time_t, 64-bit time_t}.
119template <typename WideFileData>
120_Success_(return != -1)
121static intptr_t __cdecl common_find_first_wide(wchar_t const* const pattern, _Out_ WideFileData* const result) throw()
122{
123 _VALIDATE_RETURN(result != nullptr, EINVAL, -1);
124 _VALIDATE_RETURN(pattern != nullptr, EINVAL, -1);
125
126 // Ensure the underlying WIN32_FIND_DATA's file name buffer is not larger
127 // than ours.
128 static_assert(sizeof(WideFileData().name) <= sizeof(WIN32_FIND_DATAW().cFileName), "");
129
133 {
134 DWORD const os_error = GetLastError();
135 switch (os_error)
136 {
140 errno = ENOENT;
141 break;
142
144 errno = ENOMEM;
145 break;
146
147 default:
148 errno = EINVAL;
149 break;
150 }
151
152 return -1;
153 }
154
155 result->attrib = wfd.dwFileAttributes == FILE_ATTRIBUTE_NORMAL
156 ? 0
157 : wfd.dwFileAttributes;
158
159 typedef decltype(result->time_create) crt_time_type;
160 result->time_create = convert_file_time_to_time_t<crt_time_type>(wfd.ftCreationTime);
161 result->time_access = convert_file_time_to_time_t<crt_time_type>(wfd.ftLastAccessTime);
162 result->time_write = convert_file_time_to_time_t<crt_time_type>(wfd.ftLastWriteTime);
163
164 typedef decltype(result->size) file_size_type;
165 result->size = convert_file_size_to_integer<file_size_type>(wfd.nFileSizeHigh, wfd.nFileSizeLow);
166
167 _ERRCHECK(wcscpy_s(result->name, _countof(result->name), wfd.cFileName));
168
169 return reinterpret_cast<intptr_t>(hFile);
170}
171
172template <typename WideFileData, typename NarrowFileData>
173_Success_(return != -1)
174static intptr_t __cdecl common_find_first_narrow(char const* const pattern, _Out_ NarrowFileData* const result, unsigned int const code_page) throw()
175{
176 _VALIDATE_RETURN(result != nullptr, EINVAL, -1);
177
179
180 errno_t const cvt = __acrt_mbs_to_wcs_cp(pattern, wide_pattern, code_page);
181
182 if (cvt != 0) {
183 return -1;
184 }
185
186 WideFileData wide_result;
187 intptr_t const handle = common_find_first_wide(wide_pattern.data(), &wide_result);
188 if (handle == -1)
189 return -1;
190
191 if (!copy_wide_to_narrow_find_data(wide_result, *result, code_page))
192 return -1;
193
194 return handle;
195}
196
197// Narrow name, 32-bit time_t, 32-bit size
198extern "C" intptr_t __cdecl _findfirst32(char const* const pattern, _finddata32_t* const result)
199{
200 return common_find_first_narrow<_wfinddata32_t>(pattern, result, __acrt_get_utf8_acp_compatibility_codepage());
201}
202
203// Narrow name, 32-bit time_t, 64-bit size
204extern "C" intptr_t __cdecl _findfirst32i64(char const* const pattern, _finddata32i64_t* const result)
205{
206 return common_find_first_narrow<_wfinddata32i64_t>(pattern, result, __acrt_get_utf8_acp_compatibility_codepage());
207}
208
209// Narrow name, 64-bit time_t, 32-bit size
210extern "C" intptr_t __cdecl _findfirst64i32(char const* const pattern, _finddata64i32_t* const result)
211{
212 return common_find_first_narrow<_wfinddata64i32_t>(pattern, result, __acrt_get_utf8_acp_compatibility_codepage());
213}
214
215// Narrow name, 64-bit time_t, 64-bit size
216extern "C" intptr_t __cdecl _findfirst64(char const* const pattern, __finddata64_t* const result)
217{
218 return common_find_first_narrow<_wfinddata64_t>(pattern, result, __acrt_get_utf8_acp_compatibility_codepage());
219}
220
221// Wide name, 32-bit time_t, 32-bit size
222extern "C" intptr_t __cdecl _wfindfirst32(wchar_t const* const pattern, _wfinddata32_t* const result)
223{
224 return common_find_first_wide(pattern, result);
225}
226
227// Wide name, 32-bit time_t, 64-bit size
228extern "C" intptr_t __cdecl _wfindfirst32i64(wchar_t const* const pattern, _wfinddata32i64_t* const result)
229{
230 return common_find_first_wide(pattern, result);
231}
232
233// Wide name, 64-bit time_t, 32-bit size
234extern "C" intptr_t __cdecl _wfindfirst64i32(wchar_t const* const pattern, _wfinddata64i32_t* const result)
235{
236 return common_find_first_wide(pattern, result);
237}
238
239// Wide name, 64-bit time_t, 64-bit size
240extern "C" intptr_t __cdecl _wfindfirst64(wchar_t const* const pattern, _wfinddata64_t* const result)
241{
242 return common_find_first_wide(pattern, result);
243}
244
245
246
247//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
248//
249// The _findnext family of functions
250//
251//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
252// These functions perform iteration over a set of files matching a wildcard
253// pattern. The handle argument must be a handle returned by a previous call to
254// one of the _findfirst functions that completed successfully. Each call to a
255// _findnext function advances the internal iterator and returns information
256// about the next file in the set.
257//
258// If iteration has not yet completed and a file is found, information about that
259// file is stored in the pointed-to result parameter. The return value is a
260// handle that identifies the group of files that match the pattern. If no file
261// is found, or if an error occurs, errno is set and -1 is returned.
262//
263// There are eight functions in this family, combining {wide name, narrow name}
264// x {32-bit file size, 64-bit file size} x {32-bit time_t, 64-bit time_t}.
265template <typename WideFileData>
266static int __cdecl common_find_next_wide(intptr_t const handle, WideFileData* const result) throw()
267{
268 HANDLE const os_handle = reinterpret_cast<HANDLE>(handle);
269
270 _VALIDATE_RETURN(os_handle != 0 , EINVAL, -1);
272 _VALIDATE_RETURN(result != nullptr, EINVAL, -1);
273
275 if (!FindNextFileW(os_handle, &wfd))
276 {
277 DWORD const os_error = GetLastError();
278 switch (os_error)
279 {
283 errno = ENOENT;
284 break;
285
287 errno = ENOMEM;
288 break;
289
290 default:
291 errno = EINVAL;
292 break;
293 }
294
295 return -1;
296 }
297
298 result->attrib = wfd.dwFileAttributes == FILE_ATTRIBUTE_NORMAL
299 ? 0
300 : wfd.dwFileAttributes;
301
302 typedef decltype(result->time_create) crt_time_type;
303 result->time_create = convert_file_time_to_time_t<crt_time_type>(wfd.ftCreationTime);
304 result->time_access = convert_file_time_to_time_t<crt_time_type>(wfd.ftLastAccessTime);
305 result->time_write = convert_file_time_to_time_t<crt_time_type>(wfd.ftLastWriteTime);
306
307 typedef decltype(result->size) file_size_type;
308 result->size = convert_file_size_to_integer<file_size_type>(wfd.nFileSizeHigh, wfd.nFileSizeLow);
309
310 _ERRCHECK(wcscpy_s(result->name, _countof(result->name), wfd.cFileName));
311
312 return 0;
313}
314
315template <typename WideFileData, typename NarrowFileData>
316static int __cdecl common_find_next_narrow(intptr_t const pattern, NarrowFileData* const result, unsigned int const code_page) throw()
317{
318 WideFileData wide_result;
319 int const return_value = common_find_next_wide(pattern, &wide_result);
320 if (return_value == -1)
321 return -1;
322
323 if (!copy_wide_to_narrow_find_data(wide_result, *result, code_page))
324 return -1;
325
326 return return_value;
327}
328
329// Narrow name, 32-bit time_t, 32-bit size
331{
332 return common_find_next_narrow<_wfinddata32_t>(handle, result, __acrt_get_utf8_acp_compatibility_codepage());
333}
334
335// Narrow name, 32-bit time_t, 64-bit size
337{
338 return common_find_next_narrow<_wfinddata32i64_t>(handle, result, __acrt_get_utf8_acp_compatibility_codepage());
339}
340
341// Narrow name, 64-bit time_t, 32-bit size
343{
344 return common_find_next_narrow<_wfinddata64i32_t>(handle, result, __acrt_get_utf8_acp_compatibility_codepage());
345}
346
347// Narrow name, 64-bit time_t, 64-bit size
349{
350 return common_find_next_narrow<_wfinddata64_t>(handle, result, __acrt_get_utf8_acp_compatibility_codepage());
351}
352
353// Wide name, 32-bit time_t, 32-bit size
355{
357}
358
359// Wide name, 32-bit time_t, 64-bit size
361{
363}
364
365// Wide name, 64-bit time_t, 32-bit size
367{
369}
370
371// Wide name, 64-bit time_t, 64-bit size
373{
375}
376
377
378
379//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
380//
381// The _findclose function
382//
383//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
384// This function releases resources associated with a _findfirst/_findnext
385// iteration. It must be called exactly once for each handle returned by
386// _findfirst. Returns 0 on success; -1 on failure.
387extern "C" int __cdecl _findclose(intptr_t const handle)
388{
389 if (!FindClose(reinterpret_cast<HANDLE>(handle)))
390 {
391 errno = EINVAL;
392 return -1;
393 }
394 return 0;
395}
#define ENOENT
Definition: acclib.h:79
#define EINVAL
Definition: acclib.h:90
#define ENOMEM
Definition: acclib.h:84
#define __cdecl
Definition: accygwin.h:79
#define __int64
Definition: basetyps.h:16
_Out_opt_ UINT * code_page
#define _ERRCHECK(e)
#define _VALIDATE_RETURN(expr, errorcode, retexpr)
__time32_t __cdecl __loctotime32_t(int, int, int, int, int, int, int)
Definition: loctotime.cpp:93
__time64_t __cdecl __loctotime64_t(int, int, int, int, int, int, int)
Definition: loctotime.cpp:106
errno_t __acrt_mbs_to_wcs_cp(char const *const null_terminated_input_string, __crt_win32_buffer< wchar_t, ResizePolicy > &win32_buffer, unsigned int const code_page)
errno_t __acrt_wcs_to_mbs_cp(wchar_t const *const null_terminated_input_string, __crt_win32_buffer< char, ResizePolicy > &win32_buffer, unsigned int const code_page)
unsigned int __acrt_get_utf8_acp_compatibility_codepage()
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:137
BOOL WINAPI FindClose(HANDLE hFindFile)
Definition: find.c:502
BOOL WINAPI FindNextFileW(IN HANDLE hFindFile, OUT LPWIN32_FIND_DATAW lpFindFileData)
Definition: find.c:382
HANDLE WINAPI FindFirstFileExW(IN LPCWSTR lpFileName, IN FINDEX_INFO_LEVELS fInfoLevelId, OUT LPVOID lpFindFileData, IN FINDEX_SEARCH_OPS fSearchOp, LPVOID lpSearchFilter, IN DWORD dwAdditionalFlags)
Definition: find.c:649
BOOL WINAPI FileTimeToSystemTime(IN CONST FILETIME *lpFileTime, OUT LPSYSTEMTIME lpSystemTime)
Definition: time.c:188
BOOL WINAPI SystemTimeToTzSpecificLocalTime(CONST TIME_ZONE_INFORMATION *lpTimeZoneInformation, CONST SYSTEMTIME *lpUniversalTime, LPSYSTEMTIME lpLocalTime)
Definition: timezone.c:377
static char * cvt(double arg, int ndigits, int *decpt, int *sign, char *buf, int eflag)
Definition: fcvtbuf.c:45
unsigned long DWORD
Definition: ntddk_ex.h:95
intptr_t __cdecl _wfindfirst32i64(wchar_t const *const pattern, _wfinddata32i64_t *const result)
Definition: findfile.cpp:228
static int __cdecl common_find_next_narrow(intptr_t const pattern, NarrowFileData *const result, unsigned int const code_page)
Definition: findfile.cpp:316
int __cdecl _wfindnext64i32(intptr_t const handle, _wfinddata64i32_t *const result)
Definition: findfile.cpp:366
int __cdecl _findclose(intptr_t const handle)
Definition: findfile.cpp:387
static CrtTime __cdecl convert_system_time_to_time_t(SYSTEMTIME const &st)
intptr_t __cdecl _wfindfirst64(wchar_t const *const pattern, _wfinddata64_t *const result)
Definition: findfile.cpp:240
intptr_t __cdecl _wfindfirst32(wchar_t const *const pattern, _wfinddata32_t *const result)
Definition: findfile.cpp:222
intptr_t __cdecl _wfindfirst64i32(wchar_t const *const pattern, _wfinddata64i32_t *const result)
Definition: findfile.cpp:234
int __cdecl _wfindnext32(intptr_t const handle, _wfinddata32_t *const result)
Definition: findfile.cpp:354
static Integer convert_file_size_to_integer(DWORD const high, DWORD const low)
int __cdecl _findnext64i32(intptr_t const handle, _finddata64i32_t *const result)
Definition: findfile.cpp:342
intptr_t __cdecl _findfirst64i32(char const *const pattern, _finddata64i32_t *const result)
Definition: findfile.cpp:210
int __cdecl _findnext32i64(intptr_t const handle, _finddata32i64_t *const result)
Definition: findfile.cpp:336
_Out_ NarrowFileData unsigned int const code_page throw()
Definition: findfile.cpp:83
intptr_t __cdecl _findfirst32i64(char const *const pattern, _finddata32i64_t *const result)
Definition: findfile.cpp:204
_Out_ NarrowFileData & fd
Definition: findfile.cpp:83
static int __cdecl common_find_next_wide(intptr_t const handle, WideFileData *const result)
Definition: findfile.cpp:266
intptr_t __cdecl _findfirst64(char const *const pattern, __finddata64_t *const result)
Definition: findfile.cpp:216
int __cdecl _findnext64(intptr_t const handle, __finddata64_t *const result)
Definition: findfile.cpp:348
intptr_t __cdecl _findfirst32(char const *const pattern, _finddata32_t *const result)
Definition: findfile.cpp:198
static CrtTime __cdecl convert_file_time_to_time_t(FILETIME const &ft)
Definition: findfile.cpp:44
int __cdecl _wfindnext32i64(intptr_t const handle, _wfinddata32i64_t *const result)
Definition: findfile.cpp:360
int __cdecl _findnext32(intptr_t const handle, _finddata32_t *const result)
Definition: findfile.cpp:330
int __cdecl _wfindnext64(intptr_t const handle, _wfinddata64_t *const result)
Definition: findfile.cpp:372
GLubyte * pattern
Definition: glext.h:7787
GLuint64EXT * result
Definition: glext.h:11304
#define strcpy_s(d, l, s)
Definition: utility.h:200
#define wcscpy_s(d, l, s)
Definition: utility.h:201
#define ERROR_FILE_NOT_FOUND
Definition: disk.h:79
_In_ HANDLE hFile
Definition: mswsock.h:90
#define _Success_(c)
Definition: no_sal2.h:84
#define _Out_
Definition: no_sal2.h:160
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:325
#define errno
Definition: errno.h:18
long __time32_t
Definition: time.h:24
struct WIN32_FIND_DATAA WIN32_FIND_DATAW
#define _countof(array)
Definition: sndvol32.h:70
Definition: name.c:39
int errno_t
Definition: corecrt.h:615
__int64 __time64_t
Definition: corecrt.h:619
int intptr_t
Definition: vcruntime.h:134
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
@ FindExSearchNameMatch
Definition: winbase.h:1165
@ FindExInfoStandard
Definition: winbase.h:1159
#define ERROR_PATH_NOT_FOUND
Definition: winerror.h:106
#define ERROR_NO_MORE_FILES
Definition: winerror.h:121
#define const
Definition: zconf.h:233