1317 lines
36 KiB
C++
1317 lines
36 KiB
C++
//+----------------------------------------------------------------------------
|
||
//
|
||
// 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;
|
||
}
|