mirror of
https://github.com/reactos/reactos.git
synced 2024-12-27 09:34:43 +00:00
Dmitry Philippov <shedon@mail.ru>:
- Implemented FindFirstFileExW() and have removed InternalFindFirstFile() in /lib/kernel32/file/find.c, now FindFirstFileA (), FindFirstFileExA () and FindFirstFileW called FindFirstFileExW () NOTE: Filip has asked revision "16661" (the next one) to be done by him... sorry if this sounds silly, but please respect his wish :) svn path=/trunk/; revision=16660
This commit is contained in:
parent
e8ebef770f
commit
692af5f653
1 changed files with 374 additions and 376 deletions
|
@ -4,9 +4,11 @@
|
|||
* PROJECT: ReactOS system libraries
|
||||
* FILE: lib/kernel32/file/find.c
|
||||
* PURPOSE: Find functions
|
||||
* PROGRAMMER: Ariadne ( ariadne@xs4all.nl)
|
||||
* PROGRAMMERS: Ariadne ( ariadne@xs4all.nl)
|
||||
Dmitry Philippov ( shedon@mail.ru )
|
||||
* UPDATE HISTORY:
|
||||
* Created 01/11/98
|
||||
* DP (18/06/2005) remove InternalFindFirstFile, implemented FindFirstFileExW
|
||||
*/
|
||||
|
||||
/* INCLUDES *****************************************************************/
|
||||
|
@ -80,329 +82,6 @@ InternalFindNextFile (
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
HANDLE
|
||||
STDCALL
|
||||
InternalFindFirstFile (
|
||||
LPCWSTR lpFileName
|
||||
)
|
||||
{
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
PKERNEL32_FIND_FILE_DATA IData;
|
||||
IO_STATUS_BLOCK IoStatusBlock;
|
||||
UNICODE_STRING NtPathU;
|
||||
UNICODE_STRING PatternStr = RTL_CONSTANT_STRING(L"*");
|
||||
NTSTATUS Status;
|
||||
PWSTR e1, e2;
|
||||
WCHAR CurrentDir[256];
|
||||
PWCHAR SlashlessFileName;
|
||||
PWSTR SearchPath;
|
||||
PWCHAR SearchPattern;
|
||||
ULONG Length;
|
||||
BOOLEAN bResult;
|
||||
|
||||
DPRINT("FindFirstFileW(lpFileName %S)\n",
|
||||
lpFileName);
|
||||
|
||||
Length = wcslen(lpFileName);
|
||||
if (L'\\' == lpFileName[Length - 1])
|
||||
{
|
||||
SlashlessFileName = RtlAllocateHeap(hProcessHeap,
|
||||
0,
|
||||
Length * sizeof(WCHAR));
|
||||
if (NULL == SlashlessFileName)
|
||||
{
|
||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||
return NULL;
|
||||
}
|
||||
memcpy(SlashlessFileName, lpFileName, (Length - 1) * sizeof(WCHAR));
|
||||
SlashlessFileName[Length - 1] = L'\0';
|
||||
lpFileName = SlashlessFileName;
|
||||
}
|
||||
else
|
||||
{
|
||||
SlashlessFileName = NULL;
|
||||
}
|
||||
|
||||
e1 = wcsrchr(lpFileName, L'/');
|
||||
e2 = wcsrchr(lpFileName, L'\\');
|
||||
SearchPattern = max(e1, e2);
|
||||
SearchPath = CurrentDir;
|
||||
|
||||
if (NULL == SearchPattern)
|
||||
{
|
||||
CHECKPOINT;
|
||||
SearchPattern = (PWCHAR)lpFileName;
|
||||
Length = GetCurrentDirectoryW(sizeof(CurrentDir) / sizeof(WCHAR), SearchPath);
|
||||
if (0 == Length)
|
||||
{
|
||||
if (NULL != SlashlessFileName)
|
||||
{
|
||||
RtlFreeHeap(hProcessHeap,
|
||||
0,
|
||||
SlashlessFileName);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
if (Length > sizeof(CurrentDir) / sizeof(WCHAR))
|
||||
{
|
||||
SearchPath = RtlAllocateHeap(hProcessHeap,
|
||||
HEAP_ZERO_MEMORY,
|
||||
Length * sizeof(WCHAR));
|
||||
if (NULL == SearchPath)
|
||||
{
|
||||
if (NULL != SlashlessFileName)
|
||||
{
|
||||
RtlFreeHeap(hProcessHeap,
|
||||
0,
|
||||
SlashlessFileName);
|
||||
}
|
||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||
return NULL;
|
||||
}
|
||||
GetCurrentDirectoryW(Length, SearchPath);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CHECKPOINT;
|
||||
SearchPattern++;
|
||||
Length = SearchPattern - lpFileName;
|
||||
if (Length + 1 > sizeof(CurrentDir) / sizeof(WCHAR))
|
||||
{
|
||||
SearchPath = RtlAllocateHeap(hProcessHeap,
|
||||
HEAP_ZERO_MEMORY,
|
||||
(Length + 1) * sizeof(WCHAR));
|
||||
if (NULL == SearchPath)
|
||||
{
|
||||
if (NULL != SlashlessFileName)
|
||||
{
|
||||
RtlFreeHeap(hProcessHeap,
|
||||
0,
|
||||
SlashlessFileName);
|
||||
}
|
||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
memcpy(SearchPath, lpFileName, Length * sizeof(WCHAR));
|
||||
SearchPath[Length] = 0;
|
||||
}
|
||||
|
||||
bResult = RtlDosPathNameToNtPathName_U ((LPWSTR)SearchPath,
|
||||
&NtPathU,
|
||||
NULL,
|
||||
NULL);
|
||||
if (SearchPath != CurrentDir)
|
||||
{
|
||||
RtlFreeHeap(hProcessHeap,
|
||||
0,
|
||||
SearchPath);
|
||||
}
|
||||
if (FALSE == bResult)
|
||||
{
|
||||
if (NULL != SlashlessFileName)
|
||||
{
|
||||
RtlFreeHeap(hProcessHeap,
|
||||
0,
|
||||
SlashlessFileName);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DPRINT("NtPathU \'%S\'\n", NtPathU.Buffer);
|
||||
|
||||
IData = RtlAllocateHeap (hProcessHeap,
|
||||
HEAP_ZERO_MEMORY,
|
||||
sizeof(KERNEL32_FIND_FILE_DATA) + FIND_DATA_SIZE);
|
||||
if (NULL == IData)
|
||||
{
|
||||
RtlFreeHeap (hProcessHeap,
|
||||
0,
|
||||
NtPathU.Buffer);
|
||||
if (NULL != SlashlessFileName)
|
||||
{
|
||||
RtlFreeHeap(hProcessHeap,
|
||||
0,
|
||||
SlashlessFileName);
|
||||
}
|
||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* change pattern: "*.*" --> "*" */
|
||||
if (wcscmp (SearchPattern, L"*.*"))
|
||||
{
|
||||
RtlInitUnicodeString(&PatternStr, SearchPattern);
|
||||
}
|
||||
|
||||
DPRINT("NtPathU \'%S\' Pattern \'%S\'\n",
|
||||
NtPathU.Buffer, PatternStr.Buffer);
|
||||
|
||||
InitializeObjectAttributes (&ObjectAttributes,
|
||||
&NtPathU,
|
||||
0,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
Status = NtOpenFile (&IData->DirectoryHandle,
|
||||
FILE_LIST_DIRECTORY,
|
||||
&ObjectAttributes,
|
||||
&IoStatusBlock,
|
||||
FILE_SHARE_READ|FILE_SHARE_WRITE,
|
||||
FILE_DIRECTORY_FILE);
|
||||
|
||||
RtlFreeHeap (hProcessHeap,
|
||||
0,
|
||||
NtPathU.Buffer);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
RtlFreeHeap (hProcessHeap, 0, IData);
|
||||
if (NULL != SlashlessFileName)
|
||||
{
|
||||
RtlFreeHeap(hProcessHeap,
|
||||
0,
|
||||
SlashlessFileName);
|
||||
}
|
||||
SetLastErrorByStatus (Status);
|
||||
return(NULL);
|
||||
}
|
||||
IData->pFileInfo = (PVOID)((ULONG_PTR)IData + sizeof(KERNEL32_FIND_FILE_DATA));
|
||||
IData->pFileInfo->FileIndex = 0;
|
||||
|
||||
Status = NtQueryDirectoryFile (IData->DirectoryHandle,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
&IoStatusBlock,
|
||||
(PVOID)IData->pFileInfo,
|
||||
FIND_DATA_SIZE,
|
||||
FileBothDirectoryInformation,
|
||||
TRUE,
|
||||
&PatternStr,
|
||||
TRUE);
|
||||
if (NULL != SlashlessFileName)
|
||||
{
|
||||
RtlFreeHeap(hProcessHeap,
|
||||
0,
|
||||
SlashlessFileName);
|
||||
}
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("Status %lx\n", Status);
|
||||
CloseHandle (IData->DirectoryHandle);
|
||||
RtlFreeHeap (hProcessHeap, 0, IData);
|
||||
SetLastErrorByStatus (Status);
|
||||
return NULL;
|
||||
}
|
||||
DPRINT("Found %.*S\n",IData->pFileInfo->FileNameLength/sizeof(WCHAR), IData->pFileInfo->FileName);
|
||||
|
||||
return IData;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
HANDLE
|
||||
STDCALL
|
||||
FindFirstFileA (
|
||||
LPCSTR lpFileName,
|
||||
LPWIN32_FIND_DATAA lpFindFileData
|
||||
)
|
||||
{
|
||||
PKERNEL32_FIND_FILE_DATA IData;
|
||||
UNICODE_STRING FileNameU;
|
||||
ANSI_STRING FileName;
|
||||
|
||||
RtlInitAnsiString (&FileName,
|
||||
(LPSTR)lpFileName);
|
||||
|
||||
/* convert ansi (or oem) string to unicode */
|
||||
if (bIsFileApiAnsi)
|
||||
RtlAnsiStringToUnicodeString (&FileNameU,
|
||||
&FileName,
|
||||
TRUE);
|
||||
else
|
||||
RtlOemStringToUnicodeString (&FileNameU,
|
||||
&FileName,
|
||||
TRUE);
|
||||
|
||||
IData = InternalFindFirstFile (FileNameU.Buffer);
|
||||
|
||||
RtlFreeUnicodeString (&FileNameU);
|
||||
|
||||
if (IData == NULL)
|
||||
{
|
||||
DPRINT("Failing request\n");
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
DPRINT("IData->pFileInfo->FileNameLength %d\n",
|
||||
IData->pFileInfo->FileNameLength);
|
||||
|
||||
/* copy data into WIN32_FIND_DATA structure */
|
||||
lpFindFileData->dwFileAttributes = IData->pFileInfo->FileAttributes;
|
||||
|
||||
lpFindFileData->ftCreationTime.dwHighDateTime = IData->pFileInfo->CreationTime.u.HighPart;
|
||||
lpFindFileData->ftCreationTime.dwLowDateTime = IData->pFileInfo->CreationTime.u.LowPart;
|
||||
|
||||
lpFindFileData->ftLastAccessTime.dwHighDateTime = IData->pFileInfo->LastAccessTime.u.HighPart;
|
||||
lpFindFileData->ftLastAccessTime.dwLowDateTime = IData->pFileInfo->LastAccessTime.u.LowPart;
|
||||
|
||||
lpFindFileData->ftLastWriteTime.dwHighDateTime = IData->pFileInfo->LastWriteTime.u.HighPart;
|
||||
lpFindFileData->ftLastWriteTime.dwLowDateTime = IData->pFileInfo->LastWriteTime.u.LowPart;
|
||||
|
||||
lpFindFileData->nFileSizeHigh = IData->pFileInfo->EndOfFile.u.HighPart;
|
||||
lpFindFileData->nFileSizeLow = IData->pFileInfo->EndOfFile.u.LowPart;
|
||||
|
||||
FileNameU.Length = IData->pFileInfo->FileNameLength;
|
||||
FileNameU.MaximumLength = FileNameU.Length + sizeof(WCHAR);
|
||||
FileNameU.Buffer = IData->pFileInfo->FileName;
|
||||
|
||||
FileName.Length = 0;
|
||||
FileName.MaximumLength = MAX_PATH;
|
||||
FileName.Buffer = lpFindFileData->cFileName;
|
||||
|
||||
/* convert unicode string to ansi (or oem) */
|
||||
if (bIsFileApiAnsi)
|
||||
RtlUnicodeStringToAnsiString (&FileName,
|
||||
&FileNameU,
|
||||
FALSE);
|
||||
else
|
||||
RtlUnicodeStringToOemString (&FileName,
|
||||
&FileNameU,
|
||||
FALSE);
|
||||
|
||||
DPRINT("IData->pFileInfo->ShortNameLength %d\n",
|
||||
IData->pFileInfo->ShortNameLength);
|
||||
|
||||
FileNameU.Length = IData->pFileInfo->ShortNameLength;
|
||||
FileNameU.MaximumLength = FileNameU.Length + sizeof(WCHAR);
|
||||
FileNameU.Buffer = IData->pFileInfo->ShortName;
|
||||
|
||||
FileName.Length = 0;
|
||||
FileName.MaximumLength = 14;
|
||||
FileName.Buffer = lpFindFileData->cAlternateFileName;
|
||||
|
||||
/* convert unicode string to ansi (or oem) */
|
||||
if (bIsFileApiAnsi)
|
||||
RtlUnicodeStringToAnsiString (&FileName,
|
||||
&FileNameU,
|
||||
FALSE);
|
||||
else
|
||||
RtlUnicodeStringToOemString (&FileName,
|
||||
&FileNameU,
|
||||
FALSE);
|
||||
|
||||
return (HANDLE)IData;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
|
@ -518,6 +197,64 @@ FindClose (
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
HANDLE
|
||||
STDCALL
|
||||
FindFirstFileA (
|
||||
LPCSTR lpFileName,
|
||||
LPWIN32_FIND_DATAA lpFindFileData
|
||||
)
|
||||
{
|
||||
PKERNEL32_FIND_FILE_DATA IData;
|
||||
UNICODE_STRING FileNameU;
|
||||
ANSI_STRING FileName;
|
||||
WIN32_FIND_DATAW FindFileData;
|
||||
|
||||
RtlInitAnsiString (&FileName,
|
||||
(LPSTR)lpFileName);
|
||||
|
||||
/* convert ansi (or oem) string to unicode */
|
||||
if (bIsFileApiAnsi)
|
||||
RtlAnsiStringToUnicodeString (&FileNameU,
|
||||
&FileName,
|
||||
TRUE);
|
||||
else
|
||||
RtlOemStringToUnicodeString (&FileNameU,
|
||||
&FileName,
|
||||
TRUE);
|
||||
|
||||
IData = FindFirstFileExW(FileNameU.Buffer,
|
||||
FindExInfoStandard,
|
||||
&FindFileData,
|
||||
FindExSearchNameMatch,
|
||||
NULL,
|
||||
0);
|
||||
|
||||
RtlFreeUnicodeString(&FileNameU);
|
||||
|
||||
if(INVALID_HANDLE_VALUE != IData)
|
||||
{
|
||||
RtlInitUnicodeString(&FileNameU, (PWSTR)FindFileData.cFileName);
|
||||
FileName.Buffer = lpFindFileData->cFileName;
|
||||
FileName.MaximumLength = MAX_PATH;
|
||||
if (bIsFileApiAnsi) {
|
||||
RtlUnicodeStringToAnsiString (&FileName,
|
||||
&FileNameU,
|
||||
FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
RtlUnicodeStringToOemString (&FileName,
|
||||
&FileNameU,
|
||||
FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return (HANDLE)IData;
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
|
@ -529,39 +266,14 @@ FindFirstFileW (
|
|||
LPWIN32_FIND_DATAW lpFindFileData
|
||||
)
|
||||
{
|
||||
PKERNEL32_FIND_FILE_DATA IData;
|
||||
|
||||
IData = InternalFindFirstFile (lpFileName);
|
||||
if (IData == NULL)
|
||||
{
|
||||
DPRINT("Failing request\n");
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
/* copy data into WIN32_FIND_DATA structure */
|
||||
lpFindFileData->dwFileAttributes = IData->pFileInfo->FileAttributes;
|
||||
|
||||
lpFindFileData->ftCreationTime.dwHighDateTime = IData->pFileInfo->CreationTime.u.HighPart;
|
||||
lpFindFileData->ftCreationTime.dwLowDateTime = IData->pFileInfo->CreationTime.u.LowPart;
|
||||
|
||||
lpFindFileData->ftLastAccessTime.dwHighDateTime = IData->pFileInfo->LastAccessTime.u.HighPart;
|
||||
lpFindFileData->ftLastAccessTime.dwLowDateTime = IData->pFileInfo->LastAccessTime.u.LowPart;
|
||||
|
||||
lpFindFileData->ftLastWriteTime.dwHighDateTime = IData->pFileInfo->LastWriteTime.u.HighPart;
|
||||
lpFindFileData->ftLastWriteTime.dwLowDateTime = IData->pFileInfo->LastWriteTime.u.LowPart;
|
||||
|
||||
lpFindFileData->nFileSizeHigh = IData->pFileInfo->EndOfFile.u.HighPart;
|
||||
lpFindFileData->nFileSizeLow = IData->pFileInfo->EndOfFile.u.LowPart;
|
||||
|
||||
memcpy (lpFindFileData->cFileName,
|
||||
IData->pFileInfo->FileName,
|
||||
IData->pFileInfo->FileNameLength);
|
||||
lpFindFileData->cFileName[IData->pFileInfo->FileNameLength / sizeof(WCHAR)] = 0;
|
||||
memcpy (lpFindFileData->cAlternateFileName,
|
||||
IData->pFileInfo->ShortName,
|
||||
IData->pFileInfo->ShortNameLength);
|
||||
lpFindFileData->cAlternateFileName[IData->pFileInfo->ShortNameLength / sizeof(WCHAR)] = 0;
|
||||
return IData;
|
||||
return FindFirstFileExW(
|
||||
lpFileName,
|
||||
FindExInfoStandard,
|
||||
lpFindFileData,
|
||||
FindExSearchNameMatch,
|
||||
NULL,
|
||||
0
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
@ -609,7 +321,7 @@ FindNextFileW (
|
|||
lpFindFileData->nFileSizeHigh = IData->pFileInfo->EndOfFile.u.HighPart;
|
||||
lpFindFileData->nFileSizeLow = IData->pFileInfo->EndOfFile.u.LowPart;
|
||||
|
||||
memcpy (lpFindFileData->cFileName,
|
||||
memcpy (lpFindFileData->cFileName,
|
||||
IData->pFileInfo->FileName,
|
||||
IData->pFileInfo->FileNameLength);
|
||||
lpFindFileData->cFileName[IData->pFileInfo->FileNameLength / sizeof(WCHAR)] = 0;
|
||||
|
@ -622,40 +334,326 @@ FindNextFileW (
|
|||
|
||||
|
||||
/*
|
||||
* @unimplemented
|
||||
* @implemented
|
||||
*/
|
||||
HANDLE
|
||||
STDCALL
|
||||
FindFirstFileExW (
|
||||
LPCWSTR lpFileName,
|
||||
FINDEX_INFO_LEVELS fInfoLevelId,
|
||||
LPVOID lpFindFileData,
|
||||
FINDEX_SEARCH_OPS fSearchOp,
|
||||
LPVOID lpSearchFilter,
|
||||
DWORD dwAdditionalFlags
|
||||
LPCWSTR lpFileName,
|
||||
FINDEX_INFO_LEVELS fInfoLevelId,
|
||||
LPVOID lpFindFileData,
|
||||
FINDEX_SEARCH_OPS fSearchOp,
|
||||
LPVOID lpSearchFilter,
|
||||
DWORD dwAdditionalFlags
|
||||
)
|
||||
{
|
||||
/* FIXME */
|
||||
return (HANDLE) 0;
|
||||
PKERNEL32_FIND_FILE_DATA IData;
|
||||
IO_STATUS_BLOCK IoStatusBlock;
|
||||
NTSTATUS Status;
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
UNICODE_STRING DosFilePath;
|
||||
UNICODE_STRING NtName;
|
||||
UNICODE_STRING FileNameU;
|
||||
UNICODE_STRING NtFilePath;
|
||||
PWSTR e1, e2;
|
||||
WCHAR CurrentDir[256];
|
||||
PWCHAR SlashlessFileName;
|
||||
PWSTR SearchPath;
|
||||
PWCHAR SearchPattern;
|
||||
ULONG Length;
|
||||
|
||||
/*
|
||||
.....
|
||||
.....
|
||||
.....
|
||||
*/
|
||||
DPRINT("FindFirstFileExW(%S, %p, %p, %X, %p %d)\n",
|
||||
lpFileName,
|
||||
fInfoLevelId,
|
||||
lpFindFileData,
|
||||
fSearchOp,
|
||||
lpSearchFilter,
|
||||
dwAdditionalFlags);
|
||||
|
||||
RtlInitUnicodeString(&FileNameU, lpFileName);
|
||||
|
||||
Length = wcslen(lpFileName);
|
||||
if (L'\\' == lpFileName[Length - 1])
|
||||
{
|
||||
SlashlessFileName = RtlAllocateHeap(hProcessHeap, 0, Length * sizeof(WCHAR));
|
||||
if (NULL == SlashlessFileName)
|
||||
{
|
||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||
return (INVALID_HANDLE_VALUE);
|
||||
}
|
||||
memcpy(SlashlessFileName, lpFileName, (Length - 1) * sizeof(WCHAR));
|
||||
SlashlessFileName[Length - 1] = L'\0';
|
||||
lpFileName = SlashlessFileName;
|
||||
}
|
||||
else
|
||||
{
|
||||
SlashlessFileName = NULL;
|
||||
}
|
||||
|
||||
e1 = wcsrchr(lpFileName, L'/');
|
||||
e2 = wcsrchr(lpFileName, L'\\');
|
||||
SearchPattern = max(e1, e2);
|
||||
SearchPath = CurrentDir;
|
||||
|
||||
if (NULL == SearchPattern)
|
||||
{
|
||||
CHECKPOINT;
|
||||
SearchPattern = (PWCHAR)lpFileName;
|
||||
Length = GetCurrentDirectoryW(sizeof(CurrentDir) / sizeof(WCHAR), SearchPath);
|
||||
if (0 == Length)
|
||||
{
|
||||
if (NULL != SlashlessFileName) {
|
||||
RtlFreeHeap(hProcessHeap, 0, SlashlessFileName);
|
||||
}
|
||||
return (INVALID_HANDLE_VALUE);
|
||||
}
|
||||
if (Length > sizeof(CurrentDir) / sizeof(WCHAR))
|
||||
{
|
||||
SearchPath = RtlAllocateHeap(hProcessHeap, HEAP_ZERO_MEMORY, Length * sizeof(WCHAR));
|
||||
if (NULL == SearchPath)
|
||||
{
|
||||
if (NULL != SlashlessFileName) {
|
||||
RtlFreeHeap(hProcessHeap, 0, SlashlessFileName);
|
||||
}
|
||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||
return (INVALID_HANDLE_VALUE);
|
||||
}
|
||||
GetCurrentDirectoryW(Length, SearchPath);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CHECKPOINT;
|
||||
SearchPattern++;
|
||||
Length = SearchPattern - lpFileName;
|
||||
if (Length + 1 > sizeof(CurrentDir) / sizeof(WCHAR))
|
||||
{
|
||||
SearchPath = RtlAllocateHeap(hProcessHeap, HEAP_ZERO_MEMORY, (Length + 1) * sizeof(WCHAR));
|
||||
if (NULL == SearchPath) {
|
||||
if (NULL != SlashlessFileName) {
|
||||
RtlFreeHeap(hProcessHeap, 0, SlashlessFileName);
|
||||
}
|
||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||
return (INVALID_HANDLE_VALUE);
|
||||
}
|
||||
}
|
||||
memcpy(SearchPath, lpFileName, Length * sizeof(WCHAR));
|
||||
SearchPath[Length] = 0;
|
||||
}
|
||||
|
||||
if( FALSE == RtlDosPathNameToNtPathName_U(
|
||||
(PWSTR)SearchPath,
|
||||
&NtName,
|
||||
&DosFilePath.Buffer,
|
||||
(PCURDIR)&NtFilePath
|
||||
) )
|
||||
{
|
||||
RtlFreeHeap(hProcessHeap, 0, SearchPath);
|
||||
if (NULL != SlashlessFileName) {
|
||||
RtlFreeHeap(hProcessHeap, 0, SlashlessFileName);
|
||||
}
|
||||
SetLastError(ERROR_PATH_NOT_FOUND);
|
||||
return (INVALID_HANDLE_VALUE);
|
||||
}
|
||||
|
||||
|
||||
if (SearchPath != CurrentDir) {
|
||||
RtlFreeHeap(hProcessHeap, 0, SearchPath);
|
||||
}
|
||||
|
||||
DPRINT("NtName \'%S\'\n", NtName.Buffer);
|
||||
|
||||
IData = RtlAllocateHeap (hProcessHeap,
|
||||
HEAP_ZERO_MEMORY,
|
||||
sizeof(KERNEL32_FIND_FILE_DATA) + FIND_DATA_SIZE);
|
||||
if (NULL == IData)
|
||||
{
|
||||
RtlFreeHeap (hProcessHeap, 0, NtName.Buffer);
|
||||
if (NULL != SlashlessFileName) {
|
||||
RtlFreeHeap(hProcessHeap, 0, SlashlessFileName);
|
||||
}
|
||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||
return (INVALID_HANDLE_VALUE);
|
||||
}
|
||||
|
||||
/* change pattern: "*.*" --> "*" */
|
||||
if (!wcscmp (SearchPattern, L"*.*")) {
|
||||
RtlInitUnicodeString(&DosFilePath, L"*");
|
||||
} else {
|
||||
RtlInitUnicodeString(&DosFilePath, SearchPattern);
|
||||
}
|
||||
|
||||
DPRINT("NtName \'%S\' DosFilePath \'%S\'\n",
|
||||
NtName.Buffer, DosFilePath.Buffer);
|
||||
|
||||
InitializeObjectAttributes( &ObjectAttributes,
|
||||
&NtName,
|
||||
dwAdditionalFlags,
|
||||
NtFilePath.Buffer,
|
||||
NULL );
|
||||
|
||||
Status =
|
||||
NtOpenFile(
|
||||
&IData->DirectoryHandle,
|
||||
SYNCHRONIZE | FILE_LIST_DIRECTORY,
|
||||
&ObjectAttributes,
|
||||
&IoStatusBlock,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
FILE_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT | FILE_SYNCHRONOUS_IO_NONALERT
|
||||
);
|
||||
|
||||
if( !NT_SUCCESS(Status) )
|
||||
{
|
||||
DPRINT1("NtOpenFile() - failed (Status %lx)\n", Status);
|
||||
SetLastError( Status );
|
||||
return (INVALID_HANDLE_VALUE);
|
||||
}
|
||||
|
||||
RtlFreeHeap(hProcessHeap, 0, NtName.Buffer);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
RtlFreeHeap (hProcessHeap, 0, IData);
|
||||
if (NULL != SlashlessFileName) {
|
||||
RtlFreeHeap(hProcessHeap, 0, SlashlessFileName);
|
||||
}
|
||||
SetLastErrorByStatus (Status);
|
||||
return (INVALID_HANDLE_VALUE);
|
||||
}
|
||||
|
||||
if ( 0 == DosFilePath.Length ) {
|
||||
DPRINT1("0 == DosFilePath.Length\n");
|
||||
NtClose(IData->DirectoryHandle);
|
||||
SetLastError(ERROR_FILE_NOT_FOUND);
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
IData->pFileInfo = (PVOID)((ULONG_PTR)IData + sizeof(KERNEL32_FIND_FILE_DATA));
|
||||
IData->pFileInfo->FileIndex = 0;
|
||||
|
||||
Status =
|
||||
NtQueryDirectoryFile(
|
||||
IData->DirectoryHandle,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
&IoStatusBlock,
|
||||
(PVOID)IData->pFileInfo,
|
||||
FIND_DATA_SIZE,
|
||||
FileBothDirectoryInformation,
|
||||
TRUE,
|
||||
&DosFilePath,
|
||||
FALSE
|
||||
);
|
||||
|
||||
if (NULL != SlashlessFileName) {
|
||||
RtlFreeHeap(hProcessHeap, 0, SlashlessFileName);
|
||||
}
|
||||
|
||||
if( !NT_SUCCESS(Status) ) {
|
||||
DPRINT1("NtQueryDirectoryFile() - failed (Status %lx)\n", Status);
|
||||
RtlFreeHeap(hProcessHeap, 0, IData);
|
||||
NtClose(IData->DirectoryHandle);
|
||||
SetLastError(Status);
|
||||
return (INVALID_HANDLE_VALUE);
|
||||
}
|
||||
|
||||
DPRINT("Found %.*S\n",IData->pFileInfo->FileNameLength/sizeof(WCHAR), IData->pFileInfo->FileName);
|
||||
|
||||
/* copy data into WIN32_FIND_DATA structure */
|
||||
((LPWIN32_FIND_DATAW)lpFindFileData)->dwFileAttributes = IData->pFileInfo->FileAttributes;
|
||||
|
||||
((LPWIN32_FIND_DATAW)lpFindFileData)->ftCreationTime.dwHighDateTime = IData->pFileInfo->CreationTime.u.HighPart;
|
||||
((LPWIN32_FIND_DATAW)lpFindFileData)->ftCreationTime.dwLowDateTime = IData->pFileInfo->CreationTime.u.LowPart;
|
||||
|
||||
((LPWIN32_FIND_DATAW)lpFindFileData)->ftLastAccessTime.dwHighDateTime = IData->pFileInfo->LastAccessTime.u.HighPart;
|
||||
((LPWIN32_FIND_DATAW)lpFindFileData)->ftLastAccessTime.dwLowDateTime = IData->pFileInfo->LastAccessTime.u.LowPart;
|
||||
|
||||
((LPWIN32_FIND_DATAW)lpFindFileData)->ftLastWriteTime.dwHighDateTime = IData->pFileInfo->LastWriteTime.u.HighPart;
|
||||
((LPWIN32_FIND_DATAW)lpFindFileData)->ftLastWriteTime.dwLowDateTime = IData->pFileInfo->LastWriteTime.u.LowPart;
|
||||
|
||||
((LPWIN32_FIND_DATAW)lpFindFileData)->nFileSizeHigh = IData->pFileInfo->EndOfFile.u.HighPart;
|
||||
((LPWIN32_FIND_DATAW)lpFindFileData)->nFileSizeLow = IData->pFileInfo->EndOfFile.u.LowPart;
|
||||
|
||||
memcpy (((LPWIN32_FIND_DATAW)lpFindFileData)->cFileName,
|
||||
IData->pFileInfo->FileName,
|
||||
IData->pFileInfo->FileNameLength);
|
||||
((LPWIN32_FIND_DATAW)lpFindFileData)->cFileName[IData->pFileInfo->FileNameLength / sizeof(WCHAR)] = 0;
|
||||
memcpy (((LPWIN32_FIND_DATAW)lpFindFileData)->cAlternateFileName,
|
||||
IData->pFileInfo->ShortName,
|
||||
IData->pFileInfo->ShortNameLength);
|
||||
((LPWIN32_FIND_DATAW)lpFindFileData)->cAlternateFileName[IData->pFileInfo->ShortNameLength / sizeof(WCHAR)] = 0;
|
||||
|
||||
|
||||
return (HANDLE)IData;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @unimplemented
|
||||
* @implemented
|
||||
*/
|
||||
HANDLE
|
||||
STDCALL
|
||||
FindFirstFileExA (
|
||||
LPCSTR lpFileName,
|
||||
FINDEX_INFO_LEVELS fInfoLevelId,
|
||||
LPVOID lpFindFileData,
|
||||
FINDEX_SEARCH_OPS fSearchOp,
|
||||
LPVOID lpSearchFilter,
|
||||
DWORD dwAdditionalFlags
|
||||
LPCSTR lpFileName,
|
||||
FINDEX_INFO_LEVELS fInfoLevelId,
|
||||
LPVOID lpFindFileData,
|
||||
FINDEX_SEARCH_OPS fSearchOp,
|
||||
LPVOID lpSearchFilter,
|
||||
DWORD dwAdditionalFlags
|
||||
)
|
||||
{
|
||||
/* FIXME */
|
||||
return (HANDLE) 0;
|
||||
PKERNEL32_FIND_FILE_DATA IData;
|
||||
UNICODE_STRING FileNameU;
|
||||
ANSI_STRING FileNameA;
|
||||
|
||||
RtlInitAnsiString (&FileNameA,
|
||||
(LPSTR)lpFileName);
|
||||
|
||||
/* convert ansi (or oem) string to unicode */
|
||||
if (bIsFileApiAnsi)
|
||||
RtlAnsiStringToUnicodeString (&FileNameU,
|
||||
&FileNameA,
|
||||
TRUE);
|
||||
else
|
||||
RtlOemStringToUnicodeString (&FileNameU,
|
||||
&FileNameA,
|
||||
TRUE);
|
||||
|
||||
IData = FindFirstFileExW(
|
||||
(LPCWSTR)FileNameU.Buffer,
|
||||
fInfoLevelId,
|
||||
lpFindFileData,
|
||||
fSearchOp,
|
||||
lpSearchFilter,
|
||||
dwAdditionalFlags
|
||||
);
|
||||
|
||||
RtlFreeUnicodeString(&FileNameU);
|
||||
|
||||
if(INVALID_HANDLE_VALUE != IData)
|
||||
{
|
||||
RtlInitUnicodeString(&FileNameU, (PWSTR)((LPWIN32_FIND_DATAW)lpFindFileData)->cFileName);
|
||||
FileNameU.Buffer = ((LPWIN32_FIND_DATAW)lpFindFileData)->cFileName;
|
||||
FileNameU.MaximumLength = MAX_PATH;
|
||||
|
||||
/* convert unicode string to ansi (or oem) */
|
||||
if (bIsFileApiAnsi)
|
||||
RtlUnicodeStringToAnsiString (&FileNameA,
|
||||
&FileNameU,
|
||||
FALSE);
|
||||
else
|
||||
RtlUnicodeStringToOemString (&FileNameA,
|
||||
&FileNameU,
|
||||
FALSE);
|
||||
}
|
||||
|
||||
return (HANDLE)IData;
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue