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