//-------------------------------------------------------------------------- // // Copyright (C) 1999, Microsoft Corporation // // File: XMLEngine.cxx // // Author: udayh // //-------------------------------------------------------------------------- #include #include #include #include #include #include #include #include #include #include #include #include "dfsutil.hxx" #include #include #include "dfsutilschema.h" #include "dfspathname.hxx" #define STANDARD_ILLEGAL_CHARS TEXT("\"&'<>") VOID DumpLoadFailureInformation( IXMLDOMParseError *pParseError); DFSSTATUS GetXMLSchema( BSTR *pSchemaBstr ) { INT j; size_t CharacterCount = 0; DFSSTATUS Status = ERROR_SUCCESS; LPWSTR SchemaCopy; for (j = 0; j < sizeof(SchemaStr)/sizeof(SchemaStr[0]); j++) { CharacterCount += wcslen(SchemaStr[j]) + 1; } CharacterCount++; SchemaCopy = new WCHAR[CharacterCount]; if (SchemaCopy == NULL) { Status = ERROR_NOT_ENOUGH_MEMORY; } if (Status == ERROR_SUCCESS) { for (j = 0; j < sizeof(SchemaStr)/sizeof(SchemaStr[0]); j++) { if (j==0) wcscpy(SchemaCopy,SchemaStr[j]); else wcscat(SchemaCopy,SchemaStr[j]); } *pSchemaBstr = SysAllocString(SchemaCopy); if (*pSchemaBstr == NULL) { Status = ERROR_NOT_ENOUGH_MEMORY; } } return Status; } VOID ReleaseXMLSchema( BSTR SchemaBstr ) { SysFreeString(SchemaBstr); return NOTHING; } HRESULT ValidateXMLDocument( IXMLDOMDocument* pXMLDoc ) { BSTR Schema; IXMLDOMDocument* pXSDDoc; HRESULT HResult; VARIANT_BOOL IsSuccessful; DFSSTATUS Status; Status = GetXMLSchema(&Schema); if (Status != ERROR_SUCCESS) { return E_FAIL; } HResult = CoCreateInstance(CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER, IID_IXMLDOMDocument, (void**)&pXSDDoc); if (SUCCEEDED(HResult)) { HResult = pXSDDoc->put_async(VARIANT_FALSE); } if (SUCCEEDED(HResult)) { HResult = pXSDDoc->loadXML(Schema, &IsSuccessful); } if (SUCCEEDED(HResult)) { IXMLDOMParseError *pParseError; if (!IsSuccessful) { ShowInformation((L"XML schema not success loaded\n")); HResult = pXSDDoc->get_parseError(&pParseError); if (SUCCEEDED(HResult)) { DumpLoadFailureInformation(pParseError); } } else { IXMLDOMSchemaCollection* pSchemaCache; HResult = CoCreateInstance(CLSID_XMLSchemaCache, NULL, CLSCTX_SERVER, IID_IXMLDOMSchemaCollection, (void**)&pSchemaCache); VARIANT vSchemas; VariantInit( &vSchemas); vSchemas.vt = VT_DISPATCH; vSchemas.pdispVal = pSchemaCache; IXMLDOMDocument2 * pDoc2 = NULL; pXMLDoc->QueryInterface(IID_IXMLDOMDocument2, (void**)&pDoc2); if (pDoc2) { VARIANT_BOOL ParseValidate = VARIANT_TRUE; pDoc2->putref_schemas( vSchemas); pDoc2->put_validateOnParse(ParseValidate); pDoc2->Release(); } VARIANT vXSD; VariantInit( &vXSD); vXSD.vt = VT_DISPATCH; vXSD.pdispVal = pXSDDoc; //hook it up with XML Document HResult = pSchemaCache->add(SysAllocString(L""), vXSD); } } return HResult; } extern DWORD GetSites(LPWSTR Target, DfsString *pSite ); DFSSTATUS InitializeVariantFromString( VARIANT *pVar, LPWSTR InString ) { DFSSTATUS Status = ERROR_SUCCESS; pVar->bstrVal = SysAllocString( InString ); if (pVar->bstrVal) { pVar->vt = VT_BSTR; } else { Status = ERROR_NOT_ENOUGH_MEMORY; } return Status; } DFSSTATUS DfsAddAttributeToTarget ( DfsTarget *pTarget, IXMLDOMNode *pAttribute ) { HRESULT HResult; BSTR AttributeName; VARIANT AttributeValue; DFSSTATUS Status = ERROR_SUCCESS; VariantInit(&AttributeValue); HResult = pAttribute->get_nodeName( &AttributeName ); if (SUCCEEDED(HResult)) { HResult = pAttribute->get_nodeValue( &AttributeValue ); } if (wcscmp((LPWSTR)AttributeName, L"Server") == 0) { Status = pTarget->SetTargetServer((LPWSTR)V_BSTR(&AttributeValue), FALSE); } else if (wcscmp((LPWSTR)AttributeName, L"Folder") == 0) { Status = pTarget->SetTargetFolder((LPWSTR)V_BSTR(&AttributeValue)); } else if (wcscmp((LPWSTR)AttributeName, L"UNCName") == 0) { Status = pTarget->SetTargetUNCName((LPWSTR)V_BSTR(&AttributeValue), FALSE); } else if (wcscmp((LPWSTR)AttributeName, L"State")==0) { ULONG State = wcstoul((LPWSTR)V_BSTR(&AttributeValue), NULL, 10 ); pTarget->SetTargetState(State); } else { Status = ERROR_INVALID_PARAMETER; } if (!SUCCEEDED(HResult)) { Status = DfsGetErrorFromHr(HResult); } return Status; } DFSSTATUS DfsProcessTargetAttributes( DfsTarget *pTarget, IXMLDOMNode *pTargetNode ) { HRESULT HResult = S_OK; DFSSTATUS Status = ERROR_SUCCESS; IXMLDOMNamedNodeMap *pTargetAttributeMap; LONG TotalAttributes; IXMLDOMNode *pAttribute; LONG Attrib; HResult = pTargetNode->get_attributes( &pTargetAttributeMap ); if (SUCCEEDED(HResult)) { HResult = pTargetAttributeMap->get_length(&TotalAttributes); if (SUCCEEDED(HResult)) { for (Attrib = 0; Attrib < TotalAttributes; Attrib++ ) { HResult = pTargetAttributeMap->get_item( Attrib, &pAttribute ); if (SUCCEEDED(HResult)) { Status = DfsAddAttributeToTarget( pTarget, pAttribute ); } } } } if (!SUCCEEDED(HResult)) { Status = DfsGetErrorFromHr(HResult); } return Status; } DFSSTATUS DfsAddTargetToLink ( DfsLink *pLink, IXMLDOMNode *pTargetNode ) { DFSSTATUS Status = ERROR_SUCCESS; DfsTarget *pTarget; pTarget = new DfsTarget; if (pTarget == NULL) { Status = ERROR_NOT_ENOUGH_MEMORY; } else { Status = DfsProcessTargetAttributes( pTarget, pTargetNode ); if (Status == ERROR_SUCCESS) { if (pTarget->IsValidTarget()) { Status = pLink->AddTarget(pTarget); } else { Status = ERROR_INVALID_PARAMETER; } } } return Status; } DFSSTATUS DfsAddAttributeToLink ( DfsLink *pLink, IXMLDOMNode *pAttribute ) { HRESULT HResult; BSTR AttributeName; VARIANT AttributeValue; DFSSTATUS Status = ERROR_SUCCESS; VariantInit(&AttributeValue); HResult = pAttribute->get_nodeName( &AttributeName ); if (SUCCEEDED(HResult)) { HResult = pAttribute->get_nodeValue( &AttributeValue ); } if (wcscmp((LPWSTR)AttributeName, L"Name")==0) { Status = pLink->SetLinkName((LPWSTR)V_BSTR(&AttributeValue)); } else if (wcscmp((LPWSTR)AttributeName, L"Comment")==0) { Status = pLink->SetLinkComment((LPWSTR)V_BSTR(&AttributeValue)); } else if (wcscmp((LPWSTR)AttributeName, L"Timeout")==0) { ULONG Timeout = wcstoul((LPWSTR)V_BSTR(&AttributeValue), NULL, 10); pLink->SetLinkTimeout(Timeout); } else if (wcscmp((LPWSTR)AttributeName, L"State")==0) { ULONG State = wcstoul((LPWSTR)V_BSTR(&AttributeValue), NULL, 10); //(LPWSTR)V_BSTR(&AttributeValue)); pLink->SetLinkState(State); } else { Status = ERROR_INVALID_PARAMETER; } if (!SUCCEEDED(HResult)) { Status = DfsGetErrorFromHr(HResult); } return Status; } DfsProcessLinkTargets( DfsLink *pLink, IXMLDOMNode *pLinkNode ) { IXMLDOMNodeList *pChildrenList; LONG Child; LONG TotalChildren; HRESULT HResult; DFSSTATUS Status = ERROR_SUCCESS; IXMLDOMNode *pTargetNode; HResult = pLinkNode->get_childNodes( &pChildrenList ); if (SUCCEEDED(HResult)) { HResult = pChildrenList->get_length(&TotalChildren); if (SUCCEEDED(HResult)) { if (TotalChildren == 0) { Status = ERROR_INVALID_PARAMETER; } for (Child = 0; ((Child < TotalChildren) && (Status == ERROR_SUCCESS)); Child++) { HResult = pChildrenList->get_item( Child, &pTargetNode); if (SUCCEEDED(HResult)) { Status = DfsAddTargetToLink( pLink, pTargetNode ); } else { break; } } } } if (!SUCCEEDED(HResult)) { Status = DfsGetErrorFromHr(HResult); } return Status; } DfsProcessLinkAttributes( DfsLink *pLink, IXMLDOMNode *pLinkNode ) { HRESULT HResult; IXMLDOMNamedNodeMap *pLinkAttributeMap; IXMLDOMNode *pAttribute; DFSSTATUS Status = ERROR_SUCCESS; LONG TotalAttributes, Attrib; HResult = pLinkNode->get_attributes( &pLinkAttributeMap ); if (SUCCEEDED(HResult)) { HResult = pLinkAttributeMap->get_length(&TotalAttributes); if (SUCCEEDED(HResult)) { for (Attrib = 0; ((Attrib < TotalAttributes) && (Status == ERROR_SUCCESS)); Attrib++ ) { HResult = pLinkAttributeMap->get_item( Attrib, &pAttribute ); if (SUCCEEDED(HResult)) { Status = DfsAddAttributeToLink( pLink, pAttribute ); } else { break; } } } } if (!SUCCEEDED(HResult)) { Status = DfsGetErrorFromHr(HResult); } return Status; } DFSSTATUS DfsAddLinkToRoot( DfsRoot *pRoot, IXMLDOMNode *pLinkNode ) { DFSSTATUS Status = ERROR_SUCCESS; DfsLink *pLink; pLink = new DfsLink; if (pLink == NULL) { Status = ERROR_NOT_ENOUGH_MEMORY; } if (Status == ERROR_SUCCESS) { Status = DfsProcessLinkTargets( pLink, pLinkNode); } if (Status == ERROR_SUCCESS) { Status = DfsProcessLinkAttributes( pLink, pLinkNode); } if (Status == ERROR_SUCCESS) { if (pLink->IsValidLink()) { Status = pRoot->AddLinks(pLink); } else { Status = ERROR_INVALID_PARAMETER; } } return Status; } DFSSTATUS DfsAddElementToRoot( DfsRoot *pRoot, IXMLDOMNode *pDomNode ) { DFSSTATUS Status = ERROR_SUCCESS; DOMNodeType NodeType; HRESULT HResult; BSTR NodeName; HResult = pDomNode->get_nodeType( &NodeType ); if (SUCCEEDED(HResult)) { switch (NodeType) { case NODE_ELEMENT: HResult = pDomNode->get_nodeName( &NodeName ); if (SUCCEEDED(HResult)) { if (wcscmp((LPWSTR)NodeName, L"Target") == 0) { Status = DfsAddTargetToLink(pRoot, pDomNode); } else if (wcscmp((LPWSTR)NodeName, L"Link") == 0) { Status = DfsAddLinkToRoot( pRoot, pDomNode); } else { Status = ERROR_INVALID_PARAMETER; } } break; default: Status = ERROR_INVALID_PARAMETER; } } if (!SUCCEEDED(HResult)) { Status = DfsGetErrorFromHr(HResult); } return Status; } DFSSTATUS DfsReadTreeRoot( DfsRoot *pRoot, IXMLDOMElement *pRootNode) { IXMLDOMNodeList *pChildrenList; LONG TotalChildren, Child; HRESULT HResult; DFSSTATUS Status = ERROR_SUCCESS; IXMLDOMNode *pRootChild; Status = DfsProcessLinkAttributes( pRoot, pRootNode); if (Status != ERROR_SUCCESS) { return Status; } HResult = pRootNode->get_childNodes( &pChildrenList ); if (SUCCEEDED(HResult)) { HResult = pChildrenList->get_length(&TotalChildren); if (SUCCEEDED(HResult)) { for (Child = 0; ((Child < TotalChildren) && (Status == ERROR_SUCCESS)); Child++) { HResult = pChildrenList->get_item( Child, &pRootChild); if (SUCCEEDED(HResult)) { Status = DfsAddElementToRoot( pRoot, pRootChild); } else { break; } } } } if (!SUCCEEDED(HResult)) { Status = DfsGetErrorFromHr(HResult); } return Status; } VOID DumpLoadFailureInformation( IXMLDOMParseError *pParseError) { BSTR Reason, Text; HRESULT HResult; LONG ErrorCode, LineNum, LinePos; HResult = pParseError->get_reason(&Reason); if (SUCCEEDED(HResult)) { HResult = pParseError->get_errorCode(&ErrorCode); } if (SUCCEEDED(HResult)) { HResult = pParseError->get_line(&LineNum); } if (SUCCEEDED(HResult)) { HResult = pParseError->get_linepos(&LinePos); } if (SUCCEEDED(HResult)) { HResult = pParseError->get_srcText(&Text); } if (SUCCEEDED(HResult)) { ShowInformation((L"\r\n\r\nERROR in import file:\r\n")); ShowInformation((L"Error Code = 0x%x\r\n", ErrorCode)); ShowInformation((L"Source = Line : %ld; Position : %ld\r\n", LineNum, LinePos)); ShowInformation((L"Error String: %wS\r\n", (LPWSTR)Text)); ShowInformation((L"Error Description: %ws\r\n\r\n", (LPWSTR)Reason)); } else { ShowInformation((L"Error in XML file: No more information available\r\n")); } } DFSSTATUS DfsReadDocument( LPWSTR FileToRead, DfsRoot **ppRoot ) { IXMLDOMElement* pRootNode; HRESULT HResult; DFSSTATUS Status = ERROR_SUCCESS; VARIANT Variant; DfsRoot *pRoot = NULL; VariantInit(&Variant); Status = InitializeVariantFromString( &Variant, FileToRead); if (Status != ERROR_SUCCESS) { return Status; } pRoot = new DfsRoot; if (pRoot != NULL) { // Declare variables. IXMLDOMDocument* pXMLDoc; // Initialize the COM library and retrieve a pointer // to an IXMLDOMDocument interface. HResult = CoInitializeEx(NULL,COINIT_MULTITHREADED| COINIT_DISABLE_OLE1DDE); if (SUCCEEDED(HResult)) { HResult = CoCreateInstance(CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER, IID_IXMLDOMDocument, (void**)&pXMLDoc); if (SUCCEEDED(HResult)) { VARIANT_BOOL IsSuccessful; HResult = ValidateXMLDocument(pXMLDoc); if (SUCCEEDED(HResult)) { HResult = pXMLDoc->load( Variant, &IsSuccessful); } if (SUCCEEDED(HResult)) { if (!IsSuccessful) { IXMLDOMParseError *pParseError; HResult = pXMLDoc->get_parseError(&pParseError); if (SUCCEEDED(HResult)) { DumpLoadFailureInformation(pParseError); } Status = ERROR_INVALID_PARAMETER; } else { if (SUCCEEDED(HResult)) { HResult = pXMLDoc->get_documentElement( &pRootNode ); if (SUCCEEDED(HResult)) { Status = DfsReadTreeRoot( pRoot, pRootNode ); } } } } } CoUninitialize(); } } else { Status = ERROR_NOT_ENOUGH_MEMORY; } if (!SUCCEEDED(HResult)) { Status = DfsGetErrorFromHr(HResult); } if (Status == ERROR_SUCCESS) { *ppRoot = pRoot; } else if (pRoot != NULL) { delete pRoot; pRoot = NULL; } return Status; } LPWSTR AmpString = L"&"; LPWSTR LtString = L"<"; LPWSTR GtString = L">"; LPWSTR QtString = L"""; LPWSTR AposString = L"'"; DFSSTATUS GetXMLStringToUse( LPWSTR UseString, BOOLEAN ScriptOut, LPWSTR *pOutString, BOOLEAN *pAllocated) { LPWSTR NewString; LONG Position; LONG CharLength, NewCharLength; DFSSTATUS Status = ERROR_SUCCESS; if (ScriptOut == FALSE) { *pOutString = UseString; *pAllocated = FALSE; return ERROR_SUCCESS; } CharLength = wcslen(UseString); Position = wcscspn(UseString, STANDARD_ILLEGAL_CHARS); if (Position == CharLength) { *pAllocated = FALSE; *pOutString = UseString; return ERROR_SUCCESS; } else { // // Allocate the maximum we ever need! In the case the string has all ', // the string will need 6 times as much space as the original string. // NewCharLength = CharLength * 6 + 1; NewString = new WCHAR[NewCharLength]; if (NewString == NULL) { Status = ERROR_NOT_ENOUGH_MEMORY; } else { LONG SpLength; LPWSTR CurrentString = NewString; LPWSTR OldString = UseString; LONG CurrentLength = NewCharLength; LONG OldLength = CharLength; RtlZeroMemory(NewString, NewCharLength * sizeof(WCHAR)); do { if (Position) { RtlCopyMemory(CurrentString, OldString, Position * sizeof(WCHAR)); } WCHAR BadChar = *(OldString + Position); OldString += (Position + 1); CurrentString += Position; CurrentLength -= Position; OldLength -= (Position + 1); switch(BadChar) { case L'&': SpLength = wcslen(AmpString); RtlCopyMemory(CurrentString, AmpString, SpLength * sizeof(WCHAR)); CurrentString += SpLength; CurrentLength -= SpLength + 1; break; case L'<': SpLength = wcslen(LtString); RtlCopyMemory(CurrentString, LtString, SpLength * sizeof(WCHAR)); CurrentString += SpLength; CurrentLength -= SpLength; break; case L'>': SpLength = wcslen(GtString); RtlCopyMemory(CurrentString, GtString, SpLength * sizeof(WCHAR)); CurrentString += SpLength; CurrentLength -= SpLength; break; case L'\"': SpLength = wcslen(QtString); RtlCopyMemory(CurrentString, QtString, SpLength * sizeof(WCHAR)); CurrentString += SpLength; CurrentLength -= SpLength; break; case L'\'': SpLength = wcslen(AposString); RtlCopyMemory(CurrentString, AposString, SpLength * sizeof(WCHAR)); CurrentString += SpLength; CurrentLength -= SpLength; break; default: Status = ERROR_INVALID_PARAMETER; } if (OldLength) { Position = wcscspn(OldString, STANDARD_ILLEGAL_CHARS); if (Position == OldLength) { RtlCopyMemory(CurrentString, OldString, Position * sizeof(WCHAR)); } } else { break; } if (CurrentLength < OldLength) { Status = ERROR_GEN_FAILURE; break; } } while (Position != OldLength); } if (Status == ERROR_SUCCESS) { *pOutString = NewString; *pAllocated = TRUE; } } return Status; } VOID ReleaseXMLStringToUse( LPWSTR UseString, BOOLEAN Allocated) { if (Allocated) { delete [] UseString; } } DFSSTATUS DumpTargetInformation ( DfsTarget *pTarget, HANDLE FileHandle, LPWSTR StartFormat, BOOLEAN ScriptOut ) { LPWSTR UseString; BOOLEAN Allocated = FALSE; DFSSTATUS Status = ERROR_SUCCESS; for ( ; pTarget != NULL; pTarget = pTarget->GetNextTarget()) { DfsPrintToFile( FileHandle, ScriptOut, L"%ws", StartFormat); if (ScriptOut) DfsPrintToFile( FileHandle, ScriptOut, L"<"); Status = GetXMLStringToUse(pTarget->GetTargetServerString(), ScriptOut, &UseString, &Allocated ); if (Status != ERROR_SUCCESS) { goto done; } DfsPrintToFile( FileHandle, ScriptOut, L"Target Server=\"%wS\" ", UseString); ReleaseXMLStringToUse(UseString, Allocated); Status = GetXMLStringToUse(pTarget->GetTargetFolderString(), ScriptOut, &UseString, &Allocated ); if (Status != ERROR_SUCCESS) { goto done; } DfsPrintToFile( FileHandle, ScriptOut, L"Folder=\"%wS\" ", UseString); ReleaseXMLStringToUse(UseString, Allocated); if (pTarget->GetTargetState()) { DfsPrintToFile( FileHandle, ScriptOut, L"State=\"%d\"", pTarget->GetTargetState()); } if (ScriptOut) { DfsPrintToFile( FileHandle, ScriptOut, L"/>"); } else { DfsPrintToFile( FileHandle, ScriptOut, L" [Site: %wS]", pTarget->GetTargetSiteString()); } } DfsPrintToFile( FileHandle, ScriptOut, L"\r\n"); done: return Status; } DFSSTATUS DumpLinkInformation( DfsLink *pLink, HANDLE FileHandle, BOOLEAN ScriptOut ) { LPWSTR UseString; BOOLEAN Allocated = FALSE; DFSSTATUS Status = ERROR_SUCCESS; for ( ; pLink != NULL; pLink = pLink->GetNextLink()) { if (pLink->GetFirstTarget() == NULL) { continue; } DfsPrintToFile( FileHandle, ScriptOut, L"\r\n\r\n\t"); if (ScriptOut) DfsPrintToFile( FileHandle, ScriptOut,L"<"); Status = GetXMLStringToUse(pLink->GetLinkNameString(), ScriptOut, &UseString, &Allocated ); if (Status != ERROR_SUCCESS) { goto done; } DfsPrintToFile( FileHandle, ScriptOut,L"Link Name=\"%wS\" ", UseString); ReleaseXMLStringToUse(UseString, Allocated); if (IsEmptyString(pLink->GetLinkCommentString()) == FALSE) { Status = GetXMLStringToUse(pLink->GetLinkCommentString(), ScriptOut, &UseString, &Allocated ); if (Status != ERROR_SUCCESS) { goto done; } DfsPrintToFile( FileHandle, ScriptOut,L"Comment=\"%wS\" ", UseString); ReleaseXMLStringToUse(UseString, Allocated); } if (pLink->GetLinkState()) { DfsPrintToFile( FileHandle, ScriptOut,L"State=\"%d\" ", pLink->GetLinkState()); } if (pLink->GetLinkTimeout()) { DfsPrintToFile( FileHandle, ScriptOut,L"Timeout=\"%d\" ", pLink->GetLinkTimeout()); } if (ScriptOut) DfsPrintToFile( FileHandle, ScriptOut,L">"); Status = DumpTargetInformation(pLink->GetFirstTarget(), FileHandle, L"\r\n\t\t", ScriptOut); if (Status != ERROR_SUCCESS) { goto done; } if (ScriptOut) DfsPrintToFile( FileHandle, ScriptOut,L"\t\r\n"); } done: return Status; } DFSSTATUS DumpRoots ( DfsRoot *pRoot, HANDLE FileHandle, BOOLEAN ScriptOut ) { LPWSTR UseString; BOOLEAN Allocated = FALSE; ULONG BlobSize = 0, Attrib = 0; DFSSTATUS Status = ERROR_SUCCESS; BOOLEAN GotBlobSize = FALSE, GotAttrib = FALSE; LPWSTR RootType = L""; if (pRoot->RootBlobSize(&BlobSize) == ERROR_SUCCESS) { GotBlobSize = TRUE; } if (pRoot->GetExtendedAttributes(&Attrib) == ERROR_SUCCESS) { GotAttrib = TRUE; } if (ScriptOut) { ULONG cch; // // we want to start the file with FFFE. This is the key word to get the file // to be recognized as containing unicode, so we support globalization. // WriteFile(FileHandle, "\xFF\xFE", 2, &cch, NULL); DfsPrintToFile( FileHandle, ScriptOut, L"\r\n"); } else { if ((pRoot->GetLinkState() & DFS_VOLUME_FLAVORS) == DFS_VOLUME_FLAVOR_STANDALONE) { RootType = L"Standalone"; } else if ((pRoot->GetLinkState() & DFS_VOLUME_FLAVORS) == DFS_VOLUME_FLAVOR_AD_BLOB) { RootType = L"Domain"; } DfsPrintToFile( FileHandle, ScriptOut,L"%ws Root with %d Links", RootType, pRoot->GetLinkCount()); if (GotBlobSize && (BlobSize != 0)) { DfsPrintToFile( FileHandle, ScriptOut,L" [Blob Size: %d bytes]", BlobSize); } DfsPrintToFile( FileHandle, ScriptOut,L"\r\n"); if (GotAttrib) { BOOLEAN Found = FALSE; if (Attrib & PKT_ENTRY_TYPE_INSITE_ONLY) { Found = TRUE; DfsPrintToFile( FileHandle, ScriptOut,L"InSite:ENABLED "); } #if 0 else { DfsPrintToFile( FileHandle, ScriptOut,L"InSite:DISABLED "); } #endif if (Attrib & PKT_ENTRY_TYPE_COST_BASED_SITE_SELECTION) { Found = TRUE; DfsPrintToFile( FileHandle, ScriptOut,L"SiteCosting:ENABLED "); } #if 0 else { DfsPrintToFile( FileHandle, ScriptOut,L"SiteCosting:DISABLED "); } #endif if (Attrib & PKT_ENTRY_TYPE_ROOT_SCALABILITY) { Found = TRUE; DfsPrintToFile( FileHandle, ScriptOut,L"RootScalability:ENABLED "); } #if 0 else { DfsPrintToFile( FileHandle, ScriptOut,L"RootScalability:DISABLED "); } #endif if (Found == FALSE) { DfsPrintToFile( FileHandle, ScriptOut,L"Root information follows "); } DfsPrintToFile( FileHandle, ScriptOut,L"\r\n"); } DfsPrintToFile( FileHandle, ScriptOut,L"\r\n"); } DfsPrintToFile( FileHandle, ScriptOut,L"\r\n"); if (ScriptOut) DfsPrintToFile( FileHandle, ScriptOut,L"<"); DfsPrintToFile( FileHandle, ScriptOut,L"Root "); if (pRoot->GetLinkNameString() != NULL) { Status = GetXMLStringToUse(pRoot->GetLinkNameString(), ScriptOut, &UseString, &Allocated ); if (Status != ERROR_SUCCESS) { goto done; } DfsPrintToFile( FileHandle, ScriptOut,L"Name=\"%ws\" ", UseString); ReleaseXMLStringToUse(UseString, Allocated); } if (IsEmptyString(pRoot->GetLinkCommentString()) == FALSE) { Status = GetXMLStringToUse(pRoot->GetLinkCommentString(), ScriptOut, &UseString, &Allocated ); if (Status != ERROR_SUCCESS) { goto done; } DfsPrintToFile( FileHandle, ScriptOut,L"Comment=\"%wS\" ", UseString); ReleaseXMLStringToUse(UseString, Allocated); } if (pRoot->GetLinkState()) { DfsPrintToFile( FileHandle, ScriptOut,L"State=\"%d\" ", pRoot->GetLinkState() & DFS_VOLUME_STATES); } if (pRoot->GetLinkTimeout()) { DfsPrintToFile( FileHandle, ScriptOut,L"Timeout=\"%d\" ", pRoot->GetLinkTimeout()); } if (ScriptOut) DfsPrintToFile( FileHandle, ScriptOut,L">"); Status = DumpTargetInformation(pRoot->GetFirstTarget(), FileHandle, L"\r\n\t", ScriptOut); if (Status != ERROR_SUCCESS) { goto done; } Status = DumpLinkInformation(pRoot->GetFirstLink(), FileHandle, ScriptOut); if (Status != ERROR_SUCCESS) { goto done; } if (ScriptOut) { DfsPrintToFile( FileHandle, ScriptOut,L"\r\n"); } else { DfsPrintToFile( FileHandle, ScriptOut,L"\r\n\r\nRoot with %d Links", pRoot->GetLinkCount()); if (GotBlobSize && (BlobSize != 0)) { DfsPrintToFile( FileHandle, ScriptOut,L" [Blob Size: %d bytes]", BlobSize); } DfsPrintToFile( FileHandle, ScriptOut,L"\r\n\r\n\r\nNOTE: All site information shown was generated by this utility.\r\n"); DfsPrintToFile( FileHandle, ScriptOut,L" Actual DFS behavior depends on site information currently in use by \r\n"); DfsPrintToFile( FileHandle, ScriptOut,L" DFS service, and may not reflect configuration changes made recently.\r\n"); } DfsPrintToFile( FileHandle, ScriptOut,L"\r\n\r\n"); done: return Status; } DFSSTATUS AddTargetCosting( DfsTarget *pTarget, PULONG pCumulative, BOOLEAN RootTarget ) { LPWSTR ServerString, FolderString; BOOLEAN ServerAllocated = FALSE, FolderAllocated = FALSE; DFSSTATUS Status = ERROR_SUCCESS; for ( ; pTarget != NULL; pTarget = pTarget->GetNextTarget()) { Status = GetXMLStringToUse(pTarget->GetTargetServerString(), FALSE, &ServerString, &ServerAllocated ); if (Status != ERROR_SUCCESS) { goto done; } Status = GetXMLStringToUse(pTarget->GetTargetFolderString(), FALSE, &FolderString, &FolderAllocated ); if (Status != ERROR_SUCCESS) { goto done; } if (RootTarget) { *pCumulative += 6; *pCumulative += wcslen(ServerString) * sizeof(WCHAR); *pCumulative += wcslen(FolderString) * sizeof(WCHAR); } *pCumulative += 20; *pCumulative += 6; *pCumulative += wcslen(ServerString) * sizeof(WCHAR); *pCumulative += wcslen(FolderString) * sizeof(WCHAR); ReleaseXMLStringToUse(ServerString, ServerAllocated); ReleaseXMLStringToUse(FolderString, FolderAllocated); } done: return Status; } DFSSTATUS AddLinkCosting( DfsLink *pLink, ULONG FixedOverhead, PULONG pCumulative ) { LPWSTR LinkNameString = NULL, CommentString = NULL; BOOLEAN LinkNameAllocated = FALSE, CommentAllocated = FALSE; DFSSTATUS Status = ERROR_SUCCESS; ULONG LinkCost; for ( ; pLink != NULL; pLink = pLink->GetNextLink()) { LinkCost = 0; if (pLink->GetFirstTarget() == NULL) { continue; } Status = GetXMLStringToUse(pLink->GetLinkNameString(), FALSE, &LinkNameString, &LinkNameAllocated ); if (Status != ERROR_SUCCESS) { break; } if (IsEmptyString(pLink->GetLinkCommentString()) == FALSE) { Status = GetXMLStringToUse(pLink->GetLinkCommentString(), FALSE, &CommentString, &CommentAllocated ); if (Status != ERROR_SUCCESS) { break; } } LinkCost += 214; LinkCost += FixedOverhead * 2; LinkCost += (wcslen(pLink->GetLinkNameString()) * sizeof(WCHAR)) * 2; if (CommentString) { LinkCost += wcslen(CommentString) * sizeof(WCHAR); } ReleaseXMLStringToUse(LinkNameString, LinkNameAllocated); ReleaseXMLStringToUse(CommentString, CommentAllocated); Status = AddTargetCosting( pLink->GetFirstTarget(), &LinkCost, FALSE); if (Status != ERROR_SUCCESS) { break; } DebugInformation((L"Cost for link %ws is %d\r\n", pLink->GetLinkNameString(), LinkCost)); *pCumulative += LinkCost; } return Status; } // //For each DFS root and for each link, the DFS overhead is 180 bytes. //The total space, in bytes, taken up by a root is 180 + (number of // characters in DFS Name * 4) + (number of characters in each root // target * 2). //The total space, in bytes, taken up by each link is 180 + (number of // characters in the link name – number of characters in the domain name) // * 4) //For each DFS root target or target, the DFS overhead is 20 bytes. //The total space, in bytes, taken up by a target is 20 + (number of // characters in target name * 2) For each unique server that is added // as a target or root target, site information takes up some space. //This space, in bytes, is 12 + (number of characters in server name // + number of characters in site name) * 2. // DFSSTATUS SizeRoot( DfsRoot *pRoot, PULONG pBlobSize ) { ULONG FixedOverhead; ULONG Cumulative = 0; DfsPathName PathName; DFSSTATUS Status; LPWSTR RootName; RootName = pRoot->GetLinkNameString(); if (IsEmptyString(RootName) == FALSE) { Status = PathName.CreatePathName(RootName); if (Status != ERROR_SUCCESS) { return Status; } FixedOverhead = wcslen(PathName.GetShareString()) * sizeof(WCHAR); Cumulative += 180 + wcslen(pRoot->GetLinkNameString()) * sizeof(WCHAR) * 2; } else { FixedOverhead = 100; Cumulative += 380; } Status = AddTargetCosting(pRoot->GetFirstTarget(), &Cumulative, TRUE); if (Status == ERROR_SUCCESS) { Status = AddLinkCosting(pRoot->GetFirstLink(), FixedOverhead, &Cumulative); } if (Status == ERROR_SUCCESS) { // 100K is the smallest amount we display. if (Cumulative < 100 * 1024) { Cumulative = 100 *1024; } *pBlobSize = Cumulative; } return Status; }