mirror of
				https://github.com/winfsp/winfsp.git
				synced 2025-10-30 19:48:38 -05:00 
			
		
		
		
	sys: IRP_MJ_CREATE: FspFsvolCreateRequestFini
This commit is contained in:
		
							
								
								
									
										103
									
								
								src/sys/create.c
									
									
									
									
									
								
							
							
						
						
									
										103
									
								
								src/sys/create.c
									
									
									
									
									
								
							| @@ -16,6 +16,7 @@ FSP_IOPREP_DISPATCH FspFsvolCreatePrepare; | ||||
| FSP_IOCMPL_DISPATCH FspFsvolCreateComplete; | ||||
| static VOID FspFsvolCreateCleanupClose( | ||||
|     PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response); | ||||
| FSP_IOP_REQUEST_FINI FspFsvolCreateRequestFini; | ||||
| FSP_DRIVER_DISPATCH FspCreate; | ||||
|  | ||||
| #ifdef ALLOC_PRAGMA | ||||
| @@ -25,9 +26,17 @@ FSP_DRIVER_DISPATCH FspCreate; | ||||
| #pragma alloc_text(PAGE, FspFsvolCreatePrepare) | ||||
| #pragma alloc_text(PAGE, FspFsvolCreateComplete) | ||||
| #pragma alloc_text(PAGE, FspFsvolCreateCleanupClose) | ||||
| #pragma alloc_text(PAGE, FspFsvolCreateRequestFini) | ||||
| #pragma alloc_text(PAGE, FspCreate) | ||||
| #endif | ||||
|  | ||||
| enum | ||||
| { | ||||
|     ContextFileObject = 0, | ||||
|     ContextFsContext, | ||||
|     ContextAccessToken, | ||||
| }; | ||||
|  | ||||
| static NTSTATUS FspFsctlCreate( | ||||
|     PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp) | ||||
| { | ||||
| @@ -90,7 +99,7 @@ static NTSTATUS FspFsvolCreate( | ||||
|         /* cannot open the volume object */ | ||||
|         if (0 == RelatedFileObject && 0 == FileName.Length) | ||||
|         { | ||||
|             Result = STATUS_ACCESS_DENIED; /* need error code like POSIX EPERM (STATUS_NOT_SUPPORTED?) */ | ||||
|             Result = STATUS_ACCESS_DENIED; | ||||
|             goto exit; | ||||
|         } | ||||
|  | ||||
| @@ -256,21 +265,21 @@ static NTSTATUS FspFsvolCreate( | ||||
|         Result = RtlAppendUnicodeStringToString(&FsContext->FileName, &FileName); | ||||
|         ASSERT(NT_SUCCESS(Result)); | ||||
|  | ||||
|         /* | ||||
|          * From this point forward we MUST remember to delete the FsContext on error. | ||||
|          */ | ||||
|  | ||||
|         /* create the user-mode file system request */ | ||||
|         Result = FspIopCreateRequest(Irp, &FsContext->FileName, SecurityDescriptorSize, &Request); | ||||
|         Result = FspIopCreateRequestEx(Irp, &FsContext->FileName, SecurityDescriptorSize, | ||||
|             FspFsvolCreateRequestFini, &Request); | ||||
|         if (!NT_SUCCESS(Result)) | ||||
|         { | ||||
|             FspFileContextDelete(FsContext); | ||||
|             FspFileContextRelease(FsContext); | ||||
|             goto exit; | ||||
|         } | ||||
|  | ||||
|         /* | ||||
|          * The new request is associated with our IRP and will be deleted during its completion. | ||||
|          * Go ahead and associate the FileObject and FsContext with the Request as well. | ||||
|          */ | ||||
|         FspIopRequestContext(Request, ContextFileObject) = FileObject; | ||||
|         FspIopRequestContext(Request, ContextFsContext) = FsContext; | ||||
|  | ||||
|         /* populate the Create request */ | ||||
|         Request->Kind = FspFsctlTransactCreateKind; | ||||
| @@ -297,9 +306,8 @@ static NTSTATUS FspFsvolCreate( | ||||
|                 Request->Buffer + Request->Req.Create.SecurityDescriptor.Offset, &SecurityDescriptorSize); | ||||
|             if (!NT_SUCCESS(Result)) | ||||
|             { | ||||
|                 FspFileContextDelete(FsContext); | ||||
|                 if (STATUS_BAD_DESCRIPTOR_FORMAT == Result || STATUS_BUFFER_TOO_SMALL == Result) | ||||
|                     return STATUS_INVALID_PARAMETER; /* should not happen */ | ||||
|                     Result = STATUS_INVALID_PARAMETER; /* should not happen */ | ||||
|                 goto exit; | ||||
|             } | ||||
|         } | ||||
| @@ -307,19 +315,6 @@ static NTSTATUS FspFsvolCreate( | ||||
|             RtlCopyMemory(Request->Buffer + Request->Req.Create.SecurityDescriptor.Offset, | ||||
|                 SecurityDescriptor, SecurityDescriptorSize); | ||||
|  | ||||
|         /* | ||||
|          * Post the IRP to our Ioq; we do this here instead of at FSP_LEAVE_MJ time, | ||||
|          * so that we can FspFileContextDelete() on failure. | ||||
|          */ | ||||
|         if (!FspIoqPostIrp(&FsvrtDeviceExtension->Ioq, Irp)) | ||||
|         { | ||||
|             /* this can only happen if the Ioq was stopped */ | ||||
|             ASSERT(FspIoqStopped(&FsvrtDeviceExtension->Ioq)); | ||||
|             FspFileContextDelete(FsContext); | ||||
|             Result = STATUS_CANCELLED; | ||||
|             goto exit; | ||||
|         } | ||||
|  | ||||
|         FileObject->FsContext = FsContext; | ||||
|  | ||||
|         Result = STATUS_PENDING; | ||||
| @@ -357,15 +352,10 @@ NTSTATUS FspFsvolCreatePrepare( | ||||
|     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 */ | ||||
|     FspIrpContextHandle(Irp) = UserModeAccessToken; | ||||
|     FspIopRequestContext(Request, ContextAccessToken) = UserModeAccessToken; | ||||
|     Request->Req.Create.AccessToken = (UINT_PTR)UserModeAccessToken; | ||||
|  | ||||
|     FSP_LEAVE_IOP(); | ||||
| @@ -394,6 +384,7 @@ VOID FspFsvolCreateComplete( | ||||
|     FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject); | ||||
|     FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension = | ||||
|         FspFsvrtDeviceExtension(FsvolDeviceExtension->FsvrtDeviceObject); | ||||
|     FSP_FSCTL_TRANSACT_REQ *Request = FspIopRequest(Irp); | ||||
|     PFILE_OBJECT FileObject = IrpSp->FileObject; | ||||
|     PACCESS_STATE AccessState = IrpSp->Parameters.Create.SecurityContext->AccessState; | ||||
|     ULONG CreateOptions = IrpSp->Parameters.Create.Options; | ||||
| @@ -415,9 +406,6 @@ VOID FspFsvolCreateComplete( | ||||
|     /* did the user-mode file system sent us a failure code? */ | ||||
|     if (!NT_SUCCESS(Response->IoStatus.Status)) | ||||
|     { | ||||
|         FspFileContextDelete(FileObject->FsContext); | ||||
|         FileObject->FsContext = 0; | ||||
|  | ||||
|         Irp->IoStatus.Information = Response->IoStatus.Information; | ||||
|         Result = Response->IoStatus.Status; | ||||
|         FSP_RETURN(); | ||||
| @@ -437,16 +425,13 @@ VOID FspFsvolCreateComplete( | ||||
|             if (0 == ReparseFileName.Length || | ||||
|                 (PUINT8)ReparseFileName.Buffer + ReparseFileName.Length > | ||||
|                 (PUINT8)Response + Response->Size) | ||||
|                 goto reparse_fail; | ||||
|                 FSP_RETURN(); | ||||
|  | ||||
|             if (ReparseFileName.Length > FileObject->FileName.MaximumLength) | ||||
|             { | ||||
|                 PVOID Buffer = ExAllocatePoolWithTag(NonPagedPool, ReparseFileName.Length, FSP_TAG); | ||||
|                 if (0 == Buffer) | ||||
|                 { | ||||
|                     Result = STATUS_INSUFFICIENT_RESOURCES; | ||||
|                     goto reparse_fail; | ||||
|                 } | ||||
|                     FSP_RETURN(Result = STATUS_INSUFFICIENT_RESOURCES); | ||||
|                 ExFreePool(FileObject->FileName.Buffer); | ||||
|                 FileObject->FileName.MaximumLength = ReparseFileName.Length; | ||||
|                 FileObject->FileName.Buffer = Buffer; | ||||
| @@ -458,19 +443,14 @@ VOID FspFsvolCreateComplete( | ||||
|         if (IO_REMOUNT == Response->IoStatus.Information) | ||||
|         { | ||||
|             if (0 != ReparseFileName.Length) | ||||
|                 goto reparse_fail; | ||||
|                 FSP_RETURN(); | ||||
|         } | ||||
|         else | ||||
|             goto reparse_fail; | ||||
|             FSP_RETURN(); | ||||
|  | ||||
|         Irp->IoStatus.Information = Response->IoStatus.Information; | ||||
|         Result = Response->IoStatus.Status; | ||||
|         FSP_RETURN(); | ||||
|  | ||||
|     reparse_fail: | ||||
|         FspFileContextDelete(FileObject->FsContext); | ||||
|         FileObject->FsContext = 0; | ||||
|         FSP_RETURN(); | ||||
|     } | ||||
|  | ||||
|     /* record the user-mode file system contexts */ | ||||
| @@ -629,11 +609,17 @@ VOID FspFsvolCreateComplete( | ||||
|         FSP_RETURN(); | ||||
|     } | ||||
|  | ||||
|     /* | ||||
|      * Looks like SUCCESS! Disassociate our FileObject and FileObject->FsContext from the Request. | ||||
|      */ | ||||
|     FspIopRequestContext(Request, ContextFileObject) = 0; | ||||
|     FspIopRequestContext(Request, ContextFsContext) = 0; | ||||
|  | ||||
|     /* did an FsContext with the same UserContext already exist? */ | ||||
|     if (!Inserted) | ||||
|     { | ||||
|         /* delete the newly created FsContext and use the existing one */ | ||||
|         FspFileContextDelete(FileObject->FsContext); | ||||
|         FspFileContextRelease(FileObject->FsContext); | ||||
|         FileObject->FsContext = FsContext; | ||||
|     } | ||||
|  | ||||
| @@ -709,9 +695,32 @@ leak_exit:; | ||||
|         UserContext, UserContext2); | ||||
| #endif | ||||
|  | ||||
| exit: | ||||
|     FspFileContextDelete(FsContext); | ||||
|     FileObject->FsContext = 0; | ||||
| exit:; | ||||
| } | ||||
|  | ||||
| VOID FspFsvolCreateRequestFini(PVOID Context[3]) | ||||
| { | ||||
|     PAGED_CODE(); | ||||
|  | ||||
|     if (0 != Context[ContextFsContext]) | ||||
|     { | ||||
|         PFILE_OBJECT FileObject = Context[ContextFileObject]; | ||||
|         if (0 != FileObject && FileObject->FsContext == Context[ContextFsContext]) | ||||
|             FileObject->FsContext = 0; | ||||
|         FspFileContextRelease(Context[ContextFsContext]); | ||||
|     } | ||||
|  | ||||
|     if (0 != Context[ContextAccessToken]) | ||||
|     { | ||||
| #if DBG | ||||
|         NTSTATUS Result0; | ||||
|         Result0 = ObCloseHandle(Context[ContextAccessToken], KernelMode); | ||||
|         if (!NT_SUCCESS(Result0)) | ||||
|             DEBUGLOG("ObCloseHandle() = %s", NtStatusSym(Result0)); | ||||
| #else | ||||
|         ObCloseHandle(Context[ContextAccessToken], KernelMode); | ||||
| #endif | ||||
|     } | ||||
| } | ||||
|  | ||||
| NTSTATUS FspCreate( | ||||
|   | ||||
| @@ -267,8 +267,6 @@ PIRP FspIoqEndProcessingIrp(FSP_IOQ *Ioq, UINT_PTR IrpHint); | ||||
|     (*(FSP_FSCTL_TRANSACT_REQ **)&(Irp)->Tail.Overlay.DriverContext[0]) | ||||
| #define FspIopRequestContext(Request, I)\ | ||||
|     (*FspIopRequestContextAddress(Request, I)) | ||||
| #define FspIrpContextHandle(Irp)        \ | ||||
|     (*(HANDLE *)&(Irp)->Tail.Overlay.DriverContext[1]) | ||||
| #define FspIopCreateRequest(I, F, E, P) FspIopCreateRequestEx(I, F, E, 0, P) | ||||
| typedef VOID FSP_IOP_REQUEST_FINI(PVOID Context[3]); | ||||
| NTSTATUS FspIopCreateRequestEx( | ||||
|   | ||||
| @@ -44,12 +44,16 @@ static NTSTATUS FspFsvolInternalDeviceControl( | ||||
|                 Request->Hint = (UINT_PTR)Irp; | ||||
|                 FspIopRequest(Irp) = Request; | ||||
|  | ||||
|                 /* | ||||
|                  * Post the IRP to our Ioq; we do this here instead of at IRP_LEAVE_MJ time, | ||||
|                  * so that we can disassociate the Request on failure and release ownership | ||||
|                  * back to the caller. | ||||
|                  */ | ||||
|                 if (!FspIoqPostIrp(&FsvrtDeviceExtension->Ioq, Irp)) | ||||
|                 { | ||||
|                     /* this can only happen if the Ioq was stopped */ | ||||
|                     ASSERT(FspIoqStopped(&FsvrtDeviceExtension->Ioq)); | ||||
|  | ||||
|                     /* disocciate the Request from our Irp; release ownership back to caller */ | ||||
|                     Request->Hint = 0; | ||||
|                     FspIopRequest(Irp) = 0; | ||||
|  | ||||
|   | ||||
| @@ -160,20 +160,7 @@ VOID FspIopCompleteIrpEx(PIRP Irp, NTSTATUS Result, BOOLEAN DeviceRelease) | ||||
|         FspIopRequest(Irp) = 0; | ||||
|     } | ||||
|  | ||||
|     if (0 != FspIrpContextHandle(Irp)) | ||||
|     { | ||||
| #if DBG | ||||
|         NTSTATUS Result0; | ||||
|         Result0 = ObCloseHandle(FspIrpContextHandle(Irp), KernelMode); | ||||
|         if (!NT_SUCCESS(Result0)) | ||||
|             DEBUGLOG("ObCloseHandle() = %s", NtStatusSym(Result0)); | ||||
| #else | ||||
|         ObCloseHandle(FspIrpContextHandle(Irp), KernelMode); | ||||
| #endif | ||||
|  | ||||
|         FspIrpContextHandle(Irp) = 0; | ||||
|     } | ||||
|  | ||||
|     /* get the device object out of the IRP before completion */ | ||||
|     PDEVICE_OBJECT DeviceObject = IoGetCurrentIrpStackLocation(Irp)->DeviceObject; | ||||
|  | ||||
|     if (!NT_SUCCESS(Result)) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user