windows-nt/Source/XPSP1/NT/base/cluster/clusapi/registry.c

1575 lines
39 KiB
C
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
registry.c
Abstract:
Provides interface for managing cluster registry
Author:
John Vert (jvert) 19-Jan-1996
Revision History:
--*/
#include "clusapip.h"
//
// Function prototypes for routines local to this module
//
VOID
FreeKey(
IN PCKEY Key
);
HKEY
OpenClusterRelative(
IN HCLUSTER hCluster,
IN LPCWSTR RelativeName,
IN LPCWSTR SpecificName,
IN DWORD samDesired
);
HKEY
WINAPI
GetClusterKey(
IN HCLUSTER hCluster,
IN REGSAM samDesired
)
/*++
Routine Description:
Opens the the root of the cluster registry subtree
for the given cluster.
Arguments:
hCluster - Supplies a handle to the cluster
samDesired - Specifies an access mask that describes the desired
security access for the new key.
Return Value:
A cluster registry key handle to the root of the registry subtree
for the given cluster
If unsuccessful, NULL is returned and GetLastError() provides the
specific error code.
--*/
{
PCLUSTER Cluster = (PCLUSTER)hCluster;
PCKEY Key;
error_status_t Status = ERROR_SUCCESS;
//
// Allocate new CKEY structure and connect to cluster registry.
//
Key = LocalAlloc(LMEM_FIXED, sizeof(CKEY));
if (Key == NULL) {
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return(NULL);
}
Key->Parent = NULL;
Key->RelativeName = NULL;
Key->SamDesired = samDesired;
Key->Cluster = Cluster;
InitializeListHead(&Key->ChildList);
InitializeListHead(&Key->NotifyList);
WRAP_NULL(Key->RemoteKey,
(ApiGetRootKey(Cluster->RpcBinding,
samDesired,
&Status)),
&Status,
Cluster);
if ((Key->RemoteKey == NULL) ||
(Status != ERROR_SUCCESS)) {
LocalFree(Key);
SetLastError(Status);
return(NULL);
}
EnterCriticalSection(&Cluster->Lock);
InsertHeadList(&Cluster->KeyList, &Key->ParentList);
LeaveCriticalSection(&Cluster->Lock);
return((HKEY)Key);
}
HKEY
WINAPI
GetClusterNodeKey(
IN HNODE hNode,
IN REGSAM samDesired
)
/*++
Routine Description:
Opens the the root of the cluster registry subtree
for the given node
Arguments:
hNode - Supplies a handle to the node
samDesired - Specifies an access mask that describes the desired
security access for the new key.
Return Value:
A cluster registry key handle to the root of the registry subtree
for the given node
If unsuccessful, NULL is returned and GetLastError() provides the
specific error code.
--*/
{
PCNODE Node = (PCNODE)hNode;
HCLUSTER Cluster = (HCLUSTER)Node->Cluster;
DWORD Status;
LPWSTR Guid=NULL;
HKEY NodeKey;
WRAP(Status,
(ApiGetNodeId(Node->hNode, &Guid)),
Node->Cluster);
if (Status != ERROR_SUCCESS) {
SetLastError(Status);
return(NULL);
}
NodeKey = OpenClusterRelative(Cluster,
CLUSREG_KEYNAME_NODES,
Guid,
samDesired);
if (NodeKey == NULL) {
Status = GetLastError();
}
MIDL_user_free(Guid);
if (NodeKey == NULL) {
SetLastError(Status);
}
return(NodeKey);
}
HKEY
WINAPI
GetClusterGroupKey(
IN HGROUP hGroup,
IN REGSAM samDesired
)
/*++
Routine Description:
Opens the the root of the cluster registry subtree
for the given group
Arguments:
hResource - Supplies a handle to the group
samDesired - Specifies an access mask that describes the desired
security access for the new key.
Return Value:
A cluster registry key handle to the root of the registry subtree
for the given group
If unsuccessful, NULL is returned and GetLastError() provides the
specific error code.
--*/
{
PCGROUP Group = (PCGROUP)hGroup;
HCLUSTER Cluster = (HCLUSTER)Group->Cluster;
DWORD Status;
LPWSTR Guid=NULL;
HKEY GroupKey;
WRAP(Status,
(ApiGetGroupId(Group->hGroup, &Guid)),
Group->Cluster);
if (Status != ERROR_SUCCESS) {
SetLastError(Status);
return(NULL);
}
GroupKey = OpenClusterRelative(Cluster,
CLUSREG_KEYNAME_GROUPS,
Guid,
samDesired);
if (GroupKey == NULL) {
Status = GetLastError();
}
MIDL_user_free(Guid);
if (GroupKey == NULL) {
SetLastError(Status);
}
return(GroupKey);
}
HKEY
WINAPI
GetClusterResourceKey(
IN HRESOURCE hResource,
IN REGSAM samDesired
)
/*++
Routine Description:
Opens the the root of the cluster registry subtree
for the given resource.
Arguments:
hResource - Supplies a handle to the resource
samDesired - Specifies an access mask that describes the desired
security access for the new key.
Return Value:
A cluster registry key handle to the root of the registry subtree
for the given resource
If unsuccessful, NULL is returned and GetLastError() provides the
specific error code.
--*/
{
PCRESOURCE Resource = (PCRESOURCE)hResource;
HCLUSTER Cluster = (HCLUSTER)Resource->Cluster;
DWORD Status;
LPWSTR Guid=NULL;
HKEY ResKey;
WRAP(Status,
(ApiGetResourceId(Resource->hResource, &Guid)),
Resource->Cluster);
if (Status != ERROR_SUCCESS) {
SetLastError(Status);
return(NULL);
}
ResKey = OpenClusterRelative(Cluster,
CLUSREG_KEYNAME_RESOURCES,
Guid,
samDesired);
if (ResKey == NULL) {
Status = GetLastError();
}
MIDL_user_free(Guid);
if (ResKey == NULL) {
SetLastError(Status);
}
return(ResKey);
}
HKEY
WINAPI
GetClusterResourceTypeKey(
IN HCLUSTER hCluster,
IN LPCWSTR lpszTypeName,
IN REGSAM samDesired
)
/*++
Routine Description:
Opens the the root of the cluster registry subtree
for the given resource type.
Arguments:
hCluster - Supplies the cluster the open is relative to.
lpszTypeName - Supplies the resource type name.
samDesired - Specifies an access mask that describes the desired
security access for the new key.
Return Value:
A cluster registry key handle to the root of the registry subtree
for the given resource type.
If unsuccessful, NULL is returned and GetLastError() provides the
specific error code.
--*/
{
return(OpenClusterRelative(hCluster,
CLUSREG_KEYNAME_RESOURCE_TYPES,
lpszTypeName,
samDesired));
}
HKEY
WINAPI
GetClusterNetworkKey(
IN HNETWORK hNetwork,
IN REGSAM samDesired
)
/*++
Routine Description:
Opens the the root of the cluster registry subtree
for the given network.
Arguments:
hNetwork - Supplies a handle to the network.
samDesired - Specifies an access mask that describes the desired
security access for the new key.
Return Value:
A cluster registry key handle to the root of the registry subtree
for the given network.
If unsuccessful, NULL is returned and GetLastError() provides the
specific error code.
--*/
{
PCNETWORK Network = (PCNETWORK)hNetwork;
HCLUSTER Cluster = (HCLUSTER)Network->Cluster;
DWORD Status;
LPWSTR Guid=NULL;
HKEY NetworkKey;
WRAP(Status,
(ApiGetNetworkId(Network->hNetwork, &Guid)),
Network->Cluster);
if (Status != ERROR_SUCCESS) {
SetLastError(Status);
return(NULL);
}
NetworkKey = OpenClusterRelative(Cluster,
CLUSREG_KEYNAME_NETWORKS,
Guid,
samDesired);
if (NetworkKey == NULL) {
Status = GetLastError();
}
MIDL_user_free(Guid);
if (NetworkKey == NULL) {
SetLastError(Status);
}
return(NetworkKey);
}
HKEY
WINAPI
GetClusterNetInterfaceKey(
IN HNETINTERFACE hNetInterface,
IN REGSAM samDesired
)
/*++
Routine Description:
Opens the the root of the cluster registry subtree
for the given network interface.
Arguments:
hNetInterface - Supplies a handle to the network interface.
samDesired - Specifies an access mask that describes the desired
security access for the new key.
Return Value:
A cluster registry key handle to the root of the registry subtree
for the given network interface.
If unsuccessful, NULL is returned and GetLastError() provides the
specific error code.
--*/
{
PCNETINTERFACE NetInterface = (PCNETINTERFACE)hNetInterface;
HCLUSTER Cluster = (HCLUSTER)NetInterface->Cluster;
DWORD Status;
LPWSTR Guid=NULL;
HKEY NetInterfaceKey;
WRAP(Status,
(ApiGetNetInterfaceId(NetInterface->hNetInterface, &Guid)),
NetInterface->Cluster);
if (Status != ERROR_SUCCESS) {
SetLastError(Status);
return(NULL);
}
NetInterfaceKey = OpenClusterRelative(Cluster,
CLUSREG_KEYNAME_NETINTERFACES,
Guid,
samDesired);
if (NetInterfaceKey == NULL) {
Status = GetLastError();
}
MIDL_user_free(Guid);
if (NetInterfaceKey == NULL) {
SetLastError(Status);
}
return(NetInterfaceKey);
}
HKEY
OpenClusterRelative(
IN HCLUSTER Cluster,
IN LPCWSTR RelativeName,
IN LPCWSTR SpecificName,
IN DWORD samDesired
)
/*++
Routine Description:
Helper routine for the functions that open cluster object keys.
(GetCluster*Key)
Arguments:
Cluster - Supplies the cluster the key should be opened in.
RelativeName - Supplies the first part of the relative name
(i.e. L"Resources")
SpecificName - Supplies the name of the object.
Return Value:
An open registry key if successful
NULL if unsuccessful. LastError will be set to a Win32 error code
--*/
{
LPWSTR Buff;
HKEY ClusterKey;
HKEY Key;
LONG Status;
Buff = LocalAlloc(LMEM_FIXED, (lstrlenW(RelativeName)+lstrlenW(SpecificName)+2)*sizeof(WCHAR));
if ( Buff == NULL ) {
return(NULL);
}
lstrcpyW(Buff, RelativeName);
lstrcatW(Buff, L"\\");
lstrcatW(Buff, SpecificName);
ClusterKey = GetClusterKey(Cluster, KEY_READ);
if (ClusterKey == NULL) {
Status = GetLastError();
LocalFree(Buff);
SetLastError(Status);
return(NULL);
}
Status = ClusterRegOpenKey(ClusterKey,
Buff,
samDesired,
&Key);
LocalFree(Buff);
ClusterRegCloseKey(ClusterKey);
if (Status == ERROR_SUCCESS) {
return(Key);
} else {
SetLastError(Status);
return(NULL);
}
}
LONG
WINAPI
ClusterRegCreateKey(
IN HKEY hKey,
IN LPCWSTR lpSubKey,
IN DWORD dwOptions,
IN REGSAM samDesired,
IN LPSECURITY_ATTRIBUTES lpSecurityAttributes,
OUT PHKEY phkResult,
OUT OPTIONAL LPDWORD lpdwDisposition
)
/*++
Routine Description:
Creates the specified key in the cluster registry. If the
key already exists in the registry, the function opens it.
Arguments:
hKey - Supplies a currently open key.
lpSubKey - Points to a null-terminated string specifying the name
of a subkey that this function opens or creates. The subkey
specified must be a subkey of the key identified by the hKey
parameter. This subkey must not begin with the backslash
character ('\'). This parameter cannot be NULL.
dwOptions - Specifies special options for this key. Valid options are:
REG_OPTION_VOLATILE - This key is volatile; the information is
stored in memory and is not preserved when
the system is restarted.
samDesired - Specifies an access mask that specifies the desired security
access for the new key
lpSecurityAttributes - The lpSecurityDescriptor member of the structure
specifies a security descriptor for the new key. If
lpSecurityAttributes is NULL, the key gets a default security
descriptor. Since cluster registry handles are not inheritable,
the bInheritHandle field of the SECURITY_ATTRIBUTES structure
must be FALSE.
phkResult - Points to a variable that receives the handle of the opened
or created key
lpdwDisposition - Points to a variable that receives one of the following
disposition values:
Value Meaning
REG_CREATED_NEW_KEY The key did not exist and was created.
REG_OPENED_EXISTING_KEY The key existed and was simply opened
without being changed.
Return Value:
If the function succeeds, the return value is ERROR_SUCCESS.
If the function fails, the return value is an error value.
--*/
{
PCKEY Key;
PCKEY ParentKey = (PCKEY)hKey;
PCLUSTER Cluster = ParentKey->Cluster;
PRPC_SECURITY_ATTRIBUTES pRpcSA;
RPC_SECURITY_ATTRIBUTES RpcSA;
error_status_t Status = ERROR_SUCCESS;
DWORD Disposition;
if (lpdwDisposition == NULL) {
lpdwDisposition = &Disposition;
}
//
// Allocate new CKEY structure and create cluster registry key
//
Key = LocalAlloc(LMEM_FIXED, sizeof(CKEY));
if (Key == NULL) {
return(ERROR_NOT_ENOUGH_MEMORY);
}
Key->Parent = ParentKey;
Key->RelativeName = LocalAlloc(LMEM_FIXED, (lstrlenW(lpSubKey)+1)*sizeof(WCHAR));
if (Key->RelativeName == NULL) {
LocalFree(Key);
return(ERROR_NOT_ENOUGH_MEMORY);
}
lstrcpyW(Key->RelativeName, lpSubKey);
Key->SamDesired = samDesired;
Key->Cluster = Cluster;
InitializeListHead(&Key->ChildList);
InitializeListHead(&Key->NotifyList);
if( ARGUMENT_PRESENT( lpSecurityAttributes )) {
DWORD Error;
pRpcSA = &RpcSA;
Error = MapSAToRpcSA( lpSecurityAttributes, pRpcSA );
if( Error != ERROR_SUCCESS ) {
LocalFree(Key->RelativeName);
LocalFree(Key);
return Error;
}
} else {
//
// No PSECURITY_ATTRIBUTES argument, therefore no mapping was done.
//
pRpcSA = NULL;
}
WRAP_NULL(Key->RemoteKey,
(ApiCreateKey(ParentKey->RemoteKey,
lpSubKey,
dwOptions,
samDesired,
pRpcSA,
lpdwDisposition,
&Status)),
&Status,
ParentKey->Cluster);
if ((Key->RemoteKey == NULL) ||
(Status != ERROR_SUCCESS)) {
*phkResult = NULL;
LocalFree(Key->RelativeName);
LocalFree(Key);
return(Status);
}
EnterCriticalSection(&Cluster->Lock);
InsertHeadList(&ParentKey->ChildList, &Key->ParentList);
LeaveCriticalSection(&Cluster->Lock);
*phkResult = (HKEY)Key;
return(ERROR_SUCCESS);
}
LONG
WINAPI
ClusterRegOpenKey(
IN HKEY hKey,
IN LPCWSTR lpSubKey,
IN REGSAM samDesired,
OUT PHKEY phkResult
)
/*++
Routine Description:
Opens the specified key in the cluster registry.
Arguments:
hKey - Supplies a currently open key.
lpSubKey - Points to a null-terminated string specifying the name
of a subkey that this function opens or creates. The subkey
specified must be a subkey of the key identified by the hKey
parameter. This subkey must not begin with the backslash
character ('\'). This parameter cannot be NULL.
samDesired - Specifies an access mask that specifies the desired security
access for the new key
phkResult - Points to a variable that receives the handle of the opened
or created key. Initialized to NULL on failure.
Return Value:
If the function succeeds, the return value is ERROR_SUCCESS.
If the function fails, the return value is an error value.
--*/
{
PCKEY Key;
PCKEY ParentKey = (PCKEY)hKey;
PCLUSTER Cluster = ParentKey->Cluster;
error_status_t Status = ERROR_SUCCESS;
//
// Allocate new CKEY structure and create cluster registry key
//
Key = LocalAlloc(LMEM_FIXED, sizeof(CKEY));
if (Key == NULL) {
return(ERROR_NOT_ENOUGH_MEMORY);
}
*phkResult = NULL;
Key->Parent = ParentKey;
Key->RelativeName = LocalAlloc(LMEM_FIXED, (lstrlenW(lpSubKey)+1)*sizeof(WCHAR));
if (Key->RelativeName == NULL) {
LocalFree(Key);
return(ERROR_NOT_ENOUGH_MEMORY);
}
lstrcpyW(Key->RelativeName, lpSubKey);
Key->SamDesired = samDesired;
Key->Cluster = Cluster;
InitializeListHead(&Key->ChildList);
InitializeListHead(&Key->NotifyList);
WRAP_NULL(Key->RemoteKey,
(ApiOpenKey(ParentKey->RemoteKey,
lpSubKey,
samDesired,
&Status)),
&Status,
ParentKey->Cluster);
if (Status != ERROR_SUCCESS) {
LocalFree(Key->RelativeName);
LocalFree(Key);
return(Status);
}
EnterCriticalSection(&Cluster->Lock);
InsertHeadList(&ParentKey->ChildList, &Key->ParentList);
LeaveCriticalSection(&Cluster->Lock);
*phkResult = (HKEY)Key;
return(ERROR_SUCCESS);
}
LONG
WINAPI
ClusterRegDeleteKey(
IN HKEY hKey,
IN LPCWSTR lpSubKey
)
/*++
Routine Description:
Deletes the specified key. A key that has subkeys cannot
be deleted.
Arguments:
hKey - Supplies a handle to a currently open key.
lpSubKey - Points to a null-terminated string specifying the
name of the key to delete. This parameter cannot be NULL,
and the specified key must not have subkeys.
Return Value:
If the function succeeds, the return value is ERROR_SUCCESS.
If the function fails, the return value is an error value.
--*/
{
PCKEY Key = (PCKEY)hKey;
DWORD Status;
WRAP(Status,
(ApiDeleteKey(Key->RemoteKey, lpSubKey)),
Key->Cluster);
return(Status);
}
LONG
WINAPI
ClusterRegCloseKey(
IN HKEY hKey
)
/*++
Routine Description:
Closes the handle of the specified cluster registry key
Arguments:
hKey - Supplies the open key to close
Return Value:
If the function succeeds, the return value is ERROR_SUCCESS.
If the function fails, the return value is an error value.
--*/
{
PCKEY Key = (PCKEY)hKey;
PCLUSTER Cluster = Key->Cluster;
//
// If any keys have been opened relative to this key, we need to
// keep this CKEY around so that we can reconstruct the key names
// if we need to reopen the handles.
//
// If there are no children of this key, all the storage can be
// freed. Note that freeing this key may also require us to free
// up its parent if the parent has been closed but not freed because
// it has children.
//
EnterCriticalSection(&Cluster->Lock);
if (Cluster->Flags & CLUS_DEAD)
{
if (Key->RemoteKey)
RpcSmDestroyClientContext(&Key->RemoteKey);
}
else
{
ApiCloseKey(&Key->RemoteKey);
}
//
// Remove any notifications posted against this key.
//
RundownNotifyEvents(&Key->NotifyList, L"");
if (IsListEmpty(&Key->ChildList)) {
FreeKey(Key);
}
LeaveCriticalSection(&Cluster->Lock);
//
// If this key was the last thing keeping the cluster structure
// around, we can clean it up now.
//
CleanupCluster(Cluster);
return(ERROR_SUCCESS);
}
VOID
FreeKey(
IN PCKEY Key
)
/*++
Routine Description:
Frees up the storage for a key and removes it from its
parent's ChildList. If this is the last key in its parent's
ChildList, this routine calls itself recursively to free
the parent storage.
Arguments:
Key - Supplies the CKEY to be freed.
Return Value:
None.
--*/
{
RemoveEntryList(&Key->ParentList);
if (Key->Parent != NULL) {
//
// This is not a root key, so see if we need to free the
// parent.
//
if ((Key->Parent->RemoteKey == NULL) &&
(IsListEmpty(&Key->Parent->ChildList))) {
FreeKey(Key->Parent);
}
LocalFree(Key->RelativeName);
}
LocalFree(Key);
}
LONG
WINAPI
ClusterRegEnumKey(
IN HKEY hKey,
IN DWORD dwIndex,
OUT LPWSTR lpszName,
IN OUT LPDWORD lpcchName,
OUT PFILETIME lpftLastWriteTime
)
/*++
Routine Description:
Enumerates subkeys of the specified open cluster registry key.
The function retrieves information about one subkey each time it is called.
Arguments:
hKey - Supplies a currently open key or NULL. If NULL is specified,
the root of the cluster registry is enumerated.
dwIndex - Supplies the index of the subkey to retrieve. This parameter
should be zero for the first call to the RegEnumKeyEx function
and then incremented for subsequent calls. Because subkeys are
not ordered, any new subkey will have an arbitrary index. This
means that the function may return subkeys in any order.
lpszName - Points to a buffer that receives the name of the subkey,
including the terminating null character. The function copies
only the name of the subkey, not the full key hierarchy, to
the buffer.
lpcchName - Points to a variable that specifies the size, in characters,
of the buffer specified by the lpszName parameter. This size should
include the terminating null character. When the function returns,
the variable pointed to by lpcchName contains the number of characters
stored in the buffer. The count returned does not include the
terminating null character.
lpftLastWriteTime - Points to a variable that receives the time the
enumerated subkey was last written to.
Return Value:
If the function succeeds, the return value is ERROR_SUCCESS.
If the function fails, the return value is an error value.
--*/
{
PCKEY Key = (PCKEY)hKey;
LONG Status;
FILETIME LastWriteTime;
LPWSTR KeyName=NULL;
DWORD dwNameLen;
WRAP(Status,
(ApiEnumKey(Key->RemoteKey,
dwIndex,
&KeyName,
&LastWriteTime)),
Key->Cluster);
if (Status != ERROR_SUCCESS) {
return(Status);
}
MylstrcpynW(lpszName, KeyName, *lpcchName);
dwNameLen = lstrlenW(KeyName);
if (*lpcchName < (dwNameLen + 1)) {
if (lpszName != NULL) {
Status = ERROR_MORE_DATA;
}
}
*lpcchName = dwNameLen;
MIDL_user_free(KeyName);
return(Status);
}
DWORD
WINAPI
ClusterRegSetValue(
IN HKEY hKey,
IN LPCWSTR lpszValueName,
IN DWORD dwType,
IN CONST BYTE* lpData,
IN DWORD cbData
)
/*++
Routine Description:
Sets the named value for the given resource.
Arguments:
hKey - Supplies the handle of the cluster registry key.
lpszValueName - Supplies a pointer to a string containing
the name of the value to set. If a value with this
name is not already present in the resource, the function
adds it to the resource.
dwType - Supplies the type of information to be stored as the
value's data. This parameter can be one of the following values:
Value Meaning
REG_BINARY Binary data in any form.
REG_DWORD A 32-bit number.
REG_EXPAND_SZ A null-terminated Unicode string that contains unexpanded
references to environment variables (for example, "%PATH%").
REG_MULTI_SZ An array of null-terminated Unicode strings, terminated
by two null characters.
REG_NONE No defined value type.
REG_SZ A null-terminated Unicode string.
lpData - Supplies a pointer to a buffer containing the data
to be stored with the specified value name.
cbData - Supplies the size, in bytes, of the information
pointed to by the lpData parameter. If the data
is of type REG_SZ, REG_EXPAND_SZ, or REG_MULTI_SZ,
cbData must include the size of the terminating null character.
Return value:
If the function succeeds, the return value is ERROR_SUCCESS.
If the function fails, the return value is an error value.
--*/
{
PCKEY Key = (PCKEY)hKey;
DWORD Status;
WRAP(Status,
(ApiSetValue(Key->RemoteKey,
lpszValueName,
dwType,
lpData,
cbData)),
Key->Cluster);
return(Status);
}
DWORD
WINAPI
ClusterRegDeleteValue(
IN HKEY hKey,
IN LPCWSTR lpszValueName
)
/*++
Routine Description:
Removes the specified value from a given registry subkey
Arguments:
hKey - Supplies the key whose value is to be deleted.
lpszValueName - Supplies the name of the value to be removed.
Return Value:
If the function succeeds, the return value is ERROR_SUCCESS.
If the function fails, the return value is an error value.
--*/
{
PCKEY Key = (PCKEY)hKey;
DWORD Status;
WRAP(Status,
(ApiDeleteValue(Key->RemoteKey, lpszValueName)),
Key->Cluster);
return(Status);
}
LONG
WINAPI
ClusterRegQueryValue(
IN HKEY hKey,
IN LPCWSTR lpszValueName,
OUT LPDWORD lpdwValueType,
OUT LPBYTE lpData,
IN OUT LPDWORD lpcbData
)
/*++
Routine Description:
Retrieves the type and data for a specified value name associated with
an open cluster registry key.
Arguments:
hKey - Supplies the handle of the cluster registry key.
lpszValueName - Supplies a pointer to a string containing the
name of the value to be queried.
lpdwValueType - Points to a variable that receives the key's value
type. The value returned through this parameter will
be one of the following:
Value Meaning
REG_BINARY Binary data in any form.
REG_DWORD A 32-bit number.
REG_EXPAND_SZ A null-terminated Unicode string that contains unexpanded
references to environment variables (for example, "%PATH%").
REG_MULTI_SZ An array of null-terminated Unicode strings, terminated
by two null characters.
REG_NONE No defined value type.
REG_SZ A null-terminated Unicode string.
The lpdwValueType parameter can be NULL if the type is not required
lpData - Points to a buffer that receives the value's data. This parameter
can be NULL if the data is not required.
lpcbData - Points to a variable that specifies the size, in bytes, of the buffer
pointed to by the lpData parameter. When the function returns, this
variable contains the size of the data copied to lpData.
If the buffer specified by lpData parameter is not large enough to hold
the data, the function returns the value ERROR_MORE_DATA, and stores the
required buffer size, in bytes, into the variable pointed to by
lpcbData.
If lpData is NULL, and lpcbData is non-NULL, the function returns
ERROR_SUCCESS, and stores the size of the data, in bytes, in the variable
pointed to by lpcbData. This lets an application determine the best way
to allocate a buffer for the value key's data.
If the data has the REG_SZ, REG_MULTI_SZ or REG_EXPAND_SZ type, then
lpData will also include the size of the terminating null character.
The lpcbData parameter can be NULL only if lpData is NULL.
Return Value:
If the function succeeds, the return value is ERROR_SUCCESS.
If the function fails, the return value is an error value.
--*/
{
DWORD Dummy1;
DWORD Dummy2;
DWORD Required;
PCKEY Key = (PCKEY)hKey;
DWORD Status;
LPBYTE TempData;
DWORD BufferSize;
if (lpdwValueType == NULL) {
lpdwValueType = &Dummy1;
}
if (lpData == NULL) {
TempData = (LPBYTE)&Dummy2;
BufferSize = 0;
} else {
TempData = lpData;
BufferSize = *lpcbData;
}
WRAP(Status,
(ApiQueryValue(Key->RemoteKey,
lpszValueName,
lpdwValueType,
TempData,
BufferSize,
&Required)),
Key->Cluster);
if ((Status == ERROR_SUCCESS) ||
(Status == ERROR_MORE_DATA)) {
if ((Status == ERROR_MORE_DATA) &&
(lpData == NULL)) {
//
// Map this error to success to match the spec.
//
Status = ERROR_SUCCESS;
}
*lpcbData = Required;
}
return(Status);
}
DWORD
WINAPI
ClusterRegEnumValue(
IN HKEY hKey,
IN DWORD dwIndex,
OUT LPWSTR lpszValueName,
IN OUT LPDWORD lpcchValueName,
IN LPDWORD lpdwType,
OUT LPBYTE lpData,
IN OUT LPDWORD lpcbData
)
/*++
Routine Description:
Enumerates the properties of the given resource.
Arguments:
hKey - Supplies the handle of the key
dwIndex - Specifies the index of the value to retrieve. This parameter
should be zero for the first call to the EnumClusterResourceValue
function and then be incremented for subsequent calls. Because
properties are not ordered, any new value will have an arbitrary
index. This means that the function may return properties in any
order.
lpszValueName - Points to a buffer that receives the name of the value,
including the terminating null character.
lpcchValueName - Points to a variable that specifies the size, in characters,
of the buffer pointed to by the lpszValueName parameter. This size
should include the terminating null character. When the function returns,
the variable pointed to by lpcchValueName contains the number of
characters stored in the buffer. The count returned does not include
the terminating null character.
lpdwType - Points to a variable that receives the type code for the value entry.
The type code can be one of the following values:
Value Meaning
REG_BINARY Binary data in any form.
REG_DWORD A 32-bit number.
REG_EXPAND_SZ A null-terminated Unicode string that contains unexpanded
references to environment variables (for example, "%PATH%").
REG_MULTI_SZ An array of null-terminated Unicode strings, terminated
by two null characters.
REG_NONE No defined value type.
REG_SZ A null-terminated Unicode string.
The lpdwType parameter can be NULL if the type code is not required.
lpData - Points to a buffer that receives the data for the value entry.
This parameter can be NULL if the data is not required.
lpcbData - Points to a variable that specifies the size, in bytes, of the
buffer pointed to by the lpData parameter. When the function
returns, the variable pointed to by the lpcbData parameter contains
the number of bytes stored in the buffer. This parameter can be NULL
only if lpData is NULL.
Return Value:
If the function succeeds, the return value is ERROR_SUCCESS.
If the function fails, the return value is an error value.
--*/
{
PCKEY Key = (PCKEY)hKey;
LONG Status;
LPWSTR ValueName=NULL;
DWORD TotalSize;
DWORD DummyType;
BYTE DummyData;
DWORD DummycbData;
DWORD dwNameLen;
if (lpdwType == NULL) {
lpdwType = &DummyType;
}
if (lpcbData == NULL) {
if (lpData != NULL) {
return(ERROR_INVALID_PARAMETER);
}
DummycbData = 0;
lpcbData = &DummycbData;
}
if (lpData == NULL) {
lpData = &DummyData;
}
WRAP(Status,
(ApiEnumValue(Key->RemoteKey,
dwIndex,
&ValueName,
lpdwType,
lpData,
lpcbData,
&TotalSize)),
Key->Cluster);
if ((Status != ERROR_SUCCESS) &&
(Status != ERROR_MORE_DATA)) {
return(Status);
}
if (Status == ERROR_MORE_DATA) {
*lpcbData = TotalSize;
if (lpData == &DummyData) {
Status = ERROR_SUCCESS;
}
}
MylstrcpynW(lpszValueName, ValueName, *lpcchValueName);
dwNameLen = lstrlenW(ValueName);
if (*lpcchValueName < (dwNameLen + 1)) {
if (lpszValueName != NULL) {
Status = ERROR_MORE_DATA;
}
}
*lpcchValueName = dwNameLen;
MIDL_user_free(ValueName);
return(Status);
}
LONG
WINAPI
ClusterRegQueryInfoKey(
HKEY hKey,
LPDWORD lpcSubKeys,
LPDWORD lpcchMaxSubKeyLen,
LPDWORD lpcValues,
LPDWORD lpcchMaxValueNameLen,
LPDWORD lpcbMaxValueLen,
LPDWORD lpcbSecurityDescriptor,
PFILETIME lpftLastWriteTime
)
/*++
Routine Description:
Retrieves information about a specified cluster registry key.
Arguments:
hKey - Supplies the handle of the key.
lpcSubKeys - Points to a variable that receives the number of subkeys
contained by the specified key. This parameter can be NULL.
lpcchMaxSubKeyLen - Points to a variable that receives the length, in
characters, of the key's subkey with the longest name. The count
returned does not include the terminating null character. This parameter can be NULL.
lpcValues - Points to a variable that receives the number of values
associated with the key. This parameter can be NULL.
lpcchMaxValueNameLen - Points to a variable that receives the length,
in characters, of the key's longest value name. The count returned
does not include the terminating null character. This parameter can be NULL.
lpcbMaxValueLen - Points to a variable that receives the length, in
bytes, of the longest data component among the key's values. This parameter can be NULL.
lpcbSecurityDescriptor - Points to a variable that receives the length,
in bytes, of the key's security descriptor. This parameter can be NULL.
lpftLastWriteTime - Pointer to a FILETIME structure. This parameter can be NULL.
Return Value:
ERROR_SUCCESS if successful
Win32 error code otherwise
--*/
{
DWORD SubKeys;
DWORD MaxSubKeyLen;
DWORD Values;
DWORD MaxValueNameLen;
DWORD MaxValueLen;
DWORD SecurityDescriptor;
DWORD Status;
FILETIME LastWriteTime;
PCKEY Key = (PCKEY)hKey;
WRAP(Status,
ApiQueryInfoKey(Key->RemoteKey,
&SubKeys,
&MaxSubKeyLen,
&Values,
&MaxValueNameLen,
&MaxValueLen,
&SecurityDescriptor,
&LastWriteTime),
Key->Cluster);
if (Status == ERROR_SUCCESS) {
if (ARGUMENT_PRESENT(lpcSubKeys)) {
*lpcSubKeys = SubKeys;
}
if (ARGUMENT_PRESENT(lpcchMaxSubKeyLen)) {
*lpcchMaxSubKeyLen = MaxSubKeyLen;
}
if (ARGUMENT_PRESENT(lpcValues)) {
*lpcValues = Values;
}
if (ARGUMENT_PRESENT(lpcchMaxValueNameLen)) {
*lpcchMaxValueNameLen = MaxValueNameLen;
}
if (ARGUMENT_PRESENT(lpcbMaxValueLen)) {
*lpcbMaxValueLen = MaxValueLen;
}
if (ARGUMENT_PRESENT(lpcbSecurityDescriptor)) {
*lpcbSecurityDescriptor = SecurityDescriptor;
}
if (ARGUMENT_PRESENT(lpftLastWriteTime)) {
*lpftLastWriteTime = LastWriteTime;
}
}
return(Status);
}
LONG
WINAPI
ClusterRegGetKeySecurity(
HKEY hKey,
SECURITY_INFORMATION RequestedInformation,
PSECURITY_DESCRIPTOR pSecurityDescriptor,
LPDWORD lpcbSecurityDescriptor
)
/*++
Routine Description:
Retrieves a copy of the security descriptor protecting
the specified cluster registry key.
Arguments:
hKey - Supplies the handle of the key
RequestedInformation - Specifies a SECURITY_INFORMATION structure that
indicates the requested security information.
pSecurityDescriptor - Points to a buffer that receives a copy of the
requested security descriptor.
lpcbSecurityDescriptor - Points to a variable that specifies the size,
in bytes, of the buffer pointed to by the pSecurityDescriptor parameter.
When the function returns, the variable contains the number of bytes
written to the buffer.
Return Value:
ERROR_SUCCESS if successful
Win32 error code otherwise
--*/
{
PCKEY Key = (PCKEY)hKey;
RPC_SECURITY_DESCRIPTOR RpcSD;
DWORD Status;
//
// Convert the supplied SECURITY_DESCRIPTOR to a RPCable version.
//
RpcSD.lpSecurityDescriptor = pSecurityDescriptor;
RpcSD.cbInSecurityDescriptor = *lpcbSecurityDescriptor;
RpcSD.cbOutSecurityDescriptor = 0;
WRAP(Status,
(ApiGetKeySecurity(Key->RemoteKey,
RequestedInformation,
&RpcSD)),
Key->Cluster);
//
// Extract the size of the SECURITY_DESCRIPTOR from the RPCable version.
//
*lpcbSecurityDescriptor = RpcSD.cbOutSecurityDescriptor;
return Status;
}
LONG
WINAPI
ClusterRegSetKeySecurity(
HKEY hKey,
SECURITY_INFORMATION SecurityInformation,
PSECURITY_DESCRIPTOR pSecurityDescriptor
)
/*++
Routine Description:
Sets the security of an open cluster registry key.
Arguments:
hKey - Supplies the cluster registry key
SecurityInformation - Specifies a SECURITY_INFORMATION structure that
indicates the contents of the supplied security descriptor.
pSecurityDescriptor - Points to a SECURITY_DESCRIPTOR structure that
specifies the security attributes to set for the specified key.
Return Value:
ERROR_SUCCESS if successful
Win32 error code otherwise
--*/
{
PCKEY Key = (PCKEY)hKey;
RPC_SECURITY_DESCRIPTOR RpcSD;
DWORD Status;
//
// Convert the supplied SECURITY_DESCRIPTOR to a RPCable version.
//
RpcSD.lpSecurityDescriptor = NULL;
Status = MapSDToRpcSD(pSecurityDescriptor,&RpcSD);
if (Status != ERROR_SUCCESS) {
return(Status);
}
WRAP(Status,
(ApiSetKeySecurity(Key->RemoteKey,
SecurityInformation,
&RpcSD)),
Key->Cluster);
//
// Free the buffer allocated by MapSDToRpcSD.
//
LocalFree(RpcSD.lpSecurityDescriptor);
return(Status);
}