|
|
/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
uasp.c
Abstract:
Private functions shared by the UAS API routines.
Author:
Cliff Van Dyke (cliffv) 20-Feb-1991
Environment:
User mode only. Contains NT-specific code. Requires ANSI C extensions: slash-slash comments, long external names.
Revision History:
17-Apr-1991 (cliffv) Incorporated review comments.
--*/
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#undef DOMAIN_ALL_ACCESS // defined in both ntsam.h and ntwinapi.h
#include <ntsam.h>
#include <ntlsa.h>
#include <windef.h>
#include <winbase.h>
#include <lmcons.h>
#include <accessp.h>
#include <dsgetdc.h>
#include <icanon.h>
#include <lmerr.h>
#include <lmwksta.h>
#include <lmaccess.h>
#include <lmapibuf.h>
#include <lmremutl.h> // NetpRemoteComputerSupports(), SUPPORTS_ stuff
#include <lmsvc.h> // SERVICE_WORKSTATION.
#include <names.h>
#include <netdebug.h>
#include <netlib.h>
#include <netlibnt.h>
#include <stddef.h>
#include <stdlib.h>
#include <uasp.h>
#include <tstring.h> // NetAllocWStrFromWStr
SID_IDENTIFIER_AUTHORITY UaspBuiltinAuthority = SECURITY_NT_AUTHORITY;
#ifdef UAS_DEBUG
DWORD UasTrace = 0; #endif // UAS_DEBUG
NET_API_STATUS UaspOpenSam( IN LPCWSTR ServerName OPTIONAL, IN BOOL AllowNullSession, OUT PSAM_HANDLE SamServerHandle )
/*++
Routine Description:
Open a handle to a Sam server.
Arguments:
ServerName - A pointer to a string containing the name of the Domain Controller (DC) to query. A NULL pointer or string specifies the local machine.
AllowNullSession - TRUE if we should fall back to the NULL session if we cannot connect using current credentials
SamServerHandle - Returns the SAM connection handle if the caller wants it. Close this handle by calling SamCloseHandle
Return Value:
Error code for the operation.
--*/
{ NET_API_STATUS NetStatus; NTSTATUS Status;
BOOLEAN ImpersonatingAnonymous = FALSE; HANDLE CurrentToken = NULL;
UNICODE_STRING ServerNameString;
//
// Sanity check the server name
//
if ( ServerName == NULL ) { ServerName = L""; }
#ifdef notdef
if ( *ServerName != L'\0' && (ServerName[0] != L'\\' || ServerName[1] != L'\\') ) { return NERR_InvalidComputer; } #endif // notdef
//
// Connect to the SAM server
//
RtlInitUnicodeString( &ServerNameString, ServerName );
Status = SamConnect( &ServerNameString, SamServerHandle, SAM_SERVER_LOOKUP_DOMAIN | SAM_SERVER_ENUMERATE_DOMAINS, NULL);
//
// If the caller would rather use the null session than fail,
// impersonate the anonymous token.
//
if ( AllowNullSession && Status == STATUS_ACCESS_DENIED ) { *SamServerHandle = NULL;
//
// Check to see if we're already impsonating
//
Status = NtOpenThreadToken( NtCurrentThread(), TOKEN_IMPERSONATE, TRUE, // as self to ensure we never fail
&CurrentToken );
if ( Status == STATUS_NO_TOKEN ) { //
// We're not already impersonating
CurrentToken = NULL;
} else if ( !NT_SUCCESS(Status) ) { IF_DEBUG( UAS_DEBUG_UASP ) { NetpKdPrint(( "UaspOpenSam: cannot NtOpenThreadToken: 0x%lx\n", Status )); }
NetStatus = NetpNtStatusToApiStatus( Status ); goto Cleanup; }
//
// Impersonate the anonymous token
//
Status = NtImpersonateAnonymousToken( NtCurrentThread() );
if ( !NT_SUCCESS( Status)) { IF_DEBUG( UAS_DEBUG_UASP ) { NetpKdPrint(( "UaspOpenSam: cannot NtImpersonateAnonymousToken: 0x%lx\n", Status )); }
NetStatus = NetpNtStatusToApiStatus( Status ); goto Cleanup; }
ImpersonatingAnonymous = TRUE;
//
// Connect again now that we're impersonating anonymous
//
Status = SamConnect( &ServerNameString, SamServerHandle, SAM_SERVER_LOOKUP_DOMAIN | SAM_SERVER_ENUMERATE_DOMAINS, NULL);
}
if ( !NT_SUCCESS(Status)) { IF_DEBUG( UAS_DEBUG_UASP ) { NetpKdPrint(( "UaspOpenSam: Cannot connect to Sam %lX\n", Status )); } *SamServerHandle = NULL; NetStatus = NetpNtStatusToApiStatus( Status ); goto Cleanup; }
NetStatus = NERR_Success;
//
// Cleanup locally used resources
//
Cleanup:
if ( ImpersonatingAnonymous ) {
Status = NtSetInformationThread( NtCurrentThread(), ThreadImpersonationToken, &CurrentToken, sizeof(HANDLE) );
if ( !NT_SUCCESS( Status)) { IF_DEBUG( UAS_DEBUG_UASP ) { NetpKdPrint(( "UaspOpenSam: cannot NtSetInformationThread: 0x%lx\n", Status )); } }
}
if ( CurrentToken != NULL ) { NtClose( CurrentToken ); }
return NetStatus;
}
NET_API_STATUS UaspGetDomainId( IN SAM_HANDLE SamServerHandle, OUT PSID *DomainId )
/*++
Routine Description:
Return a domain ID of the account domain of a server.
Arguments:
SamServerHandle - A handle to the SAM server to open the domain on
DomainId - Receives a pointer to the domain ID. Caller must deallocate buffer using NetpMemoryFree.
Return Value:
Error code for the operation.
--*/
{ NET_API_STATUS NetStatus; NTSTATUS Status;
SAM_ENUMERATE_HANDLE EnumContext; PSAM_RID_ENUMERATION EnumBuffer = NULL; DWORD CountReturned = 0; PSID LocalDomainId = NULL; DWORD LocalBuiltinDomainSid[sizeof(SID)/sizeof(DWORD) + SID_MAX_SUB_AUTHORITIES ];
BOOL AllDone = FALSE; ULONG i;
//
// Compute the builtin domain sid.
//
RtlInitializeSid( (PSID) LocalBuiltinDomainSid, &UaspBuiltinAuthority, 1 ); *(RtlSubAuthoritySid( (PSID)LocalBuiltinDomainSid, 0 )) = SECURITY_BUILTIN_DOMAIN_RID;
//
// Loop getting the list of domain ids from SAM
//
EnumContext = 0; do {
//
// Get several domain names.
//
Status = SamEnumerateDomainsInSamServer( SamServerHandle, &EnumContext, &EnumBuffer, 8192, // PrefMaxLen
&CountReturned );
if ( !NT_SUCCESS( Status ) ) {
IF_DEBUG( UAS_DEBUG_UASP ) { NetpKdPrint(( "UaspGetDomainId: Cannot SamEnumerateDomainsInSamServer %lX\n", Status )); } NetStatus = NetpNtStatusToApiStatus( Status ); goto Cleanup; }
if( Status != STATUS_MORE_ENTRIES ) { AllDone = TRUE; }
//
// Lookup the domain ids for the domains
//
for( i = 0; i < CountReturned; i++ ) {
IF_DEBUG( UAS_DEBUG_UASP ) { NetpKdPrint(( "UaspGetDomainId: %wZ: domain name\n", &EnumBuffer[i].Name )); }
//
// Free the sid from the previous iteration.
//
if ( LocalDomainId != NULL ) { SamFreeMemory( LocalDomainId ); LocalDomainId = NULL; }
//
// Lookup the domain id
//
Status = SamLookupDomainInSamServer( SamServerHandle, &EnumBuffer[i].Name, &LocalDomainId );
if ( !NT_SUCCESS( Status ) ) { IF_DEBUG( UAS_DEBUG_UASP ) { NetpKdPrint(( "UaspGetDomainId: Cannot SamLookupDomainInSamServer %lX\n", Status )); } NetStatus = NetpNtStatusToApiStatus( Status ); goto Cleanup; }
//
// If this is the builtin domain,
// ignore it.
//
if ( RtlEqualSid( (PSID)LocalBuiltinDomainSid, LocalDomainId ) ) { continue; }
//
// Found it.
//
*DomainId = LocalDomainId; LocalDomainId = NULL; NetStatus = NO_ERROR; goto Cleanup;
}
//
// free up current EnumBuffer and get another EnumBuffer.
//
Status = SamFreeMemory( EnumBuffer ); NetpAssert( NT_SUCCESS(Status) ); EnumBuffer = NULL;
} while ( !AllDone );
NetStatus = ERROR_NO_SUCH_DOMAIN;
//
// Cleanup locally used resources
//
Cleanup:
if ( EnumBuffer != NULL ) { Status = SamFreeMemory( EnumBuffer ); NetpAssert( NT_SUCCESS(Status) ); }
return NetStatus;
} // UaspGetDomainId
NET_API_STATUS UaspOpenDomain( IN SAM_HANDLE SamServerHandle, IN ULONG DesiredAccess, IN BOOL AccountDomain, OUT PSAM_HANDLE DomainHandle, OUT PSID *DomainId OPTIONAL )
/*++
Routine Description:
Return a domain handle given the server name and the access desired to the domain.
Arguments:
SamServerHandle - A handle to the SAM server to open the domain on
DesiredAccess - Supplies the access mask indicating which access types are desired to the domain. This routine always requests DOMAIN_LOOKUP access in addition to those specified.
AccountDomain - TRUE to open the Account domain. FALSE to open the builtin domain.
DomainHandle - Receives the Domain handle to be used on future calls to the SAM server.
DomainId - Recieves a pointer to the Sid of the domain. This domain ID must be freed using NetpMemoryFree.
Return Value:
Error code for the operation. NULL means initialization was successful.
--*/
{
NET_API_STATUS NetStatus; NTSTATUS Status; PSID LocalDomainId; PSID AccountDomainId = NULL; DWORD LocalBuiltinDomainSid[sizeof(SID)/sizeof(DWORD) + SID_MAX_SUB_AUTHORITIES ];
//
// Give everyone DOMAIN_LOOKUP access.
//
DesiredAccess |= DOMAIN_LOOKUP;
//
// Choose the domain ID for the right SAM domain.
//
if ( AccountDomain ) { NetStatus = UaspGetDomainId( SamServerHandle, &AccountDomainId );
if ( NetStatus != NO_ERROR ) { goto Cleanup; }
LocalDomainId = AccountDomainId; } else { RtlInitializeSid( (PSID) LocalBuiltinDomainSid, &UaspBuiltinAuthority, 1 ); *(RtlSubAuthoritySid( (PSID)LocalBuiltinDomainSid, 0 )) = SECURITY_BUILTIN_DOMAIN_RID; LocalDomainId = (PSID) LocalBuiltinDomainSid; }
//
// Open the domain.
//
Status = SamOpenDomain( SamServerHandle, DesiredAccess, LocalDomainId, DomainHandle );
if ( !NT_SUCCESS( Status ) ) {
IF_DEBUG( UAS_DEBUG_UASP ) { NetpKdPrint(( "UaspOpenDomain: Cannot SamOpenDomain %lX\n", Status )); } *DomainHandle = NULL; NetStatus = NetpNtStatusToApiStatus( Status ); goto Cleanup; }
//
// Return the DomainId to the caller in an allocated buffer
//
if (ARGUMENT_PRESENT( DomainId ) ) {
//
// If we've already allocated the sid,
// just return it.
//
if ( AccountDomainId != NULL ) { *DomainId = AccountDomainId; AccountDomainId = NULL;
//
// Otherwise make a copy.
//
} else { ULONG SidSize; SidSize = RtlLengthSid( LocalDomainId );
*DomainId = NetpMemoryAllocate( SidSize );
if ( *DomainId == NULL ) { (VOID) SamCloseHandle( *DomainHandle ); *DomainHandle = NULL; NetStatus = ERROR_NOT_ENOUGH_MEMORY; goto Cleanup; }
if ( !NT_SUCCESS( RtlCopySid( SidSize, *DomainId, LocalDomainId) ) ) { (VOID) SamCloseHandle( *DomainHandle ); *DomainHandle = NULL; NetpMemoryFree( *DomainId ); *DomainId = NULL; NetStatus = NERR_InternalError; goto Cleanup; } }
}
NetStatus = NERR_Success;
Cleanup: if ( AccountDomainId != NULL ) { NetpMemoryFree( AccountDomainId ); }
return NetStatus;
}
NET_API_STATUS UaspOpenDomainWithDomainName( IN LPCWSTR DomainName, IN ULONG DesiredAccess, IN BOOL AccountDomain, OUT PSAM_HANDLE DomainHandle, OUT PSID *DomainId OPTIONAL )
/*++
Routine Description:
Returns the name of a DC in the specified domain. The Server is guaranteed to be up at the instance of this call.
Arguments:
DoaminName - A pointer to a string containing the name of the remote domain containing the SAM database. A NULL pointer or string specifies the local machine.
DesiredAccess - Supplies the access mask indicating which access types are desired to the domain. This routine always requests DOMAIN_LOOKUP access in addition to those specified.
AccountDomain - TRUE to open the Account domain. FALSE to open the builtin domain.
DomainHandle - Receives the Domain handle to be used on future calls to the SAM server.
DomainId - Recieves a pointer to the Sid of the domain. This domain ID must be freed using NetpMemoryFree.
Return Value:
NERR_Success - Operation completed successfully NERR_DCNotFound - DC for the specified domain could not be found. etc.
--*/
{ NET_API_STATUS NetStatus;
NT_PRODUCT_TYPE NtProductType; LPWSTR ServerName; LPWSTR MyDomainName = NULL; ULONG Flags; ULONG i; PDOMAIN_CONTROLLER_INFOW DcInfo = NULL; SAM_HANDLE SamServerHandle = NULL;
//
// Check to see if the domain specified refers to this machine.
//
if ( DomainName == NULL || *DomainName == L'\0' ) {
//
// Connect to the SAM server
//
NetStatus = UaspOpenSam( NULL, FALSE, // Don't try null session
&SamServerHandle );
if ( NetStatus != NERR_Success ) { IF_DEBUG( UAS_DEBUG_UASP ) { NetpKdPrint(( "UaspOpenDomainWithDomainName: Cannot UaspOpenSam %ld\n", NetStatus )); } }
goto Cleanup; }
//
// Validate the DomainName
//
if ( !NetpIsDomainNameValid( (LPWSTR)DomainName) ) { NetStatus = NERR_DCNotFound; IF_DEBUG( UAS_DEBUG_UASP ) { NetpKdPrint(( "UaspOpenDomainWithDomainName: %ws: Cannot SamOpenDomain %ld\n", DomainName, NetStatus )); } goto Cleanup; }
//
// Grab the product type once.
//
if ( !RtlGetNtProductType( &NtProductType ) ) { NtProductType = NtProductWinNt; }
//
// If this machine is a DC, this machine is refered to by domain name.
//
if ( NtProductType == NtProductLanManNt ) {
NetStatus = NetpGetDomainName( &MyDomainName );
if ( NetStatus != NERR_Success ) { IF_DEBUG( UAS_DEBUG_UASP ) { NetpKdPrint(( "UaspOpenDomainWithDomainName: %ws: Cannot NetpGetDomainName %ld\n", DomainName, NetStatus )); } goto Cleanup; }
//
// If this machine is not a DC, this machine is refered to by computer name.
//
} else {
NetStatus = NetpGetComputerName( &MyDomainName );
if ( NetStatus != NERR_Success ) { IF_DEBUG( UAS_DEBUG_UASP ) { NetpKdPrint(( "UaspOpenDomainWithDomainName: %ws: Cannot NetpGetComputerName %ld\n", DomainName, NetStatus )); } goto Cleanup; } }
if ( UaspNameCompare( MyDomainName, (LPWSTR) DomainName, NAMETYPE_DOMAIN ) == 0 ) {
//
// Connect to the SAM server
//
NetStatus = UaspOpenSam( NULL, FALSE, // Don't try null session
&SamServerHandle );
if ( NetStatus != NERR_Success ) { IF_DEBUG( UAS_DEBUG_UASP ) { NetpKdPrint(( "UaspOpenDomainWithDomainName: Cannot UaspOpenSam %ld\n", NetStatus )); } }
goto Cleanup; }
//
// Try at least twice to find a DC.
//
Flags = 0; for ( i=0; i<2; i++ ) {
//
// Get the name of a DC in the domain.
//
NetStatus = DsGetDcNameW( NULL, DomainName, NULL, // No domain GUID
NULL, // No site name
Flags | DS_IS_FLAT_NAME | DS_RETURN_FLAT_NAME, &DcInfo );
if ( NetStatus != NO_ERROR ) {
IF_DEBUG( UAS_DEBUG_UASP ) { NetpKdPrint(( "UaspOpenDomainWithDomainName: %ws: Cannot DsGetDcName %ld\n", DomainName, NetStatus )); }
goto Cleanup; }
//
// Connect to the SAM server on that DC
//
NetStatus = UaspOpenSam( DcInfo->DomainControllerName, TRUE, // Try null session
&SamServerHandle );
if ( NetStatus != NERR_Success ) { IF_DEBUG( UAS_DEBUG_UASP ) { NetpKdPrint(( "UaspOpenDomainWithDomainName: Cannot UaspOpenSam %ld\n", NetStatus )); } }
//
// If we got a definitive answer back from this DC,
// use it.
//
switch ( NetStatus ) { case NO_ERROR: case ERROR_ACCESS_DENIED: case ERROR_NOT_ENOUGH_MEMORY: case NERR_InvalidComputer: goto Cleanup; }
//
// Otherwise, force rediscovery of a new DC.
//
Flags |= DS_FORCE_REDISCOVERY;
}
//
// Delete locally used resources
//
Cleanup:
//
// If we've successfully gotten this far,
// we have a SamServer handle.
//
// Just open the domain.
//
if ( NetStatus == NO_ERROR && SamServerHandle != NULL ) {
NetStatus = UaspOpenDomain( SamServerHandle, DesiredAccess, AccountDomain, DomainHandle, DomainId ); }
//
// The SamServerHandle has outlived its usefulness
//
if ( SamServerHandle != NULL ) { (VOID) SamCloseHandle( SamServerHandle ); }
if ( MyDomainName != NULL ) { NetApiBufferFree( MyDomainName ); } if ( DcInfo != NULL) { NetApiBufferFree( DcInfo ); }
if ( NetStatus != NERR_Success ) { *DomainHandle = NULL; }
return NetStatus; } // UaspOpenDomainWithDomainName
VOID UaspCloseDomain( IN SAM_HANDLE DomainHandle OPTIONAL )
/*++
Routine Description:
Close a Domain handle opened by UaspOpenDomain.
Arguments:
DomainHandle - Supplies the Domain Handle to close.
Return Value:
None.
--*/
{
//
// Close the Domain Handle
//
if ( DomainHandle != NULL ) { (VOID) SamCloseHandle( DomainHandle ); }
return; } // UaspCloseDomain
NET_API_STATUS UaspDownlevel( IN LPCWSTR ServerName OPTIONAL, IN NET_API_STATUS OriginalError, OUT LPBOOL TryDownLevel ) /*++
Routine Description:
This routine is based on NetpHandleRpcFailure (courtesy of JohnRo). It is different in that it doesn't handle RPC failures. Rather, it tries to determine if a Sam call should go downlevel simply by calling using the specified ServerName.
Arguments:
ServerName - The server name to handle the call.
OriginalError - Error gotten from RPC attempt.
TryDownLevel - Returns TRUE if we should try down-level.
Return Value:
NERR_Success - Use SAM to handle the call.
Other - Return the error to the caller.
--*/
{ NET_API_STATUS NetStatus; DWORD OptionsSupported = 0;
*TryDownLevel = FALSE;
//
// Learn about the machine. This is fairly easy since the
// NetRemoteComputerSupports also handles the local machine (whether
// or not a server name is given).
//
NetStatus = NetRemoteComputerSupports( (LPWSTR) ServerName, SUPPORTS_RPC | SUPPORTS_LOCAL | SUPPORTS_SAM_PROTOCOL, &OptionsSupported);
if (NetStatus != NERR_Success) { // This is where machine not found gets handled.
return NetStatus; }
//
// If the machine supports SAM,
// just return now.
//
if (OptionsSupported & SUPPORTS_SAM_PROTOCOL) { // SAM is only supported over RPC
NetpAssert((OptionsSupported & SUPPORTS_RPC) == SUPPORTS_RPC ); return OriginalError; }
// The local system should always support SAM
NetpAssert((OptionsSupported & SUPPORTS_LOCAL) == 0 );
//
// Local workstation is not started? (It must be in order to
// remote APIs to the other system.)
//
if ( ! NetpIsServiceStarted(SERVICE_WORKSTATION) ) { return (NERR_WkstaNotStarted); }
//
// Tell the caller to try the RxNet routine.
//
*TryDownLevel = TRUE; return OriginalError;
} // UaspDownlevel
NET_API_STATUS UaspLSASetServerRole( IN LPCWSTR ServerName, IN PDOMAIN_SERVER_ROLE_INFORMATION DomainServerRole )
/*++
Routine Description:
This function sets the server role in LSA.
Arguments:
ServerName - The server name to handle the call.
ServerRole - The server role information.
Return Value:
NERR_Success - if the server role is successfully set in LSA.
Error code for the operation - if the operation was unsuccessful.
--*/
{ NTSTATUS Status; NET_API_STATUS NetStatus;
UNICODE_STRING UnicodeStringServerName;
ACCESS_MASK LSADesiredAccess; LSA_HANDLE LSAPolicyHandle = NULL; OBJECT_ATTRIBUTES LSAObjectAttributes;
POLICY_LSA_SERVER_ROLE_INFO PolicyLsaServerRoleInfo;
RtlInitUnicodeString( &UnicodeStringServerName, ServerName );
//
// set desired access mask.
//
LSADesiredAccess = POLICY_SERVER_ADMIN;
InitializeObjectAttributes( &LSAObjectAttributes, NULL, // Name
0, // Attributes
NULL, // Root
NULL ); // Security Descriptor
Status = LsaOpenPolicy( &UnicodeStringServerName, &LSAObjectAttributes, LSADesiredAccess, &LSAPolicyHandle );
if( !NT_SUCCESS(Status) ) {
IF_DEBUG( UAS_DEBUG_UASP ) { NetpKdPrint(( "UaspLSASetServerRole: " "Cannot open LSA Policy %lX\n", Status )); }
NetStatus = NetpNtStatusToApiStatus( Status ); goto Cleanup; }
//
// make PolicyLsaServerRoleInfo
//
switch( DomainServerRole->DomainServerRole ) {
case DomainServerRoleBackup :
PolicyLsaServerRoleInfo.LsaServerRole = PolicyServerRoleBackup;
break;
case DomainServerRolePrimary :
PolicyLsaServerRoleInfo.LsaServerRole = PolicyServerRolePrimary;
break;
default:
IF_DEBUG( UAS_DEBUG_UASP ) { NetpKdPrint(( "UaspLSASetServerRole: " "Unknown Server Role %lX\n", DomainServerRole->DomainServerRole )); }
NetStatus = NERR_InternalError; goto Cleanup;
}
//
// now set PolicyLsaServerRoleInformation
//
Status = LsaSetInformationPolicy( LSAPolicyHandle, PolicyLsaServerRoleInformation, (PVOID) &PolicyLsaServerRoleInfo );
if( !NT_SUCCESS(Status) ) {
IF_DEBUG( UAS_DEBUG_UASP ) { NetpKdPrint(( "UaspLSASetServerRole: " "Cannot set Information Policy %lX\n", Status )); }
NetStatus = NetpNtStatusToApiStatus( Status ); goto Cleanup;
}
//
// Successfully done
//
NetStatus = NERR_Success;
Cleanup:
if( LSAPolicyHandle != NULL ) { Status = LsaClose( LSAPolicyHandle ); NetpAssert( NT_SUCCESS( Status ) ); }
return NetStatus;
}
NET_API_STATUS UaspBuiltinDomainSetServerRole( IN SAM_HANDLE SamServerHandle, IN PDOMAIN_SERVER_ROLE_INFORMATION DomainServerRole )
/*++
Routine Description:
This function sets the server role in builtin domain.
Arguments:
SamServerHandle - A handle to the SAM server to set the role on
ServerRole - The server role information.
Return Value:
NERR_Success - if the server role is successfully set in LSA.
Error code for the operation - if the operation was unsuccessful.
--*/
{ NTSTATUS Status; NET_API_STATUS NetStatus;
SAM_HANDLE BuiltinDomainHandle = NULL;
//
// Open the domain asking for accumulated desired access
//
NetStatus = UaspOpenDomain( SamServerHandle, DOMAIN_ADMINISTER_SERVER, FALSE, // Builtin Domain
&BuiltinDomainHandle, NULL ); // DomainId
if ( NetStatus != NERR_Success ) {
IF_DEBUG( UAS_DEBUG_UASP ) { NetpKdPrint(( "UaspBuiltinSetServerRole: " "Cannot UaspOpenDomain [Builtin] %ld\n", NetStatus )); } goto Cleanup; }
//
// now we have open the builtin domain, update server role.
//
Status = SamSetInformationDomain( BuiltinDomainHandle, DomainServerRoleInformation, DomainServerRole );
if ( !NT_SUCCESS( Status ) ) {
IF_DEBUG( UAS_DEBUG_UASP ) { NetpKdPrint(( "UaspBuiltinSetServerRole: " "Cannot SamSetInformationDomain %lX\n", Status )); }
NetStatus = NetpNtStatusToApiStatus( Status ); goto Cleanup; }
NetStatus = NERR_Success;
Cleanup:
//
// Close DomainHandle.
//
if ( BuiltinDomainHandle != NULL ) { (VOID) SamCloseHandle( BuiltinDomainHandle ); }
return NetStatus; }
|