2405 lines
60 KiB
C++
2405 lines
60 KiB
C++
|
//--------------------------------------------------------------------------
|
||
|
//
|
||
|
// Copyright (C) 1999, Microsoft Corporation
|
||
|
//
|
||
|
// File: stdsup.cxx
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
#define UNICODE
|
||
|
|
||
|
#include <stdio.h>
|
||
|
#include <nt.h>
|
||
|
#include <ntrtl.h>
|
||
|
#include <nturtl.h>
|
||
|
#include <windows.h>
|
||
|
#include <winldap.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <dsgetdc.h>
|
||
|
#include <lm.h>
|
||
|
#include <dfsstr.h>
|
||
|
#include <dfsmrshl.h>
|
||
|
#include <marshal.hxx>
|
||
|
#include <lmdfs.h>
|
||
|
#include <dfspriv.h>
|
||
|
#include <csites.hxx>
|
||
|
#include <dfsm.hxx>
|
||
|
#include <recon.hxx>
|
||
|
|
||
|
#include <rpc.h>
|
||
|
|
||
|
#include "struct.hxx"
|
||
|
#include "rootsup.hxx"
|
||
|
#include "dfsacl.hxx"
|
||
|
#include "misc.hxx"
|
||
|
#include "messages.h"
|
||
|
|
||
|
#include "struct.hxx"
|
||
|
#include "ftsup.hxx"
|
||
|
#include "stdsup.hxx"
|
||
|
|
||
|
DWORD
|
||
|
PutSiteTable(
|
||
|
HKEY hKey,
|
||
|
PDFS_VOLUME_LIST pDfsVolList);
|
||
|
|
||
|
DWORD
|
||
|
DfsRecoverVolList(
|
||
|
PDFS_VOLUME_LIST pDfsVolList);
|
||
|
|
||
|
DWORD
|
||
|
DfsRegDeleteKeyAndChildren(
|
||
|
HKEY hkey,
|
||
|
LPWSTR s);
|
||
|
|
||
|
DWORD
|
||
|
DfsGetStdVol(
|
||
|
HKEY rKey,
|
||
|
PDFS_VOLUME_LIST pDfsVolList)
|
||
|
{
|
||
|
|
||
|
HKEY hKey = NULL;
|
||
|
DWORD dwErr;
|
||
|
LPWSTR *pNames = NULL;
|
||
|
ULONG cKeys = 0;
|
||
|
ULONG i;
|
||
|
WCHAR VolumesDir[MAX_PATH+1];
|
||
|
|
||
|
wcscpy(VolumesDir, VOLUMES_DIR);
|
||
|
wcscat(VolumesDir, L"domainroot");
|
||
|
|
||
|
dwErr = RegOpenKey(
|
||
|
rKey,
|
||
|
VolumesDir,
|
||
|
&hKey);
|
||
|
|
||
|
if (dwErr != ERROR_SUCCESS) {
|
||
|
MyPrintf(L"Not a StdDfs root!\r\n");
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
dwErr = EnumKeys(
|
||
|
hKey,
|
||
|
&cKeys,
|
||
|
&pNames);
|
||
|
|
||
|
if (dwErr != ERROR_SUCCESS) {
|
||
|
MyPrintf(L"No exit points...\r\n");
|
||
|
goto SiteInfo;
|
||
|
}
|
||
|
|
||
|
pDfsVolList->Version = 3;
|
||
|
pDfsVolList->VolCount = cKeys+1;
|
||
|
pDfsVolList->Volumes = (PDFS_VOLUME *)malloc((cKeys+1) * sizeof(PDFS_VOLUME));
|
||
|
|
||
|
if (pDfsVolList->Volumes == NULL) {
|
||
|
dwErr = ERROR_OUTOFMEMORY;
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
pDfsVolList->AllocatedVolCount = cKeys + 1;
|
||
|
RtlZeroMemory(pDfsVolList->Volumes, pDfsVolList->AllocatedVolCount * sizeof(PDFS_VOLUME));
|
||
|
|
||
|
pDfsVolList->Volumes[0] = (PDFS_VOLUME) malloc(sizeof(DFS_VOLUME));
|
||
|
if (pDfsVolList->Volumes[0] == NULL) {
|
||
|
dwErr = ERROR_OUTOFMEMORY;
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
RtlZeroMemory(pDfsVolList->Volumes[0], sizeof(DFS_VOLUME));
|
||
|
dwErr = GetDfsKey(
|
||
|
rKey,
|
||
|
L"domainroot",
|
||
|
pDfsVolList->Volumes[0]);
|
||
|
|
||
|
for (i = 0; i < cKeys; i++) {
|
||
|
wcscpy(VolumesDir, L"domainroot\\");
|
||
|
wcscat(VolumesDir, pNames[i]);
|
||
|
pDfsVolList->Volumes[i+1] = (PDFS_VOLUME) malloc(sizeof(DFS_VOLUME));
|
||
|
if (pDfsVolList->Volumes[i+1] == NULL) {
|
||
|
dwErr = ERROR_OUTOFMEMORY;
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
RtlZeroMemory(pDfsVolList->Volumes[i+1], sizeof(DFS_VOLUME));
|
||
|
dwErr = GetDfsKey(
|
||
|
rKey,
|
||
|
VolumesDir,
|
||
|
pDfsVolList->Volumes[i+1]);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Do any recovery needed
|
||
|
//
|
||
|
|
||
|
dwErr = DfsRecoverVolList(pDfsVolList);
|
||
|
|
||
|
RegCloseKey(hKey);
|
||
|
hKey = NULL;
|
||
|
|
||
|
pDfsVolList->DfsType = STDDFS;
|
||
|
|
||
|
SiteInfo:
|
||
|
|
||
|
//
|
||
|
// Site information
|
||
|
//
|
||
|
wcscpy(VolumesDir, VOLUMES_DIR);
|
||
|
wcscat(VolumesDir, L"siteroot");
|
||
|
|
||
|
dwErr = RegOpenKey(
|
||
|
rKey,
|
||
|
VolumesDir,
|
||
|
&hKey);
|
||
|
|
||
|
if (dwErr != ERROR_SUCCESS) {
|
||
|
dwErr = ERROR_SUCCESS;
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
dwErr = GetSiteTable(
|
||
|
hKey,
|
||
|
pDfsVolList);
|
||
|
|
||
|
if (dwErr != ERROR_SUCCESS) {
|
||
|
MyPrintf(L"Missing siteroot key (non-fatal error)\r\n");
|
||
|
dwErr = ERROR_SUCCESS;
|
||
|
}
|
||
|
|
||
|
|
||
|
Cleanup:
|
||
|
|
||
|
FreeNameList(
|
||
|
pNames,
|
||
|
cKeys);
|
||
|
|
||
|
pNames = NULL;
|
||
|
|
||
|
if (hKey != NULL)
|
||
|
RegCloseKey(hKey);
|
||
|
|
||
|
return dwErr;
|
||
|
|
||
|
}
|
||
|
|
||
|
DWORD
|
||
|
GetDfsKey(
|
||
|
HKEY rKey,
|
||
|
LPWSTR wszKeyName,
|
||
|
PDFS_VOLUME pVolume)
|
||
|
{
|
||
|
DWORD dwErr = 0;
|
||
|
HKEY hKey = NULL;
|
||
|
ULONG cRepl;
|
||
|
WCHAR VolumesDir[MAX_PATH+1];
|
||
|
|
||
|
wcscpy(VolumesDir, VOLUMES_DIR);
|
||
|
wcscat(VolumesDir, wszKeyName);
|
||
|
|
||
|
if (fSwDebug == TRUE)
|
||
|
MyPrintf(L"GetDfsKey(%ws)\r\n", VolumesDir);
|
||
|
|
||
|
dwErr = RegOpenKey(
|
||
|
rKey,
|
||
|
VolumesDir,
|
||
|
&hKey);
|
||
|
|
||
|
if (dwErr != ERROR_SUCCESS) {
|
||
|
if (fSwDebug == TRUE)
|
||
|
MyPrintf(L"RegOpenKey(%ws) returned %d\r\n", VolumesDir, dwErr);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Id (Prefix, Type, state, etc)
|
||
|
//
|
||
|
|
||
|
wcscpy(VolumesDir, L"\\");
|
||
|
wcscat(VolumesDir, wszKeyName);
|
||
|
|
||
|
GIP_DUPLICATE_STRING(dwErr, VolumesDir, &pVolume->wszObjectName);
|
||
|
|
||
|
if (dwErr != ERROR_SUCCESS) {
|
||
|
if (fSwDebug == TRUE)
|
||
|
MyPrintf(L"DUP_STRING(%ws) returned %d\r\n", VolumesDir, dwErr);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
dwErr = GetIdProps(
|
||
|
hKey,
|
||
|
&pVolume->dwType,
|
||
|
&pVolume->dwState,
|
||
|
&pVolume->wszPrefix,
|
||
|
&pVolume->wszShortPrefix,
|
||
|
&pVolume->idVolume,
|
||
|
&pVolume->wszComment,
|
||
|
&pVolume->dwTimeout,
|
||
|
&pVolume->ftPrefix,
|
||
|
&pVolume->ftState,
|
||
|
&pVolume->ftComment);
|
||
|
|
||
|
if (dwErr != ERROR_SUCCESS) {
|
||
|
if (fSwDebug == TRUE)
|
||
|
MyPrintf(L"GetIdProps() returned %d\r\n", dwErr);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Services (replicas)
|
||
|
//
|
||
|
|
||
|
dwErr = GetSvcProps(
|
||
|
hKey,
|
||
|
pVolume);
|
||
|
|
||
|
if (dwErr != ERROR_SUCCESS) {
|
||
|
if (fSwDebug == TRUE)
|
||
|
MyPrintf(L"GetSvcProps() returned %d\r\n", dwErr);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
dwErr = GetVersionProps(
|
||
|
hKey,
|
||
|
VERSION_PROPS,
|
||
|
&pVolume->dwVersion);
|
||
|
|
||
|
if (dwErr != ERROR_SUCCESS) {
|
||
|
if (fSwDebug == TRUE)
|
||
|
MyPrintf(L"GetVersionProps() returned %d\r\n", dwErr);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
dwErr = GetRecoveryProps(
|
||
|
hKey,
|
||
|
RECOVERY_PROPS,
|
||
|
&pVolume->cbRecovery,
|
||
|
&pVolume->pRecovery);
|
||
|
|
||
|
if (dwErr != ERROR_SUCCESS) {
|
||
|
if (fSwDebug == TRUE)
|
||
|
MyPrintf(L"GetRecoveryProps() returned %d\r\n", dwErr);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
Cleanup:
|
||
|
|
||
|
if (hKey != NULL)
|
||
|
RegCloseKey(hKey);
|
||
|
|
||
|
if (fSwDebug == TRUE)
|
||
|
MyPrintf(L"GetDfsKey exit %d\r\n", dwErr);
|
||
|
|
||
|
return( dwErr );
|
||
|
|
||
|
}
|
||
|
|
||
|
DWORD
|
||
|
ReadSiteTable(PBYTE pBuffer, ULONG cbBuffer)
|
||
|
{
|
||
|
DWORD dwErr;
|
||
|
ULONG cObjects = 0;
|
||
|
ULONG cbThisObj;
|
||
|
ULONG i;
|
||
|
ULONG j;
|
||
|
PLIST_ENTRY pListHead, pLink;
|
||
|
PDFSM_SITE_ENTRY pSiteInfo;
|
||
|
MARSHAL_BUFFER marshalBuffer;
|
||
|
GUID guid;
|
||
|
ULONG Size;
|
||
|
|
||
|
dwErr = ERROR_SUCCESS;
|
||
|
|
||
|
if (dwErr == ERROR_SUCCESS && cbBuffer >= sizeof(ULONG)) {
|
||
|
|
||
|
//
|
||
|
// Unmarshall all the objects (NET_DFS_SITENAME_INFO's) in the buffer
|
||
|
//
|
||
|
|
||
|
MarshalBufferInitialize(
|
||
|
&marshalBuffer,
|
||
|
cbBuffer,
|
||
|
pBuffer);
|
||
|
|
||
|
DfsRtlGetGuid(&marshalBuffer, &guid);
|
||
|
DfsRtlGetUlong(&marshalBuffer, &cObjects);
|
||
|
|
||
|
for (j = 0; j < cObjects; j++) {
|
||
|
|
||
|
pSiteInfo = (PDFSM_SITE_ENTRY) new BYTE [cbBuffer-sizeof(ULONG)];
|
||
|
if (pSiteInfo == NULL) {
|
||
|
dwErr = ERROR_OUTOFMEMORY;
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
dwErr = DfsRtlGet(&marshalBuffer,&MiDfsmSiteEntry, pSiteInfo);
|
||
|
Size = (ULONG)((PCHAR)&pSiteInfo->Info.Site[pSiteInfo->Info.cSites] - (PCHAR)pSiteInfo);
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
Cleanup:
|
||
|
|
||
|
return dwErr;
|
||
|
}
|
||
|
|
||
|
//+----------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: GetIdProps
|
||
|
//
|
||
|
// Synopsis: Retrieves the Id Properties of a Dfs Manager volume object.
|
||
|
//
|
||
|
// 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
|
||
|
GetIdProps(
|
||
|
HKEY hKey,
|
||
|
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 dwType;
|
||
|
DWORD cbBuffer;
|
||
|
ULONG dwTimeout;
|
||
|
PBYTE pBuffer = NULL;
|
||
|
MARSHAL_BUFFER marshalBuffer;
|
||
|
DFS_ID_PROPS idProps;
|
||
|
|
||
|
if (fSwDebug == TRUE)
|
||
|
MyPrintf(L"GetIdProps()\r\n");
|
||
|
|
||
|
*ppwszPrefix = NULL;
|
||
|
*ppwszComment = NULL;
|
||
|
|
||
|
dwErr = GetBlobByValue(
|
||
|
hKey,
|
||
|
ID_PROPS,
|
||
|
&pBuffer,
|
||
|
&cbBuffer);
|
||
|
|
||
|
if (dwErr != ERROR_SUCCESS)
|
||
|
goto Cleanup;
|
||
|
|
||
|
MarshalBufferInitialize(&marshalBuffer, cbBuffer, pBuffer);
|
||
|
|
||
|
status = DfsRtlGet(&marshalBuffer, &MiDfsIdProps, &idProps);
|
||
|
|
||
|
if (NT_SUCCESS(status)) {
|
||
|
|
||
|
GIP_DUPLICATE_PREFIX( dwErr, idProps.wszPrefix, ppwszPrefix );
|
||
|
|
||
|
if (dwErr == ERROR_SUCCESS) {
|
||
|
|
||
|
GIP_DUPLICATE_PREFIX(
|
||
|
dwErr,
|
||
|
idProps.wszShortPath,
|
||
|
ppwszShortPath );
|
||
|
|
||
|
}
|
||
|
|
||
|
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 (*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;
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
Cleanup:
|
||
|
|
||
|
if (pBuffer != NULL)
|
||
|
delete [] pBuffer;
|
||
|
|
||
|
if (fSwDebug == TRUE)
|
||
|
MyPrintf(L"GetIdProps exit %d\r\n", dwErr);
|
||
|
|
||
|
return( dwErr );
|
||
|
}
|
||
|
|
||
|
DWORD
|
||
|
DfsSetStdVol(
|
||
|
HKEY rKey,
|
||
|
PDFS_VOLUME_LIST pDfsVolList)
|
||
|
{
|
||
|
|
||
|
HKEY hKey = NULL;
|
||
|
DWORD dwErr = ERROR_SUCCESS;
|
||
|
DWORD dwErr2 = ERROR_SUCCESS;
|
||
|
ULONG i;
|
||
|
PDFS_VOLUME pVol;
|
||
|
PWCHAR wCp;
|
||
|
WCHAR FolderDir[MAX_PATH+1];
|
||
|
|
||
|
if (fSwDebug == TRUE)
|
||
|
MyPrintf(L"DfsSetStdVol()\r\n");
|
||
|
|
||
|
wcscpy(FolderDir, VOLUMES_DIR);
|
||
|
wcscat(FolderDir, L"domainroot");
|
||
|
|
||
|
dwErr = RegOpenKey(
|
||
|
rKey,
|
||
|
FolderDir,
|
||
|
&hKey);
|
||
|
|
||
|
if (dwErr != ERROR_SUCCESS) {
|
||
|
MyPrintf(L"Not a StdDfs root!\r\n");
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Loop through all the dfs links and if the modify bit is set,
|
||
|
// create an entry in the registry. If the delete bit is set,
|
||
|
// delete the entry.
|
||
|
//
|
||
|
// On error we continue, but capture the error which will
|
||
|
// later be returned.
|
||
|
//
|
||
|
|
||
|
for (i = 1; i < pDfsVolList->VolCount; i++) {
|
||
|
pVol = pDfsVolList->Volumes[i];
|
||
|
if ((pVol->vFlags & VFLAGS_DELETE) != 0) {
|
||
|
for (wCp = &pVol->wszObjectName[1]; *wCp != NULL && *wCp != UNICODE_PATH_SEP; wCp++)
|
||
|
NOTHING;
|
||
|
wCp++;
|
||
|
dwErr = RegDeleteKey(hKey, wCp);
|
||
|
} else if ((pVol->vFlags & VFLAGS_MODIFY) != 0) {
|
||
|
dwErr = SetDfsKey(hKey, pVol->wszObjectName, pVol);
|
||
|
} else {
|
||
|
dwErr = ERROR_SUCCESS;
|
||
|
}
|
||
|
if (dwErr != ERROR_SUCCESS)
|
||
|
dwErr2 = dwErr;
|
||
|
}
|
||
|
|
||
|
RegCloseKey(hKey);
|
||
|
hKey = NULL;
|
||
|
|
||
|
//
|
||
|
// Write site table only if it has changed
|
||
|
//
|
||
|
if ((pDfsVolList->sFlags & VFLAGS_MODIFY) != 0 || pDfsVolList->SiteCount > 0) {
|
||
|
wcscpy(FolderDir, VOLUMES_DIR);
|
||
|
wcscat(FolderDir, L"siteroot");
|
||
|
|
||
|
dwErr = RegOpenKey(
|
||
|
rKey,
|
||
|
FolderDir,
|
||
|
&hKey);
|
||
|
|
||
|
if (dwErr != ERROR_SUCCESS) {
|
||
|
MyPrintf(L"Can not open siteroot\r\n");
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
dwErr2 = PutSiteTable(hKey, pDfsVolList);
|
||
|
}
|
||
|
|
||
|
Cleanup:
|
||
|
|
||
|
if (hKey != NULL)
|
||
|
RegCloseKey(hKey);
|
||
|
|
||
|
if (fSwDebug == TRUE)
|
||
|
MyPrintf(L"DfsSetStdVol() exit %d\r\n", dwErr2);
|
||
|
|
||
|
return dwErr2;
|
||
|
|
||
|
}
|
||
|
|
||
|
DWORD
|
||
|
SetDfsKey(
|
||
|
HKEY rKey,
|
||
|
LPWSTR wszKeyName,
|
||
|
PDFS_VOLUME pVolume)
|
||
|
{
|
||
|
DWORD dwErr = ERROR_SUCCESS;
|
||
|
HKEY hKey = NULL;
|
||
|
PWCHAR wCp;
|
||
|
|
||
|
if (fSwDebug == TRUE)
|
||
|
MyPrintf(L"SetDfsKey(%ws)\r\n", wszKeyName);
|
||
|
|
||
|
for (wCp = &wszKeyName[1]; *wCp != NULL && *wCp != UNICODE_PATH_SEP; wCp++)
|
||
|
NOTHING;
|
||
|
|
||
|
if (*wCp != UNICODE_PATH_SEP) {
|
||
|
dwErr = ERROR_INVALID_PARAMETER;
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
wCp++;
|
||
|
dwErr = RegCreateKey(
|
||
|
rKey,
|
||
|
wCp,
|
||
|
&hKey);
|
||
|
|
||
|
if (dwErr != ERROR_SUCCESS) {
|
||
|
if (fSwDebug == TRUE)
|
||
|
MyPrintf(L"RegCreateKey(%ws) returned %d\r\n", wCp, dwErr);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
dwErr = SetIdProps(
|
||
|
hKey,
|
||
|
pVolume->dwType,
|
||
|
pVolume->dwState,
|
||
|
pVolume->wszPrefix,
|
||
|
pVolume->wszShortPrefix,
|
||
|
pVolume->idVolume,
|
||
|
pVolume->wszComment,
|
||
|
pVolume->dwTimeout,
|
||
|
pVolume->ftPrefix,
|
||
|
pVolume->ftState,
|
||
|
pVolume->ftComment);
|
||
|
|
||
|
if (dwErr != ERROR_SUCCESS) {
|
||
|
if (fSwDebug == TRUE)
|
||
|
MyPrintf(L"SetIdProps() returned %d\r\n", dwErr);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Services (replicas)
|
||
|
//
|
||
|
|
||
|
dwErr = SetSvcProps(
|
||
|
hKey,
|
||
|
pVolume);
|
||
|
|
||
|
if (dwErr != ERROR_SUCCESS) {
|
||
|
if (fSwDebug == TRUE)
|
||
|
MyPrintf(L"SetSvcProps() returned %d\r\n", dwErr);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
dwErr = SetVersionProps(
|
||
|
hKey,
|
||
|
pVolume);
|
||
|
|
||
|
if (dwErr != ERROR_SUCCESS) {
|
||
|
if (fSwDebug == TRUE)
|
||
|
MyPrintf(L"SetVersionProps() returned %d\r\n", dwErr);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
dwErr = SetRecoveryProps(
|
||
|
hKey,
|
||
|
pVolume);
|
||
|
|
||
|
if (dwErr != ERROR_SUCCESS) {
|
||
|
if (fSwDebug == TRUE)
|
||
|
MyPrintf(L"SetRecoveryProps() returned %d\r\n", dwErr);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
Cleanup:
|
||
|
|
||
|
if (hKey != NULL)
|
||
|
RegCloseKey(hKey);
|
||
|
|
||
|
if (fSwDebug == TRUE)
|
||
|
MyPrintf(L"SetDfsKey exit %d\r\n", dwErr);
|
||
|
|
||
|
return( dwErr );
|
||
|
|
||
|
}
|
||
|
|
||
|
//+----------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: SetIdProps
|
||
|
//
|
||
|
// Synopsis: Sets the Id Properties of a Dfs Manager volume object.
|
||
|
//
|
||
|
// Arguments:
|
||
|
//
|
||
|
// Returns: [S_OK] -- Successfully retrieved the properties.
|
||
|
//
|
||
|
// [ERROR_OUTOFMEMORY] -- Unable to allocate memory for properties
|
||
|
// or other uses.
|
||
|
//
|
||
|
//-----------------------------------------------------------------------------
|
||
|
|
||
|
DWORD
|
||
|
SetIdProps(
|
||
|
HKEY hKey,
|
||
|
ULONG dwType,
|
||
|
ULONG dwState,
|
||
|
LPWSTR pwszPrefix,
|
||
|
LPWSTR pwszShortPath,
|
||
|
GUID idVolume,
|
||
|
LPWSTR pwszComment,
|
||
|
ULONG dwTimeout,
|
||
|
FILETIME ftPrefix,
|
||
|
FILETIME ftState,
|
||
|
FILETIME ftComment)
|
||
|
{
|
||
|
|
||
|
// prefix bug 447510; initialize dwerr
|
||
|
DWORD dwErr = ERROR_SUCCESS;
|
||
|
NTSTATUS status;
|
||
|
DWORD cbBuffer;
|
||
|
PBYTE pBuffer = NULL;
|
||
|
MARSHAL_BUFFER marshalBuffer;
|
||
|
DFS_ID_PROPS idProps;
|
||
|
|
||
|
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 );
|
||
|
DfsRtlPutUlong(&marshalBuffer, &dwTimeout);
|
||
|
if (NT_SUCCESS(status)) {
|
||
|
dwErr = SetBlobByValue(
|
||
|
hKey,
|
||
|
ID_PROPS,
|
||
|
pBuffer,
|
||
|
cbBuffer);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (pBuffer != NULL)
|
||
|
delete [] pBuffer;
|
||
|
|
||
|
return( dwErr );
|
||
|
}
|
||
|
|
||
|
DWORD
|
||
|
SetSvcProps(
|
||
|
HKEY hKey,
|
||
|
PDFS_VOLUME pVol)
|
||
|
{
|
||
|
DWORD cbBuffer;
|
||
|
DWORD dwErr = ERROR_SUCCESS;
|
||
|
PBYTE Buffer = NULL;
|
||
|
PBYTE pBuf = NULL;
|
||
|
ULONG *Size = NULL;
|
||
|
ULONG *pSize = NULL;
|
||
|
ULONG TotalSize = 0;
|
||
|
ULONG i;
|
||
|
|
||
|
if (fSwDebug == TRUE)
|
||
|
MyPrintf(L"SetSvcProps(%ws)\r\n", pVol->wszObjectName);
|
||
|
|
||
|
pSize = Size = (PULONG) malloc(sizeof(ULONG) * (pVol->ReplCount + pVol->DelReplCount));
|
||
|
if (Size == NULL) {
|
||
|
dwErr = ERROR_OUTOFMEMORY;
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Need all the size values now and later for marshalling stuff.
|
||
|
// So we collect them here into an array.
|
||
|
//
|
||
|
TotalSize = 0;
|
||
|
for (i = 0; i < pVol->ReplCount; i++) {
|
||
|
*pSize = GetReplicaMarshalSize(&pVol->ReplicaInfo[i], &pVol->FtModification[i]);
|
||
|
TotalSize += *pSize;
|
||
|
pSize++;
|
||
|
}
|
||
|
for (i = 0; i < pVol->DelReplCount; i++) {
|
||
|
*pSize = GetReplicaMarshalSize(&pVol->DelReplicaInfo[i], &pVol->DelFtModification[i]);
|
||
|
TotalSize += *pSize;
|
||
|
pSize++;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Allocate the byte Buffer we need
|
||
|
//
|
||
|
// TotalSize is the size required marshal all the replicas and
|
||
|
// their last-modification-timestamps.
|
||
|
//
|
||
|
// In addition, we need:
|
||
|
//
|
||
|
// 1 ULONG for storing the count of replicas
|
||
|
// ReplCount ULONGs for storing the marshal size of each replica.
|
||
|
//
|
||
|
|
||
|
TotalSize += sizeof(ULONG) * (1 + pVol->ReplCount + 1 + pVol->DelReplCount);
|
||
|
Buffer = pBuf = (PBYTE) malloc(TotalSize);
|
||
|
if (Buffer == NULL) {
|
||
|
dwErr = ERROR_OUTOFMEMORY;
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Set the number of entries to follow in the Buffer at the start.
|
||
|
//
|
||
|
_PutULong(pBuf, pVol->ReplCount);
|
||
|
pBuf += sizeof(ULONG);
|
||
|
pSize = Size;
|
||
|
for (i = 0; i < pVol->ReplCount; i++) {
|
||
|
//
|
||
|
// Marshall each replica Entry into the Buffer.
|
||
|
// Remember we first need to put the size of the marshalled
|
||
|
// replica entry to follow, then the FILETIME for the replica,
|
||
|
// and finally, the marshalled replica entry structure.
|
||
|
//
|
||
|
_PutULong(pBuf, *pSize);
|
||
|
pBuf += sizeof(ULONG);
|
||
|
dwErr = SerializeReplica(
|
||
|
&pVol->ReplicaInfo[i],
|
||
|
pVol->FtModification ? &pVol->FtModification[i] : NULL,
|
||
|
pBuf,
|
||
|
*pSize);
|
||
|
if (dwErr != ERROR_SUCCESS)
|
||
|
goto Cleanup;
|
||
|
pBuf += *pSize;
|
||
|
pSize++;
|
||
|
}
|
||
|
//
|
||
|
// Now the deleted replicas
|
||
|
//
|
||
|
_PutULong(pBuf, pVol->DelReplCount);
|
||
|
pBuf += sizeof(ULONG);
|
||
|
for (i = 0; i < pVol->DelReplCount; i++) {
|
||
|
_PutULong(pBuf, *pSize);
|
||
|
pBuf += sizeof(ULONG);
|
||
|
dwErr = SerializeReplica(
|
||
|
&pVol->DelReplicaInfo[i],
|
||
|
pVol->DelFtModification ? &pVol->DelFtModification[i] : NULL,
|
||
|
pBuf,
|
||
|
*pSize);
|
||
|
if (dwErr != ERROR_SUCCESS)
|
||
|
goto Cleanup;
|
||
|
pBuf += *pSize;
|
||
|
pSize++;
|
||
|
}
|
||
|
dwErr = SetBlobByValue(
|
||
|
hKey,
|
||
|
SVC_PROPS,
|
||
|
Buffer,
|
||
|
TotalSize);
|
||
|
|
||
|
Cleanup:
|
||
|
|
||
|
if (Buffer != NULL)
|
||
|
delete [] Buffer;
|
||
|
|
||
|
if (Size != NULL)
|
||
|
delete [] Size;
|
||
|
|
||
|
if (fSwDebug == TRUE)
|
||
|
MyPrintf(L"SetSvcProps exit %d\n", dwErr);
|
||
|
|
||
|
return dwErr;
|
||
|
}
|
||
|
|
||
|
DWORD
|
||
|
SetVersionProps(
|
||
|
HKEY hKey,
|
||
|
PDFS_VOLUME pVol)
|
||
|
{
|
||
|
DWORD dwErr = ERROR_SUCCESS;
|
||
|
|
||
|
if (fSwDebug == TRUE)
|
||
|
MyPrintf(L"SetVersionProps(%ws)\r\n", pVol->wszObjectName);
|
||
|
|
||
|
dwErr = RegSetValueEx(
|
||
|
hKey,
|
||
|
VERSION_PROPS,
|
||
|
NULL,
|
||
|
REG_DWORD,
|
||
|
(LPBYTE) &pVol->dwVersion,
|
||
|
sizeof(DWORD));
|
||
|
|
||
|
if (fSwDebug == TRUE)
|
||
|
MyPrintf(L"SetVersionProps exit %d\n", dwErr);
|
||
|
|
||
|
return dwErr;
|
||
|
}
|
||
|
|
||
|
DWORD
|
||
|
SetRecoveryProps(
|
||
|
HKEY hKey,
|
||
|
PDFS_VOLUME pVol)
|
||
|
{
|
||
|
DWORD dwErr = ERROR_SUCCESS;
|
||
|
DWORD dwRecovery = 0;
|
||
|
|
||
|
if (fSwDebug == TRUE)
|
||
|
MyPrintf(L"SetRecoveryProps(%ws)\r\n", pVol->wszObjectName);
|
||
|
|
||
|
dwErr = RegSetValueEx(
|
||
|
hKey,
|
||
|
RECOVERY_PROPS,
|
||
|
NULL,
|
||
|
REG_BINARY,
|
||
|
(LPBYTE) &dwRecovery,
|
||
|
sizeof(DWORD));
|
||
|
|
||
|
if (fSwDebug == TRUE)
|
||
|
MyPrintf(L"SetRecoveryProps exit %d\n", dwErr);
|
||
|
|
||
|
return dwErr;
|
||
|
}
|
||
|
|
||
|
DWORD
|
||
|
PutSiteTable(
|
||
|
HKEY hKey,
|
||
|
PDFS_VOLUME_LIST pDfsVolList)
|
||
|
{
|
||
|
DWORD dwErr;
|
||
|
DWORD cbBuffer;
|
||
|
PBYTE pBuffer = NULL;
|
||
|
ULONG cObjects;
|
||
|
ULONG i;
|
||
|
PLIST_ENTRY pListHead, pLink;
|
||
|
PDFSM_SITE_ENTRY pSiteInfo;
|
||
|
MARSHAL_BUFFER marshalBuffer;
|
||
|
GUID SiteTableGuid = {0};
|
||
|
|
||
|
if (fSwDebug == TRUE)
|
||
|
MyPrintf(L"PutSiteTable()\n");
|
||
|
|
||
|
//
|
||
|
// Create a new Guid
|
||
|
//
|
||
|
|
||
|
|
||
|
dwErr = UuidCreate(&SiteTableGuid);
|
||
|
|
||
|
if(dwErr != RPC_S_OK){
|
||
|
// couldn't create a valid uuid
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// The cObjects count
|
||
|
//
|
||
|
cbBuffer = sizeof(ULONG) + sizeof(GUID);
|
||
|
|
||
|
//
|
||
|
// Add up the number of entries we need to store, and the total size of all
|
||
|
// of them.
|
||
|
//
|
||
|
cObjects = 0;
|
||
|
pListHead = &pDfsVolList->SiteList;
|
||
|
for (pLink = pListHead->Flink; pLink != pListHead; pLink = pLink->Flink) {
|
||
|
pSiteInfo = CONTAINING_RECORD(pLink, DFSM_SITE_ENTRY, Link);
|
||
|
DfsRtlSize(&MiDfsmSiteEntry, pSiteInfo, &cbBuffer);
|
||
|
cObjects++;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Get a buffer big enough
|
||
|
//
|
||
|
pBuffer = (PBYTE) malloc(cbBuffer);
|
||
|
if (pBuffer == NULL) {
|
||
|
dwErr = ERROR_OUTOFMEMORY;
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Put the guid, then the object count in the beginning of the buffer
|
||
|
//
|
||
|
MarshalBufferInitialize(
|
||
|
&marshalBuffer,
|
||
|
cbBuffer,
|
||
|
pBuffer);
|
||
|
|
||
|
DfsRtlPutGuid(&marshalBuffer, &SiteTableGuid);
|
||
|
DfsRtlPutUlong(&marshalBuffer, &cObjects);
|
||
|
|
||
|
//
|
||
|
// Walk the linked list of objects, marshalling them into the buffer.
|
||
|
//
|
||
|
for (pLink = pListHead->Flink; pLink != pListHead; pLink = pLink->Flink) {
|
||
|
pSiteInfo = CONTAINING_RECORD(pLink, DFSM_SITE_ENTRY, Link);
|
||
|
DfsRtlPut(&marshalBuffer,&MiDfsmSiteEntry, pSiteInfo);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Write the site table binary blob
|
||
|
//
|
||
|
dwErr = RegSetValueEx(
|
||
|
hKey,
|
||
|
SITE_VALUE_NAME,
|
||
|
NULL,
|
||
|
REG_BINARY,
|
||
|
pBuffer,
|
||
|
cbBuffer);
|
||
|
|
||
|
Cleanup:
|
||
|
if (pBuffer)
|
||
|
free(pBuffer);
|
||
|
|
||
|
if (fSwDebug == TRUE)
|
||
|
MyPrintf(L"PutSiteTable exit %d\n", dwErr);
|
||
|
|
||
|
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 );
|
||
|
}
|
||
|
|
||
|
//+----------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: GetBlobByValue
|
||
|
//
|
||
|
// Synopsis: Retrieves a property of type Binary from the value wszProperty
|
||
|
//
|
||
|
// Arguments:
|
||
|
//
|
||
|
// Returns:
|
||
|
//
|
||
|
//-----------------------------------------------------------------------------
|
||
|
|
||
|
DWORD
|
||
|
GetBlobByValue(
|
||
|
HKEY hKey,
|
||
|
LPWSTR wszProperty,
|
||
|
PBYTE *ppBuffer,
|
||
|
PULONG pcbBuffer)
|
||
|
{
|
||
|
DWORD dwErr;
|
||
|
DWORD 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: SetBlobByValue
|
||
|
//
|
||
|
// Synopsis: Saves a property of type Binary for the value wszProperty
|
||
|
//
|
||
|
// Arguments:
|
||
|
//
|
||
|
// Returns:
|
||
|
//
|
||
|
//-----------------------------------------------------------------------------
|
||
|
|
||
|
DWORD
|
||
|
SetBlobByValue(
|
||
|
HKEY hKey,
|
||
|
LPWSTR wszProperty,
|
||
|
PBYTE pBuffer,
|
||
|
ULONG cbBuffer)
|
||
|
{
|
||
|
DWORD dwErr;
|
||
|
DWORD dwUnused;
|
||
|
DWORD unused;
|
||
|
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
|
||
|
&unused, // max size of value data,
|
||
|
NULL, // security descriptor
|
||
|
NULL); // Last write time
|
||
|
|
||
|
if (dwErr == ERROR_SUCCESS) {
|
||
|
dwErr = RegSetValueEx(
|
||
|
hKey,
|
||
|
wszProperty,
|
||
|
NULL,
|
||
|
REG_BINARY,
|
||
|
pBuffer,
|
||
|
cbBuffer);
|
||
|
|
||
|
} else {
|
||
|
dwErr = ERROR_OUTOFMEMORY;
|
||
|
}
|
||
|
|
||
|
return( dwErr );
|
||
|
|
||
|
}
|
||
|
|
||
|
DWORD
|
||
|
GetSvcProps(
|
||
|
HKEY hKey,
|
||
|
PDFS_VOLUME pVol)
|
||
|
{
|
||
|
DWORD cbBuffer;
|
||
|
DWORD dwErr;
|
||
|
PBYTE Buffer = NULL;
|
||
|
PBYTE pBuf = NULL;
|
||
|
|
||
|
if (fSwDebug == TRUE)
|
||
|
MyPrintf(L"GetSvcProps(%ws)\r\n", pVol->wszObjectName);
|
||
|
|
||
|
dwErr = GetBlobByValue(
|
||
|
hKey,
|
||
|
SVC_PROPS,
|
||
|
&Buffer,
|
||
|
&cbBuffer);
|
||
|
|
||
|
if (dwErr != ERROR_SUCCESS)
|
||
|
goto Cleanup;
|
||
|
|
||
|
pBuf = Buffer;
|
||
|
dwErr = UnSerializeReplicaList(
|
||
|
&pVol->ReplCount,
|
||
|
&pVol->AllocatedReplCount,
|
||
|
&pVol->ReplicaInfo,
|
||
|
&pVol->FtModification,
|
||
|
&pBuf);
|
||
|
|
||
|
if (dwErr != ERROR_SUCCESS)
|
||
|
goto Cleanup;
|
||
|
|
||
|
//
|
||
|
// Get deleted replicas
|
||
|
//
|
||
|
|
||
|
if (pBuf < (pBuf + cbBuffer)) {
|
||
|
dwErr = UnSerializeReplicaList(
|
||
|
&pVol->DelReplCount,
|
||
|
&pVol->AllocatedDelReplCount,
|
||
|
&pVol->DelReplicaInfo,
|
||
|
&pVol->DelFtModification,
|
||
|
&pBuf);
|
||
|
}
|
||
|
|
||
|
Cleanup:
|
||
|
|
||
|
if (Buffer != NULL)
|
||
|
delete [] Buffer;
|
||
|
|
||
|
if (fSwDebug == TRUE)
|
||
|
MyPrintf(L"GetSvcProps exit %d\n", dwErr);
|
||
|
|
||
|
return dwErr;
|
||
|
}
|
||
|
|
||
|
//+----------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: GetVersionProps
|
||
|
//
|
||
|
// Synopsis: Retrieves the version property set of a Dfs Manager volume
|
||
|
// object.
|
||
|
//
|
||
|
// Returns: [S_OK] -- If successful.
|
||
|
//
|
||
|
// DWORD from DfsmQueryValue
|
||
|
//
|
||
|
//-----------------------------------------------------------------------------
|
||
|
|
||
|
DWORD
|
||
|
GetVersionProps(
|
||
|
HKEY hKey,
|
||
|
LPWSTR wszProperty,
|
||
|
PULONG pVersion)
|
||
|
{
|
||
|
DWORD dwErr;
|
||
|
DWORD cbSize;
|
||
|
|
||
|
cbSize = sizeof(ULONG);
|
||
|
|
||
|
dwErr = DfsmQueryValue(
|
||
|
hKey,
|
||
|
wszProperty,
|
||
|
REG_DWORD,
|
||
|
sizeof(DWORD),
|
||
|
(LPBYTE) pVersion,
|
||
|
&cbSize);
|
||
|
|
||
|
return dwErr;
|
||
|
}
|
||
|
|
||
|
//+----------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: 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
|
||
|
GetRecoveryProps(
|
||
|
HKEY hKey,
|
||
|
LPWSTR wszProperty,
|
||
|
PULONG pcbRecovery,
|
||
|
PBYTE *ppRecovery)
|
||
|
{
|
||
|
DWORD dwErr;
|
||
|
|
||
|
dwErr = GetBlobByValue(
|
||
|
hKey,
|
||
|
wszProperty,
|
||
|
ppRecovery,
|
||
|
pcbRecovery);
|
||
|
|
||
|
return dwErr;
|
||
|
}
|
||
|
|
||
|
DWORD
|
||
|
EnumKeys(
|
||
|
HKEY hKey,
|
||
|
PULONG pcKeys,
|
||
|
LPWSTR **ppNames)
|
||
|
{
|
||
|
// figure out how many keys are currently stored in this key
|
||
|
// and allocate a buffer to hold the return results.
|
||
|
|
||
|
LPWSTR *pNames = NULL;
|
||
|
WCHAR wszClass[MAX_PATH+1];
|
||
|
ULONG cbClass = sizeof(wszClass);
|
||
|
ULONG cSubKeys, cbMaxSubKeyLen, cbMaxClassLen;
|
||
|
ULONG cValues, cbMaxValueIDLen, cbMaxValueLen;
|
||
|
SECURITY_DESCRIPTOR SecDescriptor;
|
||
|
FILETIME ft;
|
||
|
DWORD dwErr = ERROR_SUCCESS;
|
||
|
DWORD dwIndex=0;
|
||
|
|
||
|
dwErr = RegQueryInfoKey(
|
||
|
hKey,
|
||
|
wszClass,
|
||
|
&cbClass,
|
||
|
NULL,
|
||
|
&cSubKeys,
|
||
|
&cbMaxSubKeyLen,
|
||
|
&cbMaxClassLen,
|
||
|
&cValues,
|
||
|
&cbMaxValueIDLen,
|
||
|
&cbMaxValueLen,
|
||
|
(DWORD *)&SecDescriptor,
|
||
|
&ft);
|
||
|
|
||
|
if (dwErr != ERROR_SUCCESS)
|
||
|
goto Cleanup;
|
||
|
|
||
|
pNames = new LPWSTR [cSubKeys];
|
||
|
|
||
|
if (pNames == NULL) {
|
||
|
dwErr = ERROR_OUTOFMEMORY;
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
RtlZeroMemory(pNames, cSubKeys * sizeof(LPWSTR));
|
||
|
|
||
|
// loop enumerating and adding names
|
||
|
|
||
|
for (dwIndex = 0; dwIndex < cSubKeys && dwErr == ERROR_SUCCESS; dwIndex++) {
|
||
|
|
||
|
WCHAR wszKeyName[MAX_PATH];
|
||
|
ULONG cbKeyName = sizeof(wszKeyName)/sizeof(WCHAR);
|
||
|
WCHAR wszClass[MAX_PATH];
|
||
|
ULONG cbClass = sizeof(wszClass)/sizeof(WCHAR);
|
||
|
FILETIME ft;
|
||
|
|
||
|
dwErr = RegEnumKeyEx(
|
||
|
hKey, // handle
|
||
|
dwIndex, // index
|
||
|
wszKeyName, // key name
|
||
|
&cbKeyName, // length of key name
|
||
|
NULL, // title index
|
||
|
wszClass, // class
|
||
|
&cbClass, // length of class
|
||
|
&ft); // last write time
|
||
|
|
||
|
if (dwErr == ERROR_SUCCESS) {
|
||
|
|
||
|
GIP_DUPLICATE_STRING(
|
||
|
dwErr,
|
||
|
wszKeyName,
|
||
|
&pNames[dwIndex]);
|
||
|
|
||
|
}
|
||
|
|
||
|
};
|
||
|
|
||
|
|
||
|
// finished the enumeration, check the results
|
||
|
if (dwErr == ERROR_NO_MORE_ITEMS || dwErr == ERROR_SUCCESS) {
|
||
|
*pcKeys = dwIndex;
|
||
|
*ppNames = pNames;
|
||
|
} else {
|
||
|
// Cleanup and return an error
|
||
|
while (dwIndex) {
|
||
|
delete pNames[--dwIndex];
|
||
|
}
|
||
|
delete [] pNames;
|
||
|
}
|
||
|
|
||
|
Cleanup:
|
||
|
|
||
|
return(dwErr);
|
||
|
}
|
||
|
|
||
|
DWORD
|
||
|
GetSiteTable(
|
||
|
HKEY hKey,
|
||
|
PDFS_VOLUME_LIST pDfsVolList)
|
||
|
{
|
||
|
DWORD dwErr = ERROR_SUCCESS;
|
||
|
NTSTATUS NtStatus;
|
||
|
ULONG cSite;
|
||
|
PDFSM_SITE_ENTRY pSiteEntry;
|
||
|
PDFSM_SITE_ENTRY pTmpSiteEntry;
|
||
|
MARSHAL_BUFFER marshalBuffer;
|
||
|
ULONG Size;
|
||
|
PLIST_ENTRY pListHead;
|
||
|
PLIST_ENTRY pLink;
|
||
|
PBYTE pObjectData = NULL;
|
||
|
ULONG cbObjectData;
|
||
|
PBYTE pBuffer = NULL;
|
||
|
ULONG cbBuffer;
|
||
|
ULONG i;
|
||
|
|
||
|
if (fSwDebug == TRUE)
|
||
|
MyPrintf(L"GetSiteTable()\r\n");
|
||
|
|
||
|
dwErr = GetBlobByValue(
|
||
|
hKey,
|
||
|
L"SiteTable",
|
||
|
&pObjectData,
|
||
|
&cbObjectData);
|
||
|
|
||
|
if (dwErr != ERROR_SUCCESS)
|
||
|
goto Cleanup;
|
||
|
|
||
|
//
|
||
|
// Unserialize the buffer
|
||
|
//
|
||
|
|
||
|
InitializeListHead(&pDfsVolList->SiteList);
|
||
|
|
||
|
MarshalBufferInitialize(
|
||
|
&marshalBuffer,
|
||
|
cbObjectData,
|
||
|
pObjectData);
|
||
|
|
||
|
NtStatus = DfsRtlGetGuid(&marshalBuffer, &pDfsVolList->SiteGuid);
|
||
|
|
||
|
if (!NT_SUCCESS(NtStatus)) {
|
||
|
dwErr = RtlNtStatusToDosError(NtStatus);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
NtStatus = DfsRtlGetUlong(&marshalBuffer, &pDfsVolList->SiteCount);
|
||
|
|
||
|
if (!NT_SUCCESS(NtStatus)) {
|
||
|
dwErr = RtlNtStatusToDosError(NtStatus);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
pBuffer = (BYTE *)malloc(cbObjectData);
|
||
|
|
||
|
if (pBuffer == NULL) {
|
||
|
dwErr = ERROR_OUTOFMEMORY;
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
pTmpSiteEntry = (PDFSM_SITE_ENTRY)pBuffer;
|
||
|
|
||
|
for (cSite = 0; cSite < pDfsVolList->SiteCount; cSite++) {
|
||
|
|
||
|
RtlZeroMemory(pBuffer, cbObjectData);
|
||
|
|
||
|
NtStatus = DfsRtlGet(
|
||
|
&marshalBuffer,
|
||
|
&MiDfsmSiteEntry,
|
||
|
pBuffer);
|
||
|
|
||
|
if (!NT_SUCCESS(NtStatus)) {
|
||
|
dwErr = RtlNtStatusToDosError(NtStatus);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
Size = sizeof(DFSM_SITE_ENTRY) + (pTmpSiteEntry->Info.cSites * sizeof(DFS_SITENAME_INFO));
|
||
|
|
||
|
pSiteEntry = (PDFSM_SITE_ENTRY) malloc(Size);
|
||
|
|
||
|
if (pSiteEntry == NULL) {
|
||
|
dwErr = ERROR_OUTOFMEMORY;
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
RtlCopyMemory(pSiteEntry, pBuffer, Size);
|
||
|
InsertHeadList(&pDfsVolList->SiteList, &pSiteEntry->Link);
|
||
|
|
||
|
}
|
||
|
|
||
|
Cleanup:
|
||
|
|
||
|
if (pBuffer != NULL)
|
||
|
delete [] pBuffer;
|
||
|
|
||
|
return dwErr;
|
||
|
}
|
||
|
|
||
|
//+------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: DfsCheckVolList
|
||
|
//
|
||
|
// Synopsis: Prints the volume information represented by the volume
|
||
|
// list passed in.
|
||
|
//
|
||
|
// Returns: [ERROR_SUCCESS] -- If all went well.
|
||
|
//
|
||
|
// History: 11/19/98 JHarper Created
|
||
|
//
|
||
|
//-------------------------------------------------------------------------
|
||
|
|
||
|
VOID
|
||
|
DfsCheckVolList(
|
||
|
PDFS_VOLUME_LIST pDfsVolList,
|
||
|
ULONG Level)
|
||
|
{
|
||
|
ULONG cVol;
|
||
|
ULONG cRepl;
|
||
|
ULONG cExit;
|
||
|
PLIST_ENTRY pListHead;
|
||
|
PLIST_ENTRY pLink;
|
||
|
PDFSM_SITE_ENTRY pSiteEntry;
|
||
|
PDFS_ROOTLOCALVOL pRootLocalVol = pDfsVolList->pRootLocalVol;
|
||
|
BOOLEAN SvcOk = FALSE;
|
||
|
BOOLEAN IdOk = FALSE;
|
||
|
BOOLEAN VerOk = FALSE;
|
||
|
BOOLEAN RecOk = FALSE;
|
||
|
BOOLEAN Ok1 = FALSE;
|
||
|
BOOLEAN Ok2 = FALSE;
|
||
|
|
||
|
MyPrintf(L"(metadata)..\r\n");
|
||
|
|
||
|
for (cVol = 0; cVol < pDfsVolList->VolCount; cVol++) {
|
||
|
|
||
|
IdOk = SvcOk = VerOk = RecOk = TRUE;
|
||
|
|
||
|
if (
|
||
|
pDfsVolList->Volumes[cVol]->wszPrefix == NULL
|
||
|
||
|
||
|
pDfsVolList->Volumes[cVol]->wszShortPrefix == NULL
|
||
|
||
|
||
|
pDfsVolList->Volumes[cVol]->dwTimeout <= 0
|
||
|
||
|
||
|
pDfsVolList->Volumes[cVol]->dwState == 0
|
||
|
) {
|
||
|
IdOk = FALSE;
|
||
|
}
|
||
|
|
||
|
if (pDfsVolList->Volumes[cVol]->ReplCount == 0)
|
||
|
SvcOk = FALSE;
|
||
|
|
||
|
if (pDfsVolList->Volumes[cVol]->dwVersion == 0)
|
||
|
VerOk = FALSE;
|
||
|
|
||
|
for (cRepl = 0; cRepl < pDfsVolList->Volumes[cVol]->ReplCount; cRepl++) {
|
||
|
|
||
|
if (
|
||
|
pDfsVolList->Volumes[cVol]->ReplicaInfo[cRepl].pwszServerName == NULL
|
||
|
||
|
||
|
pDfsVolList->Volumes[cVol]->ReplicaInfo[cRepl].pwszShareName == NULL
|
||
|
) {
|
||
|
SvcOk = FALSE;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
for (cRepl = 0; cRepl < pDfsVolList->Volumes[cVol]->DelReplCount; cRepl++) {
|
||
|
|
||
|
if (
|
||
|
pDfsVolList->Volumes[cVol]->DelReplicaInfo[cRepl].pwszServerName == NULL
|
||
|
||
|
||
|
pDfsVolList->Volumes[cVol]->DelReplicaInfo[cRepl].pwszShareName == NULL
|
||
|
) {
|
||
|
SvcOk = FALSE;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
if (IdOk != TRUE || SvcOk != TRUE) {
|
||
|
MyPrintf(L"%ws: Bad or Missing values: %ws %ws %ws %ws\r\n",
|
||
|
pDfsVolList->Volumes[cVol]->wszObjectName,
|
||
|
IdOk == TRUE ? L"" : L"ID",
|
||
|
SvcOk == TRUE ? L"" : L"Svc",
|
||
|
VerOk == TRUE ? L"" : L"Version",
|
||
|
RecOk == TRUE ? L"" : L"Recovery");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (Level > 0) {
|
||
|
//
|
||
|
// Verify that all the vols have exit points
|
||
|
//
|
||
|
|
||
|
MyPrintf(L"(volumes have exit points)..\r\n");
|
||
|
|
||
|
Ok1 = Ok2 = FALSE;
|
||
|
|
||
|
for (cVol = 1; cVol < pDfsVolList->VolCount; cVol++) {
|
||
|
Ok1 = FALSE;
|
||
|
if (fSwDebug == TRUE) {
|
||
|
MyPrintf(L"++++ [%ws]\r\n", pDfsVolList->Volumes[cVol]->wszObjectName);
|
||
|
MyPrintf(L" %d ExitPts:", pRootLocalVol[0].cLocalVolCount);
|
||
|
}
|
||
|
for (cExit = 0; cExit < pRootLocalVol[0].cLocalVolCount; cExit++) {
|
||
|
if (fSwDebug == TRUE)
|
||
|
MyPrintf(L"%d ", cExit);
|
||
|
if (
|
||
|
(pDfsVolList->Volumes[cVol]->wszObjectName != NULL &&
|
||
|
pRootLocalVol[0].pDfsLocalVol[cExit].wszObjectName != NULL)
|
||
|
&&
|
||
|
(pDfsVolList->Volumes[cVol]->wszObjectName[12] ==
|
||
|
pRootLocalVol[0].pDfsLocalVol[cExit].wszObjectName[0])
|
||
|
&&
|
||
|
wcscmp(
|
||
|
&pDfsVolList->Volumes[cVol]->wszObjectName[12],
|
||
|
pRootLocalVol[0].pDfsLocalVol[cExit].wszObjectName) == 0
|
||
|
) {
|
||
|
Ok1 = TRUE;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
if (fSwDebug == TRUE)
|
||
|
MyPrintf(L"\r\n", cExit);
|
||
|
|
||
|
if (Ok1 != TRUE && wcslen(&pDfsVolList->Volumes[cVol]->wszObjectName[12]) > 0) {
|
||
|
MyPrintf(L"Missing [%ws] in LocalVolumes\r\n",
|
||
|
&pDfsVolList->Volumes[cVol]->wszObjectName[12]);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Verify that all the exit points have vols
|
||
|
//
|
||
|
|
||
|
MyPrintf(L"(exit points have volumes)..\r\n");
|
||
|
|
||
|
Ok1 = Ok2 = FALSE;
|
||
|
|
||
|
for (cExit = 0; cExit < pRootLocalVol[0].cLocalVolCount; cExit++) {
|
||
|
Ok1 = FALSE;
|
||
|
if (fSwDebug == TRUE) {
|
||
|
MyPrintf(L"---- [%ws]\r\n", pRootLocalVol[0].pDfsLocalVol[cExit].wszObjectName);
|
||
|
MyPrintf(L" %d Vols:", pDfsVolList->VolCount);
|
||
|
}
|
||
|
for (cVol = 1; cVol < pDfsVolList->VolCount; cVol++) {
|
||
|
if (fSwDebug == TRUE)
|
||
|
MyPrintf(L"%d ", cVol);
|
||
|
if (
|
||
|
(pDfsVolList->Volumes[cVol]->wszObjectName != NULL &&
|
||
|
pRootLocalVol[0].pDfsLocalVol[cExit].wszObjectName != NULL)
|
||
|
&&
|
||
|
(pDfsVolList->Volumes[cVol]->wszObjectName[12] ==
|
||
|
pRootLocalVol[0].pDfsLocalVol[cExit].wszObjectName[0])
|
||
|
&&
|
||
|
wcscmp(
|
||
|
&pDfsVolList->Volumes[cVol]->wszObjectName[12],
|
||
|
pRootLocalVol[0].pDfsLocalVol[cExit].wszObjectName) == 0
|
||
|
) {
|
||
|
Ok1 = TRUE;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
if (fSwDebug == TRUE)
|
||
|
MyPrintf(L"\r\n", cVol);
|
||
|
|
||
|
if (Ok1 != TRUE) {
|
||
|
MyPrintf(L"Extra ExitPt [%ws] in LocalVolumes\r\n",
|
||
|
pRootLocalVol[0].pDfsLocalVol[cExit].wszObjectName);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
MyPrintf(L"(exit point internal consistency)...\r\n");
|
||
|
|
||
|
Ok1 = Ok2 = FALSE;
|
||
|
|
||
|
for (cVol = 0; cVol < pDfsVolList->VolCount; cVol++) {
|
||
|
Ok1 = FALSE;
|
||
|
for (cExit = 0; cExit < pRootLocalVol[0].cLocalVolCount; cExit++) {
|
||
|
if (
|
||
|
(pDfsVolList->Volumes[cVol]->wszObjectName != NULL &&
|
||
|
pRootLocalVol[0].pDfsLocalVol[cExit].wszObjectName != NULL)
|
||
|
&&
|
||
|
(pDfsVolList->Volumes[cVol]->wszObjectName[12] ==
|
||
|
pRootLocalVol[0].pDfsLocalVol[cExit].wszObjectName[0])
|
||
|
&&
|
||
|
wcscmp(
|
||
|
&pDfsVolList->Volumes[cVol]->wszObjectName[12],
|
||
|
pRootLocalVol[0].pDfsLocalVol[cExit].wszObjectName) == 0
|
||
|
) {
|
||
|
Ok1 = TRUE;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (Ok1 == TRUE && wcslen(&pDfsVolList->Volumes[cVol]->wszObjectName[12]) > 0) {
|
||
|
PWCHAR wCp1 = &pDfsVolList->Volumes[cVol]->wszPrefix[1];
|
||
|
PWCHAR wCp2 = &pRootLocalVol[0].pDfsLocalVol[cExit].wszEntryPath[1];
|
||
|
while (*wCp1 != L'\\')
|
||
|
wCp1++;
|
||
|
while (*wCp2 != L'\\')
|
||
|
wCp2++;
|
||
|
if (_wcsicmp(wCp1,wCp2) != 0) {
|
||
|
MyPrintf(L"Mismatch in ExitPt in [%ws]\r\n",
|
||
|
pRootLocalVol[0].pDfsLocalVol[cExit].wszObjectName);
|
||
|
MyPrintf(L" [%ws] vs [%ws]\r\n",
|
||
|
pDfsVolList->Volumes[cVol]->wszPrefix,
|
||
|
pRootLocalVol[0].pDfsLocalVol[cExit].wszEntryPath);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
DWORD
|
||
|
GetExitPtInfo(
|
||
|
HKEY rKey,
|
||
|
PDFS_ROOTLOCALVOL *ppRootLocalVol,
|
||
|
PULONG pcVolCount)
|
||
|
{
|
||
|
HKEY hKey = NULL;
|
||
|
HKEY hKeyExPt = NULL;
|
||
|
LPWSTR *pNames = NULL;
|
||
|
ULONG dwErr;
|
||
|
ULONG cKeys;
|
||
|
ULONG i;
|
||
|
PDFS_ROOTLOCALVOL pRootLocalVol;
|
||
|
DWORD cbBuffer;
|
||
|
DWORD cbSize;
|
||
|
DWORD dwType;
|
||
|
WCHAR wszBuffer[MAX_PATH+1];
|
||
|
|
||
|
if (fSwDebug == TRUE)
|
||
|
MyPrintf(L"GetExitPtInfo()\r\n");
|
||
|
|
||
|
dwErr = RegOpenKey(
|
||
|
rKey,
|
||
|
REG_KEY_LOCAL_VOLUMES,
|
||
|
&hKey);
|
||
|
|
||
|
if (dwErr != ERROR_SUCCESS)
|
||
|
goto Cleanup;
|
||
|
|
||
|
dwErr = EnumKeys(
|
||
|
hKey,
|
||
|
&cKeys,
|
||
|
&pNames);
|
||
|
|
||
|
if (dwErr != ERROR_SUCCESS)
|
||
|
goto Cleanup;
|
||
|
|
||
|
pRootLocalVol = (PDFS_ROOTLOCALVOL)malloc(sizeof(DFS_ROOTLOCALVOL) * cKeys);
|
||
|
|
||
|
if (pRootLocalVol == NULL) {
|
||
|
dwErr = ERROR_OUTOFMEMORY;
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
RtlZeroMemory(pRootLocalVol, sizeof(DFS_ROOTLOCALVOL) * cKeys);
|
||
|
|
||
|
for (i = 0; i < cKeys; i++) {
|
||
|
|
||
|
if (fSwDebug == TRUE)
|
||
|
MyPrintf(L"RegOpenKey(%ws)\r\n", pNames[i]);
|
||
|
|
||
|
dwErr = RegOpenKey(
|
||
|
hKey,
|
||
|
pNames[i],
|
||
|
&hKeyExPt);
|
||
|
|
||
|
if (dwErr != ERROR_SUCCESS)
|
||
|
continue;
|
||
|
|
||
|
GIP_DUPLICATE_STRING(dwErr, pNames[i], &pRootLocalVol[i].wszObjectName);
|
||
|
|
||
|
cbSize = sizeof(ULONG);
|
||
|
|
||
|
dwErr = DfsmQueryValue(
|
||
|
hKeyExPt,
|
||
|
REG_VALUE_ENTRY_TYPE,
|
||
|
REG_DWORD,
|
||
|
sizeof(DWORD),
|
||
|
(LPBYTE) &pRootLocalVol[i].dwEntryType,
|
||
|
&cbSize);
|
||
|
|
||
|
cbBuffer = sizeof(wszBuffer);
|
||
|
dwErr = RegQueryValueEx(
|
||
|
hKeyExPt,
|
||
|
REG_VALUE_ENTRY_PATH, // "EntryPath"
|
||
|
NULL,
|
||
|
&dwType,
|
||
|
(LPBYTE) wszBuffer,
|
||
|
&cbBuffer);
|
||
|
|
||
|
if (dwErr == ERROR_MORE_DATA)
|
||
|
dwErr = ERROR_SUCCESS;
|
||
|
|
||
|
if (dwErr == ERROR_SUCCESS)
|
||
|
GIP_DUPLICATE_STRING(dwErr, wszBuffer, &pRootLocalVol[i].wszEntryPath);
|
||
|
|
||
|
cbBuffer = sizeof(wszBuffer);
|
||
|
dwErr = RegQueryValueEx(
|
||
|
hKeyExPt,
|
||
|
REG_VALUE_SHARE_NAME, // "ShareName"
|
||
|
NULL,
|
||
|
&dwType,
|
||
|
(LPBYTE) wszBuffer,
|
||
|
&cbBuffer);
|
||
|
|
||
|
if (dwErr == ERROR_MORE_DATA)
|
||
|
dwErr = ERROR_SUCCESS;
|
||
|
|
||
|
if (dwErr == ERROR_SUCCESS)
|
||
|
GIP_DUPLICATE_STRING(dwErr, wszBuffer, &pRootLocalVol[i].wszShareName);
|
||
|
|
||
|
cbBuffer = sizeof(wszBuffer);
|
||
|
dwErr = RegQueryValueEx(
|
||
|
hKeyExPt,
|
||
|
REG_VALUE_SHORT_PATH, // "ShortEntryPath"
|
||
|
NULL,
|
||
|
&dwType,
|
||
|
(LPBYTE) wszBuffer,
|
||
|
&cbBuffer);
|
||
|
|
||
|
if (dwErr == ERROR_SUCCESS)
|
||
|
GIP_DUPLICATE_STRING(dwErr, wszBuffer, &pRootLocalVol[i].wszShortEntryPath);
|
||
|
|
||
|
cbBuffer = sizeof(wszBuffer);
|
||
|
dwErr = RegQueryValueEx(
|
||
|
hKeyExPt,
|
||
|
REG_VALUE_STORAGE_ID, // "StorageId"
|
||
|
NULL,
|
||
|
&dwType,
|
||
|
(LPBYTE) wszBuffer,
|
||
|
&cbBuffer);
|
||
|
|
||
|
if (dwErr == ERROR_MORE_DATA)
|
||
|
dwErr = ERROR_SUCCESS;
|
||
|
|
||
|
if (dwErr == ERROR_SUCCESS)
|
||
|
GIP_DUPLICATE_STRING(dwErr, wszBuffer, &pRootLocalVol[i].wszStorageId);
|
||
|
|
||
|
dwErr = GetExitPts(
|
||
|
hKeyExPt,
|
||
|
&pRootLocalVol[i]);
|
||
|
|
||
|
RegCloseKey(hKeyExPt);
|
||
|
}
|
||
|
|
||
|
FreeNameList(
|
||
|
pNames,
|
||
|
cKeys);
|
||
|
|
||
|
pNames = NULL;
|
||
|
|
||
|
*ppRootLocalVol = pRootLocalVol;
|
||
|
*pcVolCount = cKeys;
|
||
|
|
||
|
Cleanup:
|
||
|
|
||
|
FreeNameList(
|
||
|
pNames,
|
||
|
cKeys);
|
||
|
|
||
|
if (hKey != NULL)
|
||
|
RegCloseKey(hKey);
|
||
|
|
||
|
if (fSwDebug == TRUE)
|
||
|
MyPrintf(L"GetExitPtInfo returning %d\r\n", dwErr);
|
||
|
|
||
|
return dwErr;
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
FreeNameList(
|
||
|
LPWSTR *pNames,
|
||
|
ULONG cNames)
|
||
|
{
|
||
|
ULONG i;
|
||
|
|
||
|
if (pNames != NULL) {
|
||
|
for (i = 0; i < cNames; i++) {
|
||
|
if (pNames[i] != NULL)
|
||
|
delete [] pNames[i];
|
||
|
}
|
||
|
delete [] pNames;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
DWORD
|
||
|
GetExitPts(
|
||
|
HKEY hKey,
|
||
|
PDFS_ROOTLOCALVOL pRootLocalVol)
|
||
|
{
|
||
|
ULONG cNames = 0;
|
||
|
LPWSTR *pNames = NULL;
|
||
|
ULONG cKeys = 0;
|
||
|
ULONG dwErr = ERROR_SUCCESS;
|
||
|
ULONG i;
|
||
|
DWORD dwType = 0;
|
||
|
DWORD cbBuffer = 0;
|
||
|
DWORD cbSize = 0;
|
||
|
HKEY hKeyExPt = NULL;
|
||
|
WCHAR wszBuffer[MAX_PATH+1];
|
||
|
|
||
|
dwErr = EnumKeys(
|
||
|
hKey,
|
||
|
&cKeys,
|
||
|
&pNames);
|
||
|
|
||
|
if (dwErr != ERROR_SUCCESS)
|
||
|
goto Cleanup;
|
||
|
|
||
|
pRootLocalVol->pDfsLocalVol = (PDFS_LOCALVOLUME)malloc(sizeof(DFS_LOCALVOLUME) * cKeys);
|
||
|
|
||
|
if (pRootLocalVol->pDfsLocalVol == NULL) {
|
||
|
dwErr = ERROR_OUTOFMEMORY;
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
RtlZeroMemory(pRootLocalVol->pDfsLocalVol, sizeof(DFS_LOCALVOLUME) * cKeys);
|
||
|
pRootLocalVol->cLocalVolCount = cKeys;
|
||
|
|
||
|
for (i = 0; i < cKeys; i++) {
|
||
|
|
||
|
if (fSwDebug == TRUE)
|
||
|
MyPrintf(L" GetExitPts(%ws)\r\n", pNames[i]);
|
||
|
|
||
|
//
|
||
|
// Get EntryPath
|
||
|
//
|
||
|
dwErr = RegOpenKey(
|
||
|
hKey,
|
||
|
pNames[i],
|
||
|
&hKeyExPt);
|
||
|
|
||
|
if (dwErr != ERROR_SUCCESS) {
|
||
|
if (fSwDebug == TRUE)
|
||
|
MyPrintf(L"RegOpenKey returned %d\r\n", dwErr);
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
GIP_DUPLICATE_STRING(dwErr, pNames[i], &pRootLocalVol->pDfsLocalVol[i].wszObjectName);
|
||
|
|
||
|
cbBuffer = sizeof(wszBuffer);
|
||
|
dwErr = RegQueryValueEx(
|
||
|
hKeyExPt,
|
||
|
REG_VALUE_ENTRY_PATH, // "EntryPath"
|
||
|
NULL,
|
||
|
&dwType,
|
||
|
(LPBYTE) wszBuffer,
|
||
|
&cbBuffer);
|
||
|
|
||
|
if (dwErr == ERROR_MORE_DATA)
|
||
|
dwErr = ERROR_SUCCESS;
|
||
|
|
||
|
if (dwErr != ERROR_SUCCESS && fSwDebug == TRUE)
|
||
|
MyPrintf(L"RegQueryValueEx returned %d\r\n", dwErr);
|
||
|
|
||
|
if (dwErr == ERROR_SUCCESS)
|
||
|
GIP_DUPLICATE_STRING(dwErr, wszBuffer, &pRootLocalVol->pDfsLocalVol[i].wszEntryPath);
|
||
|
|
||
|
RegCloseKey(hKeyExPt);
|
||
|
}
|
||
|
|
||
|
Cleanup:
|
||
|
|
||
|
FreeNameList(
|
||
|
pNames,
|
||
|
cKeys);
|
||
|
|
||
|
return dwErr;
|
||
|
}
|
||
|
|
||
|
DWORD
|
||
|
DfsSetOnSite(
|
||
|
HKEY rKey,
|
||
|
LPWSTR wszKeyName,
|
||
|
ULONG set)
|
||
|
{
|
||
|
HKEY hKey = NULL;
|
||
|
DWORD dwErr;
|
||
|
LPWSTR *pNames = NULL;
|
||
|
ULONG cKeys = 0;
|
||
|
ULONG i;
|
||
|
WCHAR VolumesDir[MAX_PATH+1];
|
||
|
|
||
|
wcscpy(VolumesDir, VOLUMES_DIR);
|
||
|
wcscat(VolumesDir, L"domainroot");
|
||
|
|
||
|
dwErr = RegOpenKey(
|
||
|
rKey,
|
||
|
VolumesDir,
|
||
|
&hKey);
|
||
|
|
||
|
if (dwErr != ERROR_SUCCESS) {
|
||
|
MyPrintf(L"Not a StdDfs root!\r\n");
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
dwErr = EnumKeys(
|
||
|
hKey,
|
||
|
&cKeys,
|
||
|
&pNames);
|
||
|
|
||
|
if (dwErr != ERROR_SUCCESS) {
|
||
|
MyPrintf(L"No exit points...\r\n");
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
dwErr = SetSiteInfoOnKey(
|
||
|
rKey,
|
||
|
L"domainroot",
|
||
|
wszKeyName,
|
||
|
set);
|
||
|
|
||
|
for (i = 0; i < cKeys && dwErr != ERROR_SUCCESS && dwErr != ERROR_REQUEST_ABORTED && dwErr != ERROR_PATH_NOT_FOUND; i++) {
|
||
|
wcscpy(VolumesDir, L"domainroot\\");
|
||
|
wcscat(VolumesDir, pNames[i]);
|
||
|
dwErr = SetSiteInfoOnKey(
|
||
|
rKey,
|
||
|
VolumesDir, wszKeyName, set);
|
||
|
}
|
||
|
|
||
|
if (dwErr == ERROR_PATH_NOT_FOUND)
|
||
|
ErrorMessage(MSG_LINK_NOT_FOUND, wszKeyName);
|
||
|
|
||
|
Cleanup:
|
||
|
|
||
|
if (pNames != NULL)
|
||
|
FreeNameList(
|
||
|
pNames,
|
||
|
cKeys);
|
||
|
|
||
|
if (hKey != NULL)
|
||
|
RegCloseKey(hKey);
|
||
|
|
||
|
return dwErr;
|
||
|
}
|
||
|
|
||
|
DWORD
|
||
|
SetSiteInfoOnKey(
|
||
|
HKEY rKey,
|
||
|
LPWSTR wszKeyName,
|
||
|
LPWSTR wszPrefixMatch,
|
||
|
ULONG Set)
|
||
|
{
|
||
|
DWORD dwErr = 0;
|
||
|
HKEY hKey = NULL;
|
||
|
ULONG cRepl;
|
||
|
WCHAR VolumesDir[MAX_PATH+1];
|
||
|
DFS_VOLUME Volume;
|
||
|
PDFS_VOLUME pVolume = &Volume;
|
||
|
wcscpy(VolumesDir, VOLUMES_DIR);
|
||
|
wcscat(VolumesDir, wszKeyName);
|
||
|
LPWSTR usePrefix;
|
||
|
|
||
|
if (fSwDebug == TRUE)
|
||
|
MyPrintf(L"SetSiteInfoOnKey(%ws)\r\n", VolumesDir);
|
||
|
|
||
|
dwErr = RegOpenKey(
|
||
|
rKey,
|
||
|
VolumesDir,
|
||
|
&hKey);
|
||
|
|
||
|
if (dwErr != ERROR_SUCCESS) {
|
||
|
if (fSwDebug == TRUE)
|
||
|
MyPrintf(L"RegOpenKey(%ws) returned %d\r\n", VolumesDir, dwErr);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Id (Prefix, Type, state, etc)
|
||
|
//
|
||
|
|
||
|
dwErr = GetIdProps(
|
||
|
hKey,
|
||
|
&pVolume->dwType,
|
||
|
&pVolume->dwState,
|
||
|
&pVolume->wszPrefix,
|
||
|
&pVolume->wszShortPrefix,
|
||
|
&pVolume->idVolume,
|
||
|
&pVolume->wszComment,
|
||
|
&pVolume->dwTimeout,
|
||
|
&pVolume->ftPrefix,
|
||
|
&pVolume->ftState,
|
||
|
&pVolume->ftComment);
|
||
|
|
||
|
if (dwErr != ERROR_SUCCESS) {
|
||
|
if (fSwDebug == TRUE)
|
||
|
MyPrintf(L"GetIdProps() returned %d\r\n", dwErr);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
usePrefix = pVolume->wszPrefix;
|
||
|
|
||
|
DfspGetLinkName(usePrefix, &usePrefix);
|
||
|
|
||
|
if (fSwDebug) {
|
||
|
MyPrintf(L"prefix (%ws, %ws), keyname (%ws)\r\n",
|
||
|
usePrefix,
|
||
|
pVolume->wszShortPrefix,
|
||
|
wszPrefixMatch);
|
||
|
}
|
||
|
|
||
|
if (_wcsicmp(usePrefix, wszPrefixMatch) == 0) {
|
||
|
dwErr = ERROR_SUCCESS;
|
||
|
if (fSwDebug) {
|
||
|
MyPrintf(L"Match found prefix (%ws, %ws), keyname (%ws)\r\n",
|
||
|
usePrefix,
|
||
|
pVolume->wszShortPrefix,
|
||
|
wszPrefixMatch);
|
||
|
}
|
||
|
if (Set) {
|
||
|
if (pVolume->dwType & PKT_ENTRY_TYPE_INSITE_ONLY) {
|
||
|
ErrorMessage(MSG_SITE_INFO_ALREADY_SET,
|
||
|
pVolume->wszPrefix);
|
||
|
dwErr = ERROR_REQUEST_ABORTED;
|
||
|
}
|
||
|
else {
|
||
|
ErrorMessage(MSG_SITE_INFO_NOW_SET,
|
||
|
pVolume->wszPrefix);
|
||
|
pVolume->dwType |= PKT_ENTRY_TYPE_INSITE_ONLY;
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
if (pVolume->dwType & PKT_ENTRY_TYPE_INSITE_ONLY) {
|
||
|
ErrorMessage(MSG_SITE_INFO_NOW_SET,
|
||
|
pVolume->wszPrefix);
|
||
|
pVolume->dwType &= ~PKT_ENTRY_TYPE_INSITE_ONLY;
|
||
|
}
|
||
|
else {
|
||
|
ErrorMessage(MSG_SITE_INFO_ALREADY_SET,
|
||
|
pVolume->wszPrefix);
|
||
|
dwErr = ERROR_REQUEST_ABORTED;
|
||
|
}
|
||
|
}
|
||
|
if (dwErr == ERROR_SUCCESS) {
|
||
|
dwErr = SetIdProps(
|
||
|
hKey,
|
||
|
pVolume->dwType,
|
||
|
pVolume->dwState,
|
||
|
pVolume->wszPrefix,
|
||
|
pVolume->wszShortPrefix,
|
||
|
pVolume->idVolume,
|
||
|
pVolume->wszComment,
|
||
|
pVolume->dwTimeout,
|
||
|
pVolume->ftPrefix,
|
||
|
pVolume->ftState,
|
||
|
pVolume->ftComment);
|
||
|
|
||
|
if (dwErr != ERROR_SUCCESS) {
|
||
|
if (fSwDebug == TRUE)
|
||
|
MyPrintf(L"SetIdProps() returned %d\r\n", dwErr);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
dwErr = ERROR_PATH_NOT_FOUND;
|
||
|
}
|
||
|
|
||
|
Cleanup:
|
||
|
|
||
|
if (hKey != NULL)
|
||
|
RegCloseKey(hKey);
|
||
|
|
||
|
if (fSwDebug == TRUE)
|
||
|
MyPrintf(L"SetSiteInfoOnKey exit %d\r\n", dwErr);
|
||
|
|
||
|
return( dwErr );
|
||
|
|
||
|
}
|
||
|
|
||
|
DWORD
|
||
|
CmdStdUnmap(
|
||
|
LPWSTR pwszServerName)
|
||
|
{
|
||
|
DWORD dwErr = ERROR_SUCCESS;
|
||
|
HKEY rKey = NULL;
|
||
|
HKEY hKey = NULL;
|
||
|
|
||
|
if (fSwDebug != 0)
|
||
|
MyPrintf(L"CmdStdUnmap(%ws)\r\n", pwszServerName);
|
||
|
|
||
|
dwErr = RegConnectRegistry(
|
||
|
pwszServerName,
|
||
|
HKEY_LOCAL_MACHINE,
|
||
|
&rKey);
|
||
|
|
||
|
if (dwErr != ERROR_SUCCESS) {
|
||
|
MyPrintf(L"Can not open registry of %ws (error %d)\r\n", pwszServerName, dwErr);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Remove VOLUMES_DIR and children
|
||
|
//
|
||
|
dwErr = DfsRegDeleteKeyAndChildren(rKey, DFSHOST_DIR);
|
||
|
if (dwErr != ERROR_SUCCESS)
|
||
|
goto Cleanup;
|
||
|
|
||
|
//
|
||
|
// New remove all local vol information
|
||
|
//
|
||
|
dwErr = DfsRegDeleteKeyAndChildren(rKey, REG_KEY_LOCAL_VOLUMES);
|
||
|
if (dwErr != ERROR_SUCCESS)
|
||
|
goto Cleanup;
|
||
|
|
||
|
Cleanup:
|
||
|
|
||
|
RegCreateKey(rKey, REG_KEY_LOCAL_VOLUMES, &hKey);
|
||
|
RegCreateKey(rKey, DFSHOST_DIR, &hKey);
|
||
|
|
||
|
|
||
|
if (rKey != NULL)
|
||
|
RegCloseKey(rKey);
|
||
|
|
||
|
if (hKey != NULL)
|
||
|
RegCloseKey(hKey);
|
||
|
|
||
|
if (fSwDebug != 0)
|
||
|
MyPrintf(L"CmdStdUnmap exit %d\r\n", dwErr);
|
||
|
|
||
|
return dwErr;
|
||
|
}
|
||
|
|
||
|
DWORD
|
||
|
CmdClean(
|
||
|
LPWSTR pwszServerName)
|
||
|
{
|
||
|
DWORD dwErr = ERROR_SUCCESS;
|
||
|
HKEY rKey = NULL;
|
||
|
HKEY hKey = NULL;
|
||
|
|
||
|
if (fSwDebug != 0)
|
||
|
MyPrintf(L"CmdClean(%ws)\r\n", pwszServerName);
|
||
|
|
||
|
dwErr = RegConnectRegistry(
|
||
|
pwszServerName,
|
||
|
HKEY_LOCAL_MACHINE,
|
||
|
&rKey);
|
||
|
|
||
|
if (dwErr != ERROR_SUCCESS) {
|
||
|
MyPrintf(L"Can not open registry of %ws (error %d)\r\n", pwszServerName, dwErr);
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Remove VOLUMES_DIR and children
|
||
|
//
|
||
|
dwErr = DfsRegDeleteKeyAndChildren(rKey, DFSHOST_DIR);
|
||
|
if (dwErr != ERROR_SUCCESS)
|
||
|
goto Cleanup;
|
||
|
|
||
|
//
|
||
|
// New remove all local vol information
|
||
|
//
|
||
|
dwErr = DfsRegDeleteKeyAndChildren(rKey, REG_KEY_LOCAL_VOLUMES);
|
||
|
if (dwErr != ERROR_SUCCESS)
|
||
|
goto Cleanup;
|
||
|
|
||
|
Cleanup:
|
||
|
|
||
|
RegCreateKey(rKey, REG_KEY_LOCAL_VOLUMES, &hKey);
|
||
|
RegCreateKey(rKey, DFSHOST_DIR, &hKey);
|
||
|
|
||
|
|
||
|
if (rKey != NULL)
|
||
|
RegCloseKey(rKey);
|
||
|
|
||
|
if (hKey != NULL)
|
||
|
RegCloseKey(hKey);
|
||
|
|
||
|
if (fSwDebug != 0)
|
||
|
MyPrintf(L"CmdClean exit %d\r\n", dwErr);
|
||
|
|
||
|
return dwErr;
|
||
|
}
|
||
|
|
||
|
DWORD
|
||
|
DfsDeleteChildKeys(
|
||
|
HKEY hKey,
|
||
|
LPWSTR s)
|
||
|
{
|
||
|
WCHAR *wcp, *wcp1;
|
||
|
HKEY nKey;
|
||
|
DWORD dwErr;
|
||
|
DWORD hErr;
|
||
|
|
||
|
if (fSwDebug != 0)
|
||
|
MyPrintf(L"DfsDeleteChildKeys(%ws)\r\n", s);
|
||
|
|
||
|
for (wcp = s; *wcp; wcp++)
|
||
|
;
|
||
|
hErr = dwErr = RegOpenKey(hKey, s, &nKey);
|
||
|
while (RegEnumKey(nKey, 0, wcp, 50 * sizeof(WCHAR)) == ERROR_SUCCESS) {
|
||
|
for (wcp1 = wcp; *wcp1; wcp1++)
|
||
|
;
|
||
|
*wcp1++ = L'\\';
|
||
|
*wcp1 = L'\0';
|
||
|
dwErr = DfsDeleteChildKeys(hKey, s);
|
||
|
if (dwErr == ERROR_SUCCESS) {
|
||
|
dwErr = RegDeleteKey(hKey, s);
|
||
|
}
|
||
|
}
|
||
|
*wcp = L'\0';
|
||
|
if (hErr == ERROR_SUCCESS) {
|
||
|
RegCloseKey(nKey);
|
||
|
}
|
||
|
if (fSwDebug != 0)
|
||
|
MyPrintf(L"DfsDeleteChildKeys exit %d\r\n", dwErr);
|
||
|
return dwErr;
|
||
|
}
|
||
|
|
||
|
DWORD
|
||
|
DfsRegDeleteKeyAndChildren(
|
||
|
HKEY hkey,
|
||
|
LPWSTR s)
|
||
|
{
|
||
|
DWORD dwErr;
|
||
|
LONG l;
|
||
|
LPWSTR wCp;
|
||
|
|
||
|
if (fSwDebug != 0)
|
||
|
MyPrintf(L"DfsRegDeleteKeyAndChildren(%ws)\r\n", s);
|
||
|
|
||
|
wCp = (LPWSTR)malloc(4096);
|
||
|
if (wCp == NULL) {
|
||
|
return ERROR_NOT_ENOUGH_MEMORY;
|
||
|
}
|
||
|
wcscpy(wCp, s);
|
||
|
l = wcslen(s);
|
||
|
if (l > 0 && wCp[l-1] != L'\\') {
|
||
|
wcscat(wCp, L"\\");
|
||
|
}
|
||
|
dwErr = DfsDeleteChildKeys(hkey, wCp);
|
||
|
if (dwErr == ERROR_SUCCESS) {
|
||
|
dwErr = RegDeleteKey(hkey, wCp);
|
||
|
}
|
||
|
free(wCp);
|
||
|
if (fSwDebug != 0)
|
||
|
MyPrintf(L"DfsRegDeleteKeyAndChildren exit %d\r\n", dwErr);
|
||
|
return dwErr;
|
||
|
}
|