Lots of changes to the kernel
[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
60 static void FileDataToWin32Data(LPWIN32_FIND_DATA lpFindFileData, PKERNEL32_FIND_FILE_DATA IData)
61 {
62 lpFindFileData->dwFileAttributes = IData->FileInfo.FileAttributes;
63 memcpy(&lpFindFileData->ftCreationTime,&IData->FileInfo.CreationTime,sizeof(FILETIME));
64 memcpy(&lpFindFileData->ftLastAccessTime,&IData->FileInfo.LastAccessTime,sizeof(FILETIME));
65 memcpy(&lpFindFileData->ftLastWriteTime,&IData->FileInfo.LastWriteTime,sizeof(FILETIME));
66 lpFindFileData->nFileSizeHigh = IData->FileInfo.EndOfFile.u.HighPart;
67 lpFindFileData->nFileSizeLow = IData->FileInfo.EndOfFile.u.LowPart;
68 }
69
70 WINBOOL STDCALL InternalFindNextFile(HANDLE hFindFile,
71 LPWIN32_FIND_DATA lpFindFileData)
72 {
73 IO_STATUS_BLOCK IoStatusBlock;
74 NTSTATUS Status;
75 PKERNEL32_FIND_FILE_DATA IData;
76
77 IData = (PKERNEL32_FIND_FILE_DATA)hFindFile;
78
79 Status = NtQueryDirectoryFile(IData->DirectoryHandle,
80 NULL,
81 NULL,
82 NULL,
83 &IoStatusBlock,
84 (PVOID)&IData->FileInfo,
85 sizeof(IData->FileInfo) +
86 sizeof(IData->FileNameExtra),
87 FileBothDirectoryInformation,
88 TRUE,
89 &(IData->PatternStr),
90 FALSE);
91 DPRINT("Found %w\n",IData->FileInfo.FileName);
92 if (Status != STATUS_SUCCESS)
93 {
94 return(FALSE);
95 }
96
97 FileDataToWin32Data(lpFindFileData, IData);
98
99 return(TRUE);
100 }
101
102 HANDLE STDCALL InternalFindFirstFile(LPCWSTR lpFileName,
103 LPWIN32_FIND_DATA lpFindFileData)
104 {
105 WCHAR CurrentDirectory[MAX_PATH];
106 WCHAR Pattern[MAX_PATH];
107 WCHAR Directory[MAX_PATH];
108 PWSTR End;
109 PKERNEL32_FIND_FILE_DATA IData;
110 OBJECT_ATTRIBUTES ObjectAttributes;
111 UNICODE_STRING DirectoryNameStr;
112 IO_STATUS_BLOCK IoStatusBlock;
113
114 DPRINT("FindFirstFileW(lpFileName %w, lpFindFileData %x)\n",
115 lpFileName, lpFindFileData);
116
117 GetFullPathNameW(lpFileName, MAX_PATH, CurrentDirectory, NULL);
118 Directory[0] = '\\';
119 Directory[1] = '?';
120 Directory[2] = '?';
121 Directory[3] = '\\';
122 Directory[4] = 0;
123 DPRINT("Directory %w\n",Directory);
124 wcscat(Directory, CurrentDirectory);
125 DPRINT("Directory %w\n",Directory);
126 End = wcsrchr(Directory, '\\');
127 *End = 0;
128
129 wcscpy(Pattern, End+1);
130 *(End+1) = 0;
131 *End = '\\';
132
133 /* change pattern: "*.*" --> "*" */
134 if (!wcscmp(Pattern, L"*.*"))
135 Pattern[1] = 0;
136
137 DPRINT("Directory %w Pattern %w\n",Directory,Pattern);
138
139 IData = HeapAlloc(GetProcessHeap(),
140 HEAP_ZERO_MEMORY,
141 sizeof(KERNEL32_FIND_FILE_DATA));
142
143 RtlInitUnicodeString(&DirectoryNameStr, Directory);
144 InitializeObjectAttributes(&ObjectAttributes,
145 &DirectoryNameStr,
146 0,
147 NULL,
148 NULL);
149
150 if (ZwOpenFile(&IData->DirectoryHandle,
151 FILE_LIST_DIRECTORY,
152 &ObjectAttributes,
153 &IoStatusBlock,
154 FILE_OPEN_IF,
155 OPEN_EXISTING)!=STATUS_SUCCESS)
156 {
157 return(NULL);
158 }
159
160 RtlInitUnicodeString(&(IData->PatternStr), Pattern);
161
162 NtQueryDirectoryFile(IData->DirectoryHandle,
163 NULL,
164 NULL,
165 NULL,
166 &IoStatusBlock,
167 (PVOID)&IData->FileInfo,
168 sizeof(IData->FileInfo) +
169 sizeof(IData->FileNameExtra),
170 FileBothDirectoryInformation,
171 TRUE,
172 &(IData->PatternStr),
173 FALSE);
174 DPRINT("Found %w\n",IData->FileInfo.FileName);
175
176 FileDataToWin32Data(lpFindFileData, IData);
177
178 return(IData);
179 }
180
181 HANDLE FindFirstFileA(LPCTSTR lpFileName, LPWIN32_FIND_DATA lpFindFileData)
182 {
183 WCHAR lpFileNameW[MAX_PATH];
184 ULONG i;
185 PKERNEL32_FIND_FILE_DATA IData;
186 PWIN32_FIND_DATA_ASCII Ret;
187
188 i = 0;
189 while (lpFileName[i]!=0)
190 {
191 lpFileNameW[i] = lpFileName[i];
192 i++;
193 }
194 lpFileNameW[i] = 0;
195
196 IData = InternalFindFirstFile(lpFileNameW,lpFindFileData);
197 if (IData == NULL)
198 {
199 DPRINT("Failing request\n");
200 return(INVALID_HANDLE_VALUE);
201 }
202
203
204 Ret = (PWIN32_FIND_DATA_ASCII)lpFindFileData;
205
206 DPRINT("IData->FileInfo.FileNameLength %d\n",
207 IData->FileInfo.FileNameLength);
208 for (i=0; i<IData->FileInfo.FileNameLength; i++)
209 {
210 Ret->cFileName[i] = IData->FileInfo.FileName[i];
211 }
212 Ret->cFileName[i] = 0;
213
214 DPRINT("IData->FileInfo.ShortNameLength %d\n",
215 IData->FileInfo.ShortNameLength);
216 if (IData->FileInfo.ShortNameLength > 13)
217 {
218 IData->FileInfo.ShortNameLength = 13;
219 }
220 for (i=0; i<IData->FileInfo.ShortNameLength; i++)
221 {
222 Ret->cAlternateFileName[i] = IData->FileInfo.ShortName[i];
223 }
224 Ret->cAlternateFileName[i] = 0;
225
226
227 return(IData);
228 }
229
230 WINBOOL FindNextFileA(HANDLE hFindFile, LPWIN32_FIND_DATA lpFindFileData)
231 {
232 PWIN32_FIND_DATA_ASCII Ret;
233 PKERNEL32_FIND_FILE_DATA IData;
234 ULONG i;
235
236 IData = (PKERNEL32_FIND_FILE_DATA)hFindFile;
237 if (IData == NULL)
238 {
239 return(FALSE);
240 }
241 if (!InternalFindNextFile(hFindFile, lpFindFileData))
242 {
243 DPRINT("InternalFindNextFile() failed\n");
244 return(FALSE);
245 }
246
247 Ret = (PWIN32_FIND_DATA_ASCII)lpFindFileData;
248
249 DPRINT("IData->FileInfo.FileNameLength %d\n",
250 IData->FileInfo.FileNameLength);
251 for (i=0; i<IData->FileInfo.FileNameLength; i++)
252 {
253 Ret->cFileName[i] = IData->FileInfo.FileName[i];
254 }
255 Ret->cFileName[i] = 0;
256
257 DPRINT("IData->FileInfo.ShortNameLength %d\n",
258 IData->FileInfo.ShortNameLength);
259 for (i=0; i<IData->FileInfo.ShortNameLength; i++)
260 {
261 Ret->cAlternateFileName[i] = IData->FileInfo.ShortName[i];
262 }
263 Ret->cAlternateFileName[i] = 0;
264
265 return(TRUE);
266 }
267
268 BOOL FindClose(HANDLE hFindFile)
269 {
270 PKERNEL32_FIND_FILE_DATA IData;
271
272 DPRINT("FindClose(hFindFile %x)\n",hFindFile);
273
274 if (hFindFile || hFindFile == INVALID_HANDLE_VALUE)
275 {
276 SetLastError (ERROR_INVALID_HANDLE);
277 return(FALSE);
278 }
279 IData = (PKERNEL32_FIND_FILE_DATA)hFindFile;
280 CloseHandle(IData->DirectoryHandle);
281 HeapFree(GetProcessHeap(), 0, IData);
282 return(TRUE);
283 }
284
285 HANDLE STDCALL FindFirstFileW(LPCWSTR lpFileName,
286 LPWIN32_FIND_DATA lpFindFileData)
287 {
288 PWIN32_FIND_DATA_UNICODE Ret;
289 PKERNEL32_FIND_FILE_DATA IData;
290
291 IData = InternalFindFirstFile(lpFileName,lpFindFileData);
292 Ret = (PWIN32_FIND_DATA_UNICODE)lpFindFileData;
293
294 memcpy(Ret->cFileName, IData->FileInfo.FileName,
295 IData->FileInfo.FileNameLength);
296 memcpy(Ret->cAlternateFileName, IData->FileInfo.ShortName,
297 IData->FileInfo.ShortNameLength);
298
299 return(IData);
300 }
301
302 WINBOOL STDCALL FindNextFileW(HANDLE hFindFile,
303 LPWIN32_FIND_DATA lpFindFileData)
304 {
305 PWIN32_FIND_DATA_UNICODE Ret;
306 PKERNEL32_FIND_FILE_DATA IData;
307
308 IData = (PKERNEL32_FIND_FILE_DATA)hFindFile;
309 if (!InternalFindNextFile(hFindFile, lpFindFileData))
310 {
311 return(FALSE);
312 }
313
314 Ret = (PWIN32_FIND_DATA_UNICODE)lpFindFileData;
315
316 memcpy(Ret->cFileName, IData->FileInfo.FileName,
317 IData->FileInfo.FileNameLength);
318 memcpy(Ret->cAlternateFileName, IData->FileInfo.ShortName,
319 IData->FileInfo.ShortNameLength);
320
321 return(TRUE);
322 }