|
|
/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
dmupdate.c
Abstract:
Contains the global update handlers for the Configuration Database Manager
Author:
John Vert (jvert) 24-Apr-1996
Revision History:
--*/ #include "dmp.h"
#if NO_SHARED_LOCKS
extern CRITICAL_SECTION gLockDmpRoot; #else
extern RTL_RESOURCE gLockDmpRoot; #endif
VOID DmpUpdateSequence( VOID );
DWORD DmpUpdateHandler( IN DWORD Context, IN BOOL SourceNode, IN DWORD BufferLength, IN PVOID Buffer )
/*++
Routine Description:
Update handler for registry updates
Arguments:
Context - Supplies the update context. This is the message type
SourceNode - Supplies whether or not the update originated on this node.
BufferLength - Supplies the length of the update.
Buffer - Supplies a pointer to the buffer.
Return Value:
ERROR_SUCCESS if successful
Win32 error code otherwise
--*/
{ DWORD Status;
if ( gbDmpShutdownUpdates ) return( ERROR_SUCCESS );
switch (Context) {
case DmUpdateDeleteKey: ClRtlLogPrint(LOG_NOISE,"[DM] DmUpdateDeleteKey \n"); Status = DmpUpdateDeleteKey(SourceNode, (PDM_DELETE_KEY_UPDATE)Buffer); break;
case DmUpdateSetValue: ClRtlLogPrint(LOG_NOISE,"[DM] DmUpdateSetValue \n"); Status = DmpUpdateSetValue(SourceNode, (PDM_SET_VALUE_UPDATE)Buffer); break;
case DmUpdateDeleteValue: ClRtlLogPrint(LOG_NOISE,"[DM] DmUpdateDeleteValue\n"); Status = DmpUpdateDeleteValue(SourceNode, (PDM_DELETE_VALUE_UPDATE)Buffer); break;
case DmUpdateJoin: ClRtlLogPrint(LOG_UNUSUAL,"[DM] DmUpdateJoin\n"); Status = ERROR_SUCCESS; // Reset this variable now that another node is beginning a join. If CsDmOrFmHasChanged is TRUE
// when we see the FmUpdateJoin, then we will reject the join.
CsDmOrFmHasChanged = FALSE; break;
default: Status = ERROR_INVALID_DATA; CL_UNEXPECTED_ERROR(ERROR_INVALID_DATA); break; } return(Status); }
DWORD DmpUpdateDeleteKey( IN BOOL SourceNode, IN PDM_DELETE_KEY_UPDATE Update )
/*++
Routine Description:
Deletes the specified registry key on this node.
Arguments:
SourceNode - Supplies whether or not this node is the one that originated the update.
Buffer - Supplies the DM_DELETE_KEY_UPDATE structure with the information necessary to delete the key.
Return Value:
ERROR_SUCCESS if successful.
Win32 error otherwise.
--*/
{ DWORD Disposition; DWORD Status; HKEY Key;
ACQUIRE_EXCLUSIVE_LOCK(gLockDmpRoot);
Status = RegDeleteKeyW(DmpRoot, Update->Name); if (SourceNode) { *Update->lpStatus = Status; } if (Status == ERROR_SUCCESS) { DmpUpdateSequence(); DmpReportNotify(Update->Name, CLUSTER_CHANGE_REGISTRY_NAME); }
RELEASE_LOCK(gLockDmpRoot);
return(Status); }
DWORD DmpUpdateSetValue( IN BOOL SourceNode, IN PDM_SET_VALUE_UPDATE Update )
/*++
Routine Description:
Updates the specified registry value on this node.
Arguments:
SourceNode - Supplies whether or not this node is the one that originated the update.
Buffer - Supplies the DM_SET_VALUE_UPDATE structure with the information necessary to set the value.
Return Value:
ERROR_SUCCESS if successful.
Win32 error otherwise.
--*/
{ DWORD Status; HKEY Key; LPWSTR ValueName; CONST BYTE *lpData;
ValueName = (LPWSTR)((PUCHAR)Update + Update->NameOffset);
switch( Update->Type ) { case REG_DWORD: ClRtlLogPrint(LOG_NOISE, "[DM] Setting value of %1!ws! for key %2!ws! to 0x%3!08lx!\n", ValueName, Update->KeyName, *(PDWORD)((CONST BYTE *)Update + Update->DataOffset)); break;
case REG_SZ: ClRtlLogPrint(LOG_NOISE, "[DM] Setting value of %1!ws! for key %2!ws! to %3!ws!\n", ValueName, Update->KeyName, (CONST BYTE *)Update + Update->DataOffset); break;
default: ClRtlLogPrint(LOG_NOISE, "[DM] Setting value of %1!ws! for key %2!ws!\n", ValueName, Update->KeyName); break; }
ACQUIRE_EXCLUSIVE_LOCK(gLockDmpRoot);
Status = RegOpenKeyExW(DmpRoot, Update->KeyName, 0, KEY_SET_VALUE, &Key);
if (Status != ERROR_SUCCESS) { if (SourceNode) { *Update->lpStatus = Status; } ClRtlLogPrint(LOG_NOISE, "[DM] SetValue failed to open target key %1!ws!\n", Update->KeyName); goto FnExit; }
lpData = (CONST BYTE *)Update + Update->DataOffset;
Status = RegSetValueExW(Key, ValueName, 0, Update->Type, lpData, Update->DataLength); RegCloseKey(Key); if (SourceNode) { *Update->lpStatus = Status; } if (Status == ERROR_SUCCESS) { DmpUpdateSequence(); DmpReportNotify(Update->KeyName, CLUSTER_CHANGE_REGISTRY_VALUE); }
FnExit: RELEASE_LOCK(gLockDmpRoot); return(Status); }
DWORD DmpUpdateDeleteValue( IN BOOL SourceNode, IN PDM_DELETE_VALUE_UPDATE Update )
/*++
Routine Description:
Deletes the specified registry value on this node.
Arguments:
SourceNode - Supplies whether or not this node is the one that originated the update.
Buffer - Supplies the DM_DELETE_VALUE_UPDATE structure with the information necessary to delete the value.
Return Value:
ERROR_SUCCESS if successful.
Win32 error otherwise.
--*/
{ DWORD Status; HKEY Key; LPWSTR ValueName;
ACQUIRE_EXCLUSIVE_LOCK(gLockDmpRoot); Status = RegOpenKeyExW(DmpRoot, Update->KeyName, 0, KEY_SET_VALUE, &Key); if (Status != ERROR_SUCCESS) { if (SourceNode) { *Update->lpStatus = Status; } goto FnExit; }
ValueName = (LPWSTR)((PUCHAR)Update + Update->NameOffset);
Status = RegDeleteValueW(Key, ValueName); RegCloseKey(Key); if (SourceNode) { *Update->lpStatus = Status; } if (Status == ERROR_SUCCESS) { DmpUpdateSequence(); DmpReportNotify(Update->KeyName, CLUSTER_CHANGE_REGISTRY_VALUE); }
FnExit: RELEASE_LOCK(gLockDmpRoot); return(Status); }
VOID DmpUpdateSequence( VOID ) /*++
Routine Description:
Updates the sequence number stored in the registry.
Arguments:
None.
Return Value:
None.
--*/
{ DWORD Sequence; DWORD Status;
Sequence = GumGetCurrentSequence(GumUpdateRegistry);
ACQUIRE_EXCLUSIVE_LOCK(gLockDmpRoot);
Status = RegSetValueExW(DmpRoot, CLUSREG_NAME_CLUS_REG_SEQUENCE, 0, REG_DWORD, (BYTE CONST *)&Sequence, sizeof(Sequence));
RELEASE_LOCK(gLockDmpRoot);
if (Status != ERROR_SUCCESS) { CL_UNEXPECTED_ERROR( Status ); }
}
DWORD DmpUpdateCreateKey( IN BOOL SourceNode, IN PDM_CREATE_KEY_UPDATE CreateUpdate, IN LPCWSTR KeyName, IN OPTIONAL LPVOID lpSecurityDescriptor ) /*++
Routine Description:
GUM dispatch routine for creating a registry key.
Arguments:
SourceNode - Supplies whether or not this node initiated the GUM update. Not used.
CreateUpdate - Supplies key creation options.
KeyName - Supplies the key name
lpSecurityDescriptor - if present, supplies the security descriptor to be applied when the key is created.
Return Value:
ERROR_SUCCESS if successful.
Win32 error code otherwise.
--*/
{ DWORD Disposition; DWORD Status; HKEY Key; SECURITY_ATTRIBUTES SecurityAttributes; LPSECURITY_ATTRIBUTES lpSecurityAttributes;
if (CreateUpdate->SecurityPresent) { SecurityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES); SecurityAttributes.bInheritHandle = FALSE; SecurityAttributes.lpSecurityDescriptor = lpSecurityDescriptor; lpSecurityAttributes = &SecurityAttributes; } else { lpSecurityAttributes = NULL; }
ClRtlLogPrint(LOG_NOISE, "[DM] DmpUpdateCreateKey: Creating key <%1!ws!>...\n", KeyName);
ACQUIRE_EXCLUSIVE_LOCK(gLockDmpRoot);
Status = RegCreateKeyEx(DmpRoot, KeyName, 0, NULL, CreateUpdate->dwOptions, CreateUpdate->samDesired, lpSecurityAttributes, &Key, &Disposition); if (SourceNode) { *CreateUpdate->lpDisposition = Disposition; *CreateUpdate->phKey = Key; } else { RegCloseKey(Key); } if ((Status == ERROR_SUCCESS) && (Disposition == REG_CREATED_NEW_KEY)) { DmpUpdateSequence(); DmpReportNotify(KeyName, CLUSTER_CHANGE_REGISTRY_NAME); }
RELEASE_LOCK(gLockDmpRoot);
return(Status); }
DWORD DmpUpdateSetSecurity( IN BOOL SourceNode, IN PSECURITY_INFORMATION pSecurityInformation, IN LPCWSTR KeyName, IN PSECURITY_DESCRIPTOR lpSecurityDescriptor, IN LPDWORD pGrantedAccess ) /*++
Routine Description:
GUM dispatch routine for creating a registry key.
Arguments:
SourceNode - Supplies whether or not this node initiated the GUM update. Not used.
pSecurityInformation - Supplies a pointer to the security information
KeyName - Supplies the key name
lpSecurityDescriptor - Supplies the security descriptor to be applied.
pGrantedAccess - Supplies the access that the key was opened with.
Return Value:
ERROR_SUCCESS if successful.
Win32 error code otherwise.
--*/
{ DWORD Status; HKEY Key;
ACQUIRE_EXCLUSIVE_LOCK(gLockDmpRoot);
Status = RegOpenKeyExW(DmpRoot, KeyName, 0, *pGrantedAccess, &Key); if (Status != ERROR_SUCCESS) { if ((Status == ERROR_ACCESS_DENIED) || (Status == ERROR_PRIVILEGE_NOT_HELD)) { BOOLEAN Enabled;
Status = ClRtlEnableThreadPrivilege(SE_SECURITY_PRIVILEGE, &Enabled); if (Status == ERROR_SUCCESS) { Status = RegOpenKeyExW(DmpRoot, KeyName, 0, *pGrantedAccess, &Key); ClRtlRestoreThreadPrivilege(SE_SECURITY_PRIVILEGE, Enabled); }
} if (Status != ERROR_SUCCESS) { goto FnExit; } }
Status = RegSetKeySecurity(Key, *pSecurityInformation, lpSecurityDescriptor); RegCloseKey(Key); if (Status == ERROR_SUCCESS) { DmpUpdateSequence(); DmpReportNotify(KeyName, CLUSTER_CHANGE_REGISTRY_ATTRIBUTES); }
FnExit: RELEASE_LOCK(gLockDmpRoot); return(Status);
}
|