mirror of
https://github.com/reactos/reactos.git
synced 2025-02-24 17:34:57 +00:00
Rewrite parts of FindFirstFileEx to:
- Fix searches relative to the current directory using the features RtlDosPathNameToNtPathName_U provides instead of hacking around them - Enable searches for fake DOS devices. Some installers like NSIS use this feature to determine if a drive exists, this works now. svn path=/trunk/; revision=27634
This commit is contained in:
parent
5bce20b1be
commit
532f7fecc5
1 changed files with 231 additions and 174 deletions
|
@ -21,6 +21,8 @@
|
||||||
|
|
||||||
#define FIND_DATA_SIZE (16*1024)
|
#define FIND_DATA_SIZE (16*1024)
|
||||||
|
|
||||||
|
#define FIND_DEVICE_HANDLE ((HANDLE)0x1)
|
||||||
|
|
||||||
typedef struct _KERNEL32_FIND_FILE_DATA
|
typedef struct _KERNEL32_FIND_FILE_DATA
|
||||||
{
|
{
|
||||||
HANDLE DirectoryHandle;
|
HANDLE DirectoryHandle;
|
||||||
|
@ -49,6 +51,61 @@ typedef struct _KERNEL32_FIND_DATA_HEADER
|
||||||
|
|
||||||
/* FUNCTIONS ****************************************************************/
|
/* FUNCTIONS ****************************************************************/
|
||||||
|
|
||||||
|
HANDLE
|
||||||
|
InternalCopyDeviceFindDataW(LPWIN32_FIND_DATAW lpFindFileData,
|
||||||
|
LPCWSTR lpFileName,
|
||||||
|
ULONG DeviceNameInfo)
|
||||||
|
{
|
||||||
|
UNICODE_STRING DeviceName;
|
||||||
|
|
||||||
|
DeviceName.Length = DeviceName.MaximumLength = (USHORT)(DeviceNameInfo & 0xFFFF);
|
||||||
|
DeviceName.Buffer = (LPWSTR)((ULONG_PTR)lpFileName + (DeviceNameInfo >> 16));
|
||||||
|
|
||||||
|
/* Return the data */
|
||||||
|
RtlZeroMemory(lpFindFileData,
|
||||||
|
sizeof(*lpFindFileData));
|
||||||
|
lpFindFileData->dwFileAttributes = FILE_ATTRIBUTE_ARCHIVE;
|
||||||
|
RtlCopyMemory(lpFindFileData->cFileName,
|
||||||
|
DeviceName.Buffer,
|
||||||
|
DeviceName.Length);
|
||||||
|
|
||||||
|
return FIND_DEVICE_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
HANDLE
|
||||||
|
InternalCopyDeviceFindDataA(LPWIN32_FIND_DATAA lpFindFileData,
|
||||||
|
PUNICODE_STRING FileName,
|
||||||
|
ULONG DeviceNameInfo)
|
||||||
|
{
|
||||||
|
UNICODE_STRING DeviceName;
|
||||||
|
ANSI_STRING BufferA;
|
||||||
|
CHAR Buffer[MAX_PATH];
|
||||||
|
|
||||||
|
DeviceName.Length = DeviceName.MaximumLength = (USHORT)(DeviceNameInfo & 0xFFFF);
|
||||||
|
DeviceName.Buffer = (LPWSTR)((ULONG_PTR)FileName->Buffer + (DeviceNameInfo >> 16));
|
||||||
|
|
||||||
|
BufferA.MaximumLength = sizeof(Buffer) - sizeof(Buffer[0]);
|
||||||
|
BufferA.Buffer = Buffer;
|
||||||
|
if (bIsFileApiAnsi)
|
||||||
|
RtlUnicodeStringToAnsiString (&BufferA, &DeviceName, FALSE);
|
||||||
|
else
|
||||||
|
RtlUnicodeStringToOemString (&BufferA, &DeviceName, FALSE);
|
||||||
|
|
||||||
|
/* NOTE: Free the string before we try to write the results to the caller,
|
||||||
|
this way we prevent a memory leak in case of a fault... */
|
||||||
|
RtlFreeUnicodeString(FileName);
|
||||||
|
|
||||||
|
/* Return the data */
|
||||||
|
RtlZeroMemory(lpFindFileData,
|
||||||
|
sizeof(*lpFindFileData));
|
||||||
|
lpFindFileData->dwFileAttributes = FILE_ATTRIBUTE_ARCHIVE;
|
||||||
|
RtlCopyMemory(lpFindFileData->cFileName,
|
||||||
|
BufferA.Buffer,
|
||||||
|
BufferA.Length);
|
||||||
|
|
||||||
|
return FIND_DEVICE_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
InternalCopyFindDataW(LPWIN32_FIND_DATAW lpFindFileData,
|
InternalCopyFindDataW(LPWIN32_FIND_DATAW lpFindFileData,
|
||||||
PFILE_BOTH_DIR_INFORMATION lpFileInfo)
|
PFILE_BOTH_DIR_INFORMATION lpFileInfo)
|
||||||
|
@ -143,6 +200,12 @@ InternalFindNextFile (
|
||||||
|
|
||||||
DPRINT("InternalFindNextFile(%lx)\n", hFindFile);
|
DPRINT("InternalFindNextFile(%lx)\n", hFindFile);
|
||||||
|
|
||||||
|
if (hFindFile == FIND_DEVICE_HANDLE)
|
||||||
|
{
|
||||||
|
SetLastError (ERROR_NO_MORE_FILES);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
IHeader = (PKERNEL32_FIND_DATA_HEADER)hFindFile;
|
IHeader = (PKERNEL32_FIND_DATA_HEADER)hFindFile;
|
||||||
if (hFindFile == NULL || hFindFile == INVALID_HANDLE_VALUE ||
|
if (hFindFile == NULL || hFindFile == INVALID_HANDLE_VALUE ||
|
||||||
IHeader->Type != FileFind)
|
IHeader->Type != FileFind)
|
||||||
|
@ -197,135 +260,140 @@ HANDLE
|
||||||
STDCALL
|
STDCALL
|
||||||
InternalFindFirstFile (
|
InternalFindFirstFile (
|
||||||
LPCWSTR lpFileName,
|
LPCWSTR lpFileName,
|
||||||
BOOLEAN DirectoryOnly
|
BOOLEAN DirectoryOnly,
|
||||||
|
PULONG DeviceNameInfo
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||||
PKERNEL32_FIND_DATA_HEADER IHeader;
|
PKERNEL32_FIND_DATA_HEADER IHeader;
|
||||||
PKERNEL32_FIND_FILE_DATA IData;
|
PKERNEL32_FIND_FILE_DATA IData;
|
||||||
IO_STATUS_BLOCK IoStatusBlock;
|
IO_STATUS_BLOCK IoStatusBlock;
|
||||||
UNICODE_STRING NtPathU;
|
UNICODE_STRING NtPathU, FileName, PathFileName;
|
||||||
UNICODE_STRING PatternStr = RTL_CONSTANT_STRING(L"*");
|
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
PWSTR e1, e2;
|
PWSTR NtPathBuffer;
|
||||||
WCHAR CurrentDir[256];
|
BOOLEAN RemovedSlash = FALSE;
|
||||||
PWCHAR SlashlessFileName;
|
|
||||||
PWSTR SearchPath;
|
|
||||||
PWCHAR SearchPattern;
|
|
||||||
ULONG Length;
|
|
||||||
BOOL bResult;
|
BOOL bResult;
|
||||||
|
CURDIR DirInfo;
|
||||||
|
HANDLE hDirectory = NULL;
|
||||||
|
|
||||||
DPRINT("FindFirstFileW(lpFileName %S)\n",
|
DPRINT("FindFirstFileW(lpFileName %S)\n",
|
||||||
lpFileName);
|
lpFileName);
|
||||||
|
|
||||||
Length = wcslen(lpFileName);
|
*DeviceNameInfo = 0;
|
||||||
if (L'\\' == lpFileName[Length - 1])
|
RtlZeroMemory(&PathFileName,
|
||||||
{
|
sizeof(PathFileName));
|
||||||
SlashlessFileName = RtlAllocateHeap(hProcessHeap,
|
RtlInitUnicodeString(&FileName,
|
||||||
0,
|
lpFileName);
|
||||||
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'/');
|
bResult = RtlDosPathNameToNtPathName_U (lpFileName,
|
||||||
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 (SearchPath,
|
|
||||||
&NtPathU,
|
&NtPathU,
|
||||||
NULL,
|
(PCWSTR *)((ULONG_PTR)&PathFileName.Buffer),
|
||||||
NULL);
|
&DirInfo);
|
||||||
if (SearchPath != CurrentDir)
|
|
||||||
{
|
|
||||||
RtlFreeHeap(hProcessHeap,
|
|
||||||
0,
|
|
||||||
SearchPath);
|
|
||||||
}
|
|
||||||
if (FALSE == bResult)
|
if (FALSE == bResult)
|
||||||
{
|
{
|
||||||
if (NULL != SlashlessFileName)
|
SetLastError(ERROR_PATH_NOT_FOUND);
|
||||||
{
|
|
||||||
RtlFreeHeap(hProcessHeap,
|
|
||||||
0,
|
|
||||||
SlashlessFileName);
|
|
||||||
}
|
|
||||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
DPRINT("NtPathU \'%S\'\n", NtPathU.Buffer);
|
/* Save the buffer pointer for later, we need to free it! */
|
||||||
|
NtPathBuffer = NtPathU.Buffer;
|
||||||
|
|
||||||
|
/* If there is a file name/pattern then determine it's length */
|
||||||
|
if (PathFileName.Buffer != NULL)
|
||||||
|
{
|
||||||
|
PathFileName.Length = NtPathU.Length -
|
||||||
|
(USHORT)((ULONG_PTR)PathFileName.Buffer - (ULONG_PTR)NtPathU.Buffer);
|
||||||
|
}
|
||||||
|
PathFileName.MaximumLength = PathFileName.Length;
|
||||||
|
|
||||||
|
if (DirInfo.DosPath.Length != 0 && DirInfo.DosPath.Buffer != PathFileName.Buffer)
|
||||||
|
{
|
||||||
|
if (PathFileName.Buffer != NULL)
|
||||||
|
{
|
||||||
|
/* This is a relative path to DirInfo.Handle, adjust NtPathU! */
|
||||||
|
NtPathU.Length = NtPathU.MaximumLength =
|
||||||
|
(USHORT)((ULONG_PTR)PathFileName.Buffer - (ULONG_PTR)DirInfo.DosPath.Buffer);
|
||||||
|
NtPathU.Buffer = DirInfo.DosPath.Buffer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* This is an absolute path, NtPathU receives the full path */
|
||||||
|
DirInfo.Handle = NULL;
|
||||||
|
if (PathFileName.Buffer != NULL)
|
||||||
|
{
|
||||||
|
NtPathU.Length = NtPathU.MaximumLength =
|
||||||
|
(USHORT)((ULONG_PTR)PathFileName.Buffer - (ULONG_PTR)NtPathU.Buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remove a trailing backslash from the path, unless it's a DOS drive directly */
|
||||||
|
if (NtPathU.Length > 3 * sizeof(WCHAR) &&
|
||||||
|
NtPathU.Buffer[(NtPathU.Length / sizeof(WCHAR)) - 2] != L':' &&
|
||||||
|
NtPathU.Buffer[(NtPathU.Length / sizeof(WCHAR)) - 1] != L'\\')
|
||||||
|
{
|
||||||
|
NtPathU.Length -= sizeof(WCHAR);
|
||||||
|
RemovedSlash = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINT("lpFileName: \"%ws\"\n", lpFileName);
|
||||||
|
DPRINT("NtPathU: \"%wZ\"\n", &NtPathU);
|
||||||
|
DPRINT("PathFileName: \"%wZ\"\n", &PathFileName);
|
||||||
|
DPRINT("RelativeTo: 0x%p\n", DirInfo.Handle);
|
||||||
|
|
||||||
|
InitializeObjectAttributes (&ObjectAttributes,
|
||||||
|
&NtPathU,
|
||||||
|
OBJ_CASE_INSENSITIVE,
|
||||||
|
DirInfo.Handle,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
Status = NtOpenFile (&hDirectory,
|
||||||
|
FILE_LIST_DIRECTORY,
|
||||||
|
&ObjectAttributes,
|
||||||
|
&IoStatusBlock,
|
||||||
|
FILE_SHARE_READ|FILE_SHARE_WRITE,
|
||||||
|
FILE_DIRECTORY_FILE);
|
||||||
|
|
||||||
|
if (!NT_SUCCESS(Status) && RemovedSlash)
|
||||||
|
{
|
||||||
|
/* Try again, this time with the trailing slash... */
|
||||||
|
NtPathU.Length -= sizeof(WCHAR);
|
||||||
|
|
||||||
|
Status = NtOpenFile (&hDirectory,
|
||||||
|
FILE_LIST_DIRECTORY,
|
||||||
|
&ObjectAttributes,
|
||||||
|
&IoStatusBlock,
|
||||||
|
FILE_SHARE_READ|FILE_SHARE_WRITE,
|
||||||
|
FILE_DIRECTORY_FILE);
|
||||||
|
|
||||||
|
NtPathU.Length -= sizeof(WCHAR);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
RtlFreeHeap (hProcessHeap,
|
||||||
|
0,
|
||||||
|
NtPathBuffer);
|
||||||
|
|
||||||
|
/* See if the application tries to look for a DOS device */
|
||||||
|
*DeviceNameInfo = RtlIsDosDeviceName_U((PWSTR)((ULONG_PTR)lpFileName));
|
||||||
|
if (*DeviceNameInfo != 0)
|
||||||
|
return FIND_DEVICE_HANDLE;
|
||||||
|
|
||||||
|
SetLastErrorByStatus (Status);
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PathFileName.Length == 0)
|
||||||
|
{
|
||||||
|
/* No file part?! */
|
||||||
|
NtClose(hDirectory);
|
||||||
|
RtlFreeHeap (hProcessHeap,
|
||||||
|
0,
|
||||||
|
NtPathBuffer);
|
||||||
|
SetLastError(ERROR_FILE_NOT_FOUND);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
IHeader = RtlAllocateHeap (hProcessHeap,
|
IHeader = RtlAllocateHeap (hProcessHeap,
|
||||||
HEAP_ZERO_MEMORY,
|
HEAP_ZERO_MEMORY,
|
||||||
|
@ -335,69 +403,35 @@ InternalFindFirstFile (
|
||||||
{
|
{
|
||||||
RtlFreeHeap (hProcessHeap,
|
RtlFreeHeap (hProcessHeap,
|
||||||
0,
|
0,
|
||||||
NtPathU.Buffer);
|
NtPathBuffer);
|
||||||
if (NULL != SlashlessFileName)
|
NtClose(hDirectory);
|
||||||
{
|
|
||||||
RtlFreeHeap(hProcessHeap,
|
|
||||||
0,
|
|
||||||
SlashlessFileName);
|
|
||||||
}
|
|
||||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
IHeader->Type = FileFind;
|
IHeader->Type = FileFind;
|
||||||
IData = (PKERNEL32_FIND_FILE_DATA)(IHeader + 1);
|
IData = (PKERNEL32_FIND_FILE_DATA)(IHeader + 1);
|
||||||
|
IData->DirectoryHandle = hDirectory;
|
||||||
|
|
||||||
/* change pattern: "*.*" --> "*" */
|
/* change pattern: "*.*" --> "*" */
|
||||||
if (wcscmp (SearchPattern, L"*.*"))
|
if (PathFileName.Length == 6 &&
|
||||||
|
RtlCompareMemory(PathFileName.Buffer,
|
||||||
|
L"*.*",
|
||||||
|
6) == 6)
|
||||||
{
|
{
|
||||||
RtlInitUnicodeString(&PatternStr, SearchPattern);
|
PathFileName.Length = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
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, IHeader);
|
|
||||||
if (NULL != SlashlessFileName)
|
|
||||||
{
|
|
||||||
RtlFreeHeap(hProcessHeap,
|
|
||||||
0,
|
|
||||||
SlashlessFileName);
|
|
||||||
}
|
|
||||||
SetLastErrorByStatus (Status);
|
|
||||||
return(NULL);
|
|
||||||
}
|
|
||||||
IData->pFileInfo = (PVOID)((ULONG_PTR)IData + sizeof(KERNEL32_FIND_FILE_DATA));
|
IData->pFileInfo = (PVOID)((ULONG_PTR)IData + sizeof(KERNEL32_FIND_FILE_DATA));
|
||||||
IData->pFileInfo->FileIndex = 0;
|
IData->pFileInfo->FileIndex = 0;
|
||||||
IData->DirectoryOnly = DirectoryOnly;
|
IData->DirectoryOnly = DirectoryOnly;
|
||||||
|
|
||||||
bResult = InternalFindNextFile((HANDLE)IHeader, &PatternStr);
|
bResult = InternalFindNextFile((HANDLE)IHeader, &PathFileName);
|
||||||
if (NULL != SlashlessFileName)
|
|
||||||
{
|
|
||||||
RtlFreeHeap (hProcessHeap,
|
RtlFreeHeap (hProcessHeap,
|
||||||
0,
|
0,
|
||||||
SlashlessFileName);
|
NtPathBuffer);
|
||||||
}
|
|
||||||
|
|
||||||
if (!bResult)
|
if (!bResult)
|
||||||
{
|
{
|
||||||
|
@ -423,6 +457,7 @@ FindFirstFileA (
|
||||||
PKERNEL32_FIND_FILE_DATA IData;
|
PKERNEL32_FIND_FILE_DATA IData;
|
||||||
UNICODE_STRING FileNameU;
|
UNICODE_STRING FileNameU;
|
||||||
ANSI_STRING FileName;
|
ANSI_STRING FileName;
|
||||||
|
ULONG DeviceNameInfo;
|
||||||
|
|
||||||
RtlInitAnsiString (&FileName,
|
RtlInitAnsiString (&FileName,
|
||||||
(LPSTR)lpFileName);
|
(LPSTR)lpFileName);
|
||||||
|
@ -437,16 +472,23 @@ FindFirstFileA (
|
||||||
&FileName,
|
&FileName,
|
||||||
TRUE);
|
TRUE);
|
||||||
|
|
||||||
IHeader = InternalFindFirstFile (FileNameU.Buffer, FALSE);
|
IHeader = InternalFindFirstFile (FileNameU.Buffer, FALSE, &DeviceNameInfo);
|
||||||
|
|
||||||
RtlFreeUnicodeString (&FileNameU);
|
|
||||||
|
|
||||||
if (IHeader == NULL)
|
if (IHeader == NULL)
|
||||||
{
|
{
|
||||||
|
RtlFreeUnicodeString (&FileNameU);
|
||||||
DPRINT("Failing request\n");
|
DPRINT("Failing request\n");
|
||||||
return INVALID_HANDLE_VALUE;
|
return INVALID_HANDLE_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((HANDLE)IHeader == FIND_DEVICE_HANDLE)
|
||||||
|
{
|
||||||
|
/* NOTE: FileNameU will be freed in InternalCopyDeviceFindDataA */
|
||||||
|
return InternalCopyDeviceFindDataA(lpFindFileData, &FileNameU, DeviceNameInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
RtlFreeUnicodeString (&FileNameU);
|
||||||
|
|
||||||
IData = (PKERNEL32_FIND_FILE_DATA)(IHeader + 1);
|
IData = (PKERNEL32_FIND_FILE_DATA)(IHeader + 1);
|
||||||
|
|
||||||
DPRINT("IData->pFileInfo->FileNameLength %d\n",
|
DPRINT("IData->pFileInfo->FileNameLength %d\n",
|
||||||
|
@ -502,6 +544,9 @@ FindClose (
|
||||||
|
|
||||||
DPRINT("FindClose(hFindFile %x)\n",hFindFile);
|
DPRINT("FindClose(hFindFile %x)\n",hFindFile);
|
||||||
|
|
||||||
|
if (hFindFile == FIND_DEVICE_HANDLE)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
if (!hFindFile || hFindFile == INVALID_HANDLE_VALUE)
|
if (!hFindFile || hFindFile == INVALID_HANDLE_VALUE)
|
||||||
{
|
{
|
||||||
SetLastError (ERROR_INVALID_HANDLE);
|
SetLastError (ERROR_INVALID_HANDLE);
|
||||||
|
@ -600,6 +645,7 @@ FindFirstFileExW (LPCWSTR lpFileName,
|
||||||
{
|
{
|
||||||
PKERNEL32_FIND_DATA_HEADER IHeader;
|
PKERNEL32_FIND_DATA_HEADER IHeader;
|
||||||
PKERNEL32_FIND_FILE_DATA IData;
|
PKERNEL32_FIND_FILE_DATA IData;
|
||||||
|
ULONG DeviceNameInfo;
|
||||||
|
|
||||||
if (fInfoLevelId != FindExInfoStandard)
|
if (fInfoLevelId != FindExInfoStandard)
|
||||||
{
|
{
|
||||||
|
@ -614,13 +660,16 @@ FindFirstFileExW (LPCWSTR lpFileName,
|
||||||
return INVALID_HANDLE_VALUE;
|
return INVALID_HANDLE_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
IHeader = InternalFindFirstFile (lpFileName, fSearchOp == FindExSearchLimitToDirectories ? TRUE : FALSE);
|
IHeader = InternalFindFirstFile (lpFileName, fSearchOp == FindExSearchLimitToDirectories ? TRUE : FALSE, &DeviceNameInfo);
|
||||||
if (IHeader == NULL)
|
if (IHeader == NULL)
|
||||||
{
|
{
|
||||||
DPRINT("Failing request\n");
|
DPRINT("Failing request\n");
|
||||||
return INVALID_HANDLE_VALUE;
|
return INVALID_HANDLE_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((HANDLE)IHeader == FIND_DEVICE_HANDLE)
|
||||||
|
return InternalCopyDeviceFindDataW((LPWIN32_FIND_DATAW)lpFindFileData, lpFileName, DeviceNameInfo);
|
||||||
|
|
||||||
IData = (PKERNEL32_FIND_FILE_DATA)(IHeader + 1);
|
IData = (PKERNEL32_FIND_FILE_DATA)(IHeader + 1);
|
||||||
|
|
||||||
/* copy data into WIN32_FIND_DATA structure */
|
/* copy data into WIN32_FIND_DATA structure */
|
||||||
|
@ -650,6 +699,7 @@ FindFirstFileExA (
|
||||||
PKERNEL32_FIND_FILE_DATA IData;
|
PKERNEL32_FIND_FILE_DATA IData;
|
||||||
UNICODE_STRING FileNameU;
|
UNICODE_STRING FileNameU;
|
||||||
ANSI_STRING FileNameA;
|
ANSI_STRING FileNameA;
|
||||||
|
ULONG DeviceNameInfo;
|
||||||
|
|
||||||
if (fInfoLevelId != FindExInfoStandard)
|
if (fInfoLevelId != FindExInfoStandard)
|
||||||
{
|
{
|
||||||
|
@ -672,16 +722,23 @@ FindFirstFileExA (
|
||||||
else
|
else
|
||||||
RtlOemStringToUnicodeString (&FileNameU, &FileNameA, TRUE);
|
RtlOemStringToUnicodeString (&FileNameU, &FileNameA, TRUE);
|
||||||
|
|
||||||
IHeader = InternalFindFirstFile (FileNameU.Buffer, FALSE);
|
IHeader = InternalFindFirstFile (FileNameU.Buffer, FALSE, &DeviceNameInfo);
|
||||||
|
|
||||||
RtlFreeUnicodeString (&FileNameU);
|
|
||||||
|
|
||||||
if (IHeader == NULL)
|
if (IHeader == NULL)
|
||||||
{
|
{
|
||||||
|
RtlFreeUnicodeString (&FileNameU);
|
||||||
DPRINT("Failing request\n");
|
DPRINT("Failing request\n");
|
||||||
return INVALID_HANDLE_VALUE;
|
return INVALID_HANDLE_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((HANDLE)IHeader == FIND_DEVICE_HANDLE)
|
||||||
|
{
|
||||||
|
/* NOTE: FileNameU will be freed in InternalCopyDeviceFindDataA */
|
||||||
|
return InternalCopyDeviceFindDataA(lpFindFileData, &FileNameU, DeviceNameInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
RtlFreeUnicodeString (&FileNameU);
|
||||||
|
|
||||||
IData = (PKERNEL32_FIND_FILE_DATA)(IHeader + 1);
|
IData = (PKERNEL32_FIND_FILE_DATA)(IHeader + 1);
|
||||||
|
|
||||||
/* copy data into WIN32_FIND_DATA structure */
|
/* copy data into WIN32_FIND_DATA structure */
|
||||||
|
|
Loading…
Reference in a new issue