FreeRDP
Loading...
Searching...
No Matches
TestFileFindFirstFile.c
1
2#include <stdio.h>
3#include <winpr/crt.h>
4#include <winpr/handle.h>
5#include <winpr/file.h>
6#include <winpr/path.h>
7#include <winpr/tchar.h>
8#include <winpr/collections.h>
9#include <winpr/windows.h>
10
11static const CHAR testFile1A[] = "TestFile1A";
12
13static BOOL create_fileA(const char* FilePath)
14{
15 HANDLE hdl = winpr_CreateFile(FilePath, GENERIC_ALL, 0, nullptr, CREATE_ALWAYS,
16 FILE_ATTRIBUTE_NORMAL, nullptr);
17 if (hdl == INVALID_HANDLE_VALUE)
18 return FALSE;
19 (void)CloseHandle(hdl);
20 return TRUE;
21}
22
23static BOOL create_fileW(const WCHAR* FilePath)
24{
25 HANDLE hdl = CreateFileW(FilePath, GENERIC_ALL, 0, nullptr, CREATE_ALWAYS,
26 FILE_ATTRIBUTE_NORMAL, nullptr);
27 if (hdl == INVALID_HANDLE_VALUE)
28 return FALSE;
29 (void)CloseHandle(hdl);
30 return TRUE;
31}
32
33static BOOL create_layout_files(size_t level, const char* BasePath, wArrayList* files)
34{
35 BOOL rc = TRUE;
36 for (size_t x = 0; x < 10; x++)
37 {
38 CHAR FilePath[PATHCCH_MAX_CCH] = WINPR_C_ARRAY_INIT;
39 strncpy(FilePath, BasePath, ARRAYSIZE(FilePath));
40
41 CHAR name[64] = WINPR_C_ARRAY_INIT;
42 (void)_snprintf(name, ARRAYSIZE(name), "%zd-TestFile%zd", level, x);
43 if (FAILED(NativePathCchAppendA(FilePath, PATHCCH_MAX_CCH, name)))
44 rc = FALSE;
45
46 if (create_fileA(FilePath))
47 {
48 if (!ArrayList_Append(files, FilePath))
49 rc = FALSE;
50 }
51 }
52 return rc;
53}
54
55static BOOL create_layout_directories(size_t level, size_t max_level, const char* BasePath,
56 wArrayList* files)
57{
58 if (level >= max_level)
59 return TRUE;
60
61 CHAR FilePath[PATHCCH_MAX_CCH] = WINPR_C_ARRAY_INIT;
62 strncpy(FilePath, BasePath, ARRAYSIZE(FilePath));
63 if (FAILED(PathCchConvertStyleA(FilePath, ARRAYSIZE(FilePath), PATH_STYLE_NATIVE)))
64 return FALSE;
65 if (!winpr_PathMakePath(FilePath, nullptr))
66 return FALSE;
67 ArrayList_Append(files, FilePath);
68
69 if (!create_layout_files(level + 1, BasePath, files))
70 return FALSE;
71
72 for (size_t x = 0; x < 10; x++)
73 {
74 CHAR CurFilePath[PATHCCH_MAX_CCH] = WINPR_C_ARRAY_INIT;
75 strncpy(CurFilePath, FilePath, ARRAYSIZE(CurFilePath));
76
77 if (FAILED(PathCchConvertStyleA(CurFilePath, ARRAYSIZE(CurFilePath), PATH_STYLE_NATIVE)))
78 return FALSE;
79
80 CHAR name[64] = WINPR_C_ARRAY_INIT;
81 (void)_snprintf(name, ARRAYSIZE(name), "%zd-TestPath%zd", level, x);
82 if (FAILED(NativePathCchAppendA(CurFilePath, PATHCCH_MAX_CCH, name)))
83 return FALSE;
84
85 if (!create_layout_directories(level + 1, max_level, CurFilePath, files))
86 return FALSE;
87 }
88 return TRUE;
89}
90
91static BOOL create_layout(const char* BasePath, wArrayList* files)
92{
93 CHAR BasePathNative[PATHCCH_MAX_CCH] = WINPR_C_ARRAY_INIT;
94 memcpy(BasePathNative, BasePath, sizeof(BasePathNative));
95 if (FAILED(PathCchConvertStyleA(BasePathNative, ARRAYSIZE(BasePathNative), PATH_STYLE_NATIVE)))
96 return FALSE;
97
98 return create_layout_directories(0, 3, BasePathNative, files);
99}
100
101static void cleanup_layout(const char* BasePath)
102{
103 winpr_RemoveDirectory_RecursiveA(BasePath);
104}
105
106static BOOL find_first_file_success(const char* FilePath)
107{
108 BOOL rc = FALSE;
109 WIN32_FIND_DATAA FindData = WINPR_C_ARRAY_INIT;
110 HANDLE hFind = FindFirstFileA(FilePath, &FindData);
111 if (hFind == INVALID_HANDLE_VALUE)
112 {
113 printf("FindFirstFile failure: %s (INVALID_HANDLE_VALUE -1)\n", FilePath);
114 goto fail;
115 }
116
117 printf("FindFirstFile: %s\n", FindData.cFileName);
118
119 if (strcmp(FindData.cFileName, testFile1A) != 0)
120 {
121 printf("FindFirstFile failure: Expected: %s, Actual: %s\n", testFile1A, FindData.cFileName);
122 goto fail;
123 }
124 rc = TRUE;
125fail:
126 if (hFind != INVALID_HANDLE_VALUE)
127 FindClose(hFind);
128 return rc;
129}
130
131static BOOL list_directory_dot(const char* BasePath, wArrayList* files)
132{
133 BOOL rc = FALSE;
134 CHAR BasePathDot[PATHCCH_MAX_CCH] = WINPR_C_ARRAY_INIT;
135 memcpy(BasePathDot, BasePath, ARRAYSIZE(BasePathDot));
136 if (FAILED(PathCchConvertStyleA(BasePathDot, ARRAYSIZE(BasePathDot), PATH_STYLE_NATIVE)))
137 return FALSE;
138 if (FAILED(NativePathCchAppendA(BasePathDot, PATHCCH_MAX_CCH, ".")))
139 return FALSE;
140 WIN32_FIND_DATAA FindData = WINPR_C_ARRAY_INIT;
141 HANDLE hFind = FindFirstFileA(BasePathDot, &FindData);
142 if (hFind == INVALID_HANDLE_VALUE)
143 return FALSE;
144 size_t count = 0;
145 do
146 {
147 count++;
148 if (strcmp(FindData.cFileName, ".") != 0)
149 goto fail;
150 } while (FindNextFile(hFind, &FindData));
151
152 rc = TRUE;
153fail:
154 FindClose(hFind);
155
156 if (count != 1)
157 return FALSE;
158 return rc;
159}
160
161static BOOL list_directory_star(const char* BasePath, wArrayList* files)
162{
163 CHAR BasePathDot[PATHCCH_MAX_CCH] = WINPR_C_ARRAY_INIT;
164 memcpy(BasePathDot, BasePath, ARRAYSIZE(BasePathDot));
165
166 if (FAILED(PathCchConvertStyleA(BasePathDot, ARRAYSIZE(BasePathDot), PATH_STYLE_NATIVE)))
167 return FALSE;
168
169 if (FAILED(NativePathCchAppendA(BasePathDot, PATHCCH_MAX_CCH, "*")))
170 return FALSE;
171
172 WIN32_FIND_DATAA FindData = WINPR_C_ARRAY_INIT;
173 HANDLE hFind = FindFirstFileA(BasePathDot, &FindData);
174 if (hFind == INVALID_HANDLE_VALUE)
175 return FALSE;
176 size_t count = 0;
177 size_t dotcount = 0;
178 size_t dotdotcount = 0;
179 do
180 {
181 if (strcmp(FindData.cFileName, ".") == 0)
182 dotcount++;
183 else if (strcmp(FindData.cFileName, "..") == 0)
184 dotdotcount++;
185 else
186 count++;
187 } while (FindNextFile(hFind, &FindData));
188 FindClose(hFind);
189
190 const char sep = PathGetSeparatorA(PATH_STYLE_NATIVE);
191 size_t fcount = 0;
192 const size_t baselen = strlen(BasePath);
193 const size_t total = ArrayList_Count(files);
194 for (size_t x = 0; x < total; x++)
195 {
196 const char* path = ArrayList_GetItem(files, x);
197 const size_t pathlen = strlen(path);
198 if (pathlen < baselen)
199 continue;
200 const char* skip = &path[baselen];
201 if (*skip == sep)
202 skip++;
203 const char* end = strrchr(skip, sep);
204 if (end)
205 continue;
206 fcount++;
207 }
208
209 return (fcount == count);
210}
211
212static BOOL find_first_file_fail(const char* FilePath)
213{
214 WIN32_FIND_DATAA FindData = WINPR_C_ARRAY_INIT;
215 HANDLE hFind = FindFirstFileA(FilePath, &FindData);
216 if (hFind == INVALID_HANDLE_VALUE)
217 return TRUE;
218
219 FindClose(hFind);
220 return FALSE;
221}
222
223static int TestFileFindFirstFileA(const char* str)
224{
225 int rc = -1;
226
227 printf("[%s] basepath: '%s'\n", __func__, str);
228 if (!str)
229 return -1;
230
231 CHAR BasePath[PATHCCH_MAX_CCH] = WINPR_C_ARRAY_INIT;
232
233 strncpy(BasePath, str, ARRAYSIZE(BasePath));
234
235 const size_t length = strnlen(BasePath, PATHCCH_MAX_CCH - 1);
236
237 CHAR FilePath[PATHCCH_MAX_CCH] = WINPR_C_ARRAY_INIT;
238 CopyMemory(FilePath, BasePath, length * sizeof(CHAR));
239
240 if (FAILED(PathCchConvertStyleA(BasePath, length, PATH_STYLE_WINDOWS)))
241 return -2;
242
243 wArrayList* files = ArrayList_New(FALSE);
244 if (!files)
245 return -3;
246 wObject* obj = ArrayList_Object(files);
247 obj->fnObjectFree = winpr_ObjectStringFree;
248 obj->fnObjectNew = winpr_ObjectStringClone;
249
250 if (!create_layout(BasePath, files))
251 goto fail;
252
253 if (FAILED(NativePathCchAppendA(FilePath, PATHCCH_MAX_CCH, testFile1A)))
254 goto fail;
255
256 printf("Finding file: %s\n", FilePath);
257
258 if (!find_first_file_fail(FilePath))
259 goto fail;
260
261 if (!create_fileA(FilePath))
262 goto fail;
263
264 if (!find_first_file_success(FilePath))
265 goto fail;
266
267 CHAR BasePathInvalid[PATHCCH_MAX_CCH] = WINPR_C_ARRAY_INIT;
268 memcpy(BasePathInvalid, BasePath, ARRAYSIZE(BasePathInvalid));
269 if (FAILED(PathCchAddBackslashA(BasePathInvalid, PATHCCH_MAX_CCH)))
270 goto fail;
271
272 if (!find_first_file_fail(BasePathInvalid))
273 goto fail;
274
275 if (!list_directory_dot(BasePath, files))
276 goto fail;
277
278 if (!list_directory_star(BasePath, files))
279 goto fail;
280
281 rc = 0;
282fail:
283 winpr_DeleteFile(FilePath);
284 cleanup_layout(BasePath);
285 ArrayList_Free(files);
286 return rc;
287}
288
289WINPR_ATTR_FORMAT_ARG(1, 0)
290static int printf1W(const char* WINPR_FORMAT_ARG fmt, const WCHAR* arg1)
291{
292 char* var1 = ConvertWCharToUtf8Alloc(arg1, nullptr);
293 const int rc = printf(fmt, var1);
294 free(var1);
295 return rc;
296}
297
298WINPR_ATTR_FORMAT_ARG(1, 0)
299static int printf2W(const char* WINPR_FORMAT_ARG fmt, const WCHAR* arg1, const WCHAR* arg2)
300{
301 char* var1 = ConvertWCharToUtf8Alloc(arg1, nullptr);
302 char* var2 = ConvertWCharToUtf8Alloc(arg2, nullptr);
303 const int rc = printf(fmt, var1, var2);
304 free(var1);
305 free(var2);
306 return rc;
307}
308
309static int TestFileFindFirstFileW(const char* str)
310{
311 WCHAR buffer[32] = WINPR_C_ARRAY_INIT;
312 const WCHAR* testFile1W = InitializeConstWCharFromUtf8("TestFile1W", buffer, ARRAYSIZE(buffer));
313 int rc = -1;
314 if (!str)
315 return -1;
316
317 WCHAR BasePath[PATHCCH_MAX_CCH] = WINPR_C_ARRAY_INIT;
318
319 printf("[%s] basepath: '%s'\n", __func__, str);
320 (void)ConvertUtf8ToWChar(str, BasePath, ARRAYSIZE(BasePath));
321
322 const size_t length = _wcsnlen(BasePath, PATHCCH_MAX_CCH - 1);
323
324 WCHAR FilePath[PATHCCH_MAX_CCH] = WINPR_C_ARRAY_INIT;
325 CopyMemory(FilePath, BasePath, length * sizeof(WCHAR));
326
327 HANDLE hFind = INVALID_HANDLE_VALUE;
328 if (FAILED(PathCchConvertStyleW(BasePath, length, PATH_STYLE_WINDOWS)))
329 goto fail;
330 if (FAILED(NativePathCchAppendW(FilePath, PATHCCH_MAX_CCH, testFile1W)))
331 goto fail;
332
333 if (!create_fileW(FilePath))
334 goto fail;
335
336 printf1W("Finding file: %s\n", FilePath);
337
338 WIN32_FIND_DATAW FindData = WINPR_C_ARRAY_INIT;
339 hFind = FindFirstFileW(FilePath, &FindData);
340
341 if (hFind == INVALID_HANDLE_VALUE)
342 {
343 printf1W("FindFirstFile failure: %s (INVALID_HANDLE_VALUE -1)\n", FilePath);
344 goto fail;
345 }
346
347 printf1W("FindFirstFile: %s\n", FindData.cFileName);
348
349 if (_wcscmp(FindData.cFileName, testFile1W) != 0)
350 {
351 printf2W("FindFirstFile failure: Expected: %s, Actual: %s\n", testFile1W,
352 FindData.cFileName);
353 goto fail;
354 }
355
356 rc = 0;
357fail:
358 DeleteFileW(FilePath);
359 FindClose(hFind);
360 return rc;
361}
362
363int TestFileFindFirstFile(int argc, char* argv[])
364{
365 char* str = GetKnownSubPath(KNOWN_PATH_TEMP, "TestFileFindFirstFile");
366 if (!str)
367 return -23;
368
369 cleanup_layout(str);
370
371 int rc1 = -1;
372 int rc2 = -1;
373 if (winpr_PathMakePath(str, nullptr))
374 {
375 rc1 = TestFileFindFirstFileA(str);
376 rc2 = TestFileFindFirstFileW(str);
377 winpr_RemoveDirectory(str);
378 }
379 free(str);
380 return rc1 + rc2;
381}
This struct contains function pointer to initialize/free objects.
Definition collections.h:52
OBJECT_FREE_FN fnObjectFree
Definition collections.h:59
WINPR_ATTR_NODISCARD OBJECT_NEW_FN fnObjectNew
Definition collections.h:54