From 727975e20670e5ec9364d9270900b133f4cf003b Mon Sep 17 00:00:00 2001 From: Bill Zissimopoulos Date: Tue, 19 Jan 2016 17:38:12 -0800 Subject: [PATCH] sys: FileDesc now stored for FileObject (in FsContext2) --- build/VStudio/winfsp_sys.vcxproj | 2 +- build/VStudio/winfsp_sys.vcxproj.filters | 2 +- inc/winfsp/fsctl.h | 4 +- src/sys/cleanup.c | 9 +- src/sys/close.c | 15 +-- src/sys/create.c | 138 +++++++++++++---------- src/sys/debug.c | 1 + src/sys/driver.h | 7 ++ src/sys/{node.c => file.c} | 27 ++++- 9 files changed, 126 insertions(+), 79 deletions(-) rename src/sys/{node.c => file.c} (94%) diff --git a/build/VStudio/winfsp_sys.vcxproj b/build/VStudio/winfsp_sys.vcxproj index 33acd7a6..64f24555 100644 --- a/build/VStudio/winfsp_sys.vcxproj +++ b/build/VStudio/winfsp_sys.vcxproj @@ -156,7 +156,7 @@ - + diff --git a/build/VStudio/winfsp_sys.vcxproj.filters b/build/VStudio/winfsp_sys.vcxproj.filters index 4f5dfceb..d73bf222 100644 --- a/build/VStudio/winfsp_sys.vcxproj.filters +++ b/build/VStudio/winfsp_sys.vcxproj.filters @@ -83,7 +83,7 @@ Source - + Source diff --git a/inc/winfsp/fsctl.h b/inc/winfsp/fsctl.h index 28a816fd..740d66a4 100644 --- a/inc/winfsp/fsctl.h +++ b/inc/winfsp/fsctl.h @@ -164,8 +164,8 @@ typedef struct /* IoStatus.Status == STATUS_SUCCESS */ struct { - UINT64 UserContext; /* open file user context (unique file id) */ - UINT64 UserContext2; /* kernel file object user context (stores as many bits as a pointer) */ + UINT64 UserContext; /* user context (unique file id) associated with file node */ + UINT64 UserContext2; /* user context associated with file descriptor (handle) */ UINT32 FileAttributes; /* FILE_ATTRIBUTE_{NORMAL,DIRECTORY,etc.} */ UINT64 AllocationSize; /* file allocation size */ UINT64 FileSize; /* file size */ diff --git a/src/sys/cleanup.c b/src/sys/cleanup.c index eab5fcf2..123b3fe9 100644 --- a/src/sys/cleanup.c +++ b/src/sys/cleanup.c @@ -57,8 +57,7 @@ static NTSTATUS FspFsvolCleanup( BOOLEAN FileNameRequired = 0 != FsvolDeviceExtension->VolumeParams.FileNameRequired; PFILE_OBJECT FileObject = IrpSp->FileObject; FSP_FILE_NODE *FileNode = FileObject->FsContext; - UINT64 UserContext = FileNode->UserContext; - UINT64 UserContext2 = (UINT_PTR)FileObject->FsContext2; + FSP_FILE_DESC *FileDesc = FileObject->FsContext2; FSP_FSCTL_TRANSACT_REQ *Request; BOOLEAN DeletePending; @@ -66,11 +65,9 @@ static NTSTATUS FspFsvolCleanup( /* create the user-mode file system request; MustSucceed because IRP_MJ_CLEANUP cannot fail */ FspIopCreateRequestMustSucceed(Irp, FileNameRequired ? &FileNode->FileName : 0, 0, &Request); - - /* populate the Cleanup request */ Request->Kind = FspFsctlTransactCleanupKind; - Request->Req.Cleanup.UserContext = UserContext; - Request->Req.Cleanup.UserContext2 = UserContext2; + Request->Req.Cleanup.UserContext = FileNode->UserContext; + Request->Req.Cleanup.UserContext2 = FileDesc->UserContext2; Request->Req.Cleanup.Delete = DeletePending; return FSP_STATUS_IOQ_POST_BEST_EFFORT; diff --git a/src/sys/close.c b/src/sys/close.c index f07920aa..54044e5f 100644 --- a/src/sys/close.c +++ b/src/sys/close.c @@ -54,20 +54,17 @@ static NTSTATUS FspFsvolClose( BOOLEAN FileNameRequired = 0 != FsvolDeviceExtension->VolumeParams.FileNameRequired; PFILE_OBJECT FileObject = IrpSp->FileObject; FSP_FILE_NODE *FileNode = FileObject->FsContext; - UINT64 UserContext = FileNode->UserContext; - UINT64 UserContext2 = (UINT_PTR)FileObject->FsContext2; + FSP_FILE_DESC *FileDesc = FileObject->FsContext2; FSP_FSCTL_TRANSACT_REQ *Request; - /* dereference the FileNode (and delete if no more references) */ - FspFileNodeDereference(FileNode); - /* create the user-mode file system request; MustSucceed because IRP_MJ_CLOSE cannot fail */ FspIopCreateRequestMustSucceed(0, FileNameRequired ? &FileNode->FileName : 0, 0, &Request); - - /* populate the Close request */ Request->Kind = FspFsctlTransactCloseKind; - Request->Req.Close.UserContext = UserContext; - Request->Req.Close.UserContext2 = UserContext2; + Request->Req.Close.UserContext = FileNode->UserContext; + Request->Req.Close.UserContext2 = FileDesc->UserContext2; + + FspFileNodeDereference(FileNode); + FspFileDescDelete(FileDesc); /* * Post as a BestEffort work request. This allows us to complete our own IRP diff --git a/src/sys/create.c b/src/sys/create.c index f506723e..32a8eff0 100644 --- a/src/sys/create.c +++ b/src/sys/create.c @@ -14,8 +14,7 @@ static NTSTATUS FspFsvolCreate( PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp); FSP_IOPREP_DISPATCH FspFsvolCreatePrepare; FSP_IOCMPL_DISPATCH FspFsvolCreateComplete; -static VOID FspFsvolCreatePostClose( - FSP_FILE_NODE *FileNode, UINT64 UserContext2); +static VOID FspFsvolCreatePostClose(FSP_FILE_DESC *FileDesc); static FSP_IOP_REQUEST_FINI FspFsvolCreateRequestFini; static FSP_IOP_REQUEST_FINI FspFsvolCreateOverwriteRequestFini; FSP_DRIVER_DISPATCH FspCreate; @@ -38,12 +37,17 @@ FSP_DRIVER_DISPATCH FspCreate; enum { /* CreateRequest */ - RequestFileNode = 0, + RequestFileDesc = 0, RequestAccessToken = 1, RequestProcess = 2, /* OverwriteRequest */ - //RequestFileNode = 0, + //RequestFileDesc = 0, RequestFileObject = 1, + RequestStatus = 2, + + /* RequestFiniAction */ + RequestPending = 0, + RequestProcessing = 1, }; static NTSTATUS FspFsctlCreate( @@ -118,6 +122,7 @@ static NTSTATUS FspFsvolCreate( BOOLEAN IsSelfRelativeSecurityDescriptor = FALSE; BOOLEAN HasTrailingBackslash = FALSE; FSP_FILE_NODE *FileNode, *RelatedFileNode; + FSP_FILE_DESC *FileDesc; FSP_FSCTL_TRANSACT_REQ *Request; /* cannot open files by fileid */ @@ -262,21 +267,30 @@ static NTSTATUS FspFsvolCreate( Result = RtlAppendUnicodeStringToString(&FileNode->FileName, &FileName); ASSERT(NT_SUCCESS(Result)); - /* create the user-mode file system request */ - Result = FspIopCreateRequestEx(Irp, &FileNode->FileName, SecurityDescriptorSize, - FspFsvolCreateRequestFini, &Request); + Result = FspFileDescCreate(&FileDesc); if (!NT_SUCCESS(Result)) { FspFileNodeDereference(FileNode); return Result; } + /* create the user-mode file system request */ + Result = FspIopCreateRequestEx(Irp, &FileNode->FileName, SecurityDescriptorSize, + FspFsvolCreateRequestFini, &Request); + if (!NT_SUCCESS(Result)) + { + FspFileDescDelete(FileDesc); + FspFileNodeDereference(FileNode); + return Result; + } + /* - * The new request is associated with our IRP. Go ahead and associate our FileNode + * The new request is associated with our IRP. Go ahead and associate our FileNode/FileDesc * with the Request as well. After this is done completing our IRP will automatically * delete the Request and any associated resources. */ - FspIopRequestContext(Request, RequestFileNode) = FileNode; + FileDesc->FileNode = FileNode; + FspIopRequestContext(Request, RequestFileDesc) = FileDesc; /* populate the Create request */ Request->Kind = FspFsctlTransactCreateKind; @@ -329,6 +343,7 @@ NTSTATUS FspFsvolCreatePrepare( HANDLE UserModeAccessToken; PEPROCESS Process; FSP_FILE_NODE *FileNode; + FSP_FILE_DESC *FileDesc; PFILE_OBJECT FileObject; if (FspFsctlTransactCreateKind == Request->Kind) @@ -370,7 +385,8 @@ NTSTATUS FspFsvolCreatePrepare( } else if (FspFsctlTransactOverwriteKind == Request->Kind) { - FileNode = FspIopRequestContext(Request, RequestFileNode); + FileDesc = FspIopRequestContext(Request, RequestFileDesc); + FileNode = FileDesc->FileNode; FileObject = FspIopRequestContext(Request, RequestFileObject); /* lock the FileNode for overwriting */ @@ -384,9 +400,6 @@ NTSTATUS FspFsvolCreatePrepare( return Result; } - /* no longer post a Close if the IRP gets cancelled */ - FspIopRequestContext(Request, RequestFileObject) = 0; - /* see what the MM thinks about all this */ LARGE_INTEGER Zero = { 0 }; Success = MmCanFileBeTruncated(&FileNode->NonPaged->SectionObjectPointers, &Zero); @@ -394,12 +407,11 @@ NTSTATUS FspFsvolCreatePrepare( { FspFileNodeRelease(FileNode, Both); - FspFsvolCreatePostClose(FileNode, (UINT_PTR)FileObject->FsContext2); - FspFileNodeClose(FileNode, FileObject, 0); - return STATUS_USER_MAPPED_FILE; } + FspIopRequestContext(Request, RequestStatus) = (PVOID)RequestProcessing; + /* purge any caches on this file */ CcPurgeCacheSection(&FileNode->NonPaged->SectionObjectPointers, 0, 0, FALSE); @@ -422,7 +434,8 @@ VOID FspFsvolCreateComplete( FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject); PFILE_OBJECT FileObject = IrpSp->FileObject; FSP_FSCTL_TRANSACT_REQ *Request = FspIrpRequest(Irp); - FSP_FILE_NODE *FileNode = FspIopRequestContext(Request, RequestFileNode); + FSP_FILE_DESC *FileDesc = FspIopRequestContext(Request, RequestFileDesc); + FSP_FILE_NODE *FileNode = FileDesc->FileNode; FSP_FILE_NODE *OpenedFileNode; UNICODE_STRING ReparseFileName; BOOLEAN DeleteOnClose; @@ -494,10 +507,11 @@ VOID FspFsvolCreateComplete( FSP_RETURN(); } - /* populate the FileNode fields from the Response */ + /* populate the FileNode/FileDesc fields from the Response */ FileNode->Header.AllocationSize.QuadPart = Response->Rsp.Create.Opened.AllocationSize; FileNode->Header.FileSize.QuadPart = Response->Rsp.Create.Opened.FileSize; FileNode->UserContext = Response->Rsp.Create.Opened.UserContext; + FileDesc->UserContext2 = Response->Rsp.Create.Opened.UserContext2; DeleteOnClose = BooleanFlagOn(Request->Req.Create.CreateOptions, FILE_DELETE_ON_CLOSE); @@ -509,13 +523,16 @@ VOID FspFsvolCreateComplete( if (0 == OpenedFileNode) { /* unable to open the FileNode; post a Close request */ - FspFsvolCreatePostClose(FileNode, - Response->Rsp.Create.Opened.UserContext2); + FspFsvolCreatePostClose(FileDesc); FSP_RETURN(); } - FileNode = OpenedFileNode; + if (FileNode != OpenedFileNode) + { + FspFileNodeDereference(FileNode); + FileDesc->FileNode = FileNode = OpenedFileNode; + } /* set up the FileObject */ if (0 != FsvolDeviceExtension->FsvrtDeviceObject) @@ -524,7 +541,7 @@ VOID FspFsvolCreateComplete( FileObject->SectionObjectPointer = &FileNode->NonPaged->SectionObjectPointers; FileObject->PrivateCacheMap = 0; FileObject->FsContext = FileNode; - FileObject->FsContext2 = (PVOID)(UINT_PTR)Response->Rsp.Create.Opened.UserContext2; + FileObject->FsContext2 = FileDesc; if (FILE_OPENED == Response->IoStatus.Information) { @@ -543,8 +560,7 @@ VOID FspFsvolCreateComplete( if (!MmFlushImageSection(&FileNode->NonPaged->SectionObjectPointers, MmFlushForWrite)) { - FspFsvolCreatePostClose(FileNode, - Response->Rsp.Create.Opened.UserContext2); + FspFsvolCreatePostClose(FileDesc); FspFileNodeClose(FileNode, FileObject, 0); Result = DeleteOnClose ? STATUS_CANNOT_DELETE : STATUS_SHARING_VIOLATION; @@ -553,7 +569,7 @@ VOID FspFsvolCreateComplete( } /* SUCCESS! */ - FspIopRequestContext(Request, RequestFileNode) = 0; + FspIopRequestContext(Request, RequestFileDesc) = 0; Irp->IoStatus.Information = (ULONG_PTR)Response->IoStatus.Information; Result = STATUS_SUCCESS; } @@ -567,6 +583,8 @@ VOID FspFsvolCreateComplete( /* delete the old request */ FspIrpRequest(Irp) = 0; + FspIopRequestContext(Request, RequestFileDesc) = 0; + /* disassociate the FileDesc from the old Request as we want to keep it around! */ FspIopDeleteRequest(Request); /* create the Overwrite request; MustSucceed because we must either overwrite or close */ @@ -575,14 +593,15 @@ VOID FspFsvolCreateComplete( FspFsvolCreateOverwriteRequestFini, TRUE, &Request); - /* associate the FileNode and FileObject with the Overwrite request */ - FspIopRequestContext(Request, RequestFileNode) = FileNode; + /* associate the FileDesc and FileObject with the Overwrite request */ + FspIopRequestContext(Request, RequestFileDesc) = FileDesc; FspIopRequestContext(Request, RequestFileObject) = FileObject; + FspIopRequestContext(Request, RequestStatus) = (PVOID)RequestPending; /* populate the Overwrite request */ Request->Kind = FspFsctlTransactOverwriteKind; Request->Req.Overwrite.UserContext = FileNode->UserContext; - Request->Req.Overwrite.UserContext2 = (UINT_PTR)FileObject->FsContext2; + Request->Req.Overwrite.UserContext2 = FileDesc->UserContext2; Request->Req.Overwrite.FileAttributes = IrpSp->Parameters.Create.FileAttributes; Request->Req.Overwrite.Supersede = FILE_SUPERSEDED == Response->IoStatus.Information; @@ -597,7 +616,7 @@ VOID FspFsvolCreateComplete( else { /* SUCCESS! */ - FspIopRequestContext(Request, RequestFileNode) = 0; + FspIopRequestContext(Request, RequestFileDesc) = 0; Irp->IoStatus.Information = (ULONG_PTR)Response->IoStatus.Information; Result = STATUS_SUCCESS; } @@ -612,10 +631,6 @@ VOID FspFsvolCreateComplete( /* did the user-mode file system sent us a failure code? */ if (!NT_SUCCESS(Response->IoStatus.Status)) { - FspFileNodeRelease(FileNode, Both); - - FspFileNodeClose(FileNode, FileObject, 0); - Irp->IoStatus.Information = 0; Result = Response->IoStatus.Status; FSP_RETURN(); @@ -629,7 +644,7 @@ VOID FspFsvolCreateComplete( FspFileNodeRelease(FileNode, Both); /* SUCCESS! */ - FspIopRequestContext(Request, RequestFileNode) = 0; + FspIopRequestContext(Request, RequestFileDesc) = 0; Irp->IoStatus.Information = Request->Req.Overwrite.Supersede ? FILE_SUPERSEDED : FILE_OVERWRITTEN; Result = STATUS_SUCCESS; } @@ -641,11 +656,11 @@ VOID FspFsvolCreateComplete( IrpSp->FileObject, IrpSp->FileObject->RelatedFileObject, IrpSp->FileObject->FileName); } -static VOID FspFsvolCreatePostClose( - FSP_FILE_NODE *FileNode, UINT64 UserContext2) +static VOID FspFsvolCreatePostClose(FSP_FILE_DESC *FileDesc) { PAGED_CODE(); + FSP_FILE_NODE *FileNode = FileDesc->FileNode; PDEVICE_OBJECT FsvolDeviceObject = FileNode->FsvolDeviceObject; FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject); FSP_FSCTL_TRANSACT_REQ *Request; @@ -658,7 +673,7 @@ static VOID FspFsvolCreatePostClose( /* populate the Close request */ Request->Kind = FspFsctlTransactCloseKind; Request->Req.Close.UserContext = FileNode->UserContext; - Request->Req.Close.UserContext2 = UserContext2; + Request->Req.Close.UserContext2 = FileDesc->UserContext2; /* * Post as a BestEffort work request. This allows us to complete our own IRP @@ -678,15 +693,18 @@ static VOID FspFsvolCreateRequestFini(PVOID Context[3]) { PAGED_CODE(); - if (0 != Context[RequestFileNode]) + FSP_FILE_DESC *FileDesc = Context[RequestFileDesc]; + HANDLE AccessToken = Context[RequestAccessToken]; + PEPROCESS Process = Context[RequestProcess]; + + if (0 != FileDesc) { - FspFileNodeDereference(Context[RequestFileNode]); - Context[RequestFileNode] = 0; + FspFileNodeDereference(FileDesc->FileNode); + FspFileDescDelete(FileDesc); } - if (0 != Context[RequestAccessToken]) + if (0 != AccessToken) { - PEPROCESS Process = Context[RequestProcess]; KAPC_STATE ApcState; BOOLEAN Attach; @@ -697,42 +715,44 @@ static VOID FspFsvolCreateRequestFini(PVOID Context[3]) KeStackAttachProcess(Process, &ApcState); #if DBG NTSTATUS Result0; - Result0 = ObCloseHandle(Context[RequestAccessToken], UserMode); + Result0 = ObCloseHandle(AccessToken, UserMode); if (!NT_SUCCESS(Result0)) DEBUGLOG("ObCloseHandle() = %s", NtStatusSym(Result0)); #else - ObCloseHandle(Context[RequestAccessToken], UserMode); + ObCloseHandle(AccessToken, UserMode); #endif if (Attach) KeUnstackDetachProcess(&ApcState); ObDereferenceObject(Process); - - Context[RequestAccessToken] = 0; - Context[RequestProcess] = 0; } + + Context[RequestFileDesc] = Context[RequestAccessToken] = Context[RequestProcess] = 0; } static VOID FspFsvolCreateOverwriteRequestFini(PVOID Context[3]) { PAGED_CODE(); - if (0 != Context[RequestFileNode]) + FSP_FILE_DESC *FileDesc = Context[RequestFileDesc]; + PFILE_OBJECT FileObject = Context[RequestFileObject]; + ULONG Status = (ULONG)(UINT_PTR)Context[RequestStatus]; + + if (0 != FileDesc) { - FSP_FILE_NODE *FileNode = Context[RequestFileNode]; - PFILE_OBJECT FileObject = Context[RequestFileObject]; + ASSERT(0 != FileObject); - if (0 != FileObject) - { - FspFsvolCreatePostClose(FileNode, (UINT_PTR)FileObject->FsContext2); - FspFileNodeClose(FileNode, FileObject, 0); - } + if (RequestPending == Status) + FspFsvolCreatePostClose(FileDesc); + else if (RequestProcessing == Status) + FspFileNodeRelease(FileDesc->FileNode, Both); - FspFileNodeDereference(FileNode); - - Context[RequestFileObject] = 0; - Context[RequestFileNode] = 0; + FspFileNodeClose(FileDesc->FileNode, FileObject, 0); + FspFileNodeDereference(FileDesc->FileNode); + FspFileDescDelete(FileDesc); } + + Context[RequestFileDesc] = Context[RequestFileObject] = 0; } NTSTATUS FspCreate( diff --git a/src/sys/debug.c b/src/sys/debug.c index 229bc2d7..ae7c8777 100644 --- a/src/sys/debug.c +++ b/src/sys/debug.c @@ -160,6 +160,7 @@ const char *IoctlCodeSym(ULONG ControlCode) SYM(FSP_FSCTL_VOLUME_NAME) SYM(FSP_FSCTL_TRANSACT) SYM(FSP_FSCTL_WORK) + SYM(FSP_FSCTL_WORK_BEST_EFFORT) // cygwin: sed -n '/[IF][OS]CTL.*CTL_CODE/s/^#define[ \t]*\([^ \t]*\).*/SYM(\1)/p' #include "ioctl.i" default: diff --git a/src/sys/driver.h b/src/sys/driver.h index 1bba4ca9..8c1b4fc9 100644 --- a/src/sys/driver.h +++ b/src/sys/driver.h @@ -547,6 +547,11 @@ typedef struct UNICODE_STRING FileName; WCHAR FileNameBuf[]; } FSP_FILE_NODE; +typedef struct +{ + FSP_FILE_NODE *FileNode; + UINT64 UserContext2; +} FSP_FILE_DESC; NTSTATUS FspFileNodeCreate(PDEVICE_OBJECT DeviceObject, ULONG ExtraSize, FSP_FILE_NODE **PFileNode); VOID FspFileNodeDelete(FSP_FILE_NODE *FileNode); @@ -571,6 +576,8 @@ FSP_FILE_NODE *FspFileNodeOpen(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject, DWORD GrantedAccess, DWORD ShareAccess, BOOLEAN DeleteOnClose, NTSTATUS *PResult); VOID FspFileNodeClose(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject, PBOOLEAN PDeletePending); +NTSTATUS FspFileDescCreate(FSP_FILE_DESC **PFileDesc); +VOID FspFileDescDelete(FSP_FILE_DESC *FileDesc); #define FspFileNodeAcquireShared(N,F) FspFileNodeAcquireShared(N, FspFileNodeAcquire ## F) #define FspFileNodeTryAcquireShared(N,F) FspFileNodeTryAcquireShared(N, FspFileNodeAcquire ## F) #define FspFileNodeAcquireExclusive(N,F) FspFileNodeAcquireExclusive(N, FspFileNodeAcquire ## F) diff --git a/src/sys/node.c b/src/sys/file.c similarity index 94% rename from src/sys/node.c rename to src/sys/file.c index 0e375916..cdf5fcc2 100644 --- a/src/sys/node.c +++ b/src/sys/file.c @@ -1,5 +1,5 @@ /** - * @file sys/node.c + * @file sys/file.c * * @copyright 2015 Bill Zissimopoulos */ @@ -25,6 +25,9 @@ FSP_FILE_NODE *FspFileNodeOpen(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject, VOID FspFileNodeClose(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject, PBOOLEAN PDeletePending); +NTSTATUS FspFileDescCreate(FSP_FILE_DESC **PFileDesc); +VOID FspFileDescDelete(FSP_FILE_DESC *FileDesc); + #ifdef ALLOC_PRAGMA #pragma alloc_text(PAGE, FspFileNodeCreate) #pragma alloc_text(PAGE, FspFileNodeDelete) @@ -35,6 +38,8 @@ VOID FspFileNodeClose(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject, #pragma alloc_text(PAGE, FspFileNodeRelease) #pragma alloc_text(PAGE, FspFileNodeOpen) #pragma alloc_text(PAGE, FspFileNodeClose) +#pragma alloc_text(PAGE, FspFileDescCreate) +#pragma alloc_text(PAGE, FspFileDescDelete) #endif NTSTATUS FspFileNodeCreate(PDEVICE_OBJECT DeviceObject, @@ -306,3 +311,23 @@ VOID FspFileNodeClose(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject, if (0 != PDeletePending) *PDeletePending = Deleted && DeletePending; } + +NTSTATUS FspFileDescCreate(FSP_FILE_DESC **PFileDesc) +{ + PAGED_CODE(); + + *PFileDesc = FspAlloc(sizeof(FSP_FILE_DESC)); + if (0 == *PFileDesc) + return STATUS_INSUFFICIENT_RESOURCES; + + RtlZeroMemory(*PFileDesc, sizeof(FSP_FILE_DESC)); + + return STATUS_SUCCESS; +} + +VOID FspFileDescDelete(FSP_FILE_DESC *FileDesc) +{ + PAGED_CODE(); + + FspFree(FileDesc); +}