/************************************************************************* * SetKernelObjectSecurity [ADVAPI32.@] */ BOOL WINAPI SetKernelObjectSecurity ( IN HANDLE Handle, IN SECURITY_INFORMATION SecurityInformation, IN PSECURITY_DESCRIPTOR SecurityDescriptor ) { CallWin32ToNt (NtSetSecurityObject (Handle, SecurityInformation, SecurityDescriptor)); }
static void SetTokenObjectIntegrityLevel(DWORD dwIntegrityLevel) { SID_IDENTIFIER_AUTHORITY Sia = SECURITY_MANDATORY_LABEL_AUTHORITY; SECURITY_DESCRIPTOR sd; HANDLE hToken; DWORD dwLength; PACL pAcl; PSID pSid; // Do nothing on OSes where mandatory ACEs are not supported if(pfnAddMandatoryAce == NULL) return; // Initialize blank security descriptor if(!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) return; // Allocate mandatory label SID if(!AllocateAndInitializeSid(&Sia, 1, dwIntegrityLevel, 0, 0, 0, 0, 0, 0, 0, &pSid)) return; // Open current token if(!OpenThreadToken(GetCurrentThread(), WRITE_OWNER, TRUE, &hToken)) { if(GetLastError() == ERROR_NO_TOKEN) OpenProcessToken(GetCurrentProcess(), WRITE_OWNER, &hToken); } // If succeeded, set the integrity level if(hToken != NULL) { // Create ACL dwLength = sizeof(ACL) + sizeof(SYSTEM_MANDATORY_LABEL_ACE) - sizeof(DWORD) + GetLengthSid(pSid); pAcl = (PACL)HeapAlloc(g_hHeap, 0, dwLength); if(pAcl != NULL) { if(InitializeAcl(pAcl, dwLength, ACL_REVISION)) { if(pfnAddMandatoryAce(pAcl, ACL_REVISION, 0, SYSTEM_MANDATORY_LABEL_NO_WRITE_UP, pSid)) { NtSetSecurityObject(hToken, LABEL_SECURITY_INFORMATION, &sd); } } HeapFree(g_hHeap, 0, pAcl); } } FreeSid(pSid); }
VOID StripPermissions( WCHAR* KeyName ) { HANDLE keyHandle; unsigned char p[9000]; PSECURITY_DESCRIPTOR psecdesc = (PSECURITY_DESCRIPTOR)p; VOID* selfSecurityDescriptor; ULONG bufferLength = 20; keyHandle = Registry::OpenKey(KeyName, WRITE_DAC); RtlCreateSecurityDescriptor(psecdesc, SECURITY_DESCRIPTOR_REVISION); RtlSetDaclSecurityDescriptor(psecdesc, TRUE, NULL, TRUE); selfSecurityDescriptor = RtlAllocateHeap(PushHeapHandle, 0, 20); RtlMakeSelfRelativeSD(psecdesc, selfSecurityDescriptor, &bufferLength); NtSetSecurityObject(keyHandle, DACL_SECURITY_INFORMATION, selfSecurityDescriptor); NtClose(keyHandle); }
HRESULT STDMETHODCALLTYPE SetSecurity( _In_ IObjectSecurity * This, _In_ SECURITY_INFORMATION SecurityInformation, _In_ PSECURITY_DESCRIPTOR pSecurityDescriptor ) { NTSTATUS status; HANDLE hObject = NULL; ACCESS_MASK DesiredAccess; DesiredAccess = propGetObjectAccessMask(SecurityInformation, TRUE); if (!This->OpenObjectMethod(This->ObjectContext, &hObject, DesiredAccess)) { return HRESULT_FROM_WIN32(GetLastError()); } status = NtSetSecurityObject(hObject, SecurityInformation, pSecurityDescriptor); //cleanup This->CloseObjectMethod(This, hObject); return HRESULT_FROM_WIN32(RtlNtStatusToDosError(status)); }
// Takes ownership on handle (file or registry key). // The handle must be open for WRITE_OWNER access static NTSTATUS NtTakeOwnershipObject(HANDLE ObjectHandle) { SECURITY_DESCRIPTOR sd; PTOKEN_USER pTokenUser = NULL; NTSTATUS Status; HANDLE TokenHandle = NULL; ULONG cbTokenUser = 0; // Open the token of the current process Status = NtOpenProcessToken(NtCurrentProcess(), TOKEN_QUERY, &TokenHandle); if(NT_SUCCESS(Status)) { NtQueryInformationToken(TokenHandle, TokenUser, pTokenUser, cbTokenUser, &cbTokenUser); if(cbTokenUser == 0) { NtClose(TokenHandle); return STATUS_UNSUCCESSFUL; } pTokenUser = (PTOKEN_USER)RtlAllocateHeap(RtlProcessHeap(), 0, cbTokenUser); if(pTokenUser != NULL) { Status = NtQueryInformationToken(TokenHandle, TokenUser, pTokenUser, cbTokenUser, &cbTokenUser); } else { Status = STATUS_NO_MEMORY; } } // Initialize the blank security descriptor if(NT_SUCCESS(Status)) { Status = RtlCreateSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION); } // Set the owner to the security descriptor if(NT_SUCCESS(Status)) { Status = RtlSetOwnerSecurityDescriptor(&sd, pTokenUser->User.Sid, FALSE); } // Apply the owner to the object handle if(NT_SUCCESS(Status)) { Status = NtSetSecurityObject(ObjectHandle, OWNER_SECURITY_INFORMATION, &sd); } // Free buffers if(pTokenUser != NULL) RtlFreeHeap(RtlProcessHeap(), 0, pTokenUser); if(TokenHandle != NULL) NtClose(TokenHandle); return Status; }
// Sets the access-control list for a handle to "Everyone:AccessMask" // The handle must be open for WRITE_DAC access static NTSTATUS NtSetObjectAccessForEveryone( IN HANDLE ObjectHandle, IN ACCESS_MASK AccessMask) { SID_IDENTIFIER_AUTHORITY SiaEveryone = SECURITY_WORLD_SID_AUTHORITY; SECURITY_DESCRIPTOR sd; NTSTATUS Status; ULONG cbAclLength = 0; PSID pSidEveryone = NULL; PACL pAcl = NULL; // Get the SID of Everyone Status = RtlAllocateAndInitializeSid(&SiaEveryone, 1, 0, 0, 0, 0, 0, 0, 0, 0, &pSidEveryone); // Allocate space for ACL if(NT_SUCCESS(Status)) { ULONG dwSidLength = RtlLengthSid(pSidEveryone); // Create ACL for full access to the file cbAclLength = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) + dwSidLength - sizeof(DWORD); pAcl = (PACL)RtlAllocateHeap(RtlProcessHeap(), 0, cbAclLength); if(pAcl == NULL) Status = STATUS_INSUFFICIENT_RESOURCES; } // Create the Access control list with one ACE if(NT_SUCCESS(Status)) { Status = RtlCreateAcl(pAcl, cbAclLength, ACL_REVISION); } // Add the ACE to the ACL if(NT_SUCCESS(Status)) { Status = RtlAddAccessAllowedAce(pAcl, ACL_REVISION, AccessMask, pSidEveryone); } // Initialize the blank security descriptor if(NT_SUCCESS(Status)) { Status = RtlCreateSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION); } // Set the ACL to the security descriptor if(NT_SUCCESS(Status)) { Status = RtlSetDaclSecurityDescriptor(&sd, TRUE, pAcl, FALSE); } // Apply the security information to the handle if(NT_SUCCESS(Status)) { Status = NtSetSecurityObject(ObjectHandle, DACL_SECURITY_INFORMATION, &sd); } // Free buffers if(pAcl != NULL) RtlFreeHeap(RtlProcessHeap(), 0, pAcl); if(pSidEveryone != NULL) RtlFreeSid(pSidEveryone); return Status; }
/*++ * @name CsrSetProcessSecurity * * The CsrSetProcessSecurity routine protects access to the CSRSS process * from unauthorized tampering. * * @param None. * * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL otherwise. * * @remarks None. * *--*/ NTSTATUS NTAPI CsrSetProcessSecurity(VOID) { NTSTATUS Status; HANDLE hToken, hProcess = NtCurrentProcess(); ULONG Length; PTOKEN_USER TokenInfo = NULL; PSECURITY_DESCRIPTOR ProcSd = NULL; PACL Dacl; PSID UserSid; /* Open our token */ Status = NtOpenProcessToken(hProcess, TOKEN_QUERY, &hToken); if (!NT_SUCCESS(Status)) goto Quickie; /* Get the Token User Length */ NtQueryInformationToken(hToken, TokenUser, NULL, 0, &Length); /* Allocate space for it */ TokenInfo = RtlAllocateHeap(CsrHeap, HEAP_ZERO_MEMORY, Length); if (!TokenInfo) { Status = STATUS_NO_MEMORY; goto Quickie; } /* Now query the data */ Status = NtQueryInformationToken(hToken, TokenUser, TokenInfo, Length, &Length); NtClose(hToken); if (!NT_SUCCESS(Status)) goto Quickie; /* Now check the SID Length */ UserSid = TokenInfo->User.Sid; Length = RtlLengthSid(UserSid) + sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE); /* Allocate a buffer for the Security Descriptor, with SID and DACL */ ProcSd = RtlAllocateHeap(CsrHeap, HEAP_ZERO_MEMORY, SECURITY_DESCRIPTOR_MIN_LENGTH + Length); if (!ProcSd) { Status = STATUS_NO_MEMORY; goto Quickie; } /* Set the pointer to the DACL */ Dacl = (PACL)((ULONG_PTR)ProcSd + SECURITY_DESCRIPTOR_MIN_LENGTH); /* Now create the SD itself */ Status = RtlCreateSecurityDescriptor(ProcSd, SECURITY_DESCRIPTOR_REVISION); if (!NT_SUCCESS(Status)) { DPRINT1("CSRSS: SD creation failed - status = %lx\n", Status); goto Quickie; } /* Create the DACL for it*/ Status = RtlCreateAcl(Dacl, Length, ACL_REVISION2); if (!NT_SUCCESS(Status)) { DPRINT1("CSRSS: DACL creation failed - status = %lx\n", Status); goto Quickie; } /* Create the ACE */ Status = RtlAddAccessAllowedAce(Dacl, ACL_REVISION, PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION | PROCESS_DUP_HANDLE | PROCESS_TERMINATE | PROCESS_SUSPEND_RESUME | PROCESS_QUERY_INFORMATION | READ_CONTROL, UserSid); if (!NT_SUCCESS(Status)) { DPRINT1("CSRSS: ACE creation failed - status = %lx\n", Status); goto Quickie; } /* Clear the DACL in the SD */ Status = RtlSetDaclSecurityDescriptor(ProcSd, TRUE, Dacl, FALSE); if (!NT_SUCCESS(Status)) { DPRINT1("CSRSS: set DACL failed - status = %lx\n", Status); goto Quickie; } /* Write the SD into the Process */ Status = NtSetSecurityObject(hProcess, DACL_SECURITY_INFORMATION, ProcSd); if (!NT_SUCCESS(Status)) { DPRINT1("CSRSS: set process DACL failed - status = %lx\n", Status); goto Quickie; } /* Free the memory and return */ Quickie: if (ProcSd) RtlFreeHeap(CsrHeap, 0, ProcSd); RtlFreeHeap(CsrHeap, 0, TokenInfo); return Status; }
HANDLE OpenProcess( DWORD ProcessId ) { HANDLE processHandle = 0; processHandle = Process_Open( ProcessId, PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION | PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | SYNCHRONIZE ); if (!processHandle) { NTSTATUS status; ULONG bufferSize; SECURITY_DESCRIPTOR* securityDescriptor; bufferSize = 0x100; securityDescriptor = (SECURITY_DESCRIPTOR*)Memory_Allocate(bufferSize); // Get the DACL of this process since we know we have all rights in it. status = NtQuerySecurityObject( NtCurrentProcess(), DACL_SECURITY_INFORMATION, securityDescriptor, bufferSize, &bufferSize ); if (status == STATUS_BUFFER_TOO_SMALL) { Memory_Free(securityDescriptor); securityDescriptor = (SECURITY_DESCRIPTOR*)Memory_Allocate(bufferSize); status = NtQuerySecurityObject( NtCurrentProcess(), DACL_SECURITY_INFORMATION, securityDescriptor, bufferSize, &bufferSize ); } if (!NT_SUCCESS(status)) { Memory_Free(securityDescriptor); return NULL; } // Open it with WRITE_DAC access so that we can write to the DACL. processHandle = Process_Open(ProcessId, (0x00040000L)); //WRITE_DAC if (processHandle == 0) { Memory_Free(securityDescriptor); return NULL; } status = NtSetSecurityObject( processHandle, DACL_SECURITY_INFORMATION | UNPROTECTED_DACL_SECURITY_INFORMATION, securityDescriptor ); if (!NT_SUCCESS(status)) { Memory_Free(securityDescriptor); return NULL; } // The DACL is overwritten with our own DACL. We // should be able to open it with the requested // privileges now. Process_Close(processHandle); processHandle = 0; Memory_Free(securityDescriptor); processHandle = Process_Open( ProcessId, PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION | PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | SYNCHRONIZE ); } if (!processHandle) { return NULL; } return processHandle; }
NTSTATUS SspCreateTokenDacl( HANDLE Token ) /*++ RoutineDescription: Creates a new DACL for the token granting the server and client all access to the token. Arguments: Token - Handle to an impersonation token open for TOKEN_QUERY and WRITE_DAC Return Value: STATUS_INSUFFICIENT_RESOURCES - insufficient memory to complete the function. Errors from NtSetSecurityObject --*/ { NTSTATUS Status; PTOKEN_USER ProcessTokenUser = NULL; PTOKEN_USER ThreadTokenUser = NULL; HANDLE ProcessToken = NULL; SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY; ULONG AclLength; PACL NewDacl = NULL; SECURITY_DESCRIPTOR SecurityDescriptor; // // Build the two well known sids we need. // EnterCriticalSection(&csCheaterList); if (SspGlobalLocalSystemSid == NULL) { Status = RtlAllocateAndInitializeSid( &NtAuthority, 1, SECURITY_LOCAL_SYSTEM_RID, 0,0,0,0,0,0,0, &SspGlobalLocalSystemSid ); if (!NT_SUCCESS(Status)) { LeaveCriticalSection(&csCheaterList); goto Cleanup; } } if (SspGlobalAliasAdminsSid == NULL) { Status = RtlAllocateAndInitializeSid( &NtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0,0,0,0,0,0, &SspGlobalAliasAdminsSid ); if (!NT_SUCCESS(Status)) { LeaveCriticalSection(&csCheaterList); goto Cleanup; } } LeaveCriticalSection(&csCheaterList); // // Open the process token to find out the user sid // Status = NtOpenProcessToken( NtCurrentProcess(), TOKEN_QUERY, &ProcessToken ); if (!NT_SUCCESS(Status)) { goto Cleanup; } Status = SspGetTokenUser( ProcessToken, &ProcessTokenUser ); if (!NT_SUCCESS(Status)) { goto Cleanup; } // // Now get the token user for the thread. // Status = SspGetTokenUser( Token, &ThreadTokenUser ); if (!NT_SUCCESS(Status)) { goto Cleanup; } AclLength = 4 * sizeof( ACCESS_ALLOWED_ACE ) - 4 * sizeof( ULONG ) + RtlLengthSid( ProcessTokenUser->User.Sid ) + RtlLengthSid( ThreadTokenUser->User.Sid ) + RtlLengthSid( SspGlobalLocalSystemSid ) + RtlLengthSid( SspGlobalAliasAdminsSid ) + sizeof( ACL ); NewDacl = LocalAlloc(0, AclLength ); if (NewDacl == NULL) { Status = STATUS_INSUFFICIENT_RESOURCES; goto Cleanup; } Status = RtlCreateAcl( NewDacl, AclLength, ACL_REVISION2 ); ASSERT(NT_SUCCESS( Status )); Status = RtlAddAccessAllowedAce ( NewDacl, ACL_REVISION2, TOKEN_ALL_ACCESS, ProcessTokenUser->User.Sid ); ASSERT( NT_SUCCESS( Status )); Status = RtlAddAccessAllowedAce ( NewDacl, ACL_REVISION2, TOKEN_ALL_ACCESS, ThreadTokenUser->User.Sid ); ASSERT( NT_SUCCESS( Status )); Status = RtlAddAccessAllowedAce ( NewDacl, ACL_REVISION2, TOKEN_ALL_ACCESS, SspGlobalAliasAdminsSid ); ASSERT( NT_SUCCESS( Status )); Status = RtlAddAccessAllowedAce ( NewDacl, ACL_REVISION2, TOKEN_ALL_ACCESS, SspGlobalLocalSystemSid ); ASSERT( NT_SUCCESS( Status )); Status = RtlCreateSecurityDescriptor ( &SecurityDescriptor, SECURITY_DESCRIPTOR_REVISION ); ASSERT( NT_SUCCESS( Status )); Status = RtlSetDaclSecurityDescriptor( &SecurityDescriptor, TRUE, NewDacl, FALSE ); ASSERT( NT_SUCCESS( Status )); Status = NtSetSecurityObject( Token, DACL_SECURITY_INFORMATION, &SecurityDescriptor ); ASSERT( NT_SUCCESS( Status )); Cleanup: if (ThreadTokenUser != NULL) { LocalFree( ThreadTokenUser ); } if (ProcessTokenUser != NULL) { LocalFree( ProcessTokenUser ); } if (NewDacl != NULL) { LocalFree( NewDacl ); } if (ProcessToken != NULL) { NtClose(ProcessToken); } return( Status ); }
BOOLEAN WepCreateServerObjects( VOID ) { OBJECT_ATTRIBUTES objectAttributes; WCHAR buffer[256]; UNICODE_STRING objectName; SECURITY_DESCRIPTOR securityDescriptor; UCHAR saclBuffer[sizeof(ACL) + FIELD_OFFSET(SYSTEM_MANDATORY_LABEL_ACE, SidStart) + FIELD_OFFSET(SID, SubAuthority) + sizeof(ULONG)]; PACL sacl; UCHAR mandatoryLabelAceBuffer[FIELD_OFFSET(SYSTEM_MANDATORY_LABEL_ACE, SidStart) + FIELD_OFFSET(SID, SubAuthority) + sizeof(ULONG)]; PSYSTEM_MANDATORY_LABEL_ACE mandatoryLabelAce; PSID sid; if (!WeServerSharedSection) { LARGE_INTEGER maximumSize; WeFormatLocalObjectName(WE_SERVER_SHARED_SECTION_NAME, buffer, &objectName); InitializeObjectAttributes(&objectAttributes, &objectName, OBJ_CASE_INSENSITIVE, NULL, NULL); maximumSize.QuadPart = sizeof(WE_HOOK_SHARED_DATA); if (!NT_SUCCESS(NtCreateSection( &WeServerSharedSection, SECTION_ALL_ACCESS, &objectAttributes, &maximumSize, PAGE_READWRITE, SEC_COMMIT, NULL ))) { return FALSE; } } if (!WeServerSharedData) { PVOID viewBase; SIZE_T viewSize; viewBase = NULL; viewSize = sizeof(WE_HOOK_SHARED_DATA); if (!NT_SUCCESS(NtMapViewOfSection( WeServerSharedSection, NtCurrentProcess(), &viewBase, 0, 0, NULL, &viewSize, ViewShare, 0, PAGE_READWRITE ))) { WepCloseServerObjects(); return FALSE; } WeServerSharedData = viewBase; } if (!WeServerSharedSectionLock) { WeFormatLocalObjectName(WE_SERVER_SHARED_SECTION_LOCK_NAME, buffer, &objectName); InitializeObjectAttributes(&objectAttributes, &objectName, OBJ_CASE_INSENSITIVE, NULL, NULL); if (!NT_SUCCESS(NtCreateMutant( &WeServerSharedSectionLock, MUTANT_ALL_ACCESS, &objectAttributes, FALSE ))) { WepCloseServerObjects(); return FALSE; } } if (!WeServerSharedSectionEvent) { WeFormatLocalObjectName(WE_SERVER_SHARED_SECTION_EVENT_NAME, buffer, &objectName); InitializeObjectAttributes(&objectAttributes, &objectName, OBJ_CASE_INSENSITIVE, NULL, NULL); if (!NT_SUCCESS(NtCreateEvent( &WeServerSharedSectionEvent, EVENT_ALL_ACCESS, &objectAttributes, NotificationEvent, FALSE ))) { WepCloseServerObjects(); return FALSE; } } // If mandatory labels are supported, set it to the lowest possible level. if (WE_WindowsVersion >= WINDOWS_VISTA) { static SID_IDENTIFIER_AUTHORITY mandatoryLabelAuthority = SECURITY_MANDATORY_LABEL_AUTHORITY; RtlCreateSecurityDescriptor(&securityDescriptor, SECURITY_DESCRIPTOR_REVISION); sacl = (PACL)saclBuffer; RtlCreateAcl(sacl, sizeof(saclBuffer), ACL_REVISION); mandatoryLabelAce = (PSYSTEM_MANDATORY_LABEL_ACE)mandatoryLabelAceBuffer; mandatoryLabelAce->Header.AceType = SYSTEM_MANDATORY_LABEL_ACE_TYPE; mandatoryLabelAce->Header.AceFlags = 0; mandatoryLabelAce->Header.AceSize = sizeof(mandatoryLabelAceBuffer); mandatoryLabelAce->Mask = SYSTEM_MANDATORY_LABEL_NO_WRITE_UP; sid = (PSID)&mandatoryLabelAce->SidStart; RtlInitializeSid(sid, &mandatoryLabelAuthority, 1); *RtlSubAuthoritySid(sid, 0) = SECURITY_MANDATORY_LOW_RID; if (NT_SUCCESS(RtlAddAce(sacl, ACL_REVISION, MAXULONG32, mandatoryLabelAce, sizeof(mandatoryLabelAceBuffer)))) { if (NT_SUCCESS(RtlSetSaclSecurityDescriptor(&securityDescriptor, TRUE, sacl, FALSE))) { NtSetSecurityObject(WeServerSharedSection, LABEL_SECURITY_INFORMATION, &securityDescriptor); NtSetSecurityObject(WeServerSharedSectionLock, LABEL_SECURITY_INFORMATION, &securityDescriptor); NtSetSecurityObject(WeServerSharedSectionEvent, LABEL_SECURITY_INFORMATION, &securityDescriptor); } } } return TRUE; }
BOOL BackupWriteSecurityData(HANDLE hFile, BACKUPCONTEXT *pbuc, BACKUPIOFRAME *pbif) { NTSTATUS Status; SECURITY_INFORMATION si; switch (BackupWriteBuffer(pbuc, pbif)) { default: case BRB_FAIL: return(FALSE); case BRB_MORE: return(TRUE); case BRB_DONE: if (!pbif->fProcessSecurity) { return(TRUE); // ignore the data we read } break; } // Once the entire stream is in our buffer, we can set the ACL data. // First try to write all the security data that's there. si = OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION; if (((PISECURITY_DESCRIPTOR) pbuc->pBuffer)->Control & SE_DACL_PRESENT) { si |= DACL_SECURITY_INFORMATION; } if (((PISECURITY_DESCRIPTOR) pbuc->pBuffer)->Control & SE_SACL_PRESENT) { si |= SACL_SECURITY_INFORMATION; } Status = NtSetSecurityObject(hFile, si, pbuc->pBuffer); if (!NT_SUCCESS(Status)) { NTSTATUS Status2; // If that didn't work, the caller is probably not running as Backup // Operator, so we can't set the owner and group. Keep the current // status code, and attempt to set the DACL and SACL while ignoring // failures. if (si & SACL_SECURITY_INFORMATION) { NtSetSecurityObject( hFile, SACL_SECURITY_INFORMATION, pbuc->pBuffer); } if (si & DACL_SECURITY_INFORMATION) { Status = NtSetSecurityObject( hFile, DACL_SECURITY_INFORMATION, pbuc->pBuffer); } Status2 = NtSetSecurityObject( hFile, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION, pbuc->pBuffer); if (NT_SUCCESS(Status)) { Status = Status2; } } if (!NT_SUCCESS(Status)) { BaseSetLastNTError(Status); return(FALSE); } return(TRUE); }