d92fbea648eee0c5cdaf75243ad9092cf32157d0
[reactos.git] / reactos / lib / kernel32 / file / find.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * FILE: lib/kernel32/file/find.c
5 * PURPOSE: Find functions
6 * PROGRAMMER: Ariadne ( ariadne@xs4all.nl)
7 * UPDATE HISTORY:
8 * Created 01/11/98
9 */
10
11 /* INCLUDES *****************************************************************/
12
13 #include <windows.h>
14 #include <wchar.h>
15 #include <ddk/ntddk.h>
16 #include <string.h>
17
18 #define NDEBUG
19 #include <kernel32/kernel32.h>
20
21 /* TYPES ********************************************************************/
22
23 typedef struct _KERNEL32_FIND_FILE_DATA
24 {
25 HANDLE DirectoryHandle;
26 FILE_BOTH_DIRECTORY_INFORMATION FileInfo;
27 WCHAR FileNameExtra[MAX_PATH];
28 UNICODE_STRING PatternStr;
29 } KERNEL32_FIND_FILE_DATA, *PKERNEL32_FIND_FILE_DATA;
30
31 typedef struct _WIN32_FIND_DATA_UNICODE {
32 DWORD dwFileAttributes;
33 FILETIME ftCreationTime;
34 FILETIME ftLastAccessTime;
35 FILETIME ftLastWriteTime;
36 DWORD nFileSizeHigh;
37 DWORD nFileSizeLow;
38 DWORD dwReserved0;
39 DWORD dwReserved1;
40 WCHAR cFileName[ MAX_PATH ];
41 WCHAR cAlternateFileName[ 14 ];
42 } WIN32_FIND_DATA_UNICODE, *PWIN32_FIND_DATA_UNICODE;
43
44 typedef struct _WIN32_FIND_DATA_ASCII {
45 DWORD dwFileAttributes;
46 FILETIME ftCreationTime;
47 FILETIME ftLastAccessTime;
48 FILETIME ftLastWriteTime;
49 DWORD nFileSizeHigh;
50 DWORD nFileSizeLow;
51 DWORD dwReserved0;
52 DWORD dwReserved1;
53 CHAR cFileName[ MAX_PATH ];
54 CHAR cAlternateFileName[ 14 ];
55 } WIN32_FIND_DATA_ASCII, *PWIN32_FIND_DATA_ASCII;
56
57 /* FUNCTIONS ****************************************************************/
58
59 static void FileDataToWin32Data(LPWIN32_FIND_DATA lpFindFileData, PKERNEL32_FIND_FILE_DATA IData)
60 {
61 lpFindFileData->dwFileAttributes = IData->FileInfo.FileAttributes;
62 memcpy(&lpFindFileData->ftCreationTime,&IData->FileInfo.CreationTime,sizeof(FILETIME));
63 memcpy(&lpFindFileData->ftLastAccessTime,&IData->FileInfo.LastAccessTime,sizeof(FILETIME));
64 memcpy(&lpFindFileData->ftLastWriteTime,&IData->FileInfo.LastWriteTime,sizeof(FILETIME));
65 lpFindFileData->nFileSizeHigh = IData->FileInfo.EndOfFile.u.HighPart;
66 lpFindFileData->nFileSizeLow = IData->FileInfo.EndOfFile.u.LowPart;
67 }
68
69 WINBOOL STDCALL InternalFindNextFile(HANDLE hFindFile,
70 LPWIN32_FIND_DATA lpFindFileData)
71 {
72 IO_STATUS_BLOCK IoStatusBlock;
73 NTSTATUS Status;
74 PKERNEL32_FIND_FILE_DATA IData;
75
76 IData = (PKERNEL32_FIND_FILE_DATA)hFindFile;
77
78 Status = NtQueryDirectoryFile(IData->DirectoryHandle,
79 NULL,
80 NULL,
81 NULL,
82 &IoStatusBlock,
83 (PVOID)&IData->FileInfo,
84 sizeof(IData->FileInfo) +
85 sizeof(IData->FileNameExtra),
86 FileBothDirectoryInformation,
87 TRUE,
88 &(IData->PatternStr),
89 FALSE);
90 DPRINT("Found %w\n",IData->FileInfo.FileName);
91 if (Status != STATUS_SUCCESS)
92 {
93 return(FALSE);
94 }
95
96 FileDataToWin32Data(lpFindFileData, IData);
97
98 return(TRUE);
99 }
100
101 HANDLE STDCALL InternalFindFirstFile(LPCWSTR lpFileName,
102 LPWIN32_FIND_DATA lpFindFileData)
103 {
104 WCHAR CurrentDirectory[MAX_PATH];
105 WCHAR Pattern[MAX_PATH];
106 WCHAR Directory[MAX_PATH];
107 PWSTR End;
108 PKERNEL32_FIND_FILE_DATA IData;
109 OBJECT_ATTRIBUTES ObjectAttributes;
110 UNICODE_STRING DirectoryNameStr;
111 IO_STATUS_BLOCK IoStatusBlock;
112
113 DPRINT("FindFirstFileW(lpFileName %w, lpFindFileData %x)\n",
114 lpFileName, lpFindFileData);
115
116 GetFullPathNameW(lpFileName, MAX_PATH, CurrentDirectory, NULL);
117 Directory[0] = '\\';
118 Directory[1] = '?';
119 Directory[2] = '?';
120 Directory[3] = '\\';
121 Directory[4] = 0;
122 DPRINT("Directory %w\n",Directory);
123 wcscat(Directory, CurrentDirectory);
124 DPRINT("Directory %w\n",Directory);
125 End = wcsrchr(Directory, '\\');
126 *End = 0;
127
128 wcscpy(Pattern, End+1);
129 *(End+1) = 0;
130 *End = '\\';
131
132 /* change pattern: "*.*" --> "*" */
133 if (!wcscmp(Pattern, L"*.*"))
134 Pattern[1] = 0;
135
136 DPRINT("Directory %w Pattern %w\n",Directory,Pattern);
137
138 IData = HeapAlloc(GetProcessHeap(),
139 HEAP_ZERO_MEMORY,
140 sizeof(KERNEL32_FIND_FILE_DATA));
141
142 RtlInitUnicodeString(&DirectoryNameStr, Directory);
143 InitializeObjectAttributes(&ObjectAttributes,
144 &DirectoryNameStr,
145 0,
146 NULL,
147 NULL);
148
149 if (ZwOpenFile(&IData->DirectoryHandle,
150 FILE_LIST_DIRECTORY,
151 &ObjectAttributes,
152 &IoStatusBlock,
153 FILE_OPEN_IF,
154 OPEN_EXISTING)!=STATUS_SUCCESS)
155 {
156 return(NULL);
157 }
158
159 RtlInitUnicodeString(&(IData->PatternStr), Pattern);
160
161 NtQueryDirectoryFile(IData->DirectoryHandle,
162 NULL,
163 NULL,
164 NULL,
165 &IoStatusBlock,
166 (PVOID)&IData->FileInfo,
167 sizeof(IData->FileInfo) +
168 sizeof(IData->FileNameExtra),
169 FileBothDirectoryInformation,
170 TRUE,
171 &(IData->PatternStr),
172 FALSE);
173 DPRINT("Found %w\n",IData->FileInfo.FileName);
174
175 FileDataToWin32Data(lpFindFileData, IData);
176
177 return(IData);
178 }
179
180 HANDLE FindFirstFileA(LPCTSTR lpFileName, LPWIN32_FIND_DATA lpFindFileData)
181 {
182 WCHAR lpFileNameW[MAX_PATH];
183 ULONG i;
184 PKERNEL32_FIND_FILE_DATA IData;
185 PWIN32_FIND_DATA_ASCII Ret;
186
187 i = 0;
188 while (lpFileName[i]!=0)
189 {
190 lpFileNameW[i] = lpFileName[i];
191 i++;
192 }
193 lpFileNameW[i] = 0;
194
195 IData = InternalFindFirstFile(lpFileNameW,lpFindFileData);
196 if (IData == NULL)
197 {
198 DPRINT("Failing request\n");
199 return(INVALID_HANDLE_VALUE);
200 }
201
202
203 Ret = (PWIN32_FIND_DATA_ASCII)lpFindFileData;
204
205 DPRINT("IData->FileInfo.FileNameLength %d\n",
206 IData->FileInfo.FileNameLength);
207 for (i=0; i<IData->FileInfo.FileNameLength; i++)
208 {
209 Ret->cFileName[i] = IData->FileInfo.FileName[i];
210 }
211 Ret->cFileName[i] = 0;
212
213 DPRINT("IData->FileInfo.ShortNameLength %d\n",
214 IData->FileInfo.ShortNameLength);
215 if (IData->FileInfo.ShortNameLength > 13)
216 {
217 IData->FileInfo.ShortNameLength = 13;
218 }
219 for (i=0; i<IData->FileInfo.ShortNameLength; i++)
220 {
221 Ret->cAlternateFileName[i] = IData->FileInfo.ShortName[i];
222 }
223 Ret->cAlternateFileName[i] = 0;
224
225
226 return(IData);
227 }
228
229 WINBOOL FindNextFileA(HANDLE hFindFile, LPWIN32_FIND_DATA lpFindFileData)
230 {
231 PWIN32_FIND_DATA_ASCII Ret;
232 PKERNEL32_FIND_FILE_DATA IData;
233 ULONG i;
234
235 IData = (PKERNEL32_FIND_FILE_DATA)hFindFile;
236 if (IData == NULL)
237 {
238 return(FALSE);
239 }
240 if (!InternalFindNextFile(hFindFile, lpFindFileData))
241 {
242 DPRINT("InternalFindNextFile() failed\n");
243 return(FALSE);
244 }
245
246 Ret = (PWIN32_FIND_DATA_ASCII)lpFindFileData;
247
248 DPRINT("IData->FileInfo.FileNameLength %d\n",
249 IData->FileInfo.FileNameLength);
250 for (i=0; i<IData->FileInfo.FileNameLength; i++)
251 {
252 Ret->cFileName[i] = IData->FileInfo.FileName[i];
253 }
254 Ret->cFileName[i] = 0;
255
256 DPRINT("IData->FileInfo.ShortNameLength %d\n",
257 IData->FileInfo.ShortNameLength);
258 for (i=0; i<IData->FileInfo.ShortNameLength; i++)
259 {
260 Ret->cAlternateFileName[i] = IData->FileInfo.ShortName[i];
261 }
262 Ret->cAlternateFileName[i] = 0;
263
264 return(TRUE);
265 }
266
267 BOOL FindClose(HANDLE hFindFile)
268 {
269 PKERNEL32_FIND_FILE_DATA IData;
270
271 DPRINT("FindClose(hFindFile %x)\n",hFindFile);
272
273 if (hFindFile || hFindFile == INVALID_HANDLE_VALUE)
274 {
275 SetLastError (ERROR_INVALID_HANDLE);
276 return(FALSE);
277 }
278 IData = (PKERNEL32_FIND_FILE_DATA)hFindFile;
279 CloseHandle(IData->DirectoryHandle);
280 HeapFree(GetProcessHeap(), 0, IData);
281 return(TRUE);
282 }
283
284 HANDLE STDCALL FindFirstFileW(LPCWSTR lpFileName,
285 LPWIN32_FIND_DATA lpFindFileData)
286 {
287 PWIN32_FIND_DATA_UNICODE Ret;
288 PKERNEL32_FIND_FILE_DATA IData;
289
290 IData = InternalFindFirstFile(lpFileName,lpFindFileData);
291 Ret = (PWIN32_FIND_DATA_UNICODE)lpFindFileData;
292
293 memcpy(Ret->cFileName, IData->FileInfo.FileName,
294 IData->FileInfo.FileNameLength);
295 memcpy(Ret->cAlternateFileName, IData->FileInfo.ShortName,
296 IData->FileInfo.ShortNameLength);
297
298 return(IData);
299 }
300
301 WINBOOL STDCALL FindNextFileW(HANDLE hFindFile,
302 LPWIN32_FIND_DATA lpFindFileData)
303 {
304 PWIN32_FIND_DATA_UNICODE Ret;
305 PKERNEL32_FIND_FILE_DATA IData;
306
307 IData = (PKERNEL32_FIND_FILE_DATA)hFindFile;
308 if (!InternalFindNextFile(hFindFile, lpFindFileData))
309 {
310 return(FALSE);
311 }
312
313 Ret = (PWIN32_FIND_DATA_UNICODE)lpFindFileData;
314
315 memcpy(Ret->cFileName, IData->FileInfo.FileName,
316 IData->FileInfo.FileNameLength);
317 memcpy(Ret->cAlternateFileName, IData->FileInfo.ShortName,
318 IData->FileInfo.ShortNameLength);
319
320 return(TRUE);
321 }