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