windows-nt/Source/XPSP1/NT/base/remoteboot/imirror/findfile.c
2020-09-26 16:20:57 +08:00

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