Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1741 lines
56 KiB

/*++
Copyright (c) 1998 Microsoft Corporation
Module Name:
upgrade.c
Abstract:
Implements the server side of the routines to upgrade NT4 (downlevel) servers
Author:
Mac McLain (MacM) 24 January, 1998
Environment:
User Mode
Revision History:
--*/
#include <setpch.h>
#include <dssetp.h>
#include <loadfn.h>
#include <ntlsa.h>
#include <lsarpc.h>
#include <lsaisrv.h>
#include <samrpc.h>
#include <samisrv.h>
#include <db.h>
#define DSROLEP_UPGRADE_KEY L"Security\\"
#define DSROLEP_UPGRADE_VALUE L"Upgrade"
#define DSROLEP_UPGRADE_WINLOGON \
L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\"
#define DSROLEP_UPGRADE_SAVE_PREFIX L"DcpromoOld_"
#define DSROLEP_UPGRADE_AUTOADMIN L"AutoAdminLogon"
#define DSROLEP_UPGRADE_AUTOPASSWD L"DefaultPassword"
#define DSROLEP_UPGRADE_DEFDOMAIN L"DefaultDomainName"
#define DSROLEP_UPGRADE_DEFUSER L"DefaultUserName"
#define DSROLEP_UPGRADE_AUTOUSERINIT L"Userinit"
#define DSROLEP_UPGRADE_DCPROMO L",dcpromo /upgrade"
#define DSROLEP_UPGRADE_ANSWERFILE L"/answer:"
DWORD
DsRolepSetLogonDomain(
IN LPWSTR Domain,
IN BOOLEAN FailureAllowed
)
/*++
Routine Description:
This function sets the default logon domain for winlogon
Arguments:
Domain -- Default logon domain
FailureAllowed -- If true, a failure is not considered catastrophic
Return Values:
ERROR_SUCCESS - Success
--*/
{
DWORD Win32Err = ERROR_SUCCESS;
HKEY WinlogonHandle = NULL;
//
// Open the key
//
Win32Err = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
DSROLEP_UPGRADE_WINLOGON,
0,
KEY_READ | KEY_WRITE,
&WinlogonHandle );
if ( Win32Err == ERROR_SUCCESS ) {
//
// Default logon domain
//
Win32Err = RegSetValueEx( WinlogonHandle,
DSROLEP_UPGRADE_DEFDOMAIN,
0,
REG_SZ,
( CONST PBYTE )Domain,
( wcslen( Domain ) + 1 ) * sizeof( WCHAR ) );
RegCloseKey( WinlogonHandle );
}
if ( Win32Err != ERROR_SUCCESS && FailureAllowed ) {
//
// Raise an event
//
SpmpReportEvent( TRUE,
EVENTLOG_WARNING_TYPE,
DSROLERES_FAIL_LOGON_DOMAIN,
0,
sizeof( ULONG ),
&Win32Err,
1,
Domain );
DSROLEP_SET_NON_FATAL_ERROR( Win32Err );
Win32Err = ERROR_SUCCESS;
}
return( Win32Err );
}
DWORD
DsRolepClearLsaSecretAutoLogonPassword()
/*++
Routine Description:
This function is to be invoked during setup and deletes the
auto logon password that was save in a lsa secret.
Arguments:
Return Values:
ERROR_SUCCESS - Success
ERROR_NOT_ENOUGH_MEMORY - A memory allocation failed
--*/
{
LSAPR_OBJECT_ATTRIBUTES ObjectAttributes;
LSAPR_HANDLE LsaPolicyHandle = NULL;
LSAPR_UNICODE_STRING lusSecretName, lusSecretNameOld;
PLSAPR_CR_CIPHER_VALUE plusSecretData = NULL;
USHORT SecretNameLength, SecretNameOldLength;
NTSTATUS status = STATUS_SUCCESS;
DWORD Win32Err = ERROR_SUCCESS;
ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes));
// Get a handle to the Policy object.
status = LsarOpenPolicy(NULL, //local machine
&ObjectAttributes,
POLICY_CREATE_SECRET |
POLICY_READ,
&LsaPolicyHandle);
if (!NT_SUCCESS(status)) {
Win32Err = LsaNtStatusToWinError(status);
goto Cleanup;
}
//Initialize an LSA_UNICODE_STRING
SecretNameLength = (USHORT)wcslen(DSROLEP_UPGRADE_AUTOPASSWD);
lusSecretName.Buffer = DSROLEP_UPGRADE_AUTOPASSWD;
lusSecretName.Length = SecretNameLength * sizeof(WCHAR);
lusSecretName.MaximumLength = (SecretNameLength+1) * sizeof(WCHAR);
//Initialize an LSA_UNICODE_STRING
SecretNameOldLength = (USHORT)wcslen(DSROLEP_UPGRADE_SAVE_PREFIX
DSROLEP_UPGRADE_AUTOPASSWD);
lusSecretNameOld.Buffer = DSROLEP_UPGRADE_SAVE_PREFIX
DSROLEP_UPGRADE_AUTOPASSWD;
lusSecretNameOld.Length = SecretNameOldLength * sizeof(WCHAR);
lusSecretNameOld.MaximumLength = (SecretNameOldLength+1) * sizeof(WCHAR);
//erase the autologon password
status = LsarStorePrivateData(LsaPolicyHandle,
&lusSecretName,
NULL);
if (!NT_SUCCESS(status)) {
Win32Err = LsaNtStatusToWinError(status);
goto Cleanup;
}
//get the value of any secret that may currently be stored there
//and save it off to a different location
status = LsarRetrievePrivateData(LsaPolicyHandle,
&lusSecretNameOld,
&plusSecretData);
if ( status != STATUS_OBJECT_NAME_NOT_FOUND ) {
if ( !NT_SUCCESS(status) ) {
Win32Err = LsaNtStatusToWinError(status);
goto Cleanup;
} else {
//store the value else where
status = LsarStorePrivateData(LsaPolicyHandle,
&lusSecretName,
plusSecretData);
RtlSecureZeroMemory(plusSecretData->Buffer,plusSecretData->Length);
if (!NT_SUCCESS(status)) {
Win32Err = LsaNtStatusToWinError(status);
goto Cleanup;
}
//erase the value
status = LsarStorePrivateData(LsaPolicyHandle,
&lusSecretNameOld,
NULL);
if (!NT_SUCCESS(status)) {
Win32Err = LsaNtStatusToWinError(status);
goto Cleanup;
}
}
}
Cleanup:
if( NULL != LsaPolicyHandle )
{
LsaClose(LsaPolicyHandle);
}
if ( plusSecretData ) {
LsaFreeMemory(plusSecretData);
}
return Win32Err;
}
DWORD
DsRolepSaveUpgradePasswordForAutoLogonAsLsaSecret(
IN LPWSTR NewAdminPassword)
/*++
Routine Description:
This function is to be invoked during setup and saves the admin password for
autologon as a lsa secret.
Arguments:
NewAdminPassword -- Password to save as a LSASECRET
Return Values:
ERROR_SUCCESS - Success
ERROR_NOT_ENOUGH_MEMORY - A memory allocation failed
--*/
{
LSAPR_OBJECT_ATTRIBUTES ObjectAttributes;
LSAPR_HANDLE LsaPolicyHandle;
LSAPR_UNICODE_STRING lusSecretName, lusSecretNameOld;
PLSAPR_CR_CIPHER_VALUE plusSecretData = NULL;
PLSAPR_CR_CIPHER_VALUE plusSecretDataNew = NULL;
USHORT SecretNameLength, SecretNameOldLength, SecretDataLength;
NTSTATUS status = STATUS_SUCCESS;
DWORD Win32Err = ERROR_SUCCESS;
LSAP_CR_CIPHER_KEY *SessionKey = NULL;
LSAP_CR_CLEAR_VALUE lusSecretDataClear;
// Object attributes are reserved, so initialize to zeroes.
ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes));
// Get a handle to the Policy object.
status = LsarOpenPolicy(NULL, //local machine
&ObjectAttributes,
POLICY_CREATE_SECRET |
POLICY_READ,
&LsaPolicyHandle);
if (!NT_SUCCESS(status)) {
Win32Err = LsaNtStatusToWinError(status);
goto Cleanup;
}
//Initialize an LSA_UNICODE_STRING
SecretNameLength = (USHORT)wcslen(DSROLEP_UPGRADE_AUTOPASSWD);
lusSecretName.Buffer = DSROLEP_UPGRADE_AUTOPASSWD;
lusSecretName.Length = SecretNameLength * sizeof(WCHAR);
lusSecretName.MaximumLength = (SecretNameLength+1) * sizeof(WCHAR);
//Initialize an LSA_UNICODE_STRING
SecretNameOldLength = (USHORT)wcslen(DSROLEP_UPGRADE_SAVE_PREFIX
DSROLEP_UPGRADE_AUTOPASSWD);
lusSecretNameOld.Buffer = DSROLEP_UPGRADE_SAVE_PREFIX
DSROLEP_UPGRADE_AUTOPASSWD;
lusSecretNameOld.Length = SecretNameOldLength * sizeof(WCHAR);
lusSecretNameOld.MaximumLength = (SecretNameOldLength+1) * sizeof(WCHAR);
//get the value of any secret that may currently be stored there
//and save it off to a different location
status = LsarRetrievePrivateData(LsaPolicyHandle,
&lusSecretName,
&plusSecretData);
if ( status != STATUS_OBJECT_NAME_NOT_FOUND ) {
if ( !NT_SUCCESS(status) ) {
Win32Err = LsaNtStatusToWinError(status);
goto Cleanup;
} else {
//store the value else where
status = LsarStorePrivateData(LsaPolicyHandle,
&lusSecretNameOld,
plusSecretData);
RtlSecureZeroMemory(plusSecretData->Buffer,plusSecretData->Length);
if (!NT_SUCCESS(status)) {
Win32Err = LsaNtStatusToWinError(status);
goto Cleanup;
}
//erase the value
status = LsarStorePrivateData(LsaPolicyHandle,
&lusSecretName,
NULL);
if (!NT_SUCCESS(status)) {
Win32Err = LsaNtStatusToWinError(status);
goto Cleanup;
}
}
}
//Save the admin password
//Initialize the Password LSA_UNICODE_STRING
SecretDataLength = (USHORT)wcslen(NewAdminPassword);
lusSecretDataClear.Buffer = (PUCHAR)NewAdminPassword;
lusSecretDataClear.Length = SecretDataLength * sizeof(WCHAR);
lusSecretDataClear.MaximumLength = (SecretDataLength+1) * sizeof(WCHAR);
//
// Obtain the Session Key to be used to two-way encrypt the
// Current Value.
//
status = LsapCrServerGetSessionKey( LsaPolicyHandle, &SessionKey);
if (!NT_SUCCESS(status)) {
Win32Err = LsaNtStatusToWinError(status);
goto Cleanup;
}
//
// Encrypt the Current Value if specified and not too long.
//
status = LsapCrEncryptValue(
&lusSecretDataClear,
SessionKey,
(PLSAP_CR_CIPHER_VALUE*)&plusSecretDataNew
);
if (!NT_SUCCESS(status)) {
goto Cleanup;
}
status = LsarStorePrivateData(LsaPolicyHandle,
&lusSecretName,
plusSecretDataNew);
RtlSecureZeroMemory(plusSecretDataNew->Buffer,plusSecretDataNew->Length);
LsapCrFreeMemoryValue(plusSecretDataNew);
if (!NT_SUCCESS(status)) {
Win32Err = LsaNtStatusToWinError(status);
goto Cleanup;
}
Cleanup:
if( NULL != LsaPolicyHandle )
{
LsaClose(LsaPolicyHandle);
}
if ( SessionKey ) {
MIDL_user_free(SessionKey);
}
if ( plusSecretData ) {
LsaFreeMemory(plusSecretData);
}
if (plusSecretDataNew) {
LsapCrFreeMemoryValue(plusSecretDataNew);
}
return Win32Err;
}
#pragma warning(push)
#pragma warning(disable:4701)
DWORD
DsRolepSaveUpgradeState(
IN LPWSTR AnswerFile
)
/*++
Routine Description:
This function is to be invoked during setup and saves the required server state to
complete the promotion following the reboot. Following the successful completion
of this API call, the server will be demoted to a member server in the same domain.
Arguments:
AnswerFile -- Optional path to an answer file to be used by DCPROMO during the subsequent
invocation
Return Values:
ERROR_SUCCESS - Success
ERROR_NOT_ENOUGH_MEMORY - A memory allocation failed
--*/
{
DWORD Win32Err = ERROR_SUCCESS;
NTSTATUS Status;
LSAPR_HANDLE PolicyHandle = NULL;
POLICY_ACCOUNT_DOMAIN_INFO AccountDomainInfo;
PPOLICY_LSA_SERVER_ROLE_INFO ServerRoleInfo;
OBJECT_ATTRIBUTES ObjectAttributes;
HANDLE Handle = NULL;
HKEY WinlogonHandle, UpgradeKey;
ULONG Disp, Length;
UNICODE_STRING KeyName;
UNICODE_STRING ValueName;
WCHAR ComputerName[ MAX_COMPUTERNAME_LENGTH + 1 ];
PBYTE UserInitBuffer, TempBuffer;
DWORD Type;
LPWSTR NewAdminPassword = NULL;
WCHAR Buffer[MAX_PATH];
LPWSTR AdminName = Buffer;
LPWSTR DefaultAdminName = L"Administrator";
//
// Get the localized Admin
//
Length = sizeof(Buffer)/sizeof(Buffer[0]);
Status = SamIGetDefaultAdministratorName( AdminName,
&Length );
if ( !NT_SUCCESS(Status) ) {
DsRolepLogOnFailure( ERROR_GEN_FAILURE,
DsRolepLogPrint(( DEB_TRACE,
"SamIGetDefaultAdministratorName failed with 0x%x\n",
Status )) );
AdminName = DefaultAdminName;
Status = STATUS_SUCCESS;
}
DsRolepInitializeOperationHandle();
//
// Steps involved: Set new SAM hives
// Save LSA state
// Set auto admin logon
//
// Invoke the SAM save code. It returns the new account domain sid
//
DSROLEP_CURRENT_OP0( DSROLEEVT_UPGRADE_SAM );
Win32Err = NtdsPrepareForDsUpgrade( &AccountDomainInfo,
&NewAdminPassword );
DsRolepLogOnFailure( Win32Err,
DsRolepLogPrint(( DEB_TRACE,
"NtdsPrepareForDsUpgrade failed with %lu\n",
Win32Err )) );
//
// Set the new lsa account domain sid
//
if ( Win32Err == ERROR_SUCCESS ) {
RtlZeroMemory( &ObjectAttributes, sizeof( ObjectAttributes ) );
Status = LsaOpenPolicy( NULL,
&ObjectAttributes,
POLICY_READ | POLICY_WRITE |
POLICY_VIEW_LOCAL_INFORMATION | POLICY_TRUST_ADMIN,
&PolicyHandle );
if ( NT_SUCCESS( Status ) ) {
//
// Set the new policy info
//
Status = LsaSetInformationPolicy( PolicyHandle,
PolicyAccountDomainInformation,
( PVOID ) &AccountDomainInfo );
}
Win32Err = RtlNtStatusToDosError( Status );
RtlFreeHeap( RtlProcessHeap(), 0, AccountDomainInfo.DomainSid );
RtlFreeHeap( RtlProcessHeap(), 0, AccountDomainInfo.DomainName.Buffer );
}
//
// Set the LSA registry keys that let the server know on the next reboot that this
// is an upgrade
//
if ( Win32Err == ERROR_SUCCESS ) {
//
// Get the current server role
//
Status = LsaQueryInformationPolicy( PolicyHandle,
PolicyLsaServerRoleInformation,
( PVOID )&ServerRoleInfo );
Win32Err = RtlNtStatusToDosError( Status );
if ( Win32Err == ERROR_SUCCESS ) {
//
// Open the key
//
if ( Win32Err == ERROR_SUCCESS ) {
Win32Err = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
DSROLEP_UPGRADE_KEY,
0,
KEY_READ | KEY_WRITE,
&UpgradeKey );
}
if ( Win32Err == ERROR_SUCCESS ) {
//
// Set the server role
//
Win32Err = RegSetValueEx( UpgradeKey,
DSROLEP_UPGRADE_VALUE,
0,
REG_DWORD,
( CONST PBYTE )&ServerRoleInfo->LsaServerRole,
sizeof( DWORD ) );
RegCloseKey( UpgradeKey );
}
LsaFreeMemory( ServerRoleInfo );
}
}
//
// Set the machine to do auto admin logon
//
if ( Win32Err == ERROR_SUCCESS ) {
//
// Get the computer name. That will be used for the default logon domain
//
Length = MAX_COMPUTERNAME_LENGTH + 1;
if ( GetComputerName( ComputerName, &Length ) == FALSE ) {
Win32Err = GetLastError();
} else {
//
// Open the root key
//
Win32Err = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
DSROLEP_UPGRADE_WINLOGON,
0,
KEY_READ | KEY_WRITE,
&WinlogonHandle );
if ( Win32Err == ERROR_SUCCESS ) {
//
// Auto logon
//
//
// First, see if the value currently exists...
//
Length = 0;
Win32Err = RegQueryValueEx( WinlogonHandle,
DSROLEP_UPGRADE_AUTOADMIN,
0,
&Type,
0,
&Length );
if ( Win32Err == ERROR_SUCCESS ) {
TempBuffer = RtlAllocateHeap( RtlProcessHeap(), 0, Length );
if ( TempBuffer == NULL ) {
Win32Err = ERROR_NOT_ENOUGH_MEMORY;
} else {
Win32Err = RegQueryValueEx( WinlogonHandle,
DSROLEP_UPGRADE_AUTOADMIN,
0,
&Type,
TempBuffer,
&Length );
if ( Win32Err == ERROR_SUCCESS ) {
Win32Err = RegSetValueEx( WinlogonHandle,
DSROLEP_UPGRADE_SAVE_PREFIX
DSROLEP_UPGRADE_AUTOADMIN,
0,
Type,
TempBuffer,
Length );
}
RtlFreeHeap( RtlProcessHeap(), 0, TempBuffer );
}
} else if ( Win32Err == ERROR_FILE_NOT_FOUND ) {
Win32Err = ERROR_SUCCESS;
}
if ( Win32Err == ERROR_SUCCESS ) {
Win32Err = RegSetValueEx( WinlogonHandle,
DSROLEP_UPGRADE_AUTOADMIN,
0,
REG_SZ,
( CONST PBYTE )L"1",
2 * sizeof ( WCHAR ) );
}
}
if ( Win32Err == ERROR_SUCCESS ) {
//
// Set the account password
//
//
// First, see if the value currently exists...
//
Length = 0;
Win32Err = RegQueryValueEx( WinlogonHandle,
DSROLEP_UPGRADE_AUTOPASSWD,
0,
&Type,
0,
&Length );
if ( Win32Err == ERROR_SUCCESS ) {
TempBuffer = RtlAllocateHeap( RtlProcessHeap(), 0, Length );
if ( TempBuffer == NULL ) {
Win32Err = ERROR_NOT_ENOUGH_MEMORY;
} else {
Win32Err = RegQueryValueEx( WinlogonHandle,
DSROLEP_UPGRADE_AUTOPASSWD,
0,
&Type,
TempBuffer,
&Length );
if ( Win32Err == ERROR_SUCCESS ) {
Win32Err = RegSetValueEx( WinlogonHandle,
DSROLEP_UPGRADE_SAVE_PREFIX
DSROLEP_UPGRADE_AUTOPASSWD,
0,
Type,
TempBuffer,
Length );
}
RtlSecureZeroMemory( TempBuffer, Length );
RtlFreeHeap( RtlProcessHeap(), 0, TempBuffer );
}
} else if ( Win32Err == ERROR_FILE_NOT_FOUND ) {
Win32Err = ERROR_SUCCESS;
}
if ( Win32Err == ERROR_SUCCESS ) {
Win32Err = DsRolepSaveUpgradePasswordForAutoLogonAsLsaSecret(NewAdminPassword);
RtlSecureZeroMemory(NewAdminPassword,
NewAdminPassword ? wcslen(NewAdminPassword)*sizeof(WCHAR) : 0);
if ( Win32Err == ERROR_SUCCESS ) {
Win32Err = RegDeleteValue( WinlogonHandle,
DSROLEP_UPGRADE_AUTOPASSWD );
}
//If there is no autologon password value then RegDeleteValue will return
// ERROR_FILE_NOT_FOUND. We shouldn't fail due to this.
if ( Win32Err == ERROR_FILE_NOT_FOUND ) {
Win32Err = ERROR_SUCCESS;
}
}
}
if ( Win32Err == ERROR_SUCCESS ) {
//
// Set the user name to be administrator
//
//
// First, see if the value currently exists...
//
Length = 0;
Win32Err = RegQueryValueEx( WinlogonHandle,
DSROLEP_UPGRADE_DEFUSER,
0,
&Type,
0,
&Length );
if ( Win32Err == ERROR_SUCCESS ) {
TempBuffer = RtlAllocateHeap( RtlProcessHeap(), 0, Length );
if ( TempBuffer == NULL ) {
Win32Err = ERROR_NOT_ENOUGH_MEMORY;
} else {
Win32Err = RegQueryValueEx( WinlogonHandle,
DSROLEP_UPGRADE_DEFUSER,
0,
&Type,
TempBuffer,
&Length );
if ( Win32Err == ERROR_SUCCESS ) {
Win32Err = RegSetValueEx( WinlogonHandle,
DSROLEP_UPGRADE_SAVE_PREFIX
DSROLEP_UPGRADE_DEFUSER,
0,
Type,
TempBuffer,
Length );
}
RtlFreeHeap( RtlProcessHeap(), 0, TempBuffer );
}
} else if ( Win32Err == ERROR_FILE_NOT_FOUND ) {
Win32Err = ERROR_SUCCESS;
}
if ( Win32Err == ERROR_SUCCESS ) {
Win32Err = RegSetValueEx( WinlogonHandle,
DSROLEP_UPGRADE_DEFUSER,
0,
REG_SZ,
( CONST PBYTE )AdminName,
( wcslen( AdminName ) + 1 ) * sizeof( WCHAR ) );
}
}
if ( Win32Err == ERROR_SUCCESS ) {
//
// Set the logon domain to the machine
//
//
// First, see if the value currently exists...
//
Length = 0;
Win32Err = RegQueryValueEx( WinlogonHandle,
DSROLEP_UPGRADE_DEFDOMAIN,
0,
&Type,
0,
&Length );
if ( Win32Err == ERROR_SUCCESS ) {
TempBuffer = RtlAllocateHeap( RtlProcessHeap(), 0, Length );
if ( TempBuffer == NULL ) {
Win32Err = ERROR_NOT_ENOUGH_MEMORY;
} else {
Win32Err = RegQueryValueEx( WinlogonHandle,
DSROLEP_UPGRADE_DEFDOMAIN,
0,
&Type,
TempBuffer,
&Length );
if ( Win32Err == ERROR_SUCCESS ) {
Win32Err = RegSetValueEx( WinlogonHandle,
DSROLEP_UPGRADE_SAVE_PREFIX
DSROLEP_UPGRADE_DEFDOMAIN,
0,
Type,
TempBuffer,
Length );
}
RtlFreeHeap( RtlProcessHeap(), 0, TempBuffer );
}
} else if ( Win32Err == ERROR_FILE_NOT_FOUND ) {
Win32Err = ERROR_SUCCESS;
}
if ( Win32Err == ERROR_SUCCESS ) {
Win32Err = RegSetValueEx( WinlogonHandle,
DSROLEP_UPGRADE_DEFDOMAIN,
0,
REG_SZ,
( CONST PBYTE )ComputerName,
( wcslen( ComputerName ) + 1 ) * sizeof( WCHAR ) );
}
}
if ( Win32Err == ERROR_SUCCESS ) {
//
// Finally, set dcpromo to autostart
//
Length = 0;
Win32Err = RegQueryValueEx( WinlogonHandle,
DSROLEP_UPGRADE_AUTOUSERINIT,
0, // reserved
&Type,
0,
&Length );
if ( Win32Err == ERROR_SUCCESS ) {
Length += sizeof( DSROLEP_UPGRADE_DCPROMO );
if ( AnswerFile ) {
Length += sizeof( DSROLEP_UPGRADE_ANSWERFILE ) +
( wcslen( AnswerFile ) * sizeof( WCHAR ) );
}
UserInitBuffer = RtlAllocateHeap( RtlProcessHeap(), 0,
Length );
if ( UserInitBuffer == NULL ) {
Win32Err = ERROR_NOT_ENOUGH_MEMORY;
} else {
Win32Err = RegQueryValueEx( WinlogonHandle,
DSROLEP_UPGRADE_AUTOUSERINIT,
0,
&Type,
UserInitBuffer,
&Length );
if ( Win32Err == ERROR_SUCCESS ) {
wcscat( ( PWSTR )UserInitBuffer, DSROLEP_UPGRADE_DCPROMO );
if ( AnswerFile ) {
wcscat( ( PWSTR )UserInitBuffer, DSROLEP_UPGRADE_ANSWERFILE );
wcscat( ( PWSTR )UserInitBuffer, AnswerFile );
}
Status = RegSetValueEx( WinlogonHandle,
DSROLEP_UPGRADE_AUTOUSERINIT,
0,
Type,
UserInitBuffer,
( wcslen( ( PWSTR )UserInitBuffer ) + 1 ) *
sizeof( WCHAR ) );
}
}
RtlFreeHeap( RtlProcessHeap(), 0, UserInitBuffer );
}
RegCloseKey( WinlogonHandle );
}
}
}
if ( PolicyHandle ) {
LsaClose( PolicyHandle );
}
//
// Set the product types
//
if ( Win32Err == ERROR_SUCCESS ) {
Win32Err = DsRolepSetProductType( DSROLEP_MT_STANDALONE );
}
if ( NewAdminPassword ) {
RtlSecureZeroMemory(NewAdminPassword, (wcslen(NewAdminPassword)+1)*sizeof(WCHAR) );
RtlFreeHeap( RtlProcessHeap(), 0, NewAdminPassword );
}
return( Win32Err );
}
#pragma warning(pop)
DWORD
DsRolepDeleteUpgradeInfo(
VOID
)
/*++
Routine Description:
This function deletes the saved information
Arguments:
VOID
Return Values:
ERROR_SUCCESS - Success
ERROR_NOT_ENOUGH_MEMORY - A memory allocation failed
--*/
{
DWORD Win32Err = ERROR_SUCCESS, RestoreError = Win32Err;
NTSTATUS Status;
OBJECT_ATTRIBUTES ObjectAttributes;
HKEY WinlogonHandle, UpgradeKey;
PWSTR Remove, Next, DeletePath;
PBYTE UserInitBuffer, TempBuffer;
DWORD Type, Length = 0;
//
// Remove autostarting dcpromo
//
//
// Open the root key
//
Win32Err = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
DSROLEP_UPGRADE_WINLOGON,
0,
KEY_READ | KEY_WRITE,
&WinlogonHandle );
#if DBG
DsRolepLogOnFailure( Win32Err,
DsRolepLogPrint(( DEB_TRACE,
"RegOpenKeyEx on %ws failed with %lu\n",
DSROLEP_UPGRADE_WINLOGON,
Win32Err )) );
#endif
if ( Win32Err == ERROR_SUCCESS ) {
//
// Stop dcpromo from autostarting...
//
Win32Err = RegQueryValueEx( WinlogonHandle,
DSROLEP_UPGRADE_AUTOUSERINIT,
0, // reserved
&Type,
0,
&Length );
#if DBG
DsRolepLogOnFailure( Win32Err,
DsRolepLogPrint(( DEB_TRACE,
"RegQueryValyueEx on %ws failed with %lu\n",
DSROLEP_UPGRADE_AUTOUSERINIT,
Win32Err )) );
#endif
if ( Win32Err == ERROR_SUCCESS ) {
UserInitBuffer = RtlAllocateHeap( RtlProcessHeap(), 0,
Length );
if ( UserInitBuffer == NULL ) {
Win32Err = ERROR_NOT_ENOUGH_MEMORY;
} else {
Win32Err = RegQueryValueEx( WinlogonHandle,
DSROLEP_UPGRADE_AUTOUSERINIT,
0,
&Type,
UserInitBuffer,
&Length );
#if DBG
DsRolepLogOnFailure( Win32Err,
DsRolepLogPrint(( DEB_TRACE,
"RegQueryValyueEx on %ws failed with %lu\n",
DSROLEP_UPGRADE_AUTOUSERINIT,
Win32Err )) );
#endif
if ( Win32Err == ERROR_SUCCESS ) {
Remove = wcsstr ( ( PWSTR )UserInitBuffer, DSROLEP_UPGRADE_DCPROMO );
if ( Remove ) {
Next = Remove + ( ( sizeof( DSROLEP_UPGRADE_DCPROMO ) - sizeof( WCHAR ) ) /
sizeof( WCHAR ) );
while ( *Next ) {
*Remove++ = *Next++;
}
*Remove = UNICODE_NULL;
Status = RegSetValueEx( WinlogonHandle,
DSROLEP_UPGRADE_AUTOUSERINIT,
0,
Type,
UserInitBuffer,
( wcslen( ( PWSTR )UserInitBuffer ) + 1 ) *
sizeof( WCHAR ) );
#if DBG
DsRolepLogOnFailure( Win32Err,
DsRolepLogPrint(( DEB_TRACE,
"RegQSetValyueEx on %ws failed with %lu\n",
DSROLEP_UPGRADE_AUTOUSERINIT,
Win32Err )) );
#endif
}
}
}
RtlFreeHeap( RtlProcessHeap(), 0, UserInitBuffer );
}
if ( Win32Err == ERROR_SUCCESS ) {
//
// Auto logon
//
//
// Restore the old values, if they exist
//
DeletePath = DSROLEP_UPGRADE_AUTOADMIN;
Length = 0;
Win32Err = RegQueryValueEx( WinlogonHandle,
DSROLEP_UPGRADE_SAVE_PREFIX DSROLEP_UPGRADE_AUTOADMIN,
0,
&Type,
0,
&Length );
if ( Win32Err == ERROR_SUCCESS ) {
TempBuffer = RtlAllocateHeap( RtlProcessHeap(), 0, Length );
if ( TempBuffer == NULL ) {
Win32Err = ERROR_NOT_ENOUGH_MEMORY;
} else {
Win32Err = RegQueryValueEx( WinlogonHandle,
DSROLEP_UPGRADE_SAVE_PREFIX
DSROLEP_UPGRADE_AUTOADMIN,
0,
&Type,
TempBuffer,
&Length );
if ( Win32Err == ERROR_SUCCESS ) {
Win32Err = RegSetValueEx( WinlogonHandle,
DSROLEP_UPGRADE_AUTOADMIN,
0,
Type,
TempBuffer,
Length );
RegDeleteValue( WinlogonHandle,
DSROLEP_UPGRADE_SAVE_PREFIX DSROLEP_UPGRADE_AUTOADMIN );
}
RtlFreeHeap( RtlProcessHeap(), 0, TempBuffer );
}
} else if ( Win32Err == ERROR_FILE_NOT_FOUND ) {
Win32Err = RegDeleteValue( WinlogonHandle, DeletePath );
DsRolepLogOnFailure( Win32Err,
DsRolepLogPrint(( DEB_TRACE,
"RegDeleteKey on %ws failed with %lu\n",
DeletePath,
Win32Err )) );
//
// An error here is not considered fatal...
//
Win32Err = ERROR_SUCCESS;
}
//
// Restore the default user logon name
//
DeletePath = DSROLEP_UPGRADE_DEFUSER;
Length = 0;
Win32Err = RegQueryValueEx( WinlogonHandle,
DSROLEP_UPGRADE_SAVE_PREFIX DSROLEP_UPGRADE_DEFUSER,
0,
&Type,
0,
&Length );
if ( Win32Err == ERROR_SUCCESS ) {
TempBuffer = RtlAllocateHeap( RtlProcessHeap(), 0, Length );
if ( TempBuffer == NULL ) {
Win32Err = ERROR_NOT_ENOUGH_MEMORY;
} else {
Win32Err = RegQueryValueEx( WinlogonHandle,
DSROLEP_UPGRADE_SAVE_PREFIX
DSROLEP_UPGRADE_DEFUSER,
0,
&Type,
TempBuffer,
&Length );
if ( Win32Err == ERROR_SUCCESS ) {
Win32Err = RegSetValueEx( WinlogonHandle,
DSROLEP_UPGRADE_DEFUSER,
0,
Type,
TempBuffer,
Length );
RegDeleteValue( WinlogonHandle,
DSROLEP_UPGRADE_SAVE_PREFIX DSROLEP_UPGRADE_DEFUSER );
}
RtlFreeHeap( RtlProcessHeap(), 0, TempBuffer );
}
} else if ( Win32Err == ERROR_FILE_NOT_FOUND ) {
Win32Err = RegDeleteValue( WinlogonHandle, DeletePath );
DsRolepLogOnFailure( Win32Err,
DsRolepLogPrint(( DEB_TRACE,
"RegDeleteKey on %ws failed with %lu\n",
DeletePath,
Win32Err )) );
//
// An error here is not considered fatal...
//
Win32Err = ERROR_SUCCESS;
}
//
// Restore the default domain name
//
DeletePath = DSROLEP_UPGRADE_DEFDOMAIN;
Length = 0;
Win32Err = RegQueryValueEx( WinlogonHandle,
DSROLEP_UPGRADE_SAVE_PREFIX DSROLEP_UPGRADE_DEFDOMAIN,
0,
&Type,
0,
&Length );
if ( Win32Err == ERROR_SUCCESS ) {
TempBuffer = RtlAllocateHeap( RtlProcessHeap(), 0, Length );
if ( TempBuffer == NULL ) {
Win32Err = ERROR_NOT_ENOUGH_MEMORY;
} else {
Win32Err = RegQueryValueEx( WinlogonHandle,
DSROLEP_UPGRADE_SAVE_PREFIX
DSROLEP_UPGRADE_DEFDOMAIN,
0,
&Type,
TempBuffer,
&Length );
if ( Win32Err == ERROR_SUCCESS ) {
Win32Err = RegSetValueEx( WinlogonHandle,
DSROLEP_UPGRADE_DEFDOMAIN,
0,
Type,
TempBuffer,
Length );
RegDeleteValue( WinlogonHandle,
DSROLEP_UPGRADE_SAVE_PREFIX DSROLEP_UPGRADE_DEFDOMAIN );
}
RtlFreeHeap( RtlProcessHeap(), 0, TempBuffer );
}
} else if ( Win32Err == ERROR_FILE_NOT_FOUND ) {
Win32Err = RegDeleteValue( WinlogonHandle, DeletePath );
DsRolepLogOnFailure( Win32Err,
DsRolepLogPrint(( DEB_TRACE,
"RegDeleteKey on %ws failed with %lu\n",
DeletePath,
Win32Err )) );
//
// An error here is not considered fatal...
//
Win32Err = ERROR_SUCCESS;
}
if ( Win32Err == ERROR_SUCCESS ) {
//
// Delete the account password
//
Win32Err = DsRolepClearLsaSecretAutoLogonPassword();
Length = 0;
Win32Err = RegQueryValueEx( WinlogonHandle,
DSROLEP_UPGRADE_SAVE_PREFIX
DSROLEP_UPGRADE_AUTOPASSWD,
0,
&Type,
0,
&Length );
if ( Win32Err == ERROR_SUCCESS ) {
TempBuffer = RtlAllocateHeap( RtlProcessHeap(), 0, Length );
if ( TempBuffer == NULL ) {
Win32Err = ERROR_NOT_ENOUGH_MEMORY;
} else {
Win32Err = RegQueryValueEx( WinlogonHandle,
DSROLEP_UPGRADE_SAVE_PREFIX
DSROLEP_UPGRADE_AUTOPASSWD,
0,
&Type,
TempBuffer,
&Length );
if ( Win32Err == ERROR_SUCCESS ) {
Win32Err = RegSetValueEx( WinlogonHandle,
DSROLEP_UPGRADE_AUTOPASSWD,
0,
Type,
TempBuffer,
Length );
RegDeleteValue( WinlogonHandle,
DSROLEP_UPGRADE_SAVE_PREFIX
DSROLEP_UPGRADE_AUTOPASSWD );
}
RtlFreeHeap( RtlProcessHeap(), 0, TempBuffer );
}
} else if ( Win32Err == ERROR_FILE_NOT_FOUND ) {
DeletePath = DSROLEP_UPGRADE_AUTOPASSWD;
Win32Err = RegDeleteValue( WinlogonHandle, DeletePath );
DsRolepLogOnFailure( Win32Err,
DsRolepLogPrint(( DEB_TRACE,
"RegDeleteKey on %ws failed with %lu\n",
DeletePath,
Win32Err )) );
//
// An error here is not considered fatal...
//
Win32Err = ERROR_SUCCESS;
}
}
if ( Win32Err != ERROR_SUCCESS ) {
//
// Raise an event
//
SpmpReportEvent( TRUE,
EVENTLOG_WARNING_TYPE,
DSROLERES_FAIL_DISABLE_AUTO_LOGON,
0,
sizeof( ULONG ),
&Win32Err,
1,
DeletePath );
DSROLEP_SET_NON_FATAL_ERROR( Win32Err );
Win32Err = ERROR_SUCCESS;
}
}
RegCloseKey( WinlogonHandle );
}
//
// Delete the registry key that LSA uses to determine if this is an upgrade
//
//
// Open the key
//
if ( Win32Err == ERROR_SUCCESS ) {
Win32Err = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
DSROLEP_UPGRADE_KEY,
0,
DELETE | KEY_SET_VALUE,
&UpgradeKey );
#if DBG
DsRolepLogOnFailure( Win32Err,
DsRolepLogPrint(( DEB_TRACE,
"RegOpenKey on %ws failed with %lu\n",
DSROLEP_UPGRADE_KEY,
Win32Err )) );
#endif
if ( Win32Err == ERROR_SUCCESS ) {
Win32Err = RegDeleteValue( UpgradeKey, DSROLEP_UPGRADE_VALUE );
if ( ERROR_FILE_NOT_FOUND == Win32Err ) {
// This is ok.
Win32Err = ERROR_SUCCESS;
}
#if DBG
DsRolepLogOnFailure( Win32Err,
DsRolepLogPrint(( DEB_TRACE,
"RegDeleteKey on %ws failed with %lu\n",
DSROLEP_UPGRADE_KEY,
Win32Err )) );
#endif
RegCloseKey( UpgradeKey );
}
}
//
// Finally remove the nt4 LSA information
//
//
// Remove the nt4 LSA stuff that has been put into the registry
//
LsapDsUnitializeDsStateInfo();
Status = LsaIUpgradeRegistryToDs( TRUE );
RestoreError = RtlNtStatusToDosError( Status );
DsRolepLogOnFailure( RestoreError,
DsRolepLogPrint(( DEB_WARN,
"Failed to cleanup NT4 LSA (%d)\n",
RestoreError )) );
if ( ERROR_SUCCESS != RestoreError
&& ERROR_SUCCESS == Win32Err ) {
Win32Err = RestoreError;
}
return( Win32Err );
}
DWORD
DsRolepQueryUpgradeInfo(
OUT PBOOLEAN IsUpgrade,
OUT PULONG ServerRole
)
/*++
Routine Description:
This function queries the current update information.
Arguments:
IsUpgrade - A pointer to a BOOLEAN to hold a value of TRUE if there is upgrade information
saved away, or a FALSE if not
ServerRole - If this is an upgrade, the previous server role is returned here.
Return Values:
ERROR_SUCCESS - Success
--*/
{
DWORD Win32Err = ERROR_SUCCESS;
HKEY UpgradeKey;
ULONG Type, Length = sizeof( ULONG );
//
// Open the upgrade key
//
Win32Err = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
DSROLEP_UPGRADE_KEY,
0,
KEY_READ | KEY_WRITE,
&UpgradeKey );
if ( Win32Err == ERROR_SUCCESS ) {
//
// Finally, set dcpromo to autostart
//
Win32Err = RegQueryValueEx( UpgradeKey,
DSROLEP_UPGRADE_VALUE,
0, // reserved
&Type,
( PBYTE )ServerRole,
&Length );
if ( Win32Err == ERROR_SUCCESS ) {
*IsUpgrade = TRUE;
}
RegCloseKey( UpgradeKey );
}
if ( Win32Err == ERROR_FILE_NOT_FOUND ) {
Win32Err = ERROR_SUCCESS;
*IsUpgrade = FALSE;
}
return( Win32Err );
}
DWORD
DsRolepGetBuiltinAdminAccountName(
OUT LPWSTR *BuiltinAdmin
)
/*++
Routine Description:
This routine finds the alias name for the builtin user account ADMINISTRATOR
Arguments:
BuiltinAdmin - Where the admin name is returned
Return Values:
ERROR_SUCCESS - Success
ERROR_NOT_ENOUGH_MEMORY - A memory allocation failed
--*/
{
DWORD Win32Err = ERROR_SUCCESS;
SID_IDENTIFIER_AUTHORITY UaspNtAuthority = SECURITY_NT_AUTHORITY;
DWORD SidBuff[ sizeof( SID ) / sizeof( DWORD ) + 5];
PSID Sid = ( PSID )SidBuff;
SID_NAME_USE SNE;
LPWSTR Domain = NULL;
LPWSTR Name = NULL;
ULONG NameLen = 0, DomainLen = 0;
//
// Build the sid
//
RtlInitializeSid( Sid, &UaspNtAuthority, 2 );
*( RtlSubAuthoritySid( Sid, 0 ) ) = SECURITY_BUILTIN_DOMAIN_RID;
*( RtlSubAuthoritySid( Sid, 1 ) ) = DOMAIN_USER_RID_ADMIN;
if ( LookupAccountSid( NULL,
Sid,
NULL,
&NameLen,
NULL,
&DomainLen,
&SNE ) == FALSE ) {
Win32Err = GetLastError();
if ( Win32Err == ERROR_INSUFFICIENT_BUFFER ) {
Win32Err = ERROR_SUCCESS;
Name = RtlAllocateHeap( RtlProcessHeap(), 0, NameLen * sizeof( WCHAR ) );
Domain = RtlAllocateHeap( RtlProcessHeap(), 0, DomainLen * sizeof( WCHAR ) );
if ( !Name || !Domain ) {
Win32Err = ERROR_NOT_ENOUGH_MEMORY;
} else {
if ( LookupAccountSid( NULL,
Sid,
Name,
&NameLen,
Domain,
&DomainLen,
&SNE ) == FALSE ) {
Win32Err = GetLastError();
}
}
}
}
if ( Win32Err != ERROR_SUCCESS ) {
RtlFreeHeap( RtlProcessHeap(), 0, Domain );
RtlFreeHeap( RtlProcessHeap(), 0, Name );
}
return( Win32Err );
}
DWORD
DsRolepSetBuiltinAdminAccountPassword(
IN LPWSTR Password
)
/*++
Routine Description:
This routine will change the password on the builtin administrator account to the one
specified
Arguments:
Password - Password to set
Return Values:
ERROR_SUCCESS - Success
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
SAM_HANDLE SamHandle, SamDomainHandle, SamAdministrator;
PPOLICY_ACCOUNT_DOMAIN_INFO AccountDomainInfo;
LSA_HANDLE PolicyHandle;
USER_ALL_INFORMATION UserAllInfo;
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING UserPassword;
RtlZeroMemory( &ObjectAttributes, sizeof( ObjectAttributes ) );
Status = LsaOpenPolicy( NULL,
&ObjectAttributes,
POLICY_VIEW_LOCAL_INFORMATION,
&PolicyHandle );
if ( NT_SUCCESS( Status ) ) {
Status = LsaQueryInformationPolicy( PolicyHandle,
PolicyAccountDomainInformation,
( PVOID * )&AccountDomainInfo );
LsaClose( PolicyHandle );
}
if ( NT_SUCCESS( Status ) ) {
Status = SamConnect( NULL,
&SamHandle,
MAXIMUM_ALLOWED,
&ObjectAttributes );
if ( NT_SUCCESS( Status ) ) {
//
// Open the builtin domain
//
Status = SamOpenDomain( SamHandle,
MAXIMUM_ALLOWED,
AccountDomainInfo->DomainSid,
&SamDomainHandle );
if ( NT_SUCCESS( Status ) ) {
Status = SamOpenUser( SamDomainHandle,
MAXIMUM_ALLOWED,
DOMAIN_USER_RID_ADMIN,
&SamAdministrator );
if ( NT_SUCCESS( Status ) ) {
RtlZeroMemory( &UserAllInfo, sizeof( USER_ALL_INFORMATION ) );
RtlInitUnicodeString( &UserPassword, Password );
UserAllInfo.NtPassword = UserPassword;
UserAllInfo.NtPasswordPresent = TRUE;
UserAllInfo.WhichFields = USER_ALL_NTPASSWORDPRESENT;
Status = SamSetInformationUser( SamAdministrator,
UserAllInformation,
( PSAMPR_USER_INFO_BUFFER )&UserAllInfo );
SamCloseHandle( SamAdministrator );
}
SamCloseHandle( SamDomainHandle );
}
SamCloseHandle( SamHandle );
}
LsaFreeMemory( AccountDomainInfo );
}
return( RtlNtStatusToDosError( Status ) );
}