WindowsXP-SP1/base/fs/dfs/dfsm/server/cregstor.cxx
2020-09-30 16:53:49 +02:00

1317 lines
36 KiB
C++
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//+----------------------------------------------------------------------------
//
// Copyright (C) 1992, Microsoft Corporation
//
// File: CRegStor.cxx
//
// Contents: Implementation of classes derived from CStorage and
// CEnumStorage that use the NT Registry for persistent storage.
//
// In addition to providing this, this class
// maintains a global mapping from the Prefix property to
// "object name" in an object directory. Thus, given an
// Prefix, one can find the object path.
//
// Note that this map from Prefix to object path has the
// following restrictions:
//
// o At process start time, all objects are "read in" and their
// ReadIdProps() method called. This is needed to populate the
// map.
//
// o When a new object is created, its SetIdProps() method must
// be called before it can be located via the map.
//
// o Maps are many to 1 - many EntryPaths may map to the same
// object. At no point in time can one try to map the same
// EntryPath to many objects.
//
// Classes: CRegStorage
//
// Functions:
//
// History: 12-19-95 Milans created
//
//-----------------------------------------------------------------------------
#include "headers.hxx"
#pragma hdrstop
#include "cregstor.hxx"
#include "recon.hxx" // For DFS_ID_PROPS
#include "marshal.hxx" // For MiDfsIdProps
INIT_FILE_TIME_INFO() // Initialize some needed
INIT_DFS_ID_PROPS_INFO() // marshalling infos
#define VERSION_PROPS L"Version"
#define ID_PROPS L"ID"
#define SVC_PROPS L"Svc"
#define RECOVERY_PROPS L"Recovery"
DWORD
DfsmQueryValue(
HKEY hkey,
LPWSTR wszValueName,
DWORD dwExpectedType,
DWORD dwExpectedSize,
PBYTE pBuffer,
LPDWORD cbBuffer);
//+----------------------------------------------------------------------------
//
// Function: CRegStorage::CRegStorage
//
// Synopsis: Constructor for CRegStorage object. Opens the key given by
// the name and makes a copy of the name.
//
// Arguments: [pwszFileName] -- Name of subkey to open.
// [pdwErr] -- If the constructor fails, this value is set to an
// appropriate error code.
//
// Returns: Nothing. However, if an error occurs, the error code is
// returned via the pdwErr argument
//
//-----------------------------------------------------------------------------
CRegStorage::CRegStorage(
LPCWSTR lpwszFileName,
DWORD *pdwErr) :
CStorage(lpwszFileName),
_pwszPrefix(NULL),
_wszFileName(NULL),
_hKey(NULL)
{
IDfsVolInlineDebOut((
DEB_TRACE, "CRegStorage::+CRegStorage(0x%x)\n",
this));
*pdwErr = RegOpenKey( HKEY_LOCAL_MACHINE, lpwszFileName, &_hKey );
if (*pdwErr == ERROR_SUCCESS) {
_wszFileName = new WCHAR[ wcslen(lpwszFileName) + 1];
if (_wszFileName != NULL) {
wcscpy( _wszFileName, lpwszFileName );
} else {
*pdwErr = ERROR_OUTOFMEMORY;
RegCloseKey( _hKey );
_hKey = NULL;
}
}
}
//+----------------------------------------------------------------------------
//
// Function: CRegStorage::~CRegStorage
//
// Synopsis: Destructor for CRegStorage object.
//
// Arguments: None
//
// Returns: Nothing
//
//-----------------------------------------------------------------------------
CRegStorage::~CRegStorage()
{
IDfsVolInlineDebOut((
DEB_TRACE, "CRegStorage::~CRegStorage(0x%x)\n",
this));
if (_hKey != NULL)
RegCloseKey( _hKey );
if (_wszFileName != NULL)
delete [] _wszFileName;
if (_pwszPrefix != NULL)
delete [] _pwszPrefix;
}
//+----------------------------------------------------------------------------
//
// Function: CRegStorage::DestroyElement
//
// Synopsis: Deletes a child key
//
// Arguments: [lpwszChildName] -- Name of child key to delete
//
// Returns: Result of trying to delete the child key
//
//-----------------------------------------------------------------------------
DWORD CRegStorage::DestroyElement(
IN LPCWSTR lpwszChildName)
{
DWORD dwErr;
dwErr = RegDeleteKey( _hKey, lpwszChildName );
return( dwErr );
}
//+----------------------------------------------------------------------------
//
// Function: CRegStorage::GetEnumDirectory
//
// Synopsis: Returns an enumerator for the child keys of this CRegStorage
// object.
//
// Arguments: [ppRegDir] -- If successful, ppRegDir is set to point to an
// object of class CRegEnumDirectory.
//
// Returns: S_OK if successful.
//
// ERROR_OUTOFMEMORY if unable to allocate memory for new object.
//
// DWORD_FROM_WIN32 of error set by DuplicateHandle
//
//-----------------------------------------------------------------------------
DWORD
CRegStorage::GetEnumDirectory(
CEnumDirectory **ppRegDir)
{
DWORD dwErr;
CRegEnumDirectory *pRegDir;
pRegDir = new CRegEnumDirectory( _hKey, &dwErr );
if (pRegDir == NULL) {
dwErr = ERROR_OUTOFMEMORY;
} else if (dwErr) {
pRegDir->Release();
pRegDir = NULL;
}
*ppRegDir = (CEnumDirectory *) pRegDir;
return( dwErr );
}
//+----------------------------------------------------------------------------
//
// Function: CRegStorage::SetVersionProps
//
// Synopsis: Sets the version property set of a Dfs Manager volume object.
//
// Arguments: [ulVersion] -- The version number to set.
//
// Returns: [S_OK] -- If property set.
//
// DWORD_FROM_WIN32 of RegSetValue.
//
//-----------------------------------------------------------------------------
DWORD
CRegStorage::SetVersionProps(
IN ULONG ulVersion)
{
DWORD dwErr;
dwErr = RegSetValueEx(
_hKey,
VERSION_PROPS,
NULL,
REG_DWORD,
(LPBYTE) &ulVersion,
sizeof(ulVersion));
return( dwErr );
}
//+----------------------------------------------------------------------------
//
// Function: CRegStorage::GetVersionProps
//
// Synopsis: Retrieves the version property set of a Dfs Manager volume
// object.
//
// Arguments: [pulVersion] -- On successful return, contains the value
// of the Version property.
//
// Returns: [S_OK] -- If successful.
//
// DWORD from DfsmQueryValue
//
//-----------------------------------------------------------------------------
DWORD
CRegStorage::GetVersionProps(
PULONG pulVersion)
{
DWORD dwErr;
DWORD dwType;
DWORD cbSize;
cbSize = sizeof(*pulVersion);
dwErr = DfsmQueryValue(
_hKey,
VERSION_PROPS,
REG_DWORD,
sizeof(DWORD),
(LPBYTE) pulVersion,
&cbSize);
return( dwErr );
}
//+----------------------------------------------------------------------------
//
// Function: CRegStorage::SetIdProps
//
// Synopsis: Sets the ID properties of a Dfs Manager volume object. Also
// updates the CRegStorageDirectory to add a mapping from
// the prefix to this object name, if necessary.
//
// The pseudo algorithm is:
//
// Phase 1
// Add mapping of prefix to DfsmStorageDirectory if needed.
// Phase 2
// Update the ID props in the registry.
// Phase 3
// if (success)
// delete mapping of old prefix, if any, from Directory
// else
// delete mapping of new prefix from directory
//
// This algorithm assumes that deleting a prefix mapping from
// the directory is guaranteed to succeed. Based on this
// assumption, we can maintain a guaranteed consistency between
// DfsmStorageDirectory and the ID property stored in the
// registry.
//
// Arguments:
//
// Returns: [S_OK] -- If successful.
//
// [ERROR_OUTOFMEMORY] -- If unable to allocate memory for
// internal use.
//
// [ERROR_INVALID_PARAMETER] -- If unable to parse the passed in
// parameters.
//
// DWORD_FROM_WIN32 of RegSetValueEx return code.
//
//-----------------------------------------------------------------------------
DWORD
CRegStorage::SetIdProps(
ULONG dwType,
ULONG dwState,
LPWSTR pwszPrefix,
LPWSTR pwszShortPath,
GUID idVolume,
LPWSTR pwszComment,
ULONG dwTimeout,
FILETIME ftPrefix,
FILETIME ftState,
FILETIME ftComment)
{
DWORD dwErr;
NTSTATUS status;
DFS_ID_PROPS idProps;
MARSHAL_BUFFER marshalBuffer;
PBYTE pBuffer;
ULONG cbBuffer;
LPWSTR pwszOldPrefix = NULL;
BOOLEAN fRegisteredNewPrefix = FALSE;
//
// Phase 1.
// First, update the CRegStorageDirectory if needed.
//
if ((_pwszPrefix) != NULL && (_wcsicmp(_pwszPrefix, pwszPrefix) != 0)) {
//
// Our prefix changed. At this point, we'll only register the
// new prefix, leaving the old prefix in place. This will aid
// rollback if necessary.
//
pwszOldPrefix = _pwszPrefix;
_pwszPrefix = NULL;
}
if (_pwszPrefix == NULL) {
ASSERT(pwszPrefix != NULL);
_pwszPrefix = new WCHAR [ wcslen(pwszPrefix) + 1 ];
if (_pwszPrefix != NULL) {
wcscpy( _pwszPrefix, pwszPrefix );
dwErr = pDfsmStorageDirectory->_InsertIfNeeded(
_pwszPrefix,
_wszFileName);
ASSERT( dwErr != NERR_DfsInconsistent );
if (dwErr == ERROR_SUCCESS)
fRegisteredNewPrefix = TRUE;
} else {
dwErr = ERROR_OUTOFMEMORY;
}
if (dwErr != ERROR_SUCCESS)
goto Cleanup;
}
//
// Phase 2.
// Next, try to update the registry with the new ID props. Note that
// we do not persist the first component (machine name) of the prefix
//
idProps.wszPrefix = wcschr( &pwszPrefix[1], UNICODE_PATH_SEP );
idProps.wszShortPath = wcschr( &pwszShortPath[1], UNICODE_PATH_SEP );
idProps.idVolume = idVolume;
idProps.dwState = dwState;
idProps.dwType = dwType;
idProps.wszComment = pwszComment;
idProps.dwTimeout = dwTimeout;
idProps.ftEntryPath = ftPrefix;
idProps.ftState = ftState;
idProps.ftComment = ftComment;
cbBuffer = 0;
status = DfsRtlSize( &MiDfsIdProps, &idProps, &cbBuffer );
if (NT_SUCCESS(status)) {
//
// Add extra bytes for the timeout, which will go at the end
//
cbBuffer += sizeof(ULONG);
pBuffer = new BYTE [cbBuffer];
if (pBuffer != NULL) {
MarshalBufferInitialize( &marshalBuffer, cbBuffer, pBuffer);
status = DfsRtlPut( &marshalBuffer, &MiDfsIdProps, &idProps );
if (NT_SUCCESS(status)) {
DfsRtlPutUlong(&marshalBuffer, &dwTimeout);
dwErr = RegSetValueEx(
_hKey,
ID_PROPS,
NULL,
REG_BINARY,
pBuffer,
cbBuffer);
} else {
dwErr = ERROR_INVALID_PARAMETER;
}
delete [] pBuffer;
} else {
dwErr = ERROR_OUTOFMEMORY;
}
} else {
dwErr = ERROR_INVALID_PARAMETER;
}
Cleanup:
//
// Phase 3.
// Lastly, either delete any old prefix from DfsmStorageRegistry, or
// rollback any changes made to DfsmStorageRegistry if needed.
//
if (dwErr == ERROR_SUCCESS) {
//
// The entire operation was successful. See if we need to delete any
// old prefix mapping in DfsmStorageDirectory
//
if (pwszOldPrefix != NULL) {
DWORD dwErrDelete;
dwErrDelete = pDfsmStorageDirectory->_Delete( pwszOldPrefix );
ASSERT( dwErrDelete == ERROR_SUCCESS );
delete [] pwszOldPrefix;
}
} else {
//
// An error occured somewhere along the line. Delete any new prefix
// mapping that may have been made, and restore the original
// _pwszPrefix if necessary.
//
if (fRegisteredNewPrefix) {
DWORD dwErrDelete;
dwErrDelete = pDfsmStorageDirectory->_Delete( _pwszPrefix );
ASSERT( dwErrDelete == ERROR_SUCCESS );
}
if (pwszOldPrefix != NULL) {
if (_pwszPrefix != NULL) {
delete [] _pwszPrefix;
}
_pwszPrefix = pwszOldPrefix;
}
}
return( dwErr );
}
//+----------------------------------------------------------------------------
//
// Function: CRegStorage::GetIdProps
//
// Synopsis: Retrieves the Id Properties of a Dfs Manager volume object.
// Also, if this is the first time that the ID Props are being
// read, a mapping from the retrieved prefix to the object name
// is registered in DfsmStorageDirectory.
//
// Arguments:
//
// Returns: [S_OK] -- Successfully retrieved the properties.
//
// [DFS_E_VOLUME_OBJECT_CORRUPT] -- The stored properties could
// not be parsed properly.
//
// [DFS_E_INCONSISTENT] -- Another volume object seems to have
// the same prefix!
//
// [ERROR_OUTOFMEMORY] -- Unable to allocate memory for properties
// or other uses.
//
// DWORD from DfsmQueryValue
//
//-----------------------------------------------------------------------------
DWORD
CRegStorage::GetIdProps(
PULONG pdwType,
PULONG pdwState,
LPWSTR *ppwszPrefix,
LPWSTR *ppwszShortPath,
GUID *pidVolume,
LPWSTR *ppwszComment,
PULONG pdwTimeout,
FILETIME *pftPrefix,
FILETIME *pftState,
FILETIME *pftComment)
{
DWORD dwErr;
NTSTATUS status;
DWORD dwUnused, dwType, cbBuffer;
ULONG dwTimeout;
PBYTE pBuffer;
MARSHAL_BUFFER marshalBuffer;
DFS_ID_PROPS idProps;
*ppwszPrefix = NULL;
*ppwszComment = NULL;
dwErr = RegQueryInfoKey(
_hKey, // Key
NULL, // Class string
NULL, // Size of class string
NULL, // Reserved
&dwUnused, // # of subkeys
&dwUnused, // max size of subkey name
&dwUnused, // max size of class name
&dwUnused, // # of values
&dwUnused, // max size of value name
&cbBuffer, // max size of value data,
NULL, // security descriptor
NULL); // Last write time
if (dwErr == ERROR_SUCCESS) {
pBuffer = new BYTE [cbBuffer];
if (pBuffer != NULL) {
dwErr = DfsmQueryValue(
_hKey,
ID_PROPS,
REG_BINARY,
0,
pBuffer,
&cbBuffer);
} else {
dwErr = ERROR_OUTOFMEMORY;
}
if (dwErr == ERROR_SUCCESS) {
MarshalBufferInitialize(&marshalBuffer, cbBuffer, pBuffer);
status = DfsRtlGet(&marshalBuffer, &MiDfsIdProps, &idProps);
if (NT_SUCCESS(status)) {
#define GIP_DUPLICATE_STRING(dwErr, src, dest) \
if ((src) != NULL) \
(*(dest)) = new WCHAR [ wcslen(src) + 1 ]; \
else \
(*(dest)) = new WCHAR [1]; \
\
if (*(dest) != NULL) \
if ((src) != NULL) \
wcscpy( *(dest), (src) ); \
else \
(*(dest))[0] = UNICODE_NULL; \
else \
dwErr = ERROR_OUTOFMEMORY;
#define GIP_DUPLICATE_PREFIX(dwErr, src, dest) \
(*(dest)) = new WCHAR [ 1 + \
wcslen(pwszDfsRootName) + \
((src) ? wcslen(src) : 0) + \
1]; \
if ((*(dest)) != NULL) { \
wcscpy( *(dest), UNICODE_PATH_SEP_STR ); \
wcscat( *(dest), pwszDfsRootName ); \
if (src) \
wcscat( *(dest), (src) ); \
} else { \
dwErr = ERROR_OUTOFMEMORY; \
}
if (pwszDfsRootName != NULL) {
GIP_DUPLICATE_PREFIX( dwErr, idProps.wszPrefix, ppwszPrefix );
if (dwErr == ERROR_SUCCESS) {
GIP_DUPLICATE_PREFIX(
dwErr,
idProps.wszShortPath,
ppwszShortPath );
}
} else {
dwErr = ERROR_INVALID_NAME;
}
if (dwErr == ERROR_SUCCESS) {
GIP_DUPLICATE_STRING(
dwErr,
idProps.wszComment,
ppwszComment);
}
//
// There are two possible versions of the blob. One has the timeout
// after all the other stuff, the other doesn't.
// So, if there are sizeof(ULONG) bytes left in the blob,
// assume it is the timeout. Otherwise this is an old
// version of the blob, and the timeout isn't here, so we set it to
// the global value.
idProps.dwTimeout = GTimeout;
if (
(marshalBuffer.Current < marshalBuffer.Last)
&&
(marshalBuffer.Last - marshalBuffer.Current) == sizeof(ULONG)
) {
DfsRtlGetUlong(&marshalBuffer, &idProps.dwTimeout);
}
if (dwErr == ERROR_SUCCESS) {
*pdwType = idProps.dwType;
*pdwState = idProps.dwState;
*pidVolume = idProps.idVolume;
*pdwTimeout = idProps.dwTimeout;
*pftPrefix = idProps.ftEntryPath;
*pftState = idProps.ftState;
*pftComment = idProps.ftComment;
}
if (dwErr == ERROR_SUCCESS) {
if (_pwszPrefix != NULL) {
delete [] _pwszPrefix;
}
_pwszPrefix = new WCHAR[ wcslen(*ppwszPrefix) + 1];
if (_pwszPrefix != NULL) {
wcscpy( _pwszPrefix, *ppwszPrefix );
dwErr = pDfsmStorageDirectory->_InsertIfNeeded(
_pwszPrefix,
_wszFileName);
} else {
dwErr = ERROR_OUTOFMEMORY;
}
}
if (dwErr != ERROR_SUCCESS) {
if (*ppwszPrefix != NULL) {
delete [] *ppwszPrefix;
*ppwszPrefix = NULL;
}
if (*ppwszShortPath != NULL) {
delete [] *ppwszShortPath;
*ppwszShortPath = NULL;
}
if (*ppwszComment != NULL) {
delete [] *ppwszComment;
*ppwszComment = NULL;
}
}
if (idProps.wszPrefix != NULL)
MarshalBufferFree(idProps.wszPrefix);
if (idProps.wszShortPath != NULL)
MarshalBufferFree(idProps.wszShortPath);
if (idProps.wszComment != NULL)
MarshalBufferFree(idProps.wszComment);
} else {
if (status == STATUS_INSUFFICIENT_RESOURCES) {
dwErr = ERROR_OUTOFMEMORY;
} else {
dwErr = NERR_DfsInternalCorruption;
}
}
}
if (pBuffer != NULL) {
delete [] pBuffer;
}
}
return( dwErr );
}
//+----------------------------------------------------------------------------
//
// Function: CRegStorage::SetSvcProps
//
// Synopsis: Sets the Svc properties of a Dfs Manager volume object
//
// Arguments: [pBuffer] -- Svc argument buffer
// [cbBuffer] -- Size of Svc argument buffer
//
// Returns:
//
//-----------------------------------------------------------------------------
DWORD
CRegStorage::SetSvcProps(
PBYTE pSvc,
ULONG cbSvc)
{
return( SetBlobProp( SVC_PROPS, pSvc, cbSvc ) );
}
//+----------------------------------------------------------------------------
//
// Function: CRegStorage::GetSvcProps
//
// Synopsis: Retrieves the Svc properties of a Dfs Manager volume
// object.
//
// Arguments: [ppSvc] -- On successful return, points to a buffer
// allocated to hold the Svc property.
// [pcbSvc] -- On successful return, size in bytes of
// Svc buffer.
//
// Returns:
//
//-----------------------------------------------------------------------------
DWORD
CRegStorage::GetSvcProps(
PBYTE *ppSvc,
PULONG pcbSvc)
{
return( GetBlobProp( SVC_PROPS, ppSvc, pcbSvc ) );
}
//+----------------------------------------------------------------------------
//
// Function: CRegStorage::SetRecoveryProps
//
// Synopsis: Sets the recovery properties of a Dfs Manager volume object
//
// Arguments: [pBuffer] -- Recovery argument buffer
// [cbBuffer] -- Size of recovery argument buffer
//
// Returns:
//
//-----------------------------------------------------------------------------
DWORD
CRegStorage::SetRecoveryProps(
PBYTE pRecovery,
ULONG cbRecovery)
{
return( SetBlobProp( RECOVERY_PROPS, pRecovery, cbRecovery ) );
}
//+----------------------------------------------------------------------------
//
// Function: CRegStorage::GetRecoveryProps
//
// Synopsis: Retrieves the recovery properties of a Dfs Manager volume
// object.
//
// Arguments: [ppRecovery] -- On successful return, points to a buffer
// allocated to hold the recovery property.
// [pcbRecovery] -- On successful return, size in bytes of
// recovery buffer.
//
// Returns:
//
//-----------------------------------------------------------------------------
DWORD
CRegStorage::GetRecoveryProps(
PBYTE *ppRecovery,
PULONG pcbRecovery)
{
return( GetBlobProp( RECOVERY_PROPS, ppRecovery, pcbRecovery ) );
}
//+----------------------------------------------------------------------------
//
// Function: CRegStorage::SetBlobProp
//
// Synopsis: Sets a property of type Binary in a Dfs Manager volume object
//
// Arguments:
//
// Returns:
//
//-----------------------------------------------------------------------------
DWORD
CRegStorage::SetBlobProp(
LPWSTR wszProperty,
PBYTE pBlob,
ULONG cbBlob)
{
DWORD dwErr;
dwErr = RegSetValueEx(
_hKey,
wszProperty,
NULL,
REG_BINARY,
pBlob,
cbBlob);
return ( dwErr );
}
//+----------------------------------------------------------------------------
//
// Function: CRegStorage::GetBlobProp
//
// Synopsis: Retrieves a property of type Binary from the
//
// Arguments:
//
// Returns:
//
//-----------------------------------------------------------------------------
DWORD
CRegStorage::GetBlobProp(
LPWSTR wszProperty,
PBYTE *ppBuffer,
PULONG pcbBuffer)
{
DWORD dwErr, dwUnused;
dwErr = RegQueryInfoKey(
_hKey, // Key
NULL, // Class string
NULL, // Size of class string
NULL, // Reserved
&dwUnused, // # of subkeys
&dwUnused, // max size of subkey name
&dwUnused, // max size of class name
&dwUnused, // # of values
&dwUnused, // max size of value name
pcbBuffer, // max size of value data,
NULL, // security descriptor
NULL); // Last write time
if (dwErr == ERROR_SUCCESS) {
*ppBuffer = new BYTE [*pcbBuffer];
if (*ppBuffer != NULL) {
dwErr = DfsmQueryValue(
_hKey,
wszProperty,
REG_BINARY,
0,
*ppBuffer,
pcbBuffer);
if (dwErr) {
delete [] *ppBuffer;
*ppBuffer = NULL;
*pcbBuffer = 0;
}
} else {
dwErr = ERROR_OUTOFMEMORY;
}
}
return( dwErr );
}
//+----------------------------------------------------------------------------
//
// Function: CRegEnumDirectory::CRegEnumDirectory
//
// Synopsis: Constructor for an object of class CRegEnumDirectory.
//
// Arguments: [hKey] -- The registry key over which this enumerator is being
// instantiated. This handle will be duplicated.
//
// [pdwErr] -- Error code if error occurs during construction.
// Win32 error of result of DuplicateHandle call.
//
// Returns: Nothing. See comment on [pdwErr]
//
//-----------------------------------------------------------------------------
CRegEnumDirectory::CRegEnumDirectory(
HKEY hKey,
DWORD *pdwErr)
{
BOOL fResult;
IDfsVolInlineDebOut((
DEB_TRACE, "CRegEnumDirectory::+CRegEnumDirectory(0x%x)\n",
this));
fResult = DuplicateHandle(
GetCurrentProcess(), // Source Process
(HANDLE) hKey, // Source Handle
GetCurrentProcess(), // Target Process
(HANDLE *) &_hKey, // Target Handle
0, // Desired Access - ignored
FALSE, // Non inheritable
DUPLICATE_SAME_ACCESS); // Options - set to
// DUPLICATE_SAME_ACCESS,
// causes Desired Access to
// be ignored.
if (!fResult) {
*pdwErr = GetLastError();
_hKey = NULL;
} else {
*pdwErr = ERROR_SUCCESS;
}
_iNext = 0;
}
//+----------------------------------------------------------------------------
//
// Function: CRegEnumDirectory::~CRegEnumDirectory
//
// Synopsis: Destructor for an object of class CRegEnumDirectory
//
// Arguments: None
//
// Returns: Nothing
//
//-----------------------------------------------------------------------------
CRegEnumDirectory::~CRegEnumDirectory()
{
IDfsVolInlineDebOut((
DEB_TRACE, "CRegEnumDirectory::~CRegEnumDirectory(0x%x)\n",
this));
if (_hKey != NULL) {
CloseHandle( _hKey );
}
}
//+----------------------------------------------------------------------------
//
// Function: CRegEnumDirectory::Next
//
// Synopsis: Returns the next child of this directory.
//
// Arguments: [rgelt] -- Pointer to STATDIR structure. Only the name
// of the child relative to this storage is returned.
// [pcFetched] -- Set to 1 if a child name is successfully
// retrieved, 0 if an error occurs or if no more
// children.
//
// Returns: [ERROR_SUCCESS] -- Operation succeeded. If no more children
// are available, ERROR_SUCCESS is returned and
// *pcFetched is set to 0.
//
// [ERROR_OUTOFMEMORY] -- Unable to allocate room for child name.
//
//-----------------------------------------------------------------------------
DWORD
CRegEnumDirectory::Next(
DFSMSTATDIR *rgelt,
PULONG pcFetched)
{
DWORD dwErr;
LPWSTR lpwszChildName;
ZeroMemory( rgelt, sizeof(DFSMSTATDIR) );
lpwszChildName = new WCHAR[ MAX_PATH + 1 ];
if (lpwszChildName != NULL) {
dwErr = RegEnumKey(
_hKey,
_iNext,
lpwszChildName,
(MAX_PATH + 1) );
if (dwErr == ERROR_SUCCESS) {
rgelt->pwcsName = lpwszChildName;
*pcFetched = 1;
_iNext++;
} else {
delete [] lpwszChildName;
*pcFetched = 0;
if (dwErr == ERROR_NO_MORE_ITEMS)
dwErr = ERROR_SUCCESS;
}
} else {
dwErr = ERROR_OUTOFMEMORY;
}
return( dwErr );
}
//+----------------------------------------------------------------------------
//
// Function: DfsmQueryValue
//
// Synopsis: Helper function that calls RegQueryValueEx and verifies that
// the returned type is equal to the expected type.
//
// Arguments: [hkey] -- Handle to key
// [wszValueName] -- Name of value to read
// [dwExpectedType] -- Expected type of value
// [dwExpectedSize] -- Expected size of read in value. If
// this is nonzero, this routine will return an error
// if the read-in size is not equal to expected size.
// If this is 0, no checking is performed.
// [pBuffer] -- To receive the value data
// [pcbBuffer] -- On call, size of pBuffer. On successful return,
// the size of data read in
//
// Returns: [ERROR_SUCCESS] -- Successfully read the value data.
//
// [DFS_E_VOLUME_OBJECT_CORRUPT] -- If read-in type did not
// match dwExpectedType, or if dwExpectedSize was
// nonzero and the read-in size did not match it.
//
// DWORD_FROM_WIN32 of RegQueryValueEx return code.
//
//-----------------------------------------------------------------------------
DWORD
DfsmQueryValue(
HKEY hkey,
LPWSTR wszValueName,
DWORD dwExpectedType,
DWORD dwExpectedSize,
PBYTE pBuffer,
LPDWORD pcbBuffer)
{
DWORD dwErr;
DWORD dwType;
dwErr = RegQueryValueEx(
hkey,
wszValueName,
NULL,
&dwType,
pBuffer,
pcbBuffer);
if (dwErr == ERROR_SUCCESS) {
if (dwExpectedType != dwType) {
dwErr = NERR_DfsInternalCorruption;
} else if (dwExpectedSize != 0 && dwExpectedSize != *pcbBuffer) {
dwErr = NERR_DfsInternalCorruption;
} else {
dwErr = ERROR_SUCCESS;
}
}
return( dwErr );
}
DWORD
RegCreateObject(
IN LPWSTR lpwszFileName)
{
DWORD dwErr;
HKEY hkey;
dwErr = RegCreateKey(HKEY_LOCAL_MACHINE, lpwszFileName, &hkey);
if (dwErr == ERROR_SUCCESS) {
RegCloseKey( hkey );
}
return( dwErr );
}
DWORD
RegPutData(
IN LPWSTR lpwszFileName,
IN LPWSTR lpwszProperty,
IN DWORD cBytes,
IN PBYTE pData)
{
DWORD dwErr;
HKEY hKey;
dwErr = RegOpenKey( HKEY_LOCAL_MACHINE, lpwszFileName, &hKey );
if (dwErr == ERROR_SUCCESS) {
dwErr = RegSetValueEx(
hKey,
lpwszProperty,
NULL,
REG_BINARY,
pData,
cBytes);
RegCloseKey( hKey );
}
return ( dwErr );
}
DWORD
RegGetData(
IN LPWSTR lpwszFileName,
IN LPWSTR lpwszProperty,
OUT PDWORD pcbBuffer,
OUT PBYTE *ppBuffer)
{
DWORD dwErr;
DWORD dwUnused;
HKEY hKey;
PBYTE pBuffer;
DWORD cbBuffer;
dwErr = RegOpenKey( HKEY_LOCAL_MACHINE, lpwszFileName, &hKey );
if (dwErr == ERROR_SUCCESS) {
dwErr = RegQueryInfoKey(
hKey, // Key
NULL, // Class string
NULL, // Size of class string
NULL, // Reserved
&dwUnused, // # of subkeys
&dwUnused, // max size of subkey name
&dwUnused, // max size of class name
&dwUnused, // # of values
&dwUnused, // max size of value name
&cbBuffer, // max size of value data,
NULL, // security descriptor
NULL); // Last write time
if (dwErr == ERROR_SUCCESS) {
pBuffer = new BYTE [cbBuffer];
if (pBuffer != NULL) {
dwErr = DfsmQueryValue(
hKey,
lpwszProperty,
REG_BINARY,
0,
pBuffer,
&cbBuffer);
if (dwErr != ERROR_SUCCESS) {
delete [] pBuffer;
}
} else {
dwErr = ERROR_OUTOFMEMORY;
}
}
RegCloseKey(hKey);
}
if (dwErr == ERROR_SUCCESS) {
*pcbBuffer = cbBuffer;
*ppBuffer = pBuffer;
}
return dwErr;
}