⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 find.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 2 页
字号:
	                 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 + -