//-------------------------------------------------------------------------- // // Copyright (C) 1999, Microsoft Corporation // // File: ftsup.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 "ftsup.hxx" #include "rootsup.hxx" #include "dfsacl.hxx" #include "misc.hxx" #include "fileio.hxx" #include "messages.h" DWORD CmdUnmapOneRoot( LPWSTR pwszDomDfsName, LPWSTR pwszRootName, LPWSTR pwszDcName, LPWSTR pwszDomainName, PSEC_WINNT_AUTH_IDENTITY pAuthIdent); DWORD DfsUpdateSiteReferralInfo( PDFS_VOLUME_LIST pDfsVolList, LPWSTR wszPrefixMatch, ULONG Set); DWORD DfsGetFtVol( PDFS_VOLUME_LIST pDfsVolList, LPWSTR wszFtDfsName, LPWSTR pwszDcName, LPWSTR pwszDomainName, PSEC_WINNT_AUTH_IDENTITY pAuthIdent) { DWORD dwErr = ERROR_SUCCESS; ULONG cbBlob = 0; BYTE *pBlob = NULL; WCHAR wszDcName[MAX_PATH+1]; if (fSwDebug == TRUE) MyPrintf(L"DfsGetFtVol(%ws,%ws,%ws)\r\n", wszFtDfsName, pwszDcName, pwszDomainName); if (pwszDcName == NULL) { dwErr = DfspGetPdc(wszDcName, pwszDomainName); } else { wcscpy(wszDcName, pwszDcName); } if (dwErr != ERROR_SUCCESS) goto Cleanup; ErrorMessage(MSG_CONNECTING, wszDcName); // // Get blob & root list from Ds // dwErr = DfsGetDsBlob( wszFtDfsName, DfsConfigContainer, wszDcName, pAuthIdent, &cbBlob, &pBlob, &pDfsVolList->RootServers); if (dwErr != ERROR_SUCCESS) goto Cleanup; // // Unserialize it // dwErr = DfsGetVolList( cbBlob, pBlob, pDfsVolList); pDfsVolList->DfsType = DOMDFS; Cleanup: if (pBlob != NULL) free(pBlob); if (fSwDebug == TRUE) MyPrintf(L"DfsGetFtVol exit %d\r\n", dwErr); return dwErr; } //+------------------------------------------------------------------------ // // Function: DfsGetDsBlob // // Synopsis: Reads a Dfs BLOB from the DS // // History: 11/19/98 JHarper Created // //------------------------------------------------------------------------- DWORD DfsGetDsBlob( LPWSTR wszFtDfsName, LPWSTR wszContainerName, LPWSTR wszDcName, PSEC_WINNT_AUTH_IDENTITY pAuthIdent, ULONG *pcbBlob, BYTE **ppBlob, LPWSTR **ppRootServers) { DWORD dwErr; LDAP *pldap = NULL; PLDAPMessage pMsg = NULL; PLDAP_BERVAL *rgldapPktBlob = NULL; PLDAP_BERVAL pldapPktBlob; LDAPMessage *pmsgServers; DWORD i; WCHAR *wszConfigurationDN = NULL; WCHAR wszDfsConfigDN[MAX_PATH+1]; LPWSTR rgAttrs[5]; BYTE *pBlob = NULL; if (fSwDebug == TRUE) MyPrintf(L"DfsGetDsBlob(%ws,%ws, %ws)\r\n", wszFtDfsName, wszContainerName, wszDcName); dwErr = DfspLdapOpen(wszDcName, pAuthIdent, &pldap, wszContainerName, &wszConfigurationDN); if (dwErr != ERROR_SUCCESS) goto Cleanup; // // Build the entry name we want to search in // wcscpy(wszDfsConfigDN,L"CN="); wcscat(wszDfsConfigDN,wszFtDfsName); wcscat(wszDfsConfigDN,L","); wcscat(wszDfsConfigDN,wszConfigurationDN); if (fSwDebug == TRUE) MyPrintf(L"wszDfsConfigDN=[%ws]\r\n", wszDfsConfigDN); rgAttrs[0] = L"pKT"; rgAttrs[1] = NULL; dwErr = ldap_search_s( pldap, wszDfsConfigDN, LDAP_SCOPE_BASE, L"(objectClass=*)", rgAttrs, 0, &pMsg); if (dwErr != LDAP_SUCCESS) { dwErr = LdapMapErrorToWin32(dwErr); goto Cleanup; } pmsgServers = ldap_first_entry(pldap, pMsg); if (pmsgServers == NULL) { dwErr = ERROR_OUTOFMEMORY; goto Cleanup; } rgldapPktBlob = ldap_get_values_len( pldap, pMsg, L"pKT"); if (rgldapPktBlob == NULL || *rgldapPktBlob == NULL) { dwErr = ERROR_INTERNAL_DB_CORRUPTION; goto Cleanup; } pldapPktBlob = rgldapPktBlob[0]; pBlob = (BYTE *)malloc(pldapPktBlob->bv_len + sizeof(DWORD)); if (pBlob == NULL) { dwErr = ERROR_OUTOFMEMORY; goto Cleanup; } RtlZeroMemory(pBlob, pldapPktBlob->bv_len + sizeof(DWORD)); MyPrintf(L"\r\n"); MyPrintf(L" ------ Blob is %d bytes...\r\n", pldapPktBlob->bv_len); MyPrintf(L"\r\n"); RtlCopyMemory(pBlob, pldapPktBlob->bv_val, pldapPktBlob->bv_len); *ppBlob = pBlob; *pcbBlob = pldapPktBlob->bv_len; dwErr = NetDfsRootServerEnum( pldap, wszDfsConfigDN, ppRootServers); Cleanup: if (rgldapPktBlob != NULL) ldap_value_free_len(rgldapPktBlob); if (pMsg != NULL) ldap_msgfree(pMsg); if (pldap != NULL) ldap_unbind(pldap); if (wszConfigurationDN != NULL) free(wszConfigurationDN); if (fSwDebug == TRUE) MyPrintf(L"DfsGetDsBlob returning %d\r\n", dwErr); return (dwErr); } //+------------------------------------------------------------------------ // // Function: DfsPutDsBlob // // Synopsis: Updates a Dfs BLOB in the DS // // History: 12/8/98 JHarper Created // //------------------------------------------------------------------------- DWORD DfsPutDsBlob( LPWSTR wszFtDfsName, LPWSTR wszContainerName, LPWSTR wszDcName, PSEC_WINNT_AUTH_IDENTITY pAuthIdent, ULONG cbBlob, BYTE *pBlob, LPWSTR *pRootServers) { DWORD dwErr; LDAP *pldap = NULL; GUID idNewPkt; LDAP_BERVAL ldapVal; PLDAP_BERVAL rgldapVals[2]; LDAPModW ldapMod; LDAP_BERVAL ldapIdVal; PLDAP_BERVAL rgldapIdVals[2]; LDAPModW ldapIdMod; PLDAPModW rgldapMods[4]; WCHAR *wszConfigurationDN = NULL; LDAPModW ldapModServer; WCHAR wszDfsConfigDN[MAX_PATH+1]; if (fSwDebug == TRUE) MyPrintf(L"DfsPutDsBlob(%ws,%ws, %ws)\r\n", wszFtDfsName, wszContainerName, wszDcName); dwErr = DfspLdapOpen(wszDcName, pAuthIdent, &pldap, wszContainerName, &wszConfigurationDN); if (dwErr != ERROR_SUCCESS) goto Cleanup; // // Build the entry name // wcscpy(wszDfsConfigDN,L"CN="); wcscat(wszDfsConfigDN,wszFtDfsName); wcscat(wszDfsConfigDN,L","); wcscat(wszDfsConfigDN,wszConfigurationDN); if (fSwDebug == TRUE) MyPrintf(L"wszDfsConfigDN=[%ws]\r\n", wszDfsConfigDN); dwErr = UuidCreate( &idNewPkt ); if(dwErr != RPC_S_OK) { goto Cleanup; } ldapIdVal.bv_len = sizeof(GUID); ldapIdVal.bv_val = (PCHAR) &idNewPkt; rgldapIdVals[0] = &ldapIdVal; rgldapIdVals[1] = NULL; ldapIdMod.mod_op = LDAP_MOD_REPLACE | LDAP_MOD_BVALUES; ldapIdMod.mod_type = L"pKTGuid"; ldapIdMod.mod_vals.modv_bvals = rgldapIdVals; ldapVal.bv_len = cbBlob; ldapVal.bv_val = (PCHAR) pBlob; rgldapVals[0] = &ldapVal; rgldapVals[1] = NULL; ldapMod.mod_op = LDAP_MOD_REPLACE | LDAP_MOD_BVALUES; ldapMod.mod_type = L"pKT"; ldapMod.mod_vals.modv_bvals = rgldapVals; ldapModServer.mod_op = LDAP_MOD_REPLACE; ldapModServer.mod_type = L"remoteServerName"; ldapModServer.mod_vals.modv_strvals = pRootServers; rgldapMods[0] = &ldapMod; rgldapMods[1] = &ldapIdMod; rgldapMods[2] = &ldapModServer; rgldapMods[3] = NULL; if (fSwDebug == TRUE) MyPrintf(L"Writing BLOB of %d bytes\r\n", cbBlob); dwErr = ldap_modify_s( pldap, wszDfsConfigDN, rgldapMods); if (fSwDebug == TRUE) { MyPrintf(L"ldap_modify_s returned %d(0x%x)\r\n", dwErr, dwErr); } ldap_unbind(pldap); pldap = NULL; if (dwErr != LDAP_SUCCESS) { dwErr = LdapMapErrorToWin32(dwErr); } else { dwErr = ERROR_SUCCESS; } Cleanup: if (pldap != NULL) ldap_unbind( pldap ); if (wszConfigurationDN != NULL) free(wszConfigurationDN); if (fSwDebug == TRUE) MyPrintf(L"DfsPutDsBlob returning %d\r\n", dwErr); return (dwErr); } //+------------------------------------------------------------------------ // // Function: DfsGetVolList // // Synopsis: Unserializes an FtDfs BLOB and creates // a volume list representing an FtDfs. // // History: 11/19/98 JHarper Created // //------------------------------------------------------------------------- DWORD DfsGetVolList( ULONG cbBlob, BYTE *pBlob, PDFS_VOLUME_LIST pDfsVolList) { DWORD dwErr; DWORD cObj; DWORD cVol; LDAP_PKT LdapPkt; MARSHAL_BUFFER marshalBuffer; NTSTATUS NtStatus; if (fSwDebug == TRUE) MyPrintf(L"DfsGetVolList()\r\n"); RtlZeroMemory(&LdapPkt, sizeof(LDAP_PKT)); if (cbBlob > sizeof(DWORD)) { _GetULong(pBlob, pDfsVolList->Version); if (fSwDebug == TRUE) { MyPrintf(L"Blob Version = %d\r\n", pDfsVolList->Version); MyPrintf(L"BLOB is %d bytes:\r\n", cbBlob); } MarshalBufferInitialize( &marshalBuffer, cbBlob - sizeof(DWORD), pBlob + sizeof(DWORD)); NtStatus = DfsRtlGet(&marshalBuffer, &MiLdapPkt, &LdapPkt); if (!NT_SUCCESS(NtStatus)) { dwErr = RtlNtStatusToDosError(NtStatus); goto Cleanup; } if (fSwDebug == TRUE) { MyPrintf(L" %d objects found\r\n", LdapPkt.cLdapObjects); for (cObj = 0; cObj < LdapPkt.cLdapObjects; cObj++) { MyPrintf(L"%d:name=%ws size=%d p=0x%p\r\n", cObj, LdapPkt.rgldapObjects[cObj].wszObjectName, LdapPkt.rgldapObjects[cObj].cbObjectData, LdapPkt.rgldapObjects[cObj].pObjectData); // DumpBuf( // LdapPkt.rgldapObjects[cObj].pObjectData, // LdapPkt.rgldapObjects[cObj].cbObjectData); } } for (cObj = 0; cObj < LdapPkt.cLdapObjects; cObj++) { if (wcscmp(LdapPkt.rgldapObjects[cObj].wszObjectName, L"\\siteroot") != 0) { pDfsVolList->VolCount++; } } pDfsVolList->Volumes = (PDFS_VOLUME *) malloc(pDfsVolList->VolCount * sizeof(PDFS_VOLUME)); if (pDfsVolList->Volumes == NULL) { dwErr = ERROR_OUTOFMEMORY; goto Cleanup; } RtlZeroMemory(pDfsVolList->Volumes, pDfsVolList->VolCount * sizeof(PDFS_VOLUME)); // // Save the true/allocated size so to optimize deletions/additions // pDfsVolList->AllocatedVolCount = pDfsVolList->VolCount; if (fSwDebug == TRUE) MyPrintf(L"===============================\r\n"); for (cVol = cObj = 0; cObj < LdapPkt.cLdapObjects; cObj++) { if (wcscmp(LdapPkt.rgldapObjects[cObj].wszObjectName, L"\\siteroot") == 0) { dwErr = DfsGetSiteTable( pDfsVolList, &LdapPkt.rgldapObjects[cObj]); } else { pDfsVolList->Volumes[cVol] = (PDFS_VOLUME) malloc(sizeof(DFS_VOLUME)); if (pDfsVolList->Volumes[cVol] == NULL) { dwErr = ERROR_OUTOFMEMORY; goto Cleanup; } RtlZeroMemory(pDfsVolList->Volumes[cVol], sizeof(DFS_VOLUME)); dwErr = DfsGetVolume( pDfsVolList->Volumes[cVol], &LdapPkt.rgldapObjects[cObj]); } if (dwErr != ERROR_SUCCESS) goto Cleanup; cVol++; } } else if (cbBlob == sizeof(DWORD)) { if (fSwDebug == TRUE) MyPrintf(L"pKT BLOB is simply one DWORD\r\n"); dwErr = ERROR_INTERNAL_DB_CORRUPTION; } else { if (fSwDebug == TRUE) MyPrintf(L"pKT BLOB is corrupt!\r\n"); dwErr = ERROR_INTERNAL_DB_CORRUPTION; } Cleanup: FreeLdapPkt(&LdapPkt); // // Do any recovery needed // // 447511, do this only if volumes is not null if (pDfsVolList->Volumes != NULL) { dwErr = DfsRecoverVolList(pDfsVolList); } if (fSwDebug == TRUE) MyPrintf(L"DfsGetVolList returning %d\r\n", dwErr); return( dwErr ); } //+------------------------------------------------------------------------ // // Function: DfsGetVolume // // Synopsis: Unserializes the data in a buffer/blob to a volume // // History: 11/19/98 JHarper Created // //------------------------------------------------------------------------- DWORD DfsGetVolume( PDFS_VOLUME pVolume, PLDAP_OBJECT pLdapObject) { DFS_VOLUME_PROPERTIES VolProps; DWORD dwErr = ERROR_SUCCESS; MARSHAL_BUFFER marshalBuffer; NTSTATUS NtStatus; PBYTE pBuffer = NULL; if (fSwDebug == TRUE) MyPrintf(L"DfsGetVolume(%ws,%d)\r\n", pLdapObject->wszObjectName, pLdapObject->cbObjectData); RtlZeroMemory(&VolProps, sizeof(DFS_VOLUME_PROPERTIES)); pVolume->wszObjectName = (WCHAR *) malloc( (wcslen(pLdapObject->wszObjectName)+1) * sizeof(WCHAR)); if (pVolume->wszObjectName == NULL) { dwErr = ERROR_OUTOFMEMORY; goto Cleanup; } wcscpy( pVolume->wszObjectName, pLdapObject->wszObjectName); MarshalBufferInitialize( &marshalBuffer, pLdapObject->cbObjectData, pLdapObject->pObjectData); NtStatus = DfsRtlGet( &marshalBuffer, &MiVolumeProperties, &VolProps); if (!NT_SUCCESS(NtStatus)) { dwErr = RtlNtStatusToDosError(NtStatus); goto Cleanup; } VolProps.dwTimeout = 300; if ( (marshalBuffer.Current < marshalBuffer.Last) && (marshalBuffer.Last - marshalBuffer.Current) == sizeof(ULONG) ) { DfsRtlGetUlong(&marshalBuffer, &VolProps.dwTimeout); } pVolume->idVolume = VolProps.idVolume; pVolume->wszPrefix = VolProps.wszPrefix; pVolume->wszShortPrefix = VolProps.wszShortPrefix; pVolume->dwType = VolProps.dwType; pVolume->dwState = VolProps.dwState; pVolume->wszComment = VolProps.wszComment; pVolume->dwTimeout = VolProps.dwTimeout; pVolume->ftPrefix = VolProps.ftPrefix; pVolume->ftState = VolProps.ftState; pVolume->ftComment = VolProps.ftComment; pVolume->dwVersion = VolProps.dwVersion; pVolume->cbRecovery = VolProps.cbRecovery; pVolume->pRecovery = VolProps.pRecovery; pBuffer = VolProps.pSvc; if (fSwDebug == TRUE) MyPrintf(L"VolProps.cbSvc = %d\r\n", VolProps.cbSvc); dwErr = UnSerializeReplicaList( &pVolume->ReplCount, &pVolume->AllocatedReplCount, &pVolume->ReplicaInfo, &pVolume->FtModification, &pBuffer); if (dwErr != ERROR_SUCCESS) goto Cleanup; // // Get deleted replicas // if (pBuffer < (pBuffer + VolProps.cbSvc)) { dwErr = UnSerializeReplicaList( &pVolume->DelReplCount, &pVolume->AllocatedDelReplCount, &pVolume->DelReplicaInfo, &pVolume->DelFtModification, &pBuffer); } Cleanup: if (VolProps.pSvc != NULL) MarshalBufferFree(VolProps.pSvc); if (fSwDebug == TRUE) MyPrintf(L"DfsGetVolume returning %d\r\n", dwErr); return dwErr; } //+------------------------------------------------------------------------ // // Function: DfsFreeVolList // // Synopsis: Frees the volume list and associated substructures representing // an FtDfs. // // History: 11/19/98 JHarper Created // //------------------------------------------------------------------------- VOID DfsFreeVolList( PDFS_VOLUME_LIST pDfsVolList) { ULONG cVol; ULONG cSite; ULONG i; PLIST_ENTRY pListHead; PDFSM_SITE_ENTRY pSiteEntry; if (pDfsVolList->VolCount > 0 && pDfsVolList->Volumes) { for (cVol = 0; cVol < pDfsVolList->VolCount; cVol++) { DfsFreeVol(pDfsVolList->Volumes[cVol]); free(pDfsVolList->Volumes[cVol]); pDfsVolList->Volumes[cVol] = NULL; } pDfsVolList->VolCount = 0; } if (pDfsVolList->Volumes != NULL) { free(pDfsVolList->Volumes); pDfsVolList->Volumes = NULL; } if (pDfsVolList->RootServers != NULL) { free(pDfsVolList->RootServers); pDfsVolList->RootServers = NULL; } pListHead = &pDfsVolList->SiteList; if (pListHead->Flink != NULL) { while (pListHead->Flink != pListHead) { pSiteEntry = CONTAINING_RECORD(pListHead->Flink, DFSM_SITE_ENTRY, Link); RemoveEntryList(pListHead->Flink); for (i = 0; i < pSiteEntry->Info.cSites; i++) { if (pSiteEntry->Info.Site[i].SiteName != NULL) MarshalBufferFree(pSiteEntry->Info.Site[i].SiteName); } if (pSiteEntry->ServerName != NULL) MarshalBufferFree(pSiteEntry->ServerName); free(pSiteEntry); } } } VOID DfsFreeRootLocalVol( PDFS_ROOTLOCALVOL pRootLocalVol, ULONG cRootLocalVol) { ULONG cRoot; ULONG cVol; if (pRootLocalVol == NULL) return; for (cRoot = 0; cRoot < cRootLocalVol; cRoot++) { if (pRootLocalVol[cRoot].wszObjectName != NULL) delete [] pRootLocalVol[cRoot].wszObjectName; if (pRootLocalVol[cRoot].wszEntryPath) delete [] pRootLocalVol[cRoot].wszEntryPath; if (pRootLocalVol[cRoot].wszShortEntryPath) delete [] pRootLocalVol[cRoot].wszShortEntryPath; if (pRootLocalVol[cRoot].wszShareName) delete [] pRootLocalVol[cRoot].wszShareName; if (pRootLocalVol[cRoot].wszStorageId) delete [] pRootLocalVol[cRoot].wszStorageId; for (cVol = 0; cVol < pRootLocalVol[cRoot].cLocalVolCount; cVol++) { if (pRootLocalVol[cRoot].pDfsLocalVol[cVol].wszObjectName != NULL) delete [] pRootLocalVol[cRoot].pDfsLocalVol[cVol].wszObjectName; if (pRootLocalVol[cRoot].pDfsLocalVol[cVol].wszEntryPath != NULL) delete pRootLocalVol[cRoot].pDfsLocalVol[cVol].wszEntryPath; } if (pRootLocalVol[cRoot].pDfsLocalVol) delete [] pRootLocalVol[cRoot].pDfsLocalVol; } delete [] pRootLocalVol; } //+------------------------------------------------------------------------ // // Function: DfsFreeVol // // Synopsis: Frees the volume and associated substructures representing // an FtDfs volume // // History: 12/16/98 JHarper Created // //------------------------------------------------------------------------- VOID DfsFreeVol( PDFS_VOLUME pVol) { ULONG cRepl; if (pVol->ReplCount > 0 && pVol->ReplicaInfo != NULL) { for (cRepl = 0; cRepl < pVol->ReplCount; cRepl++) { DfsFreeRepl(&pVol->ReplicaInfo[cRepl]); } } if (pVol->DelReplCount > 0 && pVol->DelReplicaInfo != NULL) { for (cRepl = 0; cRepl < pVol->DelReplCount; cRepl++) { DfsFreeRepl(&pVol->DelReplicaInfo[cRepl]); } } if (pVol->wszPrefix != NULL) MarshalBufferFree(pVol->wszPrefix); if (pVol->wszShortPrefix != NULL) MarshalBufferFree(pVol->wszShortPrefix); if (pVol->wszComment != NULL) MarshalBufferFree(pVol->wszComment); if (pVol->pRecovery != NULL) MarshalBufferFree(pVol->pRecovery); if (pVol->ReplicaInfo != NULL) free(pVol->ReplicaInfo); if (pVol->DelReplicaInfo != NULL) free(pVol->DelReplicaInfo); if (pVol->FtModification != NULL) free(pVol->FtModification); if (pVol->DelFtModification != NULL) free(pVol->DelFtModification); if (pVol->wszObjectName != NULL) free(pVol->wszObjectName); RtlZeroMemory(pVol, sizeof(DFS_VOLUME)); } //+------------------------------------------------------------------------ // // Function: DfsFreeRepl // // Synopsis: Frees the Replica and associated substructures representing // an FtDfs replica // // History: 12/16/98 JHarper Created // //------------------------------------------------------------------------- VOID DfsFreeRepl( PDFS_REPLICA_INFO pRepl) { if (pRepl->pwszServerName != NULL) MarshalBufferFree(pRepl->pwszServerName); if (pRepl->pwszShareName != NULL) MarshalBufferFree(pRepl->pwszShareName); RtlZeroMemory(pRepl, sizeof(DFS_REPLICA_INFO)); } //+------------------------------------------------------------------------ // // Function: DfsPutVolList // // Synopsis: Serializes the structs representing a Dfs volume and // creates a BLOB. // // History: 11/19/98 JHarper Created // //------------------------------------------------------------------------- DWORD DfsPutVolList( ULONG *pcbBlob, BYTE **ppBlob, PDFS_VOLUME_LIST pDfsVolList) { ULONG cVol; ULONG cRepl; ULONG cObj; ULONG cBuffer = 0; ULONG dwRecovery = 0; ULONG cSite; DWORD dwErr = ERROR_SUCCESS; PBYTE Buffer; MARSHAL_BUFFER marshalBuffer; NTSTATUS NtStatus; DFS_VOLUME_PROPERTIES VolProps; LDAP_PKT LdapPkt; PLIST_ENTRY pListHead; PLIST_ENTRY pLink; PDFSM_SITE_ENTRY pSiteEntry; if (fSwDebug == TRUE) MyPrintf(L"DfsPutVolList()\r\n"); LdapPkt.cLdapObjects = pDfsVolList->VolCount + 1; LdapPkt.rgldapObjects = (PLDAP_OBJECT) malloc(LdapPkt.cLdapObjects * sizeof(LDAP_OBJECT)); if (LdapPkt.rgldapObjects == NULL) { dwErr = ERROR_OUTOFMEMORY; goto Cleanup; } RtlZeroMemory(LdapPkt.rgldapObjects, LdapPkt.cLdapObjects * sizeof(LDAP_OBJECT)); // // For each volume, serialize the replicas, then the volume // for (cVol = 0; cVol < pDfsVolList->VolCount; cVol++) { RtlZeroMemory(&VolProps, sizeof(DFS_VOLUME_PROPERTIES)); LdapPkt.rgldapObjects[cVol].wszObjectName = (WCHAR *) MarshalBufferAllocate( (wcslen(pDfsVolList->Volumes[cVol]->wszObjectName)+1) * sizeof(WCHAR)); if (LdapPkt.rgldapObjects[cVol].wszObjectName == NULL) { dwErr = ERROR_OUTOFMEMORY; goto Cleanup; } wcscpy( LdapPkt.rgldapObjects[cVol].wszObjectName, pDfsVolList->Volumes[cVol]->wszObjectName); // // Serialize the replicas // dwErr = SerializeReplicaList( pDfsVolList->Volumes[cVol]->ReplCount, pDfsVolList->Volumes[cVol]->ReplicaInfo, pDfsVolList->Volumes[cVol]->FtModification, pDfsVolList->Volumes[cVol]->DelReplCount, pDfsVolList->Volumes[cVol]->DelReplicaInfo, pDfsVolList->Volumes[cVol]->DelFtModification, &VolProps.cbSvc, &VolProps.pSvc); if (dwErr != ERROR_SUCCESS) { dwErr = ERROR_OUTOFMEMORY; goto Cleanup; } if (fSwDebug == TRUE) MyPrintf(L" cbSvc = %d\r\n", VolProps.cbSvc); VolProps.idVolume = pDfsVolList->Volumes[cVol]->idVolume; VolProps.wszPrefix = pDfsVolList->Volumes[cVol]->wszPrefix; VolProps.wszShortPrefix = pDfsVolList->Volumes[cVol]->wszShortPrefix; VolProps.dwType = pDfsVolList->Volumes[cVol]->dwType; VolProps.dwState = pDfsVolList->Volumes[cVol]->dwState; VolProps.wszComment = pDfsVolList->Volumes[cVol]->wszComment; VolProps.dwTimeout = pDfsVolList->Volumes[cVol]->dwTimeout; VolProps.ftPrefix = pDfsVolList->Volumes[cVol]->ftPrefix; VolProps.ftState = pDfsVolList->Volumes[cVol]->ftState; VolProps.ftComment = pDfsVolList->Volumes[cVol]->ftComment; VolProps.dwVersion = pDfsVolList->Volumes[cVol]->dwVersion; if (pDfsVolList->Volumes[cVol]->cbRecovery != 0) { VolProps.cbRecovery = pDfsVolList->Volumes[cVol]->cbRecovery; VolProps.pRecovery = pDfsVolList->Volumes[cVol]->pRecovery; } else { VolProps.pRecovery = (PBYTE) MarshalBufferAllocate(sizeof(DWORD)); if (VolProps.pRecovery != NULL) { RtlZeroMemory(VolProps.pRecovery, sizeof(DWORD)); VolProps.cbRecovery = sizeof(DWORD); } else { VolProps.cbRecovery = 0; VolProps.pRecovery = NULL; } } // // Now serialize the volume cBuffer = 0; NtStatus = DfsRtlSize(&MiVolumeProperties, &VolProps, &cBuffer); if (!NT_SUCCESS(NtStatus)) { MarshalBufferFree(VolProps.pSvc); dwErr = RtlNtStatusToDosError(NtStatus); goto Cleanup; } cBuffer += sizeof(ULONG); if (fSwDebug == TRUE) MyPrintf(L"VolProps marshaled size = %d\r\n", cBuffer); Buffer = (PBYTE) MarshalBufferAllocate(cBuffer); if (Buffer == NULL) { MarshalBufferFree(VolProps.pSvc); dwErr = ERROR_OUTOFMEMORY; goto Cleanup; } LdapPkt.rgldapObjects[cVol].pObjectData = (PCHAR) Buffer; LdapPkt.rgldapObjects[cVol].cbObjectData = cBuffer; MarshalBufferInitialize( &marshalBuffer, cBuffer, Buffer); NtStatus = DfsRtlPut(&marshalBuffer, &MiVolumeProperties, &VolProps); if (!NT_SUCCESS(NtStatus)) { MarshalBufferFree(VolProps.pSvc); dwErr = RtlNtStatusToDosError(NtStatus); goto Cleanup; } NtStatus = DfsRtlPutUlong(&marshalBuffer, &VolProps.dwTimeout); if (!NT_SUCCESS(NtStatus)) { MarshalBufferFree(VolProps.pSvc); dwErr = RtlNtStatusToDosError(NtStatus); goto Cleanup; } MarshalBufferFree(VolProps.pSvc); } // // Serialize the site table // cBuffer = sizeof(ULONG) + sizeof(GUID); // // Add the size of all the entries // pListHead = &pDfsVolList->SiteList; if (pListHead->Flink != NULL) { for (pLink = pListHead->Flink; pLink != pListHead; pLink = pLink->Flink) { pSiteEntry = CONTAINING_RECORD(pLink, DFSM_SITE_ENTRY, Link); if (fSwDebug == TRUE) MyPrintf(L"pSiteEntry for %ws\r\n", pSiteEntry->ServerName); NtStatus = DfsRtlSize(&MiDfsmSiteEntry, pSiteEntry, &cBuffer); if (!NT_SUCCESS(NtStatus)) { dwErr = RtlNtStatusToDosError(NtStatus); goto Cleanup; } } } // // Get a buffer big enough // Buffer = (BYTE *) MarshalBufferAllocate(cBuffer); if (Buffer == NULL) { dwErr = ERROR_OUTOFMEMORY; goto Cleanup; } LdapPkt.rgldapObjects[pDfsVolList->VolCount].wszObjectName = (WCHAR *)MarshalBufferAllocate(sizeof(L"\\siteroot")); if (LdapPkt.rgldapObjects[pDfsVolList->VolCount].wszObjectName == NULL) { dwErr = ERROR_OUTOFMEMORY; goto Cleanup; } wcscpy(LdapPkt.rgldapObjects[pDfsVolList->VolCount].wszObjectName, L"\\siteroot"); LdapPkt.rgldapObjects[pDfsVolList->VolCount].pObjectData = (PCHAR) Buffer; LdapPkt.rgldapObjects[pDfsVolList->VolCount].cbObjectData = cBuffer; MarshalBufferInitialize( &marshalBuffer, cBuffer, Buffer); // // Put the guid, then the object count in the beginning of the buffer // DfsRtlPutGuid(&marshalBuffer, &pDfsVolList->SiteGuid); DfsRtlPutUlong(&marshalBuffer, &pDfsVolList->SiteCount); if (pListHead->Flink != NULL) { for (pLink = pListHead->Flink; pLink != pListHead; pLink = pLink->Flink) { pSiteEntry = CONTAINING_RECORD(pLink, DFSM_SITE_ENTRY, Link); DfsRtlPut(&marshalBuffer,&MiDfsmSiteEntry, pSiteEntry); if (!NT_SUCCESS(NtStatus)) { dwErr = RtlNtStatusToDosError(NtStatus); goto Cleanup; } } } if (fSwDebug == TRUE) { MyPrintf(L"After reserialization, %d objects found\r\n", LdapPkt.cLdapObjects); for (cObj = 0; cObj < LdapPkt.cLdapObjects; cObj++) { MyPrintf(L"%d:name=%ws size=%d p=0x%p\r\n", cObj, LdapPkt.rgldapObjects[cObj].wszObjectName, LdapPkt.rgldapObjects[cObj].cbObjectData, LdapPkt.rgldapObjects[cObj].pObjectData); // DumpBuf( // LdapPkt.rgldapObjects[cObj].pObjectData, // LdapPkt.rgldapObjects[cObj].cbObjectData); } } // // Finally, serialize all the volumes and the site table into a blob // cBuffer = 0; NtStatus = DfsRtlSize(&MiLdapPkt, &LdapPkt, &cBuffer); if (!NT_SUCCESS(NtStatus)) { dwErr = RtlNtStatusToDosError(dwErr); goto Cleanup; } cBuffer += sizeof(DWORD); if (fSwDebug == TRUE) MyPrintf(L"New ldap size = %d\r\n", cBuffer); Buffer = (PBYTE) malloc(cBuffer); if (Buffer == NULL) { dwErr = ERROR_OUTOFMEMORY; goto Cleanup; } *((PDWORD) Buffer) = 2; // Version # MarshalBufferInitialize( &marshalBuffer, cBuffer, Buffer + sizeof(DWORD)); NtStatus = DfsRtlPut(&marshalBuffer, &MiLdapPkt, &LdapPkt); if (!NT_SUCCESS(NtStatus)) { dwErr = RtlNtStatusToDosError(dwErr); goto Cleanup; } if (fSwDebug == TRUE) MyPrintf(L"Remarshal succeeded cBuffer = %d\r\n", cBuffer); *pcbBlob = cBuffer; *ppBlob = Buffer; Buffer = NULL; Cleanup: FreeLdapPkt(&LdapPkt); if (dwErr != ERROR_SUCCESS && Buffer != NULL) free(Buffer); if (fSwDebug == TRUE) MyPrintf(L"DfsPutVolList exit %d\r\n", dwErr); return dwErr; } //+------------------------------------------------------------------------ // // Function: FreeLdapPkt // // Synopsis: Frees an LDAP_PKT structure and all substructures. // // History: 11/19/98 JHarper Created // //------------------------------------------------------------------------- VOID FreeLdapPkt( LDAP_PKT *pLdapPkt) { ULONG cObj; if (pLdapPkt->rgldapObjects != NULL) { for (cObj = 0; cObj < pLdapPkt->cLdapObjects; cObj++) { if (pLdapPkt->rgldapObjects[cObj].wszObjectName != NULL) MarshalBufferFree(pLdapPkt->rgldapObjects[cObj].wszObjectName); if (pLdapPkt->rgldapObjects[cObj].pObjectData != NULL) MarshalBufferFree(pLdapPkt->rgldapObjects[cObj].pObjectData); } MarshalBufferFree(pLdapPkt->rgldapObjects); } } //+------------------------------------------------------------------------ // // Function: SerializeReplicaList // // Synopsis: This method serializes the replica info list and the // deleted replica info list into a buffer. // // Returns: [ERROR_SUCCESS] -- If all went well. // // [ERROR_OUTOFMEMORY] - If unable to allocate the target buffer. // // History: 11/19/98 JHarper Created // //------------------------------------------------------------------------- DWORD SerializeReplicaList( ULONG ReplCount, DFS_REPLICA_INFO *pReplicaInfo, FILETIME *pFtModification, ULONG DelReplCount, DFS_REPLICA_INFO *pDelReplicaInfo, FILETIME *pDelFtModification, ULONG *cBuffer, PBYTE *ppBuffer) { DWORD dwErr = ERROR_SUCCESS; ULONG TotalSize; ULONG i; ULONG *pSize; BYTE *Buffer = NULL; ULONG *SizeBuffer = NULL; if (fSwDebug == TRUE) MyPrintf(L"SerializeReplicaList(%d,%d)\r\n", ReplCount, DelReplCount); pSize = SizeBuffer = (PULONG) malloc(sizeof(ULONG) * (ReplCount + DelReplCount)); if (SizeBuffer == NULL) { return ERROR_OUTOFMEMORY; } // // Need all the size values now and later for marshalling stuff. // So we collect them here into an array. // TotalSize = 0; pSize = SizeBuffer; for (i = 0; i < ReplCount; i++) { *pSize = GetReplicaMarshalSize(&pReplicaInfo[i], &pFtModification[i]); TotalSize += *pSize; pSize++; } for (i = 0; i < DelReplCount; i++) { *pSize = GetReplicaMarshalSize(&pDelReplicaInfo[i], &pDelFtModification[i]); TotalSize += *pSize; pSize++; } // // Allocate the byte Buffer we need to pass back // // TotalSize is the size required just to 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. // 1 ULONG for count of deleted replicas // DelReplCount ULONGS for storing the marshal size of each deleted Repl // // // First calc the size of the Buffer. // TotalSize += sizeof(ULONG) * (1 + ReplCount + 1 + DelReplCount); *ppBuffer = Buffer = (PBYTE) malloc(TotalSize); if (Buffer == NULL) { free(SizeBuffer); return ERROR_OUTOFMEMORY; } // // Set the number of entries to follow in the Buffer at the start. // _PutULong(Buffer, ReplCount); Buffer += sizeof(ULONG); pSize = SizeBuffer; for (i = 0; i < 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(Buffer, *pSize); Buffer += sizeof(ULONG); dwErr = SerializeReplica( &pReplicaInfo[i], pFtModification ? &pFtModification[i] : NULL, Buffer, *pSize); if (dwErr != ERROR_SUCCESS) { free(*ppBuffer); return dwErr; } Buffer += *pSize; pSize++; } // // Now marshal the deleted Repl list. // _PutULong(Buffer, DelReplCount); Buffer += sizeof(ULONG); for (i = 0; i < DelReplCount; i++) { _PutULong(Buffer, *pSize); Buffer += sizeof(ULONG); dwErr = SerializeReplica( &pDelReplicaInfo[i], pDelFtModification ? &pDelFtModification[i] : NULL, Buffer, *pSize); if (dwErr != ERROR_SUCCESS) { free(*ppBuffer); return dwErr; } Buffer += *pSize; pSize++; } *cBuffer = TotalSize; if (fSwDebug == TRUE) MyPrintf(L"SerializeReplicaList exit %d\r\n", dwErr); return( dwErr ); } //+------------------------------------------------------------------------ // // Member: SerializeReplica // // Synopsis: Serializes a replica info structure // // Notes: The size of the buffer should have been calculated using // the function GetReplicaMarshalSize() // // History: 13-May-93 SudK Created. // 19-Nov-98 Jharper Modified. // //------------------------------------------------------------------------- DWORD SerializeReplica( DFS_REPLICA_INFO *pDfsReplicaInfo, FILETIME *pFtModification, PBYTE Buffer, ULONG Size) { DWORD dwErr; MARSHAL_BUFFER MarshalBuffer; NTSTATUS NtStatus; SYSTEMTIME st; FILETIME FtModification; if (pFtModification == NULL) { GetSystemTime( &st ); SystemTimeToFileTime( &st, &FtModification ); pFtModification = &FtModification; } MarshalBufferInitialize(&MarshalBuffer, Size, Buffer); NtStatus = DfsRtlPut(&MarshalBuffer, &MiFileTime, pFtModification); if (NT_SUCCESS(NtStatus)) NtStatus = DfsRtlPut(&MarshalBuffer, &MiDfsReplicaInfo, pDfsReplicaInfo); dwErr = RtlNtStatusToDosError(NtStatus); return dwErr; } //+---------------------------------------------------------------------- // // Member: GetReplicaMarshalSize, public // // Synopsis: Returns the size of a buffer required to marshal this // replica. // // History: 12-May-93 SudK Created. // 19-Nov-98 Jharper Modified. // //----------------------------------------------------------------------- ULONG GetReplicaMarshalSize( DFS_REPLICA_INFO *pDfsReplicaInfo, FILETIME *pFtModification) { ULONG Size = 0; NTSTATUS NtStatus; SYSTEMTIME st; FILETIME FtModification; if (pFtModification == NULL) { GetSystemTime( &st ); SystemTimeToFileTime( &st, &FtModification ); pFtModification = &FtModification; } NtStatus = DfsRtlSize(&MiFileTime, pFtModification, &Size); if (NT_SUCCESS(NtStatus)) NtStatus = DfsRtlSize(&MiDfsReplicaInfo, pDfsReplicaInfo, &Size); return(Size); } //+------------------------------------------------------------------------ // // Member: UnSerializeReplicaList // // Synopsis: Unserializes a buffer into a relica list. // // History: 20-Nov-98 Jharper created // //------------------------------------------------------------------------- DWORD UnSerializeReplicaList( ULONG *pReplCount, ULONG *pAllocatedReplCount, DFS_REPLICA_INFO **ppReplicaInfo, FILETIME **ppFtModification, BYTE **ppBuffer) { DFS_REPLICA_INFO *pReplicaInfo = NULL; FILETIME *pFtModification = NULL; ULONG ReplCount; BYTE *pBuffer = *ppBuffer; ULONG cRepl; ULONG Size; DWORD dwErr = ERROR_SUCCESS; MARSHAL_BUFFER marshalBuffer; NTSTATUS NtStatus; if (fSwDebug == TRUE) MyPrintf(L"UnSerializeReplicaList()\r\n"); // // Get # replicas // _GetULong(pBuffer, ReplCount); pBuffer += sizeof(ULONG); pReplicaInfo = (DFS_REPLICA_INFO *) malloc(sizeof(DFS_REPLICA_INFO) * ReplCount); pFtModification = (FILETIME *) malloc(sizeof(FILETIME) * ReplCount); if(pReplicaInfo == NULL || pFtModification == NULL) { dwErr = ERROR_OUTOFMEMORY; goto Cleanup; } // // Now get each replica // for (cRepl = 0; cRepl < ReplCount; cRepl++) { _GetULong(pBuffer, Size); pBuffer += sizeof(ULONG); MarshalBufferInitialize( &marshalBuffer, Size, pBuffer); NtStatus = DfsRtlGet( &marshalBuffer, &MiFileTime, &pFtModification[cRepl]); if (NT_SUCCESS(NtStatus)) { NtStatus = DfsRtlGet( &marshalBuffer, &MiDfsReplicaInfo, &pReplicaInfo[cRepl]); } if (NT_SUCCESS(NtStatus)) { pBuffer += Size; } } *ppReplicaInfo = pReplicaInfo; *ppFtModification = pFtModification; *ppBuffer = pBuffer; *pAllocatedReplCount = *pReplCount = ReplCount; Cleanup: if (dwErr != ERROR_SUCCESS) { if (pReplicaInfo != NULL) free(pReplicaInfo); if (pFtModification != NULL) free(pFtModification); } if (fSwDebug == TRUE) MyPrintf(L"UnSerializeReplicaList exit %d\r\n", dwErr); return dwErr; } //+------------------------------------------------------------------------ // // Function: DfsGetSiteTable // // Synopsis: Unserializes the buffer passed in into a dfs site table. // // Returns: [ERROR_SUCCESS] -- If all went well. // // [ERROR_OUTOFMEMORY] - If unable to allocate the target buffer. // // History: 11/19/98 JHarper Created // //------------------------------------------------------------------------- DWORD DfsGetSiteTable( PDFS_VOLUME_LIST pDfsVolList, PLDAP_OBJECT pLdapObject) { DWORD dwErr = ERROR_SUCCESS; NTSTATUS NtStatus; ULONG cSite; PDFSM_SITE_ENTRY pSiteEntry; PDFSM_SITE_ENTRY pTmpSiteEntry; MARSHAL_BUFFER marshalBuffer; BYTE *pBuffer = NULL; ULONG Size; if (fSwDebug == TRUE) MyPrintf(L"DfsGetSiteTable(%d)\r\n", pLdapObject->cbObjectData); InitializeListHead(&pDfsVolList->SiteList); MarshalBufferInitialize( &marshalBuffer, pLdapObject->cbObjectData, pLdapObject->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(pLdapObject->cbObjectData); if (pBuffer == NULL) { dwErr = ERROR_OUTOFMEMORY; goto Cleanup; } pTmpSiteEntry = (PDFSM_SITE_ENTRY)pBuffer; for (cSite = 0; cSite < pDfsVolList->SiteCount; cSite++) { RtlZeroMemory(pBuffer, pLdapObject->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) free(pBuffer); if (fSwDebug == TRUE) MyPrintf(L"DfsGetSiteTable exit dwErr=%d\r\n", dwErr); return dwErr; } //+---------------------------------------------------------------------------- // // Function: GetNetInfoEx // // Synopsis: Gets information about the volume. // // Arguments: [Level] -- Level of Information desired. // // [pDfsVol] - Pointer to DFS_VOLUME to use to fill the info // // [pInfo] -- Pointer to info struct to be filled. Pointer // members will be allocated using MIDL_user_allocate. // The type of this variable is LPDFS_INFO_3, but one // can pass in pointers to lower levels, and only the // fields appropriate for the level will be touched. // // [pcbInfo] -- On successful return, contains the size in // bytes of the returned info. The returned size does // not include the size of the DFS_INFO_3 struct itself. // // Returns: ERROR_SUCCESS -- Successfully returning info // // ERROR_OUTOFMEMORY -- Out of memory // //----------------------------------------------------------------------------- DWORD GetNetInfoEx( PDFS_VOLUME pDfsVol, DWORD Level, LPDFS_INFO_3 pInfo, LPDWORD pcbInfo) { DWORD dwErr = ERROR_SUCCESS; DWORD cbInfo = 0; DWORD cbItem; ULONG i; if (fSwDebug == TRUE) MyPrintf(L"GetNetInfoEx(%ws,%d)\r\n", pDfsVol->wszPrefix, Level); // // See if this is a Level 100 or 101. If so, we handle them right away // and return if (Level == 100) { LPDFS_INFO_100 pInfo100 = (LPDFS_INFO_100) pInfo; if (pDfsVol->wszComment != NULL) { cbItem = (wcslen(pDfsVol->wszComment) + 1) * sizeof(WCHAR); pInfo100->Comment = (LPWSTR) MIDL_user_allocate(cbItem); if (pInfo100->Comment != NULL) { wcscpy(pInfo100->Comment, pDfsVol->wszComment); cbInfo += cbItem; goto AllDone; } else { dwErr = ERROR_OUTOFMEMORY; goto AllDone; } } else { pInfo100->Comment = (LPWSTR) MIDL_user_allocate(sizeof(WCHAR)); if (pInfo100->Comment != NULL) { pInfo100->Comment[0] = UNICODE_NULL; cbInfo += sizeof(WCHAR); goto AllDone; } else { dwErr = ERROR_OUTOFMEMORY; goto AllDone; } } } if (Level == 101) { LPDFS_INFO_101 pInfo101 = (LPDFS_INFO_101) pInfo; pInfo->State = pDfsVol->dwState; goto AllDone; } // // level 4 isn't just an extension of 3, so handle it seperately // if (Level == 4) { LPDFS_INFO_4 pInfo4 = (LPDFS_INFO_4) pInfo; cbItem = sizeof(UNICODE_PATH_SEP) + (wcslen(pDfsVol->wszPrefix) + 1) * sizeof(WCHAR); pInfo4->EntryPath = (LPWSTR) MIDL_user_allocate(cbItem); if (pInfo4->EntryPath != NULL) { pInfo4->EntryPath[0] = UNICODE_PATH_SEP; wcscpy(&pInfo4->EntryPath[1], pDfsVol->wszPrefix); cbInfo += cbItem; } else { dwErr = ERROR_OUTOFMEMORY; goto AllDone; } if (pDfsVol->wszComment != NULL) { cbItem = (wcslen(pDfsVol->wszComment)+1) * sizeof(WCHAR); pInfo4->Comment = (LPWSTR) MIDL_user_allocate(cbItem); if (pInfo4->Comment != NULL) { wcscpy( pInfo4->Comment, pDfsVol->wszComment ); cbInfo += cbItem; } else { dwErr = ERROR_OUTOFMEMORY; goto AllDone; } } else { pInfo4->Comment = (LPWSTR) MIDL_user_allocate(sizeof(WCHAR)); if (pInfo4->Comment != NULL) { pInfo4->Comment[0] = UNICODE_NULL; cbInfo += sizeof(WCHAR); } else { dwErr = ERROR_OUTOFMEMORY; goto AllDone; } } pInfo4->State = pDfsVol->dwState; pInfo4->Timeout = pDfsVol->dwTimeout; pInfo4->Guid = pDfsVol->idVolume; pInfo4->NumberOfStorages = pDfsVol->ReplCount; cbItem = pInfo4->NumberOfStorages * sizeof(DFS_STORAGE_INFO); pInfo4->Storage = (LPDFS_STORAGE_INFO) MIDL_user_allocate(cbItem); if (pInfo4->Storage != NULL) { cbInfo += cbItem; for (i = 0; i < pDfsVol->ReplCount; i++) { dwErr = GetNetStorageInfo(&pDfsVol->ReplicaInfo[i],&pInfo4->Storage[i],&cbItem); cbInfo += cbItem; } if (dwErr != ERROR_SUCCESS) { for (; i > 0; i--) { MIDL_user_free(pInfo4->Storage[i-1].ServerName); MIDL_user_free(pInfo4->Storage[i-1].ShareName); } } } else { dwErr = ERROR_OUTOFMEMORY; } // // See if we need to clean up... // if (dwErr != ERROR_SUCCESS) { if (pInfo4->EntryPath != NULL) { MIDL_user_free(pInfo4->EntryPath); } if (pInfo4->Storage != NULL) { MIDL_user_free(pInfo4->Storage); } goto AllDone; } else { *pcbInfo = cbInfo; } goto AllDone; } // // Level is 1,2 or 3 // // // Fill in the Level 1 stuff // cbItem = sizeof(UNICODE_PATH_SEP) + (wcslen(pDfsVol->wszPrefix)+1) * sizeof(WCHAR); pInfo->EntryPath = (LPWSTR) MIDL_user_allocate(cbItem); if (pInfo->EntryPath != NULL) { pInfo->EntryPath[0] = UNICODE_PATH_SEP; wcscpy(&pInfo->EntryPath[1], pDfsVol->wszPrefix); cbInfo += cbItem; } else { dwErr = ERROR_OUTOFMEMORY; goto AllDone; } // // Fill in the Level 2 stuff if needed // if (Level > 1) { pInfo->State = pDfsVol->dwState; pInfo->NumberOfStorages = pDfsVol->ReplCount; if (pDfsVol->wszComment != NULL) { cbItem = (wcslen(pDfsVol->wszComment)+1) * sizeof(WCHAR); pInfo->Comment = (LPWSTR) MIDL_user_allocate(cbItem); if (pInfo->Comment != NULL) { wcscpy( pInfo->Comment, pDfsVol->wszComment ); cbInfo += cbItem; } else { dwErr = ERROR_OUTOFMEMORY; } } else { pInfo->Comment = (LPWSTR) MIDL_user_allocate(sizeof(WCHAR)); if (pInfo->Comment != NULL) { pInfo->Comment[0] = UNICODE_NULL; cbInfo += sizeof(WCHAR); } else { dwErr = ERROR_OUTOFMEMORY; } } } // // Fill in the Level 3 stuff if needed // if (dwErr == ERROR_SUCCESS && Level > 2) { cbItem = pInfo->NumberOfStorages * sizeof(DFS_STORAGE_INFO); pInfo->Storage = (LPDFS_STORAGE_INFO) MIDL_user_allocate(cbItem); if (pInfo->Storage != NULL) { cbInfo += cbItem; for (i = 0; i < pDfsVol->ReplCount; i++) { dwErr = GetNetStorageInfo(&pDfsVol->ReplicaInfo[i], &pInfo->Storage[i], &cbItem); cbInfo += cbItem; } if (dwErr != ERROR_SUCCESS) { for (; i > 0; i--) { MIDL_user_free(pInfo->Storage[i-1].ServerName); MIDL_user_free(pInfo->Storage[i-1].ShareName); } } } else { dwErr = ERROR_OUTOFMEMORY; } } // // See if we need to clean up... // if (dwErr != ERROR_SUCCESS) { if (Level > 1) { if (pInfo->EntryPath != NULL) { MIDL_user_free(pInfo->EntryPath); } } if (Level > 2) { if (pInfo->Storage != NULL) { MIDL_user_free(pInfo->Storage); } } } AllDone: // // Finally, we are done // if (dwErr == ERROR_SUCCESS) *pcbInfo = cbInfo; if (fSwDebug == TRUE) MyPrintf(L"GetNetInfoEx returning %d\r\n", dwErr); return(dwErr); } DWORD GetNetStorageInfo( PDFS_REPLICA_INFO pRepl, LPDFS_STORAGE_INFO pInfo, LPDWORD pcbInfo) { DWORD dwErr = ERROR_SUCCESS; LPWSTR wszShare; DWORD cbInfo = 0, cbItem; if (fSwDebug == TRUE) MyPrintf(L"GetNetStorageInfo(\\\\%ws\\%ws)\r\n", pRepl->pwszServerName, pRepl->pwszShareName); pInfo->State = pRepl->ulReplicaState; cbItem = (wcslen(pRepl->pwszServerName) + 1) * sizeof(WCHAR); pInfo->ServerName = (LPWSTR) MIDL_user_allocate(cbItem); if (pInfo->ServerName != NULL) { wcscpy(pInfo->ServerName, pRepl->pwszServerName); cbInfo += cbItem; } else { dwErr = ERROR_OUTOFMEMORY; } if (dwErr == ERROR_SUCCESS) { cbItem = (wcslen(pRepl->pwszShareName) + 1) * sizeof(WCHAR); pInfo->ShareName = (LPWSTR) MIDL_user_allocate(cbItem); if (pInfo->ShareName != NULL) { wcscpy( pInfo->ShareName, pRepl->pwszShareName ); cbInfo += cbItem; } else { MIDL_user_free( pInfo->ServerName ); dwErr = ERROR_OUTOFMEMORY; } } if (dwErr == ERROR_SUCCESS) *pcbInfo = cbInfo; if (fSwDebug == TRUE) MyPrintf(L"GetStorageInfo returning %d\r\n", dwErr); return( dwErr ); } //+------------------------------------------------------------------------ // // Function: DfsRemoveRootReplica // // Synopsis: Removes a Dfs root replica from the dfs root replica list // // History: 12/16/98 JHarper Created // //------------------------------------------------------------------------- DWORD DfsRemoveRootReplica( PDFS_VOLUME_LIST pDfsVolList, LPWSTR RootName) { ULONG cVol; ULONG cRepl; ULONG cRoot; DWORD dwErr = ERROR_SUCCESS; if (fSwDebug == TRUE) MyPrintf(L"DfsRemoveRootReplica(%ws)\r\n", RootName); for (cVol = 0; cVol < pDfsVolList->VolCount; cVol++) { if (wcscmp(pDfsVolList->Volumes[cVol]->wszObjectName,L"\\domainroot") != 0) continue; ScanReplicas: for (cRepl = 0; cRepl < pDfsVolList->Volumes[cVol]->ReplCount; cRepl++) { if ( _wcsicmp( pDfsVolList->Volumes[cVol]->ReplicaInfo[cRepl].pwszServerName, RootName) == 0 ) { DfsReplDeleteByIndex(pDfsVolList->Volumes[cVol], cRepl); goto ScanReplicas; } } break; } // // Remove from RootServers list, if it is there // ScanRoots: if (pDfsVolList->RootServers != NULL) { ULONG cCount = 0; for (cCount = 0; pDfsVolList->RootServers[cCount] != NULL; cCount++) NOTHING; for (cRoot = 0; cRoot < cCount; cRoot++) { if (fSwDebug == TRUE) MyPrintf(L" %d: %ws\r\n", cRoot, pDfsVolList->RootServers[cRoot]); if (wcslen(pDfsVolList->RootServers[cRoot]) > 2 && _wcsnicmp(&pDfsVolList->RootServers[cRoot][2], RootName, wcslen(RootName)) == 0) { LPWSTR VolRoot = &pDfsVolList->RootServers[cRoot][2]; WCHAR Next = 0; if (wcslen(RootName) != wcslen(VolRoot)) { Next = VolRoot[wcslen(RootName)]; } MyPrintf(L"Found match: next is %wc\n", Next); if (Next == 0 || Next == L'.' || Next == L'\\') { for (; cRoot < (cCount - 1); cRoot++) pDfsVolList->RootServers[cRoot] = pDfsVolList->RootServers[cRoot+1]; pDfsVolList->RootServers[cCount-1] = NULL; goto ScanRoots; } } } } if (fSwDebug == TRUE) MyPrintf(L"DfsRemoveRootReplica exit %d\r\n", dwErr); return dwErr; } //+---------------------------------------------------------------------------- // // Function: DfsRecoverVolList, public // // Synopsis: Walks the dfs_volume list, checking the recovery params, and // applying any recovery needed. Also applies the deleted replica // list to the volume's replica list. // // Arguments: [pDfsVolList] -- Pointer to DFS_VOLUME_LIST work on. // // Returns: // //----------------------------------------------------------------------------- DWORD DfsRecoverVolList( PDFS_VOLUME_LIST pDfsVolList) { DWORD dwErr = ERROR_SUCCESS; ULONG iVol; ULONG iRepl; ULONG iDelRepl; PDFS_VOLUME pVol; ULONG RecoveryState; ULONG Operation; ULONG OperState; if (fSwDebug == TRUE) MyPrintf(L"DfsRecoverVolList(%d volumes)\r\n", pDfsVolList->VolCount); ReStart: for (iVol = 0; dwErr == ERROR_SUCCESS && iVol < pDfsVolList->VolCount; iVol++) { pVol = pDfsVolList->Volumes[iVol]; if (pVol->cbRecovery >= sizeof(ULONG)) { _GetULong(pVol->pRecovery, RecoveryState); if (DFS_GET_RECOVERY_STATE(RecoveryState) != DFS_RECOVERY_STATE_NONE) { Operation = DFS_GET_RECOVERY_STATE(RecoveryState); OperState = DFS_GET_OPER_STAGE(RecoveryState); switch (Operation) { case DFS_RECOVERY_STATE_CREATING: if (fSwDebug == TRUE) MyPrintf(L"DFS_RECOVERY_STATE_CREATING\r\n"); dwErr = DfsVolDelete(pDfsVolList, iVol); goto ReStart; case DFS_RECOVERY_STATE_ADD_SERVICE: if (fSwDebug == TRUE) MyPrintf(L"DFS_RECOVERY_STATE_ADD_SERVICE\r\n"); // dwErr = RecoverFromAddService(OperState); ASSERT(L"DFS_RECOVERY_STATE_ADD_SERVICE - WHY?\r\n"); break; case DFS_RECOVERY_STATE_REMOVE_SERVICE: if (fSwDebug == TRUE) MyPrintf(L"DFS_RECOVERY_STATE_REMOVE_SERVICE\r\n"); // dwErr = RecoverFromRemoveService(OperState); ASSERT(L"DFS_RECOVERY_STATE_REMOVE_SERVICE - WHY?\r\n"); break; case DFS_RECOVERY_STATE_DELETE: if (fSwDebug == TRUE) MyPrintf(L"DFS_RECOVERY_STATE_DELETE\r\n"); dwErr = DfsVolDelete(pDfsVolList, iVol); goto ReStart; default: if (fSwDebug == TRUE) MyPrintf(L"default\r\n"); dwErr = ERROR_INTERNAL_DB_CORRUPTION; } } } if (pVol->pRecovery != NULL) MarshalBufferFree(pVol->pRecovery); pVol->pRecovery = NULL; pVol->cbRecovery = 0; } if (dwErr != ERROR_SUCCESS) goto AllDone; // // Now apply deleted replica list to each volume // for (iVol = 0; dwErr == ERROR_SUCCESS && iVol < pDfsVolList->VolCount; iVol++) { pVol = pDfsVolList->Volumes[iVol]; for (iDelRepl = 0; dwErr == ERROR_SUCCESS && iDelRepl < pVol->DelReplCount; iDelRepl++) { #if 0 // XXX This appears to be wrong - don't do it. dwErr = DfsReplDeleteByName( pVol, pVol->DelReplicaInfo[iDelRepl].pwszServerName, pVol->DelReplicaInfo[iDelRepl].pwszShareName); #endif DfsFreeRepl(&pVol->DelReplicaInfo[iDelRepl]); } if (pVol->DelReplicaInfo != NULL) { free(pVol->DelReplicaInfo); pVol->DelReplicaInfo = NULL; } if (pVol->DelFtModification != NULL) { free(pVol->DelFtModification); pVol->DelFtModification = NULL; } pVol->DelReplCount = 0; } AllDone: if (fSwDebug == TRUE) MyPrintf(L"DfsRecoverVolList returning %d\r\n", dwErr); return dwErr; } //+---------------------------------------------------------------------------- // // Function: DfsVolDelete, public // // Synopsis: Removes a DFS_VOLUME from DFS_VOLUME_LIST // // Arguments: [pDfsVolList] -- Pointer to DFS_VOLUME_LIST work on. // [iVol] -- Index of volume to delete // // Returns: // //----------------------------------------------------------------------------- DWORD DfsVolDelete( PDFS_VOLUME_LIST pDfsVolList, ULONG iVol) { ULONG i; DWORD dwErr = ERROR_SUCCESS; ASSERT(iVol < pDfsVolList->VolCount); if (fSwDebug == TRUE) MyPrintf(L"DfsVolDelete(%d)\r\n", iVol); // // Free any memory this Volume is using // DfsFreeVol(pDfsVolList->Volumes[iVol]); free(pDfsVolList->Volumes[iVol]); pDfsVolList->Volumes[iVol] = NULL; // // Since we're shrinking the list, we simply clip out the entry we don't want // and adjust the count. // for (i = iVol+1; i < pDfsVolList->VolCount; i++) pDfsVolList->Volumes[i-1] = pDfsVolList->Volumes[i]; pDfsVolList->VolCount--; pDfsVolList->Volumes[pDfsVolList->VolCount] = NULL; if (fSwDebug == TRUE) MyPrintf(L"DfsVolDelete returning %d\r\n", dwErr); return dwErr; } //+---------------------------------------------------------------------------- // // Function: DfsReplDeleteByIndex, public // // Synopsis: Removes a PDFS_REPLICA_INFO from a DFS_VOLUME's replica list // // Arguments: [pDfsVol] -- Pointer to DFS_VOLUME work on. // [iRepl] -- Index of replica to delete // // Returns: // //----------------------------------------------------------------------------- DWORD DfsReplDeleteByIndex( PDFS_VOLUME pVol, ULONG iRepl) { ULONG i; DWORD dwErr = ERROR_SUCCESS; ASSERT(iRepl < pVol->ReplCount); if (fSwDebug == TRUE) MyPrintf(L"DfsReplDeleteByIndex(%d)\r\n", iRepl); // // Free any memory this replica is using // DfsFreeRepl(&pVol->ReplicaInfo[iRepl]); // // Since we're shrinking the list(s), we simply clip out the entry we don't want // and adjust the count. // for (i = iRepl+1; i < pVol->ReplCount; i++) { pVol->ReplicaInfo[i-1] = pVol->ReplicaInfo[i]; pVol->FtModification[i-1] = pVol->FtModification[i]; } pVol->ReplCount--; RtlZeroMemory(&pVol->ReplicaInfo[pVol->ReplCount], sizeof(DFS_REPLICA_INFO)); if (fSwDebug == TRUE) MyPrintf(L"DfsReplDeleteByIndex returning %d\r\n", dwErr); return dwErr; } //+---------------------------------------------------------------------------- // // Function: DfsReplDeleteByName, public // // Synopsis: Removes a PDFS_REPLICA_INFO from a DFS_VOLUME's replica list. Simply // looks up the replica by name and then calls DfsReplDeleteByIndex() // // Arguments: [pDfsVol] -- Pointer to DFS_VOLUME work on. // [pwszServername] - Server Name // [pwszShareName] - Share Name // // Returns: // //----------------------------------------------------------------------------- DWORD DfsReplDeleteByName( PDFS_VOLUME pVol, LPWSTR pwszServerName, LPWSTR pwszShareName) { ULONG iRep; DWORD dwErr = ERROR_SUCCESS; if (fSwDebug == TRUE) MyPrintf(L"DfsReplDeleteByName(%ws,%ws)\r\n", pwszServerName, pwszShareName); if (pwszServerName == NULL || pwszShareName == NULL) { dwErr = ERROR_INVALID_PARAMETER; goto AllDone; } ReStart: // // Scan the volume's replica list, and if there is a match on the // passed-in servername and sharename, remove the replica. // for (iRep = 0; iRep < pVol->ReplCount; iRep++) { if (_wcsicmp(pVol->ReplicaInfo[iRep].pwszServerName, pwszServerName) == 0 && _wcsicmp(pVol->ReplicaInfo[iRep].pwszShareName, pwszShareName) == 0 ) { dwErr = DfsReplDeleteByIndex(pVol, iRep); goto ReStart; } } AllDone: if (fSwDebug == TRUE) MyPrintf(L"DfsReplDeleteByName returning %d\r\n", dwErr); return dwErr; } //+---------------------------------------------------------------------------- // // Function: DfsDelReplDelete, public // // Synopsis: Removes a PDFS_REPLICA_INFO from a DFS_VOLUME's deleted replica list // // Arguments: [pDfsVol] -- Pointer to DFS_VOLUME work on. // [iDelRepl] -- Index of Deleted replica to delete // // Returns: // //----------------------------------------------------------------------------- DWORD DfsDelReplDelete( PDFS_VOLUME pVol, ULONG iDelRepl) { ULONG i; DWORD dwErr = ERROR_SUCCESS; ASSERT(iDelRepl < pVol->DelReplCount); if (fSwDebug == TRUE) MyPrintf(L"DfsDelReplDelete(%d)\r\n", iDelRepl); // // Free any memory this replica is using // DfsFreeRepl(&pVol->DelReplicaInfo[iDelRepl]); // // Since we're shrinking the list(s), we simply clip out the entry we don't want // and adjust the count. // for (i = iDelRepl+1; i < pVol->DelReplCount; i++) { pVol->DelReplicaInfo[i-1] = pVol->DelReplicaInfo[i]; pVol->DelFtModification[i-1] = pVol->DelFtModification[i]; } pVol->DelReplCount--; RtlZeroMemory(&pVol->DelReplicaInfo[pVol->DelReplCount], sizeof(DFS_REPLICA_INFO)); if (fSwDebug == TRUE) MyPrintf(L"DfsDelReplDelete returning %d\r\n", dwErr); return dwErr; } //+---------------------------------------------------------------------------- // // Function: DfspLdapOpen // // Synopsis: Open ldap storage and returns the object name of the // Dfs-Configuration object. // // Arguments: DfsEntryPath - wszDcName - Dc name to be used // ppldap -- pointer to pointer to ldap obj, filled in on success // pwszObjectName -- pointer to LPWSTR for name of dfs-config object // // Returns: [ERROR_SUCCESS] -- Successfully returning list // // [??] - From ldap open/bind, etc. // //----------------------------------------------------------------------------- DWORD DfspLdapOpen( LPWSTR wszDcName, PSEC_WINNT_AUTH_IDENTITY pAuthIdent, LDAP **ppldap, LPWSTR pwszObjectPrefix, LPWSTR *pwszObjectName) { DWORD dwErr; DWORD i; ULONG Size; PDOMAIN_CONTROLLER_INFO pDCInfo = NULL; PLDAPMessage pMsg = NULL; LDAP *pldap = NULL; WCHAR wszConfigurationDN[MAX_PATH+1]; LPWSTR rgAttrs[5]; if (fSwDebug) MyPrintf(L"DfspLdapOpen(%ws)\r\n", wszDcName); if (fSwDebug && pAuthIdent != NULL) { MyPrintf(L"User:%ws\r\n", pAuthIdent->User); MyPrintf(L"Domain:%ws\r\n", pAuthIdent->Domain); MyPrintf(L"Password:%ws\r\n", pAuthIdent->Password); } if ( ppldap == NULL || pwszObjectName == NULL) { dwErr = ERROR_INVALID_PARAMETER; goto Cleanup; } if (*ppldap == NULL && wszDcName == NULL) { dwErr = ERROR_INVALID_PARAMETER; goto Cleanup; } if (*ppldap == NULL) { pldap = ldap_init(wszDcName, LDAP_PORT); if (pldap == NULL) { if (fSwDebug == TRUE) MyPrintf(L"DfspLdapOpen:ldap_init failed\r\n"); dwErr = ERROR_INVALID_NAME; goto Cleanup; } dwErr = ldap_set_option(pldap, LDAP_OPT_AREC_EXCLUSIVE, LDAP_OPT_ON); if (dwErr != LDAP_SUCCESS) { pldap = NULL; goto Cleanup; } dwErr = ldap_bind_s(pldap, NULL, (LPWSTR)pAuthIdent, LDAP_AUTH_SSPI); if (dwErr != LDAP_SUCCESS) { if (fSwDebug == TRUE) MyPrintf(L"ldap_bind_s failed with ldap error %d\r\n", dwErr); pldap = NULL; dwErr = LdapMapErrorToWin32(dwErr); goto Cleanup; } } else { pldap = *ppldap; } // // Get attribute "defaultNameContext" containing name of entry we'll be // using for our DN // rgAttrs[0] = L"defaultnamingContext"; rgAttrs[1] = NULL; dwErr = ldap_search_s( pldap, L"", LDAP_SCOPE_BASE, L"(objectClass=*)", rgAttrs, 0, &pMsg); if (dwErr == LDAP_SUCCESS) { PLDAPMessage pEntry = NULL; PWCHAR *rgszNamingContexts = NULL; DWORD i, cNamingContexts; dwErr = ERROR_SUCCESS; if ((pEntry = ldap_first_entry(pldap, pMsg)) != NULL && (rgszNamingContexts = ldap_get_values(pldap, pEntry, rgAttrs[0])) != NULL && (cNamingContexts = ldap_count_values(rgszNamingContexts)) > 0) { wcscpy( wszConfigurationDN, *rgszNamingContexts ); } else { dwErr = ERROR_UNEXP_NET_ERR; } if (rgszNamingContexts != NULL) ldap_value_free( rgszNamingContexts ); } else { dwErr = LdapMapErrorToWin32(dwErr); } if (dwErr != ERROR_SUCCESS) { if (fSwDebug == TRUE) MyPrintf(L"Unable to find Configuration naming context\r\n"); goto Cleanup; } // // Create string with full object name // Size = wcslen(pwszObjectPrefix) * sizeof(WCHAR) + sizeof(WCHAR) + wcslen(wszConfigurationDN) * sizeof(WCHAR) + sizeof(WCHAR); *pwszObjectName = (LPWSTR)malloc(Size); if (*pwszObjectName == NULL) { dwErr = ERROR_OUTOFMEMORY; goto Cleanup; } wcscpy(*pwszObjectName,pwszObjectPrefix); wcscat(*pwszObjectName,L","); wcscat(*pwszObjectName,wszConfigurationDN); if (fSwDebug == TRUE) MyPrintf(L"DfsLdapOpen:object name=[%ws]\r\n", *pwszObjectName); Cleanup: if (pDCInfo != NULL) NetApiBufferFree( pDCInfo ); if (dwErr != ERROR_SUCCESS && *ppldap == NULL) { ldap_unbind( pldap ); pldap = NULL; } if (pMsg != NULL) ldap_msgfree( pMsg ); if (*ppldap == NULL) *ppldap = pldap; if (fSwDebug == TRUE) MyPrintf(L"DfsLdapOpen:returning %d\r\n", dwErr); return( dwErr ); } //+---------------------------------------------------------------------------- // // Function: DfspGetPdc // // Synopsis: Gets the PDC // // Arguments: None // // Returns: ERROR_SUCCESS or failure // //----------------------------------------------------------------------------- DWORD DfspGetPdc( LPWSTR pwszPdcName, LPWSTR pwszDomainName) { DWORD dwErr; PDOMAIN_CONTROLLER_INFO pDCInfo; if (fSwDebug == TRUE) MyPrintf(L"DfspGetPdc(%ws)\r\n", pwszDomainName); dwErr = DsGetDcName( NULL, // Computer to remote to pwszDomainName, // Domain - use local domain NULL, // Domain Guid NULL, // Site Guid DS_PDC_REQUIRED | DS_FORCE_REDISCOVERY, &pDCInfo); if (dwErr == ERROR_SUCCESS) { wcscpy(pwszPdcName, &pDCInfo->DomainControllerName[2]); NetApiBufferFree(pDCInfo); } if (fSwDebug == TRUE) MyPrintf(L"DfspGetPdc() returning %d\r\n", dwErr); return dwErr; } // ==================================================================== // MIDL allocate and free // ==================================================================== PVOID MIDL_user_allocate(ULONG len) { return malloc(len); } VOID MIDL_user_free(void * ptr) { free(ptr); } void DumpBuf(PCHAR cp, ULONG len) { ULONG i, j, c; for (i = 0; i < len; i += 16) { MyPrintf(L"%08x ", i /* +(ULONG)cp */); for (j = 0; j < 16; j++) { if (j == 8) MyPrintf(L" "); if (i+j < len) { c = cp[i+j] & 0xff; MyPrintf(L"%02x ", c); } else { MyPrintf(L" "); } } MyPrintf(L" "); for (j = 0; j < 16; j++) { if (j == 8) MyPrintf(L"|"); if (i+j < len) { c = cp[i+j] & 0xff; if (c < ' ' || c > '~') c = '.'; MyPrintf(L"%c", c); } else { MyPrintf(L" "); } } MyPrintf(L"\r\n"); } } //+------------------------------------------------------------------------ // // Function: DfsDumpVolList // // Synopsis: Prints the volume information represented by the volume // list passed in. // // Returns: Usually. // //------------------------------------------------------------------------- VOID DfsDumpVolList( PDFS_VOLUME_LIST pDfsVolList) { ULONG cVol; ULONG cRepl; ULONG cSite; ULONG cRoot; ULONG i; GUID guid; PLIST_ENTRY pListHead; PLIST_ENTRY pLink; PDFSM_SITE_ENTRY pSiteEntry; WCHAR wszGuid[sizeof(GUID) * sizeof(WCHAR) + sizeof(WCHAR)]; MyPrintf(L"****************************************\r\n"); MyPrintf(L"Type is %d (%ws)\r\n", pDfsVolList->DfsType, pDfsVolList->DfsType == DOMUNKNONN ? L"Unknown" : pDfsVolList->DfsType == DOMDFS ? L"DomDfs" : L"StdDfs"); if (pDfsVolList->RootServers != NULL) { MyPrintf(L"remoteServerName:"); for (cRoot = 0; pDfsVolList->RootServers[cRoot] != NULL; cRoot++) MyPrintf(L"[%ws]", pDfsVolList->RootServers[cRoot]); MyPrintf(L"\r\n"); } MyPrintf(L"There are %d dfs-links in this Dfs.\r\n", pDfsVolList->VolCount); for (cVol = 0; cVol < pDfsVolList->VolCount; cVol++) { MyPrintf(L"------------------------\r\n"); MyPrintf(L"ID:\r\n"); MyPrintf(L" Name=%ws\r\n", pDfsVolList->Volumes[cVol]->wszObjectName); MyPrintf(L" Prefix: %ws\r\n", pDfsVolList->Volumes[cVol]->wszPrefix); MyPrintf(L" ShortPrefix: %ws\r\n", pDfsVolList->Volumes[cVol]->wszShortPrefix); MyPrintf(L" idVolume: %ws\r\n", GuidToStringEx(&pDfsVolList->Volumes[cVol]->idVolume, wszGuid)); MyPrintf(L" Comment: %ws\r\n", pDfsVolList->Volumes[cVol]->wszComment); MyPrintf(L" Timeout: %d\r\n", pDfsVolList->Volumes[cVol]->dwTimeout); MyPrintf(L" Type: %x\r\n", pDfsVolList->Volumes[cVol]->dwType); MyPrintf(L" cbRecovery: %d\r\n", pDfsVolList->Volumes[cVol]->cbRecovery); MyPrintf(L"Svc:\r\n"); MyPrintf(L" ReplCount=%d\r\n", pDfsVolList->Volumes[cVol]->ReplCount); MyPrintf(L" AllocatedReplCount=%d\r\n", pDfsVolList->Volumes[cVol]->AllocatedReplCount); for (cRepl = 0; cRepl < pDfsVolList->Volumes[cVol]->ReplCount; cRepl++) { MyPrintf(L" [%d]ReplicaState=0x%x\r\n", cRepl, pDfsVolList->Volumes[cVol]->ReplicaInfo[cRepl].ulReplicaState); MyPrintf(L" [%d]ReplicaType=0x%x\r\n", cRepl, pDfsVolList->Volumes[cVol]->ReplicaInfo[cRepl].ulReplicaType); MyPrintf(L" [%d]ServerName=%ws\r\n", cRepl, pDfsVolList->Volumes[cVol]->ReplicaInfo[cRepl].pwszServerName); MyPrintf(L" [%d]ShareName=%ws\r\n", cRepl, pDfsVolList->Volumes[cVol]->ReplicaInfo[cRepl].pwszShareName); } MyPrintf(L"Recovery:\r\n"); MyPrintf(L" DelReplCount=%d\r\n", pDfsVolList->Volumes[cVol]->DelReplCount); MyPrintf(L" AllocatedDelReplCount=%d\r\n", pDfsVolList->Volumes[cVol]->AllocatedDelReplCount); for (cRepl = 0; cRepl < pDfsVolList->Volumes[cVol]->DelReplCount; cRepl++) { MyPrintf(L" [%d]ReplicaState=0x%x\r\n", cRepl, pDfsVolList->Volumes[cVol]->DelReplicaInfo[cRepl].ulReplicaState); MyPrintf(L" [%d]ReplicaType=0x%x\r\n", cRepl, pDfsVolList->Volumes[cVol]->DelReplicaInfo[cRepl].ulReplicaType); MyPrintf(L" [%d]ServerName=%ws\r\n", cRepl, pDfsVolList->Volumes[cVol]->DelReplicaInfo[cRepl].pwszServerName); MyPrintf(L" [%d]ShareName=%ws\r\n", cRepl, pDfsVolList->Volumes[cVol]->DelReplicaInfo[cRepl].pwszShareName); } MyPrintf(L"\r\n"); } pListHead = &pDfsVolList->SiteList; if (pListHead->Flink != NULL) { MyPrintf(L"---------SiteTable-------\r\n"); guid = pDfsVolList->SiteGuid; MyPrintf(L"SiteTableGuid:" L"%08lX-%04X-%04X-%02X%02X%02X%02X%02X%02X%02X%02X\r\n", guid.Data1, guid.Data2, guid.Data3, (int) guid.Data4[0], (int) guid.Data4[1], (int) guid.Data4[2], (int) guid.Data4[3], (int) guid.Data4[4], (int) guid.Data4[5], (int) guid.Data4[6], (int) guid.Data4[7]); for (pLink = pListHead->Flink; pLink != pListHead; pLink = pLink->Flink) { pSiteEntry = CONTAINING_RECORD(pLink, DFSM_SITE_ENTRY, Link); MyPrintf(L"[%ws-%d sites]\r\n", pSiteEntry->ServerName, pSiteEntry->Info.cSites); for (i = 0; i < pSiteEntry->Info.cSites; i++) { MyPrintf(L"\t%ws\r\n", pSiteEntry->Info.Site[i].SiteName); } } } } VOID DfsDumpExitPtList( PDFS_ROOTLOCALVOL pRootLocalVol, ULONG cRootLocalVol) { ULONG cRoot; ULONG cVol; for (cRoot = 0; cRoot < cRootLocalVol; cRoot++) { if (pRootLocalVol[cRoot].wszObjectName == NULL) continue; MyPrintf(L"LocalVolume ROOT:[%ws]\r\n", pRootLocalVol[cRoot].wszObjectName); if (pRootLocalVol[cRoot].wszEntryPath) MyPrintf(L"EntryPath:[%ws]\r\n", pRootLocalVol[cRoot].wszEntryPath); if (pRootLocalVol[cRoot].wszShortEntryPath) MyPrintf(L"ShortEntryPath:[%ws]\r\n", pRootLocalVol[cRoot].wszShortEntryPath); if (pRootLocalVol[cRoot].wszShareName) MyPrintf(L"ShareName:[%ws]\r\n", pRootLocalVol[cRoot].wszShareName); if (pRootLocalVol[cRoot].wszStorageId) MyPrintf(L"StorageId:[%ws]\r\n", pRootLocalVol[cRoot].wszStorageId); MyPrintf(L"EntryType:0x%x\r\n", pRootLocalVol[cRoot].dwEntryType); MyPrintf(L"cLocalVolCount:%d\r\n", pRootLocalVol[cRoot].cLocalVolCount); for (cVol = 0; cVol < pRootLocalVol[cRoot].cLocalVolCount; cVol++) { if (pRootLocalVol[cRoot].pDfsLocalVol[cVol].wszObjectName != NULL) MyPrintf(L" [%ws]\r\n", pRootLocalVol[cRoot].pDfsLocalVol[cVol].wszObjectName); if (pRootLocalVol[cRoot].pDfsLocalVol[cVol].wszEntryPath != NULL) MyPrintf(L" [%ws]\r\n", pRootLocalVol[cRoot].pDfsLocalVol[cVol].wszEntryPath); } } } //+---------------------------------------------------------------------------- // // Function: GuidToStringEx // // Synopsis: Converts a GUID to a 32 char wchar null terminated string. // // Arguments: [pGuid] -- Pointer to Guid structure. // [pwszGuid] -- wchar buffer into which to put the string // representation of the GUID. Must be atleast // 2 * sizeof(GUID) + 1 long. // // Returns: The string passed in // //----------------------------------------------------------------------------- const WCHAR rgwchHexDigits[] = L"0123456789ABCDEF"; LPWSTR GuidToStringEx( GUID *pGuid, LPWSTR pwszGuid) { PBYTE pbBuffer = (PBYTE) pGuid; USHORT i; for(i = 0; i < sizeof(GUID); i++) { pwszGuid[2 * i] = rgwchHexDigits[(pbBuffer[i] >> 4) & 0xF]; pwszGuid[2 * i + 1] = rgwchHexDigits[pbBuffer[i] & 0xF]; } pwszGuid[2 * i] = UNICODE_NULL; return pwszGuid; } //+---------------------------------------------------------------------------- // // 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( PWSTR pwszGuid, 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; } } //+------------------------------------------------------------------------ // // Function: DfsViewVolList // // Synopsis: Prints the volume information represented by the volume // list passed in, in the 'dfscmd/view /full' format, and // also prints the site table. // //------------------------------------------------------------------------- VOID DfsViewVolList( PDFS_VOLUME_LIST pDfsVolList, ULONG Level) { ULONG cRoot; ULONG cVol; ULONG cRepl; ULONG cSite; ULONG i; PLIST_ENTRY pListHead; PLIST_ENTRY pLink; PDFSM_SITE_ENTRY pSiteEntry; WCHAR wszGuid[sizeof(GUID) * sizeof(WCHAR) + sizeof(WCHAR)]; if (Level <= 1) { MyPrintf(L"Type is %ws\r\n", pDfsVolList->DfsType == DOMUNKNONN ? L"Unknown" : pDfsVolList->DfsType == DOMDFS ? L"DomDfs" : L"StdDfs"); MyPrintf(L"There are %d dfs-links in this Dfs.\r\n", pDfsVolList->VolCount); if (Level == 1) { MyPrintf(L"Version:%d\r\n", pDfsVolList->Version); if (pDfsVolList->RootServers != NULL) { MyPrintf(L"remoteServerName:"); for (cRoot = 0; pDfsVolList->RootServers[cRoot] != NULL; cRoot++) MyPrintf(L"[%ws]", pDfsVolList->RootServers[cRoot]); MyPrintf(L"\r\n"); } } MyPrintf(L"\r\n"); for (cVol = 0; cVol < pDfsVolList->VolCount; cVol++) { MyPrintf(L"\\%ws [%ws]\r\n", pDfsVolList->Volumes[cVol]->wszPrefix, pDfsVolList->Volumes[cVol]->wszComment); if (Level == 1) { MyPrintf(L" GUID: %ws\r\n", GuidToStringEx(&pDfsVolList->Volumes[cVol]->idVolume, wszGuid)); MyPrintf(L" ShortPrefix: %ws\r\n", pDfsVolList->Volumes[cVol]->wszShortPrefix); MyPrintf(L" ObjectName: %ws\r\n", pDfsVolList->Volumes[cVol]->wszObjectName); MyPrintf(L" State:0x%x Type:0x%x Version:0x%x\r\n", pDfsVolList->Volumes[cVol]->dwState, pDfsVolList->Volumes[cVol]->dwType, pDfsVolList->Volumes[cVol]->dwVersion); } MyPrintf(L" Timeout is %d seconds\r\n", pDfsVolList->Volumes[cVol]->dwTimeout); for (cRepl = 0; cRepl < pDfsVolList->Volumes[cVol]->ReplCount; cRepl++) { MyPrintf(L" \\\\%ws\\%ws\r\n", pDfsVolList->Volumes[cVol]->ReplicaInfo[cRepl].pwszServerName, pDfsVolList->Volumes[cVol]->ReplicaInfo[cRepl].pwszShareName); if (Level == 1) { ULONG State = pDfsVolList->Volumes[cVol]->ReplicaInfo[cRepl].ulReplicaState; ULONG Type = pDfsVolList->Volumes[cVol]->ReplicaInfo[cRepl].ulReplicaType; MyPrintf(L" State:0x%x %ws Type:0x%x %ws\r\n", State, State & DFS_STORAGE_STATE_OFFLINE ? L"(DFS_STORAGE_STATE_OFFLINE)" : State & DFS_STORAGE_STATE_ONLINE ? L"(DFS_STORAGE_STATE_ONLINE)" : L"", Type, Type == DFS_STORAGE_TYPE_DFS ? L"(DFS_STORAGE_TYPE_DFS)" : L"(DFS_STORAGE_TYPE_NONDFS)"); } } MyPrintf(L"\r\n"); } MyPrintf(L"\r\n"); pListHead = &pDfsVolList->SiteList; if (pListHead->Flink != NULL) { MyPrintf(L"Site information:\r\n"); for (pLink = pListHead->Flink; pLink != pListHead; pLink = pLink->Flink) { pSiteEntry = CONTAINING_RECORD(pLink, DFSM_SITE_ENTRY, Link); MyPrintf(L"%ws\r\n", pSiteEntry->ServerName); for (i = 0; i < pSiteEntry->Info.cSites; i++) { MyPrintf(L" %ws\r\n", pSiteEntry->Info.Site[i].SiteName); } } } } } DWORD CmdDomUnmap( LPWSTR pwszDomDfsName, LPWSTR pwszRootName, LPWSTR pwszDcName, PSEC_WINNT_AUTH_IDENTITY pAuthIdent) { DWORD dwErr = ERROR_SUCCESS; WCHAR wszDfsConfigDN[MAX_PATH+1]; WCHAR *wszConfigurationDN = NULL; LDAP *pldap = NULL; LPWSTR pwszDfsName = NULL; LPWSTR pwszShareName = NULL; LPWSTR pwszDomName = NULL; LPWSTR pwszRootServer = NULL; LPWSTR pwszRootShare = NULL; BOOLEAN IsDomainName = FALSE; if (fSwDebug == TRUE) MyPrintf(L"CmdDomUnmap(%ws,%ws,%ws,0x%p)\r\n", pwszDomDfsName, pwszRootName, pwszDcName, pAuthIdent); if (pwszDomDfsName == NULL) { dwErr = ERROR_INVALID_PARAMETER; goto Cleanup; } dwErr = DfspParseName( pwszDomDfsName, &pwszDomName, &pwszDfsName); if (dwErr != ERROR_SUCCESS) goto Cleanup; dwErr = DfspIsDomainName( pwszDomName, pwszDcName, &IsDomainName); if (dwErr != ERROR_SUCCESS) goto Cleanup; if (IsDomainName != TRUE) { dwErr = ERROR_NO_SUCH_DOMAIN; goto Cleanup; } if (pwszDcName == NULL) { dwErr = DfspGetPdc(wszDcName, pwszDomName); } else { wcscpy(wszDcName, pwszDcName); } if (dwErr != ERROR_SUCCESS) goto Cleanup; ErrorMessage(MSG_CONNECTING, wszDcName); // // If pwszRootName is not NULL, we delete one root only // if (pwszRootName != NULL) { dwErr = DfspParseName( pwszRootName, &pwszRootServer, &pwszRootShare); if (dwErr != ERROR_SUCCESS) goto Cleanup; dwErr = CmdUnmapOneRoot( pwszDfsName, pwszRootServer, wszDcName, pwszDomName, pAuthIdent); goto Cleanup; } // // Delete the whole thing... // dwErr = DfspLdapOpen(wszDcName, pAuthIdent, &pldap, DfsConfigContainer, &wszConfigurationDN); if (dwErr != ERROR_SUCCESS) goto Cleanup; // // Build the entry name we want to delete // wcscpy(wszDfsConfigDN,L"CN="); wcscat(wszDfsConfigDN,pwszDfsName); wcscat(wszDfsConfigDN,L","); wcscat(wszDfsConfigDN,wszConfigurationDN); MyPrintf(L"DS object to delete:\"%ws\"\r\n", wszDfsConfigDN); dwErr = ldap_delete_s( pldap, wszDfsConfigDN); if (dwErr != LDAP_SUCCESS) dwErr = LdapMapErrorToWin32(dwErr); Cleanup: if (pldap != NULL) ldap_unbind( pldap ); if (wszConfigurationDN != NULL) free(wszConfigurationDN); if (pwszDfsName != NULL) free(pwszDfsName); if (pwszShareName != NULL) free(pwszShareName); if (pwszDomName != NULL) free(pwszDomName); if (pwszRootServer != NULL) free(pwszRootServer); if (pwszRootShare != NULL) free(pwszRootShare); if (fSwDebug == TRUE) MyPrintf(L"CmdDomUnmap exit %d\r\n", dwErr); return dwErr; } DWORD CmdUnmapOneRoot( LPWSTR pwszDomDfsName, LPWSTR pwszRootName, LPWSTR pwszDcName, LPWSTR pwszDomainName, PSEC_WINNT_AUTH_IDENTITY pAuthIdent) { DWORD dwErr = ERROR_SUCCESS; DFS_VOLUME_LIST DfsVolList = { 0 }; ULONG cbBlob = 0; BYTE *pBlob = NULL; if (fSwDebug != 0) MyPrintf(L"CmdUnmapOneRoot(%ws,%ws,%ws,%ws)\r\n", pwszDomDfsName, pwszRootName, pwszDcName, pwszDomainName); // // Get blob from Ds // dwErr = DfsGetDsBlob( pwszDomDfsName, DfsConfigContainer, pwszDcName, pAuthIdent, &cbBlob, &pBlob, &DfsVolList.RootServers); if (dwErr != ERROR_SUCCESS) goto Cleanup; // // Unserialize it // dwErr = DfsGetVolList( cbBlob, pBlob, &DfsVolList); if (dwErr != ERROR_SUCCESS) goto Cleanup; // // Free the blob // free(pBlob); pBlob = NULL; if (fSwDebug != 0) DfsDumpVolList(&DfsVolList); // // Remove the root/server/machine // dwErr = DfsRemoveRootReplica(&DfsVolList, pwszRootName); if (dwErr != ERROR_SUCCESS) goto Cleanup; if (fSwDebug != 0) DfsDumpVolList(&DfsVolList); // // Serialize it // dwErr = DfsPutVolList( &cbBlob, &pBlob, &DfsVolList); if (dwErr != ERROR_SUCCESS) goto Cleanup; // // Update the DS // dwErr = DfsPutDsBlob( pwszDomDfsName, DfsConfigContainer, pwszDcName, pAuthIdent, cbBlob, pBlob, DfsVolList.RootServers); // // Free the volume list we created // DfsFreeVolList(&DfsVolList); Cleanup: if (pBlob != NULL) free(pBlob); if (DfsVolList.VolCount > 0 && DfsVolList.Volumes != NULL) DfsFreeVolList(&DfsVolList); if (fSwDebug != 0) MyPrintf(L"CmdUnmapOneRoot returning %d\r\n", dwErr); return( dwErr ); } DWORD DfsSetFtOnSite( LPWSTR pwszDomainName, LPWSTR pwszShareName, LPWSTR pwszLinkName, LPWSTR pwszDcName, PSEC_WINNT_AUTH_IDENTITY pAuthIdent, ULONG Set) { DWORD dwErr = ERROR_SUCCESS; DFS_VOLUME_LIST DfsVolList = { 0 }; ULONG cbBlob = 0; BYTE *pBlob = NULL; WCHAR wszDcName[MAX_PATH+1]; if (fSwDebug != 0) MyPrintf(L"DfsSetFtOnSite(%ws,%ws,%ws)\r\n", pwszDomainName, pwszShareName, pwszLinkName); if (pwszDcName == NULL) { dwErr = DfspGetPdc(wszDcName, pwszDomainName); } else { wcscpy(wszDcName, pwszDcName); } if (dwErr != ERROR_SUCCESS) goto Cleanup; // // Get blob from Ds // dwErr = DfsGetDsBlob( pwszShareName, DfsConfigContainer, wszDcName, pAuthIdent, &cbBlob, &pBlob, &DfsVolList.RootServers); if (dwErr != ERROR_SUCCESS) goto Cleanup; // // Unserialize it // dwErr = DfsGetVolList( cbBlob, pBlob, &DfsVolList); if (dwErr != ERROR_SUCCESS) goto Cleanup; // // Free the blob // free(pBlob); pBlob = NULL; if (fSwDebug != 0) DfsDumpVolList(&DfsVolList); // // Update the site referral info: either set or reset the flag // dwErr = DfsUpdateSiteReferralInfo(&DfsVolList, pwszLinkName, Set); if (dwErr != ERROR_SUCCESS) goto Cleanup; if (fSwDebug != 0) DfsDumpVolList(&DfsVolList); // // Serialize it // dwErr = DfsPutVolList( &cbBlob, &pBlob, &DfsVolList); if (dwErr != ERROR_SUCCESS) goto Cleanup; // // Update the DS // dwErr = DfsPutDsBlob( pwszShareName, DfsConfigContainer, wszDcName, pAuthIdent, cbBlob, pBlob, DfsVolList.RootServers); // // Free the volume list we created // DfsFreeVolList(&DfsVolList); Cleanup: if (pBlob != NULL) free(pBlob); if (DfsVolList.VolCount > 0 && DfsVolList.Volumes != NULL) DfsFreeVolList(&DfsVolList); if (fSwDebug != 0) MyPrintf(L"CmdUnmapOneRoot returning %d\r\n", dwErr); return( dwErr ); } //+------------------------------------------------------------------------ // // Function: DfsUpdateSiteReferralInfo( // // Synopsis: Update the referral site info for the volume // //------------------------------------------------------------------------- DWORD DfsUpdateSiteReferralInfo( PDFS_VOLUME_LIST pDfsVolList, LPWSTR wszPrefixMatch, ULONG Set) { ULONG cVol; ULONG cRepl; ULONG cRoot; DWORD dwErr = ERROR_SUCCESS; LPWSTR usePrefix; BOOLEAN found = FALSE; if (fSwDebug == TRUE) MyPrintf(L"DfsUpdateSiteReferralInfo(%ws)\r\n", wszPrefixMatch); for (cVol = 0; cVol < pDfsVolList->VolCount; cVol++) { usePrefix = pDfsVolList->Volumes[cVol]->wszPrefix; DfspGetLinkName(usePrefix, &usePrefix); if (fSwDebug) { MyPrintf(L"Checking for Match (%ws, %ws), keyname (%ws)\n", usePrefix, pDfsVolList->Volumes[cVol]->wszShortPrefix, wszPrefixMatch); } if (_wcsicmp(usePrefix, wszPrefixMatch) == 0) { if (fSwDebug) { MyPrintf(L"Match found prefix (%ws, %ws), keyname (%ws)\n", usePrefix, pDfsVolList->Volumes[cVol]->wszShortPrefix, wszPrefixMatch); } found = TRUE; if (Set) { if (pDfsVolList->Volumes[cVol]->dwType & PKT_ENTRY_TYPE_INSITE_ONLY) { ErrorMessage(MSG_SITE_INFO_ALREADY_SET, pDfsVolList->Volumes[cVol]->wszPrefix); } else { ErrorMessage(MSG_SITE_INFO_NOW_SET, pDfsVolList->Volumes[cVol]->wszPrefix); pDfsVolList->Volumes[cVol]->dwType |= PKT_ENTRY_TYPE_INSITE_ONLY; } } else { if (pDfsVolList->Volumes[cVol]->dwType & PKT_ENTRY_TYPE_INSITE_ONLY) { ErrorMessage(MSG_SITE_INFO_NOW_SET, pDfsVolList->Volumes[cVol]->wszPrefix); pDfsVolList->Volumes[cVol]->dwType &= ~PKT_ENTRY_TYPE_INSITE_ONLY; } else { ErrorMessage(MSG_SITE_INFO_ALREADY_SET, pDfsVolList->Volumes[cVol]->wszPrefix); dwErr = ERROR_REQUEST_ABORTED; } } break; } } if (!found) { ErrorMessage(MSG_LINK_NOT_FOUND, wszPrefixMatch); dwErr = ERROR_PATH_NOT_FOUND; } if (fSwDebug == TRUE) MyPrintf(L"DfsUpdateSiteReferralInfo exit %d\r\n", dwErr); return dwErr; }