You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
444 lines
15 KiB
444 lines
15 KiB
//+----------------------------------------------------------------------------
|
|
//
|
|
// Copyright (C) 2000, Microsoft Corporation
|
|
//
|
|
// File: DfsMigrate.cxx
|
|
//
|
|
// Contents: Contains the routines to migrate existing DFS root
|
|
// information in the registry to a different location,
|
|
// to allow multiple roots per server.
|
|
//
|
|
// Classes: none.
|
|
//
|
|
// History: Feb. 8 2000, Author: udayh
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
//
|
|
// dfsdev: need to add code to delete, on failure, any intermediate stuff
|
|
// we create during migration
|
|
//
|
|
|
|
#include "DfsGeneric.hxx"
|
|
#include "DfsInit.hxx"
|
|
#include "shlwapi.h"
|
|
#include "DfsStore.hxx"
|
|
DFSSTATUS
|
|
MigrateFTDfs(
|
|
LPWSTR MachineName,
|
|
HKEY DfsKey,
|
|
LPWSTR DfsLogicalShare,
|
|
LPWSTR DfsRootShare );
|
|
|
|
DFSSTATUS
|
|
MigrateStdDfs(
|
|
LPWSTR MachineName,
|
|
HKEY DfsKey,
|
|
LPWSTR DfsLogicalShare,
|
|
LPWSTR DfsRootShare,
|
|
BOOLEAN fDoCleanup);
|
|
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Function: MigrateDfs
|
|
//
|
|
// Arguments: MachineName - Name of the machine to target.
|
|
// Can be NULL for local machine.
|
|
// Returns: ERROR_SUCCESS
|
|
// Error code other wise.
|
|
//
|
|
// Description: This routine contacts the specified machine, and checks
|
|
// if the registry information indicates the machine is
|
|
// hosting a standalone or domain DFS. It moves this
|
|
// information appropriately under the new StandaloneRoot
|
|
// or DomainRoots key, so that we can have multiple roots
|
|
// on the machine.
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
DFSSTATUS
|
|
MigrateDfs(
|
|
LPWSTR MachineName )
|
|
{
|
|
LPWSTR DfsRootShare = NULL;
|
|
LPWSTR FtDfsValue = NULL;
|
|
|
|
ULONG DataSize = 0;
|
|
ULONG DataType = 0;
|
|
ULONG RootShareLength = 0;
|
|
ULONG FtDfsValueSize;
|
|
DWORD Status;
|
|
|
|
HKEY OldKey;
|
|
|
|
PRINTF("Migrate DFS Called. This will migrate the DFS on %wS\n",
|
|
(MachineName != NULL) ? MachineName : L"this machine");
|
|
|
|
Status = DfsStore::GetOldDfsRegistryKey( MachineName,
|
|
TRUE,
|
|
NULL,
|
|
&OldKey );
|
|
|
|
//
|
|
// If we opened the DFS hierarchy key properly, get the maximum
|
|
// size of any of the values under this key. This is so that we
|
|
// know how much memory to allocate, so that we can read any of
|
|
// the values we desire.
|
|
//
|
|
//
|
|
if ( Status == ERROR_SUCCESS ) {
|
|
Status = RegQueryInfoKey( OldKey, // Key
|
|
NULL, // Class string
|
|
NULL, // Size of class string
|
|
NULL, // Reserved
|
|
NULL, // # of subkeys
|
|
NULL, // max size of subkey name
|
|
NULL, // max size of class name
|
|
NULL, // # of values
|
|
NULL, // max size of value name
|
|
&DataSize, // max size of value data,
|
|
NULL, // security descriptor
|
|
NULL ); // Last write time
|
|
|
|
//
|
|
// We want to read the value of the DfsRootShare. If the value
|
|
// is still a string, this is indeed an old style DFS and needs
|
|
// to be migrated. If the value is something else, this is
|
|
// already a migrated machine, so do nothing.
|
|
//
|
|
|
|
if (Status == ERROR_SUCCESS) {
|
|
//
|
|
// Space for null terminator
|
|
//
|
|
DataSize += sizeof(WCHAR);
|
|
|
|
RootShareLength = DataSize;
|
|
DfsRootShare = (LPWSTR) new BYTE[DataSize];
|
|
if (DfsRootShare == NULL) {
|
|
Status = ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
else {
|
|
Status = RegQueryValueEx( OldKey,
|
|
DfsRootShareValueName,
|
|
NULL,
|
|
&DataType,
|
|
(LPBYTE)DfsRootShare,
|
|
&RootShareLength);
|
|
}
|
|
}
|
|
//
|
|
// check if the value is a string.
|
|
//
|
|
if ((Status == ERROR_SUCCESS) &&
|
|
(DataType == REG_SZ)) {
|
|
|
|
DWORD Migrated;
|
|
ULONG MigrateSize;
|
|
|
|
MigrateSize = sizeof(Migrated);
|
|
Status = RegQueryValueEx( OldKey,
|
|
DfsMigratedValueName,
|
|
NULL,
|
|
&DataType,
|
|
(PBYTE)&Migrated,
|
|
&MigrateSize);
|
|
|
|
if (Status == ERROR_FILE_NOT_FOUND)
|
|
{
|
|
|
|
FtDfsValueSize = DataSize;
|
|
FtDfsValue = (LPWSTR) new BYTE[DataSize];
|
|
if (FtDfsValue == NULL) {
|
|
Status = ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
else {
|
|
//
|
|
// Now check if this is a Domain Based root.
|
|
//
|
|
Status = RegQueryValueEx( OldKey,
|
|
DfsFtDfsValueName,
|
|
NULL,
|
|
&DataType,
|
|
(LPBYTE)FtDfsValue,
|
|
&FtDfsValueSize);
|
|
|
|
//
|
|
// At this point we do know we have a machine that
|
|
// needs to be migrated. If the machine was hosting
|
|
// a standalone root, call MigrateFTDfs to take care
|
|
// of the domain based dfs root migration. Else, this
|
|
// is a standalone root, so call the standalone root
|
|
// migration routine.
|
|
//
|
|
if (Status == ERROR_SUCCESS) {
|
|
Status = MigrateFTDfs( MachineName,
|
|
OldKey,
|
|
FtDfsValue,
|
|
DfsRootShare );
|
|
}
|
|
else {
|
|
Status = MigrateStdDfs( MachineName,
|
|
OldKey,
|
|
DfsRootShare,
|
|
DfsRootShare,
|
|
FALSE );
|
|
}
|
|
|
|
if (Status == ERROR_SUCCESS)
|
|
{
|
|
DWORD DfsMigrated = 1;
|
|
//
|
|
// ignore error returns here...
|
|
//
|
|
RegSetValueEx( OldKey,
|
|
DfsMigratedValueName,
|
|
0,
|
|
REG_DWORD,
|
|
(PBYTE)&DfsMigrated,
|
|
sizeof(DfsMigrated));
|
|
}
|
|
}
|
|
} else {
|
|
//
|
|
// Already Migrated
|
|
// dfsutil from creating an old fashioned root.
|
|
//
|
|
Status = ERROR_SUCCESS;
|
|
}
|
|
}else {
|
|
//
|
|
// there is no root here: do whatever is necessary to block
|
|
// dfsutil from creating an old fashioned root.
|
|
//
|
|
Status = ERROR_SUCCESS;
|
|
|
|
}
|
|
|
|
//
|
|
// We are done, close the key we opened.
|
|
//
|
|
RegCloseKey( OldKey );
|
|
}
|
|
|
|
|
|
//
|
|
// dfsdev: if we fail, we need to cleanup any of the work we have
|
|
// done so far!
|
|
//
|
|
//
|
|
// release any of the resources we had allocated, since we are
|
|
// about to return back to the caller.
|
|
//
|
|
if ( DfsRootShare != NULL ) {
|
|
delete [] DfsRootShare;
|
|
}
|
|
|
|
if ( FtDfsValue != NULL ) {
|
|
delete [] FtDfsValue;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Function: MigratefFTDfs
|
|
//
|
|
// Arguments:
|
|
// HKEY DfsKey - The open key to the top of DFS registry hierarchy
|
|
// LPWSTR DfsLogicalShare - the logical domain based share.
|
|
// LPWSTR DfsRootShare - the share on this machine backing the name
|
|
// LPWSTR FtDfsDN - The distinguished name in the AD for the DFS.
|
|
//
|
|
// Returns: ERROR_SUCCESS
|
|
// Error code other wise.
|
|
//
|
|
// Description: This routine moves the domain based DFS root information
|
|
// in the registry under a new key, so that we can support
|
|
// multiple roots per machine.
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
DFSSTATUS
|
|
MigrateFTDfs(
|
|
LPWSTR MachineName,
|
|
HKEY DfsKey,
|
|
LPWSTR DfsLogicalShare,
|
|
LPWSTR DfsRootShare )
|
|
{
|
|
DWORD Status;
|
|
HKEY NewBlobKey;
|
|
//
|
|
// We open the ft parent, which holds all the ft roots.
|
|
//
|
|
DFSLOG("Migrating FT Dfs\n");
|
|
|
|
Status = DfsStore::GetNewADBlobRegistryKey( MachineName,
|
|
TRUE,
|
|
NULL,
|
|
&NewBlobKey );
|
|
|
|
if (Status == ERROR_SUCCESS)
|
|
{
|
|
Status = DfsStore::SetupADBlobRootKeyInformation( NewBlobKey,
|
|
DfsLogicalShare,
|
|
DfsRootShare );
|
|
|
|
RegCloseKey( NewBlobKey );
|
|
}
|
|
|
|
|
|
//
|
|
// dfsdev: if we fail, we need to cleanup any of the work we have
|
|
// done so far!
|
|
//
|
|
|
|
|
|
if (Status == ERROR_SUCCESS) {
|
|
RegDeleteValue( DfsKey,
|
|
DfsFtDfsConfigDNValueName);
|
|
RegDeleteValue( DfsKey,
|
|
DfsFtDfsValueName );
|
|
}
|
|
|
|
DFSLOG("Migrating FT Dfs: Status %x\n", Status);
|
|
return Status;
|
|
}
|
|
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Function: MigratefStdDfs
|
|
//
|
|
// Arguments:
|
|
// HKEY DfsKey - The open key to the top of DFS registry hierarchy
|
|
// LPWSTR DfsLogicalShare - the logical dfs share.
|
|
// LPWSTR DfsRootShare - the share on this machine backing the name
|
|
//
|
|
// Returns: ERROR_SUCCESS
|
|
// Error code other wise.
|
|
//
|
|
// Description: This routine moves the registry based DFS root information
|
|
// in the registry under a new key, so that we can support
|
|
// multiple roots per machine.
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
DFSSTATUS
|
|
MigrateStdDfs(
|
|
LPWSTR MachineName,
|
|
HKEY DfsKey,
|
|
LPWSTR DfsLogicalShare,
|
|
LPWSTR DfsRootShare,
|
|
BOOLEAN fDoCleanup)
|
|
{
|
|
DWORD Status = ERROR_SUCCESS;
|
|
HKEY StdDfsKey = NULL;
|
|
HKEY StdDfsShareKey = NULL;
|
|
ULONG RootShareValue = 1;
|
|
size_t LogicalShareCchLength = 0;
|
|
size_t PhysicalShareCchLength = 0;
|
|
|
|
DFSLOG("Migrating Std Dfs\n");
|
|
//
|
|
// Open the new standalone DFS parent, which holds all the
|
|
// standalone roots and their metadata as its children.
|
|
//
|
|
Status = DfsStore::GetNewStandaloneRegistryKey( MachineName,
|
|
TRUE,
|
|
NULL,
|
|
&StdDfsKey );
|
|
|
|
//
|
|
// We now create an unique metadata name for our root, and add
|
|
// it as a child to the parent key we created.
|
|
//
|
|
if (Status == ERROR_SUCCESS) {
|
|
|
|
Status = RegCreateKeyEx( StdDfsKey,
|
|
DfsLogicalShare,
|
|
0,
|
|
L"",
|
|
REG_OPTION_NON_VOLATILE,
|
|
KEY_READ | KEY_WRITE,
|
|
NULL,
|
|
&StdDfsShareKey,
|
|
NULL );
|
|
//
|
|
// We have successfully created the child root. Now, just copy
|
|
// all the link information under the old root key to the new
|
|
// root key. If we successfully copy, we can delete the old
|
|
// standalone root and all its children.
|
|
//
|
|
if (Status == ERROR_SUCCESS) {
|
|
|
|
Status = SHCopyKey( DfsKey,
|
|
DfsOldStandaloneChild,
|
|
StdDfsShareKey,
|
|
NULL );
|
|
if (Status == ERROR_SUCCESS)
|
|
{
|
|
if(fDoCleanup)
|
|
{
|
|
Status = SHDeleteKey( DfsKey,
|
|
DfsOldStandaloneChild );
|
|
}
|
|
}
|
|
|
|
//
|
|
// Now setup the values for the new root so that we know
|
|
// the shares that are backing this new root.
|
|
//
|
|
if (Status == ERROR_SUCCESS) {
|
|
|
|
Status = DfsStringCchLength( DfsRootShare,
|
|
MAXUSHORT,
|
|
&PhysicalShareCchLength );
|
|
|
|
if (Status == ERROR_SUCCESS)
|
|
{
|
|
// Allow an extra character for NULL terminator.
|
|
PhysicalShareCchLength++;
|
|
|
|
Status = RegSetValueEx( StdDfsShareKey,
|
|
DfsRootShareValueName,
|
|
0,
|
|
REG_SZ,
|
|
(PBYTE)DfsRootShare,
|
|
PhysicalShareCchLength * sizeof(WCHAR) );
|
|
}
|
|
}
|
|
|
|
if (Status == ERROR_SUCCESS) {
|
|
|
|
Status = DfsStringCchLength( DfsRootShare,
|
|
MAXUSHORT,
|
|
&LogicalShareCchLength );
|
|
|
|
if (Status == ERROR_SUCCESS)
|
|
{
|
|
// Allow an extra character for NULL terminator.
|
|
LogicalShareCchLength++;
|
|
Status = RegSetValueEx( StdDfsShareKey,
|
|
DfsLogicalShareValueName,
|
|
0,
|
|
REG_SZ,
|
|
(PBYTE)DfsLogicalShare,
|
|
LogicalShareCchLength * sizeof(WCHAR) );
|
|
}
|
|
}
|
|
|
|
|
|
RegCloseKey( StdDfsShareKey );
|
|
}
|
|
|
|
RegCloseKey( StdDfsKey );
|
|
}
|
|
|
|
DFSLOG("Migrating Std Dfs: Status %x\n", Status);
|
|
return Status;
|
|
}
|
|
|