mirror of
				https://github.com/winfsp/winfsp.git
				synced 2025-10-30 19:48:38 -05:00 
			
		
		
		
	sys, dll: QuerySecurity, SetSecurity
This commit is contained in:
		| @@ -47,6 +47,9 @@ FSP_API NTSTATUS FspAccessCheckEx(FSP_FILE_SYSTEM *FileSystem, | ||||
|     if (0 != PSecurityDescriptor) | ||||
|         *PSecurityDescriptor = 0; | ||||
|  | ||||
|     if (FspFsctlTransactCreateKind != Request->Kind) | ||||
|         return STATUS_INVALID_PARAMETER; | ||||
|  | ||||
|     if (0 == FileSystem->Interface->GetSecurityByName || | ||||
|         (!Request->Req.Create.UserMode && 0 == PSecurityDescriptor)) | ||||
|     { | ||||
| @@ -202,13 +205,16 @@ exit: | ||||
|     return Result; | ||||
| } | ||||
|  | ||||
| FSP_API NTSTATUS FspAssignSecurity(FSP_FILE_SYSTEM *FileSystem, | ||||
| FSP_API NTSTATUS FspCreateSecurityDescriptor(FSP_FILE_SYSTEM *FileSystem, | ||||
|     FSP_FSCTL_TRANSACT_REQ *Request, | ||||
|     PSECURITY_DESCRIPTOR ParentDescriptor, | ||||
|     PSECURITY_DESCRIPTOR *PSecurityDescriptor) | ||||
| { | ||||
|     *PSecurityDescriptor = 0; | ||||
|  | ||||
|     if (FspFsctlTransactCreateKind != Request->Kind) | ||||
|         return STATUS_INVALID_PARAMETER; | ||||
|  | ||||
|     if (!CreatePrivateObjectSecurity( | ||||
|         ParentDescriptor, | ||||
|         0 != Request->Req.Create.SecurityDescriptor.Offset ? | ||||
| @@ -224,11 +230,75 @@ FSP_API NTSTATUS FspAssignSecurity(FSP_FILE_SYSTEM *FileSystem, | ||||
|     return STATUS_SUCCESS; | ||||
| } | ||||
|  | ||||
| FSP_API NTSTATUS FspSetSecurityDescriptor(FSP_FILE_SYSTEM *FileSystem, | ||||
|     FSP_FSCTL_TRANSACT_REQ *Request, | ||||
|     PSECURITY_DESCRIPTOR InputDescriptor, | ||||
|     PSECURITY_DESCRIPTOR *PSecurityDescriptor) | ||||
| { | ||||
|     *PSecurityDescriptor = 0; | ||||
|  | ||||
|     if (FspFsctlTransactSetSecurityKind != Request->Kind) | ||||
|         return STATUS_INVALID_PARAMETER; | ||||
|  | ||||
|     if (0 == InputDescriptor) | ||||
|         return STATUS_NO_SECURITY_ON_OBJECT; | ||||
|  | ||||
|     /* | ||||
|      * SetPrivateObjectSecurity is a broken API. It assumes that the passed | ||||
|      * descriptor resides on memory allocated by CreatePrivateObjectSecurity | ||||
|      * or SetPrivateObjectSecurity and frees the descriptor on success. | ||||
|      * | ||||
|      * In our case the security descriptor comes from the user mode file system, | ||||
|      * which may conjure it any way it sees fit. So we have to somehow make a copy | ||||
|      * of the InputDescriptor and place it in memory that SetPrivateObjectSecurity | ||||
|      * can then free. To complicate matters there is no API that can be used for | ||||
|      * this purpose. What a PITA! | ||||
|      */ | ||||
|     /* !!!: HACK! HACK! HACK! | ||||
|      * | ||||
|      * Turns out that SetPrivateObjectSecurity and friends really use RtlProcessHeap | ||||
|      * internally, which is just another name for GetProcessHeap(). | ||||
|      * | ||||
|      * I wish there was a cleaner way to do this! | ||||
|      */ | ||||
|  | ||||
|     HANDLE ProcessHeap = GetProcessHeap(); | ||||
|     DWORD InputDescriptorSize = GetSecurityDescriptorLength(InputDescriptor); | ||||
|     PSECURITY_DESCRIPTOR CopiedDescriptor; | ||||
|  | ||||
|     CopiedDescriptor = HeapAlloc(ProcessHeap, 0, InputDescriptorSize); | ||||
|     if (0 == CopiedDescriptor) | ||||
|         return STATUS_INSUFFICIENT_RESOURCES; | ||||
|     memcpy(CopiedDescriptor, InputDescriptor, InputDescriptorSize); | ||||
|     InputDescriptor = CopiedDescriptor; | ||||
|  | ||||
|     if (!SetPrivateObjectSecurity( | ||||
|         Request->Req.SetSecurity.SecurityInformation, | ||||
|         (PVOID)Request->Buffer, | ||||
|         &InputDescriptor, | ||||
|         &FspFileGenericMapping, | ||||
|         (HANDLE)Request->Req.SetSecurity.AccessToken)) | ||||
|     { | ||||
|         HeapFree(ProcessHeap, 0, CopiedDescriptor); | ||||
|         return FspNtStatusFromWin32(GetLastError()); | ||||
|     } | ||||
|  | ||||
|     /* CopiedDescriptor has been freed by SetPrivateObjectSecurity! */ | ||||
|  | ||||
|     *PSecurityDescriptor = InputDescriptor; | ||||
|  | ||||
|     DEBUGLOGSD("SDDL=%s", *PSecurityDescriptor); | ||||
|  | ||||
|     return STATUS_SUCCESS; | ||||
| } | ||||
|  | ||||
| FSP_API VOID FspDeleteSecurityDescriptor(PSECURITY_DESCRIPTOR SecurityDescriptor, | ||||
|     NTSTATUS(*CreateFunc)()) | ||||
|     NTSTATUS (*CreateFunc)()) | ||||
| { | ||||
|     if ((NTSTATUS (*)())FspAccessCheckEx == CreateFunc) | ||||
|         MemFree(SecurityDescriptor); | ||||
|     else if ((NTSTATUS (*)())FspAssignSecurity == CreateFunc) | ||||
|     else | ||||
|     if ((NTSTATUS (*)())FspCreateSecurityDescriptor == CreateFunc || | ||||
|         (NTSTATUS (*)())FspSetSecurityDescriptor == CreateFunc) | ||||
|         DestroyPrivateObjectSecurity(&SecurityDescriptor); | ||||
| } | ||||
|   | ||||
| @@ -83,7 +83,7 @@ static NTSTATUS FspFileSystemOpCreate_FileCreate(FSP_FILE_SYSTEM *FileSystem, | ||||
|     if (!NT_SUCCESS(Result)) | ||||
|         return Result; | ||||
|  | ||||
|     Result = FspAssignSecurity(FileSystem, Request, ParentDescriptor, &ObjectDescriptor); | ||||
|     Result = FspCreateSecurityDescriptor(FileSystem, Request, ParentDescriptor, &ObjectDescriptor); | ||||
|     FspDeleteSecurityDescriptor(ParentDescriptor, FspAccessCheckEx); | ||||
|     if (!NT_SUCCESS(Result)) | ||||
|         return Result; | ||||
| @@ -94,7 +94,7 @@ static NTSTATUS FspFileSystemOpCreate_FileCreate(FSP_FILE_SYSTEM *FileSystem, | ||||
|         (PWSTR)Request->Buffer, Request->Req.Create.CaseSensitive, Request->Req.Create.CreateOptions, | ||||
|         Request->Req.Create.FileAttributes, ObjectDescriptor, Request->Req.Create.AllocationSize, | ||||
|         &FileNode, &FileInfo); | ||||
|     FspDeleteSecurityDescriptor(ObjectDescriptor, FspAssignSecurity); | ||||
|     FspDeleteSecurityDescriptor(ObjectDescriptor, FspCreateSecurityDescriptor); | ||||
|     if (!NT_SUCCESS(Result)) | ||||
|         return Result; | ||||
|  | ||||
| @@ -171,7 +171,7 @@ static NTSTATUS FspFileSystemOpCreate_FileOpenIf(FSP_FILE_SYSTEM *FileSystem, | ||||
|         if (!NT_SUCCESS(Result)) | ||||
|             return Result; | ||||
|  | ||||
|         Result = FspAssignSecurity(FileSystem, Request, ParentDescriptor, &ObjectDescriptor); | ||||
|         Result = FspCreateSecurityDescriptor(FileSystem, Request, ParentDescriptor, &ObjectDescriptor); | ||||
|         FspDeleteSecurityDescriptor(ParentDescriptor, FspAccessCheckEx); | ||||
|         if (!NT_SUCCESS(Result)) | ||||
|             return Result; | ||||
| @@ -182,7 +182,7 @@ static NTSTATUS FspFileSystemOpCreate_FileOpenIf(FSP_FILE_SYSTEM *FileSystem, | ||||
|             (PWSTR)Request->Buffer, Request->Req.Create.CaseSensitive, Request->Req.Create.CreateOptions, | ||||
|             Request->Req.Create.FileAttributes, ObjectDescriptor, Request->Req.Create.AllocationSize, | ||||
|             &FileNode, &FileInfo); | ||||
|         FspDeleteSecurityDescriptor(ObjectDescriptor, FspAssignSecurity); | ||||
|         FspDeleteSecurityDescriptor(ObjectDescriptor, FspCreateSecurityDescriptor); | ||||
|         if (!NT_SUCCESS(Result)) | ||||
|             return Result; | ||||
|     } | ||||
| @@ -261,7 +261,7 @@ static NTSTATUS FspFileSystemOpCreate_FileOverwriteIf(FSP_FILE_SYSTEM *FileSyste | ||||
|         if (!NT_SUCCESS(Result)) | ||||
|             return Result; | ||||
|  | ||||
|         Result = FspAssignSecurity(FileSystem, Request, ParentDescriptor, &ObjectDescriptor); | ||||
|         Result = FspCreateSecurityDescriptor(FileSystem, Request, ParentDescriptor, &ObjectDescriptor); | ||||
|         FspDeleteSecurityDescriptor(ParentDescriptor, FspAccessCheckEx); | ||||
|         if (!NT_SUCCESS(Result)) | ||||
|             return Result; | ||||
| @@ -272,7 +272,7 @@ static NTSTATUS FspFileSystemOpCreate_FileOverwriteIf(FSP_FILE_SYSTEM *FileSyste | ||||
|             (PWSTR)Request->Buffer, Request->Req.Create.CaseSensitive, Request->Req.Create.CreateOptions, | ||||
|             Request->Req.Create.FileAttributes, ObjectDescriptor, Request->Req.Create.AllocationSize, | ||||
|             &FileNode, &FileInfo); | ||||
|         FspDeleteSecurityDescriptor(ObjectDescriptor, FspAssignSecurity); | ||||
|         FspDeleteSecurityDescriptor(ObjectDescriptor, FspCreateSecurityDescriptor); | ||||
|         if (!NT_SUCCESS(Result)) | ||||
|             return Result; | ||||
|     } | ||||
| @@ -544,22 +544,32 @@ FSP_API NTSTATUS FspFileSystemOpQuerySecurity(FSP_FILE_SYSTEM *FileSystem, | ||||
|     FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response) | ||||
| { | ||||
|     NTSTATUS Result; | ||||
|     SIZE_T SecurityDescriptorSize; | ||||
|  | ||||
|     if (0 == FileSystem->Interface->GetSecurity) | ||||
|         return STATUS_INVALID_DEVICE_REQUEST; | ||||
|  | ||||
|     (VOID)Result; | ||||
|     return STATUS_INVALID_DEVICE_REQUEST; | ||||
|     SecurityDescriptorSize = FSP_FSCTL_TRANSACT_RSP_SIZEMAX - sizeof *Response; | ||||
|     Result = FileSystem->Interface->GetSecurity(FileSystem, Request, | ||||
|         (PVOID)Request->Req.QuerySecurity.UserContext, | ||||
|         Response->Buffer, &SecurityDescriptorSize); | ||||
|     if (!NT_SUCCESS(Result)) | ||||
|         return STATUS_BUFFER_OVERFLOW != Result ? Result : STATUS_INVALID_SECURITY_DESCR; | ||||
|  | ||||
|     Response->Size = (UINT16)(sizeof *Response + SecurityDescriptorSize); | ||||
|     Response->Rsp.QuerySecurity.SecurityDescriptor.Offset = 0; | ||||
|     Response->Rsp.QuerySecurity.SecurityDescriptor.Size = (UINT16)SecurityDescriptorSize; | ||||
|     return STATUS_SUCCESS; | ||||
| } | ||||
|  | ||||
| FSP_API NTSTATUS FspFileSystemOpSetSecurity(FSP_FILE_SYSTEM *FileSystem, | ||||
|     FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response) | ||||
| { | ||||
|     NTSTATUS Result; | ||||
|  | ||||
|     if (0 == FileSystem->Interface->SetSecurity) | ||||
|         return STATUS_INVALID_DEVICE_REQUEST; | ||||
|  | ||||
|     (VOID)Result; | ||||
|     return STATUS_INVALID_DEVICE_REQUEST; | ||||
|     return FileSystem->Interface->SetSecurity(FileSystem, Request, | ||||
|         (PVOID)Request->Req.SetSecurity.UserContext, | ||||
|         Request->Req.SetSecurity.SecurityInformation, | ||||
|         (PSECURITY_DESCRIPTOR)Request->Buffer); | ||||
| } | ||||
|   | ||||
| @@ -86,6 +86,7 @@ NTSTATUS DriverEntry( | ||||
|     FspIopCompleteFunction[IRP_MJ_LOCK_CONTROL] = FspFsvolLockControlComplete; | ||||
|     FspIopCompleteFunction[IRP_MJ_CLEANUP] = FspFsvolCleanupComplete; | ||||
|     FspIopCompleteFunction[IRP_MJ_QUERY_SECURITY] = FspFsvolQuerySecurityComplete; | ||||
|     FspIopPrepareFunction[IRP_MJ_SET_SECURITY] = FspFsvolSetSecurityPrepare; | ||||
|     FspIopCompleteFunction[IRP_MJ_SET_SECURITY] = FspFsvolSetSecurityComplete; | ||||
|  | ||||
|     /* setup fast I/O and resource acquisition */ | ||||
|   | ||||
| @@ -258,6 +258,7 @@ FSP_IOCMPL_DISPATCH FspFsvolQueryVolumeInformationComplete; | ||||
| FSP_IOCMPL_DISPATCH FspFsvolReadComplete; | ||||
| FSP_IOCMPL_DISPATCH FspFsvolSetEaComplete; | ||||
| FSP_IOCMPL_DISPATCH FspFsvolSetInformationComplete; | ||||
| FSP_IOPREP_DISPATCH FspFsvolSetSecurityPrepare; | ||||
| FSP_IOCMPL_DISPATCH FspFsvolSetSecurityComplete; | ||||
| FSP_IOCMPL_DISPATCH FspFsvolSetVolumeInformationComplete; | ||||
| FSP_IOCMPL_DISPATCH FspFsvolShutdownComplete; | ||||
|   | ||||
| @@ -9,19 +9,23 @@ | ||||
| static NTSTATUS FspFsvolQuerySecurity( | ||||
|     PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp); | ||||
| FSP_IOCMPL_DISPATCH FspFsvolQuerySecurityComplete; | ||||
| static FSP_IOP_REQUEST_FINI FspFsvolQuerySecurityRequestFini; | ||||
| static NTSTATUS FspFsvolSetSecurity( | ||||
|     PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp); | ||||
| FSP_IOPREP_DISPATCH FspFsvolSetSecurityPrepare; | ||||
| FSP_IOCMPL_DISPATCH FspFsvolSetSecurityComplete; | ||||
| static FSP_IOP_REQUEST_FINI FspFsvolSecurityRequestFini; | ||||
| static FSP_IOP_REQUEST_FINI FspFsvolSetSecurityRequestFini; | ||||
| FSP_DRIVER_DISPATCH FspQuerySecurity; | ||||
| FSP_DRIVER_DISPATCH FspSetSecurity; | ||||
|  | ||||
| #ifdef ALLOC_PRAGMA | ||||
| #pragma alloc_text(PAGE, FspFsvolQuerySecurity) | ||||
| #pragma alloc_text(PAGE, FspFsvolQuerySecurityComplete) | ||||
| #pragma alloc_text(PAGE, FspFsvolQuerySecurityRequestFini) | ||||
| #pragma alloc_text(PAGE, FspFsvolSetSecurity) | ||||
| #pragma alloc_text(PAGE, FspFsvolSetSecurityPrepare) | ||||
| #pragma alloc_text(PAGE, FspFsvolSetSecurityComplete) | ||||
| #pragma alloc_text(PAGE, FspFsvolSecurityRequestFini) | ||||
| #pragma alloc_text(PAGE, FspFsvolSetSecurityRequestFini) | ||||
| #pragma alloc_text(PAGE, FspQuerySecurity) | ||||
| #pragma alloc_text(PAGE, FspSetSecurity) | ||||
| #endif | ||||
| @@ -34,6 +38,8 @@ enum | ||||
|  | ||||
|     /* SetSecurity */ | ||||
|     //RequestFileNode                   = 0, | ||||
|     RequestAccessToken                  = 2, | ||||
|     RequestProcess                      = 3, | ||||
| }; | ||||
|  | ||||
| static NTSTATUS FspFsvolQuerySecurity( | ||||
| @@ -72,7 +78,7 @@ static NTSTATUS FspFsvolQuerySecurity( | ||||
|  | ||||
|     FSP_FSCTL_TRANSACT_REQ *Request; | ||||
|  | ||||
|     Result = FspIopCreateRequestEx(Irp, 0, 0, FspFsvolSecurityRequestFini, &Request); | ||||
|     Result = FspIopCreateRequestEx(Irp, 0, 0, FspFsvolQuerySecurityRequestFini, &Request); | ||||
|     if (!NT_SUCCESS(Result)) | ||||
|     { | ||||
|         FspFileNodeRelease(FileNode, Full); | ||||
| @@ -158,6 +164,16 @@ NTSTATUS FspFsvolQuerySecurityComplete( | ||||
|         IrpSp->FileObject, IrpSp->Parameters.QuerySecurity.SecurityInformation); | ||||
| } | ||||
|  | ||||
| static VOID FspFsvolQuerySecurityRequestFini(FSP_FSCTL_TRANSACT_REQ *Request, PVOID Context[4]) | ||||
| { | ||||
|     PAGED_CODE(); | ||||
|  | ||||
|     FSP_FILE_NODE *FileNode = Context[RequestFileNode]; | ||||
|  | ||||
|     if (0 != FileNode) | ||||
|         FspFileNodeReleaseOwner(FileNode, Full, Request); | ||||
| } | ||||
|  | ||||
| static NTSTATUS FspFsvolSetSecurity( | ||||
|     PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp) | ||||
| { | ||||
| @@ -188,7 +204,7 @@ static NTSTATUS FspFsvolSetSecurity( | ||||
|  | ||||
|     FSP_FSCTL_TRANSACT_REQ *Request; | ||||
|  | ||||
|     Result = FspIopCreateRequestEx(Irp, 0, SecurityDescriptorSize, FspFsvolSecurityRequestFini, | ||||
|     Result = FspIopCreateRequestEx(Irp, 0, SecurityDescriptorSize, FspFsvolSetSecurityRequestFini, | ||||
|         &Request); | ||||
|     if (!NT_SUCCESS(Result)) | ||||
|     { | ||||
| @@ -210,6 +226,53 @@ static NTSTATUS FspFsvolSetSecurity( | ||||
|     return FSP_STATUS_IOQ_POST; | ||||
| } | ||||
|  | ||||
| NTSTATUS FspFsvolSetSecurityPrepare( | ||||
|     PIRP Irp, FSP_FSCTL_TRANSACT_REQ *Request) | ||||
| { | ||||
|     PAGED_CODE(); | ||||
|  | ||||
|     NTSTATUS Result; | ||||
|     SECURITY_SUBJECT_CONTEXT SecuritySubjectContext; | ||||
|     SECURITY_QUALITY_OF_SERVICE SecurityQualityOfService; | ||||
|     SECURITY_CLIENT_CONTEXT SecurityClientContext; | ||||
|     HANDLE UserModeAccessToken; | ||||
|     PEPROCESS Process; | ||||
|  | ||||
|     /* duplicate the subject context access token into an impersonation token */ | ||||
|     SecurityQualityOfService.Length = sizeof SecurityQualityOfService; | ||||
|     SecurityQualityOfService.ImpersonationLevel = SecurityIdentification; | ||||
|     SecurityQualityOfService.ContextTrackingMode = SECURITY_STATIC_TRACKING; | ||||
|     SecurityQualityOfService.EffectiveOnly = FALSE; | ||||
|     SeCaptureSubjectContext(&SecuritySubjectContext); | ||||
|     SeLockSubjectContext(&SecuritySubjectContext); | ||||
|     Result = SeCreateClientSecurityFromSubjectContext(&SecuritySubjectContext, | ||||
|         &SecurityQualityOfService, FALSE, &SecurityClientContext); | ||||
|     SeUnlockSubjectContext(&SecuritySubjectContext); | ||||
|     SeReleaseSubjectContext(&SecuritySubjectContext); | ||||
|     if (!NT_SUCCESS(Result)) | ||||
|         return Result; | ||||
|  | ||||
|     ASSERT(TokenImpersonation == SeTokenType(SecurityClientContext.ClientToken)); | ||||
|  | ||||
|     /* get a user-mode handle to the impersonation token */ | ||||
|     Result = ObOpenObjectByPointer(SecurityClientContext.ClientToken, | ||||
|         0, 0, TOKEN_QUERY, *SeTokenObjectType, UserMode, &UserModeAccessToken); | ||||
|     SeDeleteClientSecurity(&SecurityClientContext); | ||||
|     if (!NT_SUCCESS(Result)) | ||||
|         return Result; | ||||
|  | ||||
|     /* get a pointer to the current process so that we can close the impersonation token later */ | ||||
|     Process = PsGetCurrentProcess(); | ||||
|     ObReferenceObject(Process); | ||||
|  | ||||
|     /* send the user-mode handle to the user-mode file system */ | ||||
|     FspIopRequestContext(Request, RequestAccessToken) = UserModeAccessToken; | ||||
|     FspIopRequestContext(Request, RequestProcess) = Process; | ||||
|     Request->Req.SetSecurity.AccessToken = (UINT_PTR)UserModeAccessToken; | ||||
|  | ||||
|     return STATUS_SUCCESS; | ||||
| } | ||||
|  | ||||
| NTSTATUS FspFsvolSetSecurityComplete( | ||||
|     PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response) | ||||
| { | ||||
| @@ -252,14 +315,40 @@ NTSTATUS FspFsvolSetSecurityComplete( | ||||
|         IrpSp->FileObject, IrpSp->Parameters.SetSecurity.SecurityInformation); | ||||
| } | ||||
|  | ||||
| static VOID FspFsvolSecurityRequestFini(FSP_FSCTL_TRANSACT_REQ *Request, PVOID Context[4]) | ||||
| static VOID FspFsvolSetSecurityRequestFini(FSP_FSCTL_TRANSACT_REQ *Request, PVOID Context[4]) | ||||
| { | ||||
|     PAGED_CODE(); | ||||
|  | ||||
|     FSP_FILE_NODE *FileNode = Context[RequestFileNode]; | ||||
|     HANDLE AccessToken = Context[RequestAccessToken]; | ||||
|     PEPROCESS Process = Context[RequestProcess]; | ||||
|  | ||||
|     if (0 != FileNode) | ||||
|         FspFileNodeReleaseOwner(FileNode, Full, Request); | ||||
|  | ||||
|     if (0 != AccessToken) | ||||
|     { | ||||
|         KAPC_STATE ApcState; | ||||
|         BOOLEAN Attach; | ||||
|  | ||||
|         ASSERT(0 != Process); | ||||
|         Attach = Process != PsGetCurrentProcess(); | ||||
|  | ||||
|         if (Attach) | ||||
|             KeStackAttachProcess(Process, &ApcState); | ||||
| #if DBG | ||||
|         NTSTATUS Result0; | ||||
|         Result0 = ObCloseHandle(AccessToken, UserMode); | ||||
|         if (!NT_SUCCESS(Result0)) | ||||
|             DEBUGLOG("ObCloseHandle() = %s", NtStatusSym(Result0)); | ||||
| #else | ||||
|         ObCloseHandle(AccessToken, UserMode); | ||||
| #endif | ||||
|         if (Attach) | ||||
|             KeUnstackDetachProcess(&ApcState); | ||||
|  | ||||
|         ObDereferenceObject(Process); | ||||
|     } | ||||
| } | ||||
|  | ||||
| NTSTATUS FspQuerySecurity( | ||||
|   | ||||
		Reference in New Issue
	
	Block a user