/*++ Copyright (C) 1999 Microsoft Coporation Module Name: writereg.c Abstract: This module write the configuration to the registry from the MM data structures for NT4 and W2K. --*/ #include DWORD SaveOrRestoreConfigToFile( IN HKEY hKey, IN LPWSTR ConfigFileName, IN BOOL fRestore ) /*++ Routine Description: This routine backs up or restores the dhcp configuration between the registry and the file. Arguments: hKey -- key to backup or restore onto ConfigFileName -- file name to use to backup onto or restore from. This must be full path name. fRestore -- TRUE ==> do a restore from file; FALSE => do backup to file. Return Values: Win32 errors... --*/ { DWORD Error; BOOL fError; BOOLEAN WasEnable; NTSTATUS NtStatus; HANDLE ImpersonationToken; if( FALSE == fRestore ) { // // If backing up, delete the old file. // fError = DeleteFile( ConfigFileName ); if(FALSE == fError ) { Error = GetLastError(); if( ERROR_FILE_NOT_FOUND != Error && ERROR_PATH_NOT_FOUND != Error ) { ASSERT(FALSE); return Error; } } } // // Impersonate to self. // NtStatus = RtlImpersonateSelf( SecurityImpersonation ); if( !NT_SUCCESS(NtStatus) ) { DbgPrint("Impersonation failed: 0x%lx\n", NtStatus); Error = RtlNtStatusToDosError( NtStatus ); return Error; } NtStatus = RtlAdjustPrivilege( SE_BACKUP_PRIVILEGE, TRUE, // enable privilege TRUE, // adjust client token &WasEnable ); if( !NT_SUCCESS (NtStatus ) ) { DbgPrint("RtlAdjustPrivilege: 0x%lx\n", NtStatus ); Error = RtlNtStatusToDosError( NtStatus ); goto Cleanup; } NtStatus = RtlAdjustPrivilege( SE_RESTORE_PRIVILEGE, TRUE, // enable privilege TRUE, // adjust client token &WasEnable ); if( !NT_SUCCESS (NtStatus ) ) { DbgPrint( "RtlAdjustPrivilege: 0x%lx\n", NtStatus ); Error = RtlNtStatusToDosError( NtStatus ); goto Cleanup; } // // Backup or restore appropriately. // if( FALSE == fRestore ) { Error = RegSaveKey( hKey, ConfigFileName, NULL ); } else { Error = RegRestoreKey( hKey, ConfigFileName, 0 ); } if( ERROR_SUCCESS != Error ) { DbgPrint("Backup/Restore: 0x%lx\n", Error); } // // revert impersonation. // Cleanup: ImpersonationToken = NULL; NtStatus = NtSetInformationThread( NtCurrentThread(), ThreadImpersonationToken, (PVOID)&ImpersonationToken, sizeof(ImpersonationToken) ); if( !NT_SUCCESS(NtStatus ) ) { DbgPrint("NtSetInfo: 0x%lx\n", NtStatus); if( ERROR_SUCCESS == Error ) { Error = RtlNtStatusToDosError(NtStatus); } } return Error; } DWORD DhcpRegDeleteKey( HKEY ParentKeyHandle, LPWSTR KeyName ) /*++ Routine Description: This function deletes the specified key and all its subkeys. Arguments: ParentKeyHandle : handle of the parent key. KeyName : name of the key to be deleted. Return Value: Registry Errors. --*/ { DWORD Error, NumSubKeys; HKEY KeyHandle = NULL; // // open key. // Error = RegOpenKeyEx( ParentKeyHandle, KeyName, 0, KEY_ALL_ACCESS, &KeyHandle ); if ( Error != ERROR_SUCCESS ) { goto Cleanup; } // // query key info. // Error = RegQueryInfoKey( KeyHandle, NULL, NULL, NULL, &NumSubKeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL ); if( Error != ERROR_SUCCESS ) { goto Cleanup; } // // delete all its subkeys if they exist. // if( NumSubKeys != 0 ) { DWORD Index; DWORD KeyLength; WCHAR KeyBuffer[100]; FILETIME KeyLastWrite; for(Index = 0; Index < NumSubKeys ; Index++ ) { // // read next subkey name. // // Note : specify '0' as index each time, since deleting // first element causes the next element as first // element after delete. // KeyLength = sizeof(KeyBuffer)/sizeof(WCHAR); Error = RegEnumKeyEx( KeyHandle, 0, // index. KeyBuffer, &KeyLength, 0, // reserved. NULL, // class string not required. 0, // class string buffer size. &KeyLastWrite ); if( Error != ERROR_SUCCESS ) { goto Cleanup; } // // delete this key recursively. // Error = DhcpRegDeleteKey( KeyHandle, KeyBuffer ); if( Error != ERROR_SUCCESS ) { goto Cleanup; } } } // // close the key before delete. // RegCloseKey( KeyHandle ); KeyHandle = NULL; // // at last delete this key. // Error = RegDeleteKey( ParentKeyHandle, KeyName ); Cleanup: if( KeyHandle == NULL ) { RegCloseKey( KeyHandle ); } return( Error ); } DWORD DhcpRegDeleteKeyByName( IN LPWSTR Parent, IN LPWSTR SubKey ) { HKEY hKey; ULONG Error; Error = RegOpenKeyEx( HKEY_LOCAL_MACHINE, Parent, 0, KEY_ALL_ACCESS, &hKey ); if( ERROR_SUCCESS != Error ) return Error; Error = DhcpRegDeleteKey(hKey, SubKey); RegCloseKey(hKey); return Error; } DWORD DhcpeximWriteRegistryConfiguration( IN PM_SERVER Server ) { REG_HANDLE Hdl; DWORD Error, Disp; LPTSTR Loc, TempLoc; HKEY hKey; // // The location in the registry where things are read from is // different between whether it is NT4 or W2K. // if( IsNT4() ) Loc = DHCPEXIM_REG_CFG_LOC4; else Loc = DHCPEXIM_REG_CFG_LOC5; TempLoc = TEXT("Software\\Microsoft\\DhcpExim"); // // Now open the regkey // Error = RegCreateKeyEx( HKEY_LOCAL_MACHINE, TempLoc, 0, TEXT("DHCPCLASS"), REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &Hdl.Key, &Disp ); if( NO_ERROR != Error ) return Error; Error = RegOpenKeyEx( HKEY_LOCAL_MACHINE, Loc, 0, KEY_ALL_ACCESS, &hKey ); if( NO_ERROR != Error ) { RegCloseKey( Hdl.Key ); return Error; } // // Set this as the current server // DhcpRegSetCurrentServer(&Hdl); // // Save the configuration temporarily // Error = DhcpRegServerSave(Server); // // Now attempt to save the temporary key to disk and restore // it back where it should really be and delete temp key // if( NO_ERROR == Error ) { Error = SaveOrRestoreConfigToFile( Hdl.Key, L"Dhcpexim.reg", FALSE ); if( NO_ERROR == Error ) { Error = SaveOrRestoreConfigToFile( hKey, L"Dhcpexim.reg", TRUE ); if( NO_ERROR == Error ) { RegCloseKey(Hdl.Key); Hdl.Key = NULL; DhcpRegDeleteKeyByName( L"Software\\Microsoft", L"DhcpExim" ); } } } if( NULL != Hdl.Key ) RegCloseKey(Hdl.Key); RegCloseKey(hKey); DhcpRegSetCurrentServer(NULL); return Error; }