1 /* $Id: find.c,v 1.40 2003/11/17 02:12:50 hyperion Exp $
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS system libraries
5 * FILE: lib/kernel32/file/find.c
6 * PURPOSE: Find functions
7 * PROGRAMMER: Ariadne ( ariadne@xs4all.nl)
12 /* INCLUDES *****************************************************************/
17 #include <kernel32/kernel32.h>
20 /* TYPES ********************************************************************/
23 #define offsetof(TYPE, MEMBER) ((size_t) &( ((TYPE *) 0)->MEMBER ))
26 #define FIND_DATA_SIZE (16*1024)
28 typedef struct _KERNEL32_FIND_FILE_DATA
30 HANDLE DirectoryHandle
;
31 PFILE_BOTH_DIRECTORY_INFORMATION pFileInfo
;
32 } KERNEL32_FIND_FILE_DATA
, *PKERNEL32_FIND_FILE_DATA
;
35 /* FUNCTIONS ****************************************************************/
43 InternalFindNextFile (
47 PKERNEL32_FIND_FILE_DATA IData
;
48 IO_STATUS_BLOCK IoStatusBlock
;
51 IData
= (PKERNEL32_FIND_FILE_DATA
)hFindFile
;
53 if (IData
->pFileInfo
->NextEntryOffset
!= 0)
55 IData
->pFileInfo
= (PVOID
)IData
->pFileInfo
+ IData
->pFileInfo
->NextEntryOffset
;
56 DPRINT("Found %.*S\n",IData
->pFileInfo
->FileNameLength
/sizeof(WCHAR
), IData
->pFileInfo
->FileName
);
59 IData
->pFileInfo
= (PVOID
)IData
+ sizeof(KERNEL32_FIND_FILE_DATA
);
60 IData
->pFileInfo
->FileIndex
= 0;
61 Status
= NtQueryDirectoryFile (IData
->DirectoryHandle
,
66 (PVOID
)IData
->pFileInfo
,
68 FileBothDirectoryInformation
,
72 if (!NT_SUCCESS(Status
))
74 SetLastErrorByStatus (Status
);
77 DPRINT("Found %.*S\n",IData
->pFileInfo
->FileNameLength
/sizeof(WCHAR
), IData
->pFileInfo
->FileName
);
87 InternalFindFirstFile (
91 OBJECT_ATTRIBUTES ObjectAttributes
;
92 PKERNEL32_FIND_FILE_DATA IData
;
93 IO_STATUS_BLOCK IoStatusBlock
;
94 UNICODE_STRING NtPathU
;
95 UNICODE_STRING PatternStr
;
98 WCHAR CurrentDir
[256];
100 PWCHAR SearchPattern
;
104 DPRINT("FindFirstFileW(lpFileName %S)\n",
107 e1
= wcsrchr(lpFileName
, L
'/');
108 e2
= wcsrchr(lpFileName
, L
'\\');
109 SearchPattern
= max(e1
, e2
);
110 SearchPath
= CurrentDir
;
112 if (NULL
== SearchPattern
)
115 SearchPattern
= (PWCHAR
)lpFileName
;
116 Length
= GetCurrentDirectoryW(sizeof(CurrentDir
) / sizeof(WCHAR
), SearchPath
);
121 if (Length
> sizeof(CurrentDir
) / sizeof(WCHAR
))
123 SearchPath
= RtlAllocateHeap(hProcessHeap
,
125 Length
* sizeof(WCHAR
));
126 if (NULL
== SearchPath
)
128 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
131 GetCurrentDirectoryW(Length
, SearchPath
);
138 Length
= SearchPattern
- lpFileName
;
139 if (Length
+ 1 > sizeof(CurrentDir
) / sizeof(WCHAR
))
141 SearchPath
= RtlAllocateHeap(hProcessHeap
,
143 (Length
+ 1) * sizeof(WCHAR
));
144 if (NULL
== SearchPath
)
146 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
150 memcpy(SearchPath
, lpFileName
, Length
* sizeof(WCHAR
));
151 SearchPath
[Length
] = 0;
154 bResult
= RtlDosPathNameToNtPathName_U ((LPWSTR
)SearchPath
,
158 if (SearchPath
!= CurrentDir
)
160 RtlFreeHeap(hProcessHeap
,
164 if (FALSE
== bResult
)
169 DPRINT("NtPathU \'%S\'\n", NtPathU
.Buffer
);
171 IData
= RtlAllocateHeap (hProcessHeap
,
173 sizeof(KERNEL32_FIND_FILE_DATA
) + FIND_DATA_SIZE
);
176 RtlFreeHeap (hProcessHeap
,
179 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
183 /* change pattern: "*.*" --> "*" */
184 if (!wcscmp (SearchPattern
, L
"*.*"))
186 RtlRosInitUnicodeStringFromLiteral(&PatternStr
, L
"*");
190 RtlInitUnicodeString(&PatternStr
, SearchPattern
);
193 DPRINT("NtPathU \'%S\' Pattern \'%S\'\n",
194 NtPathU
.Buffer
, PatternStr
.Buffer
);
196 InitializeObjectAttributes (&ObjectAttributes
,
202 Status
= NtOpenFile (&IData
->DirectoryHandle
,
209 RtlFreeHeap (hProcessHeap
,
213 if (!NT_SUCCESS(Status
))
215 RtlFreeHeap (hProcessHeap
, 0, IData
);
216 SetLastErrorByStatus (Status
);
219 IData
->pFileInfo
= (PVOID
)IData
+ sizeof(KERNEL32_FIND_FILE_DATA
);
220 IData
->pFileInfo
->FileIndex
= 0;
222 Status
= NtQueryDirectoryFile (IData
->DirectoryHandle
,
227 (PVOID
)IData
->pFileInfo
,
229 FileBothDirectoryInformation
,
233 if (!NT_SUCCESS(Status
))
235 DPRINT("Status %lx\n", Status
);
236 RtlFreeHeap (hProcessHeap
, 0, IData
);
237 SetLastErrorByStatus (Status
);
240 DPRINT("Found %.*S\n",IData
->pFileInfo
->FileNameLength
/sizeof(WCHAR
), IData
->pFileInfo
->FileName
);
253 LPWIN32_FIND_DATAA lpFindFileData
256 PKERNEL32_FIND_FILE_DATA IData
;
257 UNICODE_STRING FileNameU
;
258 ANSI_STRING FileName
;
260 RtlInitAnsiString (&FileName
,
263 /* convert ansi (or oem) string to unicode */
265 RtlAnsiStringToUnicodeString (&FileNameU
,
269 RtlOemStringToUnicodeString (&FileNameU
,
273 IData
= InternalFindFirstFile (FileNameU
.Buffer
);
275 RtlFreeUnicodeString (&FileNameU
);
279 DPRINT("Failing request\n");
280 return INVALID_HANDLE_VALUE
;
283 DPRINT("IData->pFileInfo->FileNameLength %d\n",
284 IData
->pFileInfo
->FileNameLength
);
286 /* copy data into WIN32_FIND_DATA structure */
287 lpFindFileData
->dwFileAttributes
= IData
->pFileInfo
->FileAttributes
;
288 memcpy (&lpFindFileData
->ftCreationTime
,
289 &IData
->pFileInfo
->CreationTime
,
291 memcpy (&lpFindFileData
->ftLastAccessTime
,
292 &IData
->pFileInfo
->LastAccessTime
,
294 memcpy (&lpFindFileData
->ftLastWriteTime
,
295 &IData
->pFileInfo
->LastWriteTime
,
297 lpFindFileData
->nFileSizeHigh
= IData
->pFileInfo
->EndOfFile
.u
.HighPart
;
298 lpFindFileData
->nFileSizeLow
= IData
->pFileInfo
->EndOfFile
.u
.LowPart
;
300 FileNameU
.Length
= IData
->pFileInfo
->FileNameLength
;
301 FileNameU
.MaximumLength
= FileNameU
.Length
+ sizeof(WCHAR
);
302 FileNameU
.Buffer
= IData
->pFileInfo
->FileName
;
305 FileName
.MaximumLength
= MAX_PATH
;
306 FileName
.Buffer
= lpFindFileData
->cFileName
;
308 /* convert unicode string to ansi (or oem) */
310 RtlUnicodeStringToAnsiString (&FileName
,
314 RtlUnicodeStringToOemString (&FileName
,
318 DPRINT("IData->pFileInfo->ShortNameLength %d\n",
319 IData
->pFileInfo
->ShortNameLength
);
321 FileNameU
.Length
= IData
->pFileInfo
->ShortNameLength
;
322 FileNameU
.MaximumLength
= FileNameU
.Length
+ sizeof(WCHAR
);
323 FileNameU
.Buffer
= IData
->pFileInfo
->ShortName
;
326 FileName
.MaximumLength
= 14;
327 FileName
.Buffer
= lpFindFileData
->cAlternateFileName
;
329 /* convert unicode string to ansi (or oem) */
331 RtlUnicodeStringToAnsiString (&FileName
,
335 RtlUnicodeStringToOemString (&FileName
,
339 return (HANDLE
)IData
;
350 LPWIN32_FIND_DATAA lpFindFileData
)
352 PKERNEL32_FIND_FILE_DATA IData
;
353 UNICODE_STRING FileNameU
;
354 ANSI_STRING FileName
;
356 IData
= (PKERNEL32_FIND_FILE_DATA
)hFindFile
;
362 if (!InternalFindNextFile (hFindFile
))
364 DPRINT("InternalFindNextFile() failed\n");
368 DPRINT("IData->pFileInfo->FileNameLength %d\n",
369 IData
->pFileInfo
->FileNameLength
);
371 /* copy data into WIN32_FIND_DATA structure */
372 lpFindFileData
->dwFileAttributes
= IData
->pFileInfo
->FileAttributes
;
373 memcpy (&lpFindFileData
->ftCreationTime
,
374 &IData
->pFileInfo
->CreationTime
,
376 memcpy (&lpFindFileData
->ftLastAccessTime
,
377 &IData
->pFileInfo
->LastAccessTime
,
379 memcpy (&lpFindFileData
->ftLastWriteTime
,
380 &IData
->pFileInfo
->LastWriteTime
,
382 lpFindFileData
->nFileSizeHigh
= IData
->pFileInfo
->EndOfFile
.u
.HighPart
;
383 lpFindFileData
->nFileSizeLow
= IData
->pFileInfo
->EndOfFile
.u
.LowPart
;
385 FileNameU
.Length
= IData
->pFileInfo
->FileNameLength
;
386 FileNameU
.MaximumLength
= FileNameU
.Length
+ sizeof(WCHAR
);
387 FileNameU
.Buffer
= IData
->pFileInfo
->FileName
;
390 FileName
.MaximumLength
= MAX_PATH
;
391 FileName
.Buffer
= lpFindFileData
->cFileName
;
393 /* convert unicode string to ansi (or oem) */
395 RtlUnicodeStringToAnsiString (&FileName
,
399 RtlUnicodeStringToOemString (&FileName
,
403 DPRINT("IData->pFileInfo->ShortNameLength %d\n",
404 IData
->pFileInfo
->ShortNameLength
);
406 FileNameU
.Length
= IData
->pFileInfo
->ShortNameLength
;
407 FileNameU
.MaximumLength
= FileNameU
.Length
+ sizeof(WCHAR
);
408 FileNameU
.Buffer
= IData
->pFileInfo
->ShortName
;
411 FileName
.MaximumLength
= 14;
412 FileName
.Buffer
= lpFindFileData
->cAlternateFileName
;
414 /* convert unicode string to ansi (or oem) */
416 RtlUnicodeStringToAnsiString (&FileName
,
420 RtlUnicodeStringToOemString (&FileName
,
437 PKERNEL32_FIND_FILE_DATA IData
;
439 DPRINT("FindClose(hFindFile %x)\n",hFindFile
);
441 if (!hFindFile
|| hFindFile
== INVALID_HANDLE_VALUE
)
443 SetLastError (ERROR_INVALID_HANDLE
);
447 IData
= (PKERNEL32_FIND_FILE_DATA
)hFindFile
;
449 CloseHandle (IData
->DirectoryHandle
);
450 RtlFreeHeap (hProcessHeap
, 0, IData
);
463 LPWIN32_FIND_DATAW lpFindFileData
466 PKERNEL32_FIND_FILE_DATA IData
;
468 IData
= InternalFindFirstFile (lpFileName
);
471 DPRINT("Failing request\n");
472 return INVALID_HANDLE_VALUE
;
475 /* copy data into WIN32_FIND_DATA structure */
476 lpFindFileData
->dwFileAttributes
= IData
->pFileInfo
->FileAttributes
;
477 memcpy (&lpFindFileData
->ftCreationTime
,
478 &IData
->pFileInfo
->CreationTime
,
480 memcpy (&lpFindFileData
->ftLastAccessTime
,
481 &IData
->pFileInfo
->LastAccessTime
,
483 memcpy (&lpFindFileData
->ftLastWriteTime
,
484 &IData
->pFileInfo
->LastWriteTime
,
486 lpFindFileData
->nFileSizeHigh
= IData
->pFileInfo
->EndOfFile
.u
.HighPart
;
487 lpFindFileData
->nFileSizeLow
= IData
->pFileInfo
->EndOfFile
.u
.LowPart
;
488 memcpy (lpFindFileData
->cFileName
,
489 IData
->pFileInfo
->FileName
,
490 IData
->pFileInfo
->FileNameLength
);
491 lpFindFileData
->cFileName
[IData
->pFileInfo
->FileNameLength
/ sizeof(WCHAR
)] = 0;
492 memcpy (lpFindFileData
->cAlternateFileName
,
493 IData
->pFileInfo
->ShortName
,
494 IData
->pFileInfo
->ShortNameLength
);
495 lpFindFileData
->cAlternateFileName
[IData
->pFileInfo
->ShortNameLength
/ sizeof(WCHAR
)] = 0;
507 LPWIN32_FIND_DATAW lpFindFileData
510 PKERNEL32_FIND_FILE_DATA IData
;
512 IData
= (PKERNEL32_FIND_FILE_DATA
)hFindFile
;
513 if (!InternalFindNextFile(hFindFile
))
515 DPRINT("Failing request\n");
519 /* copy data into WIN32_FIND_DATA structure */
520 lpFindFileData
->dwFileAttributes
= IData
->pFileInfo
->FileAttributes
;
521 memcpy (&lpFindFileData
->ftCreationTime
,
522 &IData
->pFileInfo
->CreationTime
,
524 memcpy (&lpFindFileData
->ftLastAccessTime
,
525 &IData
->pFileInfo
->LastAccessTime
,
527 memcpy (&lpFindFileData
->ftLastWriteTime
,
528 &IData
->pFileInfo
->LastWriteTime
,
530 lpFindFileData
->nFileSizeHigh
= IData
->pFileInfo
->EndOfFile
.u
.HighPart
;
531 lpFindFileData
->nFileSizeLow
= IData
->pFileInfo
->EndOfFile
.u
.LowPart
;
532 memcpy (lpFindFileData
->cFileName
,
533 IData
->pFileInfo
->FileName
,
534 IData
->pFileInfo
->FileNameLength
);
535 lpFindFileData
->cFileName
[IData
->pFileInfo
->FileNameLength
/ sizeof(WCHAR
)] = 0;
536 memcpy (lpFindFileData
->cAlternateFileName
,
537 IData
->pFileInfo
->ShortName
,
538 IData
->pFileInfo
->ShortNameLength
);
539 lpFindFileData
->cAlternateFileName
[IData
->pFileInfo
->ShortNameLength
/ sizeof(WCHAR
)] = 0;
551 FINDEX_INFO_LEVELS fInfoLevelId
,
552 LPVOID lpFindFileData
,
553 FINDEX_SEARCH_OPS fSearchOp
,
554 LPVOID lpSearchFilter
,
555 DWORD dwAdditionalFlags
570 FINDEX_INFO_LEVELS fInfoLevelId
,
571 LPVOID lpFindFileData
,
572 FINDEX_SEARCH_OPS fSearchOp
,
573 LPVOID lpSearchFilter
,
574 DWORD dwAdditionalFlags