Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1476 lines
38 KiB

  1. //--------------------------------------------------------------------------
  2. //
  3. // Copyright (C) 1999, Microsoft Corporation
  4. //
  5. // File: XMLEngine.cxx
  6. //
  7. // Author: udayh
  8. //
  9. //--------------------------------------------------------------------------
  10. #include <stdio.h>
  11. #include <nt.h>
  12. #include <ntrtl.h>
  13. #include <nturtl.h>
  14. #include <windows.h>
  15. #include <shellapi.h>
  16. #include <winldap.h>
  17. #include <stdlib.h>
  18. #include <dfslink.hxx>
  19. #include <dfsroot.hxx>
  20. #include <dfstarget.hxx>
  21. #include "dfsutil.hxx"
  22. #include <ole2.h>
  23. #include <msxml2.h>
  24. #include "dfsutilschema.h"
  25. #include "dfspathname.hxx"
  26. #define STANDARD_ILLEGAL_CHARS TEXT("\"&'<>")
  27. VOID
  28. DumpLoadFailureInformation(
  29. IXMLDOMParseError *pParseError);
  30. DFSSTATUS
  31. GetXMLSchema( BSTR *pSchemaBstr )
  32. {
  33. INT j;
  34. size_t CharacterCount = 0;
  35. DFSSTATUS Status = ERROR_SUCCESS;
  36. LPWSTR SchemaCopy;
  37. for (j = 0; j < sizeof(SchemaStr)/sizeof(SchemaStr[0]); j++)
  38. {
  39. CharacterCount += wcslen(SchemaStr[j]) + 1;
  40. }
  41. CharacterCount++;
  42. SchemaCopy = new WCHAR[CharacterCount];
  43. if (SchemaCopy == NULL)
  44. {
  45. Status = ERROR_NOT_ENOUGH_MEMORY;
  46. }
  47. if (Status == ERROR_SUCCESS)
  48. {
  49. for (j = 0; j < sizeof(SchemaStr)/sizeof(SchemaStr[0]); j++)
  50. {
  51. if (j==0) wcscpy(SchemaCopy,SchemaStr[j]);
  52. else wcscat(SchemaCopy,SchemaStr[j]);
  53. }
  54. *pSchemaBstr = SysAllocString(SchemaCopy);
  55. if (*pSchemaBstr == NULL)
  56. {
  57. Status = ERROR_NOT_ENOUGH_MEMORY;
  58. }
  59. }
  60. return Status;
  61. }
  62. VOID
  63. ReleaseXMLSchema( BSTR SchemaBstr )
  64. {
  65. SysFreeString(SchemaBstr);
  66. return NOTHING;
  67. }
  68. HRESULT
  69. ValidateXMLDocument(
  70. IXMLDOMDocument* pXMLDoc )
  71. {
  72. BSTR Schema;
  73. IXMLDOMDocument* pXSDDoc;
  74. HRESULT HResult;
  75. VARIANT_BOOL IsSuccessful;
  76. DFSSTATUS Status;
  77. Status = GetXMLSchema(&Schema);
  78. if (Status != ERROR_SUCCESS)
  79. {
  80. return E_FAIL;
  81. }
  82. HResult = CoCreateInstance(CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER,
  83. IID_IXMLDOMDocument, (void**)&pXSDDoc);
  84. if (SUCCEEDED(HResult))
  85. {
  86. HResult = pXSDDoc->put_async(VARIANT_FALSE);
  87. }
  88. if (SUCCEEDED(HResult))
  89. {
  90. HResult = pXSDDoc->loadXML(Schema, &IsSuccessful);
  91. }
  92. if (SUCCEEDED(HResult))
  93. {
  94. IXMLDOMParseError *pParseError;
  95. if (!IsSuccessful)
  96. {
  97. ShowInformation((L"XML schema not success loaded\n"));
  98. HResult = pXSDDoc->get_parseError(&pParseError);
  99. if (SUCCEEDED(HResult))
  100. {
  101. DumpLoadFailureInformation(pParseError);
  102. }
  103. }
  104. else
  105. {
  106. IXMLDOMSchemaCollection* pSchemaCache;
  107. HResult = CoCreateInstance(CLSID_XMLSchemaCache, NULL, CLSCTX_SERVER,
  108. IID_IXMLDOMSchemaCollection, (void**)&pSchemaCache);
  109. VARIANT vSchemas;
  110. VariantInit( &vSchemas);
  111. vSchemas.vt = VT_DISPATCH;
  112. vSchemas.pdispVal = pSchemaCache;
  113. IXMLDOMDocument2 * pDoc2 = NULL;
  114. pXMLDoc->QueryInterface(IID_IXMLDOMDocument2, (void**)&pDoc2);
  115. if (pDoc2)
  116. {
  117. VARIANT_BOOL ParseValidate = VARIANT_TRUE;
  118. pDoc2->putref_schemas( vSchemas);
  119. pDoc2->put_validateOnParse(ParseValidate);
  120. pDoc2->Release();
  121. }
  122. VARIANT vXSD;
  123. VariantInit( &vXSD);
  124. vXSD.vt = VT_DISPATCH;
  125. vXSD.pdispVal = pXSDDoc;
  126. //hook it up with XML Document
  127. HResult = pSchemaCache->add(SysAllocString(L""), vXSD);
  128. }
  129. }
  130. return HResult;
  131. }
  132. extern DWORD
  133. GetSites(LPWSTR Target,
  134. DfsString *pSite );
  135. DFSSTATUS
  136. InitializeVariantFromString(
  137. VARIANT *pVar,
  138. LPWSTR InString )
  139. {
  140. DFSSTATUS Status = ERROR_SUCCESS;
  141. pVar->bstrVal = SysAllocString( InString );
  142. if (pVar->bstrVal)
  143. {
  144. pVar->vt = VT_BSTR;
  145. }
  146. else
  147. {
  148. Status = ERROR_NOT_ENOUGH_MEMORY;
  149. }
  150. return Status;
  151. }
  152. DFSSTATUS
  153. DfsAddAttributeToTarget (
  154. DfsTarget *pTarget,
  155. IXMLDOMNode *pAttribute )
  156. {
  157. HRESULT HResult;
  158. BSTR AttributeName;
  159. VARIANT AttributeValue;
  160. DFSSTATUS Status = ERROR_SUCCESS;
  161. VariantInit(&AttributeValue);
  162. HResult = pAttribute->get_nodeName( &AttributeName );
  163. if (SUCCEEDED(HResult))
  164. {
  165. HResult = pAttribute->get_nodeValue( &AttributeValue );
  166. }
  167. if (wcscmp((LPWSTR)AttributeName, L"Server") == 0)
  168. {
  169. Status = pTarget->SetTargetServer((LPWSTR)V_BSTR(&AttributeValue), FALSE);
  170. }
  171. else if (wcscmp((LPWSTR)AttributeName, L"Folder") == 0)
  172. {
  173. Status = pTarget->SetTargetFolder((LPWSTR)V_BSTR(&AttributeValue));
  174. }
  175. else if (wcscmp((LPWSTR)AttributeName, L"UNCName") == 0)
  176. {
  177. Status = pTarget->SetTargetUNCName((LPWSTR)V_BSTR(&AttributeValue), FALSE);
  178. }
  179. else if (wcscmp((LPWSTR)AttributeName, L"State")==0)
  180. {
  181. ULONG State = wcstoul((LPWSTR)V_BSTR(&AttributeValue),
  182. NULL,
  183. 10 );
  184. pTarget->SetTargetState(State);
  185. }
  186. else
  187. {
  188. Status = ERROR_INVALID_PARAMETER;
  189. }
  190. if (!SUCCEEDED(HResult))
  191. {
  192. Status = DfsGetErrorFromHr(HResult);
  193. }
  194. return Status;
  195. }
  196. DFSSTATUS
  197. DfsProcessTargetAttributes(
  198. DfsTarget *pTarget,
  199. IXMLDOMNode *pTargetNode )
  200. {
  201. HRESULT HResult = S_OK;
  202. DFSSTATUS Status = ERROR_SUCCESS;
  203. IXMLDOMNamedNodeMap *pTargetAttributeMap;
  204. LONG TotalAttributes;
  205. IXMLDOMNode *pAttribute;
  206. LONG Attrib;
  207. HResult = pTargetNode->get_attributes( &pTargetAttributeMap );
  208. if (SUCCEEDED(HResult))
  209. {
  210. HResult = pTargetAttributeMap->get_length(&TotalAttributes);
  211. if (SUCCEEDED(HResult))
  212. {
  213. for (Attrib = 0;
  214. Attrib < TotalAttributes;
  215. Attrib++ )
  216. {
  217. HResult = pTargetAttributeMap->get_item( Attrib,
  218. &pAttribute );
  219. if (SUCCEEDED(HResult))
  220. {
  221. Status = DfsAddAttributeToTarget( pTarget,
  222. pAttribute );
  223. }
  224. }
  225. }
  226. }
  227. if (!SUCCEEDED(HResult))
  228. {
  229. Status = DfsGetErrorFromHr(HResult);
  230. }
  231. return Status;
  232. }
  233. DFSSTATUS
  234. DfsAddTargetToLink (
  235. DfsLink *pLink,
  236. IXMLDOMNode *pTargetNode )
  237. {
  238. DFSSTATUS Status = ERROR_SUCCESS;
  239. DfsTarget *pTarget;
  240. pTarget = new DfsTarget;
  241. if (pTarget == NULL)
  242. {
  243. Status = ERROR_NOT_ENOUGH_MEMORY;
  244. }
  245. else
  246. {
  247. Status = DfsProcessTargetAttributes( pTarget, pTargetNode );
  248. if (Status == ERROR_SUCCESS)
  249. {
  250. if (pTarget->IsValidTarget())
  251. {
  252. Status = pLink->AddTarget(pTarget);
  253. }
  254. else
  255. {
  256. Status = ERROR_INVALID_PARAMETER;
  257. }
  258. }
  259. }
  260. return Status;
  261. }
  262. DFSSTATUS
  263. DfsAddAttributeToLink (
  264. DfsLink *pLink,
  265. IXMLDOMNode *pAttribute )
  266. {
  267. HRESULT HResult;
  268. BSTR AttributeName;
  269. VARIANT AttributeValue;
  270. DFSSTATUS Status = ERROR_SUCCESS;
  271. VariantInit(&AttributeValue);
  272. HResult = pAttribute->get_nodeName( &AttributeName );
  273. if (SUCCEEDED(HResult))
  274. {
  275. HResult = pAttribute->get_nodeValue( &AttributeValue );
  276. }
  277. if (wcscmp((LPWSTR)AttributeName, L"Name")==0)
  278. {
  279. Status = pLink->SetLinkName((LPWSTR)V_BSTR(&AttributeValue));
  280. }
  281. else if (wcscmp((LPWSTR)AttributeName, L"Comment")==0)
  282. {
  283. Status = pLink->SetLinkComment((LPWSTR)V_BSTR(&AttributeValue));
  284. }
  285. else if (wcscmp((LPWSTR)AttributeName, L"Timeout")==0)
  286. {
  287. ULONG Timeout = wcstoul((LPWSTR)V_BSTR(&AttributeValue),
  288. NULL,
  289. 10);
  290. pLink->SetLinkTimeout(Timeout);
  291. }
  292. else if (wcscmp((LPWSTR)AttributeName, L"State")==0)
  293. {
  294. ULONG State = wcstoul((LPWSTR)V_BSTR(&AttributeValue),
  295. NULL,
  296. 10);
  297. //(LPWSTR)V_BSTR(&AttributeValue));
  298. pLink->SetLinkState(State);
  299. }
  300. else
  301. {
  302. Status = ERROR_INVALID_PARAMETER;
  303. }
  304. if (!SUCCEEDED(HResult))
  305. {
  306. Status = DfsGetErrorFromHr(HResult);
  307. }
  308. return Status;
  309. }
  310. DfsProcessLinkTargets(
  311. DfsLink *pLink,
  312. IXMLDOMNode *pLinkNode )
  313. {
  314. IXMLDOMNodeList *pChildrenList;
  315. LONG Child;
  316. LONG TotalChildren;
  317. HRESULT HResult;
  318. DFSSTATUS Status = ERROR_SUCCESS;
  319. IXMLDOMNode *pTargetNode;
  320. HResult = pLinkNode->get_childNodes( &pChildrenList );
  321. if (SUCCEEDED(HResult))
  322. {
  323. HResult = pChildrenList->get_length(&TotalChildren);
  324. if (SUCCEEDED(HResult))
  325. {
  326. if (TotalChildren == 0)
  327. {
  328. Status = ERROR_INVALID_PARAMETER;
  329. }
  330. for (Child = 0;
  331. ((Child < TotalChildren) && (Status == ERROR_SUCCESS));
  332. Child++)
  333. {
  334. HResult = pChildrenList->get_item( Child, &pTargetNode);
  335. if (SUCCEEDED(HResult))
  336. {
  337. Status = DfsAddTargetToLink( pLink, pTargetNode );
  338. }
  339. else
  340. {
  341. break;
  342. }
  343. }
  344. }
  345. }
  346. if (!SUCCEEDED(HResult))
  347. {
  348. Status = DfsGetErrorFromHr(HResult);
  349. }
  350. return Status;
  351. }
  352. DfsProcessLinkAttributes(
  353. DfsLink *pLink,
  354. IXMLDOMNode *pLinkNode )
  355. {
  356. HRESULT HResult;
  357. IXMLDOMNamedNodeMap *pLinkAttributeMap;
  358. IXMLDOMNode *pAttribute;
  359. DFSSTATUS Status = ERROR_SUCCESS;
  360. LONG TotalAttributes, Attrib;
  361. HResult = pLinkNode->get_attributes( &pLinkAttributeMap );
  362. if (SUCCEEDED(HResult))
  363. {
  364. HResult = pLinkAttributeMap->get_length(&TotalAttributes);
  365. if (SUCCEEDED(HResult))
  366. {
  367. for (Attrib = 0;
  368. ((Attrib < TotalAttributes) && (Status == ERROR_SUCCESS));
  369. Attrib++ )
  370. {
  371. HResult = pLinkAttributeMap->get_item( Attrib,
  372. &pAttribute );
  373. if (SUCCEEDED(HResult))
  374. {
  375. Status = DfsAddAttributeToLink( pLink,
  376. pAttribute );
  377. }
  378. else
  379. {
  380. break;
  381. }
  382. }
  383. }
  384. }
  385. if (!SUCCEEDED(HResult))
  386. {
  387. Status = DfsGetErrorFromHr(HResult);
  388. }
  389. return Status;
  390. }
  391. DFSSTATUS
  392. DfsAddLinkToRoot(
  393. DfsRoot *pRoot,
  394. IXMLDOMNode *pLinkNode )
  395. {
  396. DFSSTATUS Status = ERROR_SUCCESS;
  397. DfsLink *pLink;
  398. pLink = new DfsLink;
  399. if (pLink == NULL)
  400. {
  401. Status = ERROR_NOT_ENOUGH_MEMORY;
  402. }
  403. if (Status == ERROR_SUCCESS)
  404. {
  405. Status = DfsProcessLinkTargets( pLink, pLinkNode);
  406. }
  407. if (Status == ERROR_SUCCESS)
  408. {
  409. Status = DfsProcessLinkAttributes( pLink, pLinkNode);
  410. }
  411. if (Status == ERROR_SUCCESS)
  412. {
  413. if (pLink->IsValidLink())
  414. {
  415. Status = pRoot->AddLinks(pLink);
  416. }
  417. else
  418. {
  419. Status = ERROR_INVALID_PARAMETER;
  420. }
  421. }
  422. return Status;
  423. }
  424. DFSSTATUS
  425. DfsAddElementToRoot(
  426. DfsRoot *pRoot,
  427. IXMLDOMNode *pDomNode )
  428. {
  429. DFSSTATUS Status = ERROR_SUCCESS;
  430. DOMNodeType NodeType;
  431. HRESULT HResult;
  432. BSTR NodeName;
  433. HResult = pDomNode->get_nodeType( &NodeType );
  434. if (SUCCEEDED(HResult))
  435. {
  436. switch (NodeType)
  437. {
  438. case NODE_ELEMENT:
  439. HResult = pDomNode->get_nodeName( &NodeName );
  440. if (SUCCEEDED(HResult))
  441. {
  442. if (wcscmp((LPWSTR)NodeName, L"Target") == 0)
  443. {
  444. Status = DfsAddTargetToLink(pRoot, pDomNode);
  445. }
  446. else if (wcscmp((LPWSTR)NodeName, L"Link") == 0)
  447. {
  448. Status = DfsAddLinkToRoot( pRoot, pDomNode);
  449. }
  450. else
  451. {
  452. Status = ERROR_INVALID_PARAMETER;
  453. }
  454. }
  455. break;
  456. default:
  457. Status = ERROR_INVALID_PARAMETER;
  458. }
  459. }
  460. if (!SUCCEEDED(HResult))
  461. {
  462. Status = DfsGetErrorFromHr(HResult);
  463. }
  464. return Status;
  465. }
  466. DFSSTATUS
  467. DfsReadTreeRoot(
  468. DfsRoot *pRoot,
  469. IXMLDOMElement *pRootNode)
  470. {
  471. IXMLDOMNodeList *pChildrenList;
  472. LONG TotalChildren, Child;
  473. HRESULT HResult;
  474. DFSSTATUS Status = ERROR_SUCCESS;
  475. IXMLDOMNode *pRootChild;
  476. Status = DfsProcessLinkAttributes( pRoot, pRootNode);
  477. if (Status != ERROR_SUCCESS)
  478. {
  479. return Status;
  480. }
  481. HResult = pRootNode->get_childNodes( &pChildrenList );
  482. if (SUCCEEDED(HResult))
  483. {
  484. HResult = pChildrenList->get_length(&TotalChildren);
  485. if (SUCCEEDED(HResult))
  486. {
  487. for (Child = 0;
  488. ((Child < TotalChildren) && (Status == ERROR_SUCCESS));
  489. Child++)
  490. {
  491. HResult = pChildrenList->get_item( Child, &pRootChild);
  492. if (SUCCEEDED(HResult))
  493. {
  494. Status = DfsAddElementToRoot( pRoot, pRootChild);
  495. }
  496. else
  497. {
  498. break;
  499. }
  500. }
  501. }
  502. }
  503. if (!SUCCEEDED(HResult))
  504. {
  505. Status = DfsGetErrorFromHr(HResult);
  506. }
  507. return Status;
  508. }
  509. VOID
  510. DumpLoadFailureInformation(
  511. IXMLDOMParseError *pParseError)
  512. {
  513. BSTR Reason, Text;
  514. HRESULT HResult;
  515. LONG ErrorCode, LineNum, LinePos;
  516. HResult = pParseError->get_reason(&Reason);
  517. if (SUCCEEDED(HResult))
  518. {
  519. HResult = pParseError->get_errorCode(&ErrorCode);
  520. }
  521. if (SUCCEEDED(HResult))
  522. {
  523. HResult = pParseError->get_line(&LineNum);
  524. }
  525. if (SUCCEEDED(HResult))
  526. {
  527. HResult = pParseError->get_linepos(&LinePos);
  528. }
  529. if (SUCCEEDED(HResult))
  530. {
  531. HResult = pParseError->get_srcText(&Text);
  532. }
  533. if (SUCCEEDED(HResult))
  534. {
  535. ShowInformation((L"\r\n\r\nERROR in import file:\r\n"));
  536. ShowInformation((L"Error Code = 0x%x\r\n", ErrorCode));
  537. ShowInformation((L"Source = Line : %ld; Position : %ld\r\n",
  538. LineNum, LinePos));
  539. ShowInformation((L"Error String: %wS\r\n", (LPWSTR)Text));
  540. ShowInformation((L"Error Description: %ws\r\n\r\n", (LPWSTR)Reason));
  541. }
  542. else
  543. {
  544. ShowInformation((L"Error in XML file: No more information available\r\n"));
  545. }
  546. }
  547. DFSSTATUS
  548. DfsReadDocument(
  549. LPWSTR FileToRead,
  550. DfsRoot **ppRoot )
  551. {
  552. IXMLDOMElement* pRootNode;
  553. HRESULT HResult;
  554. DFSSTATUS Status = ERROR_SUCCESS;
  555. VARIANT Variant;
  556. DfsRoot *pRoot = NULL;
  557. VariantInit(&Variant);
  558. Status = InitializeVariantFromString( &Variant, FileToRead);
  559. if (Status != ERROR_SUCCESS)
  560. {
  561. return Status;
  562. }
  563. pRoot = new DfsRoot;
  564. if (pRoot != NULL)
  565. {
  566. // Declare variables.
  567. IXMLDOMDocument* pXMLDoc;
  568. // Initialize the COM library and retrieve a pointer
  569. // to an IXMLDOMDocument interface.
  570. HResult = CoInitializeEx(NULL,COINIT_MULTITHREADED| COINIT_DISABLE_OLE1DDE);
  571. if (SUCCEEDED(HResult))
  572. {
  573. HResult = CoCreateInstance(CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER,
  574. IID_IXMLDOMDocument, (void**)&pXMLDoc);
  575. if (SUCCEEDED(HResult))
  576. {
  577. VARIANT_BOOL IsSuccessful;
  578. HResult = ValidateXMLDocument(pXMLDoc);
  579. if (SUCCEEDED(HResult))
  580. {
  581. HResult = pXMLDoc->load( Variant, &IsSuccessful);
  582. }
  583. if (SUCCEEDED(HResult))
  584. {
  585. if (!IsSuccessful)
  586. {
  587. IXMLDOMParseError *pParseError;
  588. HResult = pXMLDoc->get_parseError(&pParseError);
  589. if (SUCCEEDED(HResult))
  590. {
  591. DumpLoadFailureInformation(pParseError);
  592. }
  593. Status = ERROR_INVALID_PARAMETER;
  594. }
  595. else
  596. {
  597. if (SUCCEEDED(HResult))
  598. {
  599. HResult = pXMLDoc->get_documentElement( &pRootNode );
  600. if (SUCCEEDED(HResult))
  601. {
  602. Status = DfsReadTreeRoot( pRoot,
  603. pRootNode );
  604. }
  605. }
  606. }
  607. }
  608. }
  609. CoUninitialize();
  610. }
  611. }
  612. else
  613. {
  614. Status = ERROR_NOT_ENOUGH_MEMORY;
  615. }
  616. if (!SUCCEEDED(HResult))
  617. {
  618. Status = DfsGetErrorFromHr(HResult);
  619. }
  620. if (Status == ERROR_SUCCESS)
  621. {
  622. *ppRoot = pRoot;
  623. }
  624. else if (pRoot != NULL)
  625. {
  626. delete pRoot;
  627. pRoot = NULL;
  628. }
  629. return Status;
  630. }
  631. LPWSTR AmpString = L"&amp;";
  632. LPWSTR LtString = L"&lt;";
  633. LPWSTR GtString = L"&gt;";
  634. LPWSTR QtString = L"&quot;";
  635. LPWSTR AposString = L"&apos;";
  636. DFSSTATUS
  637. GetXMLStringToUse(
  638. LPWSTR UseString,
  639. BOOLEAN ScriptOut,
  640. LPWSTR *pOutString,
  641. BOOLEAN *pAllocated)
  642. {
  643. LPWSTR NewString;
  644. LONG Position;
  645. LONG CharLength, NewCharLength;
  646. DFSSTATUS Status = ERROR_SUCCESS;
  647. if (ScriptOut == FALSE)
  648. {
  649. *pOutString = UseString;
  650. *pAllocated = FALSE;
  651. return ERROR_SUCCESS;
  652. }
  653. CharLength = wcslen(UseString);
  654. Position = wcscspn(UseString, STANDARD_ILLEGAL_CHARS);
  655. if (Position == CharLength)
  656. {
  657. *pAllocated = FALSE;
  658. *pOutString = UseString;
  659. return ERROR_SUCCESS;
  660. }
  661. else
  662. {
  663. //
  664. // Allocate the maximum we ever need! In the case the string has all ',
  665. // the string will need 6 times as much space as the original string.
  666. //
  667. NewCharLength = CharLength * 6 + 1;
  668. NewString = new WCHAR[NewCharLength];
  669. if (NewString == NULL)
  670. {
  671. Status = ERROR_NOT_ENOUGH_MEMORY;
  672. }
  673. else
  674. {
  675. LONG SpLength;
  676. LPWSTR CurrentString = NewString;
  677. LPWSTR OldString = UseString;
  678. LONG CurrentLength = NewCharLength;
  679. LONG OldLength = CharLength;
  680. RtlZeroMemory(NewString, NewCharLength * sizeof(WCHAR));
  681. do {
  682. if (Position)
  683. {
  684. RtlCopyMemory(CurrentString,
  685. OldString,
  686. Position * sizeof(WCHAR));
  687. }
  688. WCHAR BadChar = *(OldString + Position);
  689. OldString += (Position + 1);
  690. CurrentString += Position;
  691. CurrentLength -= Position;
  692. OldLength -= (Position + 1);
  693. switch(BadChar)
  694. {
  695. case L'&':
  696. SpLength = wcslen(AmpString);
  697. RtlCopyMemory(CurrentString,
  698. AmpString,
  699. SpLength * sizeof(WCHAR));
  700. CurrentString += SpLength;
  701. CurrentLength -= SpLength + 1;
  702. break;
  703. case L'<':
  704. SpLength = wcslen(LtString);
  705. RtlCopyMemory(CurrentString,
  706. LtString,
  707. SpLength * sizeof(WCHAR));
  708. CurrentString += SpLength;
  709. CurrentLength -= SpLength;
  710. break;
  711. case L'>':
  712. SpLength = wcslen(GtString);
  713. RtlCopyMemory(CurrentString,
  714. GtString,
  715. SpLength * sizeof(WCHAR));
  716. CurrentString += SpLength;
  717. CurrentLength -= SpLength;
  718. break;
  719. case L'\"':
  720. SpLength = wcslen(QtString);
  721. RtlCopyMemory(CurrentString,
  722. QtString,
  723. SpLength * sizeof(WCHAR));
  724. CurrentString += SpLength;
  725. CurrentLength -= SpLength;
  726. break;
  727. case L'\'':
  728. SpLength = wcslen(AposString);
  729. RtlCopyMemory(CurrentString,
  730. AposString,
  731. SpLength * sizeof(WCHAR));
  732. CurrentString += SpLength;
  733. CurrentLength -= SpLength;
  734. break;
  735. default:
  736. Status = ERROR_INVALID_PARAMETER;
  737. }
  738. if (OldLength)
  739. {
  740. Position = wcscspn(OldString, STANDARD_ILLEGAL_CHARS);
  741. if (Position == OldLength)
  742. {
  743. RtlCopyMemory(CurrentString,
  744. OldString,
  745. Position * sizeof(WCHAR));
  746. }
  747. }
  748. else
  749. {
  750. break;
  751. }
  752. if (CurrentLength < OldLength)
  753. {
  754. Status = ERROR_GEN_FAILURE;
  755. break;
  756. }
  757. } while (Position != OldLength);
  758. }
  759. if (Status == ERROR_SUCCESS)
  760. {
  761. *pOutString = NewString;
  762. *pAllocated = TRUE;
  763. }
  764. }
  765. return Status;
  766. }
  767. VOID
  768. ReleaseXMLStringToUse(
  769. LPWSTR UseString,
  770. BOOLEAN Allocated)
  771. {
  772. if (Allocated)
  773. {
  774. delete [] UseString;
  775. }
  776. }
  777. DFSSTATUS
  778. DumpTargetInformation (
  779. DfsTarget *pTarget,
  780. HANDLE FileHandle,
  781. LPWSTR StartFormat,
  782. BOOLEAN ScriptOut )
  783. {
  784. LPWSTR UseString;
  785. BOOLEAN Allocated = FALSE;
  786. DFSSTATUS Status = ERROR_SUCCESS;
  787. for ( ;
  788. pTarget != NULL;
  789. pTarget = pTarget->GetNextTarget())
  790. {
  791. DfsPrintToFile( FileHandle, ScriptOut, L"%ws", StartFormat);
  792. if (ScriptOut) DfsPrintToFile( FileHandle, ScriptOut, L"<");
  793. Status = GetXMLStringToUse(pTarget->GetTargetServerString(),
  794. ScriptOut,
  795. &UseString,
  796. &Allocated );
  797. if (Status != ERROR_SUCCESS)
  798. {
  799. goto done;
  800. }
  801. DfsPrintToFile( FileHandle, ScriptOut, L"Target Server=\"%wS\" ", UseString);
  802. ReleaseXMLStringToUse(UseString, Allocated);
  803. Status = GetXMLStringToUse(pTarget->GetTargetFolderString(),
  804. ScriptOut,
  805. &UseString,
  806. &Allocated );
  807. if (Status != ERROR_SUCCESS)
  808. {
  809. goto done;
  810. }
  811. DfsPrintToFile( FileHandle, ScriptOut, L"Folder=\"%wS\" ", UseString);
  812. ReleaseXMLStringToUse(UseString, Allocated);
  813. if (pTarget->GetTargetState())
  814. {
  815. DfsPrintToFile( FileHandle, ScriptOut, L"State=\"%d\"", pTarget->GetTargetState());
  816. }
  817. if (ScriptOut)
  818. {
  819. DfsPrintToFile( FileHandle, ScriptOut, L"/>");
  820. }
  821. else
  822. {
  823. DfsPrintToFile( FileHandle, ScriptOut, L" [Site: %wS]", pTarget->GetTargetSiteString());
  824. }
  825. }
  826. DfsPrintToFile( FileHandle, ScriptOut, L"\r\n");
  827. done:
  828. return Status;
  829. }
  830. DFSSTATUS
  831. DumpLinkInformation(
  832. DfsLink *pLink,
  833. HANDLE FileHandle,
  834. BOOLEAN ScriptOut )
  835. {
  836. LPWSTR UseString;
  837. BOOLEAN Allocated = FALSE;
  838. DFSSTATUS Status = ERROR_SUCCESS;
  839. for ( ;
  840. pLink != NULL;
  841. pLink = pLink->GetNextLink())
  842. {
  843. if (pLink->GetFirstTarget() == NULL)
  844. {
  845. continue;
  846. }
  847. DfsPrintToFile( FileHandle, ScriptOut, L"\r\n\r\n\t");
  848. if (ScriptOut) DfsPrintToFile( FileHandle, ScriptOut,L"<");
  849. Status = GetXMLStringToUse(pLink->GetLinkNameString(),
  850. ScriptOut,
  851. &UseString,
  852. &Allocated );
  853. if (Status != ERROR_SUCCESS)
  854. {
  855. goto done;
  856. }
  857. DfsPrintToFile( FileHandle, ScriptOut,L"Link Name=\"%wS\" ", UseString);
  858. ReleaseXMLStringToUse(UseString, Allocated);
  859. if (IsEmptyString(pLink->GetLinkCommentString()) == FALSE)
  860. {
  861. Status = GetXMLStringToUse(pLink->GetLinkCommentString(),
  862. ScriptOut,
  863. &UseString,
  864. &Allocated );
  865. if (Status != ERROR_SUCCESS)
  866. {
  867. goto done;
  868. }
  869. DfsPrintToFile( FileHandle, ScriptOut,L"Comment=\"%wS\" ", UseString);
  870. ReleaseXMLStringToUse(UseString, Allocated);
  871. }
  872. if (pLink->GetLinkState())
  873. {
  874. DfsPrintToFile( FileHandle, ScriptOut,L"State=\"%d\" ", pLink->GetLinkState());
  875. }
  876. if (pLink->GetLinkTimeout())
  877. {
  878. DfsPrintToFile( FileHandle, ScriptOut,L"Timeout=\"%d\" ", pLink->GetLinkTimeout());
  879. }
  880. if (ScriptOut) DfsPrintToFile( FileHandle, ScriptOut,L">");
  881. Status = DumpTargetInformation(pLink->GetFirstTarget(),
  882. FileHandle,
  883. L"\r\n\t\t",
  884. ScriptOut);
  885. if (Status != ERROR_SUCCESS)
  886. {
  887. goto done;
  888. }
  889. if (ScriptOut) DfsPrintToFile( FileHandle, ScriptOut,L"\t</Link>\r\n");
  890. }
  891. done:
  892. return Status;
  893. }
  894. DFSSTATUS
  895. DumpRoots (
  896. DfsRoot *pRoot,
  897. HANDLE FileHandle,
  898. BOOLEAN ScriptOut )
  899. {
  900. LPWSTR UseString;
  901. BOOLEAN Allocated = FALSE;
  902. ULONG BlobSize = 0, Attrib = 0;
  903. DFSSTATUS Status = ERROR_SUCCESS;
  904. BOOLEAN GotBlobSize = FALSE, GotAttrib = FALSE;
  905. LPWSTR RootType = L"";
  906. if (pRoot->RootBlobSize(&BlobSize) == ERROR_SUCCESS)
  907. {
  908. GotBlobSize = TRUE;
  909. }
  910. if (pRoot->GetExtendedAttributes(&Attrib) == ERROR_SUCCESS)
  911. {
  912. GotAttrib = TRUE;
  913. }
  914. if (ScriptOut)
  915. {
  916. ULONG cch;
  917. //
  918. // we want to start the file with FFFE. This is the key word to get the file
  919. // to be recognized as containing unicode, so we support globalization.
  920. //
  921. WriteFile(FileHandle, "\xFF\xFE", 2, &cch, NULL);
  922. DfsPrintToFile( FileHandle, ScriptOut, L"<?xml version=\"1.0\"?>\r\n");
  923. }
  924. else
  925. {
  926. if ((pRoot->GetLinkState() & DFS_VOLUME_FLAVORS) == DFS_VOLUME_FLAVOR_STANDALONE)
  927. {
  928. RootType = L"Standalone";
  929. }
  930. else if ((pRoot->GetLinkState() & DFS_VOLUME_FLAVORS) == DFS_VOLUME_FLAVOR_AD_BLOB)
  931. {
  932. RootType = L"Domain";
  933. }
  934. DfsPrintToFile( FileHandle, ScriptOut,L"%ws Root with %d Links", RootType, pRoot->GetLinkCount());
  935. if (GotBlobSize && (BlobSize != 0))
  936. {
  937. DfsPrintToFile( FileHandle, ScriptOut,L" [Blob Size: %d bytes]", BlobSize);
  938. }
  939. DfsPrintToFile( FileHandle, ScriptOut,L"\r\n");
  940. if (GotAttrib)
  941. {
  942. BOOLEAN Found = FALSE;
  943. if (Attrib & PKT_ENTRY_TYPE_INSITE_ONLY)
  944. {
  945. Found = TRUE;
  946. DfsPrintToFile( FileHandle, ScriptOut,L"InSite:ENABLED ");
  947. }
  948. #if 0
  949. else
  950. {
  951. DfsPrintToFile( FileHandle, ScriptOut,L"InSite:DISABLED ");
  952. }
  953. #endif
  954. if (Attrib & PKT_ENTRY_TYPE_COST_BASED_SITE_SELECTION)
  955. {
  956. Found = TRUE;
  957. DfsPrintToFile( FileHandle, ScriptOut,L"SiteCosting:ENABLED ");
  958. }
  959. #if 0
  960. else
  961. {
  962. DfsPrintToFile( FileHandle, ScriptOut,L"SiteCosting:DISABLED ");
  963. }
  964. #endif
  965. if (Attrib & PKT_ENTRY_TYPE_ROOT_SCALABILITY)
  966. {
  967. Found = TRUE;
  968. DfsPrintToFile( FileHandle, ScriptOut,L"RootScalability:ENABLED ");
  969. }
  970. #if 0
  971. else
  972. {
  973. DfsPrintToFile( FileHandle, ScriptOut,L"RootScalability:DISABLED ");
  974. }
  975. #endif
  976. if (Found == FALSE)
  977. {
  978. DfsPrintToFile( FileHandle, ScriptOut,L"Root information follows ");
  979. }
  980. DfsPrintToFile( FileHandle, ScriptOut,L"\r\n");
  981. }
  982. DfsPrintToFile( FileHandle, ScriptOut,L"\r\n");
  983. }
  984. DfsPrintToFile( FileHandle, ScriptOut,L"\r\n");
  985. if (ScriptOut) DfsPrintToFile( FileHandle, ScriptOut,L"<");
  986. DfsPrintToFile( FileHandle, ScriptOut,L"Root ");
  987. if (pRoot->GetLinkNameString() != NULL)
  988. {
  989. Status = GetXMLStringToUse(pRoot->GetLinkNameString(),
  990. ScriptOut,
  991. &UseString,
  992. &Allocated );
  993. if (Status != ERROR_SUCCESS)
  994. {
  995. goto done;
  996. }
  997. DfsPrintToFile( FileHandle, ScriptOut,L"Name=\"%ws\" ", UseString);
  998. ReleaseXMLStringToUse(UseString, Allocated);
  999. }
  1000. if (IsEmptyString(pRoot->GetLinkCommentString()) == FALSE)
  1001. {
  1002. Status = GetXMLStringToUse(pRoot->GetLinkCommentString(),
  1003. ScriptOut,
  1004. &UseString,
  1005. &Allocated );
  1006. if (Status != ERROR_SUCCESS)
  1007. {
  1008. goto done;
  1009. }
  1010. DfsPrintToFile( FileHandle, ScriptOut,L"Comment=\"%wS\" ", UseString);
  1011. ReleaseXMLStringToUse(UseString, Allocated);
  1012. }
  1013. if (pRoot->GetLinkState())
  1014. {
  1015. DfsPrintToFile( FileHandle, ScriptOut,L"State=\"%d\" ", pRoot->GetLinkState() & DFS_VOLUME_STATES);
  1016. }
  1017. if (pRoot->GetLinkTimeout())
  1018. {
  1019. DfsPrintToFile( FileHandle, ScriptOut,L"Timeout=\"%d\" ", pRoot->GetLinkTimeout());
  1020. }
  1021. if (ScriptOut) DfsPrintToFile( FileHandle, ScriptOut,L">");
  1022. Status = DumpTargetInformation(pRoot->GetFirstTarget(),
  1023. FileHandle,
  1024. L"\r\n\t",
  1025. ScriptOut);
  1026. if (Status != ERROR_SUCCESS)
  1027. {
  1028. goto done;
  1029. }
  1030. Status = DumpLinkInformation(pRoot->GetFirstLink(),
  1031. FileHandle,
  1032. ScriptOut);
  1033. if (Status != ERROR_SUCCESS)
  1034. {
  1035. goto done;
  1036. }
  1037. if (ScriptOut)
  1038. {
  1039. DfsPrintToFile( FileHandle, ScriptOut,L"\r\n</Root>");
  1040. }
  1041. else
  1042. {
  1043. DfsPrintToFile( FileHandle, ScriptOut,L"\r\n\r\nRoot with %d Links", pRoot->GetLinkCount());
  1044. if (GotBlobSize && (BlobSize != 0))
  1045. {
  1046. DfsPrintToFile( FileHandle, ScriptOut,L" [Blob Size: %d bytes]", BlobSize);
  1047. }
  1048. DfsPrintToFile( FileHandle, ScriptOut,L"\r\n\r\n\r\nNOTE: All site information shown was generated by this utility.\r\n");
  1049. DfsPrintToFile( FileHandle, ScriptOut,L" Actual DFS behavior depends on site information currently in use by \r\n");
  1050. DfsPrintToFile( FileHandle, ScriptOut,L" DFS service, and may not reflect configuration changes made recently.\r\n");
  1051. }
  1052. DfsPrintToFile( FileHandle, ScriptOut,L"\r\n\r\n");
  1053. done:
  1054. return Status;
  1055. }
  1056. DFSSTATUS
  1057. AddTargetCosting(
  1058. DfsTarget *pTarget,
  1059. PULONG pCumulative,
  1060. BOOLEAN RootTarget )
  1061. {
  1062. LPWSTR ServerString, FolderString;
  1063. BOOLEAN ServerAllocated = FALSE, FolderAllocated = FALSE;
  1064. DFSSTATUS Status = ERROR_SUCCESS;
  1065. for ( ;
  1066. pTarget != NULL;
  1067. pTarget = pTarget->GetNextTarget())
  1068. {
  1069. Status = GetXMLStringToUse(pTarget->GetTargetServerString(),
  1070. FALSE,
  1071. &ServerString,
  1072. &ServerAllocated );
  1073. if (Status != ERROR_SUCCESS)
  1074. {
  1075. goto done;
  1076. }
  1077. Status = GetXMLStringToUse(pTarget->GetTargetFolderString(),
  1078. FALSE,
  1079. &FolderString,
  1080. &FolderAllocated );
  1081. if (Status != ERROR_SUCCESS)
  1082. {
  1083. goto done;
  1084. }
  1085. if (RootTarget)
  1086. {
  1087. *pCumulative += 6;
  1088. *pCumulative += wcslen(ServerString) * sizeof(WCHAR);
  1089. *pCumulative += wcslen(FolderString) * sizeof(WCHAR);
  1090. }
  1091. *pCumulative += 20;
  1092. *pCumulative += 6;
  1093. *pCumulative += wcslen(ServerString) * sizeof(WCHAR);
  1094. *pCumulative += wcslen(FolderString) * sizeof(WCHAR);
  1095. ReleaseXMLStringToUse(ServerString, ServerAllocated);
  1096. ReleaseXMLStringToUse(FolderString, FolderAllocated);
  1097. }
  1098. done:
  1099. return Status;
  1100. }
  1101. DFSSTATUS
  1102. AddLinkCosting(
  1103. DfsLink *pLink,
  1104. ULONG FixedOverhead,
  1105. PULONG pCumulative )
  1106. {
  1107. LPWSTR LinkNameString = NULL, CommentString = NULL;
  1108. BOOLEAN LinkNameAllocated = FALSE, CommentAllocated = FALSE;
  1109. DFSSTATUS Status = ERROR_SUCCESS;
  1110. ULONG LinkCost;
  1111. for ( ;
  1112. pLink != NULL;
  1113. pLink = pLink->GetNextLink())
  1114. {
  1115. LinkCost = 0;
  1116. if (pLink->GetFirstTarget() == NULL)
  1117. {
  1118. continue;
  1119. }
  1120. Status = GetXMLStringToUse(pLink->GetLinkNameString(),
  1121. FALSE,
  1122. &LinkNameString,
  1123. &LinkNameAllocated );
  1124. if (Status != ERROR_SUCCESS)
  1125. {
  1126. break;
  1127. }
  1128. if (IsEmptyString(pLink->GetLinkCommentString()) == FALSE)
  1129. {
  1130. Status = GetXMLStringToUse(pLink->GetLinkCommentString(),
  1131. FALSE,
  1132. &CommentString,
  1133. &CommentAllocated );
  1134. if (Status != ERROR_SUCCESS)
  1135. {
  1136. break;
  1137. }
  1138. }
  1139. LinkCost += 214;
  1140. LinkCost += FixedOverhead * 2;
  1141. LinkCost += (wcslen(pLink->GetLinkNameString()) * sizeof(WCHAR)) * 2;
  1142. if (CommentString)
  1143. {
  1144. LinkCost += wcslen(CommentString) * sizeof(WCHAR);
  1145. }
  1146. ReleaseXMLStringToUse(LinkNameString, LinkNameAllocated);
  1147. ReleaseXMLStringToUse(CommentString, CommentAllocated);
  1148. Status = AddTargetCosting( pLink->GetFirstTarget(), &LinkCost, FALSE);
  1149. if (Status != ERROR_SUCCESS)
  1150. {
  1151. break;
  1152. }
  1153. DebugInformation((L"Cost for link %ws is %d\r\n",
  1154. pLink->GetLinkNameString(), LinkCost));
  1155. *pCumulative += LinkCost;
  1156. }
  1157. return Status;
  1158. }
  1159. //
  1160. //For each DFS root and for each link, the DFS overhead is 180 bytes.
  1161. //The total space, in bytes, taken up by a root is 180 + (number of
  1162. // characters in DFS Name * 4) + (number of characters in each root
  1163. // target * 2).
  1164. //The total space, in bytes, taken up by each link is 180 + (number of
  1165. // characters in the link name � number of characters in the domain name)
  1166. // * 4)
  1167. //For each DFS root target or target, the DFS overhead is 20 bytes.
  1168. //The total space, in bytes, taken up by a target is 20 + (number of
  1169. // characters in target name * 2) For each unique server that is added
  1170. // as a target or root target, site information takes up some space.
  1171. //This space, in bytes, is 12 + (number of characters in server name
  1172. // + number of characters in site name) * 2.
  1173. //
  1174. DFSSTATUS
  1175. SizeRoot(
  1176. DfsRoot *pRoot,
  1177. PULONG pBlobSize )
  1178. {
  1179. ULONG FixedOverhead;
  1180. ULONG Cumulative = 0;
  1181. DfsPathName PathName;
  1182. DFSSTATUS Status;
  1183. LPWSTR RootName;
  1184. RootName = pRoot->GetLinkNameString();
  1185. if (IsEmptyString(RootName) == FALSE)
  1186. {
  1187. Status = PathName.CreatePathName(RootName);
  1188. if (Status != ERROR_SUCCESS)
  1189. {
  1190. return Status;
  1191. }
  1192. FixedOverhead = wcslen(PathName.GetShareString()) * sizeof(WCHAR);
  1193. Cumulative += 180 + wcslen(pRoot->GetLinkNameString()) * sizeof(WCHAR) * 2;
  1194. }
  1195. else
  1196. {
  1197. FixedOverhead = 100;
  1198. Cumulative += 380;
  1199. }
  1200. Status = AddTargetCosting(pRoot->GetFirstTarget(), &Cumulative, TRUE);
  1201. if (Status == ERROR_SUCCESS)
  1202. {
  1203. Status = AddLinkCosting(pRoot->GetFirstLink(), FixedOverhead, &Cumulative);
  1204. }
  1205. if (Status == ERROR_SUCCESS)
  1206. {
  1207. // 100K is the smallest amount we display.
  1208. if (Cumulative < 100 * 1024)
  1209. {
  1210. Cumulative = 100 *1024;
  1211. }
  1212. *pBlobSize = Cumulative;
  1213. }
  1214. return Status;
  1215. }