windows-nt/Source/XPSP1/NT/base/fs/dfs/ui/dfsutil/stdsup.cxx
2020-09-26 16:20:57 +08:00

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;
}