FreeRDP
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 
11 static const CHAR testFile1A[] = "TestFile1A";
12 
13 static 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 
34 static 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 
67 static 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 
76 static void cleanup_layout(const char* BasePath)
77 {
78  winpr_RemoveDirectory_RecursiveA(BasePath);
79 }
80 
81 static 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;
100 fail:
101  if (hFind != INVALID_HANDLE_VALUE)
102  FindClose(hFind);
103  return rc;
104 }
105 
106 static 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;
126 fail:
127  FindClose(hFind);
128 
129  if (count != 1)
130  return FALSE;
131  return rc;
132 }
133 
134 static 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 
182 static 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 
193 static 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  return -1;
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;
250 fail:
251  DeleteFileA(FilePath);
252  cleanup_layout(BasePath);
253  ArrayList_Free(files);
254  return rc;
255 }
256 
257 static 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;
303 fail:
304  DeleteFileW(FilePath);
305  FindClose(hFind);
306  return rc;
307 }
308 
309 int 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