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)
11 /* INCLUDES *****************************************************************/
15 #include <ddk/ntddk.h>
19 #include <kernel32/kernel32.h>
21 /* TYPES ********************************************************************/
23 typedef struct _KERNEL32_FIND_FILE_DATA
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
;
31 typedef struct _WIN32_FIND_DATA_UNICODE
{
32 DWORD dwFileAttributes
;
33 FILETIME ftCreationTime
;
34 FILETIME ftLastAccessTime
;
35 FILETIME ftLastWriteTime
;
40 WCHAR cFileName
[ MAX_PATH
];
41 WCHAR cAlternateFileName
[ 14 ];
42 } WIN32_FIND_DATA_UNICODE
, *PWIN32_FIND_DATA_UNICODE
;
44 typedef struct _WIN32_FIND_DATA_ASCII
{
45 DWORD dwFileAttributes
;
46 FILETIME ftCreationTime
;
47 FILETIME ftLastAccessTime
;
48 FILETIME ftLastWriteTime
;
53 CHAR cFileName
[ MAX_PATH
];
54 CHAR cAlternateFileName
[ 14 ];
55 } WIN32_FIND_DATA_ASCII
, *PWIN32_FIND_DATA_ASCII
;
57 /* FUNCTIONS ****************************************************************/
59 static void FileDataToWin32Data(LPWIN32_FIND_DATA lpFindFileData
, PKERNEL32_FIND_FILE_DATA IData
)
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
;
69 WINBOOL STDCALL
InternalFindNextFile(HANDLE hFindFile
,
70 LPWIN32_FIND_DATA lpFindFileData
)
72 IO_STATUS_BLOCK IoStatusBlock
;
74 PKERNEL32_FIND_FILE_DATA IData
;
76 IData
= (PKERNEL32_FIND_FILE_DATA
)hFindFile
;
78 Status
= NtQueryDirectoryFile(IData
->DirectoryHandle
,
83 (PVOID
)&IData
->FileInfo
,
84 sizeof(IData
->FileInfo
) +
85 sizeof(IData
->FileNameExtra
),
86 FileBothDirectoryInformation
,
90 DPRINT("Found %w\n",IData
->FileInfo
.FileName
);
91 if (Status
!= STATUS_SUCCESS
)
96 FileDataToWin32Data(lpFindFileData
, IData
);
101 HANDLE STDCALL
InternalFindFirstFile(LPCWSTR lpFileName
,
102 LPWIN32_FIND_DATA lpFindFileData
)
104 WCHAR CurrentDirectory
[MAX_PATH
];
105 WCHAR Pattern
[MAX_PATH
];
106 WCHAR Directory
[MAX_PATH
];
108 PKERNEL32_FIND_FILE_DATA IData
;
109 OBJECT_ATTRIBUTES ObjectAttributes
;
110 UNICODE_STRING DirectoryNameStr
;
111 IO_STATUS_BLOCK IoStatusBlock
;
113 DPRINT("FindFirstFileW(lpFileName %w, lpFindFileData %x)\n",
114 lpFileName
, lpFindFileData
);
116 GetFullPathNameW(lpFileName
, MAX_PATH
, CurrentDirectory
, NULL
);
122 DPRINT("Directory %w\n",Directory
);
123 wcscat(Directory
, CurrentDirectory
);
124 DPRINT("Directory %w\n",Directory
);
125 End
= wcsrchr(Directory
, '\\');
128 wcscpy(Pattern
, End
+1);
132 /* change pattern: "*.*" --> "*" */
133 if (!wcscmp(Pattern
, L
"*.*"))
136 DPRINT("Directory %w Pattern %w\n",Directory
,Pattern
);
138 IData
= HeapAlloc(GetProcessHeap(),
140 sizeof(KERNEL32_FIND_FILE_DATA
));
142 RtlInitUnicodeString(&DirectoryNameStr
, Directory
);
143 InitializeObjectAttributes(&ObjectAttributes
,
149 if (ZwOpenFile(&IData
->DirectoryHandle
,
154 OPEN_EXISTING
)!=STATUS_SUCCESS
)
159 RtlInitUnicodeString(&(IData
->PatternStr
), Pattern
);
161 NtQueryDirectoryFile(IData
->DirectoryHandle
,
166 (PVOID
)&IData
->FileInfo
,
167 sizeof(IData
->FileInfo
) +
168 sizeof(IData
->FileNameExtra
),
169 FileBothDirectoryInformation
,
171 &(IData
->PatternStr
),
173 DPRINT("Found %w\n",IData
->FileInfo
.FileName
);
175 FileDataToWin32Data(lpFindFileData
, IData
);
180 HANDLE
FindFirstFileA(LPCTSTR lpFileName
, LPWIN32_FIND_DATA lpFindFileData
)
182 WCHAR lpFileNameW
[MAX_PATH
];
184 PKERNEL32_FIND_FILE_DATA IData
;
185 PWIN32_FIND_DATA_ASCII Ret
;
188 while (lpFileName
[i
]!=0)
190 lpFileNameW
[i
] = lpFileName
[i
];
195 IData
= InternalFindFirstFile(lpFileNameW
,lpFindFileData
);
198 DPRINT("Failing request\n");
199 return(INVALID_HANDLE_VALUE
);
203 Ret
= (PWIN32_FIND_DATA_ASCII
)lpFindFileData
;
205 DPRINT("IData->FileInfo.FileNameLength %d\n",
206 IData
->FileInfo
.FileNameLength
);
207 for (i
=0; i
<IData
->FileInfo
.FileNameLength
; i
++)
209 Ret
->cFileName
[i
] = IData
->FileInfo
.FileName
[i
];
211 Ret
->cFileName
[i
] = 0;
213 DPRINT("IData->FileInfo.ShortNameLength %d\n",
214 IData
->FileInfo
.ShortNameLength
);
215 if (IData
->FileInfo
.ShortNameLength
> 13)
217 IData
->FileInfo
.ShortNameLength
= 13;
219 for (i
=0; i
<IData
->FileInfo
.ShortNameLength
; i
++)
221 Ret
->cAlternateFileName
[i
] = IData
->FileInfo
.ShortName
[i
];
223 Ret
->cAlternateFileName
[i
] = 0;
229 WINBOOL
FindNextFileA(HANDLE hFindFile
, LPWIN32_FIND_DATA lpFindFileData
)
231 PWIN32_FIND_DATA_ASCII Ret
;
232 PKERNEL32_FIND_FILE_DATA IData
;
235 IData
= (PKERNEL32_FIND_FILE_DATA
)hFindFile
;
240 if (!InternalFindNextFile(hFindFile
, lpFindFileData
))
242 DPRINT("InternalFindNextFile() failed\n");
246 Ret
= (PWIN32_FIND_DATA_ASCII
)lpFindFileData
;
248 DPRINT("IData->FileInfo.FileNameLength %d\n",
249 IData
->FileInfo
.FileNameLength
);
250 for (i
=0; i
<IData
->FileInfo
.FileNameLength
; i
++)
252 Ret
->cFileName
[i
] = IData
->FileInfo
.FileName
[i
];
254 Ret
->cFileName
[i
] = 0;
256 DPRINT("IData->FileInfo.ShortNameLength %d\n",
257 IData
->FileInfo
.ShortNameLength
);
258 for (i
=0; i
<IData
->FileInfo
.ShortNameLength
; i
++)
260 Ret
->cAlternateFileName
[i
] = IData
->FileInfo
.ShortName
[i
];
262 Ret
->cAlternateFileName
[i
] = 0;
267 BOOL
FindClose(HANDLE hFindFile
)
269 PKERNEL32_FIND_FILE_DATA IData
;
271 DPRINT("FindClose(hFindFile %x)\n",hFindFile
);
273 if (hFindFile
|| hFindFile
== INVALID_HANDLE_VALUE
)
275 SetLastError (ERROR_INVALID_HANDLE
);
278 IData
= (PKERNEL32_FIND_FILE_DATA
)hFindFile
;
279 CloseHandle(IData
->DirectoryHandle
);
280 HeapFree(GetProcessHeap(), 0, IData
);
284 HANDLE STDCALL
FindFirstFileW(LPCWSTR lpFileName
,
285 LPWIN32_FIND_DATA lpFindFileData
)
287 PWIN32_FIND_DATA_UNICODE Ret
;
288 PKERNEL32_FIND_FILE_DATA IData
;
290 IData
= InternalFindFirstFile(lpFileName
,lpFindFileData
);
291 Ret
= (PWIN32_FIND_DATA_UNICODE
)lpFindFileData
;
293 memcpy(Ret
->cFileName
, IData
->FileInfo
.FileName
,
294 IData
->FileInfo
.FileNameLength
);
295 memcpy(Ret
->cAlternateFileName
, IData
->FileInfo
.ShortName
,
296 IData
->FileInfo
.ShortNameLength
);
301 WINBOOL STDCALL
FindNextFileW(HANDLE hFindFile
,
302 LPWIN32_FIND_DATA lpFindFileData
)
304 PWIN32_FIND_DATA_UNICODE Ret
;
305 PKERNEL32_FIND_FILE_DATA IData
;
307 IData
= (PKERNEL32_FIND_FILE_DATA
)hFindFile
;
308 if (!InternalFindNextFile(hFindFile
, lpFindFileData
))
313 Ret
= (PWIN32_FIND_DATA_UNICODE
)lpFindFileData
;
315 memcpy(Ret
->cFileName
, IData
->FileInfo
.FileName
,
316 IData
->FileInfo
.FileNameLength
);
317 memcpy(Ret
->cAlternateFileName
, IData
->FileInfo
.ShortName
,
318 IData
->FileInfo
.ShortNameLength
);