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