//-------------------------------------------------------------------------- // // Copyright (C) 1999, Microsoft Corporation // // File: stdsup.cxx // //-------------------------------------------------------------------------- #define UNICODE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "struct.hxx" #include "rootsup.hxx" #include "dfsacl.hxx" #include "misc.hxx" #include "messages.h" #include "struct.hxx" #include "ftsup.hxx" #include "stdsup.hxx" DWORD PutSiteTable( HKEY hKey, PDFS_VOLUME_LIST pDfsVolList); DWORD DfsRecoverVolList( PDFS_VOLUME_LIST pDfsVolList); DWORD DfsRegDeleteKeyAndChildren( HKEY hkey, LPWSTR s); DWORD DfsGetStdVol( HKEY rKey, PDFS_VOLUME_LIST pDfsVolList) { HKEY hKey = NULL; DWORD dwErr; LPWSTR *pNames = NULL; ULONG cKeys = 0; ULONG i; WCHAR VolumesDir[MAX_PATH+1]; wcscpy(VolumesDir, VOLUMES_DIR); wcscat(VolumesDir, L"domainroot"); dwErr = RegOpenKey( rKey, VolumesDir, &hKey); if (dwErr != ERROR_SUCCESS) { MyPrintf(L"Not a StdDfs root!\r\n"); goto Cleanup; } dwErr = EnumKeys( hKey, &cKeys, &pNames); if (dwErr != ERROR_SUCCESS) { MyPrintf(L"No exit points...\r\n"); goto SiteInfo; } pDfsVolList->Version = 3; pDfsVolList->VolCount = cKeys+1; pDfsVolList->Volumes = (PDFS_VOLUME *)malloc((cKeys+1) * sizeof(PDFS_VOLUME)); if (pDfsVolList->Volumes == NULL) { dwErr = ERROR_OUTOFMEMORY; goto Cleanup; } pDfsVolList->AllocatedVolCount = cKeys + 1; RtlZeroMemory(pDfsVolList->Volumes, pDfsVolList->AllocatedVolCount * sizeof(PDFS_VOLUME)); pDfsVolList->Volumes[0] = (PDFS_VOLUME) malloc(sizeof(DFS_VOLUME)); if (pDfsVolList->Volumes[0] == NULL) { dwErr = ERROR_OUTOFMEMORY; goto Cleanup; } RtlZeroMemory(pDfsVolList->Volumes[0], sizeof(DFS_VOLUME)); dwErr = GetDfsKey( rKey, L"domainroot", pDfsVolList->Volumes[0]); for (i = 0; i < cKeys; i++) { wcscpy(VolumesDir, L"domainroot\\"); wcscat(VolumesDir, pNames[i]); pDfsVolList->Volumes[i+1] = (PDFS_VOLUME) malloc(sizeof(DFS_VOLUME)); if (pDfsVolList->Volumes[i+1] == NULL) { dwErr = ERROR_OUTOFMEMORY; goto Cleanup; } RtlZeroMemory(pDfsVolList->Volumes[i+1], sizeof(DFS_VOLUME)); dwErr = GetDfsKey( rKey, VolumesDir, pDfsVolList->Volumes[i+1]); } // // Do any recovery needed // dwErr = DfsRecoverVolList(pDfsVolList); RegCloseKey(hKey); hKey = NULL; pDfsVolList->DfsType = STDDFS; SiteInfo: // // Site information // wcscpy(VolumesDir, VOLUMES_DIR); wcscat(VolumesDir, L"siteroot"); dwErr = RegOpenKey( rKey, VolumesDir, &hKey); if (dwErr != ERROR_SUCCESS) { dwErr = ERROR_SUCCESS; goto Cleanup; } dwErr = GetSiteTable( hKey, pDfsVolList); if (dwErr != ERROR_SUCCESS) { MyPrintf(L"Missing siteroot key (non-fatal error)\r\n"); dwErr = ERROR_SUCCESS; } Cleanup: FreeNameList( pNames, cKeys); pNames = NULL; if (hKey != NULL) RegCloseKey(hKey); return dwErr; } DWORD GetDfsKey( HKEY rKey, LPWSTR wszKeyName, PDFS_VOLUME pVolume) { DWORD dwErr = 0; HKEY hKey = NULL; ULONG cRepl; WCHAR VolumesDir[MAX_PATH+1]; wcscpy(VolumesDir, VOLUMES_DIR); wcscat(VolumesDir, wszKeyName); if (fSwDebug == TRUE) MyPrintf(L"GetDfsKey(%ws)\r\n", VolumesDir); dwErr = RegOpenKey( rKey, VolumesDir, &hKey); if (dwErr != ERROR_SUCCESS) { if (fSwDebug == TRUE) MyPrintf(L"RegOpenKey(%ws) returned %d\r\n", VolumesDir, dwErr); goto Cleanup; } // // Id (Prefix, Type, state, etc) // wcscpy(VolumesDir, L"\\"); wcscat(VolumesDir, wszKeyName); GIP_DUPLICATE_STRING(dwErr, VolumesDir, &pVolume->wszObjectName); if (dwErr != ERROR_SUCCESS) { if (fSwDebug == TRUE) MyPrintf(L"DUP_STRING(%ws) returned %d\r\n", VolumesDir, dwErr); goto Cleanup; } dwErr = GetIdProps( hKey, &pVolume->dwType, &pVolume->dwState, &pVolume->wszPrefix, &pVolume->wszShortPrefix, &pVolume->idVolume, &pVolume->wszComment, &pVolume->dwTimeout, &pVolume->ftPrefix, &pVolume->ftState, &pVolume->ftComment); if (dwErr != ERROR_SUCCESS) { if (fSwDebug == TRUE) MyPrintf(L"GetIdProps() returned %d\r\n", dwErr); goto Cleanup; } // // Services (replicas) // dwErr = GetSvcProps( hKey, pVolume); if (dwErr != ERROR_SUCCESS) { if (fSwDebug == TRUE) MyPrintf(L"GetSvcProps() returned %d\r\n", dwErr); goto Cleanup; } dwErr = GetVersionProps( hKey, VERSION_PROPS, &pVolume->dwVersion); if (dwErr != ERROR_SUCCESS) { if (fSwDebug == TRUE) MyPrintf(L"GetVersionProps() returned %d\r\n", dwErr); goto Cleanup; } dwErr = GetRecoveryProps( hKey, RECOVERY_PROPS, &pVolume->cbRecovery, &pVolume->pRecovery); if (dwErr != ERROR_SUCCESS) { if (fSwDebug == TRUE) MyPrintf(L"GetRecoveryProps() returned %d\r\n", dwErr); goto Cleanup; } Cleanup: if (hKey != NULL) RegCloseKey(hKey); if (fSwDebug == TRUE) MyPrintf(L"GetDfsKey exit %d\r\n", dwErr); return( dwErr ); } DWORD ReadSiteTable(PBYTE pBuffer, ULONG cbBuffer) { DWORD dwErr; ULONG cObjects = 0; ULONG cbThisObj; ULONG i; ULONG j; PLIST_ENTRY pListHead, pLink; PDFSM_SITE_ENTRY pSiteInfo; MARSHAL_BUFFER marshalBuffer; GUID guid; ULONG Size; dwErr = ERROR_SUCCESS; if (dwErr == ERROR_SUCCESS && cbBuffer >= sizeof(ULONG)) { // // Unmarshall all the objects (NET_DFS_SITENAME_INFO's) in the buffer // MarshalBufferInitialize( &marshalBuffer, cbBuffer, pBuffer); DfsRtlGetGuid(&marshalBuffer, &guid); DfsRtlGetUlong(&marshalBuffer, &cObjects); for (j = 0; j < cObjects; j++) { pSiteInfo = (PDFSM_SITE_ENTRY) new BYTE [cbBuffer-sizeof(ULONG)]; if (pSiteInfo == NULL) { dwErr = ERROR_OUTOFMEMORY; goto Cleanup; } dwErr = DfsRtlGet(&marshalBuffer,&MiDfsmSiteEntry, pSiteInfo); Size = (ULONG)((PCHAR)&pSiteInfo->Info.Site[pSiteInfo->Info.cSites] - (PCHAR)pSiteInfo); } } Cleanup: return dwErr; } //+---------------------------------------------------------------------------- // // Function: GetIdProps // // Synopsis: Retrieves the Id Properties of a Dfs Manager volume object. // // Arguments: // // Returns: [S_OK] -- Successfully retrieved the properties. // // [DFS_E_VOLUME_OBJECT_CORRUPT] -- The stored properties could // not be parsed properly. // // [DFS_E_INCONSISTENT] -- Another volume object seems to have // the same prefix! // // [ERROR_OUTOFMEMORY] -- Unable to allocate memory for properties // or other uses. // // DWORD from DfsmQueryValue // //----------------------------------------------------------------------------- DWORD GetIdProps( HKEY hKey, PULONG pdwType, PULONG pdwState, LPWSTR *ppwszPrefix, LPWSTR *ppwszShortPath, GUID *pidVolume, LPWSTR *ppwszComment, PULONG pdwTimeout, FILETIME *pftPrefix, FILETIME *pftState, FILETIME *pftComment) { DWORD dwErr; NTSTATUS status; DWORD dwType; DWORD cbBuffer; ULONG dwTimeout; PBYTE pBuffer = NULL; MARSHAL_BUFFER marshalBuffer; DFS_ID_PROPS idProps; if (fSwDebug == TRUE) MyPrintf(L"GetIdProps()\r\n"); *ppwszPrefix = NULL; *ppwszComment = NULL; dwErr = GetBlobByValue( hKey, ID_PROPS, &pBuffer, &cbBuffer); if (dwErr != ERROR_SUCCESS) goto Cleanup; MarshalBufferInitialize(&marshalBuffer, cbBuffer, pBuffer); status = DfsRtlGet(&marshalBuffer, &MiDfsIdProps, &idProps); if (NT_SUCCESS(status)) { GIP_DUPLICATE_PREFIX( dwErr, idProps.wszPrefix, ppwszPrefix ); if (dwErr == ERROR_SUCCESS) { GIP_DUPLICATE_PREFIX( dwErr, idProps.wszShortPath, ppwszShortPath ); } if (dwErr == ERROR_SUCCESS) { GIP_DUPLICATE_STRING( dwErr, idProps.wszComment, ppwszComment); } // // There are two possible versions of the blob. One has the timeout // after all the other stuff, the other doesn't. // So, if there are sizeof(ULONG) bytes left in the blob, // assume it is the timeout. Otherwise this is an old // version of the blob, and the timeout isn't here, so we set it to // the global value. idProps.dwTimeout = GTimeout; if ( (marshalBuffer.Current < marshalBuffer.Last) && (marshalBuffer.Last - marshalBuffer.Current) == sizeof(ULONG) ) { DfsRtlGetUlong(&marshalBuffer, &idProps.dwTimeout); } if (dwErr == ERROR_SUCCESS) { *pdwType = idProps.dwType; *pdwState = idProps.dwState; *pidVolume = idProps.idVolume; *pdwTimeout = idProps.dwTimeout; *pftPrefix = idProps.ftEntryPath; *pftState = idProps.ftState; *pftComment = idProps.ftComment; } if (dwErr != ERROR_SUCCESS) { if (*ppwszPrefix != NULL) { delete [] *ppwszPrefix; *ppwszPrefix = NULL; } if (*ppwszShortPath != NULL) { delete [] *ppwszShortPath; *ppwszShortPath = NULL; } if (*ppwszComment != NULL) { delete [] *ppwszComment; *ppwszComment = NULL; } } if (idProps.wszPrefix != NULL) MarshalBufferFree(idProps.wszPrefix); if (idProps.wszShortPath != NULL) MarshalBufferFree(idProps.wszShortPath); if (idProps.wszComment != NULL) MarshalBufferFree(idProps.wszComment); } else { if (status == STATUS_INSUFFICIENT_RESOURCES) { dwErr = ERROR_OUTOFMEMORY; } else { dwErr = NERR_DfsInternalCorruption; } } Cleanup: if (pBuffer != NULL) delete [] pBuffer; if (fSwDebug == TRUE) MyPrintf(L"GetIdProps exit %d\r\n", dwErr); return( dwErr ); } DWORD DfsSetStdVol( HKEY rKey, PDFS_VOLUME_LIST pDfsVolList) { HKEY hKey = NULL; DWORD dwErr = ERROR_SUCCESS; DWORD dwErr2 = ERROR_SUCCESS; ULONG i; PDFS_VOLUME pVol; PWCHAR wCp; WCHAR FolderDir[MAX_PATH+1]; if (fSwDebug == TRUE) MyPrintf(L"DfsSetStdVol()\r\n"); wcscpy(FolderDir, VOLUMES_DIR); wcscat(FolderDir, L"domainroot"); dwErr = RegOpenKey( rKey, FolderDir, &hKey); if (dwErr != ERROR_SUCCESS) { MyPrintf(L"Not a StdDfs root!\r\n"); goto Cleanup; } // // Loop through all the dfs links and if the modify bit is set, // create an entry in the registry. If the delete bit is set, // delete the entry. // // On error we continue, but capture the error which will // later be returned. // for (i = 1; i < pDfsVolList->VolCount; i++) { pVol = pDfsVolList->Volumes[i]; if ((pVol->vFlags & VFLAGS_DELETE) != 0) { for (wCp = &pVol->wszObjectName[1]; *wCp != NULL && *wCp != UNICODE_PATH_SEP; wCp++) NOTHING; wCp++; dwErr = RegDeleteKey(hKey, wCp); } else if ((pVol->vFlags & VFLAGS_MODIFY) != 0) { dwErr = SetDfsKey(hKey, pVol->wszObjectName, pVol); } else { dwErr = ERROR_SUCCESS; } if (dwErr != ERROR_SUCCESS) dwErr2 = dwErr; } RegCloseKey(hKey); hKey = NULL; // // Write site table only if it has changed // if ((pDfsVolList->sFlags & VFLAGS_MODIFY) != 0 || pDfsVolList->SiteCount > 0) { wcscpy(FolderDir, VOLUMES_DIR); wcscat(FolderDir, L"siteroot"); dwErr = RegOpenKey( rKey, FolderDir, &hKey); if (dwErr != ERROR_SUCCESS) { MyPrintf(L"Can not open siteroot\r\n"); goto Cleanup; } dwErr2 = PutSiteTable(hKey, pDfsVolList); } Cleanup: if (hKey != NULL) RegCloseKey(hKey); if (fSwDebug == TRUE) MyPrintf(L"DfsSetStdVol() exit %d\r\n", dwErr2); return dwErr2; } DWORD SetDfsKey( HKEY rKey, LPWSTR wszKeyName, PDFS_VOLUME pVolume) { DWORD dwErr = ERROR_SUCCESS; HKEY hKey = NULL; PWCHAR wCp; if (fSwDebug == TRUE) MyPrintf(L"SetDfsKey(%ws)\r\n", wszKeyName); for (wCp = &wszKeyName[1]; *wCp != NULL && *wCp != UNICODE_PATH_SEP; wCp++) NOTHING; if (*wCp != UNICODE_PATH_SEP) { dwErr = ERROR_INVALID_PARAMETER; goto Cleanup; } wCp++; dwErr = RegCreateKey( rKey, wCp, &hKey); if (dwErr != ERROR_SUCCESS) { if (fSwDebug == TRUE) MyPrintf(L"RegCreateKey(%ws) returned %d\r\n", wCp, dwErr); goto Cleanup; } dwErr = SetIdProps( hKey, pVolume->dwType, pVolume->dwState, pVolume->wszPrefix, pVolume->wszShortPrefix, pVolume->idVolume, pVolume->wszComment, pVolume->dwTimeout, pVolume->ftPrefix, pVolume->ftState, pVolume->ftComment); if (dwErr != ERROR_SUCCESS) { if (fSwDebug == TRUE) MyPrintf(L"SetIdProps() returned %d\r\n", dwErr); goto Cleanup; } // // Services (replicas) // dwErr = SetSvcProps( hKey, pVolume); if (dwErr != ERROR_SUCCESS) { if (fSwDebug == TRUE) MyPrintf(L"SetSvcProps() returned %d\r\n", dwErr); goto Cleanup; } dwErr = SetVersionProps( hKey, pVolume); if (dwErr != ERROR_SUCCESS) { if (fSwDebug == TRUE) MyPrintf(L"SetVersionProps() returned %d\r\n", dwErr); goto Cleanup; } dwErr = SetRecoveryProps( hKey, pVolume); if (dwErr != ERROR_SUCCESS) { if (fSwDebug == TRUE) MyPrintf(L"SetRecoveryProps() returned %d\r\n", dwErr); goto Cleanup; } Cleanup: if (hKey != NULL) RegCloseKey(hKey); if (fSwDebug == TRUE) MyPrintf(L"SetDfsKey exit %d\r\n", dwErr); return( dwErr ); } //+---------------------------------------------------------------------------- // // Function: SetIdProps // // Synopsis: Sets the Id Properties of a Dfs Manager volume object. // // Arguments: // // Returns: [S_OK] -- Successfully retrieved the properties. // // [ERROR_OUTOFMEMORY] -- Unable to allocate memory for properties // or other uses. // //----------------------------------------------------------------------------- DWORD SetIdProps( HKEY hKey, ULONG dwType, ULONG dwState, LPWSTR pwszPrefix, LPWSTR pwszShortPath, GUID idVolume, LPWSTR pwszComment, ULONG dwTimeout, FILETIME ftPrefix, FILETIME ftState, FILETIME ftComment) { // prefix bug 447510; initialize dwerr DWORD dwErr = ERROR_SUCCESS; NTSTATUS status; DWORD cbBuffer; PBYTE pBuffer = NULL; MARSHAL_BUFFER marshalBuffer; DFS_ID_PROPS idProps; idProps.wszPrefix = wcschr( &pwszPrefix[1], UNICODE_PATH_SEP ); idProps.wszShortPath = wcschr( &pwszShortPath[1], UNICODE_PATH_SEP ); idProps.idVolume = idVolume; idProps.dwState = dwState; idProps.dwType = dwType; idProps.wszComment = pwszComment; idProps.dwTimeout = dwTimeout; idProps.ftEntryPath = ftPrefix; idProps.ftState = ftState; idProps.ftComment = ftComment; cbBuffer = 0; status = DfsRtlSize( &MiDfsIdProps, &idProps, &cbBuffer ); if (NT_SUCCESS(status)) { // // Add extra bytes for the timeout, which will go at the end // cbBuffer += sizeof(ULONG); pBuffer = new BYTE [cbBuffer]; if (pBuffer != NULL) { MarshalBufferInitialize( &marshalBuffer, cbBuffer, pBuffer); status = DfsRtlPut( &marshalBuffer, &MiDfsIdProps, &idProps ); DfsRtlPutUlong(&marshalBuffer, &dwTimeout); if (NT_SUCCESS(status)) { dwErr = SetBlobByValue( hKey, ID_PROPS, pBuffer, cbBuffer); } } } if (pBuffer != NULL) delete [] pBuffer; return( dwErr ); } DWORD SetSvcProps( HKEY hKey, PDFS_VOLUME pVol) { DWORD cbBuffer; DWORD dwErr = ERROR_SUCCESS; PBYTE Buffer = NULL; PBYTE pBuf = NULL; ULONG *Size = NULL; ULONG *pSize = NULL; ULONG TotalSize = 0; ULONG i; if (fSwDebug == TRUE) MyPrintf(L"SetSvcProps(%ws)\r\n", pVol->wszObjectName); pSize = Size = (PULONG) malloc(sizeof(ULONG) * (pVol->ReplCount + pVol->DelReplCount)); if (Size == NULL) { dwErr = ERROR_OUTOFMEMORY; goto Cleanup; } // // Need all the size values now and later for marshalling stuff. // So we collect them here into an array. // TotalSize = 0; for (i = 0; i < pVol->ReplCount; i++) { *pSize = GetReplicaMarshalSize(&pVol->ReplicaInfo[i], &pVol->FtModification[i]); TotalSize += *pSize; pSize++; } for (i = 0; i < pVol->DelReplCount; i++) { *pSize = GetReplicaMarshalSize(&pVol->DelReplicaInfo[i], &pVol->DelFtModification[i]); TotalSize += *pSize; pSize++; } // // Allocate the byte Buffer we need // // TotalSize is the size required marshal all the replicas and // their last-modification-timestamps. // // In addition, we need: // // 1 ULONG for storing the count of replicas // ReplCount ULONGs for storing the marshal size of each replica. // TotalSize += sizeof(ULONG) * (1 + pVol->ReplCount + 1 + pVol->DelReplCount); Buffer = pBuf = (PBYTE) malloc(TotalSize); if (Buffer == NULL) { dwErr = ERROR_OUTOFMEMORY; goto Cleanup; } // // Set the number of entries to follow in the Buffer at the start. // _PutULong(pBuf, pVol->ReplCount); pBuf += sizeof(ULONG); pSize = Size; for (i = 0; i < pVol->ReplCount; i++) { // // Marshall each replica Entry into the Buffer. // Remember we first need to put the size of the marshalled // replica entry to follow, then the FILETIME for the replica, // and finally, the marshalled replica entry structure. // _PutULong(pBuf, *pSize); pBuf += sizeof(ULONG); dwErr = SerializeReplica( &pVol->ReplicaInfo[i], pVol->FtModification ? &pVol->FtModification[i] : NULL, pBuf, *pSize); if (dwErr != ERROR_SUCCESS) goto Cleanup; pBuf += *pSize; pSize++; } // // Now the deleted replicas // _PutULong(pBuf, pVol->DelReplCount); pBuf += sizeof(ULONG); for (i = 0; i < pVol->DelReplCount; i++) { _PutULong(pBuf, *pSize); pBuf += sizeof(ULONG); dwErr = SerializeReplica( &pVol->DelReplicaInfo[i], pVol->DelFtModification ? &pVol->DelFtModification[i] : NULL, pBuf, *pSize); if (dwErr != ERROR_SUCCESS) goto Cleanup; pBuf += *pSize; pSize++; } dwErr = SetBlobByValue( hKey, SVC_PROPS, Buffer, TotalSize); Cleanup: if (Buffer != NULL) delete [] Buffer; if (Size != NULL) delete [] Size; if (fSwDebug == TRUE) MyPrintf(L"SetSvcProps exit %d\n", dwErr); return dwErr; } DWORD SetVersionProps( HKEY hKey, PDFS_VOLUME pVol) { DWORD dwErr = ERROR_SUCCESS; if (fSwDebug == TRUE) MyPrintf(L"SetVersionProps(%ws)\r\n", pVol->wszObjectName); dwErr = RegSetValueEx( hKey, VERSION_PROPS, NULL, REG_DWORD, (LPBYTE) &pVol->dwVersion, sizeof(DWORD)); if (fSwDebug == TRUE) MyPrintf(L"SetVersionProps exit %d\n", dwErr); return dwErr; } DWORD SetRecoveryProps( HKEY hKey, PDFS_VOLUME pVol) { DWORD dwErr = ERROR_SUCCESS; DWORD dwRecovery = 0; if (fSwDebug == TRUE) MyPrintf(L"SetRecoveryProps(%ws)\r\n", pVol->wszObjectName); dwErr = RegSetValueEx( hKey, RECOVERY_PROPS, NULL, REG_BINARY, (LPBYTE) &dwRecovery, sizeof(DWORD)); if (fSwDebug == TRUE) MyPrintf(L"SetRecoveryProps exit %d\n", dwErr); return dwErr; } DWORD PutSiteTable( HKEY hKey, PDFS_VOLUME_LIST pDfsVolList) { DWORD dwErr; DWORD cbBuffer; PBYTE pBuffer = NULL; ULONG cObjects; ULONG i; PLIST_ENTRY pListHead, pLink; PDFSM_SITE_ENTRY pSiteInfo; MARSHAL_BUFFER marshalBuffer; GUID SiteTableGuid = {0}; if (fSwDebug == TRUE) MyPrintf(L"PutSiteTable()\n"); // // Create a new Guid // dwErr = UuidCreate(&SiteTableGuid); if(dwErr != RPC_S_OK){ // couldn't create a valid uuid goto Cleanup; } // // The cObjects count // cbBuffer = sizeof(ULONG) + sizeof(GUID); // // Add up the number of entries we need to store, and the total size of all // of them. // cObjects = 0; pListHead = &pDfsVolList->SiteList; for (pLink = pListHead->Flink; pLink != pListHead; pLink = pLink->Flink) { pSiteInfo = CONTAINING_RECORD(pLink, DFSM_SITE_ENTRY, Link); DfsRtlSize(&MiDfsmSiteEntry, pSiteInfo, &cbBuffer); cObjects++; } // // Get a buffer big enough // pBuffer = (PBYTE) malloc(cbBuffer); if (pBuffer == NULL) { dwErr = ERROR_OUTOFMEMORY; goto Cleanup; } // // Put the guid, then the object count in the beginning of the buffer // MarshalBufferInitialize( &marshalBuffer, cbBuffer, pBuffer); DfsRtlPutGuid(&marshalBuffer, &SiteTableGuid); DfsRtlPutUlong(&marshalBuffer, &cObjects); // // Walk the linked list of objects, marshalling them into the buffer. // for (pLink = pListHead->Flink; pLink != pListHead; pLink = pLink->Flink) { pSiteInfo = CONTAINING_RECORD(pLink, DFSM_SITE_ENTRY, Link); DfsRtlPut(&marshalBuffer,&MiDfsmSiteEntry, pSiteInfo); } // // Write the site table binary blob // dwErr = RegSetValueEx( hKey, SITE_VALUE_NAME, NULL, REG_BINARY, pBuffer, cbBuffer); Cleanup: if (pBuffer) free(pBuffer); if (fSwDebug == TRUE) MyPrintf(L"PutSiteTable exit %d\n", dwErr); return dwErr; } //+---------------------------------------------------------------------------- // // Function: DfsmQueryValue // // Synopsis: Helper function that calls RegQueryValueEx and verifies that // the returned type is equal to the expected type. // // Arguments: [hkey] -- Handle to key // [wszValueName] -- Name of value to read // [dwExpectedType] -- Expected type of value // [dwExpectedSize] -- Expected size of read in value. If // this is nonzero, this routine will return an error // if the read-in size is not equal to expected size. // If this is 0, no checking is performed. // [pBuffer] -- To receive the value data // [pcbBuffer] -- On call, size of pBuffer. On successful return, // the size of data read in // // Returns: [ERROR_SUCCESS] -- Successfully read the value data. // // [DFS_E_VOLUME_OBJECT_CORRUPT] -- If read-in type did not // match dwExpectedType, or if dwExpectedSize was // nonzero and the read-in size did not match it. // // DWORD_FROM_WIN32 of RegQueryValueEx return code. // //----------------------------------------------------------------------------- DWORD DfsmQueryValue( HKEY hkey, LPWSTR wszValueName, DWORD dwExpectedType, DWORD dwExpectedSize, PBYTE pBuffer, LPDWORD pcbBuffer) { DWORD dwErr; DWORD dwType; dwErr = RegQueryValueEx( hkey, wszValueName, NULL, &dwType, pBuffer, pcbBuffer); if (dwErr == ERROR_SUCCESS) { if (dwExpectedType != dwType) { dwErr = NERR_DfsInternalCorruption; } else if (dwExpectedSize != 0 && dwExpectedSize != *pcbBuffer) { dwErr = NERR_DfsInternalCorruption; } else { dwErr = ERROR_SUCCESS; } } return( dwErr ); } //+---------------------------------------------------------------------------- // // Function: GetBlobByValue // // Synopsis: Retrieves a property of type Binary from the value wszProperty // // Arguments: // // Returns: // //----------------------------------------------------------------------------- DWORD GetBlobByValue( HKEY hKey, LPWSTR wszProperty, PBYTE *ppBuffer, PULONG pcbBuffer) { DWORD dwErr; DWORD dwUnused; dwErr = 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 pcbBuffer, // max size of value data, NULL, // security descriptor NULL); // Last write time if (dwErr == ERROR_SUCCESS) { *ppBuffer = new BYTE [*pcbBuffer]; if (*ppBuffer != NULL) { dwErr = DfsmQueryValue( hKey, wszProperty, REG_BINARY, 0, *ppBuffer, pcbBuffer); if (dwErr) { delete [] *ppBuffer; *ppBuffer = NULL; *pcbBuffer = 0; } } else { dwErr = ERROR_OUTOFMEMORY; } } return( dwErr ); } //+---------------------------------------------------------------------------- // // Function: SetBlobByValue // // Synopsis: Saves a property of type Binary for the value wszProperty // // Arguments: // // Returns: // //----------------------------------------------------------------------------- DWORD SetBlobByValue( HKEY hKey, LPWSTR wszProperty, PBYTE pBuffer, ULONG cbBuffer) { DWORD dwErr; DWORD dwUnused; DWORD unused; dwErr = 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 &unused, // max size of value data, NULL, // security descriptor NULL); // Last write time if (dwErr == ERROR_SUCCESS) { dwErr = RegSetValueEx( hKey, wszProperty, NULL, REG_BINARY, pBuffer, cbBuffer); } else { dwErr = ERROR_OUTOFMEMORY; } return( dwErr ); } DWORD GetSvcProps( HKEY hKey, PDFS_VOLUME pVol) { DWORD cbBuffer; DWORD dwErr; PBYTE Buffer = NULL; PBYTE pBuf = NULL; if (fSwDebug == TRUE) MyPrintf(L"GetSvcProps(%ws)\r\n", pVol->wszObjectName); dwErr = GetBlobByValue( hKey, SVC_PROPS, &Buffer, &cbBuffer); if (dwErr != ERROR_SUCCESS) goto Cleanup; pBuf = Buffer; dwErr = UnSerializeReplicaList( &pVol->ReplCount, &pVol->AllocatedReplCount, &pVol->ReplicaInfo, &pVol->FtModification, &pBuf); if (dwErr != ERROR_SUCCESS) goto Cleanup; // // Get deleted replicas // if (pBuf < (pBuf + cbBuffer)) { dwErr = UnSerializeReplicaList( &pVol->DelReplCount, &pVol->AllocatedDelReplCount, &pVol->DelReplicaInfo, &pVol->DelFtModification, &pBuf); } Cleanup: if (Buffer != NULL) delete [] Buffer; if (fSwDebug == TRUE) MyPrintf(L"GetSvcProps exit %d\n", dwErr); return dwErr; } //+---------------------------------------------------------------------------- // // Function: GetVersionProps // // Synopsis: Retrieves the version property set of a Dfs Manager volume // object. // // Returns: [S_OK] -- If successful. // // DWORD from DfsmQueryValue // //----------------------------------------------------------------------------- DWORD GetVersionProps( HKEY hKey, LPWSTR wszProperty, PULONG pVersion) { DWORD dwErr; DWORD cbSize; cbSize = sizeof(ULONG); dwErr = DfsmQueryValue( hKey, wszProperty, REG_DWORD, sizeof(DWORD), (LPBYTE) pVersion, &cbSize); return dwErr; } //+---------------------------------------------------------------------------- // // Function: GetRecoveryProps // // Synopsis: Retrieves the recovery properties of a Dfs Manager volume // object. // // Arguments: [ppRecovery] -- On successful return, points to a buffer // allocated to hold the recovery property. // [pcbRecovery] -- On successful return, size in bytes of // recovery buffer. // // Returns: // //----------------------------------------------------------------------------- DWORD GetRecoveryProps( HKEY hKey, LPWSTR wszProperty, PULONG pcbRecovery, PBYTE *ppRecovery) { DWORD dwErr; dwErr = GetBlobByValue( hKey, wszProperty, ppRecovery, pcbRecovery); return dwErr; } DWORD EnumKeys( HKEY hKey, PULONG pcKeys, LPWSTR **ppNames) { // figure out how many keys are currently stored in this key // and allocate a buffer to hold the return results. LPWSTR *pNames = NULL; WCHAR wszClass[MAX_PATH+1]; ULONG cbClass = sizeof(wszClass); ULONG cSubKeys, cbMaxSubKeyLen, cbMaxClassLen; ULONG cValues, cbMaxValueIDLen, cbMaxValueLen; SECURITY_DESCRIPTOR SecDescriptor; FILETIME ft; DWORD dwErr = ERROR_SUCCESS; DWORD dwIndex=0; dwErr = RegQueryInfoKey( hKey, wszClass, &cbClass, NULL, &cSubKeys, &cbMaxSubKeyLen, &cbMaxClassLen, &cValues, &cbMaxValueIDLen, &cbMaxValueLen, (DWORD *)&SecDescriptor, &ft); if (dwErr != ERROR_SUCCESS) goto Cleanup; pNames = new LPWSTR [cSubKeys]; if (pNames == NULL) { dwErr = ERROR_OUTOFMEMORY; goto Cleanup; } RtlZeroMemory(pNames, cSubKeys * sizeof(LPWSTR)); // loop enumerating and adding names for (dwIndex = 0; dwIndex < cSubKeys && dwErr == ERROR_SUCCESS; dwIndex++) { WCHAR wszKeyName[MAX_PATH]; ULONG cbKeyName = sizeof(wszKeyName)/sizeof(WCHAR); WCHAR wszClass[MAX_PATH]; ULONG cbClass = sizeof(wszClass)/sizeof(WCHAR); FILETIME ft; dwErr = RegEnumKeyEx( hKey, // handle dwIndex, // index wszKeyName, // key name &cbKeyName, // length of key name NULL, // title index wszClass, // class &cbClass, // length of class &ft); // last write time if (dwErr == ERROR_SUCCESS) { GIP_DUPLICATE_STRING( dwErr, wszKeyName, &pNames[dwIndex]); } }; // finished the enumeration, check the results if (dwErr == ERROR_NO_MORE_ITEMS || dwErr == ERROR_SUCCESS) { *pcKeys = dwIndex; *ppNames = pNames; } else { // Cleanup and return an error while (dwIndex) { delete pNames[--dwIndex]; } delete [] pNames; } Cleanup: return(dwErr); } DWORD GetSiteTable( HKEY hKey, PDFS_VOLUME_LIST pDfsVolList) { DWORD dwErr = ERROR_SUCCESS; NTSTATUS NtStatus; ULONG cSite; PDFSM_SITE_ENTRY pSiteEntry; PDFSM_SITE_ENTRY pTmpSiteEntry; MARSHAL_BUFFER marshalBuffer; ULONG Size; PLIST_ENTRY pListHead; PLIST_ENTRY pLink; PBYTE pObjectData = NULL; ULONG cbObjectData; PBYTE pBuffer = NULL; ULONG cbBuffer; ULONG i; if (fSwDebug == TRUE) MyPrintf(L"GetSiteTable()\r\n"); dwErr = GetBlobByValue( hKey, L"SiteTable", &pObjectData, &cbObjectData); if (dwErr != ERROR_SUCCESS) goto Cleanup; // // Unserialize the buffer // InitializeListHead(&pDfsVolList->SiteList); MarshalBufferInitialize( &marshalBuffer, cbObjectData, pObjectData); NtStatus = DfsRtlGetGuid(&marshalBuffer, &pDfsVolList->SiteGuid); if (!NT_SUCCESS(NtStatus)) { dwErr = RtlNtStatusToDosError(NtStatus); goto Cleanup; } NtStatus = DfsRtlGetUlong(&marshalBuffer, &pDfsVolList->SiteCount); if (!NT_SUCCESS(NtStatus)) { dwErr = RtlNtStatusToDosError(NtStatus); goto Cleanup; } pBuffer = (BYTE *)malloc(cbObjectData); if (pBuffer == NULL) { dwErr = ERROR_OUTOFMEMORY; goto Cleanup; } pTmpSiteEntry = (PDFSM_SITE_ENTRY)pBuffer; for (cSite = 0; cSite < pDfsVolList->SiteCount; cSite++) { RtlZeroMemory(pBuffer, cbObjectData); NtStatus = DfsRtlGet( &marshalBuffer, &MiDfsmSiteEntry, pBuffer); if (!NT_SUCCESS(NtStatus)) { dwErr = RtlNtStatusToDosError(NtStatus); goto Cleanup; } Size = sizeof(DFSM_SITE_ENTRY) + (pTmpSiteEntry->Info.cSites * sizeof(DFS_SITENAME_INFO)); pSiteEntry = (PDFSM_SITE_ENTRY) malloc(Size); if (pSiteEntry == NULL) { dwErr = ERROR_OUTOFMEMORY; goto Cleanup; } RtlCopyMemory(pSiteEntry, pBuffer, Size); InsertHeadList(&pDfsVolList->SiteList, &pSiteEntry->Link); } Cleanup: if (pBuffer != NULL) delete [] pBuffer; return dwErr; } //+------------------------------------------------------------------------ // // Function: DfsCheckVolList // // Synopsis: Prints the volume information represented by the volume // list passed in. // // Returns: [ERROR_SUCCESS] -- If all went well. // // History: 11/19/98 JHarper Created // //------------------------------------------------------------------------- VOID DfsCheckVolList( PDFS_VOLUME_LIST pDfsVolList, ULONG Level) { ULONG cVol; ULONG cRepl; ULONG cExit; PLIST_ENTRY pListHead; PLIST_ENTRY pLink; PDFSM_SITE_ENTRY pSiteEntry; PDFS_ROOTLOCALVOL pRootLocalVol = pDfsVolList->pRootLocalVol; BOOLEAN SvcOk = FALSE; BOOLEAN IdOk = FALSE; BOOLEAN VerOk = FALSE; BOOLEAN RecOk = FALSE; BOOLEAN Ok1 = FALSE; BOOLEAN Ok2 = FALSE; MyPrintf(L"(metadata)..\r\n"); for (cVol = 0; cVol < pDfsVolList->VolCount; cVol++) { IdOk = SvcOk = VerOk = RecOk = TRUE; if ( pDfsVolList->Volumes[cVol]->wszPrefix == NULL || pDfsVolList->Volumes[cVol]->wszShortPrefix == NULL || pDfsVolList->Volumes[cVol]->dwTimeout <= 0 || pDfsVolList->Volumes[cVol]->dwState == 0 ) { IdOk = FALSE; } if (pDfsVolList->Volumes[cVol]->ReplCount == 0) SvcOk = FALSE; if (pDfsVolList->Volumes[cVol]->dwVersion == 0) VerOk = FALSE; for (cRepl = 0; cRepl < pDfsVolList->Volumes[cVol]->ReplCount; cRepl++) { if ( pDfsVolList->Volumes[cVol]->ReplicaInfo[cRepl].pwszServerName == NULL || pDfsVolList->Volumes[cVol]->ReplicaInfo[cRepl].pwszShareName == NULL ) { SvcOk = FALSE; } } for (cRepl = 0; cRepl < pDfsVolList->Volumes[cVol]->DelReplCount; cRepl++) { if ( pDfsVolList->Volumes[cVol]->DelReplicaInfo[cRepl].pwszServerName == NULL || pDfsVolList->Volumes[cVol]->DelReplicaInfo[cRepl].pwszShareName == NULL ) { SvcOk = FALSE; } } if (IdOk != TRUE || SvcOk != TRUE) { MyPrintf(L"%ws: Bad or Missing values: %ws %ws %ws %ws\r\n", pDfsVolList->Volumes[cVol]->wszObjectName, IdOk == TRUE ? L"" : L"ID", SvcOk == TRUE ? L"" : L"Svc", VerOk == TRUE ? L"" : L"Version", RecOk == TRUE ? L"" : L"Recovery"); } } if (Level > 0) { // // Verify that all the vols have exit points // MyPrintf(L"(volumes have exit points)..\r\n"); Ok1 = Ok2 = FALSE; for (cVol = 1; cVol < pDfsVolList->VolCount; cVol++) { Ok1 = FALSE; if (fSwDebug == TRUE) { MyPrintf(L"++++ [%ws]\r\n", pDfsVolList->Volumes[cVol]->wszObjectName); MyPrintf(L" %d ExitPts:", pRootLocalVol[0].cLocalVolCount); } for (cExit = 0; cExit < pRootLocalVol[0].cLocalVolCount; cExit++) { if (fSwDebug == TRUE) MyPrintf(L"%d ", cExit); if ( (pDfsVolList->Volumes[cVol]->wszObjectName != NULL && pRootLocalVol[0].pDfsLocalVol[cExit].wszObjectName != NULL) && (pDfsVolList->Volumes[cVol]->wszObjectName[12] == pRootLocalVol[0].pDfsLocalVol[cExit].wszObjectName[0]) && wcscmp( &pDfsVolList->Volumes[cVol]->wszObjectName[12], pRootLocalVol[0].pDfsLocalVol[cExit].wszObjectName) == 0 ) { Ok1 = TRUE; break; } } if (fSwDebug == TRUE) MyPrintf(L"\r\n", cExit); if (Ok1 != TRUE && wcslen(&pDfsVolList->Volumes[cVol]->wszObjectName[12]) > 0) { MyPrintf(L"Missing [%ws] in LocalVolumes\r\n", &pDfsVolList->Volumes[cVol]->wszObjectName[12]); } } // // Verify that all the exit points have vols // MyPrintf(L"(exit points have volumes)..\r\n"); Ok1 = Ok2 = FALSE; for (cExit = 0; cExit < pRootLocalVol[0].cLocalVolCount; cExit++) { Ok1 = FALSE; if (fSwDebug == TRUE) { MyPrintf(L"---- [%ws]\r\n", pRootLocalVol[0].pDfsLocalVol[cExit].wszObjectName); MyPrintf(L" %d Vols:", pDfsVolList->VolCount); } for (cVol = 1; cVol < pDfsVolList->VolCount; cVol++) { if (fSwDebug == TRUE) MyPrintf(L"%d ", cVol); if ( (pDfsVolList->Volumes[cVol]->wszObjectName != NULL && pRootLocalVol[0].pDfsLocalVol[cExit].wszObjectName != NULL) && (pDfsVolList->Volumes[cVol]->wszObjectName[12] == pRootLocalVol[0].pDfsLocalVol[cExit].wszObjectName[0]) && wcscmp( &pDfsVolList->Volumes[cVol]->wszObjectName[12], pRootLocalVol[0].pDfsLocalVol[cExit].wszObjectName) == 0 ) { Ok1 = TRUE; break; } } if (fSwDebug == TRUE) MyPrintf(L"\r\n", cVol); if (Ok1 != TRUE) { MyPrintf(L"Extra ExitPt [%ws] in LocalVolumes\r\n", pRootLocalVol[0].pDfsLocalVol[cExit].wszObjectName); } } } MyPrintf(L"(exit point internal consistency)...\r\n"); Ok1 = Ok2 = FALSE; for (cVol = 0; cVol < pDfsVolList->VolCount; cVol++) { Ok1 = FALSE; for (cExit = 0; cExit < pRootLocalVol[0].cLocalVolCount; cExit++) { if ( (pDfsVolList->Volumes[cVol]->wszObjectName != NULL && pRootLocalVol[0].pDfsLocalVol[cExit].wszObjectName != NULL) && (pDfsVolList->Volumes[cVol]->wszObjectName[12] == pRootLocalVol[0].pDfsLocalVol[cExit].wszObjectName[0]) && wcscmp( &pDfsVolList->Volumes[cVol]->wszObjectName[12], pRootLocalVol[0].pDfsLocalVol[cExit].wszObjectName) == 0 ) { Ok1 = TRUE; break; } } if (Ok1 == TRUE && wcslen(&pDfsVolList->Volumes[cVol]->wszObjectName[12]) > 0) { PWCHAR wCp1 = &pDfsVolList->Volumes[cVol]->wszPrefix[1]; PWCHAR wCp2 = &pRootLocalVol[0].pDfsLocalVol[cExit].wszEntryPath[1]; while (*wCp1 != L'\\') wCp1++; while (*wCp2 != L'\\') wCp2++; if (_wcsicmp(wCp1,wCp2) != 0) { MyPrintf(L"Mismatch in ExitPt in [%ws]\r\n", pRootLocalVol[0].pDfsLocalVol[cExit].wszObjectName); MyPrintf(L" [%ws] vs [%ws]\r\n", pDfsVolList->Volumes[cVol]->wszPrefix, pRootLocalVol[0].pDfsLocalVol[cExit].wszEntryPath); } } } } DWORD GetExitPtInfo( HKEY rKey, PDFS_ROOTLOCALVOL *ppRootLocalVol, PULONG pcVolCount) { HKEY hKey = NULL; HKEY hKeyExPt = NULL; LPWSTR *pNames = NULL; ULONG dwErr; ULONG cKeys; ULONG i; PDFS_ROOTLOCALVOL pRootLocalVol; DWORD cbBuffer; DWORD cbSize; DWORD dwType; WCHAR wszBuffer[MAX_PATH+1]; if (fSwDebug == TRUE) MyPrintf(L"GetExitPtInfo()\r\n"); dwErr = RegOpenKey( rKey, REG_KEY_LOCAL_VOLUMES, &hKey); if (dwErr != ERROR_SUCCESS) goto Cleanup; dwErr = EnumKeys( hKey, &cKeys, &pNames); if (dwErr != ERROR_SUCCESS) goto Cleanup; pRootLocalVol = (PDFS_ROOTLOCALVOL)malloc(sizeof(DFS_ROOTLOCALVOL) * cKeys); if (pRootLocalVol == NULL) { dwErr = ERROR_OUTOFMEMORY; goto Cleanup; } RtlZeroMemory(pRootLocalVol, sizeof(DFS_ROOTLOCALVOL) * cKeys); for (i = 0; i < cKeys; i++) { if (fSwDebug == TRUE) MyPrintf(L"RegOpenKey(%ws)\r\n", pNames[i]); dwErr = RegOpenKey( hKey, pNames[i], &hKeyExPt); if (dwErr != ERROR_SUCCESS) continue; GIP_DUPLICATE_STRING(dwErr, pNames[i], &pRootLocalVol[i].wszObjectName); cbSize = sizeof(ULONG); dwErr = DfsmQueryValue( hKeyExPt, REG_VALUE_ENTRY_TYPE, REG_DWORD, sizeof(DWORD), (LPBYTE) &pRootLocalVol[i].dwEntryType, &cbSize); cbBuffer = sizeof(wszBuffer); dwErr = RegQueryValueEx( hKeyExPt, REG_VALUE_ENTRY_PATH, // "EntryPath" NULL, &dwType, (LPBYTE) wszBuffer, &cbBuffer); if (dwErr == ERROR_MORE_DATA) dwErr = ERROR_SUCCESS; if (dwErr == ERROR_SUCCESS) GIP_DUPLICATE_STRING(dwErr, wszBuffer, &pRootLocalVol[i].wszEntryPath); cbBuffer = sizeof(wszBuffer); dwErr = RegQueryValueEx( hKeyExPt, REG_VALUE_SHARE_NAME, // "ShareName" NULL, &dwType, (LPBYTE) wszBuffer, &cbBuffer); if (dwErr == ERROR_MORE_DATA) dwErr = ERROR_SUCCESS; if (dwErr == ERROR_SUCCESS) GIP_DUPLICATE_STRING(dwErr, wszBuffer, &pRootLocalVol[i].wszShareName); cbBuffer = sizeof(wszBuffer); dwErr = RegQueryValueEx( hKeyExPt, REG_VALUE_SHORT_PATH, // "ShortEntryPath" NULL, &dwType, (LPBYTE) wszBuffer, &cbBuffer); if (dwErr == ERROR_SUCCESS) GIP_DUPLICATE_STRING(dwErr, wszBuffer, &pRootLocalVol[i].wszShortEntryPath); cbBuffer = sizeof(wszBuffer); dwErr = RegQueryValueEx( hKeyExPt, REG_VALUE_STORAGE_ID, // "StorageId" NULL, &dwType, (LPBYTE) wszBuffer, &cbBuffer); if (dwErr == ERROR_MORE_DATA) dwErr = ERROR_SUCCESS; if (dwErr == ERROR_SUCCESS) GIP_DUPLICATE_STRING(dwErr, wszBuffer, &pRootLocalVol[i].wszStorageId); dwErr = GetExitPts( hKeyExPt, &pRootLocalVol[i]); RegCloseKey(hKeyExPt); } FreeNameList( pNames, cKeys); pNames = NULL; *ppRootLocalVol = pRootLocalVol; *pcVolCount = cKeys; Cleanup: FreeNameList( pNames, cKeys); if (hKey != NULL) RegCloseKey(hKey); if (fSwDebug == TRUE) MyPrintf(L"GetExitPtInfo returning %d\r\n", dwErr); return dwErr; } VOID FreeNameList( LPWSTR *pNames, ULONG cNames) { ULONG i; if (pNames != NULL) { for (i = 0; i < cNames; i++) { if (pNames[i] != NULL) delete [] pNames[i]; } delete [] pNames; } } DWORD GetExitPts( HKEY hKey, PDFS_ROOTLOCALVOL pRootLocalVol) { ULONG cNames = 0; LPWSTR *pNames = NULL; ULONG cKeys = 0; ULONG dwErr = ERROR_SUCCESS; ULONG i; DWORD dwType = 0; DWORD cbBuffer = 0; DWORD cbSize = 0; HKEY hKeyExPt = NULL; WCHAR wszBuffer[MAX_PATH+1]; dwErr = EnumKeys( hKey, &cKeys, &pNames); if (dwErr != ERROR_SUCCESS) goto Cleanup; pRootLocalVol->pDfsLocalVol = (PDFS_LOCALVOLUME)malloc(sizeof(DFS_LOCALVOLUME) * cKeys); if (pRootLocalVol->pDfsLocalVol == NULL) { dwErr = ERROR_OUTOFMEMORY; goto Cleanup; } RtlZeroMemory(pRootLocalVol->pDfsLocalVol, sizeof(DFS_LOCALVOLUME) * cKeys); pRootLocalVol->cLocalVolCount = cKeys; for (i = 0; i < cKeys; i++) { if (fSwDebug == TRUE) MyPrintf(L" GetExitPts(%ws)\r\n", pNames[i]); // // Get EntryPath // dwErr = RegOpenKey( hKey, pNames[i], &hKeyExPt); if (dwErr != ERROR_SUCCESS) { if (fSwDebug == TRUE) MyPrintf(L"RegOpenKey returned %d\r\n", dwErr); continue; } GIP_DUPLICATE_STRING(dwErr, pNames[i], &pRootLocalVol->pDfsLocalVol[i].wszObjectName); cbBuffer = sizeof(wszBuffer); dwErr = RegQueryValueEx( hKeyExPt, REG_VALUE_ENTRY_PATH, // "EntryPath" NULL, &dwType, (LPBYTE) wszBuffer, &cbBuffer); if (dwErr == ERROR_MORE_DATA) dwErr = ERROR_SUCCESS; if (dwErr != ERROR_SUCCESS && fSwDebug == TRUE) MyPrintf(L"RegQueryValueEx returned %d\r\n", dwErr); if (dwErr == ERROR_SUCCESS) GIP_DUPLICATE_STRING(dwErr, wszBuffer, &pRootLocalVol->pDfsLocalVol[i].wszEntryPath); RegCloseKey(hKeyExPt); } Cleanup: FreeNameList( pNames, cKeys); return dwErr; } DWORD DfsSetOnSite( HKEY rKey, LPWSTR wszKeyName, ULONG set) { HKEY hKey = NULL; DWORD dwErr; LPWSTR *pNames = NULL; ULONG cKeys = 0; ULONG i; WCHAR VolumesDir[MAX_PATH+1]; wcscpy(VolumesDir, VOLUMES_DIR); wcscat(VolumesDir, L"domainroot"); dwErr = RegOpenKey( rKey, VolumesDir, &hKey); if (dwErr != ERROR_SUCCESS) { MyPrintf(L"Not a StdDfs root!\r\n"); goto Cleanup; } dwErr = EnumKeys( hKey, &cKeys, &pNames); if (dwErr != ERROR_SUCCESS) { MyPrintf(L"No exit points...\r\n"); goto Cleanup; } dwErr = SetSiteInfoOnKey( rKey, L"domainroot", wszKeyName, set); for (i = 0; i < cKeys && dwErr != ERROR_SUCCESS && dwErr != ERROR_REQUEST_ABORTED && dwErr != ERROR_PATH_NOT_FOUND; i++) { wcscpy(VolumesDir, L"domainroot\\"); wcscat(VolumesDir, pNames[i]); dwErr = SetSiteInfoOnKey( rKey, VolumesDir, wszKeyName, set); } if (dwErr == ERROR_PATH_NOT_FOUND) ErrorMessage(MSG_LINK_NOT_FOUND, wszKeyName); Cleanup: if (pNames != NULL) FreeNameList( pNames, cKeys); if (hKey != NULL) RegCloseKey(hKey); return dwErr; } DWORD SetSiteInfoOnKey( HKEY rKey, LPWSTR wszKeyName, LPWSTR wszPrefixMatch, ULONG Set) { DWORD dwErr = 0; HKEY hKey = NULL; ULONG cRepl; WCHAR VolumesDir[MAX_PATH+1]; DFS_VOLUME Volume; PDFS_VOLUME pVolume = &Volume; wcscpy(VolumesDir, VOLUMES_DIR); wcscat(VolumesDir, wszKeyName); LPWSTR usePrefix; if (fSwDebug == TRUE) MyPrintf(L"SetSiteInfoOnKey(%ws)\r\n", VolumesDir); dwErr = RegOpenKey( rKey, VolumesDir, &hKey); if (dwErr != ERROR_SUCCESS) { if (fSwDebug == TRUE) MyPrintf(L"RegOpenKey(%ws) returned %d\r\n", VolumesDir, dwErr); goto Cleanup; } // // Id (Prefix, Type, state, etc) // dwErr = GetIdProps( hKey, &pVolume->dwType, &pVolume->dwState, &pVolume->wszPrefix, &pVolume->wszShortPrefix, &pVolume->idVolume, &pVolume->wszComment, &pVolume->dwTimeout, &pVolume->ftPrefix, &pVolume->ftState, &pVolume->ftComment); if (dwErr != ERROR_SUCCESS) { if (fSwDebug == TRUE) MyPrintf(L"GetIdProps() returned %d\r\n", dwErr); goto Cleanup; } usePrefix = pVolume->wszPrefix; DfspGetLinkName(usePrefix, &usePrefix); if (fSwDebug) { MyPrintf(L"prefix (%ws, %ws), keyname (%ws)\r\n", usePrefix, pVolume->wszShortPrefix, wszPrefixMatch); } if (_wcsicmp(usePrefix, wszPrefixMatch) == 0) { dwErr = ERROR_SUCCESS; if (fSwDebug) { MyPrintf(L"Match found prefix (%ws, %ws), keyname (%ws)\r\n", usePrefix, pVolume->wszShortPrefix, wszPrefixMatch); } if (Set) { if (pVolume->dwType & PKT_ENTRY_TYPE_INSITE_ONLY) { ErrorMessage(MSG_SITE_INFO_ALREADY_SET, pVolume->wszPrefix); dwErr = ERROR_REQUEST_ABORTED; } else { ErrorMessage(MSG_SITE_INFO_NOW_SET, pVolume->wszPrefix); pVolume->dwType |= PKT_ENTRY_TYPE_INSITE_ONLY; } } else { if (pVolume->dwType & PKT_ENTRY_TYPE_INSITE_ONLY) { ErrorMessage(MSG_SITE_INFO_NOW_SET, pVolume->wszPrefix); pVolume->dwType &= ~PKT_ENTRY_TYPE_INSITE_ONLY; } else { ErrorMessage(MSG_SITE_INFO_ALREADY_SET, pVolume->wszPrefix); dwErr = ERROR_REQUEST_ABORTED; } } if (dwErr == ERROR_SUCCESS) { dwErr = SetIdProps( hKey, pVolume->dwType, pVolume->dwState, pVolume->wszPrefix, pVolume->wszShortPrefix, pVolume->idVolume, pVolume->wszComment, pVolume->dwTimeout, pVolume->ftPrefix, pVolume->ftState, pVolume->ftComment); if (dwErr != ERROR_SUCCESS) { if (fSwDebug == TRUE) MyPrintf(L"SetIdProps() returned %d\r\n", dwErr); goto Cleanup; } } } else { dwErr = ERROR_PATH_NOT_FOUND; } Cleanup: if (hKey != NULL) RegCloseKey(hKey); if (fSwDebug == TRUE) MyPrintf(L"SetSiteInfoOnKey exit %d\r\n", dwErr); return( dwErr ); } DWORD CmdStdUnmap( LPWSTR pwszServerName) { DWORD dwErr = ERROR_SUCCESS; HKEY rKey = NULL; HKEY hKey = NULL; if (fSwDebug != 0) MyPrintf(L"CmdStdUnmap(%ws)\r\n", pwszServerName); dwErr = RegConnectRegistry( pwszServerName, HKEY_LOCAL_MACHINE, &rKey); if (dwErr != ERROR_SUCCESS) { MyPrintf(L"Can not open registry of %ws (error %d)\r\n", pwszServerName, dwErr); goto Cleanup; } // // Remove VOLUMES_DIR and children // dwErr = DfsRegDeleteKeyAndChildren(rKey, DFSHOST_DIR); if (dwErr != ERROR_SUCCESS) goto Cleanup; // // New remove all local vol information // dwErr = DfsRegDeleteKeyAndChildren(rKey, REG_KEY_LOCAL_VOLUMES); if (dwErr != ERROR_SUCCESS) goto Cleanup; Cleanup: RegCreateKey(rKey, REG_KEY_LOCAL_VOLUMES, &hKey); RegCreateKey(rKey, DFSHOST_DIR, &hKey); if (rKey != NULL) RegCloseKey(rKey); if (hKey != NULL) RegCloseKey(hKey); if (fSwDebug != 0) MyPrintf(L"CmdStdUnmap exit %d\r\n", dwErr); return dwErr; } DWORD CmdClean( LPWSTR pwszServerName) { DWORD dwErr = ERROR_SUCCESS; HKEY rKey = NULL; HKEY hKey = NULL; if (fSwDebug != 0) MyPrintf(L"CmdClean(%ws)\r\n", pwszServerName); dwErr = RegConnectRegistry( pwszServerName, HKEY_LOCAL_MACHINE, &rKey); if (dwErr != ERROR_SUCCESS) { MyPrintf(L"Can not open registry of %ws (error %d)\r\n", pwszServerName, dwErr); goto Cleanup; } // // Remove VOLUMES_DIR and children // dwErr = DfsRegDeleteKeyAndChildren(rKey, DFSHOST_DIR); if (dwErr != ERROR_SUCCESS) goto Cleanup; // // New remove all local vol information // dwErr = DfsRegDeleteKeyAndChildren(rKey, REG_KEY_LOCAL_VOLUMES); if (dwErr != ERROR_SUCCESS) goto Cleanup; Cleanup: RegCreateKey(rKey, REG_KEY_LOCAL_VOLUMES, &hKey); RegCreateKey(rKey, DFSHOST_DIR, &hKey); if (rKey != NULL) RegCloseKey(rKey); if (hKey != NULL) RegCloseKey(hKey); if (fSwDebug != 0) MyPrintf(L"CmdClean exit %d\r\n", dwErr); return dwErr; } DWORD DfsDeleteChildKeys( HKEY hKey, LPWSTR s) { WCHAR *wcp, *wcp1; HKEY nKey; DWORD dwErr; DWORD hErr; if (fSwDebug != 0) MyPrintf(L"DfsDeleteChildKeys(%ws)\r\n", s); for (wcp = s; *wcp; wcp++) ; hErr = dwErr = RegOpenKey(hKey, s, &nKey); while (RegEnumKey(nKey, 0, wcp, 50 * sizeof(WCHAR)) == ERROR_SUCCESS) { for (wcp1 = wcp; *wcp1; wcp1++) ; *wcp1++ = L'\\'; *wcp1 = L'\0'; dwErr = DfsDeleteChildKeys(hKey, s); if (dwErr == ERROR_SUCCESS) { dwErr = RegDeleteKey(hKey, s); } } *wcp = L'\0'; if (hErr == ERROR_SUCCESS) { RegCloseKey(nKey); } if (fSwDebug != 0) MyPrintf(L"DfsDeleteChildKeys exit %d\r\n", dwErr); return dwErr; } DWORD DfsRegDeleteKeyAndChildren( HKEY hkey, LPWSTR s) { DWORD dwErr; LONG l; LPWSTR wCp; if (fSwDebug != 0) MyPrintf(L"DfsRegDeleteKeyAndChildren(%ws)\r\n", s); wCp = (LPWSTR)malloc(4096); if (wCp == NULL) { return ERROR_NOT_ENOUGH_MEMORY; } wcscpy(wCp, s); l = wcslen(s); if (l > 0 && wCp[l-1] != L'\\') { wcscat(wCp, L"\\"); } dwErr = DfsDeleteChildKeys(hkey, wCp); if (dwErr == ERROR_SUCCESS) { dwErr = RegDeleteKey(hkey, wCp); } free(wCp); if (fSwDebug != 0) MyPrintf(L"DfsRegDeleteKeyAndChildren exit %d\r\n", dwErr); return dwErr; }