Leaked source code of windows server 2003
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

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