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 "../include/debug.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_DIR_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 DPRINT("InternalFindNextFile(%lx)\n", hFindFile
);
53 IData
= (PKERNEL32_FIND_FILE_DATA
)hFindFile
;
55 if (IData
->pFileInfo
->NextEntryOffset
!= 0)
57 IData
->pFileInfo
= (PVOID
)((ULONG_PTR
)IData
->pFileInfo
+ IData
->pFileInfo
->NextEntryOffset
);
58 DPRINT("Found %.*S\n",IData
->pFileInfo
->FileNameLength
/sizeof(WCHAR
), IData
->pFileInfo
->FileName
);
61 IData
->pFileInfo
= (PVOID
)((ULONG_PTR
)IData
+ sizeof(KERNEL32_FIND_FILE_DATA
));
62 IData
->pFileInfo
->FileIndex
= 0;
63 Status
= NtQueryDirectoryFile (IData
->DirectoryHandle
,
68 (PVOID
)IData
->pFileInfo
,
70 FileBothDirectoryInformation
,
74 if (!NT_SUCCESS(Status
))
76 SetLastErrorByStatus (Status
);
79 DPRINT("Found %.*S\n",IData
->pFileInfo
->FileNameLength
/sizeof(WCHAR
), IData
->pFileInfo
->FileName
);
89 InternalFindFirstFile (
93 OBJECT_ATTRIBUTES ObjectAttributes
;
94 PKERNEL32_FIND_FILE_DATA IData
;
95 IO_STATUS_BLOCK IoStatusBlock
;
96 UNICODE_STRING NtPathU
;
97 UNICODE_STRING PatternStr
= RTL_CONSTANT_STRING(L
"*");
100 WCHAR CurrentDir
[256];
101 PWCHAR SlashlessFileName
;
103 PWCHAR SearchPattern
;
107 DPRINT("FindFirstFileW(lpFileName %S)\n",
110 Length
= wcslen(lpFileName
);
111 if (L
'\\' == lpFileName
[Length
- 1])
113 SlashlessFileName
= RtlAllocateHeap(hProcessHeap
,
115 Length
* sizeof(WCHAR
));
116 if (NULL
== SlashlessFileName
)
118 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
121 memcpy(SlashlessFileName
, lpFileName
, (Length
- 1) * sizeof(WCHAR
));
122 SlashlessFileName
[Length
- 1] = L
'\0';
123 lpFileName
= SlashlessFileName
;
127 SlashlessFileName
= NULL
;
130 e1
= wcsrchr(lpFileName
, L
'/');
131 e2
= wcsrchr(lpFileName
, L
'\\');
132 SearchPattern
= max(e1
, e2
);
133 SearchPath
= CurrentDir
;
135 if (NULL
== SearchPattern
)
138 SearchPattern
= (PWCHAR
)lpFileName
;
139 Length
= GetCurrentDirectoryW(sizeof(CurrentDir
) / sizeof(WCHAR
), SearchPath
);
142 if (NULL
!= SlashlessFileName
)
144 RtlFreeHeap(hProcessHeap
,
150 if (Length
> sizeof(CurrentDir
) / sizeof(WCHAR
))
152 SearchPath
= RtlAllocateHeap(hProcessHeap
,
154 Length
* sizeof(WCHAR
));
155 if (NULL
== SearchPath
)
157 if (NULL
!= SlashlessFileName
)
159 RtlFreeHeap(hProcessHeap
,
163 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
166 GetCurrentDirectoryW(Length
, SearchPath
);
173 Length
= SearchPattern
- lpFileName
;
174 if (Length
+ 1 > sizeof(CurrentDir
) / sizeof(WCHAR
))
176 SearchPath
= RtlAllocateHeap(hProcessHeap
,
178 (Length
+ 1) * sizeof(WCHAR
));
179 if (NULL
== SearchPath
)
181 if (NULL
!= SlashlessFileName
)
183 RtlFreeHeap(hProcessHeap
,
187 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
191 memcpy(SearchPath
, lpFileName
, Length
* sizeof(WCHAR
));
192 SearchPath
[Length
] = 0;
195 bResult
= RtlDosPathNameToNtPathName_U ((LPWSTR
)SearchPath
,
199 if (SearchPath
!= CurrentDir
)
201 RtlFreeHeap(hProcessHeap
,
205 if (FALSE
== bResult
)
207 if (NULL
!= SlashlessFileName
)
209 RtlFreeHeap(hProcessHeap
,
216 DPRINT("NtPathU \'%S\'\n", NtPathU
.Buffer
);
218 IData
= RtlAllocateHeap (hProcessHeap
,
220 sizeof(KERNEL32_FIND_FILE_DATA
) + FIND_DATA_SIZE
);
223 RtlFreeHeap (hProcessHeap
,
226 if (NULL
!= SlashlessFileName
)
228 RtlFreeHeap(hProcessHeap
,
232 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
236 /* change pattern: "*.*" --> "*" */
237 if (wcscmp (SearchPattern
, L
"*.*"))
239 RtlInitUnicodeString(&PatternStr
, SearchPattern
);
242 DPRINT("NtPathU \'%S\' Pattern \'%S\'\n",
243 NtPathU
.Buffer
, PatternStr
.Buffer
);
245 InitializeObjectAttributes (&ObjectAttributes
,
251 Status
= NtOpenFile (&IData
->DirectoryHandle
,
255 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
256 FILE_DIRECTORY_FILE
);
258 RtlFreeHeap (hProcessHeap
,
262 if (!NT_SUCCESS(Status
))
264 RtlFreeHeap (hProcessHeap
, 0, IData
);
265 if (NULL
!= SlashlessFileName
)
267 RtlFreeHeap(hProcessHeap
,
271 SetLastErrorByStatus (Status
);
274 IData
->pFileInfo
= (PVOID
)((ULONG_PTR
)IData
+ sizeof(KERNEL32_FIND_FILE_DATA
));
275 IData
->pFileInfo
->FileIndex
= 0;
277 Status
= NtQueryDirectoryFile (IData
->DirectoryHandle
,
282 (PVOID
)IData
->pFileInfo
,
284 FileBothDirectoryInformation
,
288 if (NULL
!= SlashlessFileName
)
290 RtlFreeHeap(hProcessHeap
,
294 if (!NT_SUCCESS(Status
))
296 DPRINT("Status %lx\n", Status
);
297 CloseHandle (IData
->DirectoryHandle
);
298 RtlFreeHeap (hProcessHeap
, 0, IData
);
299 SetLastErrorByStatus (Status
);
302 DPRINT("Found %.*S\n",IData
->pFileInfo
->FileNameLength
/sizeof(WCHAR
), IData
->pFileInfo
->FileName
);
315 LPWIN32_FIND_DATAA lpFindFileData
318 PKERNEL32_FIND_FILE_DATA IData
;
319 UNICODE_STRING FileNameU
;
320 ANSI_STRING FileName
;
322 RtlInitAnsiString (&FileName
,
325 /* convert ansi (or oem) string to unicode */
327 RtlAnsiStringToUnicodeString (&FileNameU
,
331 RtlOemStringToUnicodeString (&FileNameU
,
335 IData
= InternalFindFirstFile (FileNameU
.Buffer
);
337 RtlFreeUnicodeString (&FileNameU
);
341 DPRINT("Failing request\n");
342 return INVALID_HANDLE_VALUE
;
345 DPRINT("IData->pFileInfo->FileNameLength %d\n",
346 IData
->pFileInfo
->FileNameLength
);
348 /* copy data into WIN32_FIND_DATA structure */
349 lpFindFileData
->dwFileAttributes
= IData
->pFileInfo
->FileAttributes
;
351 lpFindFileData
->ftCreationTime
.dwHighDateTime
= IData
->pFileInfo
->CreationTime
.u
.HighPart
;
352 lpFindFileData
->ftCreationTime
.dwLowDateTime
= IData
->pFileInfo
->CreationTime
.u
.LowPart
;
354 lpFindFileData
->ftLastAccessTime
.dwHighDateTime
= IData
->pFileInfo
->LastAccessTime
.u
.HighPart
;
355 lpFindFileData
->ftLastAccessTime
.dwLowDateTime
= IData
->pFileInfo
->LastAccessTime
.u
.LowPart
;
357 lpFindFileData
->ftLastWriteTime
.dwHighDateTime
= IData
->pFileInfo
->LastWriteTime
.u
.HighPart
;
358 lpFindFileData
->ftLastWriteTime
.dwLowDateTime
= IData
->pFileInfo
->LastWriteTime
.u
.LowPart
;
360 lpFindFileData
->nFileSizeHigh
= IData
->pFileInfo
->EndOfFile
.u
.HighPart
;
361 lpFindFileData
->nFileSizeLow
= IData
->pFileInfo
->EndOfFile
.u
.LowPart
;
363 FileNameU
.Length
= IData
->pFileInfo
->FileNameLength
;
364 FileNameU
.MaximumLength
= FileNameU
.Length
+ sizeof(WCHAR
);
365 FileNameU
.Buffer
= IData
->pFileInfo
->FileName
;
368 FileName
.MaximumLength
= MAX_PATH
;
369 FileName
.Buffer
= lpFindFileData
->cFileName
;
371 /* convert unicode string to ansi (or oem) */
373 RtlUnicodeStringToAnsiString (&FileName
,
377 RtlUnicodeStringToOemString (&FileName
,
381 DPRINT("IData->pFileInfo->ShortNameLength %d\n",
382 IData
->pFileInfo
->ShortNameLength
);
384 FileNameU
.Length
= IData
->pFileInfo
->ShortNameLength
;
385 FileNameU
.MaximumLength
= FileNameU
.Length
+ sizeof(WCHAR
);
386 FileNameU
.Buffer
= IData
->pFileInfo
->ShortName
;
389 FileName
.MaximumLength
= 14;
390 FileName
.Buffer
= lpFindFileData
->cAlternateFileName
;
392 /* convert unicode string to ansi (or oem) */
394 RtlUnicodeStringToAnsiString (&FileName
,
398 RtlUnicodeStringToOemString (&FileName
,
402 return (HANDLE
)IData
;
413 LPWIN32_FIND_DATAA lpFindFileData
)
415 PKERNEL32_FIND_FILE_DATA IData
;
416 UNICODE_STRING FileNameU
;
417 ANSI_STRING FileName
;
419 if (hFindFile
== INVALID_HANDLE_VALUE
)
421 SetLastError (ERROR_INVALID_HANDLE
);
422 DPRINT("Failing request\n");
426 IData
= (PKERNEL32_FIND_FILE_DATA
)hFindFile
;
427 if (!InternalFindNextFile (hFindFile
))
429 DPRINT("InternalFindNextFile() failed\n");
433 DPRINT("IData->pFileInfo->FileNameLength %d\n",
434 IData
->pFileInfo
->FileNameLength
);
436 /* copy data into WIN32_FIND_DATA structure */
437 lpFindFileData
->dwFileAttributes
= IData
->pFileInfo
->FileAttributes
;
439 lpFindFileData
->ftCreationTime
.dwHighDateTime
= IData
->pFileInfo
->CreationTime
.u
.HighPart
;
440 lpFindFileData
->ftCreationTime
.dwLowDateTime
= IData
->pFileInfo
->CreationTime
.u
.LowPart
;
442 lpFindFileData
->ftLastAccessTime
.dwHighDateTime
= IData
->pFileInfo
->LastAccessTime
.u
.HighPart
;
443 lpFindFileData
->ftLastAccessTime
.dwLowDateTime
= IData
->pFileInfo
->LastAccessTime
.u
.LowPart
;
445 lpFindFileData
->ftLastWriteTime
.dwHighDateTime
= IData
->pFileInfo
->LastWriteTime
.u
.HighPart
;
446 lpFindFileData
->ftLastWriteTime
.dwLowDateTime
= IData
->pFileInfo
->LastWriteTime
.u
.LowPart
;
448 lpFindFileData
->nFileSizeHigh
= IData
->pFileInfo
->EndOfFile
.u
.HighPart
;
449 lpFindFileData
->nFileSizeLow
= IData
->pFileInfo
->EndOfFile
.u
.LowPart
;
451 FileNameU
.Length
= IData
->pFileInfo
->FileNameLength
;
452 FileNameU
.MaximumLength
= FileNameU
.Length
+ sizeof(WCHAR
);
453 FileNameU
.Buffer
= IData
->pFileInfo
->FileName
;
456 FileName
.MaximumLength
= MAX_PATH
;
457 FileName
.Buffer
= lpFindFileData
->cFileName
;
459 /* convert unicode string to ansi (or oem) */
461 RtlUnicodeStringToAnsiString (&FileName
,
465 RtlUnicodeStringToOemString (&FileName
,
469 DPRINT("IData->pFileInfo->ShortNameLength %d\n",
470 IData
->pFileInfo
->ShortNameLength
);
472 FileNameU
.Length
= IData
->pFileInfo
->ShortNameLength
;
473 FileNameU
.MaximumLength
= FileNameU
.Length
+ sizeof(WCHAR
);
474 FileNameU
.Buffer
= IData
->pFileInfo
->ShortName
;
477 FileName
.MaximumLength
= 14;
478 FileName
.Buffer
= lpFindFileData
->cAlternateFileName
;
480 /* convert unicode string to ansi (or oem) */
482 RtlUnicodeStringToAnsiString (&FileName
,
486 RtlUnicodeStringToOemString (&FileName
,
503 PKERNEL32_FIND_FILE_DATA IData
;
505 DPRINT("FindClose(hFindFile %x)\n",hFindFile
);
507 if (!hFindFile
|| hFindFile
== INVALID_HANDLE_VALUE
)
509 SetLastError (ERROR_INVALID_HANDLE
);
513 IData
= (PKERNEL32_FIND_FILE_DATA
)hFindFile
;
515 CloseHandle (IData
->DirectoryHandle
);
516 RtlFreeHeap (hProcessHeap
, 0, IData
);
529 LPWIN32_FIND_DATAW lpFindFileData
532 PKERNEL32_FIND_FILE_DATA IData
;
534 IData
= InternalFindFirstFile (lpFileName
);
537 DPRINT("Failing request\n");
538 return INVALID_HANDLE_VALUE
;
541 /* copy data into WIN32_FIND_DATA structure */
542 lpFindFileData
->dwFileAttributes
= IData
->pFileInfo
->FileAttributes
;
544 lpFindFileData
->ftCreationTime
.dwHighDateTime
= IData
->pFileInfo
->CreationTime
.u
.HighPart
;
545 lpFindFileData
->ftCreationTime
.dwLowDateTime
= IData
->pFileInfo
->CreationTime
.u
.LowPart
;
547 lpFindFileData
->ftLastAccessTime
.dwHighDateTime
= IData
->pFileInfo
->LastAccessTime
.u
.HighPart
;
548 lpFindFileData
->ftLastAccessTime
.dwLowDateTime
= IData
->pFileInfo
->LastAccessTime
.u
.LowPart
;
550 lpFindFileData
->ftLastWriteTime
.dwHighDateTime
= IData
->pFileInfo
->LastWriteTime
.u
.HighPart
;
551 lpFindFileData
->ftLastWriteTime
.dwLowDateTime
= IData
->pFileInfo
->LastWriteTime
.u
.LowPart
;
553 lpFindFileData
->nFileSizeHigh
= IData
->pFileInfo
->EndOfFile
.u
.HighPart
;
554 lpFindFileData
->nFileSizeLow
= IData
->pFileInfo
->EndOfFile
.u
.LowPart
;
556 memcpy (lpFindFileData
->cFileName
,
557 IData
->pFileInfo
->FileName
,
558 IData
->pFileInfo
->FileNameLength
);
559 lpFindFileData
->cFileName
[IData
->pFileInfo
->FileNameLength
/ sizeof(WCHAR
)] = 0;
560 memcpy (lpFindFileData
->cAlternateFileName
,
561 IData
->pFileInfo
->ShortName
,
562 IData
->pFileInfo
->ShortNameLength
);
563 lpFindFileData
->cAlternateFileName
[IData
->pFileInfo
->ShortNameLength
/ sizeof(WCHAR
)] = 0;
575 LPWIN32_FIND_DATAW lpFindFileData
578 PKERNEL32_FIND_FILE_DATA IData
;
580 if (hFindFile
== INVALID_HANDLE_VALUE
)
582 SetLastError (ERROR_INVALID_HANDLE
);
583 DPRINT("Failing request\n");
587 IData
= (PKERNEL32_FIND_FILE_DATA
)hFindFile
;
588 if (!InternalFindNextFile(hFindFile
))
590 DPRINT("Failing request\n");
594 /* copy data into WIN32_FIND_DATA structure */
595 lpFindFileData
->dwFileAttributes
= IData
->pFileInfo
->FileAttributes
;
597 lpFindFileData
->ftCreationTime
.dwHighDateTime
= IData
->pFileInfo
->CreationTime
.u
.HighPart
;
598 lpFindFileData
->ftCreationTime
.dwLowDateTime
= IData
->pFileInfo
->CreationTime
.u
.LowPart
;
600 lpFindFileData
->ftLastAccessTime
.dwHighDateTime
= IData
->pFileInfo
->LastAccessTime
.u
.HighPart
;
601 lpFindFileData
->ftLastAccessTime
.dwLowDateTime
= IData
->pFileInfo
->LastAccessTime
.u
.LowPart
;
603 lpFindFileData
->ftLastWriteTime
.dwHighDateTime
= IData
->pFileInfo
->LastWriteTime
.u
.HighPart
;
604 lpFindFileData
->ftLastWriteTime
.dwLowDateTime
= IData
->pFileInfo
->LastWriteTime
.u
.LowPart
;
606 lpFindFileData
->nFileSizeHigh
= IData
->pFileInfo
->EndOfFile
.u
.HighPart
;
607 lpFindFileData
->nFileSizeLow
= IData
->pFileInfo
->EndOfFile
.u
.LowPart
;
609 lpFindFileData
->nFileSizeHigh
= IData
->pFileInfo
->EndOfFile
.u
.HighPart
;
610 lpFindFileData
->nFileSizeLow
= IData
->pFileInfo
->EndOfFile
.u
.LowPart
;
612 memcpy (lpFindFileData
->cFileName
,
613 IData
->pFileInfo
->FileName
,
614 IData
->pFileInfo
->FileNameLength
);
615 lpFindFileData
->cFileName
[IData
->pFileInfo
->FileNameLength
/ sizeof(WCHAR
)] = 0;
616 memcpy (lpFindFileData
->cAlternateFileName
,
617 IData
->pFileInfo
->ShortName
,
618 IData
->pFileInfo
->ShortNameLength
);
619 lpFindFileData
->cAlternateFileName
[IData
->pFileInfo
->ShortNameLength
/ sizeof(WCHAR
)] = 0;
631 FINDEX_INFO_LEVELS fInfoLevelId
,
632 LPVOID lpFindFileData
,
633 FINDEX_SEARCH_OPS fSearchOp
,
634 LPVOID lpSearchFilter
,
635 DWORD dwAdditionalFlags
650 FINDEX_INFO_LEVELS fInfoLevelId
,
651 LPVOID lpFindFileData
,
652 FINDEX_SEARCH_OPS fSearchOp
,
653 LPVOID lpSearchFilter
,
654 DWORD dwAdditionalFlags