//+---------------------------------------------------------------------------- // // Copyright (C) 1995, Microsoft Corporation // // File: dfssetup.cxx // // Contents: Code to setup Dfs on a machine. // // Note that this code can be built as an exe or as a DLL. To // switch between the two, simply edit the following fields in // the sources file: // TARGETTYPE=[PROGRAM | DYNLINK] // UMTYPE=[console | windows] // Delete the following two lines from sources to build an exe. // DLLDEF=obj\*\dfssetup.def // DLLENTRY=_DllMainCRTStartup // DLLBASE=@$(BASEDIR)\PUBLIC\SDK\LIB\coffbase.txt,dfssetup // // Classes: None // // Functions: // // History: 12-28-95 Milans Created // //----------------------------------------------------------------------------- extern "C" { #include #include #include #include } #include #include // For UuidCreate #include #include #include #include #include #include // Needed for debug printing #include // Needed for volume types #include #include "registry.hxx" // Helper functions... #include "setupsvc.hxx" #include "config.hxx" // Config UI functions // // Until we get the schema right in the DS, we have to set our own SD on // certain objects // #include #include DECLARE_DEBUG(DfsSetup) DECLARE_INFOLEVEL(DfsSetup) #if DBG == 1 #define dprintf(x) DfsSetupInlineDebugOut x # else #define dprintf(x) #endif #define MAX_NETBIOS_NAME_LEN 16+1 extern DWORD RemoveDfs(void); BOOLEAN DfsCheckForOldDfsService(); BOOLEAN DfsIsDfsServiceRunning(); VOID Usage(); DWORD SetupDfsRoot( LPWSTR wszDfsRootShare); DWORD SetupFTDfs( IN LPWSTR wszRootShare, IN LPWSTR wszFTDfsName); DWORD InitializeVolumeObjectStorage(); DWORD CreateVolumeObject( IN LPWSTR wszObjectName, IN LPWSTR pwszEntryPath, IN LPWSTR pwszServer, IN LPWSTR pwszShare, IN LPWSTR pwszComment, OUT GUID *guidVolume); DWORD CreateFTRootVolumeInfo( LPWSTR wszObjectName, LPWSTR wszFTDfsConfigDN, LPWSTR wszDomainName, LPWSTR wszDfsName, LPWSTR wszServerName, LPWSTR wszShareName, LPWSTR wszSharePath, LPWSTR wszDCName, BOOLEAN fNewFTDfs); DWORD StoreLvolInfo( IN GUID *pVolumeID, IN PWSTR pwszStorageID, IN PWSTR pwszShareName, IN PWSTR pwszEntryPath, IN ULONG ulVolumeType); DWORD GetDomainAndComputerName( OUT LPWSTR wszDomain OPTIONAL, OUT LPWSTR wszComputer OPTIONAL); DWORD GetSharePath( IN LPWSTR wszShareName, OUT LPWSTR wszSharePath); DWORD TeardownFtDfs( IN LPWSTR wszRootShare, IN LPWSTR wszFTDfsName); //+---------------------------------------------------------------------------- // // Function: main // // Synopsis: Entry point in case you want to build this as an exe. // Configures all Dfs components on a machine. // // Arguments: [argc] -- // [argv] -- // // Returns: Nothing // //----------------------------------------------------------------------------- void _cdecl main(int argc, char *argv[]) { DWORD dwErr = ERROR_SUCCESS; DWORD cbRootLen; BOOL fRootSetup = FALSE; BOOLEAN OldDfsService = FALSE; WCHAR wszDfsRootShare[ MAX_PATH ]; // // Figure out the type of machine we are installing on - client or root // if (argc != 1 && argc != 3) { Usage(); return; } if (argc == 3) { fRootSetup = TRUE; } if ((dwErr == ERROR_SUCCESS) && fRootSetup) { if (_stricmp( argv[1], "-root" ) != 0) { Usage(); return; } cbRootLen = strlen(argv[2]); mbstowcs( wszDfsRootShare, argv[2], cbRootLen + 1 ); dprintf((DEB_ERROR,"Setting up Dfs Root...\n")); } else { dprintf((DEB_ERROR,"Setting up Dfs Server...\n")); } // // Configure the Dfs Driver // if (dwErr == ERROR_SUCCESS) { dwErr = ConfigDfs(); if (dwErr == ERROR_SUCCESS) { dwErr = ConfigDfsService(); if (dwErr != ERROR_SUCCESS) { dprintf(( DEB_ERROR, "Win32 error configuring Dfs Service %d\n", dwErr)); (void)RemoveDfs(); } else { dprintf((DEB_ERROR,"Successfully configured Dfs...\n") ); } } else { dprintf((DEB_ERROR,"Error %d configuring Dfs driver!\n", dwErr)); } } // // If this is a root setup, configure the necessary information // if (dwErr == ERROR_SUCCESS && fRootSetup) { dwErr = SetupDfsRoot( wszDfsRootShare ); } } //+---------------------------------------------------------------------------- // // Function: SetupDfsRoot // // Synopsis: Does necessary setup to make this Dfs a root of the Dfs. // // Arguments: [wszDfsRootShare] -- The share to use as the Dfs root. // // Returns: Win32 error from configuring the root storages etc. // //----------------------------------------------------------------------------- DWORD SetupDfsRoot( LPWSTR wszDfsRootShare) { DWORD dwErr = ERROR_SUCCESS; GUID guid; WCHAR wszDfsRootPath[ MAX_PATH ]; WCHAR wszComputerName[ MAX_NETBIOS_NAME_LEN ]; PWCHAR wszDfsRootPrefix = NULL; dwErr = GetDomainAndComputerName( NULL, wszComputerName ); // // Figure out the share path for the Root Dfs share // if (dwErr == ERROR_SUCCESS) { dwErr = GetSharePath( wszDfsRootShare, wszDfsRootPath ); } // // We have all the info we need now. Lets get to work.... // // 1. Initialize the volume object section in the registry. // // 2. Initialize (ie, create if necessary) the storage used for the // Dfs root. // // 3. Create the root volume object. // // 4. Configure the root volume as a local volume by updating the // LocalVolumes section in the registry. // // // Initialize the Dfs Manager Volume Object Store // if (dwErr == ERROR_SUCCESS) { dwErr = InitializeVolumeObjectStorage(); } if (dwErr == ERROR_SUCCESS) { dprintf((DEB_ERROR, "Setting [%ws] as Dfs storage root...\n", wszDfsRootPath)); dwErr = DfsInitGlobals( wszComputerName, DFS_MANAGER_SERVER ); if (dwErr == ERROR_SUCCESS) { wszDfsRootPrefix = new WCHAR[1 + wcslen(wszComputerName) + 1 + wcslen(wszDfsRootShare) + 1]; if (wszDfsRootPrefix == NULL) { dwErr = ERROR_OUTOFMEMORY; } } if (dwErr == ERROR_SUCCESS) { wszDfsRootPrefix[0] = UNICODE_PATH_SEP; wcscpy( &wszDfsRootPrefix[1], wszComputerName ); wcscat( wszDfsRootPrefix, UNICODE_PATH_SEP_STR ); wcscat( wszDfsRootPrefix, wszDfsRootShare ); dwErr = CreateVolumeObject( DOMAIN_ROOT_VOL, // Name of volume object wszDfsRootPrefix, // EntryPath of volume wszComputerName, // Server name wszDfsRootShare, // Share name L"Dfs Root Volume", // Comment &guid); // Id of created volume } if (dwErr == ERROR_SUCCESS) { dwErr = StoreLvolInfo( &guid, wszDfsRootPath, wszDfsRootShare, wszDfsRootPrefix, DFS_VOL_TYPE_DFS | DFS_VOL_TYPE_REFERRAL_SVC); } if (wszDfsRootPrefix != NULL) delete [] wszDfsRootPrefix; if (dwErr != ERROR_SUCCESS) dwErr = ERROR_INVALID_FUNCTION; if (dwErr == ERROR_SUCCESS) { DWORD dwErr; CRegKey cregVolumesDir( HKEY_LOCAL_MACHINE, &dwErr, VOLUMES_DIR ); if (dwErr == ERROR_SUCCESS) { CRegSZ cregRootShare( cregVolumesDir, ROOT_SHARE_VALUE_NAME, wszDfsRootShare ); dwErr = cregRootShare.QueryErrorStatus(); } } } return( dwErr ); } //+---------------------------------------------------------------------------- // // Function: SetupFTDfs // // Synopsis: Main exported function // // Arguments: [argc] -- // [argv] -- // // Returns: Nothing // //----------------------------------------------------------------------------- DWORD SetupFTDfs( IN LPWSTR wszRootShare, IN LPWSTR wszFTDfsName) { DWORD dwErr = ERROR_SUCCESS; WCHAR wszDomainName[MAX_PATH+1]; WCHAR wszComputerName[MAX_PATH+1]; WCHAR wszRootSharePath[MAX_PATH+1]; WCHAR wszDfsConfigDN[MAX_PATH+1]; WCHAR wszSDDfsConfigDN[MAX_PATH+1]; WCHAR wszConfigurationDN[ MAX_PATH+1 ]; WCHAR wszServerShare[MAX_PATH+1]; PDOMAIN_CONTROLLER_INFO pDCInfo = NULL; LDAP *pldap = NULL; PLDAPMessage pMsg = NULL; LDAPModW ldapModClass, ldapModCN, ldapModPkt, ldapModPktGuid, ldapModServer; LDAP_BERVAL ldapPkt, ldapPktGuid; PLDAP_BERVAL rgModPktVals[2]; PLDAP_BERVAL rgModPktGuidVals[2]; LPWSTR rgModClassVals[2]; LPWSTR rgModCNVals[2]; LPWSTR rgModServerVals[5]; LPWSTR rgAttrs[5]; PLDAPModW rgldapMods[6]; BOOLEAN fNewFTDfs; // // We need some information before we start: // // 1. Our Domain name // // 2. Our Computer name // // 3. The share path of wszRootShare // // 4. The DN of the Configuration OU of our domain // dwErr = GetDomainAndComputerName( wszDomainName, wszComputerName ); if (dwErr != ERROR_SUCCESS) { dprintf(( DEB_ERROR, "Win32 Error %d getting Domain/Computer name\n", dwErr)); goto Cleanup; } dwErr = GetSharePath( wszRootShare, wszRootSharePath ); if (dwErr != ERROR_SUCCESS) { dprintf(( DEB_ERROR, "Win32 Error %d getting share path for %ws\n", dwErr, wszRootShare)); goto Cleanup; } dwErr = DsGetDcName( NULL, // Computer to remote to NULL, // Domain - use our own NULL, // Domain Guid NULL, // Site Guid DS_DIRECTORY_SERVICE_REQUIRED | // Flags DS_PDC_REQUIRED, &pDCInfo); // Return info if (dwErr != ERROR_SUCCESS) { dprintf(( DEB_ERROR, "DsGetDcName failed with Win32 Error %d\n", dwErr)); goto Cleanup; } pldap = ldap_initW(&pDCInfo->DomainControllerAddress[2], LDAP_PORT); if (pldap == NULL) { dprintf((DEB_ERROR, "ldap_init failed\n")); goto Cleanup; } dwErr = ldap_set_option(pldap, LDAP_OPT_AREC_EXCLUSIVE, LDAP_OPT_ON); if (dwErr != LDAP_SUCCESS) { dprintf(( DEB_ERROR, "ldap_set_option failed with ldap error %d\n", dwErr)); pldap = NULL; goto Cleanup; } dwErr = ldap_bind_s(pldap, NULL, NULL, LDAP_AUTH_SSPI); if (dwErr != LDAP_SUCCESS) { dprintf(( DEB_ERROR, "ldap_bind_s failed with ldap error %d\n", dwErr)); pldap = NULL; goto Cleanup; } rgAttrs[0] = L"defaultnamingContext"; rgAttrs[1] = NULL; dwErr = ldap_search_sW( pldap, L"", LDAP_SCOPE_BASE, L"(objectClass=*)", rgAttrs, 0, &pMsg); if (dwErr == LDAP_SUCCESS) { PLDAPMessage pEntry = NULL; PWCHAR *rgszNamingContexts = NULL; DWORD i, cNamingContexts; BOOLEAN fFoundCfg; if ((pEntry = ldap_first_entry(pldap, pMsg)) != NULL && (rgszNamingContexts = ldap_get_valuesW(pldap, pEntry, rgAttrs[0])) != NULL && (cNamingContexts = ldap_count_valuesW(rgszNamingContexts)) > 0) { wcscpy( wszConfigurationDN, *rgszNamingContexts ); fFoundCfg = TRUE; if (!fFoundCfg) { dwErr = ERROR_UNEXP_NET_ERR; } } else { dwErr = ERROR_UNEXP_NET_ERR; } if (pEntry != NULL) ldap_msgfree( pEntry ); if (rgszNamingContexts != NULL) ldap_value_freeW( rgszNamingContexts ); } if (dwErr != ERROR_SUCCESS) { dprintf((DEB_ERROR, "Unable to find Configuration naming context\n")); goto Cleanup; } // // Great, we have all the parameters now, so configure the DS // // // See if the DfsConfiguration object exists; if not, create it. // wsprintf( wszDfsConfigDN, L"CN=Dfs-Configuration,CN=System,%ws", wszConfigurationDN); rgAttrs[0] = L"cn"; rgAttrs[1] = NULL; dwErr = ldap_search_sW( pldap, wszDfsConfigDN, LDAP_SCOPE_BASE, L"(objectClass=*)", rgAttrs, 0, &pMsg); if (dwErr == LDAP_SUCCESS) ldap_msgfree( pMsg ); if (dwErr == LDAP_NO_SUCH_OBJECT) { rgModClassVals[0] = L"dfsConfiguration"; rgModClassVals[1] = NULL; ldapModClass.mod_op = LDAP_MOD_ADD; ldapModClass.mod_type = L"objectClass"; ldapModClass.mod_vals.modv_strvals = rgModClassVals; rgModCNVals[0] = L"Dfs-Configuration"; rgModCNVals[1] = NULL; ldapModCN.mod_op = LDAP_MOD_ADD; ldapModCN.mod_type = L"cn"; ldapModCN.mod_vals.modv_strvals = rgModCNVals; rgldapMods[0] = &ldapModClass; rgldapMods[1] = &ldapModCN; rgldapMods[2] = NULL; dwErr = ldap_add_sW( pldap, wszDfsConfigDN, rgldapMods); } if (dwErr != LDAP_SUCCESS) { dprintf(( DEB_ERROR, "1:ldap_add_s for %ws failed with LDAP error %d\n", wszDfsConfigDN, dwErr )); goto Cleanup; } // // Check to see if we are joining an FTDfs or creating a new one. // wsprintf( wszDfsConfigDN, L"CN=%ws,CN=Dfs-Configuration,CN=System,%ws", wszFTDfsName, wszConfigurationDN); wsprintf( wszServerShare, L"\\\\%ws\\%ws", wszComputerName, wszRootShare); rgAttrs[0] = L"remoteServerName"; rgAttrs[1] = NULL; dwErr = ldap_search_sW( pldap, wszDfsConfigDN, LDAP_SCOPE_BASE, L"(objectClass=*)", rgAttrs, 0, &pMsg); if (dwErr == ERROR_SUCCESS) { // // We are joining an existing FT Dfs. Append our server\share to it // LDAPMessage *pmsgServers; PWCHAR *rgServers, *rgNewServers; DWORD cServers; fNewFTDfs = FALSE; pmsgServers = ldap_first_entry(pldap, pMsg); if (pmsgServers != NULL) { rgServers = ldap_get_valuesW( pldap, pmsgServers, L"remoteServerName"); if (rgServers != NULL) { cServers = ldap_count_valuesW( rgServers ); rgNewServers = new LPWSTR [ cServers + 2 ]; if (rgNewServers != NULL) { CopyMemory( rgNewServers, rgServers, cServers * sizeof(rgServers[0]) ); rgNewServers[cServers] = wszServerShare; rgNewServers[cServers+1] = NULL; ldapModServer.mod_op = LDAP_MOD_REPLACE; ldapModServer.mod_type = L"remoteServerName"; ldapModServer.mod_vals.modv_strvals = rgNewServers; rgldapMods[0] = &ldapModServer; rgldapMods[1] = NULL; dwErr = ldap_modify_sW(pldap, wszDfsConfigDN, rgldapMods); if (LDAP_ATTRIBUTE_OR_VALUE_EXISTS == dwErr) dwErr = ERROR_SUCCESS; delete [] rgNewServers; } else { dwErr = ERROR_OUTOFMEMORY; } ldap_value_freeW( rgServers ); } else { dwErr = ERROR_OUTOFMEMORY; } ldap_msgfree( pmsgServers ); } else { dwErr = ERROR_OUTOFMEMORY; } } else if (dwErr == LDAP_NO_SUCH_OBJECT) { GUID idPkt; DWORD dwPktVersion = 1; // // We are creating a new FTDfs, create a container to hold the Dfs // configuration for it. // fNewFTDfs = TRUE; // // Generate the class and CN attributes // rgModClassVals[0] = L"ftDfs"; rgModClassVals[1] = NULL; ldapModClass.mod_op = LDAP_MOD_ADD; ldapModClass.mod_type = L"objectClass"; ldapModClass.mod_vals.modv_strvals = rgModClassVals; rgModCNVals[0] = wszFTDfsName; rgModCNVals[1] = NULL; ldapModCN.mod_op = LDAP_MOD_ADD; ldapModCN.mod_type = L"cn"; ldapModCN.mod_vals.modv_strvals = rgModCNVals; // // Generate the null PKT attribute // ldapPkt.bv_len = sizeof(DWORD); ldapPkt.bv_val = (PCHAR) &dwPktVersion; rgModPktVals[0] = &ldapPkt; rgModPktVals[1] = NULL; ldapModPkt.mod_op = LDAP_MOD_ADD | LDAP_MOD_BVALUES; ldapModPkt.mod_type = L"pKT"; ldapModPkt.mod_vals.modv_bvals = rgModPktVals; // // Generate a PKT Guid attribute // UuidCreate( &idPkt ); ldapPktGuid.bv_len = sizeof(GUID); ldapPktGuid.bv_val = (PCHAR) &idPkt; rgModPktGuidVals[0] = &ldapPktGuid; rgModPktGuidVals[1] = NULL; ldapModPktGuid.mod_op = LDAP_MOD_ADD | LDAP_MOD_BVALUES; ldapModPktGuid.mod_type = L"pKTGuid"; ldapModPktGuid.mod_vals.modv_bvals = rgModPktGuidVals; // // Generate a Remote-Server-Name attribute // rgModServerVals[0] = wszServerShare; rgModServerVals[1] = NULL; ldapModServer.mod_op = LDAP_MOD_ADD; ldapModServer.mod_type = L"remoteServerName"; ldapModServer.mod_vals.modv_strvals = rgModServerVals; // // Assemble all the LDAPMod structures // rgldapMods[0] = &ldapModClass; rgldapMods[1] = &ldapModCN; rgldapMods[2] = &ldapModPkt; rgldapMods[3] = &ldapModPktGuid; rgldapMods[4] = &ldapModServer; rgldapMods[5] = NULL; // // Create the Dfs metadata object. // dwErr = ldap_add_sW( pldap, wszDfsConfigDN, rgldapMods ); if (dwErr == ERROR_SUCCESS) { dprintf(( DEB_ERROR, "2:ldap_add_s worked for %ws with ldap error %d\n", wszDfsConfigDN, dwErr)); } } if (dwErr != LDAP_SUCCESS) { dprintf(( DEB_ERROR, "2:ldap_add_s failed for %ws with ldap error %d\n", wszDfsConfigDN, dwErr)); goto Cleanup; } // // Finally, create the root volume object // dwErr = CreateFTRootVolumeInfo( DOMAIN_ROOT_VOL, wszDfsConfigDN, wszDomainName, wszFTDfsName, wszComputerName, wszRootShare, wszRootSharePath, &pDCInfo->DomainControllerAddress[2], fNewFTDfs); if (dwErr != LDAP_SUCCESS) { dprintf(( DEB_ERROR, "CreateVolumeObject failed with error %d\n", dwErr)); } else { dprintf(( DEB_ERROR, "Successfully created FT-Dfs Configuration!\n")); } Cleanup: if (pDCInfo != NULL) NetApiBufferFree( pDCInfo ); if (pldap != NULL) ldap_unbind( pldap ); return( dwErr ); } //+---------------------------------------------------------------------------- // // Function: RemoveDfsRoot // // Synopsis: Removes the Dfs Root config info. // // Arguments: None // // Returns: Win32 error from registry actions // //----------------------------------------------------------------------------- DWORD RemoveDfsRoot() { DWORD dwErr; CRegKey cregVolumesDir( HKEY_LOCAL_MACHINE, &dwErr, VOLUMES_DIR ); CRegKey *pcregLV = NULL; if (dwErr != ERROR_SUCCESS) { // Unable to open volumes dir return(dwErr); } pcregLV = new CRegKey( // Open local volumes section HKEY_LOCAL_MACHINE, REG_KEY_LOCAL_VOLUMES); if (pcregLV != NULL) { dwErr = pcregLV->QueryErrorStatus(); } else { dwErr = ERROR_OUTOFMEMORY; } if (dwErr == ERROR_SUCCESS) { dwErr = pcregLV->Delete(); // Delete local volumes delete pcregLV; pcregLV = NULL; if (dwErr == ERROR_SUCCESS) { // // Recreate an empty local volumes key // pcregLV = new CRegKey( HKEY_LOCAL_MACHINE, REG_KEY_LOCAL_VOLUMES); cregVolumesDir.Delete(); // Delete volumes dir } } if (pcregLV != NULL) { delete pcregLV; } return( dwErr ); } //+---------------------------------------------------------------------------- // // Function: DfsSetupDfs // // Synopsis: Entry point in case you want to build this as a DLL. This // function is suitable for being called from a setup .inf // file. // // Arguments: [cArgs] -- Count of args // [lpszArgs] -- Array of args // [lpszTextOut] -- On return, points to a global buffer // containing the null string. This is required by the // .inf file // // Returns: TRUE. // //----------------------------------------------------------------------------- LPSTR szReturn = ""; extern "C" BOOL DfsSetupDfs( DWORD cArgs, LPSTR lpszArgs[], LPSTR *lpszTextOut) { int argc; LPSTR *argv; argv = (LPSTR *) malloc( (cArgs+1) * sizeof(LPSTR) ); if (argv == NULL) { return( FALSE ); } argv[0] = "DfsSetup"; for (argc = 1; argc <= (int) cArgs; argc++) { argv[ argc ] = lpszArgs[ argc-1 ]; } main( argc, argv ); free( argv ); *lpszTextOut = szReturn; return( TRUE ); } //+---------------------------------------------------------------------------- // // Function: DfsSetupDfsRoot // // Synopsis: Entry point for setting up just the root part of Dfs in // case you want to build this as a DLL. This function is // suitable for being called from a setup .inf file. // // Arguments: [cArgs] -- Count of args // [lpszArgs] -- Array of args // [lpszTextOut] -- On return, points to a global buffer // containing the null string. This is required by the // .inf file // // Returns: TRUE. // //----------------------------------------------------------------------------- BOOLEAN DfsSetupDfsRoot( DWORD cArgs, LPSTR szArgs[], LPSTR *szTextOut) { if (cArgs == 1) { DWORD dwErr; WCHAR wszDfsRootShare[MAX_PATH]; mbstowcs( wszDfsRootShare, szArgs[0], strlen(szArgs[0]) + 1); dwErr = SetupDfsRoot( wszDfsRootShare ); } *szTextOut = szReturn; return( TRUE ); } //+---------------------------------------------------------------------------- // // Function: DfsSetupGetConfig // // Synopsis: Reads the current configuration from the registry. // // Arguments: [pcfg] -- The DFS_CONFIGURATION info to fill // // Returns: TRUE if successfully read the config info, FALSE otherwise // //----------------------------------------------------------------------------- BOOLEAN DfsSetupGetConfig( HWND hwnd, DFS_CONFIGURATION *pcfg) { DWORD dwErr; CRegKey cregVolumesDir( HKEY_LOCAL_MACHINE, &dwErr, VOLUMES_DIR ); ULONG cbBuffer; WCHAR wszErr[128]; ZeroMemory( pcfg, sizeof(DFS_CONFIGURATION) ); if (dwErr == ERROR_ACCESS_DENIED) { MessageBox( hwnd, L"Insufficient priviledge", DFS_COMPONENT_NAME, MB_OK | MB_ICONSTOP); return( FALSE ); } else if (dwErr != ERROR_SUCCESS && dwErr != ERROR_FILE_NOT_FOUND) { swprintf(wszErr, L"Unexpected error %08lx accessing registry", dwErr); MessageBox( hwnd, wszErr, DFS_COMPONENT_NAME, MB_OK | MB_ICONSTOP); return( FALSE ); } if (dwErr == ERROR_SUCCESS) { pcfg->fHostsDfs = TRUE; CRegSZ cregRootShare( cregVolumesDir, ROOT_SHARE_VALUE_NAME ); dwErr = cregRootShare.QueryErrorStatus(); if (dwErr == ERROR_SUCCESS) { cbBuffer = sizeof(pcfg->szRootShare); dwErr = cregRootShare.GetString( pcfg->szRootShare, &cbBuffer ); } if (dwErr == ERROR_SUCCESS) { DWORD dwErrFTDfs; CRegSZ cregFTDfs( cregVolumesDir, FTDFS_VALUE_NAME ); dwErrFTDfs = cregFTDfs.QueryErrorStatus(); if (dwErrFTDfs == ERROR_SUCCESS) { pcfg->fFTDfs = TRUE; cbBuffer = sizeof(pcfg->szFTDfs); dwErr = cregFTDfs.GetString(pcfg->szFTDfs, &cbBuffer); } } if (dwErr != ERROR_SUCCESS) { swprintf(wszErr, L"Error %08lx accessing registry", dwErr); MessageBox( hwnd, wszErr, DFS_COMPONENT_NAME, MB_OK | MB_ICONSTOP); return( FALSE ); } } return( TRUE ); } //+---------------------------------------------------------------------------- // // Function: DfsSetupConfigure // // Synopsis: Presents the dialog box for configuring the Dfs root. // // Arguments: [cArgs] -- Count of args // [lpszArgs] -- Array of args // [lpszTextOut] -- On return, points to a global buffer // containing the name of the share selected by the // user to serve as the root of the Dfs. If the user // hits Cancel, or decides not to setup a Dfs root, // this string is set to point to the NULL string. // // Returns: TRUE iff machine should be rebooted // //----------------------------------------------------------------------------- LPSTR szCancel = "Cancel"; LPSTR szReboot = "Reboot"; BOOLEAN DfsSetupConfigure( DWORD cArgs, LPSTR szArgs[], LPSTR *szTextOut) { DWORD dwErr = 0; HWND hwnd; DFS_CONFIGURATION dfscfg, dfsNewCfg; CHAR *pchUnused; BOOLEAN fRtn=FALSE; *szTextOut = szCancel; // Default return result ASSERT( cArgs == 1 ); hwnd = (HWND) LongToHandle( strtoul( szArgs[0], &pchUnused, 16 ) ); // // Read the current configuration // HCURSOR hCursor=LoadCursor(NULL,IDC_WAIT); if (!DfsSetupGetConfig( hwnd, &dfscfg )) { return fRtn; } // // Next, pop up a dialog to allow the user to change the configuration // dfsNewCfg = dfscfg; // Prompt the user for what flavour of Dfs to create if (ConfigureDfs( hwnd, &dfsNewCfg ) == TRUE) { // Prompt the user for a local machine share if (ConfigDfsShare(hwnd, &dfsNewCfg) == TRUE) { // Set the Hourglass if (hCursor) SetCursor(hCursor); // // User hit OK. Figure out what changed, if anything. // if (dfscfg.fHostsDfs == FALSE && dfsNewCfg.fHostsDfs == FALSE) { // // No change... // NOTHING; } else if (dfscfg.fHostsDfs == FALSE && dfsNewCfg.fHostsDfs == TRUE) { // // We want to host a new Dfs, so call SetupDfsRoot or // SetupFTDfsRoot depending on what kind of Dfs Host the user // wants to setup // if (dfsNewCfg.fFTDfs) { dwErr = SetupFTDfs( dfsNewCfg.szRootShare, dfsNewCfg.szFTDfs ); } else { dwErr = SetupDfsRoot( dfsNewCfg.szRootShare ); } *szTextOut = szReboot; if (dwErr == 0) { CRegKey RebootKey(HKEY_LOCAL_MACHINE, REBOOT_KEY, KEY_ALL_ACCESS, NULL, REG_OPTION_VOLATILE); dwErr = RebootKey.QueryErrorStatus(); if (dwErr) { dprintf((DEB_ERROR,"DfsStopHosting could not add reboot key\n")); } else { CRegDWORD rvReboot((const CRegKey &) RebootKey, REG_VALUE_REBOOT, 1); dwErr = rvReboot.QueryErrorStatus(); } } } else if (dfscfg.fHostsDfs == TRUE && dfsNewCfg.fHostsDfs == FALSE) { // // We want to delete our Dfs root // if (MessageBox( hwnd, L"Are you sure you want to delete the Dfs\n" L"rooted at this machine?", DFS_COMPONENT_NAME, MB_ICONQUESTION | MB_YESNO) == IDYES) { dwErr = RemoveDfsRoot(); *szTextOut = dwErr == ERROR_SUCCESS ? szReboot : szCancel; if (dwErr == 0) { CRegKey RebootKey(HKEY_LOCAL_MACHINE, REBOOT_KEY, KEY_ALL_ACCESS, NULL, REG_OPTION_VOLATILE); dwErr = RebootKey.QueryErrorStatus(); if (dwErr) { dprintf((DEB_ERROR,"DfsStopHosting could not add reboot key\n")); } else { CRegDWORD rvReboot((const CRegKey &) RebootKey, REG_VALUE_REBOOT, 1); dwErr = rvReboot.QueryErrorStatus(); } } } } else if (dfscfg.fHostsDfs == TRUE && dfsNewCfg.fHostsDfs == TRUE) { // // User might have changed the root share, or simply changed // status with respect to FTDfs // if ((_wcsicmp( dfscfg.szRootShare, dfsNewCfg.szRootShare )) != 0 || dfscfg.fFTDfs != dfsNewCfg.fFTDfs) { dwErr = RemoveDfsRoot(); if (dwErr == ERROR_SUCCESS) { if (dfsNewCfg.fFTDfs) { dwErr = SetupFTDfs( dfsNewCfg.szRootShare, dfsNewCfg.szFTDfs); } else { dwErr = SetupDfsRoot( dfsNewCfg.szRootShare ); } } *szTextOut = szReboot; if (dwErr == 0) { CRegKey RebootKey(HKEY_LOCAL_MACHINE, REBOOT_KEY, KEY_ALL_ACCESS, NULL, REG_OPTION_VOLATILE); dwErr = RebootKey.QueryErrorStatus(); if (dwErr) { dprintf((DEB_ERROR,"DfsStopHosting could not add reboot key\n")); } else { CRegDWORD rvReboot((const CRegKey &) RebootKey, REG_VALUE_REBOOT, 1); dwErr = rvReboot.QueryErrorStatus(); } } } // // Raid: 455295 Put in code to handle FTDfs name change // } // // Only request a reboot if everything has gone fine so far. // MariusB and JonN 8/20/97 // if (!dwErr) fRtn=TRUE; } } return fRtn; } //+---------------------------------------------------------------------------- // // Function: Usage // // Synopsis: Prints out the usage message in case you want to build this // as an .exe // // Arguments: // // Returns: // //----------------------------------------------------------------------------- VOID Usage() { dprintf((DEB_ERROR,"Usage: dfssetup -root -share \n")); dprintf((DEB_ERROR," is the name of an empty directory to use\n")); dprintf((DEB_ERROR," as the root storage for Dfs\n")); dprintf((DEB_ERROR," is the share name to access \n")); } //+---------------------------------------------------------------------------- // // Function: InitializeVolumeObjectStorage // // Synopsis: Initializes the Dfs Manager Volume Object store. // // Arguments: None // // Returns: DWORD from registry operations. // //----------------------------------------------------------------------------- DWORD InitializeVolumeObjectStorage() { DWORD dwErr; CRegKey *pcregVolumeObjectStore = NULL; pcregVolumeObjectStore = new CRegKey(HKEY_LOCAL_MACHINE, VOLUMES_DIR ); if (pcregVolumeObjectStore != NULL) { dwErr = pcregVolumeObjectStore->QueryErrorStatus(); if ( dwErr == ERROR_SUCCESS ) { dwErr = pcregVolumeObjectStore->Delete(); if (dwErr == ERROR_SUCCESS) { delete pcregVolumeObjectStore; pcregVolumeObjectStore = new CRegKey( HKEY_LOCAL_MACHINE, VOLUMES_DIR ); if (pcregVolumeObjectStore != NULL) { dwErr = pcregVolumeObjectStore->QueryErrorStatus(); } else { dwErr = ERROR_OUTOFMEMORY; } } } } else { dwErr = ERROR_OUTOFMEMORY; } if (dwErr == ERROR_SUCCESS) { dprintf((DEB_ERROR,"Successfully inited Dfs Manager Volume Storage...\n")); } if (pcregVolumeObjectStore != NULL) { delete pcregVolumeObjectStore; } return(dwErr); } //+---------------------------------------------------------------------------- // // Function: CreateVolumeObject // // Synopsis: Creates a volume object to bootstrap the Dfs namespace. // // Arguments: [pwszObjectName] -- The name of the volume object, relative // to VOLUMES_DIR // [pwszEntryPath] -- EntryPath of the volume. // [pwszServer] -- Name of server used to access this Dfs volume // [pwszShare] -- Name of share used to access this Dfs volume // [pwszComment] -- Comment to stamp on the volume object. // [guidVolume] -- ID of newly create dfs volume // // Returns: // //----------------------------------------------------------------------------- DWORD CreateVolumeObject( LPWSTR wszObjectName, LPWSTR pwszEntryPath, LPWSTR pwszServer, LPWSTR pwszShare, LPWSTR pwszComment, GUID *guidVolume) { DWORD dwErr; WCHAR wszFullObject[ MAX_PATH ]; // // First, compute the full object name, storage ids, and machine name. // wcscpy( wszFullObject, VOLUMES_DIR ); wcscat( wszFullObject, wszObjectName ); // // Next, get a guid for this volume // UuidCreate( guidVolume ); // // Lastly, create this volume object // dwErr = DfsManagerCreateVolumeObject( wszFullObject, pwszEntryPath, pwszServer, pwszShare, pwszComment, guidVolume); if (dwErr == ERROR_SUCCESS) { dprintf((DEB_ERROR,"Successfully inited Dfs Manager Volume [%ws]...\n", pwszEntryPath)); } return(dwErr); } //+---------------------------------------------------------------------------- // // Function: CreateFTRootVolumeInfo // // Synopsis: Creates a Dfs volume object - used to bootstrap a Dfs by // creating a root volume object // // Arguments: [wszObjectName] -- Name of volume object // [wszFTDfsConfigDN] -- The DN of the FTDfs config object in DS // [wszDomainName] -- Name of FTDfs domain // [wszDfsName] -- Name of Dfs // [wszServerName] -- Name of root server // [wszShareName] -- Name of root share // [wszDCName] -- DC to use // [fNewFTDfs] -- If true, this is a new FTDfs // // Returns: // //----------------------------------------------------------------------------- DWORD CreateFTRootVolumeInfo( LPWSTR wszObjectName, LPWSTR wszFTDfsConfigDN, LPWSTR wszDomainName, LPWSTR wszDfsName, LPWSTR wszServerName, LPWSTR wszShareName, LPWSTR wszSharePath, LPWSTR wszDCName, BOOLEAN fNewFTDfs) { DWORD dwErr = ERROR_SUCCESS; WCHAR wszFullObjectName[ MAX_PATH ]; WCHAR wszDfsPrefix[ MAX_PATH ]; GUID idVolume; static BOOLEAN fInited = FALSE; wcscpy( wszDfsPrefix, UNICODE_PATH_SEP_STR ); wcscat( wszDfsPrefix, wszDomainName ); wcscat( wszDfsPrefix, UNICODE_PATH_SEP_STR ); wcscat( wszDfsPrefix, wszDfsName ); wcscpy( wszFullObjectName, LDAP_VOLUMES_DIR ); wcscat( wszFullObjectName, wszObjectName ); if (!fInited) { // // Create the volumes dir key that indicates that this machine is to // be a root of an FTDfs // CRegKey cregVolumesDir( HKEY_LOCAL_MACHINE, VOLUMES_DIR ); dwErr = cregVolumesDir.QueryErrorStatus(); if (dwErr == ERROR_SUCCESS) { CRegSZ cregRootShare( cregVolumesDir, ROOT_SHARE_VALUE_NAME, wszShareName ); dwErr = cregRootShare.QueryErrorStatus(); if (dwErr == ERROR_SUCCESS) { CRegSZ cregFTDfs( cregVolumesDir, FTDFS_VALUE_NAME, wszDfsName); CRegSZ cregFTDfsConfigDN( cregVolumesDir, FTDFS_DN_VALUE_NAME, wszFTDfsConfigDN); dwErr = cregFTDfs.QueryErrorStatus(); if (dwErr == ERROR_SUCCESS) { dwErr = cregFTDfsConfigDN.QueryErrorStatus(); if (dwErr != ERROR_SUCCESS) cregFTDfs.Delete(); } } } if (dwErr == ERROR_SUCCESS) { dwErr = DfsInitGlobals( wszDfsName, DFS_MANAGER_FTDFS); } if (dwErr == ERROR_SUCCESS) fInited = TRUE; } DfsManagerSetDcName(wszDCName); if (dwErr == ERROR_SUCCESS) { if (fNewFTDfs) { // // Generate a Guid for the new Volume // UuidCreate( &idVolume ); dwErr = DfsManagerCreateVolumeObject( wszFullObjectName, wszDfsPrefix, wszServerName, wszShareName, L"Root Volume", &idVolume); } else { dwErr = DfsManagerAddService( wszFullObjectName, wszServerName, wszShareName, &idVolume); } } if (dwErr == ERROR_SUCCESS) { dwErr = StoreLvolInfo( &idVolume, wszSharePath, wszShareName, wszDfsPrefix, DFS_VOL_TYPE_DFS | DFS_VOL_TYPE_REFERRAL_SVC); } return( dwErr ); } //+---------------------------------------------------------------------------- // // Function: StoreLvolInfo // // Synopsis: Stores information about a local volume in the registry. // // Arguments: [pVolumeID] -- Id of dfs volume // [pwszStorageId] -- Storage used by dfs volume // [pwszShareName] -- LM Share used to access dfs volume // [pwszEntryPath] -- EntryPath of dfs volume // [ulVolumeType] -- Type of dfs volume. See DFS_VOL_TYPE_xxx // // Returns: DWORD from registry operations. // //----------------------------------------------------------------------------- extern VOID GuidToString( IN GUID *pID, OUT PWSTR pwszID); DWORD StoreLvolInfo( IN GUID *pVolumeID, IN PWSTR pwszStorageID, IN PWSTR pwszShareName, IN PWSTR pwszEntryPath, IN ULONG ulVolumeType) { DWORD dwErr; WCHAR wszLvolKey[_MAX_PATH]; UNICODE_STRING ustrNtStorageId; PWCHAR pwcGuid; wcscpy(wszLvolKey, REG_KEY_LOCAL_VOLUMES); wcscat(wszLvolKey, UNICODE_PATH_SEP_STR); pwcGuid = wszLvolKey + wcslen(wszLvolKey); ASSERT( *pwcGuid == UNICODE_NULL ); GuidToString( pVolumeID, pwcGuid ); if (!RtlDosPathNameToNtPathName_U( pwszStorageID, &ustrNtStorageId, NULL, NULL)) { return(ERROR_OUTOFMEMORY); } else { ustrNtStorageId.Buffer[ustrNtStorageId.Length/sizeof(WCHAR)] = UNICODE_NULL; } CRegKey rkeyLvol(HKEY_LOCAL_MACHINE, wszLvolKey, KEY_WRITE, NULL, REG_OPTION_NON_VOLATILE); dwErr = rkeyLvol.QueryErrorStatus(); if (dwErr != ERROR_SUCCESS) { RtlFreeUnicodeString(&ustrNtStorageId); return(dwErr); } CRegSZ rvEntryPath((const CRegKey &) rkeyLvol, REG_VALUE_ENTRY_PATH, pwszEntryPath); CRegSZ rvShortEntryPath((const CRegKey &) rkeyLvol, REG_VALUE_SHORT_PATH, pwszEntryPath); CRegDWORD rvEntryType((const CRegKey &) rkeyLvol, REG_VALUE_ENTRY_TYPE, ulVolumeType); CRegSZ rvStorageId((const CRegKey &) rkeyLvol, REG_VALUE_STORAGE_ID, ustrNtStorageId.Buffer); CRegSZ rvShareName((const CRegKey &) rkeyLvol, REG_VALUE_SHARE_NAME, pwszShareName); RtlFreeUnicodeString(&ustrNtStorageId); if (ERROR_SUCCESS != (dwErr = rvEntryPath.QueryErrorStatus()) || ERROR_SUCCESS != (dwErr = rvShortEntryPath.QueryErrorStatus()) || ERROR_SUCCESS != (dwErr = rvEntryType.QueryErrorStatus()) || ERROR_SUCCESS != (dwErr = rvStorageId.QueryErrorStatus()) || ERROR_SUCCESS != (dwErr = rvShareName.QueryErrorStatus())) { rkeyLvol.Delete(); } else { dprintf((DEB_ERROR,"Successfully stored local volume info for [%ws]\n", pwszEntryPath)); } return(dwErr); } //+------------------------------------------------------------------ // // Function: CheckForOldDfsService // // Synopsis: // // Effects: -none- // // Arguments: -none- // // Returns: TRUE if the old (pre -ds build) dfs service is installed // // // History: 10-09-96 JimMcN Created // // Notes: // // //------------------------------------------------------------------- BOOLEAN DfsCheckForOldDfsService( ) { DWORD dwErr = 0; DWORD DfsVersion; // Open Service Controller CService cSvc; if (!(dwErr = cSvc.Init())) { dwErr = cSvc._OpenService(L"Dfs", SERVICE_QUERY_STATUS); cSvc._CloseService(); if (dwErr != 0) { return(FALSE); } CRegKey cregDfsService( HKEY_LOCAL_MACHINE, &dwErr, L"System\\CurrentControlSet\\Services\\Dfs" ); if (dwErr == ERROR_SUCCESS) { CRegDWORD DfsNewService((const CRegKey &)cregDfsService, L"DfsVersion", &DfsVersion); dwErr = DfsNewService.QueryErrorStatus(); if (dwErr != 0) { dprintf((DEB_ERROR,"CheckForOldDfsService Failed Newserv\n")); return(TRUE); } if (DfsVersion < DFS_VERSION_NUMBER) { return(TRUE); } return(FALSE); } return(FALSE); } return FALSE ; } //+---------------------------------------------------------------------------- // // Function: GetDomainAndComputerName // // Synopsis: Retrieves the domain and computer name of the local machine // // Arguments: [wszDomain] -- On successful return, contains name of domain. // If this parameter is NULL on entry, the domain name is // not returned. // // [wszComputer] -- On successful return, contains name of // computer. If this parameter is NULL on entry, the // computer name is not returned. // // Returns: [ERROR_SUCCESS] -- Successfully returning names. // // Win32 Error from calling NetWkstaGetInfo // //----------------------------------------------------------------------------- DWORD GetDomainAndComputerName( OUT LPWSTR wszDomain OPTIONAL, OUT LPWSTR wszComputer OPTIONAL) { DWORD dwErr; PWKSTA_INFO_100 wkstaInfo = NULL; dwErr = NetWkstaGetInfo( NULL, 100, (LPBYTE *) &wkstaInfo ); if (dwErr == NERR_Success) { if (wszDomain) wcscpy(wszDomain, wkstaInfo->wki100_langroup); if (wszComputer) wcscpy(wszComputer, wkstaInfo->wki100_computername); NetApiBufferFree( wkstaInfo ); } return( dwErr ); } //+---------------------------------------------------------------------------- // // Function: GetSharePath // // Synopsis: Returns the share path for a share on the local machine // // Arguments: [wszShare] -- Name of share // // [wszPath] -- On return, share path of wszShare // // Returns: [ERROR_SUCCESS] -- Successfully returning share path // // Win32 error from NetShareGetInfo // //----------------------------------------------------------------------------- DWORD GetSharePath( IN LPWSTR wszShare, OUT LPWSTR wszPath) { DWORD dwErr; PSHARE_INFO_2 pshi2; dwErr = NetShareGetInfo( NULL, // Server (local machine) wszShare, // Share Name 2, // Level, (LPBYTE *) &pshi2); // Buffer if (dwErr == ERROR_SUCCESS) { wcscpy( wszPath, pshi2->shi2_path ); NetApiBufferFree( pshi2 ); } return( dwErr ); } //+---------------------------------------------------------------------------- // // Function: DfsIsServiceRunning // // Synopsis: Check for active dfs servvice.. // // Arguments: // // Returns: [TRUE] -- if dfs service is active. // FALSE otherwise. // //----------------------------------------------------------------------------- BOOLEAN DfsIsDfsServiceRunning() { DWORD dwErr; CService cSvc; if (!(dwErr = cSvc.Init())) { dwErr = cSvc._OpenService(L"Dfs", SERVICE_QUERY_STATUS); cSvc._CloseService(); return(dwErr == 0); } return(FALSE); } //+---------------------------------------------------------------------------- // // Function: DfsGetDfsName // // Synopsis: Returns the share for a local dfs // // Arguments: [DfsRootShare] -- Name of share // // Returns: [TRUE] -- Successfully returning share path // // FALSE otherwise. // //----------------------------------------------------------------------------- BOOLEAN DfsGetDfsName( OUT LPWSTR DfsRootShare, IN OUT ULONG *Length, OUT BOOLEAN *IsFtDfs) { DWORD dwErr; ULONG SaveLength = *Length; // CService cSvc; ULONG ul = MAX_PATH; WCHAR wc[MAX_PATH]; *IsFtDfs = FALSE; #if 0 if (!(dwErr = cSvc.Init())) { dwErr = cSvc._OpenService(L"Dfs", SERVICE_QUERY_STATUS); cSvc._CloseService(); if (dwErr != 0) { return(FALSE); } } #endif CRegKey VolKey(HKEY_LOCAL_MACHINE, &dwErr, VOLUMES_DIR, KEY_READ); if (dwErr) { dprintf((DEB_ERROR,"DfsGetDfsName Failed to open VOLUMES_DIR\n")); return(FALSE); } CRegSZ RootShare((const CRegKey &)VolKey, ROOT_SHARE_VALUE_NAME); dwErr = RootShare.QueryErrorStatus(); if (dwErr) { dprintf((DEB_ERROR,"DfsGetDfsName Failed to get root share name\n")); return(FALSE); } dwErr = RootShare.GetString(DfsRootShare, Length); if (dwErr) { dprintf((DEB_ERROR,"DfsGetDfsName Failed to get root share val\n")); return(FALSE); } CRegSZ FtDfs((const CRegKey &)VolKey, FTDFS_VALUE_NAME); dwErr = FtDfs.QueryErrorStatus(); dwErr = FtDfs.GetString(wc, &ul); *IsFtDfs = (dwErr == 0); if (*IsFtDfs) { memset(DfsRootShare, 0, SaveLength); memcpy(DfsRootShare, wc, ul); *Length=ul; } dprintf((DEB_ERROR,"DfsGetDfsName is %s FTDFS\n", *IsFtDfs?"":"NOT")); return(TRUE); } //+---------------------------------------------------------------------------- // // Function: DfsNeedReboot // // Synopsis: Returns true if reboot is required for completing configuration. // // Arguments: // // Returns: [TRUE] -- Reboot Needed. // // FALSE otherwise. // //----------------------------------------------------------------------------- BOOLEAN DfsNeedReboot() { DWORD dwErr; DWORD RebootDW = 20; WCHAR buffer[20]; CRegKey RebootKey(HKEY_LOCAL_MACHINE, &dwErr, REBOOT_KEY, KEY_READ); if (dwErr = RebootKey.QueryErrorStatus()) { return(FALSE); } CRegSZ RebootVal((const CRegKey &)RebootKey, REG_VALUE_REBOOT); dwErr = RebootVal.QueryErrorStatus(); DWORD GetString( LPWSTR pwszData, ULONG *pcbData); dwErr = RebootVal.GetString(buffer, &RebootDW); dprintf((DEB_ERROR,"DfsNeedReboot is %s Needed\n", dwErr == 0?"":"NOT")); return(dwErr == 0); } //+---------------------------------------------------------------------------- // // Function: DfsStopHostingDfs // // Synopsis: Remove this machine from a machine/ft dfs. // // Arguments: // // Returns: ERROR_SUCCESS if no error // // setup error otherwise. // //----------------------------------------------------------------------------- DWORD DfsStopHostingDfs() { DWORD dwErr = 0; BOOLEAN ftDfs = FALSE; ULONG ul = MAX_PATH; WCHAR FtDfsName[MAX_PATH]; WCHAR DfsRootShare[MAX_PATH]; WCHAR wszFullObjectName[MAX_PATH]; WCHAR wszDomainName[MAX_PATH]; WCHAR wszComputerName[MAX_PATH]; if (DfsGetDfsName(FtDfsName, &ul, &ftDfs)) { if (ftDfs) { wcscpy( wszFullObjectName, LDAP_VOLUMES_DIR ); wcscat( wszFullObjectName, DOMAIN_ROOT_VOL ); dwErr = DfsInitGlobals( FtDfsName, DFS_MANAGER_FTDFS); if (dwErr) { dprintf((DEB_ERROR,"DfsStopHostingDfs init globals fail.\n")); return(dwErr); } CRegKey VolKey(HKEY_LOCAL_MACHINE, &dwErr, VOLUMES_DIR, KEY_READ); if (dwErr) { dprintf((DEB_ERROR,"DfsGetDfsName Failed to open VOLUMES_DIR\n")); return(dwErr); } CRegSZ RootShare((const CRegKey &)VolKey, ROOT_SHARE_VALUE_NAME); dwErr = RootShare.QueryErrorStatus(); if (dwErr) { dprintf((DEB_ERROR,"DfsGetDfsName Failed to get root share name\n")); return(dwErr); } ul = MAX_PATH; dwErr = RootShare.GetString(DfsRootShare, &ul); if (dwErr) { dprintf((DEB_ERROR,"DfsGetDfsName Failed to get root share val\n")); return(dwErr); } dwErr = GetDomainAndComputerName( wszDomainName, wszComputerName ); if (dwErr) { dprintf((DEB_ERROR,"DfsGetDfsName Failed computer name\n")); return(dwErr); } dwErr = DfsManagerRemoveService(wszFullObjectName, wszComputerName); if (dwErr && dwErr != NERR_DfsCantRemoveLastServerShare) { return(dwErr); } dwErr = TeardownFtDfs(DfsRootShare, FtDfsName); } if (dwErr) return(dwErr); dwErr = RemoveDfsRoot(); } if (dwErr == 0) { CRegKey RebootKey(HKEY_LOCAL_MACHINE, REBOOT_KEY, KEY_ALL_ACCESS, NULL, REG_OPTION_VOLATILE); dwErr = RebootKey.QueryErrorStatus(); if (dwErr) { dprintf((DEB_ERROR,"DfsStopHosting could not add reboot key\n")); } else { CRegDWORD rvReboot((const CRegKey &) RebootKey, REG_VALUE_REBOOT, 1); dwErr = rvReboot.QueryErrorStatus(); } } else { dprintf((DEB_ERROR,"DfsStopHosting Dfs Failed to remove dfs root\n")); } return(dwErr); } //+---------------------------------------------------------------------------- // // Function: TeardownFtDfs // // Synopsis: Removes FtDfs information from the ds. // // Arguments: wszRootShare the share hosting the dfs. // wszFTDfsName the name of the FtDfs to remove from the ds. // // // Returns: Nothing // //----------------------------------------------------------------------------- DWORD TeardownFtDfs( IN LPWSTR wszRootShare, IN LPWSTR wszFTDfsName) { DWORD dwErr = ERROR_SUCCESS; DWORD i, j; WCHAR wszDomainName[MAX_PATH]; WCHAR wszComputerName[MAX_PATH]; WCHAR wszRootSharePath[MAX_PATH]; WCHAR wszConfigurationDN[ MAX_PATH ]; WCHAR wszDfsConfigDN[ MAX_PATH ]; WCHAR wszServerShare[MAX_PATH]; PDOMAIN_CONTROLLER_INFO pDCInfo = NULL; LDAP *pldap = NULL; PLDAPMessage pMsg = NULL; LDAPModW ldapModClass, ldapModCN, ldapModPkt, ldapModPktGuid, ldapModServer; LDAP_BERVAL ldapPkt, ldapPktGuid; PLDAP_BERVAL rgModPktVals[2]; PLDAP_BERVAL rgModPktGuidVals[2]; LPWSTR rgModClassVals[2]; LPWSTR rgModCNVals[2]; LPWSTR rgModServerVals[5]; LPWSTR rgAttrs[5]; PLDAPModW rgldapMods[6]; BOOLEAN fNewFTDfs; // // We need some information before we start: // // 1. Our Domain name // // 2. Our Computer name // // 3. The share path of wszRootShare // // 4. The DN of the Configuration OU of our domain // dwErr = GetDomainAndComputerName( wszDomainName, wszComputerName ); if (dwErr != ERROR_SUCCESS) { dprintf(( DEB_ERROR, "Win32 Error %d getting Domain/Computer name\n", dwErr)); goto Cleanup; } dwErr = GetSharePath( wszRootShare, wszRootSharePath ); if (dwErr != ERROR_SUCCESS) { dprintf(( DEB_ERROR, "Win32 Error %d getting share path for %ws\n", dwErr, wszRootShare)); goto Cleanup; } dwErr = DsGetDcName( NULL, // Computer to remote to NULL, // Domain - use our own NULL, // Domain Guid NULL, // Site Guid DS_DIRECTORY_SERVICE_REQUIRED | // Flags DS_PDC_REQUIRED, &pDCInfo); // Return info if (dwErr != ERROR_SUCCESS) { dprintf(( DEB_ERROR, "DsGetDcName failed with Win32 Error %d\n", dwErr)); goto Cleanup; } pldap = ldap_initW(&pDCInfo->DomainControllerAddress[2], LDAP_PORT); if (pldap == NULL) { dprintf((DEB_ERROR, "ldap_init failed\n")); goto Cleanup; } dwErr = ldap_set_option(pldap, LDAP_OPT_AREC_EXCLUSIVE, LDAP_OPT_ON); if (dwErr != LDAP_SUCCESS) { dprintf(( DEB_ERROR, "ldap_set_option failed with ldap error %d\n", dwErr)); pldap = NULL; goto Cleanup; } dwErr = ldap_bind_s(pldap, NULL, NULL, LDAP_AUTH_SSPI); if (dwErr != LDAP_SUCCESS) { dprintf(( DEB_ERROR, "ldap_bind_s failed with ldap error %d\n", dwErr)); pldap = NULL; goto Cleanup; } rgAttrs[0] = L"defaultnamingContext"; rgAttrs[1] = NULL; dwErr = ldap_search_sW( pldap, L"", LDAP_SCOPE_BASE, L"(objectClass=*)", rgAttrs, 0, &pMsg); if (dwErr == LDAP_SUCCESS) { PLDAPMessage pEntry = NULL; PWCHAR *rgszNamingContexts = NULL; DWORD i, cNamingContexts; BOOLEAN fFoundCfg; if ((pEntry = ldap_first_entry(pldap, pMsg)) != NULL && (rgszNamingContexts = ldap_get_valuesW(pldap, pEntry, rgAttrs[0])) != NULL && (cNamingContexts = ldap_count_valuesW(rgszNamingContexts)) > 0) { wcscpy( wszConfigurationDN, *rgszNamingContexts ); fFoundCfg = TRUE; if (!fFoundCfg) { dwErr = ERROR_UNEXP_NET_ERR; } } else { dwErr = ERROR_UNEXP_NET_ERR; } if (rgszNamingContexts != NULL) ldap_value_freeW( rgszNamingContexts ); ldap_msgfree( pMsg ); } if (dwErr != ERROR_SUCCESS) { dprintf((DEB_ERROR, "TD:Unable to find Configuration naming context\n")); goto Cleanup; } // // Great, we have all the parameters now, so configure the DS // // // See if the DfsConfiguration object exists; if not, create it. // wsprintf( wszDfsConfigDN, L"CN=Dfs-Configuration,CN=System,%ws", wszConfigurationDN); rgAttrs[0] = L"cn"; rgAttrs[1] = NULL; dwErr = ldap_search_sW( pldap, wszDfsConfigDN, LDAP_SCOPE_BASE, L"(objectClass=*)", rgAttrs, 0, &pMsg); if (dwErr == LDAP_SUCCESS) ldap_msgfree( pMsg ); if (dwErr != LDAP_SUCCESS) { dprintf(( DEB_ERROR, "3: ldap_search_sW for %ws failed with LDAP error %d\n", wszDfsConfigDN, dwErr )); goto Cleanup; } // // Check to see if we are joining an FTDfs or creating a new one. // wsprintf( wszDfsConfigDN, L"CN=%ws,CN=Dfs-Configuration,CN=System,%ws", wszFTDfsName, wszConfigurationDN); wsprintf( wszServerShare, L"\\\\%ws\\%ws", wszComputerName, wszRootShare); rgAttrs[0] = L"remoteServerName"; rgAttrs[1] = NULL; dwErr = ldap_search_sW( pldap, wszDfsConfigDN, LDAP_SCOPE_BASE, L"(objectClass=*)", rgAttrs, 0, &pMsg); if (dwErr == ERROR_SUCCESS) { // // We found a Dfs object to modify/delete // LDAPMessage *pmsgServers; PWCHAR *rgServers, *rgNewServers; DWORD cServers; fNewFTDfs = FALSE; pmsgServers = ldap_first_entry(pldap, pMsg); if (pmsgServers != NULL) { rgServers = ldap_get_valuesW( pldap, pmsgServers, L"remoteServerName"); if (rgServers != NULL) { cServers = ldap_count_valuesW( rgServers ); rgNewServers = new LPWSTR [ cServers + 1 ]; if (rgNewServers != NULL) { for (i = j = 0; i < cServers; i += 1) { if (wcscmp(wszServerShare, rgServers[i]) == 0) { continue; } rgNewServers[j++] = rgServers[i]; } rgNewServers[j] = NULL; if (j) { ldapModServer.mod_op = LDAP_MOD_REPLACE; ldapModServer.mod_type = L"remoteServerName"; ldapModServer.mod_vals.modv_strvals = rgNewServers; rgldapMods[0] = &ldapModServer; rgldapMods[1] = NULL; dwErr = ldap_modify_sW(pldap, wszDfsConfigDN, rgldapMods); } else { // // Delete the Dfs metadata object. // dwErr = ldap_delete_sW( pldap, wszDfsConfigDN); } delete [] rgNewServers; } else { dwErr = ERROR_OUTOFMEMORY; } ldap_value_freeW( rgServers ); } else { dwErr = ERROR_OUTOFMEMORY; } } else { dwErr = ERROR_OUTOFMEMORY; } ldap_msgfree( pMsg ); } if (dwErr != LDAP_SUCCESS) { dprintf(( DEB_ERROR, "4: ldap_modify_s/ldap_delete_s failed for %ws with ldap error %d\n", wszDfsConfigDN, dwErr)); goto Cleanup; } Cleanup: if (pDCInfo != NULL) NetApiBufferFree( pDCInfo ); if (pldap != NULL) ldap_unbind( pldap ); return( dwErr ); }