/*++ File Description: This file contains the driver functions to modify the domain SID on a machine. Author: Matt Holle (matth) Oct 1997 --*/ // // System header files // #include // // Disable the DbgPrint for non-debug builds // #ifndef DBG #define _DBGNT_ #endif #include #include #include #include #include #ifdef IA64 #include #include #if defined(EFI_NVRAM_ENABLED) #include #include #endif #endif // // CRT header files // #include #include // // Private header files // #include "setupcl.h" #include "msg.h" #ifdef IA64 // Seed for GUID generator function: // // This is initialized first at the beginning of main() with the NtQuerySystemTime() // and then is updated every time the CreateNewGuid function is called. // We use the system time at the time CreateNewGuid is called for another part of the GUID. // This is done so that we achieve some variability accross machines, as the time delta between // calls to NtQuerySystemTime() should be somewhat different accross machines and invocations of // this program. // ULONG RandomSeed; #endif // Start time for setupcl. This is used so we can display a UI if setupcl takes longer than 15 seconds to // complete. Note that the checks for time only happen in the recursive function calls so if a step is added // to setupcl that takes a considerable amount of time DisplayUI() should be called as part of that step as well. // LARGE_INTEGER StartTime; LARGE_INTEGER CurrentTime; LARGE_INTEGER LastDotTime; // For putting up dots every few seconds. BOOL bDisplayUI = FALSE; // Initially don't display the UI. NTSTATUS ProcessHives( VOID ); NTSTATUS FinalHiveCleanup( VOID ); NTSTATUS ProcessRepairHives( VOID ); NTSTATUS RetrieveOldSid( VOID ); NTSTATUS GenerateUniqueSid( IN DWORD Seed ); NTSTATUS ProcessHives( VOID ) /*++ =============================================================================== Routine Description: This function check keys (and all subkeys) for: - keys with the old SID name - value keys with the old SID value Arguments: None. Return Value: NTSTATUS. =============================================================================== --*/ { ULONG i; NTSTATUS Status; PWSTR KeysToWhack[] = { // // SAM hive... // L"\\REGISTRY\\MACHINE\\SAM\\SAM", // // Security hive... // L"\\REGISTRY\\MACHINE\\SECURITY", // // Software hive... // L"\\REGISTRY\\MACHINE\\SOFTWARE", // // System hive... // L"\\REGISTRY\\MACHINE\\SYSTEM", }; LARGE_INTEGER Start_Time, End_Time; // // Record our start time. // NtQuerySystemTime( &Start_Time ); for( i = 0; i < sizeof(KeysToWhack) / sizeof(PWSTR); i++ ) { DbgPrint( "\nSETUPCL: ProcessHives - About to process %ws\n", KeysToWhack[i] ); Status = SiftKey( KeysToWhack[i] ); TEST_STATUS( "SETUPCL: ProcessHives - Failed to process key..." ); } // // Record our end time. // NtQuerySystemTime( &End_Time ); // // Record our execution time. // End_Time.QuadPart = End_Time.QuadPart - Start_Time.QuadPart; #if 0 Status = SetKey( TEXT(REG_SYSTEM_SETUP), TEXT("SetupCL_Run_Time"), (PUCHAR)&End_Time.LowPart, sizeof( DWORD ), REG_DWORD ); #endif return( Status ); } NTSTATUS FinalHiveCleanup( VOID ) /*++ =============================================================================== Routine Description: This function will go load each user-specific hive on the machine and propogate the new SID into it. Arguments: None. Return Value: NTSTATUS. =============================================================================== --*/ { NTSTATUS Status = STATUS_SUCCESS; OBJECT_ATTRIBUTES Obja; UNICODE_STRING UnicodeString, UnicodeValue; HANDLE hKey, hKeyChild; ULONG ResultLength, KeyValueLength, Index, LengthNeeded; PKEY_BASIC_INFORMATION KeyInfo; WCHAR KeyBuffer[BASIC_INFO_BUFFER_SIZE]; PKEY_VALUE_PARTIAL_INFORMATION KeyValueInfo = NULL; // // ======================== // User Profile Hives // ======================== // DbgPrint( "\nAbout to operate on user-specific profile hives.\n" ); // // We need to go check the user profile hives out on the disk. // If we find any, we need to change his ACLs to reflect the new // SID. // // // Open the PROFILELIST key. // INIT_OBJA( &Obja, &UnicodeString, TEXT( REG_SOFTWARE_PROFILELIST ) ); Status = NtOpenKey( &hKey, KEY_ALL_ACCESS, &Obja ); TEST_STATUS( "SETUPCL: FinalHiveCleanup - Failed to open PROFILELIST key." ); KeyInfo = (PKEY_BASIC_INFORMATION)KeyBuffer; // // Now enumerate all his subkeys and see if any of them have a // ProfileImagePath key. // for( Index = 0; ; Index++ ) { // Local variable. // DWORD dwPass; PWCHAR lpszHiveName[] = { L"\\NTUSER.DAT", L"\\Local Settings\\Application Data\\Microsoft\\Windows\\UsrClass.dat" }; Status = NtEnumerateKey( hKey, Index, KeyBasicInformation, KeyInfo, sizeof(KeyBuffer), &ResultLength ); if(!NT_SUCCESS(Status)) { if(Status == STATUS_NO_MORE_ENTRIES) { Status = STATUS_SUCCESS; } else { TEST_STATUS( "SETUPCL: FinalHiveCleanup - Failure during enumeration of subkeys." ); } break; } // // Zero-terminate the subkey name just in case. // KeyInfo->Name[KeyInfo->NameLength/sizeof(WCHAR)] = 0; DbgPrint( "SETUPCL: FinalHiveCleanup - enumerated %ws\n", KeyInfo->Name ); // // Generate a handle for this child key and open him too. // INIT_OBJA( &Obja, &UnicodeString, KeyInfo->Name ); Obja.RootDirectory = hKey; Status = NtOpenKey( &hKeyChild, KEY_ALL_ACCESS, &Obja ); // // ISSUE-2002/02/26-brucegr,jcohen - If NtOpenKey fails, hKey is leaked // TEST_STATUS_RETURN( "SETUPCL: FinalHiveCleanup - Failed to open child key." ); // // Now get the ProfileImagePath value. // RtlInitUnicodeString( &UnicodeString, TEXT( PROFILEIMAGEPATH ) ); // // How big of a buffer do we need? // Status = NtQueryValueKey( hKeyChild, &UnicodeString, KeyValuePartialInformation, NULL, 0, &LengthNeeded ); // // ISSUE-2002/02/26-brucegr,jcohen - Check for STATUS_SUCCESS, not assume success on STATUS_OBJECT_NAME_NOT_FOUND // if( Status == STATUS_OBJECT_NAME_NOT_FOUND ) { DbgPrint( "SETUPCL: FinalHiveCleanup - Unable to query key %ws size. Error (%lx)\n", TEXT( PROFILEIMAGEPATH ), Status ); } else { Status = STATUS_SUCCESS; } // // Allocate a block. // if( NT_SUCCESS( Status ) ) { if( KeyValueInfo ) { RtlFreeHeap( RtlProcessHeap(), 0, KeyValueInfo ); KeyValueInfo = NULL; } KeyValueInfo = (PKEY_VALUE_PARTIAL_INFORMATION)RtlAllocateHeap( RtlProcessHeap(), 0, LengthNeeded + 0x10 ); if( KeyValueInfo == NULL ) { DbgPrint( "SETUPCL: FinalHiveCleanup - Unable to allocate buffer\n" ); Status = STATUS_NO_MEMORY; } } // // Get the data. // if( NT_SUCCESS( Status ) ) { Status = NtQueryValueKey( hKeyChild, &UnicodeString, KeyValuePartialInformation, (PVOID)KeyValueInfo, LengthNeeded, &KeyValueLength ); if( !NT_SUCCESS( Status ) ) { DbgPrint( "SETUPCL: FinalHiveCleanup - Failed to query key %ws (%lx)\n", TEXT( PROFILEIMAGEPATH ), Status ); } } NtClose( hKeyChild ); // // Do two passes. First pass will be for the NTUSER.DAT hive and the second will be for // UsrClass.dat hive. // for ( dwPass = 0; dwPass < AS(lpszHiveName); dwPass++ ) { if( NT_SUCCESS( Status ) ) { PWCHAR TmpChar; ULONG i; memset( TmpBuffer, 0, sizeof(TmpBuffer) ); wcsncpy( TmpBuffer, (PWCHAR)&KeyValueInfo->Data, AS(TmpBuffer) - 1); // // We've got the path to the profile hive, but it will contain // an environment variable. Expand the variable. // DbgPrint( "SETUPCL: FinalHiveCleanup - Before the expand, I think his ProfileImagePath is: %ws\n", TmpBuffer ); RtlInitUnicodeString( &UnicodeString, TmpBuffer ); UnicodeValue.Length = 0; UnicodeValue.MaximumLength = MAX_PATH * sizeof(WCHAR); UnicodeValue.Buffer = (PWSTR)RtlAllocateHeap( RtlProcessHeap(), 0, UnicodeValue.MaximumLength ); // // Prefix Bug # 111373. // if ( UnicodeValue.Buffer ) { RtlZeroMemory( UnicodeValue.Buffer, UnicodeValue.MaximumLength ); Status = RtlExpandEnvironmentStrings_U( NULL, &UnicodeString, &UnicodeValue, NULL ); // // RtlExpandEnvironmentStrings_U has given us a path, but // it will contain a drive letter. We need an NT path. // Go convert it. // if( NT_SUCCESS( Status ) && ( (UnicodeValue.Length + (wcslen(lpszHiveName[dwPass]) * sizeof(WCHAR))) < sizeof(TmpBuffer) ) ) { WCHAR DriveLetter[3]; WCHAR NTPath[MAX_PATH] = {0}; // // TmpBuffer will contain the complete path, except // he's got the drive letter. // RtlCopyMemory( TmpBuffer, UnicodeValue.Buffer, UnicodeValue.Length ); TmpBuffer[(UnicodeValue.Length / sizeof(WCHAR))] = 0; wcscat( TmpBuffer, lpszHiveName[dwPass] ); DbgPrint( "SETUPCL: FinalHiveCleanup - I think the dospath to his ProfileImagePath is: %ws\n", TmpBuffer ); DriveLetter[0] = TmpBuffer[0]; DriveLetter[1] = L':'; DriveLetter[2] = 0; // // Get the symbolic link from the drive letter. // Status = DriveLetterToNTPath( DriveLetter[0], NTPath, AS(NTPath) ); if( NT_SUCCESS( Status ) ) { // // Translation was successful. Insert the ntpath into our // path to the profile. // Status = StringSwitchString( TmpBuffer, AS(TmpBuffer), DriveLetter, NTPath ); } else { DbgPrint( "SETUPCL: FinalHiveCleanup - We failed our call to DriveLetterToNTPath (%lx)\n", Status ); } DbgPrint( "SETUPCL: FinalHiveCleanup - After the expand, I think his ProfileImagePath is: %ws\n", TmpBuffer ); } else { DbgPrint( "SETUPCL: FinalHiveCleanup - We failed our call to RtlExpandEnvironmentStrings_U (%lx)\n", Status ); } RtlFreeHeap( RtlProcessHeap(), 0, UnicodeValue.Buffer ); } // // Attempt to load the hive, open his root key, then // go swap ACLs on all the subkeys. // Status = LoadUnloadHive( TEXT( TMP_HIVE_NAME ), TmpBuffer ); if( NT_SUCCESS( Status ) ) { // // Let's go search for any instance of the SID in our // newly loaded hive. // Status = SiftKey( TEXT( TMP_HIVE_NAME ) ); TEST_STATUS( "SETUPCL: FinalHiveCleanup - Failed to push new sid into user's hive." ); #if 0 // // Move call to SetKeySecurityRecursive into // SiftKey so that implicitly fixup ACLs too. // // // Open the root of our newly loaded hive. // INIT_OBJA( &Obja, &UnicodeString, TEXT( TMP_HIVE_NAME ) ); Status = NtOpenKey( &hKeyChild, KEY_ALL_ACCESS, &Obja ); // // Now go attempt to whack the ACLs on this, and // all subkeys. // if( NT_SUCCESS( Status ) ) { SetKeySecurityRecursive( hKeyChild ); NtClose( hKeyChild ); } else { DbgPrint( "SETUPCL: FinalHiveCleanup - Failed open of TmpHive root.\n" ); } #endif LoadUnloadHive( TEXT( TMP_HIVE_NAME ), NULL ); } else { DbgPrint( "SETUPCL: FinalHiveCleanup - Failed load of TmpHive.\n" ); } } } } NtClose( hKey ); // // ======================== // \REGISTRY\MACHINE\SYSTEM\CURRENTCONTROLSET\CONTROL\REGISTRYSIZELIMIT // ======================== // DbgPrint( "\nAbout to operate on SYSTEM\\CURRENTCONTROLSET\\CONTROL\\REGISTRYSIZELIMIT.\n" ); // // sysprep bumped the registry limit up by 4Mb. We need to lower it // back down. // INIT_OBJA( &Obja, &UnicodeString, TEXT(REG_SYSTEM_CONTROL) ); Status = NtOpenKey( &hKey, KEY_ALL_ACCESS, &Obja ); TEST_STATUS( "SETUPCL: ProcessSYSTEMHive - Failed to open Control key!" ); // // ISSUE-2002/02/26-brucegr,jcohen - Shouldn't try to query value if NtOpenKey fails! // // // Get the data out of this key. // RtlInitUnicodeString(&UnicodeString, TEXT(REG_SIZE_LIMIT) ); // // How big of a buffer do we need? // Status = NtQueryValueKey( hKey, &UnicodeString, KeyValuePartialInformation, NULL, 0, &LengthNeeded ); // // ISSUE-2002/02/26-brucegr,jcohen - Check for STATUS_SUCCESS, not assume success on STATUS_OBJECT_NAME_NOT_FOUND // if( Status == STATUS_OBJECT_NAME_NOT_FOUND ) { DbgPrint( "SETUPCL: FinalHiveCleanup - Unable to query key %ws size. Error (%lx)\n", TEXT(REG_SIZE_LIMIT), Status ); } else { Status = STATUS_SUCCESS; } // // Allocate a block. // if( NT_SUCCESS( Status ) ) { if( KeyValueInfo ) { RtlFreeHeap( RtlProcessHeap(), 0, KeyValueInfo ); KeyValueInfo = NULL; } KeyValueInfo = (PKEY_VALUE_PARTIAL_INFORMATION)RtlAllocateHeap( RtlProcessHeap(), 0, LengthNeeded + 0x10 ); if( KeyValueInfo == NULL ) { DbgPrint( "SETUPCL: FinalHiveCleanup - Unable to allocate buffer\n" ); Status = STATUS_NO_MEMORY; } } // // Get the data. // if( NT_SUCCESS( Status ) ) { Status = NtQueryValueKey( hKey, &UnicodeString, KeyValuePartialInformation, (PVOID)KeyValueInfo, LengthNeeded, &KeyValueLength ); if( !NT_SUCCESS( Status ) ) { DbgPrint( "SETUPCL: FinalHiveCleanup - Failed to query key %ws (%lx)\n", TEXT(REG_SIZE_LIMIT), Status ); } else{ Index = *(PDWORD)(&KeyValueInfo->Data); Index = Index - REGISTRY_QUOTA_BUMP; //Bring it back to original value // // Set him. // Status = SetKey( TEXT(REG_SYSTEM_CONTROL), TEXT(REG_SIZE_LIMIT), (PUCHAR)&Index, sizeof( DWORD ), REG_DWORD ); DbgPrint("SETUPCL: ProcessSYSTEMHive - Size allocated = %lx\n",Index); TEST_STATUS( "SETUPCL: ProcessSYSTEMHive - Failed to update SYSTEM\\CURRENTCONTROLSET\\CONTROL\\REGISTRYSIZELIMIT key." ); } } NtClose( hKey ); // // ======================== // \REGISTRY\MACHINE\SYSTEM\CURRENTCONTROLSET\Control\Session Manager\SetupExecute // ======================== // DbgPrint( "\nAbout to operate on SYSTEM\\CURRENTCONTROLSET\\CONTROL\\SESSION MANAGER\\SETUPEXECUTE key.\n" ); // // Open the Session manager key. // INIT_OBJA( &Obja, &UnicodeString, TEXT(REG_SYSTEM_SESSIONMANAGER) ); Status = NtOpenKey( &hKey, KEY_ALL_ACCESS, &Obja ); TEST_STATUS_RETURN( "SETUPCL: ProcessSYSTEMHive - Failed to open Session Manager key!" ); // // Now delete the SetupExecute Key. // RtlInitUnicodeString(&UnicodeString, TEXT(EXECUTE) ); Status = NtDeleteValueKey( hKey, &UnicodeString ); NtClose( hKey ); TEST_STATUS( "SETUPCL: ProcessSYSTEMHive - Failed to update SYSTEM\\CURRENTCONTROLSET\\CONTROL\\SESSION MANAGER\\SETUPEXECUTE key." ); if( KeyValueInfo ) { RtlFreeHeap( RtlProcessHeap(), 0, KeyValueInfo ); KeyValueInfo = NULL; } return Status; } NTSTATUS ProcessRepairHives( VOID ) /*++ =============================================================================== Routine Description: This function check keys (and all subkeys) for: - keys with the old SID name - value keys with the old SID value Arguments: None. Return Value: NTSTATUS. =============================================================================== --*/ { ULONG i; NTSTATUS Status; PWSTR KeysToWhack[] = { // // SAM hive... // L"\\REGISTRY\\MACHINE\\RSAM", // // Security hive... // L"\\REGISTRY\\MACHINE\\RSECURITY", // // Software hive... // L"\\REGISTRY\\MACHINE\\RSOFTWARE", // // System hive... // L"\\REGISTRY\\MACHINE\\RSYSTEM", }; PWSTR KeysToLoad[] = { // // SAM hive... // L"\\SYSTEMROOT\\REPAIR\\SAM", // // Security hive... // L"\\SYSTEMROOT\\REPAIR\\SECURITY", // // Software hive... // L"\\SYSTEMROOT\\REPAIR\\SOFTWARE", // // System hive... // L"\\SYSTEMROOT\\REPAIR\\SYSTEM", }; for( i = 0; i < sizeof(KeysToWhack) / sizeof(PWSTR); i++ ) { // // Load the repair hive. // DbgPrint( "\nSETUPCL: ProcessRepairHives - About to load %ws hive.\n", KeysToLoad[i] ); Status = LoadUnloadHive( KeysToWhack[i], KeysToLoad[i] ); TEST_STATUS_RETURN( "SETUPCL: ProcessRepairHives - Failed to load repair hive." ); // // Now operate on it. // DbgPrint( "SETUPCL: ProcessRepairHives - About to process %ws\n", KeysToWhack[i] ); Status = SiftKey( KeysToWhack[i] ); TEST_STATUS( "SETUPCL: ProcessRepairHives - Failed to process key..." ); // // Unload the hive. // DbgPrint( "SETUPCL: ProcessRepairHives - About to unload %ws hive.\n", KeysToLoad[i] ); Status = LoadUnloadHive( KeysToWhack[i], NULL ); TEST_STATUS( "SETUPCL: ProcessRepairHives - Failed to unload repair hive." ); } return( Status ); } NTSTATUS RetrieveOldSid( VOID ) /*++ =============================================================================== Routine Description: Retrieves the current SID (as read from the registry. Use RtlFreeSid() to free the SID allocated by this routine. Arguments: Return Value: Status code indicating outcome. =============================================================================== --*/ { NTSTATUS Status; HANDLE hKey; PKEY_VALUE_PARTIAL_INFORMATION KeyValueInfo = NULL; OBJECT_ATTRIBUTES ObjectAttributes; UNICODE_STRING UnicodeString; ULONG KeyValueLength, LengthNeeded; UNICODE_STRING SidString; // // We can conveniently retrieve our SID from // \registry\machine\Security\Policy\PolAcDmS\ // // We'll open him up, read his data, then blast that into // a SID structure. // // // Open the PolAcDmS key. // INIT_OBJA( &ObjectAttributes, &UnicodeString, TEXT(REG_SECURITY_POLACDMS) ); Status = NtOpenKey( &hKey, KEY_ALL_ACCESS, &ObjectAttributes ); TEST_STATUS_RETURN( "SETUPCL: RetrieveOldSid - Failed to open PolAcDmS key!" ); // // Get the data out of this key. // RtlInitUnicodeString(&UnicodeString, TEXT("") ); // // How big of a buffer do we need? // Status = NtQueryValueKey( hKey, &UnicodeString, KeyValuePartialInformation, NULL, 0, &LengthNeeded ); // // ISSUE-2002/02/26-brucegr,jcohen - Check for STATUS_SUCCESS, not assume success on STATUS_OBJECT_NAME_NOT_FOUND // if( Status == STATUS_OBJECT_NAME_NOT_FOUND ) { DbgPrint( "SETUPCL: RetrieveOldSid - Unable to query size of old sid. Error (%lx)\n", Status ); } else { Status = STATUS_SUCCESS; } // // Allocate a block. // if( NT_SUCCESS( Status ) ) { // // ISSUE-2002/02/26-brucegr,jcohen - This block will never get hit // if( KeyValueInfo ) { RtlFreeHeap( RtlProcessHeap(), 0, KeyValueInfo ); KeyValueInfo = NULL; } KeyValueInfo = (PKEY_VALUE_PARTIAL_INFORMATION)RtlAllocateHeap( RtlProcessHeap(), 0, LengthNeeded + 0x10 ); if( KeyValueInfo == NULL ) { DbgPrint( "SETUPCL: RetrieveOldSid - Unable to allocate buffer\n" ); Status = STATUS_NO_MEMORY; } } // // Get the data. // if( NT_SUCCESS( Status ) ) { Status = NtQueryValueKey( hKey, &UnicodeString, KeyValuePartialInformation, (PVOID)KeyValueInfo, LengthNeeded, &KeyValueLength ); if( !NT_SUCCESS( Status ) ) { DbgPrint( "SETUPCL: RetrieveOldSid - Failed to query old sid key (%lx)\n", Status ); } } TEST_STATUS_RETURN( "SETUPCL: RetrieveOldSid - Failed to query PolAcDmS key!" ); // // Allocate space for our new SID. // G_OldSid = RtlAllocateHeap( RtlProcessHeap(), 0, SID_SIZE ); if( G_OldSid == NULL ) { DbgPrint( "SETUPCL: Call to RtlAllocateHeap failed!\n" ); return( STATUS_NO_MEMORY ); } // // Blast our Old SID into the memory we just allocated... // RtlCopyMemory( G_OldSid, ((PUCHAR)&KeyValueInfo->Data), SID_SIZE ); // // ISSUE-2002/02/26-brucegr,jcohen - Close the key sooner! // NtClose( hKey ); // // I need to get a text version of the 3 values that make // up this SID's uniqueness. This is pretty gross. It turns // out that the first 8 characters of the SID string (as gotten // from a call to RtlConvertSidtoUnicodeString) are the same // for any Domain SID. And it's always the 9th character that // starts the 3 unique numbers. // Status = RtlConvertSidToUnicodeString( &SidString, G_OldSid, TRUE ); TEST_STATUS_RETURN( "SETUPCL: RetrieveOldSid - RtlConvertSidToUnicodeString failed!" ); memset( G_OldSidSubString, 0, sizeof(G_OldSidSubString) ); wcsncpy( G_OldSidSubString, &SidString.Buffer[9], AS(G_OldSidSubString) - 1 ); #ifdef DBG // // Debug spew. // { int i; DbgPrint( "SETUPCL: RetrieveOldSid - Retrieved SID:\n" ); for( i = 0; i < SID_SIZE; i += 4 ) { DbgPrint( "%08lx ", *(PULONG)((PUCHAR)(G_OldSid) + i)); } DbgPrint( "\n" ); DbgPrint("Old Sid = %ws \n",SidString.Buffer); } #endif RtlFreeUnicodeString( &SidString ); // // ISSUE-2002/02/26-brucegr,jcohen - Free the value buffer sooner? Do we need to assign KeyValueInfo to NULL after we're done with it? // if( KeyValueInfo ) { RtlFreeHeap( RtlProcessHeap(), 0, KeyValueInfo ); KeyValueInfo = NULL; } return( STATUS_SUCCESS ); } BOOL SetupGenRandom( OUT PVOID pbRandomKey, IN ULONG cbRandomKey ) { BOOL fRet = FALSE; HANDLE hFile; NTSTATUS Status; UNICODE_STRING DriverName; IO_STATUS_BLOCK IOSB; OBJECT_ATTRIBUTES ObjA; // // have to use the Nt flavor of the file open call because it's a base // device not aliased to \DosDevices // RtlInitUnicodeString( &DriverName, DD_KSEC_DEVICE_NAME_U ); InitializeObjectAttributes( &ObjA, &DriverName, OBJ_CASE_INSENSITIVE, 0, 0 ); Status = NtOpenFile( &hFile, SYNCHRONIZE | FILE_READ_DATA, &ObjA, &IOSB, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_SYNCHRONOUS_IO_ALERT ); if ( NT_SUCCESS(Status) ) { Status = NtDeviceIoControlFile( hFile, NULL, NULL, NULL, &IOSB, IOCTL_KSEC_RNG_REKEY, // indicate a RNG rekey NULL, // input buffer (existing material) 0, // input buffer size pbRandomKey, // output buffer cbRandomKey ); // output buffer size if ( NT_SUCCESS(Status) ) { fRet = TRUE; } else { PRINT_STATUS( "SetupGenRandom: NtDeviceIoControlFile failed!" ); } NtClose( hFile ); } else { PRINT_STATUS( "SetupGenRandom: NtOpenFile failed!" ); } return fRet; } NTSTATUS SetupGenerateRandomDomainSid( OUT PSID NewDomainSid ) /*++ Routine Description: This function will generate a random sid to be used for the new account domain sid during setup. Arguments: NewDomainSid - Where the new domain sid is returned. Freed via RtlFreeSid() Return Values: STATUS_SUCCESS -- Success. STATUS_INVALID_PARAMETER -- We couldn't generate a random number STATUS_INSUFFICIENT_RESOURCES -- A memory allocation failed --*/ { NTSTATUS Status = STATUS_INVALID_PARAMETER; ULONG SubAuth1, SubAuth2, SubAuth3; // // Generate three random numbers for the new domain SID... // if ( SetupGenRandom( &SubAuth1, sizeof(SubAuth1) ) && SetupGenRandom( &SubAuth2, sizeof(SubAuth2) ) && SetupGenRandom( &SubAuth3, sizeof(SubAuth3) ) ) { SID_IDENTIFIER_AUTHORITY IdentifierAuthority = SECURITY_NT_AUTHORITY; #ifdef DBG DbgPrint( "New SID: 0x%lx, 0x%lx, 0x%lx\n", SubAuth1, SubAuth2, SubAuth3 ); #endif Status = RtlAllocateAndInitializeSid( &IdentifierAuthority, 4, 0x15, SubAuth1, SubAuth2, SubAuth3, 0, 0, 0, 0, NewDomainSid ); } return( Status ); } NTSTATUS GenerateUniqueSid( IN DWORD Seed ) /*++ =============================================================================== Routine Description: Generates a (hopefully) unique SID for use by Setup. Setup uses this SID as the Domain SID for the Account domain. Use RtlFreeSid() to free the SID allocated by this routine. Arguments: Sid - On return points to the created SID. Return Value: Status code indicating outcome. =============================================================================== --*/ { NTSTATUS Status; HANDLE hKey; UNICODE_STRING SidString; PKEY_VALUE_PARTIAL_INFORMATION KeyValueInfo = NULL; // // Use the same logic as LSASS to generate a unique system SID... // Status = SetupGenerateRandomDomainSid( &G_NewSid ); TEST_STATUS_RETURN( "SETUPCL: GenerateUniqueSid - LsapGenerateRandomDomainSid failed!" ); // // I need to get a text version of the 3 values that make // up this SID's uniqueness. This is pretty gross. It turns // out that the first 8 characters of the SID string (as gotten // from a call to RtlConvertSidtoUnicodeString) are the same // for any Domain SID. And it's always the 9th character that // starts the 3 unique numbers. // Status = RtlConvertSidToUnicodeString( &SidString, G_NewSid, TRUE ); TEST_STATUS_RETURN( "SETUPCL: GenerateUniqueSid - RtlConvertSidToUnicodeString failed!" ); wcscpy( G_NewSidSubString, &SidString.Buffer[9] ); #ifdef DBG // // Debug spew. // { int i; DbgPrint( "SETUPCL: SetupGenerateUniqueSid - Generated SID:\n" ); for( i = 0; i < SID_SIZE; i += 4 ) { DbgPrint( "%08lx ", *(PULONG)((PUCHAR)(G_NewSid) + i)); } DbgPrint( "\n" ); DbgPrint("Generated Sid = %ws \n",SidString.Buffer); } #endif RtlFreeUnicodeString( &SidString ); if( KeyValueInfo ) { RtlFreeHeap( RtlProcessHeap(), 0, KeyValueInfo ); KeyValueInfo = NULL; } return Status; } #ifdef IA64 VOID CreateNewGuid( IN GUID *Guid ) /*++ Routine Description: Creates a new pseudo GUID. Arguments: Guid - Place holder for the new pseudo Return Value: None. --*/ { if (Guid) { LARGE_INTEGER Time; ULONG Random1 = RtlRandom(&RandomSeed); ULONG Random2 = RtlRandom(&RandomSeed); // // Get system time // NtQuerySystemTime(&Time); RtlZeroMemory(Guid, sizeof(GUID)); // // First 8 bytes is system time // RtlCopyMemory(Guid, &(Time.QuadPart), sizeof(Time.QuadPart)); // // Next 8 bytes are two random numbers // RtlCopyMemory(Guid->Data4, &Random1, sizeof(ULONG)); RtlCopyMemory(((PCHAR)Guid->Data4) + sizeof(ULONG), &Random2, sizeof(ULONG)); } } VOID* MyMalloc(size_t Size) { return RtlAllocateHeap( RtlProcessHeap(), HEAP_ZERO_MEMORY, Size ); } VOID MyFree(VOID *Memory) { RtlFreeHeap( RtlProcessHeap(), 0, Memory ); } NTSTATUS GetAndWriteBootEntry( IN POS_BOOT_ENTRY pBootEntry ) /*++ Routine Description: Get the boot entry from NVRAM for the given boot entry Id. Construct a filename of the form BootXXXX, where XXXX = id. Put the file in the same directory as the EFI OS loader. The directory is determined from the LoaderFile string. Arguments: pBootEntry pointer to the POS_BOOT_ENTRY structure Return Value: NTSTATUS Remarks: This was ported from \textmode\kernel\spboot.c on 6/9/2001. --*/ { NTSTATUS status; UNICODE_STRING idStringUnicode; WCHAR idStringWChar[9] = {0}; WCHAR BootEntryPath[MAX_PATH] = {0}; HANDLE hfile; OBJECT_ATTRIBUTES oa; IO_STATUS_BLOCK iostatus; UCHAR* bootVar = NULL; ULONG bootVarSize; UNICODE_STRING uFilePath; UINT64 BootNumber; UINT64 BootSize; GUID EfiBootVariablesGuid = EFI_GLOBAL_VARIABLE; ULONG Id = 0; WCHAR* pwsFilePart = NULL; hfile = NULL; if (NULL == pBootEntry) return STATUS_INVALID_PARAMETER; // // BootEntryPath = OsLoaderVolumeName + OsLoaderPath // OsLoaderVolumeName = "\Device\HarddriveVolume1" // OsLoaderPath = "\Efi\Microsoft\Winnt50\ia64ldr.efi" // Then Strip off the ia64ldr.efi and replace with BootXXX. // wcsncpy(BootEntryPath, pBootEntry->OsLoaderVolumeName, AS(BootEntryPath) - 1); wcsncpy(BootEntryPath + wcslen(BootEntryPath), pBootEntry->OsLoaderPath, AS(BootEntryPath) - wcslen(BootEntryPath) - 1); // // Backup to last backslash before ia64ldr.efi careful of clength // pwsFilePart = wcsrchr(BootEntryPath, L'\\'); *(++pwsFilePart) = L'\0'; // // Id = BootEntry Id // Id = pBootEntry->Id; // // Retrieve the NVRAM entry for the Id specified // _snwprintf( idStringWChar, AS(idStringWChar) - 1, L"Boot%04x", Id); // // Append the BootXXXX // wcsncpy(BootEntryPath + wcslen(BootEntryPath), idStringWChar, AS(BootEntryPath) - wcslen(BootEntryPath) - 1); DbgPrint("SETUPCL: Writing to NVRBoot file %ws.\n", BootEntryPath); RtlInitUnicodeString( &idStringUnicode, idStringWChar); bootVarSize = 0; status = NtQuerySystemEnvironmentValueEx(&idStringUnicode, &EfiBootVariablesGuid, NULL, &bootVarSize, NULL); if (status != STATUS_BUFFER_TOO_SMALL) { ASSERT(FALSE); DbgPrint("SETUPCL: Failed to get size for boot entry buffer.\n"); goto Done; } else { bootVar = RtlAllocateHeap(RtlProcessHeap(), 0, bootVarSize); if (!bootVar) { status = STATUS_NO_MEMORY; DbgPrint("SETUPCL: Failed to allocate boot entry buffer.\n"); goto Done; } status = NtQuerySystemEnvironmentValueEx(&idStringUnicode, &EfiBootVariablesGuid, bootVar, &bootVarSize, NULL); if (status != STATUS_SUCCESS) { ASSERT(FALSE); DbgPrint("SETUPCL: Failed to get boot entry.\n"); goto Done; } } // // open the file // INIT_OBJA(&oa, &uFilePath, BootEntryPath); status = NtCreateFile(&hfile, FILE_GENERIC_READ | FILE_GENERIC_WRITE, &oa, &iostatus, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OVERWRITE_IF, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0 ); if ( ! NT_SUCCESS(status) ) { DbgPrint("SETUPCL: Failed to create boot entry recovery file %lx.\n", status); goto Done; } // // Write the bits to disk using the format required // by base/efiutil/efinvram/savrstor.c // // [BootNumber][BootSize][BootEntry (of BootSize)] // // // build the header info for the boot entry block // // [header] include the boot id BootNumber = Id; status = NtWriteFile( hfile, NULL, NULL, NULL, &iostatus, &BootNumber, sizeof(BootNumber), NULL, NULL ); if ( ! NT_SUCCESS(status) ) { DbgPrint("SETUPCL: Failed writing boot number to boot entry recovery file.\n"); goto Done; } // [header] include the boot size BootSize = bootVarSize; status = NtWriteFile( hfile, NULL, NULL, NULL, &iostatus, &BootSize, sizeof(BootSize), NULL, NULL ); if ( ! NT_SUCCESS(status) ) { DbgPrint("SETUPCL: Failed writing boot entry size to boot entry recovery file.\n"); goto Done; } // boot entry bits status = NtWriteFile( hfile, NULL, NULL, NULL, &iostatus, bootVar, bootVarSize, NULL, NULL ); if ( ! NT_SUCCESS(status) ) { DbgPrint("SETUPCL: Failed writing boot entry to boot entry recovery file.\n"); goto Done; } Done: // // We are done // if (bootVar) { RtlFreeHeap(RtlProcessHeap(), 0, bootVar); } if (hfile) { NtClose( hfile ); } return status; } NTSTATUS ResetDiskGuids(VOID) { NTSTATUS Status; SYSTEM_DEVICE_INFORMATION sdi; ULONG iDrive; // Clean up the memory // RtlZeroMemory(&sdi, sizeof(sdi)); // Query the number of physical devices on the system // Status = NtQuerySystemInformation(SystemDeviceInformation, &sdi, sizeof(SYSTEM_DEVICE_INFORMATION), NULL); // We successfully queried the devices and there are devices there // if ( NT_SUCCESS(Status) && sdi.NumberOfDisks) { POS_BOOT_OPTIONS pBootOptions = NULL; POS_BOOT_OPTIONS pBootOptionsInitial = NULL; POS_BOOT_ENTRY pBootEntry = NULL; DbgPrint("Successfully queried (%lx) disks.\n", sdi.NumberOfDisks); // Initialize the library with our own memory management functions // if ( OSBOLibraryInit(MyMalloc, MyFree) ) { // Determine initial BootOptions // pBootOptions = EFIOSBOCreate(); pBootOptionsInitial = EFIOSBOCreate(); // Were we able to create the BootOptions // if ( pBootOptions && pBootOptionsInitial ) { // Iterate through each disk and determine the GUID // for ( iDrive = 0; iDrive < sdi.NumberOfDisks && NT_SUCCESS(Status); iDrive++ ) { WCHAR szPhysicalDrives[MAX_PATH] = {0}; UNICODE_STRING UnicodeString; OBJECT_ATTRIBUTES Obja; HANDLE DiskHandle; IO_STATUS_BLOCK IoStatusBlock; // Generate the path to the drive // _snwprintf(szPhysicalDrives, AS(szPhysicalDrives) - 1, L"\\Device\\Harddisk%d\\Partition0", iDrive); // Initialize the handle to unicode string // INIT_OBJA(&Obja,&UnicodeString,szPhysicalDrives); // Attempt to open the file // Status = NtCreateFile( &DiskHandle, FILE_GENERIC_READ | FILE_GENERIC_WRITE, &Obja, &IoStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN, 0, NULL, 0 ); // Check to see if we were able to open the disk // if ( !NT_SUCCESS(Status) ) { DbgPrint("Unable to open file on %ws. Error (%lx)\n", szPhysicalDrives, Status); } else { PDRIVE_LAYOUT_INFORMATION_EX pLayoutInfoEx = NULL; ULONG lengthLayoutEx = 0, iPart; DbgPrint("Successfully opened file on %ws\n", szPhysicalDrives); lengthLayoutEx = sizeof(DRIVE_LAYOUT_INFORMATION_EX) + (sizeof(PARTITION_INFORMATION_EX) * 128); pLayoutInfoEx = (PDRIVE_LAYOUT_INFORMATION_EX) MyMalloc( lengthLayoutEx ); if ( pLayoutInfoEx ) { // Attempt to get the drive layout // Status = NtDeviceIoControlFile( DiskHandle, 0, NULL, NULL, &IoStatusBlock, IOCTL_DISK_GET_DRIVE_LAYOUT_EX, NULL, 0, pLayoutInfoEx, lengthLayoutEx ); // Check the status of the drive layout // if ( !NT_SUCCESS(Status) ) DbgPrint("Unable to open IOCTL on %ws. Error (%lx)\n", szPhysicalDrives, Status); else { DbgPrint("Opened IOCTL on drive %ws. Error (%lx)\n", szPhysicalDrives, Status); DbgPrint("\tPhysical Disk %d\n", iDrive); DbgPrint("\tPartition Count: %d\n", pLayoutInfoEx->PartitionCount); // Iterate through each partition // for (iPart = 0; iPart < pLayoutInfoEx->PartitionCount; iPart++) { // We only would like to deal with GPT partitions // if ( pLayoutInfoEx->PartitionEntry[iPart].PartitionStyle == PARTITION_STYLE_GPT ) { const UUID GuidNull = { 0 }; #ifdef DBG UNICODE_STRING cGuid; UNICODE_STRING cGuidNew; #endif // Only replace the Guid if it's NULL. // if (IsEqualGUID(&(pLayoutInfoEx->PartitionEntry[iPart].Gpt.PartitionId), &GuidNull)) { // // ISSUE-2002/02/26-brucegr,jcohen - CreateNewGuid expects GUID structure. Possible mismatch? // // (acosma 2002/04/24) Fix this issue in Longhorn. UUID is typedef to GUID or the // other way around so they are the same thing, however for readability we will fix this. // UUID Guid; // Create a new GUID for this machine // CreateNewGuid(&Guid); #ifdef DBG if ( NT_SUCCESS( RtlStringFromGUID((LPGUID) &(pLayoutInfoEx->PartitionEntry[iPart].Gpt.PartitionId), &cGuid) ) ) { if ( NT_SUCCESS( RtlStringFromGUID((LPGUID) &Guid, &cGuidNew) ) ) { DbgPrint("\tPartition: %ws (%x), %ws %ws\n", pLayoutInfoEx->PartitionEntry[iPart].Gpt.Name, iPart, cGuid.Buffer, cGuidNew.Buffer); RtlFreeUnicodeString(&cGuidNew); } RtlFreeUnicodeString(&cGuid); } #endif // This is a struct to struct assignment. It is legal in C. // pLayoutInfoEx->PartitionEntry[iPart].Gpt.PartitionId = Guid; } } } } TEST_STATUS("SETUPCL: ResetDiskGuids - Failed to reset Disk Guids."); if ( NT_SUCCESS( Status = NtDeviceIoControlFile( DiskHandle, 0, NULL, NULL, &IoStatusBlock, IOCTL_DISK_SET_DRIVE_LAYOUT_EX, pLayoutInfoEx, lengthLayoutEx, NULL, 0 ) ) ) { DbgPrint("\tSuccessfully reset %ws\n", szPhysicalDrives); } // // Free the layout info buffer... // MyFree( pLayoutInfoEx ); } // Clean up the memory // NtClose( DiskHandle ); } } // Delete the old boot entries and recreate them so we pick up the new GUIDS if they changed. // if ( NT_SUCCESS(Status) ) { POS_BOOT_ENTRY pActiveBootEntry = NULL; DWORD dwBootEntryCount = OSBOGetBootEntryCount(pBootOptionsInitial); DbgPrint("SETUPCL: ResetDiskGuids - Updating boot entries to use new GUIDS.\n"); if (dwBootEntryCount) { ULONG Index; BOOL bSetActive = FALSE; // Get the current boot entry // pActiveBootEntry = OSBOGetActiveBootEntry(pBootOptionsInitial); pBootEntry = OSBOGetFirstBootEntry(pBootOptionsInitial, &Index); while ( pBootEntry ) { // Don't set the current entry active by default. // bSetActive = FALSE; if ( OSBE_IS_WINDOWS(pBootEntry) ) { POS_BOOT_ENTRY pBootEntryToDelete = NULL; WCHAR FriendlyName[MAX_PATH], OsLoaderVolumeName[MAX_PATH], OsLoaderPath[MAX_PATH], BootVolumeName[MAX_PATH], BootPath[MAX_PATH], OsLoadOptions[MAX_PATH]; // Load the boot entry parameters into their own buffer // memset(FriendlyName, 0, AS(FriendlyName)); memset(OsLoaderVolumeName, 0, AS(OsLoaderVolumeName)); memset(OsLoaderPath, 0, AS(OsLoaderPath)); memset(BootVolumeName, 0, AS(BootVolumeName)); memset(BootPath, 0, AS(BootPath)); memset(OsLoadOptions, 0, AS(OsLoadOptions)); wcsncpy(FriendlyName, OSBEGetFriendlyName(pBootEntry), AS(FriendlyName) - 1); wcsncpy(OsLoaderVolumeName, OSBEGetOsLoaderVolumeName(pBootEntry), AS(OsLoaderVolumeName) - 1); wcsncpy(OsLoaderPath, OSBEGetOsLoaderPath(pBootEntry), AS(OsLoaderPath) - 1); wcsncpy(BootVolumeName, OSBEGetBootVolumeName(pBootEntry), AS(BootVolumeName) - 1); wcsncpy(BootPath, OSBEGetBootPath(pBootEntry), AS(BootPath) - 1); wcsncpy(OsLoadOptions, OSBEGetOsLoadOptions(pBootEntry), AS(OsLoadOptions) - 1); // If this is the active boot entry set active the new boot entry that we are going to create. // if ( pBootEntry == pActiveBootEntry ) { bSetActive = TRUE; } if ( ( pBootEntryToDelete = OSBOFindBootEntry(pBootOptions, pBootEntry->Id) ) && OSBODeleteBootEntry(pBootOptions, pBootEntryToDelete) ) { POS_BOOT_ENTRY pBootEntryNew = NULL; pBootEntryNew = OSBOAddNewBootEntry(pBootOptions, FriendlyName, OsLoaderVolumeName, OsLoaderPath, BootVolumeName, BootPath, OsLoadOptions); if ( pBootEntryNew ) { if ( bSetActive ) { OSBOSetActiveBootEntry(pBootOptions, pBootEntryNew); } // Update the NVRBoot file // GetAndWriteBootEntry(pBootEntryNew); // Flush out the boot options // OSBEFlush(pBootEntryNew); } else { DbgPrint("SETUPCL: ResetDiskGuids - Failed to add a boot entry [%ws]\n", FriendlyName); } } else { DbgPrint("SETUPCL: ResetDiskGuids - Failed to delete a boot entry [%ws]\n", FriendlyName); } } // Get the next entry. // pBootEntry = OSBOGetNextBootEntry(pBootOptionsInitial, &Index); } } // Flush the boot options if we've changed GUIDS. // OSBOFlush(pBootOptions); } } else { DbgPrint("SETUPCL: ResetDiskGuids - Failed to load the existing boot entries.\n"); } // // Free the boot option structures. // if ( pBootOptions ) { OSBODelete(pBootOptions); } if ( pBootOptionsInitial ) { OSBODelete(pBootOptionsInitial); } } else { DbgPrint("SETUPCL: ResetDiskGuids - Failed to initialize the boot options library.\n"); } } return Status; } #endif \\ #ifdef IA64 // This function always deletes a CRLF from the end of the string. It assumes that there // is a CRLF at the end of the line and just removes the last two characters. // void OutputString(LPTSTR szMsg) { UNICODE_STRING uMsg; RtlInitUnicodeString(&uMsg, szMsg); // Whack the CRLF at the end of the string. Doing this here for performance reasons. // Don't want to put this in DisplayUI(). // if (uMsg.Length > ( 2 * sizeof(WCHAR)) ) { uMsg.Length -= (2 * sizeof(WCHAR)); uMsg.Buffer[uMsg.Length / sizeof(WCHAR)] = 0; // UNICODE_NULL } NtDisplayString(&uMsg); } // Keep this function as short as possible. This gets called a lot in the recursive functions of setupcl. // Do not create any stack based variables here for performance reasons. // __inline void DisplayUI() { NtQuerySystemTime(&CurrentTime); if ( !bDisplayUI ) { if ( (CurrentTime.QuadPart - StartTime.QuadPart) > UITIME ) { static UNICODE_STRING UnicodeString = { 0 }; bDisplayUI = TRUE; LastDotTime.QuadPart = CurrentTime.QuadPart; if ( LoadStringResource(&UnicodeString, IDS_UIMAIN) ) { OutputString(UnicodeString.Buffer); RtlFreeUnicodeString(&UnicodeString); } } } else { // If more than 3 seconds passed since our last output put up a dot. // if ( (CurrentTime.QuadPart - LastDotTime.QuadPart) > UIDOTTIME ) { LastDotTime.QuadPart = CurrentTime.QuadPart; OutputString(TEXT(".")); } } } int __cdecl main( int argc, char** argv, char** envp, ULONG DebugParameter ) /*++ =============================================================================== Routine Description: This routine is the main entry point for the program. We do a bit of error checking, then, if all goes well, we update the registry to enable execution of our second half. =============================================================================== --*/ { BOOLEAN b; int i; NTSTATUS Status; LARGE_INTEGER Time; // // Get Time for seed generation... // NtQuerySystemTime(&Time); #ifdef IA64 // Setup the Seed for generating GUIDs // RandomSeed = (ULONG) Time.LowPart; #endif // Initialize the StartTime // StartTime.QuadPart = Time.QuadPart; LastDotTime.QuadPart = Time.QuadPart; i = 0; // // Enable several privileges that we will need. // // // NTRAID#NTBUG9-545904-2002/02/26-brucegr,jcohen - Do something smarter with regard to error conditions. // Status = RtlAdjustPrivilege(SE_BACKUP_PRIVILEGE,TRUE,FALSE,&b); TEST_STATUS( "SETUPCL: Warning - unable to enable SE_BACKUP_PRIVILEGE privilege!" ); Status = RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE,TRUE,FALSE,&b); TEST_STATUS( "SETUPCL: Warning - unable to enable SE_RESTORE_PRIVILEGE privilege!" ); Status = RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE,TRUE,FALSE,&b); TEST_STATUS( "SETUPCL: Warning - unable to enable SE_SHUTDOWN_PRIVILEGE privilege!" ); Status = RtlAdjustPrivilege(SE_TAKE_OWNERSHIP_PRIVILEGE,TRUE,FALSE,&b); TEST_STATUS( "SETUPCL: Warning - unable to enable SE_TAKE_OWNERSHIP_PRIVILEGE privilege!" ); Status = RtlAdjustPrivilege(SE_SECURITY_PRIVILEGE,TRUE,FALSE,&b); TEST_STATUS( "SETUPCL: Warning - unable to enable SE_SECURITY_PRIVILEGE privilege!" ); Status = RtlAdjustPrivilege(SE_TCB_PRIVILEGE,TRUE,FALSE,&b); TEST_STATUS( "SETUPCL: Warning - unable to enable SE_TCB_PRIVILEGE privilege!" ); #ifdef IA64 // // Reset the Disk GUIDs. // DbgPrint("We are currently running on IA64. Resetting disk GUIDs.\n"); // // ISSUE-2002/02/26-brucegr,jcohen - Error code isn't tested! // ResetDiskGuids(); #endif // // Retrieve old Security ID. // Status = RetrieveOldSid( ); TEST_STATUS_RETURN( "SETUPCL: Retrieval of old SID failed!" ); // // Generate a new Security ID. // // // NTRAID#NTBUG9-545855-2002/02/26-brucegr,jcohen - Use same sid generation algorithm as LsapGenerateRandomDomainSid // in ds\security\base\lsa\server\dspolicy\dbinit.c // Status = GenerateUniqueSid( Time.LowPart ); TEST_STATUS_RETURN( "SETUPCL: Generation of new SID failed!" ); // // Make a copy of the repair hives. // Status = BackupRepairHives(); if( NT_SUCCESS(Status) ) { // // Do the repair hives. // Status = ProcessRepairHives(); TEST_STATUS( "SETUPCL: Failed to update one of the Repair hives." ); } // // Decide if we need to restore the repair hives from our backups. // CleanupRepairHives( Status ); // // Now process the hives, one at a time. // // // NTRAID#NTBUG9-545904-2002/02/26-brucegr,jcohen - Do something smarter with regard to error conditions. // Status = ProcessHives(); // // NTRAID#NTBUG9-545904-2002/02/26-brucegr,jcohen - Do something smarter with regard to error conditions. // Status = FinalHiveCleanup(); // // Now go enumerate all the drives. For each NTFS drive, // we'll whack the ACL to reflect the new SID. // // // NTRAID#NTBUG9-545904-2002/02/26-brucegr,jcohen - Do something smarter with regard to error conditions. // Status = EnumerateDrives(); return Status; } // // Disable the DbgPrint for non-debug builds // #ifndef DBG void DbgPrintSub(char *szBuffer, ...) { return; } #endif