From 0d49e87468ebc2ba7b83562e8408ce64dc820bd5 Mon Sep 17 00:00:00 2001 From: Bill Zissimopoulos Date: Sat, 5 Dec 2015 11:31:51 -0800 Subject: [PATCH] sys: IRP_MJ_CREATE --- build/VStudio/winfsp.sln | 3 +++ src/sys/create.c | 26 +++++++++++++++++++++----- src/sys/driver.h | 25 +++++++++++++++++++++---- src/sys/fileobj.c | 1 + 4 files changed, 46 insertions(+), 9 deletions(-) diff --git a/build/VStudio/winfsp.sln b/build/VStudio/winfsp.sln index 16057469..323f8695 100644 --- a/build/VStudio/winfsp.sln +++ b/build/VStudio/winfsp.sln @@ -4,6 +4,9 @@ Microsoft Visual Studio Solution File, Format Version 12.00 VisualStudioVersion = 14.0.23107.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "winfsp.dll", "winfsp_dll.vcxproj", "{4A7C0B21-9E10-4C81-92DE-1493EFCF24EB}" + ProjectSection(ProjectDependencies) = postProject + {C85C26BA-8C22-4D30-83DA-46C3548E6332} = {C85C26BA-8C22-4D30-83DA-46C3548E6332} + EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "winfsp.sys", "winfsp_sys.vcxproj", "{C85C26BA-8C22-4D30-83DA-46C3548E6332}" EndProject diff --git a/src/sys/create.c b/src/sys/create.c index 5710cc65..463b487d 100644 --- a/src/sys/create.c +++ b/src/sys/create.c @@ -403,7 +403,7 @@ VOID FspFsvolCreateComplete( FsContext->UserContext = Response->Rsp.Create.UserContext; FileObject->FsContext2 = (PVOID)(UINT_PTR)Response->Rsp.Create.UserContext2; - /* following must be performed under the fsvol lock */ + /* lock the file system volume device while accessing its generic table */ ExAcquireResourceExclusiveLite(&FsvolDeviceExtension->Base.Resource, TRUE); try { @@ -415,19 +415,34 @@ VOID FspFsvolCreateComplete( Result = STATUS_INSUFFICIENT_RESOURCES; else { - /* do the share access checks */ + /* share access check */ if (Inserted) { + /* + * This is a newly created FsContext. Set its share access and + * increment its open count. There is no need to acquire the + * FsContext's Resource (because it is newly created). + */ IoSetShareAccess(DesiredAccess, ShareAccess, FileObject, &FsContext->ShareAccess); FspFileContextOpen(FsContext); } else { - Result = IoCheckShareAccess(DesiredAccess, ShareAccess, FileObject, - &FsContext->ShareAccess, TRUE); + /* + * This is an existing FsContext. We must acquire its Resource and + * check if there is a delete pending and the share access. Only if + * both tests succeed we increment the open count and report success. + */ + ExAcquireResourceExclusiveLite(FsContext->Header.Resource, TRUE); + if (FsContext->DeletePending) + Result = STATUS_DELETE_PENDING; + else + Result = IoCheckShareAccess(DesiredAccess, ShareAccess, FileObject, + &FsContext->ShareAccess, TRUE); if (NT_SUCCESS(Result)) FspFileContextOpen(FsContext); + ExReleaseResourceLite(FsContext->Header.Resource); } } } @@ -444,9 +459,10 @@ VOID FspFsvolCreateComplete( FSP_RETURN(); } - /* does an FsContext with the same UserContext already exist? */ + /* did an FsContext with the same UserContext already exist? */ if (!Inserted) { + /* delete the newly created FsContext and use the existing one */ FspFileContextDelete(FileObject->FsContext); FileObject->FsContext = FsContext; } diff --git a/src/sys/driver.h b/src/sys/driver.h index a71c9610..0f2c39e2 100644 --- a/src/sys/driver.h +++ b/src/sys/driver.h @@ -363,9 +363,13 @@ typedef struct { FSRTL_ADVANCED_FCB_HEADER Header; FSP_FILE_CONTEXT_NONPAGED *NonPaged; + /* interlocked access */ + LONG RefCount; + /* protected by Header.Resource */ LONG OpenCount; SHARE_ACCESS ShareAccess; - /* protected by containing fsvol lock */ + BOOLEAN DeletePending; + /* read-only after creation */ UINT64 UserContext; UNICODE_STRING FileName; WCHAR FileNameBuf[]; @@ -375,13 +379,26 @@ VOID FspFileContextDelete(FSP_FILE_CONTEXT *Context); static inline VOID FspFileContextOpen(FSP_FILE_CONTEXT *Context) { - InterlockedIncrement(&Context->OpenCount); + ASSERT(0 == Context->OpenCount || ExIsResourceAcquiredExclusiveLite(Context->Header.Resource)); + Context->OpenCount++; } static inline VOID FspFileContextClose(FSP_FILE_CONTEXT *Context) { - LONG Result = InterlockedDecrement(&Context->OpenCount); - if (0 == Result) + ASSERT(ExIsResourceAcquiredExclusiveLite(Context->Header.Resource)); + ASSERT(0 < Context->OpenCount); + Context->OpenCount--; +} +static inline +VOID FspFileContextRetain(FSP_FILE_CONTEXT *Context) +{ + InterlockedIncrement(&Context->RefCount); +} +static inline +VOID FspFileContextRelease(FSP_FILE_CONTEXT *Context) +{ + LONG RefCount = InterlockedDecrement(&Context->RefCount); + if (0 == RefCount) FspFileContextDelete(Context); } diff --git a/src/sys/fileobj.c b/src/sys/fileobj.c index cc13d875..eeef9e5f 100644 --- a/src/sys/fileobj.c +++ b/src/sys/fileobj.c @@ -46,6 +46,7 @@ NTSTATUS FspFileContextCreate(ULONG ExtraSize, FSP_FILE_CONTEXT **PFsContext) FsContext->Header.PagingIoResource = &NonPaged->PagingIoResource; FsRtlSetupAdvancedHeader(&FsContext->Header, &NonPaged->HeaderFastMutex); FsContext->NonPaged = NonPaged; + FsContext->RefCount = 1; RtlInitEmptyUnicodeString(&FsContext->FileName, FsContext->FileNameBuf, (USHORT)ExtraSize); *PFsContext = FsContext;