From e3c04e15baeecf0c1708aaf0da24460c21349cd9 Mon Sep 17 00:00:00 2001 From: Bill Zissimopoulos Date: Thu, 24 Dec 2015 15:46:54 -0800 Subject: [PATCH] Major refactoring: IRP_MJ_CREATE --- inc/winfsp/fsctl.h | 2 +- src/sys/create.c | 106 ++++++++++++++++++++++++++++++++++++++++++++- src/sys/driver.h | 73 +++++++++---------------------- 3 files changed, 126 insertions(+), 55 deletions(-) diff --git a/inc/winfsp/fsctl.h b/inc/winfsp/fsctl.h index c48e34b4..625657b8 100644 --- a/inc/winfsp/fsctl.h +++ b/inc/winfsp/fsctl.h @@ -123,7 +123,6 @@ typedef struct { UINT64 UserContext; UINT64 UserContext2; - UINT32 Delete:1; /* if set, the file or directory must be deleted */ } Cleanup; struct { @@ -154,6 +153,7 @@ typedef struct { UINT64 UserContext; /* open file user context (unique file id) */ UINT64 UserContext2; /* kernel file object user context (only low 32 bits valid) */ + UINT32 GrantedAccess; /* FILE_{READ_DATA,WRITE_DATA,etc.} */ } Opened; /* IoStatus.Status == STATUS_REPARSE */ struct diff --git a/src/sys/create.c b/src/sys/create.c index 3617847a..c9cbf765 100644 --- a/src/sys/create.c +++ b/src/sys/create.c @@ -105,7 +105,7 @@ static NTSTATUS FspFsvolCreate( BOOLEAN IsAbsoluteSecurityDescriptor = FALSE; BOOLEAN IsSelfRelativeSecurityDescriptor = FALSE; BOOLEAN HasTrailingBackslash = FALSE; - FSP_FILE_CONTEXT *FsContext = 0, *RelatedFsContext; + FSP_FILE_CONTEXT *FsContext, *RelatedFsContext; FSP_FSCTL_TRANSACT_REQ *Request; /* cannot open files by fileid */ @@ -313,6 +313,110 @@ VOID FspFsvolCreateComplete( { FSP_ENTER_IOC(PAGED_CODE()); + PDEVICE_OBJECT FsvolDeviceObject = IrpSp->DeviceObject; + FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject); + PFILE_OBJECT FileObject = IrpSp->FileObject; + SHARE_ACCESS TemporaryShareAccess; + UNICODE_STRING ReparseFileName; + FSP_FSCTL_TRANSACT_REQ *Request; + FSP_FILE_CONTEXT *FsContext; + BOOLEAN Inserted; + + /* did the user-mode file system sent us a failure code? */ + if (!NT_SUCCESS(Response->IoStatus.Status)) + { + Irp->IoStatus.Information = Response->IoStatus.Information; + Result = Response->IoStatus.Status; + FSP_RETURN(); + } + + /* special case STATUS_REPARSE */ + if (STATUS_REPARSE == Result) + { + ReparseFileName.Buffer = + (PVOID)(Response->Buffer + Response->Rsp.Create.Reparse.FileName.Offset); + ReparseFileName.Length = ReparseFileName.MaximumLength = + Response->Rsp.Create.Reparse.FileName.Size; + + Result = STATUS_ACCESS_DENIED; + if (IO_REPARSE == Response->IoStatus.Information) + { + if (0 == ReparseFileName.Length || + (PUINT8)ReparseFileName.Buffer + ReparseFileName.Length > + (PUINT8)Response + Response->Size) + FSP_RETURN(); + + if (ReparseFileName.Length > FileObject->FileName.MaximumLength) + { + PVOID Buffer = FspAllocExternal(ReparseFileName.Length); + if (0 == Buffer) + FSP_RETURN(Result = STATUS_INSUFFICIENT_RESOURCES); + FspFreeExternal(FileObject->FileName.Buffer); + FileObject->FileName.MaximumLength = ReparseFileName.Length; + FileObject->FileName.Buffer = Buffer; + } + FileObject->FileName.Length = 0; + RtlCopyUnicodeString(&FileObject->FileName, &ReparseFileName); + } + else + if (IO_REMOUNT == Response->IoStatus.Information) + { + if (0 != ReparseFileName.Length) + FSP_RETURN(); + } + else + FSP_RETURN(); + + Irp->IoStatus.Information = Response->IoStatus.Information; + Result = Response->IoStatus.Status; + FSP_RETURN(); + } + + /* get the FsContext from our Request and associate it with the Response UserContext */ + Request = FspIrpRequest(Irp); + FsContext = FspIopRequestContext(Request, RequestFsContext); + FsContext->UserContext = Response->Rsp.Create.Opened.UserContext; + + /* + * Attempt to insert our FsContext into the volume device's generic table. + * If an FsContext with the same UserContext already exists, then use that + * FsContext instead. + */ + FspFsvolDeviceLockContext(FsvolDeviceObject); + FsContext = FspFsvolDeviceInsertContext(FsvolDeviceObject, + FsContext->UserContext, FsContext, &FsContext->ElementStorage, &Inserted); + ASSERT(0 != FsContext); + if (Inserted) + /* Our FsContext was inserted into the volume device's generic table. + * Disassociate it from the Request. + */ + FspIopRequestContext(Request, RequestFsContext) = 0; + else + /* + * We are using a previously inserted FsContext. We must retain it. + * Our own FsContext is still associated with the Request and will be + * deleted during IRP completion. + */ + FspFileContextRetain(FsContext); + FspFileContextOpen(FsContext); + FspFsvolDeviceUnlockContext(FsvolDeviceObject); + + /* set up share access on FileObject; user-mode file system assumed to have done share check */ + IoSetShareAccess(Response->Rsp.Create.Opened.GrantedAccess, IrpSp->Parameters.Create.ShareAccess, + FileObject, &TemporaryShareAccess); + + /* finish seting up the FileObject */ + if (0 != FsvolDeviceExtension->FsvrtDeviceObject) + FileObject->Vpb = FsvolDeviceExtension->FsvrtDeviceObject->Vpb; + FileObject->SectionObjectPointer = &FsContext->NonPaged->SectionObjectPointers; + FileObject->PrivateCacheMap = 0; + FileObject->FsContext = FsContext; + FileObject->FsContext2 = (PVOID)(UINT_PTR)Response->Rsp.Create.Opened.UserContext2; + + /* SUCCESS! */ + Irp->IoStatus.Information = Response->IoStatus.Information; + Result = Response->IoStatus.Status; + FSP_LEAVE_IOC( "FileObject=%p[%p:\"%wZ\"]", IrpSp->FileObject, IrpSp->FileObject->RelatedFileObject, IrpSp->FileObject->FileName); diff --git a/src/sys/driver.h b/src/sys/driver.h index 01bac882..e604a589 100644 --- a/src/sys/driver.h +++ b/src/sys/driver.h @@ -456,6 +456,7 @@ typedef struct ERESOURCE Resource; ERESOURCE PagingIoResource; FAST_MUTEX HeaderFastMutex; + SECTION_OBJECT_POINTERS SectionObjectPointers; } FSP_FILE_CONTEXT_NONPAGED; typedef struct { @@ -463,34 +464,38 @@ typedef struct FSP_FILE_CONTEXT_NONPAGED *NonPaged; /* interlocked access */ LONG RefCount; -#if 0 - /* protected by Header.Resource */ LONG OpenCount; - SHARE_ACCESS ShareAccess; - BOOLEAN DeletePending; /* FileDispositionInformation */ - BOOLEAN DeleteOnClose; /* FILE_DELETE_ON_CLOSE */ - FSP_DEVICE_GENERIC_TABLE_ELEMENT ElementStorage; - UINT64 UserContext; -#endif - /* read-only after creation */ + /* read-only after creation (and insertion in the GenericTable) */ PDEVICE_OBJECT FsvolDeviceObject; + UINT64 UserContext; + FSP_DEVICE_GENERIC_TABLE_ELEMENT ElementStorage; UNICODE_STRING FileName; WCHAR FileNameBuf[]; } FSP_FILE_CONTEXT; NTSTATUS FspFileContextCreate(PDEVICE_OBJECT DeviceObject, ULONG ExtraSize, FSP_FILE_CONTEXT **PFsContext); -VOID FspFileContextDelete(FSP_FILE_CONTEXT *Context); +VOID FspFileContextDelete(FSP_FILE_CONTEXT *FsContext); static inline -VOID FspFileContextRetain(FSP_FILE_CONTEXT *Context) +VOID FspFileContextRetain(FSP_FILE_CONTEXT *FsContext) { - InterlockedIncrement(&Context->RefCount); + InterlockedIncrement(&FsContext->RefCount); } static inline -VOID FspFileContextRelease(FSP_FILE_CONTEXT *Context) +VOID FspFileContextRelease(FSP_FILE_CONTEXT *FsContext) { - LONG RefCount = InterlockedDecrement(&Context->RefCount); + LONG RefCount = InterlockedDecrement(&FsContext->RefCount); if (0 == RefCount) - FspFileContextDelete(Context); + FspFileContextDelete(FsContext); +} +static inline +VOID FspFileContextOpen(FSP_FILE_CONTEXT *FsContext) +{ + InterlockedIncrement(&FsContext->OpenCount); +} +static inline +LONG FspFileContextClose(FSP_FILE_CONTEXT *FsContext) +{ + return InterlockedDecrement(&FsContext->OpenCount); } /* debug */ @@ -508,42 +513,4 @@ extern PDEVICE_OBJECT FspFsctlNetDeviceObject; extern FSP_IOPREP_DISPATCH *FspIopPrepareFunction[]; extern FSP_IOCMPL_DISPATCH *FspIopCompleteFunction[]; -#if 0 -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; - BOOLEAN DeletePending; /* FileDispositionInformation */ - BOOLEAN DeleteOnClose; /* FILE_DELETE_ON_CLOSE */ - /* read-only after creation */ - FSP_DEVICE_GENERIC_TABLE_ELEMENT ElementStorage; - PDEVICE_OBJECT FsvolDeviceObject; - UINT64 UserContext; - UNICODE_STRING FileName; - WCHAR FileNameBuf[]; -} FSP_FILE_CONTEXT; -NTSTATUS FspFileContextCreate(PDEVICE_OBJECT DeviceObject, - ULONG ExtraSize, FSP_FILE_CONTEXT **PFsContext); -VOID FspFileContextDelete(FSP_FILE_CONTEXT *Context); -static inline -VOID FspFileContextOpen(FSP_FILE_CONTEXT *Context) -{ - ASSERT(0 == Context->OpenCount || ExIsResourceAcquiredExclusiveLite(Context->Header.Resource)); - Context->OpenCount++; -} -static inline -LONG FspFileContextClose(FSP_FILE_CONTEXT *Context) -{ - ASSERT(ExIsResourceAcquiredExclusiveLite(Context->Header.Resource)); - ASSERT(0 < Context->OpenCount); - return --Context->OpenCount; -} - -#endif - #endif