330 lines
8 KiB
C
330 lines
8 KiB
C
|
/*++
|
||
|
|
||
|
Copyright (c) 1990 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
findfile.c
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
This module implements IMFindFirst/IMFindNext
|
||
|
|
||
|
Author:
|
||
|
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
--*/
|
||
|
|
||
|
#include "precomp.h"
|
||
|
#pragma hdrstop
|
||
|
|
||
|
#define IMIRROR_DIR_ENUM_BUFFER_SIZE 4096
|
||
|
|
||
|
ULONG
|
||
|
IMConvertNT2Win32Error(
|
||
|
IN NTSTATUS Status
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This API sets the "last error value" and the "last error string"
|
||
|
based on the value of Status. For status codes that don't have
|
||
|
a corresponding error string, the string is set to null.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
Status - Supplies the status value to store as the last error value.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
The corresponding Win32 error code that was stored in the
|
||
|
"last error value" thread variable.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
ULONG dwErrorCode;
|
||
|
|
||
|
dwErrorCode = RtlNtStatusToDosError( Status );
|
||
|
SetLastError( dwErrorCode );
|
||
|
return( dwErrorCode );
|
||
|
}
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
IMFindNextFile(
|
||
|
PIMIRROR_THREAD_CONTEXT ThreadContext,
|
||
|
HANDLE DirHandle,
|
||
|
PFILE_FULL_DIR_INFORMATION *lpFindFileData
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
ThreadContext - instance data for this enumeration
|
||
|
|
||
|
DirHandle - handle of directory to query.
|
||
|
|
||
|
lpFindFileData - On a successful find, this parameter returns information
|
||
|
about the located file.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
TRUE - The operation was successful.
|
||
|
|
||
|
FALSE/NULL - The operation failed. Extended error status is available
|
||
|
using GetLastError.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
IO_STATUS_BLOCK IoStatusBlock;
|
||
|
NTSTATUS Status;
|
||
|
|
||
|
if (ThreadContext->FindBufferNext != NULL) {
|
||
|
|
||
|
*lpFindFileData = (PFILE_FULL_DIR_INFORMATION) ThreadContext->FindBufferNext;
|
||
|
|
||
|
if ((*lpFindFileData)->NextEntryOffset > 0) {
|
||
|
|
||
|
ThreadContext->FindBufferNext =
|
||
|
(PVOID)(((PCHAR)*lpFindFileData ) + (*lpFindFileData)->NextEntryOffset );
|
||
|
} else {
|
||
|
|
||
|
ThreadContext->FindBufferNext = NULL;
|
||
|
}
|
||
|
|
||
|
return ERROR_SUCCESS;
|
||
|
}
|
||
|
|
||
|
ThreadContext->FindBufferNext = NULL;
|
||
|
|
||
|
Status = NtQueryDirectoryFile(
|
||
|
DirHandle,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
&IoStatusBlock,
|
||
|
ThreadContext->FindBufferBase,
|
||
|
ThreadContext->FindBufferLength,
|
||
|
FileFullDirectoryInformation,
|
||
|
FALSE, // return multiple entries
|
||
|
NULL,
|
||
|
FALSE // not a rescan
|
||
|
);
|
||
|
|
||
|
if (NT_SUCCESS( Status )) {
|
||
|
|
||
|
*lpFindFileData = (PFILE_FULL_DIR_INFORMATION) ThreadContext->FindBufferBase;
|
||
|
|
||
|
if ((*lpFindFileData)->NextEntryOffset > 0) {
|
||
|
|
||
|
ThreadContext->FindBufferNext =
|
||
|
(PVOID)(((PCHAR) *lpFindFileData ) + (*lpFindFileData)->NextEntryOffset );
|
||
|
}
|
||
|
return STATUS_SUCCESS;
|
||
|
|
||
|
}
|
||
|
|
||
|
*lpFindFileData = NULL;
|
||
|
|
||
|
if (Status == STATUS_NO_MORE_FILES ||
|
||
|
Status == STATUS_NO_SUCH_FILE ||
|
||
|
Status == STATUS_OBJECT_NAME_NOT_FOUND) {
|
||
|
|
||
|
return STATUS_SUCCESS;
|
||
|
}
|
||
|
return IMConvertNT2Win32Error( Status );
|
||
|
}
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
IMFindFirstFile(
|
||
|
PIMIRROR_THREAD_CONTEXT ThreadContext,
|
||
|
HANDLE DirHandle,
|
||
|
PFILE_FULL_DIR_INFORMATION *lpFindFileData
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This returns all entries in a directory. This allocates a buffer if
|
||
|
needed and sets up the variables in the ThreadContext to track the
|
||
|
enumeration.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
ThreadContext - instance data for this enumeration
|
||
|
|
||
|
DirHandle - handle of directory to query.
|
||
|
|
||
|
lpFindFileData - Supplies a pointer to a full dir info structure.
|
||
|
This points into our buffer and should not be freed by the caller.
|
||
|
|
||
|
No call is required to close this, but note that a thread context
|
||
|
can only have a single enumeration going on at any time.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
Win32 error. ERROR_SUCCESS is only successful case.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
IO_STATUS_BLOCK IoStatusBlock;
|
||
|
NTSTATUS Status;
|
||
|
UNICODE_STRING allFiles;
|
||
|
|
||
|
if (ThreadContext->FindBufferBase == NULL) {
|
||
|
|
||
|
ThreadContext->FindBufferBase = IMirrorAllocMem( IMIRROR_DIR_ENUM_BUFFER_SIZE );
|
||
|
|
||
|
if (ThreadContext->FindBufferBase == NULL) {
|
||
|
|
||
|
return STATUS_NO_MEMORY;
|
||
|
}
|
||
|
|
||
|
ThreadContext->FindBufferLength = IMIRROR_DIR_ENUM_BUFFER_SIZE;
|
||
|
}
|
||
|
|
||
|
RtlInitUnicodeString( &allFiles, L"*" );
|
||
|
|
||
|
ThreadContext->FindBufferNext = NULL;
|
||
|
|
||
|
Status = NtQueryDirectoryFile(
|
||
|
DirHandle,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
&IoStatusBlock,
|
||
|
ThreadContext->FindBufferBase,
|
||
|
ThreadContext->FindBufferLength,
|
||
|
FileFullDirectoryInformation,
|
||
|
FALSE, // return multiple entries
|
||
|
&allFiles,
|
||
|
TRUE
|
||
|
);
|
||
|
if (NT_SUCCESS( Status )) {
|
||
|
|
||
|
*lpFindFileData = (PFILE_FULL_DIR_INFORMATION) ThreadContext->FindBufferBase;
|
||
|
|
||
|
if ((*lpFindFileData)->NextEntryOffset > 0) {
|
||
|
|
||
|
ThreadContext->FindBufferNext =
|
||
|
(PVOID)(((PCHAR) *lpFindFileData ) + (*lpFindFileData)->NextEntryOffset );
|
||
|
}
|
||
|
} else {
|
||
|
|
||
|
*lpFindFileData = NULL;
|
||
|
}
|
||
|
return IMConvertNT2Win32Error( Status );
|
||
|
}
|
||
|
|
||
|
|
||
|
#if 0
|
||
|
BOOL
|
||
|
IMSetFileTime(
|
||
|
HANDLE hFile,
|
||
|
CONST FILETIME *lpCreationTime,
|
||
|
CONST FILETIME *lpLastAccessTime,
|
||
|
CONST FILETIME *lpLastWriteTime,
|
||
|
CONST FILETIME *lpChangeTime
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Identical to SetFileTime Win32 api, expect this also allows to specify a new ChangeTime.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
hFile - Supplies an open handle to a file whose modification date and
|
||
|
times are to be written. The file handle must have been created
|
||
|
with GENERIC_WRITE access to the file.
|
||
|
|
||
|
lpCreationTime - An optional parameter, that if specified supplies
|
||
|
the new creation time for the file. Some file system's do not
|
||
|
support this time value, so this parameter may be ignored.
|
||
|
|
||
|
lpLastAccessTime - An optional parameter, that if specified supplies
|
||
|
the new last access time for the file. Some file system's do
|
||
|
not support this time value, so this parameter may be ignored.
|
||
|
|
||
|
lpLastWriteTime - An optional parameter, that if specified supplies
|
||
|
the new last write time for the file. A file system must support
|
||
|
this time value.
|
||
|
|
||
|
lpChangeTime - An optional parameter, that if specified supplies
|
||
|
the new change time for the file. A file system must support
|
||
|
this time value.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
TRUE - The operation was successful.
|
||
|
|
||
|
FALSE/NULL - The operation failed. Extended error status is available
|
||
|
using GetLastError.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
NTSTATUS Status;
|
||
|
IO_STATUS_BLOCK IoStatusBlock;
|
||
|
FILE_BASIC_INFORMATION BasicInfo;
|
||
|
|
||
|
|
||
|
//
|
||
|
// Zero all the time values we can set.
|
||
|
//
|
||
|
|
||
|
RtlZeroMemory(&BasicInfo,sizeof(BasicInfo));
|
||
|
|
||
|
//
|
||
|
// For each time value that is specified, copy it to the I/O system
|
||
|
// record.
|
||
|
//
|
||
|
if (ARGUMENT_PRESENT( lpCreationTime )) {
|
||
|
BasicInfo.CreationTime.LowPart = lpCreationTime->dwLowDateTime;
|
||
|
BasicInfo.CreationTime.HighPart = lpCreationTime->dwHighDateTime;
|
||
|
}
|
||
|
|
||
|
if (ARGUMENT_PRESENT( lpLastAccessTime )) {
|
||
|
BasicInfo.LastAccessTime.LowPart = lpLastAccessTime->dwLowDateTime;
|
||
|
BasicInfo.LastAccessTime.HighPart = lpLastAccessTime->dwHighDateTime;
|
||
|
}
|
||
|
|
||
|
if (ARGUMENT_PRESENT( lpLastWriteTime )) {
|
||
|
BasicInfo.LastWriteTime.LowPart = lpLastWriteTime->dwLowDateTime;
|
||
|
BasicInfo.LastWriteTime.HighPart = lpLastWriteTime->dwHighDateTime;
|
||
|
}
|
||
|
|
||
|
if (ARGUMENT_PRESENT( lpChangeTime )) {
|
||
|
BasicInfo.ChangeTime.LowPart = lpChangeTime->dwLowDateTime;
|
||
|
BasicInfo.ChangeTime.HighPart = lpChangeTime->dwHighDateTime;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Set the requested times.
|
||
|
//
|
||
|
|
||
|
Status = NtSetInformationFile(
|
||
|
hFile,
|
||
|
&IoStatusBlock,
|
||
|
&BasicInfo,
|
||
|
sizeof(BasicInfo),
|
||
|
FileBasicInformation
|
||
|
);
|
||
|
|
||
|
if ( NT_SUCCESS(Status) ) {
|
||
|
return TRUE;
|
||
|
} else {
|
||
|
IMConvertNT2Win32Error(Status);
|
||
|
return FALSE;
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
|