diff --git a/inc/winfsp/winfsp.h b/inc/winfsp/winfsp.h index f4e32901..749f116f 100644 --- a/inc/winfsp/winfsp.h +++ b/inc/winfsp/winfsp.h @@ -22,14 +22,17 @@ #include /* - * File System + * File Nodes */ -typedef struct _FSP_FILE_SYSTEM FSP_FILE_SYSTEM; typedef struct _FSP_FILE_NODE { + /* public */ PVOID UserContext; UINT64 AllocationSize; UINT64 FileSize; + /* private */ + CRITICAL_SECTION CriticalSection; + LONG OpenCount; struct { BOOLEAN DeleteOnClose:1; @@ -46,6 +49,42 @@ typedef struct _FSP_FILE_NODE ULONG SharedDelete; } ShareAccess; } FSP_FILE_NODE; +static inline +VOID FspFileNodeInit(FSP_FILE_NODE *FileNode) +{ + memset(FileNode, 0, sizeof *FileNode); + InitializeCriticalSection(&FileNode->CriticalSection); +} +static inline +VOID FspFileNodeFini(FSP_FILE_NODE *FileNode) +{ + DeleteCriticalSection(&FileNode->CriticalSection); +} +static inline +VOID FspFileNodeLock(FSP_FILE_NODE *FileNode) +{ + EnterCriticalSection(&FileNode->CriticalSection); +} +static inline +VOID FspFileNodeUnlock(FSP_FILE_NODE *FileNode) +{ + LeaveCriticalSection(&FileNode->CriticalSection); +} +static inline +VOID FspFileNodeOpen(FSP_FILE_NODE *FileNode) +{ + InterlockedIncrement(&FileNode->OpenCount); +} +static inline +LONG FspFileNodeClose(FSP_FILE_NODE *FileNode) +{ + return InterlockedDecrement(&FileNode->OpenCount); +} + +/* + * File System + */ +typedef struct _FSP_FILE_SYSTEM FSP_FILE_SYSTEM; typedef VOID FSP_FILE_SYSTEM_DISPATCHER(FSP_FILE_SYSTEM *, FSP_FSCTL_TRANSACT_REQ *); typedef NTSTATUS FSP_FILE_SYSTEM_OPERATION(FSP_FILE_SYSTEM *, FSP_FSCTL_TRANSACT_REQ *); typedef struct _FSP_FILE_SYSTEM_INTERFACE @@ -59,9 +98,9 @@ typedef struct _FSP_FILE_SYSTEM_INTERFACE FSP_FSCTL_TRANSACT_REQ *Request, FSP_FILE_NODE **PFileNode); NTSTATUS (*Overwrite)(FSP_FILE_SYSTEM *FileSystem, FSP_FSCTL_TRANSACT_REQ *Request, BOOLEAN ReplaceFileAttributes, FSP_FILE_NODE *FileNode); - NTSTATUS (*Cleanup)(FSP_FILE_SYSTEM *FileSystem, - FSP_FSCTL_TRANSACT_REQ *Request, FSP_FILE_NODE *FileNode); - NTSTATUS (*Close)(FSP_FILE_SYSTEM *FileSystem, + VOID (*Cleanup)(FSP_FILE_SYSTEM *FileSystem, + FSP_FSCTL_TRANSACT_REQ *Request, FSP_FILE_NODE *FileNode, BOOLEAN Delete); + VOID (*Close)(FSP_FILE_SYSTEM *FileSystem, FSP_FSCTL_TRANSACT_REQ *Request, FSP_FILE_NODE *FileNode); } FSP_FILE_SYSTEM_INTERFACE; typedef struct _FSP_FILE_SYSTEM diff --git a/src/dll/cleanup.c b/src/dll/cleanup.c index 5f1fa5a2..04155d86 100644 --- a/src/dll/cleanup.c +++ b/src/dll/cleanup.c @@ -13,8 +13,22 @@ FSP_API NTSTATUS FspFileSystemOpCleanup(FSP_FILE_SYSTEM *FileSystem, return FspFileSystemSendResponseWithStatus(FileSystem, Request, STATUS_INVALID_DEVICE_REQUEST); FSP_FILE_NODE *FileNode = (PVOID)Request->Req.Close.UserContext; + BOOLEAN DeletePending; + LONG OpenCount; - FileSystem->Interface->Cleanup(FileSystem, Request, FileNode); + FspFileNodeLock(FileNode); + + /* propagate the DeleteOnClose flag to DeletePending */ + if (FileNode->Flags.DeleteOnClose) + FileNode->Flags.DeletePending = TRUE; + DeletePending = FileNode->Flags.DeletePending; + + /* all handles on the kernel FILE_OBJECT gone; decrement the FileNode's OpenCount */ + OpenCount = FspFileNodeClose(FileNode); + + FspFileNodeUnlock(FileNode); + + FileSystem->Interface->Cleanup(FileSystem, Request, FileNode, 0 == OpenCount && DeletePending); return FspFileSystemSendCleanupResponse(FileSystem, Request); } diff --git a/src/dll/create.c b/src/dll/create.c index 4362a408..b6fab821 100644 --- a/src/dll/create.c +++ b/src/dll/create.c @@ -238,13 +238,16 @@ FSP_API NTSTATUS FspFileSystemPreCreateCheck(FSP_FILE_SYSTEM *FileSystem, FSP_API VOID FspFileSystemPostCreateCheck(FSP_FILE_SYSTEM *FileSystem, FSP_FSCTL_TRANSACT_REQ *Request, DWORD GrantedAccess, FSP_FILE_NODE *FileNode) { - memset(&FileNode->Flags, 0, sizeof FileNode->Flags); - memset(&FileNode->ShareAccess, 0, sizeof FileNode->ShareAccess); + FspFileNodeLock(FileNode); FspShareCheck(FileSystem, Request, GrantedAccess, FileNode); if (Request->Req.Create.CreateOptions & FILE_DELETE_ON_CLOSE) FileNode->Flags.DeleteOnClose = TRUE; + + FspFileNodeOpen(FileNode); + + FspFileNodeUnlock(FileNode); } FSP_API NTSTATUS FspFileSystemPreOpenCheck(FSP_FILE_SYSTEM *FileSystem, @@ -259,15 +262,27 @@ FSP_API NTSTATUS FspFileSystemPostOpenCheck(FSP_FILE_SYSTEM *FileSystem, { NTSTATUS Result; + FspFileNodeLock(FileNode); + if (FileNode->Flags.DeletePending) - return STATUS_DELETE_PENDING; + { + Result = STATUS_DELETE_PENDING; + goto exit; + } Result = FspShareCheck(FileSystem, Request, GrantedAccess, FileNode); if (!NT_SUCCESS(Result)) - return Result; + goto exit; if (Request->Req.Create.CreateOptions & FILE_DELETE_ON_CLOSE) FileNode->Flags.DeleteOnClose = TRUE; + + FspFileNodeOpen(FileNode); + +exit: + FspFileNodeUnlock(FileNode); + + return Result; } FSP_API NTSTATUS FspFileSystemPreOverwriteCheck(FSP_FILE_SYSTEM *FileSystem,