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