📄 find.c
字号:
/* $Id: find.c 25139 2006-12-12 23:57:24Z janderwald $
*
* 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 <k32.h>
#define NDEBUG
#include "../include/debug.h"
/* TYPES ********************************************************************/
#define FIND_DATA_SIZE (16*1024)
typedef struct _KERNEL32_FIND_FILE_DATA
{
HANDLE DirectoryHandle;
BOOLEAN DirectoryOnly;
PFILE_BOTH_DIR_INFORMATION pFileInfo;
} KERNEL32_FIND_FILE_DATA, *PKERNEL32_FIND_FILE_DATA;
typedef struct _KERNEL32_FIND_STREAM_DATA
{
STREAM_INFO_LEVELS InfoLevel;
PFILE_STREAM_INFORMATION pFileStreamInfo;
PFILE_STREAM_INFORMATION pCurrent;
} KERNEL32_FIND_STREAM_DATA, *PKERNEL32_FIND_STREAM_DATA;
typedef enum _KERNEL32_FIND_DATA_TYPE
{
FileFind,
StreamFind
} KERNEL32_FIND_DATA_TYPE;
typedef struct _KERNEL32_FIND_DATA_HEADER
{
KERNEL32_FIND_DATA_TYPE Type;
} KERNEL32_FIND_DATA_HEADER, *PKERNEL32_FIND_DATA_HEADER;
/* FUNCTIONS ****************************************************************/
VOID
InternalCopyFindDataW(LPWIN32_FIND_DATAW lpFindFileData,
PFILE_BOTH_DIR_INFORMATION lpFileInfo)
{
lpFindFileData->dwFileAttributes = lpFileInfo->FileAttributes;
lpFindFileData->ftCreationTime.dwHighDateTime = lpFileInfo->CreationTime.u.HighPart;
lpFindFileData->ftCreationTime.dwLowDateTime = lpFileInfo->CreationTime.u.LowPart;
lpFindFileData->ftLastAccessTime.dwHighDateTime = lpFileInfo->LastAccessTime.u.HighPart;
lpFindFileData->ftLastAccessTime.dwLowDateTime = lpFileInfo->LastAccessTime.u.LowPart;
lpFindFileData->ftLastWriteTime.dwHighDateTime = lpFileInfo->LastWriteTime.u.HighPart;
lpFindFileData->ftLastWriteTime.dwLowDateTime = lpFileInfo->LastWriteTime.u.LowPart;
lpFindFileData->nFileSizeHigh = lpFileInfo->EndOfFile.u.HighPart;
lpFindFileData->nFileSizeLow = lpFileInfo->EndOfFile.u.LowPart;
memcpy (lpFindFileData->cFileName, lpFileInfo->FileName, lpFileInfo->FileNameLength);
lpFindFileData->cFileName[lpFileInfo->FileNameLength / sizeof(WCHAR)] = 0;
memcpy (lpFindFileData->cAlternateFileName, lpFileInfo->ShortName, lpFileInfo->ShortNameLength);
lpFindFileData->cAlternateFileName[lpFileInfo->ShortNameLength / sizeof(WCHAR)] = 0;
}
VOID
InternalCopyFindDataA(LPWIN32_FIND_DATAA lpFindFileData,
PFILE_BOTH_DIR_INFORMATION lpFileInfo)
{
UNICODE_STRING FileNameU;
ANSI_STRING FileNameA;
lpFindFileData->dwFileAttributes = lpFileInfo->FileAttributes;
lpFindFileData->ftCreationTime.dwHighDateTime = lpFileInfo->CreationTime.u.HighPart;
lpFindFileData->ftCreationTime.dwLowDateTime = lpFileInfo->CreationTime.u.LowPart;
lpFindFileData->ftLastAccessTime.dwHighDateTime = lpFileInfo->LastAccessTime.u.HighPart;
lpFindFileData->ftLastAccessTime.dwLowDateTime = lpFileInfo->LastAccessTime.u.LowPart;
lpFindFileData->ftLastWriteTime.dwHighDateTime = lpFileInfo->LastWriteTime.u.HighPart;
lpFindFileData->ftLastWriteTime.dwLowDateTime = lpFileInfo->LastWriteTime.u.LowPart;
lpFindFileData->nFileSizeHigh = lpFileInfo->EndOfFile.u.HighPart;
lpFindFileData->nFileSizeLow = lpFileInfo->EndOfFile.u.LowPart;
FileNameU.Length = FileNameU.MaximumLength = lpFileInfo->FileNameLength;
FileNameU.Buffer = lpFileInfo->FileName;
FileNameA.MaximumLength = sizeof(lpFindFileData->cFileName) - sizeof(CHAR);
FileNameA.Buffer = lpFindFileData->cFileName;
/* convert unicode string to ansi (or oem) */
if (bIsFileApiAnsi)
RtlUnicodeStringToAnsiString (&FileNameA, &FileNameU, FALSE);
else
RtlUnicodeStringToOemString (&FileNameA, &FileNameU, FALSE);
FileNameA.Buffer[FileNameA.Length] = 0;
DPRINT("lpFileInfo->ShortNameLength %d\n", lpFileInfo->ShortNameLength);
FileNameU.Length = FileNameU.MaximumLength = lpFileInfo->ShortNameLength;
FileNameU.Buffer = lpFileInfo->ShortName;
FileNameA.MaximumLength = sizeof(lpFindFileData->cAlternateFileName) - sizeof(CHAR);
FileNameA.Buffer = lpFindFileData->cAlternateFileName;
/* convert unicode string to ansi (or oem) */
if (bIsFileApiAnsi)
RtlUnicodeStringToAnsiString (&FileNameA, &FileNameU, FALSE);
else
RtlUnicodeStringToOemString (&FileNameA, &FileNameU, FALSE);
FileNameA.Buffer[FileNameA.Length] = 0;
}
/*
* @implemented
*/
BOOL
STDCALL
InternalFindNextFile (
HANDLE hFindFile,
PUNICODE_STRING SearchPattern
)
{
PKERNEL32_FIND_DATA_HEADER IHeader;
PKERNEL32_FIND_FILE_DATA IData;
IO_STATUS_BLOCK IoStatusBlock;
NTSTATUS Status;
DPRINT("InternalFindNextFile(%lx)\n", hFindFile);
IHeader = (PKERNEL32_FIND_DATA_HEADER)hFindFile;
if (hFindFile == NULL || hFindFile == INVALID_HANDLE_VALUE ||
IHeader->Type != FileFind)
{
SetLastError (ERROR_INVALID_HANDLE);
return FALSE;
}
IData = (PKERNEL32_FIND_FILE_DATA)(IHeader + 1);
while (1)
{
if (IData->pFileInfo->NextEntryOffset != 0)
{
IData->pFileInfo = (PVOID)((ULONG_PTR)IData->pFileInfo + IData->pFileInfo->NextEntryOffset);
}
else
{
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,
SearchPattern ? TRUE : FALSE,
SearchPattern,
SearchPattern ? TRUE : FALSE);
SearchPattern = NULL;
if (!NT_SUCCESS(Status))
{
SetLastErrorByStatus (Status);
return FALSE;
}
}
if (!IData->DirectoryOnly || IData->pFileInfo->FileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
DPRINT("Found %.*S\n",IData->pFileInfo->FileNameLength/sizeof(WCHAR), IData->pFileInfo->FileName);
return TRUE;
}
}
}
/*
* @implemented
*/
HANDLE
STDCALL
InternalFindFirstFile (
LPCWSTR lpFileName,
BOOLEAN DirectoryOnly
)
{
OBJECT_ATTRIBUTES ObjectAttributes;
PKERNEL32_FIND_DATA_HEADER IHeader;
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 (SearchPath,
&NtPathU,
NULL,
NULL);
if (SearchPath != CurrentDir)
{
RtlFreeHeap(hProcessHeap,
0,
SearchPath);
}
if (FALSE == bResult)
{
if (NULL != SlashlessFileName)
{
RtlFreeHeap(hProcessHeap,
0,
SlashlessFileName);
}
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return NULL;
}
DPRINT("NtPathU \'%S\'\n", NtPathU.Buffer);
IHeader = RtlAllocateHeap (hProcessHeap,
HEAP_ZERO_MEMORY,
sizeof(KERNEL32_FIND_DATA_HEADER) +
sizeof(KERNEL32_FIND_FILE_DATA) + FIND_DATA_SIZE);
if (NULL == IHeader)
{
RtlFreeHeap (hProcessHeap,
0,
NtPathU.Buffer);
if (NULL != SlashlessFileName)
{
RtlFreeHeap(hProcessHeap,
0,
SlashlessFileName);
}
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return NULL;
}
IHeader->Type = FileFind;
IData = (PKERNEL32_FIND_FILE_DATA)(IHeader + 1);
/* 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, 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->FileIndex = 0;
IData->DirectoryOnly = DirectoryOnly;
bResult = InternalFindNextFile((HANDLE)IHeader, &PatternStr);
if (NULL != SlashlessFileName)
{
RtlFreeHeap(hProcessHeap,
0,
SlashlessFileName);
}
if (!bResult)
{
FindClose((HANDLE)IHeader);
return NULL;
}
return (HANDLE)IHeader;
}
/*
* @implemented
*/
HANDLE
STDCALL
FindFirstFileA (
LPCSTR lpFileName,
LPWIN32_FIND_DATAA lpFindFileData
)
{
PKERNEL32_FIND_DATA_HEADER IHeader;
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);
IHeader = InternalFindFirstFile (FileNameU.Buffer, FALSE);
RtlFreeUnicodeString (&FileNameU);
if (IHeader == NULL)
{
DPRINT("Failing request\n");
return INVALID_HANDLE_VALUE;
}
IData = (PKERNEL32_FIND_FILE_DATA)(IHeader + 1);
DPRINT("IData->pFileInfo->FileNameLength %d\n",
IData->pFileInfo->FileNameLength);
/* copy data into WIN32_FIND_DATA structure */
InternalCopyFindDataA(lpFindFileData, IData->pFileInfo);
return (HANDLE)IHeader;
}
/*
* @implemented
*/
BOOL
STDCALL
FindNextFileA (
HANDLE hFindFile,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -