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.
 
 
 
 
 
 

577 lines
18 KiB

extern "C" {
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <shellapi.h>
}
#include <ole2.h>
#include <activeds.h>
#include <dfsprefix.h>
#include <DfsServerLibrary.hxx>
#include <DfsRegStrings.hxx>
#include <dfsutil.hxx>
#include <dfsmisc.h>
#include <dfspathname.hxx>
#include <struct.hxx>
LPWSTR UtilRegistryHostLocation = DFS_REG_HOST_LOCATION;
LPWSTR UtilVolumesLocation = DFS_REG_VOLUMES_LOCATION;
LPWSTR UtilFtDfsConfigDNValueName = DFS_REG_FT_DFS_CONFIG_DN_VALUE;
LPWSTR DfsHostLastDomainValueName = DFS_REG_HOST_LAST_DOMAIN_VALUE;
LPWSTR DfsDriverLocalVolumesLocation = DFS_REG_LOCAL_VOLUMES_LOCATION;
LPWSTR DfsDriverLocalVolumesEntryPath = DFS_REG_ENTRY_PATH;
LPWSTR DfsDriverLocalVolumesShortEntryPath = DFS_REG_SHORT_ENTRY_PATH;
DFSSTATUS
DfsFixupRegistryValues(
IN LPWSTR DfsPathString,
IN LPWSTR RootName,
IN LPWSTR OldDomainName,
IN LPWSTR NewDomainName);
DFSSTATUS
DfsRenameRegistries(
IN DfsPathName *pPathName,
IN LPWSTR OldDomainName,
IN LPWSTR NewDomainName);
DFSSTATUS
GetCurrentRegDomainName(
IN HKEY VolumeKey,
IN LPWSTR DfsHostValueName,
OUT LPWSTR *pValueString);
DFSSTATUS
DfsSetRegDomainName(
IN const HKEY DfsKey,
IN const LPWSTR RegValueName,
IN const LPWSTR DomainString);
BOOLEAN
DfsRenameFTConfigValueName(
IN LPWSTR DNString,
IN LPWSTR NewDomainString,
IN PUNICODE_STRING OldDomain,
OUT LPWSTR *NewDNString);
DFSSTATUS
GetRegVolumesHKey(
IN LPWSTR MachineName,
OUT HKEY *VolumeKey);
DFSSTATUS
GetRegLocalVolumesHKey(
IN LPWSTR MachineName,
OUT HKEY *LocalVolumeKey);
//
// DfsRenameRegistries
//
// This contacts all root targets affected by the rename
// operation to possibly change their registry references
// to the obsolete domain name.
//
DFSSTATUS
DfsRenameRegistries(
IN DfsPathName *pPathName,
IN LPWSTR OldDomainName,
IN LPWSTR NewDomainName)
{
DFSSTATUS Status;
LPBYTE pBuffer = NULL;
DWORD ResumeHandle = 0;
DWORD EntriesRead = 0;
DWORD PrefMaxLen = 1;
DWORD Level = 4;
PDFS_INFO_4 pCurrentBuffer;
DWORD i;
PDFS_STORAGE_INFO pStorage;
//
// We are reading in just the ROOT.
// supw: DfsGetInfo is a better way to do this.
//
Status = DfsApiEnumerate( MODE_DIRECT,
pPathName->GetPathString(),
Level,
PrefMaxLen,
&pBuffer,
&EntriesRead,
&ResumeHandle);
if ((Status == ERROR_SUCCESS) && EntriesRead != 0)
{
pCurrentBuffer = (PDFS_INFO_4)pBuffer;
for( i = 0, pStorage = pCurrentBuffer->Storage;
i < pCurrentBuffer->NumberOfStorages;
i++, pStorage = pCurrentBuffer->Storage + i )
{
DebugInformation((L"DfsUtil: RenameRegistries: TARGET SERVER \\\\%ws\\%ws\n",
pStorage->ServerName, pStorage->ShareName));
//
// Now contact the appropriate server(s) for the root replicas
// and fix up their registry values if they happen to still
// point back at the obsolete domain name. Only the pre-Whistler
// servers do that currently.
// Errors are ignored entirely. The target server may or may not be a
// W2K machine.
//
// xxx supw: skip duplicate servernames here.
(VOID)DfsFixupRegistryValues(pStorage->ServerName,
pPathName->GetShareString(),
OldDomainName,
NewDomainName);
//
// Don't bother to resynchrnoize. W2K systems don't respond to RESYNCHRONIZE calls.
// Besides, the administrator is supposed to reboot all root servers.
//
// (VOID)SetInfoReSynchronize( pStorage->ServerName, pStorage->ShareName );
}
//
// Free the allocated memory.
//
DfsFreeApiBuffer(pBuffer);
}
return Status;
}
DFSSTATUS
DfsFixupRegistryValues(
IN LPWSTR MachineName,
IN LPWSTR RootName,
IN LPWSTR OldDomainName,
IN LPWSTR NewDomainName)
{
HKEY VolumeKey, LocalVolKey;
LPWSTR DNString = NULL;
LPWSTR EntryString = NULL;
DFSSTATUS Status;
DFSSTATUS RetStatus = ERROR_SUCCESS;
UNICODE_STRING OldDomUnicode;
UNICODE_STRING DomUnicode;
BOOLEAN Changed = FALSE;
Status = GetRegVolumesHKey( MachineName, &VolumeKey );
if (Status != ERROR_SUCCESS)
{
if (fSwDebug) {
DebugInformation((L"DfsUtil: RegOpen of DfsHost Volumes failed for machine %ws, with error 0x%x\n",
MachineName, Status));
}
//
// Only return fatal conditions that'll prompt us to abort.
//
return RetStatus;
}
RtlInitUnicodeString( &OldDomUnicode, OldDomainName );
//
// The \DfsHost\volumes\FTDfsObjectDN may need fixing.
//
Status = GetCurrentRegDomainName( VolumeKey,
UtilFtDfsConfigDNValueName,
&DNString);
if (Status == ERROR_SUCCESS)
{
LPWSTR NewDNString;
//
// The DNString is of the form "CN=,CN=,...DC=DomainName,DC=..."
// See if the substring DC=DomainName matches the OldDomainName.
// If so substitute it with the NewDomainName and get a new DN string.
//
//if (DfsRenameFTConfigValueName( DNString, NewDomainName, &OldDomUnicode, &NewDNString ))
//
// Simply replace the existing string with a new DN string we generate.
// This assumes that the system has already rebooted since the DC was renamed.
//
{
Status = DfsGenerateDNPathString( RootName, &NewDNString );
if (Status == ERROR_SUCCESS)
{
Status = DfsSetRegDomainName( VolumeKey, UtilFtDfsConfigDNValueName, NewDNString );
if (Status == ERROR_SUCCESS)
{
Changed = TRUE;
DebugInformation((L"FTDfsObjectDN = %ws\n", NewDNString));
}
DfsDeleteDNPathString( NewDNString );
}
}
delete [] DNString;
}
//
// The \DfsHost\volumes\LastDomainName shouldn't mention the old domain name.
//
if (Status == ERROR_SUCCESS)
{
Status = GetCurrentRegDomainName( VolumeKey,
DfsHostLastDomainValueName,
&DNString );
if (Status == ERROR_SUCCESS)
{
RtlInitUnicodeString( &DomUnicode, DNString );
if (RtlEqualDomainName( &DomUnicode, &OldDomUnicode ))
{
//
// Go ahead and make the substitution in the registry.
//
Status = DfsSetRegDomainName( VolumeKey,
DfsHostLastDomainValueName,
NewDomainName );
if (Status == ERROR_SUCCESS)
{
Changed = TRUE;
DebugInformation((L"DfsUtil: Rename of LastDomainName RegKey to %ws successful\n",
NewDomainName));
}
}
delete [] DNString;
}
}
RegCloseKey( VolumeKey );
Status = GetRegLocalVolumesHKey( MachineName, &LocalVolKey );
if (Status != ERROR_SUCCESS)
{
if (fSwDebug) {
DebugInformation((L"DfsUtil: RegOpen of Services\\DfsDriver\\LocalVolume failed for machine %ws, with error 0x%x\n",
MachineName, Status));
}
//
// Only return fatal conditions that'll prompt us to abort.
//
return RetStatus;
}
//
// The HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\DfsDriver\LocalVolume
// shouldn't mention the old domain name.
//
Status = GetCurrentRegDomainName( LocalVolKey,
DfsDriverLocalVolumesEntryPath,
&EntryString );
if (Status == ERROR_SUCCESS)
{
DfsPathName EntryPath;
Status = EntryPath.CreatePathName(EntryString );
if (Status == ERROR_SUCCESS)
{
if (RtlEqualDomainName( EntryPath.GetServerCountedString(), &OldDomUnicode ))
{
DfsPathName NewEntryPath;
//
// Go ahead and make the substitution in the registry.
// But first recreate the EntryPath using the new domain name.
//
NewEntryPath.SetPathName( NewDomainName,
EntryPath.GetShareString(),
1);
Status = DfsSetRegDomainName( LocalVolKey,
DfsDriverLocalVolumesEntryPath,
NewEntryPath.GetPathString() );
if (Status == ERROR_SUCCESS)
{
Changed = TRUE;
DebugInformation((L"DfsUtil: Rename of EntryPath RegKey from %ws to %ws successful\n",
EntryPath.GetPathString(), NewEntryPath.GetPathString()));
}
}
}
delete [] EntryString;
}
Status = GetCurrentRegDomainName( LocalVolKey,
DfsDriverLocalVolumesShortEntryPath,
&EntryString );
if (Status == ERROR_SUCCESS)
{
DfsPathName ShortEntryPath;
Status = ShortEntryPath.CreatePathName(EntryString );
if (Status == ERROR_SUCCESS)
{
if (RtlEqualDomainName( ShortEntryPath.GetServerCountedString(), &OldDomUnicode ))
{
//
// Go ahead and make the substitution in the registry.
// But first recreate the EntryPath using the new domain name.
//
DfsPathName NewEntryPath;
//
// Go ahead and make the substitution in the registry.
// But first recreate the EntryPath using the new domain name.
//
NewEntryPath.SetPathName( NewDomainName,
ShortEntryPath.GetShareString(),
1 );
Status = DfsSetRegDomainName( LocalVolKey,
DfsDriverLocalVolumesShortEntryPath,
NewEntryPath.GetPathString() );
if (Status == ERROR_SUCCESS)
{
Changed = TRUE;
DebugInformation((L"DfsUtil: Rename of ShortEntryPath RegKey From %ws to %ws successful\n",
ShortEntryPath.GetPathString(),
NewEntryPath.GetPathString()));
}
}
}
delete [] EntryString;
}
RegCloseKey( LocalVolKey );
if (Changed) {
DebugInformation((L"DfsUtil: Renamed registry references in root target system %wS\n", MachineName));
}
return RetStatus;
}
DFSSTATUS
GetCurrentRegDomainName(
IN HKEY VolumeKey,
IN LPWSTR DfsHostValueName,
OUT LPWSTR *pValueString)
{
LPWSTR FtDfsValue = NULL;
ULONG DataSize, DataType;
ULONG FtDfsValueSize;
DWORD Status;
*pValueString = NULL;
//
// 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.
//
//
Status = RegQueryInfoKey( VolumeKey, // 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
//
// check if the value is a string.
//
if (Status == ERROR_SUCCESS)
{
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( VolumeKey,
DfsHostValueName,
NULL,
&DataType,
(LPBYTE)FtDfsValue,
&FtDfsValueSize);
if (Status == ERROR_SUCCESS) {
*pValueString = FtDfsValue;
} else {
delete [] FtDfsValue;
}
}
}
return Status;
}
DFSSTATUS
DfsSetRegDomainName(
IN const HKEY DfsKey,
IN const LPWSTR RegValueName,
IN const LPWSTR DomainString)
{
DFSSTATUS Status;
Status = RegSetValueEx( DfsKey,
RegValueName,
0,
REG_SZ,
(PBYTE)DomainString,
wcslen(DomainString) * sizeof(WCHAR) );
return Status;
}
DFSSTATUS
GetRegVolumesHKey(
IN LPWSTR MachineName,
OUT HKEY *VolumeKey)
{
DFSSTATUS Status;
HKEY RootKey;
HKEY HostKey;
Status = RegConnectRegistry( MachineName,
HKEY_LOCAL_MACHINE,
&RootKey );
if ( Status != ERROR_SUCCESS )
{
return Status;
}
Status = RegOpenKeyEx( RootKey,
UtilRegistryHostLocation,
0,
KEY_READ|KEY_WRITE,
&HostKey );
if (RootKey != HKEY_LOCAL_MACHINE)
{
RegCloseKey( RootKey );
}
if (Status == ERROR_SUCCESS)
{
Status = RegOpenKeyEx( HostKey,
UtilVolumesLocation,
0,
KEY_READ|KEY_WRITE,
VolumeKey );
RegCloseKey( HostKey );
}
return Status;
}
DFSSTATUS
GetRegLocalVolumesHKey(
IN LPWSTR MachineName,
OUT HKEY *LocalVolumeKey)
{
DFSSTATUS Status;
HKEY RootKey;
HKEY LocalParentKey;
Status = RegConnectRegistry( MachineName,
HKEY_LOCAL_MACHINE,
&RootKey );
if ( Status != ERROR_SUCCESS )
{
return Status;
}
Status = RegOpenKeyEx( RootKey,
DfsDriverLocalVolumesLocation,
0,
KEY_READ|KEY_WRITE,
&LocalParentKey );
if (RootKey != HKEY_LOCAL_MACHINE)
{
RegCloseKey( RootKey );
}
//
// We know for a fact that the old W2K servers can
// host only one root. Therefore, there can only be one
// child here.
//
if (Status == ERROR_SUCCESS) {
DWORD ChildNameLen = MAX_PATH;
WCHAR ChildName[MAX_PATH];
Status = RegEnumKeyEx( LocalParentKey,
0,
ChildName,
&ChildNameLen,
NULL,
NULL,
NULL,
NULL );
if ( Status == ERROR_SUCCESS )
{
//
// We have the name of a child, so open the key to
// that root.
//
Status = RegOpenKeyEx( LocalParentKey,
ChildName,
0,
KEY_READ|KEY_WRITE,
LocalVolumeKey );
}
RegCloseKey( LocalParentKey );
}
return Status;
}
DFSSTATUS
DfsRenameLinksToDomain(
IN DfsPathName *pDfsPath,
IN LPWSTR OldDomainName,
IN LPWSTR NewDomainName)
{
DFSSTATUS Status;
DebugInformation((L"DfsUtil: Starting renaming links from %ws to %ws in ROOT %ws\n",
OldDomainName, NewDomainName, pDfsPath->GetPathString()));
Status = DfsRenameLinks( pDfsPath->GetPathString(), OldDomainName, NewDomainName );
if (Status == ERROR_SUCCESS)
{
(VOID)DfsRenameRegistries( pDfsPath, OldDomainName, NewDomainName );
CommandSucceeded = TRUE;
}
return Status;
}