//+---------------------------------------------------------------------------- // // Copyright (C) 1996, Microsoft Corporation // // File: localvol.cxx // // Contents: Code to validate local volume knowledge with the root server // of the Dfs // // Classes: // // Functions: DfsManagerValidateLocalVolumes // // DfspGetRemoteConfigInfo // DfspValidateLocalPartition // DfspPruneLocalPartition // StringToGuid // // History: April 29, 1996 Milans Created // //----------------------------------------------------------------------------- //#include //#include //#include //#include //#include #include #pragma hdrstop #include #include "dfsmwml.h" extern "C" NET_API_STATUS NetDfsManagerGetConfigInfo( LPWSTR wszServer, LPWSTR wszLocalVolumeEntryPath, GUID guidLocalVolume, LPDFSM_RELATION_INFO *ppDfsmRelationInfo); extern "C" NET_API_STATUS NetDfsManagerSendSiteInfo( LPWSTR wszServer, LPWSTR wszLocalVolumeEntryPath, LPDFS_SITELIST_INFO pSiteInfo); DWORD DfspGetRemoteConfigInfo( LPWSTR wszLocalVolumeEntryPath, LPWSTR wszLocalVolumeGuid, LPDFSM_RELATION_INFO *ppDfsmRelationInfo); VOID DfspValidateLocalPartition( LPWSTR wszLocalVolumeEntryPath, LPWSTR wszLocalVolumeGuid, LPDFSM_RELATION_INFO pDfsmRelationInfo); VOID DfspPruneLocalPartition( LPWSTR wszLocalVolumeEntryPath, LPWSTR wszLocalVolumeGuid); VOID StringToGuid( IN PWSTR pwszGuid, OUT GUID *pGuid); BOOLEAN DfspGetCoveredSiteInfo( LPWSTR ServerName, LPDFS_SITELIST_INFO *ppSiteInfo); //+---------------------------------------------------------------------------- // // Function: DfsManagerValidateLocalVolumes // // Synopsis: Validates the relation info of all local volumes with the // Dfs Root server // // Arguments: None // // Returns: TRUE if validation attempt succeeded, FALSE if could not // validate all local volumes // //----------------------------------------------------------------------------- extern "C" BOOLEAN DfsManagerValidateLocalVolumes() { DWORD dwErr, i; HKEY hkeyLv, hkeyThisLv; WCHAR wszLocalVolGuid[ 2 * sizeof(GUID) + 1 ]; BOOLEAN fValidateNextVolume; BOOLEAN fHaveCoveredSiteInfo; LPDFS_SITELIST_INFO pSiteInfo = NULL; if (pwszComputerName == NULL) return FALSE; // // Get covered site info // fHaveCoveredSiteInfo = DfspGetCoveredSiteInfo( pwszComputerName, &pSiteInfo); // // For each local volume, ask the root for its relation info and then // fsctl it down to the driver so it can validate its relation info. // IDfsVolInlineDebOut((DEB_TRACE, "DfsManagerValidateLocalVolumes()\n")); dwErr = RegOpenKey( HKEY_LOCAL_MACHINE, REG_KEY_LOCAL_VOLUMES, &hkeyLv); if (dwErr != ERROR_SUCCESS) { if (fHaveCoveredSiteInfo == TRUE) { MIDL_user_free(pSiteInfo); } return( FALSE ); } i = 0; do { WCHAR wszEntryPath[MAX_PATH + 1]; LPDFSM_RELATION_INFO pDfsmRelationInfo; fValidateNextVolume = TRUE; // // Local volumes are stored with their stringized guids as key names // dwErr = RegEnumKey( hkeyLv, i, wszLocalVolGuid, sizeof(wszLocalVolGuid) ); if (dwErr == ERROR_SUCCESS) { dwErr = RegOpenKey(hkeyLv, wszLocalVolGuid, &hkeyThisLv); if (dwErr == ERROR_SUCCESS) { DWORD cbBuffer = sizeof(wszEntryPath); DWORD dwType; dwErr = RegQueryValueEx( hkeyThisLv, REG_VALUE_ENTRY_PATH, NULL, &dwType, (LPBYTE) wszEntryPath, &cbBuffer); RegCloseKey( hkeyThisLv ); } } else if (dwErr == ERROR_NO_MORE_ITEMS) { fValidateNextVolume = FALSE; } if (dwErr == ERROR_SUCCESS) { dwErr = DfspGetRemoteConfigInfo( wszEntryPath, wszLocalVolGuid, &pDfsmRelationInfo); switch (dwErr) { case ERROR_SUCCESS: DfspValidateLocalPartition( wszEntryPath, wszLocalVolGuid, pDfsmRelationInfo); NetApiBufferFree(pDfsmRelationInfo); break; case NERR_DfsNoSuchVolume: case NERR_DfsNoSuchShare: DfspPruneLocalPartition( wszEntryPath, wszLocalVolGuid); break; case ERROR_NOT_ENOUGH_MEMORY: break; default: fValidateNextVolume = FALSE; break; } // // Tell the root what sites we cover // if (fHaveCoveredSiteInfo == TRUE && pwszComputerName != NULL) { NetDfsManagerSendSiteInfo( pwszComputerName, // Who's sending this wszEntryPath, // The dfs root to send to pSiteInfo); // the site info itself } } i++; } while ( fValidateNextVolume ); RegCloseKey( hkeyLv ); if (fHaveCoveredSiteInfo == TRUE) { MIDL_user_free(pSiteInfo); } IDfsVolInlineDebOut((DEB_TRACE, "DfsManagerValidateLocalVolumes: i=%d on exit\n", i)); return( TRUE ); } BOOLEAN DfspGetCoveredSiteInfo( LPWSTR ServerName, LPDFS_SITELIST_INFO *ppSiteInfo) { DWORD status; LPWSTR ThisSite; LPWSTR CoveredSites = NULL; LPDFS_SITELIST_INFO pSiteInfo = NULL; ULONG Size; ULONG cSites; LPWSTR pSiteName; LPWSTR pNames; ULONG iSite; ULONG j; DWORD dwType; DWORD dwUnused; ULONG cbBuffer; HKEY hkey; BOOLEAN fUsingDefault = TRUE; status = RegOpenKey( HKEY_LOCAL_MACHINE, REG_KEY_COVERED_SITES, &hkey); DFSM_TRACE_ERROR_HIGH(status, ALL_ERROR, DfspGetCoveredSiteInfo_Error_RegOpenKey, LOGSTATUS(status) LOGWSTR(ServerName)); if (status == ERROR_SUCCESS) { status = RegQueryInfoKey( hkey, // Key NULL, // Class string NULL, // Size of class string NULL, // Reserved &dwUnused, // # of subkeys &dwUnused, // max size of subkey name &dwUnused, // max size of class name &dwUnused, // # of values &dwUnused, // max size of value name &cbBuffer, // max size of value data, NULL, // security descriptor NULL); // Last write time DFSM_TRACE_ERROR_HIGH(status, ALL_ERROR, DfspGetCoveredSiteInfo_Error_RegQueryInfoKey, LOGSTATUS(status) LOGWSTR(ServerName)); // // Check if there's a value the same name as the servername passed in, // if so, use it. Else default to value REG_VALUE_COVERED_SITES. // if (status == ERROR_SUCCESS) { CoveredSites = (LPWSTR)MIDL_user_allocate(cbBuffer); if (CoveredSites != NULL) { status = RegQueryValueEx( hkey, ServerName, NULL, &dwType, (PUCHAR)CoveredSites, &cbBuffer); DFSM_TRACE_ERROR_HIGH(status, ALL_ERROR, DfspGetCoveredSiteInfo_Error_RegQueryValueEx, LOGSTATUS(status) LOGWSTR(ServerName)); if (status == ERROR_SUCCESS && dwType == REG_MULTI_SZ) { fUsingDefault = FALSE; } else { status = RegQueryValueEx( hkey, REG_VALUE_COVERED_SITES, NULL, &dwType, (PUCHAR)CoveredSites, &cbBuffer); DFSM_TRACE_ERROR_HIGH(status, ALL_ERROR, DfspGetCoveredSiteInfo_Error_RegQueryValueEx2, LOGSTATUS(status) LOGWSTR(ServerName)); if ( status != ERROR_SUCCESS || dwType != REG_MULTI_SZ) { MIDL_user_free(CoveredSites); CoveredSites = NULL; } } } } RegCloseKey( hkey ); } // // Size the return buffer // Size = 0; for (cSites = 0, pNames = CoveredSites; pNames && *pNames; cSites++) { Size += (wcslen(pNames) + 1) * sizeof(WCHAR); pNames += wcslen(pNames) + 1; } // // Get site we belong to, if we're using the defaults // ThisSite = NULL; if (fUsingDefault == TRUE) { status = DsGetSiteName(NULL, &ThisSite); DFSM_TRACE_ERROR_HIGH(status, ALL_ERROR, DfspGetCoveredSiteInfo_Error_DsGetSiteName, LOGSTATUS(status) LOGWSTR(ServerName)); if (status == NO_ERROR && ThisSite != NULL) { Size += (wcslen(ThisSite) + 1) * sizeof(WCHAR); cSites++; } } // // If no sites are configured, and we couldn't determine our site, // then we fail. // if (cSites == 0) { goto ErrorReturn; } Size += FIELD_OFFSET(DFS_SITELIST_INFO,Site[cSites]); pSiteInfo = (LPDFS_SITELIST_INFO)MIDL_user_allocate(Size); if (pSiteInfo == NULL) { goto ErrorReturn; } RtlZeroMemory(pSiteInfo, Size); pSiteInfo->cSites = cSites; pSiteName = (LPWSTR) ((PCHAR)pSiteInfo + sizeof(DFS_SITELIST_INFO) + sizeof(DFS_SITENAME_INFO) * (cSites - 1)); // // Marshall the site strings into the buffer // iSite = 0; if (ThisSite != NULL) { wcscpy(pSiteName, ThisSite); pSiteInfo->Site[iSite].SiteFlags = DFS_SITE_PRIMARY; pSiteInfo->Site[iSite++].SiteName = pSiteName; pSiteName += wcslen(ThisSite) + 1; } for (pNames = CoveredSites; pNames && *pNames; pNames += wcslen(pNames) + 1) { wcscpy(pSiteName, pNames); pSiteInfo->Site[iSite++].SiteName = pSiteName; pSiteName += wcslen(pSiteName) + 1; } *ppSiteInfo = pSiteInfo; if (CoveredSites != NULL) { MIDL_user_free(CoveredSites); } return TRUE; ErrorReturn: // // Free anything we allocated // if (pSiteInfo != NULL) { MIDL_user_free(pSiteInfo); } if (CoveredSites != NULL) { MIDL_user_free(CoveredSites); } return FALSE; } //+---------------------------------------------------------------------------- // // Function: DfspGetRemoteConfigInfo // // Synopsis: Gets the config info for a local volume from the Dfs root // server. // // Arguments: [wszLocalVolumeEntryPath] -- Entry path of local volume. // // [wszLocalVolumeGuid] -- Stringized guid of local volume. // // [ppDfsmRelationInfo] -- On successful return, contains pointer // to allocated DFSM_RELATION_INFO structure. // // Returns: Error code from NetDfsManagerGetConfigInfo or // //----------------------------------------------------------------------------- DWORD DfspGetRemoteConfigInfo( LPWSTR wszLocalVolumeEntryPath, LPWSTR wszLocalVolumeGuid, LPDFSM_RELATION_INFO *ppDfsmRelationInfo) { DWORD dwErr; GUID guidLocalVolume; if (pwszComputerName == NULL) return ERROR_INVALID_PARAMETER; StringToGuid( wszLocalVolumeGuid, &guidLocalVolume ); dwErr = NetDfsManagerGetConfigInfo( pwszComputerName, wszLocalVolumeEntryPath, guidLocalVolume, ppDfsmRelationInfo); DFSM_TRACE_ERROR_HIGH(dwErr, ALL_ERROR, DfspGetRemoteConfigInfo_Error_NetDfsManagerGetConfigInfo, LOGSTATUS(dwErr) LOGWSTR(wszLocalVolumeEntryPath)); return( dwErr ); } //+---------------------------------------------------------------------------- // // Function: DfspValidateLocalPartition // // Synopsis: Given a remote config info, this API will fsctl to the local // dfs driver to take actions and match up its local volume info // with the remote one. // // Arguments: [wszLocalVolumeEntryPath] -- local volume entry path to // validate // [wszLocalVolumeGuid] -- Guid of local volume to validate // [pDfsmRelationInfo] -- The DFSM_RELATION_INFO that this local // volume should have. // // Returns: Nothing // //----------------------------------------------------------------------------- VOID DfspValidateLocalPartition( LPWSTR wszLocalVolumeEntryPath, LPWSTR wszLocalVolumeGuid, LPDFSM_RELATION_INFO pDfsmRelationInfo) { DFS_PKT_RELATION_INFO DfsRelationInfo; DWORD i; // // Massage the DFSM_RELATION_INFO into a DFS_PKT_RELATION_INFO // StringToGuid( wszLocalVolumeGuid, &DfsRelationInfo.EntryId.Uid ); RtlInitUnicodeString( &DfsRelationInfo.EntryId.Prefix, wszLocalVolumeEntryPath); RtlInitUnicodeString( &DfsRelationInfo.EntryId.ShortPrefix, NULL ); DfsRelationInfo.SubordinateIdList = new DFS_PKT_ENTRY_ID[ pDfsmRelationInfo->cSubordinates ]; if (DfsRelationInfo.SubordinateIdList == NULL) return; DfsRelationInfo.SubordinateIdCount = pDfsmRelationInfo->cSubordinates; for (i = 0; i < pDfsmRelationInfo->cSubordinates; i++) { DfsRelationInfo.SubordinateIdList[i].Uid = pDfsmRelationInfo->eid[i].idSubordinate; RtlInitUnicodeString( &DfsRelationInfo.SubordinateIdList[i].Prefix, pDfsmRelationInfo->eid[i].wszSubordinate); RtlInitUnicodeString( &DfsRelationInfo.SubordinateIdList[i].ShortPrefix, NULL); } PktValidateLocalVolumeInfo( &DfsRelationInfo ); } //+---------------------------------------------------------------------------- // // Function: DfspPruneLocalPartition // // Synopsis: Deletes a local volume that the root server says is an extra // volume. // // Arguments: [wszLocalVolumeEntryPath] -- local volume entry path to // delete // [wszLocalVolumeGuid] -- Guid of local volume to delete // // Returns: Nothing // //----------------------------------------------------------------------------- VOID DfspPruneLocalPartition( LPWSTR wszLocalVolumeEntryPath, LPWSTR wszLocalVolumeGuid) { DFS_PKT_ENTRY_ID EntryId; RtlZeroMemory(&EntryId, sizeof(EntryId)); StringToGuid( wszLocalVolumeGuid, &EntryId.Uid ); RtlInitUnicodeString( &EntryId.Prefix, wszLocalVolumeEntryPath ); PktPruneLocalPartition( &EntryId ); } //+---------------------------------------------------------------------------- // // Function: StringToGuid // // Synopsis: Converts a 32 wchar null terminated string to a GUID. // // Arguments: [pwszGuid] -- the string to convert // [pGuid] -- Pointer to destination GUID. // // Returns: Nothing // //----------------------------------------------------------------------------- #define HEX_DIGIT_TO_INT(d, i) \ ASSERT(((d) >= L'0' && (d) <= L'9') || \ ((d) >= L'A' && (d) <= L'F')); \ if ((d) <= L'9') { \ i = (d) - L'0'; \ } else { \ i = (d) - L'A' + 10; \ } VOID StringToGuid( IN PWSTR pwszGuid, OUT GUID *pGuid) { PBYTE pbBuffer = (PBYTE) pGuid; USHORT i, n; for (i = 0; i < sizeof(GUID); i++) { HEX_DIGIT_TO_INT(pwszGuid[2 * i], n); pbBuffer[i] = n << 4; HEX_DIGIT_TO_INT(pwszGuid[2 * i + 1], n); pbBuffer[i] |= n; } }