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.
538 lines
12 KiB
538 lines
12 KiB
/*++
|
|
|
|
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);
|
|
|
|
}
|