From 0187b77f8b5978730139d05bc9c8d11c7786fa97 Mon Sep 17 00:00:00 2001 From: Bill Zissimopoulos Date: Fri, 4 Dec 2015 23:43:58 -0800 Subject: [PATCH] sys: IRP_MJ_CREATE --- inc/winfsp/fsctl.h | 1 + src/sys/create.c | 53 ++++++++++++++++++++++++++++++++++++++++------ src/sys/driver.h | 17 ++++++++++++++- src/sys/fileobj.c | 1 + 4 files changed, 64 insertions(+), 8 deletions(-) diff --git a/inc/winfsp/fsctl.h b/inc/winfsp/fsctl.h index 769e3d6e..55c7805b 100644 --- a/inc/winfsp/fsctl.h +++ b/inc/winfsp/fsctl.h @@ -133,6 +133,7 @@ typedef struct { UINT64 UserContext; /* user context attached to an open file (unique file id) */ UINT64 UserContext2; /* user context attached to a kernel file object */ + /* (only low 32 bits valid in 32-bit mode) */ UINT16 SecurityDescriptor; /* security descriptor for existing files (offset within Buffer) */ UINT16 SecurityDescriptorSize; /* security descriptor size */ } Create; diff --git a/src/sys/create.c b/src/sys/create.c index 3305af7b..ced15e24 100644 --- a/src/sys/create.c +++ b/src/sys/create.c @@ -309,11 +309,8 @@ NTSTATUS FspFsvolCreatePrepare( PDEVICE_OBJECT DeviceObject = IrpSp->DeviceObject; FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject); - ASSERT(FspFsvolDeviceExtensionKind == FsvolDeviceExtension->Base.Kind); - - /* it is not necessary to retain the FsvrtDeviceObject; our callers have already done so */ - PDEVICE_OBJECT FsvrtDeviceObject = FsvolDeviceExtension->FsvrtDeviceObject; - FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension = FspFsvrtDeviceExtension(FsvrtDeviceObject); + FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension = + FspFsvrtDeviceExtension(FsvolDeviceExtension->FsvrtDeviceObject); /* if the user-mode file system is not doing access checks, there is nothing else to do */ if (!FsvrtDeviceExtension->VolumeParams.NoSystemAccessCheck) @@ -322,14 +319,18 @@ NTSTATUS FspFsvolCreatePrepare( FSP_RETURN(Result = STATUS_SUCCESS); } + /* get a user-mode handle to the access token */ PACCESS_STATE AccessState = IrpSp->Parameters.Create.SecurityContext->AccessState; HANDLE UserModeAccessToken; - - /* get a user-mode handle to the access token */ Result = ObOpenObjectByPointer(SeQuerySubjectContextToken(&AccessState->SubjectSecurityContext), 0, 0, TOKEN_QUERY, *SeTokenObjectType, UserMode, &UserModeAccessToken); if (!NT_SUCCESS(Result)) + { + PFILE_OBJECT FileObject = IrpSp->FileObject; + FspFileContextDelete(FileObject->FsContext); + FileObject->FsContext = 0; FSP_RETURN(); + } /* send the user-mode handle to the user-mode file system */ Irp->Tail.Overlay.DriverContext[1] = UserModeAccessToken; @@ -343,6 +344,44 @@ VOID FspFsvolCreateComplete( { FSP_ENTER_IOC(PAGED_CODE()); + PDEVICE_OBJECT DeviceObject = IrpSp->DeviceObject; + PFILE_OBJECT FileObject = IrpSp->FileObject; + + /* if the user-mode file system sent us a failure code, fail the request now */ + if (!NT_SUCCESS(Response->IoStatus.Status)) + { + FspFileContextDelete(FileObject->FsContext); + FileObject->FsContext = 0; + goto exit; + } + + /* record the user-mode file system contexts */ + FSP_FILE_CONTEXT *FsContext = FileObject->FsContext; + BOOLEAN Inserted; + FsContext->UserContext = Response->Rsp.Create.UserContext; + FileObject->FsContext2 = (PVOID)(UINT_PTR)Response->Rsp.Create.UserContext2; + + /* insert the new FsContext into our generic table */ + FsContext = FspFsvolDeviceInsertContext(DeviceObject, + FsContext->UserContext, FsContext, &Inserted); + if (0 == FsContext) + { + FspFsvolCreateClose(Irp, Response); + FSP_RETURN(Result = STATUS_INSUFFICIENT_RESOURCES); + } + + /* if it was not inserted, an FsContext with the same UserContext already exists; reuse it */ + if (!Inserted) + { + FspFileContextDelete(FileObject->FsContext); + FspFileContextOpen(FsContext); + FileObject->FsContext = FsContext; + } + +exit: + 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 8309092e..727df0ec 100644 --- a/src/sys/driver.h +++ b/src/sys/driver.h @@ -262,7 +262,8 @@ PIRP FspIoqEndProcessingIrp(FSP_IOQ *Ioq, UINT_PTR IrpHint); NTSTATUS FspIopCreateRequest( PIRP Irp, PUNICODE_STRING FileName, ULONG ExtraSize, FSP_FSCTL_TRANSACT_REQ **PRequest); VOID FspIopCompleteRequestEx(PIRP Irp, NTSTATUS Result, BOOLEAN DeviceRelease); -static inline VOID FspIopCompleteRequest(PIRP Irp, NTSTATUS Result) +static inline +VOID FspIopCompleteRequest(PIRP Irp, NTSTATUS Result) { FspIopCompleteRequestEx(Irp, Result, TRUE); } @@ -363,11 +364,25 @@ typedef struct { FSRTL_ADVANCED_FCB_HEADER Header; FSP_FILE_CONTEXT_NONPAGED *NonPaged; + LONG OpenCount; + UINT64 UserContext; UNICODE_STRING FileName; WCHAR FileNameBuf[]; } FSP_FILE_CONTEXT; NTSTATUS FspFileContextCreate(ULONG ExtraSize, FSP_FILE_CONTEXT **PContext); VOID FspFileContextDelete(FSP_FILE_CONTEXT *Context); +static inline +VOID FspFileContextOpen(FSP_FILE_CONTEXT *Context) +{ + InterlockedIncrement(&Context->OpenCount); +} +static inline +VOID FspFileContextClose(FSP_FILE_CONTEXT *Context) +{ + LONG Result = InterlockedDecrement(&Context->OpenCount); + if (0 == Result) + FspFileContextDelete(Context); +} /* misc */ NTSTATUS FspCreateGuid(GUID *Guid); diff --git a/src/sys/fileobj.c b/src/sys/fileobj.c index cc13d875..dc9c1372 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->OpenCount = 1; RtlInitEmptyUnicodeString(&FsContext->FileName, FsContext->FileNameBuf, (USHORT)ExtraSize); *PFsContext = FsContext;