mirror of
https://github.com/reactos/reactos.git
synced 2025-07-05 03:11:21 +00:00
320 lines
8.6 KiB
C
320 lines
8.6 KiB
C
/*
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
* PROJECT: ReactOS system libraries
|
|
* FILE: lib/kernel32/file/find.c
|
|
* PURPOSE: Find functions
|
|
* PROGRAMMER: Ariadne ( ariadne@xs4all.nl)
|
|
* UPDATE HISTORY:
|
|
* Created 01/11/98
|
|
*/
|
|
|
|
/* INCLUDES *****************************************************************/
|
|
|
|
#include <windows.h>
|
|
#include <wchar.h>
|
|
#include <ddk/ntddk.h>
|
|
|
|
#define NDEBUG
|
|
#include <kernel32/kernel32.h>
|
|
|
|
/* TYPES ********************************************************************/
|
|
|
|
typedef struct _KERNEL32_FIND_FILE_DATA
|
|
{
|
|
HANDLE DirectoryHandle;
|
|
FILE_BOTH_DIRECTORY_INFORMATION FileInfo;
|
|
WCHAR FileNameExtra[MAX_PATH];
|
|
UNICODE_STRING PatternStr;
|
|
} KERNEL32_FIND_FILE_DATA, *PKERNEL32_FIND_FILE_DATA;
|
|
|
|
typedef struct _WIN32_FIND_DATA_UNICODE {
|
|
DWORD dwFileAttributes;
|
|
FILETIME ftCreationTime;
|
|
FILETIME ftLastAccessTime;
|
|
FILETIME ftLastWriteTime;
|
|
DWORD nFileSizeHigh;
|
|
DWORD nFileSizeLow;
|
|
DWORD dwReserved0;
|
|
DWORD dwReserved1;
|
|
WCHAR cFileName[ MAX_PATH ];
|
|
WCHAR cAlternateFileName[ 14 ];
|
|
} WIN32_FIND_DATA_UNICODE, *PWIN32_FIND_DATA_UNICODE;
|
|
|
|
typedef struct _WIN32_FIND_DATA_ASCII {
|
|
DWORD dwFileAttributes;
|
|
FILETIME ftCreationTime;
|
|
FILETIME ftLastAccessTime;
|
|
FILETIME ftLastWriteTime;
|
|
DWORD nFileSizeHigh;
|
|
DWORD nFileSizeLow;
|
|
DWORD dwReserved0;
|
|
DWORD dwReserved1;
|
|
CHAR cFileName[ MAX_PATH ];
|
|
CHAR cAlternateFileName[ 14 ];
|
|
} WIN32_FIND_DATA_ASCII, *PWIN32_FIND_DATA_ASCII;
|
|
|
|
/* FUNCTIONS ****************************************************************/
|
|
|
|
static void FileDataToWin32Data(LPWIN32_FIND_DATA lpFindFileData, PKERNEL32_FIND_FILE_DATA IData)
|
|
{
|
|
lpFindFileData->dwFileAttributes = IData->FileInfo.FileAttributes;
|
|
memcpy(&lpFindFileData->ftCreationTime,&IData->FileInfo.CreationTime,sizeof(FILETIME));
|
|
memcpy(&lpFindFileData->ftLastAccessTime,&IData->FileInfo.LastAccessTime,sizeof(FILETIME));
|
|
memcpy(&lpFindFileData->ftLastWriteTime,&IData->FileInfo.LastWriteTime,sizeof(FILETIME));
|
|
lpFindFileData->nFileSizeHigh = IData->FileInfo.EndOfFile.u.HighPart;
|
|
lpFindFileData->nFileSizeLow = IData->FileInfo.EndOfFile.u.LowPart;
|
|
}
|
|
|
|
WINBOOL STDCALL InternalFindNextFile(HANDLE hFindFile,
|
|
LPWIN32_FIND_DATA lpFindFileData)
|
|
{
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
NTSTATUS Status;
|
|
PKERNEL32_FIND_FILE_DATA IData;
|
|
|
|
IData = (PKERNEL32_FIND_FILE_DATA)hFindFile;
|
|
|
|
Status = NtQueryDirectoryFile(IData->DirectoryHandle,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&IoStatusBlock,
|
|
(PVOID)&IData->FileInfo,
|
|
sizeof(IData->FileInfo) +
|
|
sizeof(IData->FileNameExtra),
|
|
FileBothDirectoryInformation,
|
|
TRUE,
|
|
&(IData->PatternStr),
|
|
FALSE);
|
|
DPRINT("Found %w\n",IData->FileInfo.FileName);
|
|
if (Status != STATUS_SUCCESS)
|
|
{
|
|
return(FALSE);
|
|
}
|
|
|
|
FileDataToWin32Data(lpFindFileData, IData);
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
HANDLE STDCALL InternalFindFirstFile(LPCWSTR lpFileName,
|
|
LPWIN32_FIND_DATA lpFindFileData)
|
|
{
|
|
WCHAR CurrentDirectory[MAX_PATH];
|
|
WCHAR Pattern[MAX_PATH];
|
|
WCHAR Directory[MAX_PATH];
|
|
PWSTR End;
|
|
PKERNEL32_FIND_FILE_DATA IData;
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
UNICODE_STRING DirectoryNameStr;
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
|
|
DPRINT("FindFirstFileW(lpFileName %w, lpFindFileData %x)\n",
|
|
lpFileName, lpFindFileData);
|
|
|
|
GetFullPathNameW(lpFileName, MAX_PATH, CurrentDirectory, NULL);
|
|
Directory[0] = '\\';
|
|
Directory[1] = '?';
|
|
Directory[2] = '?';
|
|
Directory[3] = '\\';
|
|
Directory[4] = 0;
|
|
DPRINT("Directory %w\n",Directory);
|
|
wcscat(Directory, CurrentDirectory);
|
|
DPRINT("Directory %w\n",Directory);
|
|
End = wcsrchr(Directory, '\\');
|
|
*End = 0;
|
|
|
|
wcscpy(Pattern, End+1);
|
|
*(End+1) = 0;
|
|
*End = '\\';
|
|
|
|
/* change pattern: "*.*" --> "*" */
|
|
if (!wcscmp(Pattern, L"*.*"))
|
|
Pattern[1] = 0;
|
|
|
|
DPRINT("Directory %w Pattern %w\n",Directory,Pattern);
|
|
|
|
IData = HeapAlloc(GetProcessHeap(),
|
|
HEAP_ZERO_MEMORY,
|
|
sizeof(KERNEL32_FIND_FILE_DATA));
|
|
|
|
RtlInitUnicodeString(&DirectoryNameStr, Directory);
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
&DirectoryNameStr,
|
|
0,
|
|
NULL,
|
|
NULL);
|
|
|
|
if (ZwOpenFile(&IData->DirectoryHandle,
|
|
FILE_LIST_DIRECTORY,
|
|
&ObjectAttributes,
|
|
&IoStatusBlock,
|
|
FILE_OPEN_IF,
|
|
OPEN_EXISTING)!=STATUS_SUCCESS)
|
|
{
|
|
return(NULL);
|
|
}
|
|
|
|
RtlInitUnicodeString(&(IData->PatternStr), Pattern);
|
|
|
|
NtQueryDirectoryFile(IData->DirectoryHandle,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&IoStatusBlock,
|
|
(PVOID)&IData->FileInfo,
|
|
sizeof(IData->FileInfo) +
|
|
sizeof(IData->FileNameExtra),
|
|
FileBothDirectoryInformation,
|
|
TRUE,
|
|
&(IData->PatternStr),
|
|
FALSE);
|
|
DPRINT("Found %w\n",IData->FileInfo.FileName);
|
|
|
|
FileDataToWin32Data(lpFindFileData, IData);
|
|
|
|
return(IData);
|
|
}
|
|
|
|
HANDLE FindFirstFileA(LPCTSTR lpFileName, LPWIN32_FIND_DATA lpFindFileData)
|
|
{
|
|
WCHAR lpFileNameW[MAX_PATH];
|
|
ULONG i;
|
|
PKERNEL32_FIND_FILE_DATA IData;
|
|
PWIN32_FIND_DATA_ASCII Ret;
|
|
|
|
i = 0;
|
|
while (lpFileName[i]!=0)
|
|
{
|
|
lpFileNameW[i] = lpFileName[i];
|
|
i++;
|
|
}
|
|
lpFileNameW[i] = 0;
|
|
|
|
IData = InternalFindFirstFile(lpFileNameW,lpFindFileData);
|
|
if (IData == NULL)
|
|
{
|
|
DPRINT("Failing request\n");
|
|
return(INVALID_HANDLE_VALUE);
|
|
}
|
|
|
|
|
|
Ret = (PWIN32_FIND_DATA_ASCII)lpFindFileData;
|
|
|
|
DPRINT("IData->FileInfo.FileNameLength %d\n",
|
|
IData->FileInfo.FileNameLength);
|
|
for (i=0; i<IData->FileInfo.FileNameLength; i++)
|
|
{
|
|
Ret->cFileName[i] = IData->FileInfo.FileName[i];
|
|
}
|
|
Ret->cFileName[i] = 0;
|
|
|
|
DPRINT("IData->FileInfo.ShortNameLength %d\n",
|
|
IData->FileInfo.ShortNameLength);
|
|
if (IData->FileInfo.ShortNameLength > 13)
|
|
{
|
|
IData->FileInfo.ShortNameLength = 13;
|
|
}
|
|
for (i=0; i<IData->FileInfo.ShortNameLength; i++)
|
|
{
|
|
Ret->cAlternateFileName[i] = IData->FileInfo.ShortName[i];
|
|
}
|
|
Ret->cAlternateFileName[i] = 0;
|
|
|
|
|
|
return(IData);
|
|
}
|
|
|
|
WINBOOL FindNextFileA(HANDLE hFindFile, LPWIN32_FIND_DATA lpFindFileData)
|
|
{
|
|
PWIN32_FIND_DATA_ASCII Ret;
|
|
PKERNEL32_FIND_FILE_DATA IData;
|
|
ULONG i;
|
|
|
|
IData = (PKERNEL32_FIND_FILE_DATA)hFindFile;
|
|
if (IData == NULL)
|
|
{
|
|
return(FALSE);
|
|
}
|
|
if (!InternalFindNextFile(hFindFile, lpFindFileData))
|
|
{
|
|
DPRINT("InternalFindNextFile() failed\n");
|
|
return(FALSE);
|
|
}
|
|
|
|
Ret = (PWIN32_FIND_DATA_ASCII)lpFindFileData;
|
|
|
|
DPRINT("IData->FileInfo.FileNameLength %d\n",
|
|
IData->FileInfo.FileNameLength);
|
|
for (i=0; i<IData->FileInfo.FileNameLength; i++)
|
|
{
|
|
Ret->cFileName[i] = IData->FileInfo.FileName[i];
|
|
}
|
|
Ret->cFileName[i] = 0;
|
|
|
|
DPRINT("IData->FileInfo.ShortNameLength %d\n",
|
|
IData->FileInfo.ShortNameLength);
|
|
for (i=0; i<IData->FileInfo.ShortNameLength; i++)
|
|
{
|
|
Ret->cAlternateFileName[i] = IData->FileInfo.ShortName[i];
|
|
}
|
|
Ret->cAlternateFileName[i] = 0;
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
BOOL FindClose(HANDLE hFindFile)
|
|
{
|
|
PKERNEL32_FIND_FILE_DATA IData;
|
|
|
|
DPRINT("FindClose(hFindFile %x)\n",hFindFile);
|
|
|
|
if (hFindFile || hFindFile == INVALID_HANDLE_VALUE)
|
|
{
|
|
SetLastError (ERROR_INVALID_HANDLE);
|
|
return(FALSE);
|
|
}
|
|
IData = (PKERNEL32_FIND_FILE_DATA)hFindFile;
|
|
CloseHandle(IData->DirectoryHandle);
|
|
HeapFree(GetProcessHeap(), 0, IData);
|
|
return(TRUE);
|
|
}
|
|
|
|
HANDLE STDCALL FindFirstFileW(LPCWSTR lpFileName,
|
|
LPWIN32_FIND_DATA lpFindFileData)
|
|
{
|
|
PWIN32_FIND_DATA_UNICODE Ret;
|
|
PKERNEL32_FIND_FILE_DATA IData;
|
|
|
|
IData = InternalFindFirstFile(lpFileName,lpFindFileData);
|
|
Ret = (PWIN32_FIND_DATA_UNICODE)lpFindFileData;
|
|
|
|
memcpy(Ret->cFileName, IData->FileInfo.FileName,
|
|
IData->FileInfo.FileNameLength);
|
|
memcpy(Ret->cAlternateFileName, IData->FileInfo.ShortName,
|
|
IData->FileInfo.ShortNameLength);
|
|
|
|
return(IData);
|
|
}
|
|
|
|
WINBOOL STDCALL FindNextFileW(HANDLE hFindFile,
|
|
LPWIN32_FIND_DATA lpFindFileData)
|
|
{
|
|
PWIN32_FIND_DATA_UNICODE Ret;
|
|
PKERNEL32_FIND_FILE_DATA IData;
|
|
|
|
IData = (PKERNEL32_FIND_FILE_DATA)hFindFile;
|
|
if (!InternalFindNextFile(hFindFile, lpFindFileData))
|
|
{
|
|
return(FALSE);
|
|
}
|
|
|
|
Ret = (PWIN32_FIND_DATA_UNICODE)lpFindFileData;
|
|
|
|
memcpy(Ret->cFileName, IData->FileInfo.FileName,
|
|
IData->FileInfo.FileNameLength);
|
|
memcpy(Ret->cAlternateFileName, IData->FileInfo.ShortName,
|
|
IData->FileInfo.ShortNameLength);
|
|
|
|
return(TRUE);
|
|
}
|