mirror of
https://github.com/winfsp/winfsp.git
synced 2025-04-22 16:33:02 -05:00
sys: implement named stream open/close and related delete/share access issues
This commit is contained in:
parent
2ba46fdb71
commit
495fc7a5dc
@ -167,12 +167,21 @@ static VOID FspFsvolCleanupRequestFini(FSP_FSCTL_TRANSACT_REQ *Request, PVOID Co
|
||||
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
||||
PFILE_OBJECT FileObject = IrpSp->FileObject;
|
||||
FSP_FILE_NODE *FileNode = FileObject->FsContext;
|
||||
FSP_FILE_DESC *FileDesc = FileObject->FsContext2;
|
||||
HANDLE MainStreamHandle;
|
||||
|
||||
ASSERT(FileNode == FileDesc->FileNode);
|
||||
|
||||
FspFileNodeReleaseOwner(FileNode, Pgio, Request);
|
||||
|
||||
FspFileNodeCleanupComplete(FileNode, FileObject);
|
||||
|
||||
MainStreamHandle = FileDesc->MainStreamHandle;
|
||||
FileDesc->MainStreamHandle = 0;
|
||||
|
||||
FspFileNodeReleaseOwner(FileNode, Main, Request);
|
||||
|
||||
FspMainStreamClose(MainStreamHandle, 0);
|
||||
}
|
||||
|
||||
NTSTATUS FspCleanup(
|
||||
|
@ -77,7 +77,7 @@ static NTSTATUS FspFsvolClose(
|
||||
FspFileNodeClose(FileNode, FileObject);
|
||||
|
||||
/* delete the FileDesc and deref the FileNode; order is important (FileDesc has FileNode ref) */
|
||||
FspFileDescDelete(FileDesc);
|
||||
FspFileDescDelete(FileDesc); /* this will also close the MainStreamObject if any */
|
||||
FspFileNodeDereference(FileNode);
|
||||
|
||||
/*
|
||||
|
@ -134,7 +134,6 @@ static NTSTATUS FspFsvolCreateNoLock(
|
||||
PFILE_OBJECT FileObject = IrpSp->FileObject;
|
||||
PFILE_OBJECT RelatedFileObject = FileObject->RelatedFileObject;
|
||||
UNICODE_STRING FileName = FileObject->FileName;
|
||||
UNICODE_STRING MainStreamName = { 0 }, StreamPart = { 0 };
|
||||
|
||||
/* open the volume object? */
|
||||
if ((0 == RelatedFileObject || !FspFileNodeIsValid(RelatedFileObject->FsContext)) &&
|
||||
@ -148,6 +147,7 @@ static NTSTATUS FspFsvolCreateNoLock(
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
UNICODE_STRING MainStreamName = { 0 }, StreamPart = { 0 };
|
||||
PACCESS_STATE AccessState = IrpSp->Parameters.Create.SecurityContext->AccessState;
|
||||
ULONG CreateDisposition = (IrpSp->Parameters.Create.Options >> 24) & 0xff;
|
||||
ULONG CreateOptions = IrpSp->Parameters.Create.Options;
|
||||
@ -163,6 +163,10 @@ static NTSTATUS FspFsvolCreateNoLock(
|
||||
ULONG Flags = IrpSp->Flags;
|
||||
KPROCESSOR_MODE RequestorMode =
|
||||
FlagOn(Flags, SL_FORCE_ACCESS_CHECK) ? UserMode : Irp->RequestorMode;
|
||||
BOOLEAN CaseSensitiveRequested =
|
||||
BooleanFlagOn(Flags, SL_CASE_SENSITIVE);
|
||||
BOOLEAN CaseSensitive =
|
||||
CaseSensitiveRequested || FsvolDeviceExtension->VolumeParams.CaseSensitiveSearch;
|
||||
BOOLEAN HasTraversePrivilege =
|
||||
BooleanFlagOn(AccessState->Flags, TOKEN_HAS_TRAVERSE_PRIVILEGE);
|
||||
FSP_FILE_NODE *FileNode, *RelatedFileNode;
|
||||
@ -347,6 +351,52 @@ static NTSTATUS FspFsvolCreateNoLock(
|
||||
return Result;
|
||||
}
|
||||
|
||||
/* if we have a non-empty stream part, open the main stream */
|
||||
if (0 != StreamPart.Buffer)
|
||||
{
|
||||
Result = FspMainStreamOpen(FsvolDeviceObject,
|
||||
&MainStreamName, CaseSensitive,
|
||||
CreateDisposition,
|
||||
&FileDesc->MainStreamHandle,
|
||||
&FileDesc->MainStreamObject);
|
||||
if (!NT_SUCCESS(Result))
|
||||
goto main_stream_exit;
|
||||
|
||||
/* check that the main stream is one we recognize */
|
||||
if (!FspFileNodeIsValid(FileDesc->MainStreamObject->FsContext))
|
||||
{
|
||||
Result = STATUS_OBJECT_NAME_NOT_FOUND;
|
||||
goto main_stream_exit;
|
||||
}
|
||||
|
||||
/* named streams can never be directories (even when attached to directories) */
|
||||
if (FlagOn(CreateOptions, FILE_DIRECTORY_FILE))
|
||||
{
|
||||
Result = STATUS_NOT_A_DIRECTORY;
|
||||
goto main_stream_exit;
|
||||
}
|
||||
|
||||
/* cannot open target directory of a named stream */
|
||||
if (FlagOn(Flags, SL_OPEN_TARGET_DIRECTORY))
|
||||
{
|
||||
Result = STATUS_OBJECT_NAME_INVALID;
|
||||
goto main_stream_exit;
|
||||
}
|
||||
|
||||
/* remember the the main stream node */
|
||||
FileNode->MainStreamFileNode = FileDesc->MainStreamObject->FsContext;
|
||||
|
||||
Result = STATUS_SUCCESS;
|
||||
|
||||
main_stream_exit:
|
||||
if (!NT_SUCCESS(Result))
|
||||
{
|
||||
FspFileDescDelete(FileDesc);
|
||||
FspFileNodeDereference(FileNode);
|
||||
return Result;
|
||||
}
|
||||
}
|
||||
|
||||
/* create the user-mode file system request */
|
||||
Result = FspIopCreateRequestEx(Irp, &FileNode->FileName, SecurityDescriptorSize,
|
||||
FspFsvolCreateRequestFini, &Request);
|
||||
@ -369,9 +419,7 @@ static NTSTATUS FspFsvolCreateNoLock(
|
||||
* delete the Request and any associated resources.
|
||||
*/
|
||||
FileDesc->FileNode = FileNode;
|
||||
FileDesc->CaseSensitive =
|
||||
0 != FsvolDeviceExtension->VolumeParams.CaseSensitiveSearch ||
|
||||
BooleanFlagOn(Flags, SL_CASE_SENSITIVE);
|
||||
FileDesc->CaseSensitive = CaseSensitive;
|
||||
FileDesc->HasTraversePrivilege = HasTraversePrivilege;
|
||||
FspFsvolDeviceFileRenameSetOwner(FsvolDeviceObject, Request);
|
||||
FspIopRequestContext(Request, RequestDeviceObject) = FsvolDeviceObject;
|
||||
@ -393,7 +441,7 @@ static NTSTATUS FspFsvolCreateNoLock(
|
||||
Request->Req.Create.UserMode = UserMode == RequestorMode;
|
||||
Request->Req.Create.HasTraversePrivilege = HasTraversePrivilege;
|
||||
Request->Req.Create.OpenTargetDirectory = BooleanFlagOn(Flags, SL_OPEN_TARGET_DIRECTORY);
|
||||
Request->Req.Create.CaseSensitive = BooleanFlagOn(Flags, SL_CASE_SENSITIVE);
|
||||
Request->Req.Create.CaseSensitive = CaseSensitiveRequested;
|
||||
|
||||
/* copy the security descriptor (if any) into the request */
|
||||
if (0 != SecurityDescriptorSize)
|
||||
|
@ -431,6 +431,15 @@ VOID FspUnicodePathSuffix(PUNICODE_STRING Path, PUNICODE_STRING Remain, PUNICODE
|
||||
NTSTATUS FspCreateGuid(GUID *Guid);
|
||||
NTSTATUS FspGetDeviceObjectPointer(PUNICODE_STRING ObjectName, ACCESS_MASK DesiredAccess,
|
||||
PULONG PFileNameIndex, PFILE_OBJECT *PFileObject, PDEVICE_OBJECT *PDeviceObject);
|
||||
NTSTATUS FspMainStreamOpen(
|
||||
PDEVICE_OBJECT DeviceObject,
|
||||
PUNICODE_STRING MainStreamName, BOOLEAN CaseSensitive,
|
||||
ULONG Disposition,
|
||||
PHANDLE PMainStreamHandle,
|
||||
PFILE_OBJECT *PMainStreamObject);
|
||||
NTSTATUS FspMainStreamClose(
|
||||
HANDLE MainStreamHandle,
|
||||
PFILE_OBJECT MainStreamObject);
|
||||
NTSTATUS FspSendSetInformationIrp(PDEVICE_OBJECT DeviceObject, PFILE_OBJECT FileObject,
|
||||
FILE_INFORMATION_CLASS FileInformationClass, PVOID FileInformation, ULONG Length);
|
||||
NTSTATUS FspBufferUserBuffer(PIRP Irp, ULONG Length, LOCK_OPERATION Operation);
|
||||
@ -896,7 +905,7 @@ typedef struct
|
||||
UINT64 DirInfo;
|
||||
UINT64 StreamInfo;
|
||||
} FSP_FILE_NODE_NONPAGED;
|
||||
typedef struct
|
||||
typedef struct FSP_FILE_NODE
|
||||
{
|
||||
FSRTL_ADVANCED_FCB_HEADER Header;
|
||||
FSP_FILE_NODE_NONPAGED *NonPaged;
|
||||
@ -907,6 +916,8 @@ typedef struct
|
||||
LONG OpenCount; /* ContextTable ref count */
|
||||
LONG HandleCount; /* HANDLE count (CREATE/CLEANUP) */
|
||||
SHARE_ACCESS ShareAccess;
|
||||
ULONG MainStreamDenyDeleteCount; /* number of times main stream is denying delete */
|
||||
ULONG StreamDenyDeleteCount; /* number of open streams that are denying delete */
|
||||
FSP_DEVICE_CONTEXT_BY_NAME_TABLE_ELEMENT ContextByNameElementStorage;
|
||||
/* locked under FSP_FSVOL_DEVICE_EXTENSION::FileRenameResource or Header.Resource */
|
||||
UNICODE_STRING FileName;
|
||||
@ -941,6 +952,7 @@ typedef struct
|
||||
UINT64 IndexNumber;
|
||||
BOOLEAN IsDirectory;
|
||||
BOOLEAN IsRootDirectory;
|
||||
struct FSP_FILE_NODE *MainStreamFileNode; /* this becomes invalid after our last desc close */
|
||||
WCHAR FileNameBuf[];
|
||||
} FSP_FILE_NODE;
|
||||
typedef struct
|
||||
@ -955,6 +967,9 @@ typedef struct
|
||||
UINT64 DirectoryOffset;
|
||||
UINT64 DirInfo;
|
||||
ULONG DirInfoCacheHint;
|
||||
/* stream support */
|
||||
HANDLE MainStreamHandle;
|
||||
PFILE_OBJECT MainStreamObject;
|
||||
} FSP_FILE_DESC;
|
||||
NTSTATUS FspFileNodeCopyList(PDEVICE_OBJECT DeviceObject,
|
||||
FSP_FILE_NODE ***PFileNodes, PULONG PFileNodeCount);
|
||||
|
@ -420,12 +420,37 @@ FSP_FILE_NODE *FspFileNodeOpen(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject,
|
||||
PAGED_CODE();
|
||||
|
||||
PDEVICE_OBJECT FsvolDeviceObject = FileNode->FsvolDeviceObject;
|
||||
FSP_FILE_NODE *OpenedFileNode;
|
||||
FSP_FILE_NODE *OpenedFileNode = 0;
|
||||
BOOLEAN Inserted, DeletePending;
|
||||
NTSTATUS Result;
|
||||
|
||||
FspFsvolDeviceLockContextTable(FsvolDeviceObject);
|
||||
|
||||
/*
|
||||
* If this is a named stream we must also check with our main stream.
|
||||
* Note that FileNode->MainStreamFileNode and OpenedFileNode->MainStreamFileNode
|
||||
* will always be the same.
|
||||
*/
|
||||
if (0 != FileNode->MainStreamFileNode)
|
||||
{
|
||||
DeletePending = 0 != FileNode->MainStreamFileNode->DeletePending;
|
||||
MemoryBarrier();
|
||||
if (DeletePending)
|
||||
{
|
||||
Result = STATUS_DELETE_PENDING;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (0 < FileNode->MainStreamFileNode->MainStreamDenyDeleteCount)
|
||||
{
|
||||
if (FlagOn(GrantedAccess, DELETE))
|
||||
{
|
||||
Result = STATUS_SHARING_VIOLATION;
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
OpenedFileNode = FspFsvolDeviceInsertContextByName(FsvolDeviceObject,
|
||||
&FileNode->FileName, FileNode, &FileNode->ContextByNameElementStorage, &Inserted);
|
||||
ASSERT(0 != OpenedFileNode);
|
||||
@ -449,6 +474,7 @@ FSP_FILE_NODE *FspFileNodeOpen(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject,
|
||||
* opening a prior FileNode that we found in the table.
|
||||
*/
|
||||
ASSERT(OpenedFileNode != FileNode);
|
||||
ASSERT(OpenedFileNode->MainStreamFileNode == FileNode->MainStreamFileNode);
|
||||
|
||||
DeletePending = 0 != OpenedFileNode->DeletePending;
|
||||
MemoryBarrier();
|
||||
@ -458,6 +484,19 @@ FSP_FILE_NODE *FspFileNodeOpen(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject,
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* if this is a main stream check whether there is a named stream that denies delete */
|
||||
if (0 < OpenedFileNode->StreamDenyDeleteCount)
|
||||
{
|
||||
/* we must be the main stream! */
|
||||
ASSERT(0 == OpenedFileNode->MainStreamFileNode);
|
||||
|
||||
if (FlagOn(GrantedAccess, DELETE))
|
||||
{
|
||||
Result = STATUS_SHARING_VIOLATION;
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* FastFat says to do the following on Vista and above.
|
||||
*
|
||||
@ -478,15 +517,33 @@ FSP_FILE_NODE *FspFileNodeOpen(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject,
|
||||
/* share access check */
|
||||
Result = IoCheckShareAccess(GrantedAccess, ShareAccess, FileObject,
|
||||
&OpenedFileNode->ShareAccess, TRUE);
|
||||
|
||||
exit:
|
||||
if (!NT_SUCCESS(Result))
|
||||
{
|
||||
if (0 != PResult)
|
||||
*PResult = Result;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
OpenedFileNode = 0;
|
||||
}
|
||||
/*
|
||||
* No more failures allowed at this point!
|
||||
* This is because we have potentially inserted a new FileNode into the Context table.
|
||||
* We also updated OpenedFileNode->ShareAccess in IoSetShareAccess/IoCheckShareAccess.
|
||||
*/
|
||||
|
||||
if (FileObject->DeleteAccess && !FileObject->SharedDelete)
|
||||
{
|
||||
if (0 == OpenedFileNode->MainStreamFileNode)
|
||||
OpenedFileNode->MainStreamDenyDeleteCount++;
|
||||
else
|
||||
OpenedFileNode->MainStreamFileNode->StreamDenyDeleteCount++;
|
||||
}
|
||||
|
||||
Result = STATUS_SUCCESS;
|
||||
|
||||
exit:
|
||||
if (!NT_SUCCESS(Result))
|
||||
{
|
||||
if (0 != PResult)
|
||||
*PResult = Result;
|
||||
|
||||
OpenedFileNode = 0;
|
||||
}
|
||||
|
||||
if (0 != OpenedFileNode)
|
||||
@ -556,6 +613,14 @@ VOID FspFileNodeCleanupComplete(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject
|
||||
|
||||
FspFsvolDeviceLockContextTable(FsvolDeviceObject);
|
||||
|
||||
if (FileObject->DeleteAccess && !FileObject->SharedDelete)
|
||||
{
|
||||
if (0 == FileNode->MainStreamFileNode)
|
||||
FileNode->MainStreamDenyDeleteCount--;
|
||||
else
|
||||
FileNode->MainStreamFileNode->StreamDenyDeleteCount--;
|
||||
}
|
||||
|
||||
IoRemoveShareAccess(FileObject, &FileNode->ShareAccess);
|
||||
|
||||
if (0 == --FileNode->HandleCount)
|
||||
@ -1088,6 +1153,8 @@ VOID FspFileDescDelete(FSP_FILE_DESC *FileDesc)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
FspMainStreamClose(FileDesc->MainStreamHandle, FileDesc->MainStreamObject);
|
||||
|
||||
if (0 != FileDesc->DirectoryPattern.Buffer &&
|
||||
FspFileDescDirectoryPatternMatchAll != FileDesc->DirectoryPattern.Buffer)
|
||||
{
|
||||
|
@ -449,6 +449,9 @@ static NTSTATUS FspFsvolQueryStreamInformation(
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
if (!FspFsvolDeviceExtension(FsvolDeviceObject)->VolumeParams.NamedStreams)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
NTSTATUS Result;
|
||||
PFILE_OBJECT FileObject = IrpSp->FileObject;
|
||||
FSP_FILE_NODE *FileNode = FileObject->FsContext;
|
||||
@ -499,6 +502,10 @@ static NTSTATUS FspFsvolQueryStreamInformationSuccess(
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
if (!FspFsvolDeviceExtension(IoGetCurrentIrpStackLocation(Irp)->DeviceObject)->
|
||||
VolumeParams.NamedStreams)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
NTSTATUS Result;
|
||||
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
||||
PFILE_OBJECT FileObject = IrpSp->FileObject;
|
||||
|
113
src/sys/util.c
113
src/sys/util.c
@ -23,6 +23,15 @@ VOID FspUnicodePathSuffix(PUNICODE_STRING Path, PUNICODE_STRING Remain, PUNICODE
|
||||
NTSTATUS FspCreateGuid(GUID *Guid);
|
||||
NTSTATUS FspGetDeviceObjectPointer(PUNICODE_STRING ObjectName, ACCESS_MASK DesiredAccess,
|
||||
PULONG PFileNameIndex, PFILE_OBJECT *PFileObject, PDEVICE_OBJECT *PDeviceObject);
|
||||
NTSTATUS FspMainStreamOpen(
|
||||
PDEVICE_OBJECT DeviceObject,
|
||||
PUNICODE_STRING MainStreamName, BOOLEAN CaseSensitive,
|
||||
ULONG Disposition,
|
||||
PHANDLE PMainStreamHandle,
|
||||
PFILE_OBJECT *PMainStreamObject);
|
||||
NTSTATUS FspMainStreamClose(
|
||||
HANDLE MainStreamHandle,
|
||||
PFILE_OBJECT MainStreamObject);
|
||||
NTSTATUS FspSendSetInformationIrp(PDEVICE_OBJECT DeviceObject, PFILE_OBJECT FileObject,
|
||||
FILE_INFORMATION_CLASS FileInformationClass, PVOID FileInformation, ULONG Length);
|
||||
static NTSTATUS FspSendSetInformationIrpCompletion(
|
||||
@ -93,6 +102,8 @@ NTSTATUS FspIrpHookNext(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context);
|
||||
#pragma alloc_text(PAGE, FspUnicodePathSuffix)
|
||||
#pragma alloc_text(PAGE, FspCreateGuid)
|
||||
#pragma alloc_text(PAGE, FspGetDeviceObjectPointer)
|
||||
#pragma alloc_text(PAGE, FspMainStreamOpen)
|
||||
#pragma alloc_text(PAGE, FspMainStreamClose)
|
||||
#pragma alloc_text(PAGE, FspSendSetInformationIrp)
|
||||
#pragma alloc_text(PAGE, FspBufferUserBuffer)
|
||||
#pragma alloc_text(PAGE, FspLockUserBuffer)
|
||||
@ -373,6 +384,108 @@ NTSTATUS FspGetDeviceObjectPointer(PUNICODE_STRING ObjectName, ACCESS_MASK Desir
|
||||
return Result;
|
||||
}
|
||||
|
||||
NTSTATUS FspMainStreamOpen(
|
||||
PDEVICE_OBJECT DeviceObject,
|
||||
PUNICODE_STRING MainStreamName, BOOLEAN CaseSensitive,
|
||||
ULONG Disposition,
|
||||
PHANDLE PMainStreamHandle,
|
||||
PFILE_OBJECT *PMainStreamObject)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
IO_STATUS_BLOCK IoStatus;
|
||||
HANDLE MainStreamHandle;
|
||||
PFILE_OBJECT MainStreamObject;
|
||||
|
||||
/* assert that the supplied name is actually a main stream name */
|
||||
ASSERT(FspUnicodePathIsValid(MainStreamName, 0));
|
||||
|
||||
*PMainStreamHandle = 0;
|
||||
*PMainStreamObject = 0;
|
||||
|
||||
switch (Disposition)
|
||||
{
|
||||
case FILE_CREATE:
|
||||
case FILE_OPEN_IF:
|
||||
case FILE_OVERWRITE_IF:
|
||||
Disposition = FILE_OPEN_IF;
|
||||
break;
|
||||
case FILE_OPEN:
|
||||
case FILE_OVERWRITE:
|
||||
case FILE_SUPERSEDE:
|
||||
Disposition = FILE_OPEN;
|
||||
break;
|
||||
default:
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
InitializeObjectAttributes(
|
||||
&ObjectAttributes,
|
||||
MainStreamName,
|
||||
OBJ_KERNEL_HANDLE | OBJ_FORCE_ACCESS_CHECK | (CaseSensitive ? 0 : OBJ_CASE_INSENSITIVE),
|
||||
0/*RootDirectory*/,
|
||||
0/*SecurityDescriptor*/);
|
||||
|
||||
IoStatus.Status = IoCreateFileSpecifyDeviceObjectHint(
|
||||
&MainStreamHandle,
|
||||
FILE_READ_ATTRIBUTES,
|
||||
&ObjectAttributes,
|
||||
&IoStatus,
|
||||
0/*AllocationSize*/,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||
Disposition,
|
||||
FILE_OPEN_REPARSE_POINT,
|
||||
0/*EaBuffer*/,
|
||||
0/*EaLength*/,
|
||||
CreateFileTypeNone,
|
||||
0/*InternalParameters*/,
|
||||
IO_FORCE_ACCESS_CHECK,
|
||||
DeviceObject);
|
||||
if (!NT_SUCCESS(IoStatus.Status))
|
||||
return IoStatus.Status;
|
||||
|
||||
IoStatus.Status = ObReferenceObjectByHandle(
|
||||
MainStreamHandle,
|
||||
0/*DesiredAccess*/,
|
||||
*IoFileObjectType,
|
||||
KernelMode,
|
||||
&MainStreamObject,
|
||||
0/*HandleInformation*/);
|
||||
if (!NT_SUCCESS(IoStatus.Status))
|
||||
{
|
||||
ObCloseHandle(MainStreamHandle, KernelMode);
|
||||
return IoStatus.Status;
|
||||
}
|
||||
|
||||
*PMainStreamHandle = MainStreamHandle;
|
||||
*PMainStreamObject = MainStreamObject;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS FspMainStreamClose(
|
||||
HANDLE MainStreamHandle,
|
||||
PFILE_OBJECT MainStreamObject)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
NTSTATUS Result = STATUS_SUCCESS;
|
||||
|
||||
if (0 != MainStreamObject)
|
||||
ObDereferenceObject(MainStreamObject);
|
||||
|
||||
if (0 != MainStreamHandle)
|
||||
{
|
||||
Result = ObCloseHandle(MainStreamHandle, KernelMode);
|
||||
if (!NT_SUCCESS(Result))
|
||||
DEBUGLOG("ObCloseHandle() = %s", NtStatusSym(Result));
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
IO_STATUS_BLOCK IoStatus;
|
||||
|
Loading…
x
Reference in New Issue
Block a user