windows-nt/Source/XPSP1/NT/net/dhcp/server/exim/writereg.c
2020-09-26 16:20:57 +08:00

366 lines
7.6 KiB
C

/*++
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 <precomp.h>
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;
}