📄 find.c
字号:
0,
NtPathBuffer);
NtClose(hDirectory);
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return INVALID_HANDLE_VALUE;
}
IHeader->Type = FileFind;
IData = (PKERNEL32_FIND_FILE_DATA)(IHeader + 1);
IData->DirectoryHandle = hDirectory;
IData->HasMoreData = TRUE;
/* change pattern: "*.*" --> "*" */
if (PathFileName.Length == 6 &&
RtlCompareMemory(PathFileName.Buffer,
L"*.*",
6) == 6)
{
PathFileName.Length = 2;
}
IData->pFileInfo = (PVOID)((ULONG_PTR)IData + sizeof(KERNEL32_FIND_FILE_DATA));
IData->pFileInfo->FileIndex = 0;
IData->DirectoryOnly = DirectoryOnly;
bResult = InternalFindNextFile((HANDLE)IHeader,
&PathFileName,
lpFindFileData,
bUnicode);
RtlFreeHeap (hProcessHeap,
0,
NtPathBuffer);
if (!bResult)
{
FindClose((HANDLE)IHeader);
return INVALID_HANDLE_VALUE;
}
RtlInitializeCriticalSection(&IData->Lock);
IData->LockInitialized = TRUE;
return (HANDLE)IHeader;
}
/*
* @implemented
*/
HANDLE
STDCALL
FindFirstFileA (
LPCSTR lpFileName,
LPWIN32_FIND_DATAA lpFindFileData
)
{
return FindFirstFileExA (lpFileName,
FindExInfoStandard,
(LPVOID)lpFindFileData,
FindExSearchNameMatch,
NULL,
0);
}
/*
* @implemented
*/
BOOL
STDCALL
FindNextFileA (
HANDLE hFindFile,
LPWIN32_FIND_DATAA lpFindFileData)
{
return InternalFindNextFile (hFindFile,
NULL,
lpFindFileData,
FALSE);
}
/*
* @implemented
*/
BOOL
STDCALL
FindClose (
HANDLE hFindFile
)
{
PKERNEL32_FIND_DATA_HEADER IHeader;
DPRINT("FindClose(hFindFile %x)\n",hFindFile);
if (hFindFile == FIND_DEVICE_HANDLE)
return TRUE;
if (!hFindFile || hFindFile == INVALID_HANDLE_VALUE)
{
SetLastError (ERROR_INVALID_HANDLE);
return FALSE;
}
IHeader = (PKERNEL32_FIND_DATA_HEADER)hFindFile;
switch (IHeader->Type)
{
case FileFind:
{
PKERNEL32_FIND_FILE_DATA IData = (PKERNEL32_FIND_FILE_DATA)(IHeader + 1);
CloseHandle (IData->DirectoryHandle);
if (IData->LockInitialized)
RtlDeleteCriticalSection(&IData->Lock);
break;
}
case StreamFind:
{
PKERNEL32_FIND_STREAM_DATA IData = (PKERNEL32_FIND_STREAM_DATA)(IHeader + 1);
if (IData->pFileStreamInfo != NULL)
{
RtlFreeHeap (hProcessHeap, 0, IData->pFileStreamInfo);
}
break;
}
default:
SetLastError (ERROR_INVALID_HANDLE);
return FALSE;
}
RtlFreeHeap (hProcessHeap, 0, IHeader);
return TRUE;
}
/*
* @implemented
*/
HANDLE
STDCALL
FindFirstFileW (
LPCWSTR lpFileName,
LPWIN32_FIND_DATAW lpFindFileData
)
{
return FindFirstFileExW (lpFileName,
FindExInfoStandard,
(LPVOID)lpFindFileData,
FindExSearchNameMatch,
NULL,
0);
}
/*
* @implemented
*/
BOOL
STDCALL
FindNextFileW (
HANDLE hFindFile,
LPWIN32_FIND_DATAW lpFindFileData
)
{
return InternalFindNextFile (hFindFile,
NULL,
lpFindFileData,
TRUE);
}
/*
* @unimplemented
*/
HANDLE
STDCALL
FindFirstFileExW (LPCWSTR lpFileName,
FINDEX_INFO_LEVELS fInfoLevelId,
LPVOID lpFindFileData,
FINDEX_SEARCH_OPS fSearchOp,
LPVOID lpSearchFilter,
DWORD dwAdditionalFlags)
{
if (fInfoLevelId != FindExInfoStandard)
{
SetLastError(ERROR_INVALID_PARAMETER);
return INVALID_HANDLE_VALUE;
}
if (fSearchOp == FindExSearchNameMatch || fSearchOp == FindExSearchLimitToDirectories)
{
if (lpSearchFilter)
{
SetLastError(ERROR_INVALID_PARAMETER);
return INVALID_HANDLE_VALUE;
}
return InternalFindFirstFile (lpFileName,
fSearchOp == FindExSearchLimitToDirectories,
lpFindFileData,
TRUE);
}
SetLastError(ERROR_INVALID_PARAMETER);
return INVALID_HANDLE_VALUE;
}
/*
* @unimplemented
*/
HANDLE
STDCALL
FindFirstFileExA (
LPCSTR lpFileName,
FINDEX_INFO_LEVELS fInfoLevelId,
LPVOID lpFindFileData,
FINDEX_SEARCH_OPS fSearchOp,
LPVOID lpSearchFilter,
DWORD dwAdditionalFlags
)
{
UNICODE_STRING FileNameU;
ANSI_STRING FileNameA;
HANDLE Handle;
if (fInfoLevelId != FindExInfoStandard)
{
SetLastError(ERROR_INVALID_PARAMETER);
return INVALID_HANDLE_VALUE;
}
if (fSearchOp == FindExSearchNameMatch || fSearchOp == FindExSearchLimitToDirectories)
{
if (lpSearchFilter)
{
SetLastError(ERROR_INVALID_PARAMETER);
return INVALID_HANDLE_VALUE;
}
RtlInitAnsiString (&FileNameA, (LPSTR)lpFileName);
/* convert ansi (or oem) string to unicode */
if (bIsFileApiAnsi)
RtlAnsiStringToUnicodeString (&FileNameU, &FileNameA, TRUE);
else
RtlOemStringToUnicodeString (&FileNameU, &FileNameA, TRUE);
Handle = InternalFindFirstFile (FileNameU.Buffer,
fSearchOp == FindExSearchLimitToDirectories,
lpFindFileData,
FALSE);
RtlFreeUnicodeString (&FileNameU);
return Handle;
}
SetLastError(ERROR_INVALID_PARAMETER);
return INVALID_HANDLE_VALUE;
}
static VOID
InternalCopyStreamInfo(IN OUT PKERNEL32_FIND_STREAM_DATA IData,
OUT LPVOID lpFindStreamData)
{
ASSERT(IData->pCurrent);
switch (IData->InfoLevel)
{
case FindStreamInfoStandard:
{
ULONG StreamNameLen;
WIN32_FIND_STREAM_DATA *StreamData = (WIN32_FIND_STREAM_DATA*)lpFindStreamData;
StreamNameLen = IData->pCurrent->StreamNameLength;
if (StreamNameLen > sizeof(StreamData->cStreamName) - sizeof(WCHAR))
StreamNameLen = sizeof(StreamData->cStreamName) - sizeof(WCHAR);
StreamData->StreamSize.QuadPart = IData->pCurrent->StreamSize.QuadPart;
RtlCopyMemory(StreamData->cStreamName,
IData->pCurrent->StreamName,
StreamNameLen);
StreamData->cStreamName[StreamNameLen / sizeof(WCHAR)] = L'\0';
break;
}
default:
ASSERT(FALSE);
break;
}
}
/*
* @implemented
*/
HANDLE
WINAPI
FindFirstStreamW(IN LPCWSTR lpFileName,
IN STREAM_INFO_LEVELS InfoLevel,
OUT LPVOID lpFindStreamData,
IN DWORD dwFlags)
{
PKERNEL32_FIND_DATA_HEADER IHeader = NULL;
PKERNEL32_FIND_STREAM_DATA IData = NULL;
OBJECT_ATTRIBUTES ObjectAttributes;
IO_STATUS_BLOCK IoStatusBlock;
UNICODE_STRING NtPathU;
HANDLE FileHandle = NULL;
NTSTATUS Status;
ULONG BufferSize = 0;
if (dwFlags != 0 || InfoLevel != FindStreamInfoStandard ||
lpFindStreamData == NULL)
{
SetLastError(ERROR_INVALID_PARAMETER);
return INVALID_HANDLE_VALUE;
}
/* validate & translate the filename */
if (!RtlDosPathNameToNtPathName_U(lpFileName,
&NtPathU,
NULL,
NULL))
{
SetLastError(ERROR_PATH_NOT_FOUND);
return INVALID_HANDLE_VALUE;
}
/* open the file */
InitializeObjectAttributes(&ObjectAttributes,
&NtPathU,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
Status = NtCreateFile(&FileHandle,
0,
&ObjectAttributes,
&IoStatusBlock,
NULL,
0,
FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_OPEN,
0,
NULL,
0);
if (!NT_SUCCESS(Status))
{
goto Cleanup;
}
/* create the search context */
IHeader = RtlAllocateHeap(hProcessHeap,
0,
sizeof(KERNEL32_FIND_DATA_HEADER) +
sizeof(KERNEL32_FIND_STREAM_DATA));
if (IHeader == NULL)
{
Status = STATUS_NO_MEMORY;
goto Cleanup;
}
IHeader->Type = StreamFind;
IData = (PKERNEL32_FIND_STREAM_DATA)(IHeader + 1);
/* capture all information about the streams */
IData->InfoLevel = InfoLevel;
IData->pCurrent = NULL;
IData->pFileStreamInfo = NULL;
do
{
BufferSize += 0x1000;
if (IData->pFileStreamInfo == NULL)
{
IData->pFileStreamInfo = RtlAllocateHeap(hProcessHeap,
0,
BufferSize);
if (IData->pFileStreamInfo == NULL)
{
Status = STATUS_NO_MEMORY;
break;
}
}
else
{
PFILE_STREAM_INFORMATION pfsi;
pfsi = RtlReAllocateHeap(hProcessHeap,
0,
IData->pFileStreamInfo,
BufferSize);
if (pfsi == NULL)
{
Status = STATUS_NO_MEMORY;
break;
}
IData->pFileStreamInfo = pfsi;
}
Status = NtQueryInformationFile(FileHandle,
&IoStatusBlock,
IData->pFileStreamInfo,
BufferSize,
FileStreamInformation);
} while (Status == STATUS_BUFFER_TOO_SMALL);
if (NT_SUCCESS(Status))
{
NtClose(FileHandle);
FileHandle = NULL;
/* select the first stream and return the information */
IData->pCurrent = IData->pFileStreamInfo;
InternalCopyStreamInfo(IData,
lpFindStreamData);
/* all done */
Status = STATUS_SUCCESS;
}
Cleanup:
if (FileHandle != NULL)
{
NtClose(FileHandle);
}
RtlFreeHeap(RtlGetProcessHeap(),
0,
NtPathU.Buffer);
if (!NT_SUCCESS(Status))
{
if (IHeader != NULL)
{
if (IData->pFileStreamInfo != NULL)
{
RtlFreeHeap(hProcessHeap,
0,
IData->pFileStreamInfo);
}
RtlFreeHeap(hProcessHeap,
0,
IHeader);
}
SetLastErrorByStatus(Status);
return INVALID_HANDLE_VALUE;
}
return (HANDLE)IHeader;
}
/*
* @implemented
*/
BOOL
WINAPI
FindNextStreamW(IN HANDLE hFindStream,
OUT LPVOID lpFindStreamData)
{
PKERNEL32_FIND_DATA_HEADER IHeader;
PKERNEL32_FIND_STREAM_DATA IData;
IHeader = (PKERNEL32_FIND_DATA_HEADER)hFindStream;
if (hFindStream == NULL || hFindStream == INVALID_HANDLE_VALUE ||
IHeader->Type != StreamFind)
{
SetLastError (ERROR_INVALID_HANDLE);
return FALSE;
}
IData = (PKERNEL32_FIND_STREAM_DATA)(IHeader + 1);
/* select next stream if possible */
if (IData->pCurrent->NextEntryOffset != 0)
{
IData->pCurrent = (PFILE_STREAM_INFORMATION)((ULONG_PTR)IData->pFileStreamInfo +
IData->pCurrent->NextEntryOffset);
}
else
{
SetLastError(ERROR_HANDLE_EOF);
return FALSE;
}
/* return the information */
InternalCopyStreamInfo(IData,
lpFindStreamData);
return TRUE;
}
/* EOF */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -