Source code of Windows XP (NT5)
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.

1009 lines
22 KiB

  1. //---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1995
  5. //
  6. // File: getobj.cxx
  7. //
  8. // Contents: Windows NT 3.5 GetObject functionality
  9. //
  10. // History:
  11. //----------------------------------------------------------------------------
  12. #include "nds.hxx"
  13. #pragma hdrstop
  14. extern LPWSTR szProviderName;
  15. //+---------------------------------------------------------------------------
  16. // Function: RelativeGetObject
  17. //
  18. // Synopsis: Gets object relative to given Active Directory path.
  19. //
  20. // Arguments: [BSTR ADsPath]
  21. // [BSTR ClassName]
  22. // [BSTR RelativeName]
  23. // [IUnknown** ppObject]
  24. // [BOOT bNamespaceRelative]
  25. //
  26. // Returns: HRESULT
  27. //
  28. // Modifies: *ppObject
  29. //
  30. // History: 08-02-96 t-danal Created as such.
  31. //
  32. //----------------------------------------------------------------------------
  33. HRESULT
  34. RelativeGetObject(
  35. BSTR ADsPath,
  36. BSTR ClassName,
  37. BSTR RelativeName,
  38. CCredentials& Credentials,
  39. IDispatch * FAR* ppObject,
  40. BOOL bNamespaceRelative
  41. )
  42. {
  43. WCHAR szBuffer[MAX_PATH];
  44. HRESULT hr = S_OK;
  45. *ppObject = NULL;
  46. if (!RelativeName || !*RelativeName) {
  47. RRETURN(E_ADS_UNKNOWN_OBJECT);
  48. }
  49. memset(szBuffer, 0, sizeof(szBuffer));
  50. wcscpy(szBuffer, ADsPath);
  51. if (bNamespaceRelative)
  52. wcscat(szBuffer, L"//");
  53. else
  54. wcscat(szBuffer, L"/");
  55. wcscat(szBuffer, RelativeName);
  56. if (ClassName && *ClassName) {
  57. wcscat(szBuffer,L",");
  58. wcscat(szBuffer, ClassName);
  59. }
  60. hr = ::GetObject(
  61. szBuffer,
  62. Credentials,
  63. (LPVOID *)ppObject
  64. );
  65. BAIL_ON_FAILURE(hr);
  66. error:
  67. RRETURN(hr);
  68. }
  69. //+---------------------------------------------------------------------------
  70. // Function: GetObject
  71. //
  72. // Synopsis: Called by ResolvePathName to return an object
  73. //
  74. // Arguments: [LPWSTR szBuffer]
  75. // [LPVOID *ppObject]
  76. //
  77. // Returns: HRESULT
  78. //
  79. // Modifies: -
  80. //
  81. // History: 11-3-95 krishnag Created.
  82. //
  83. //----------------------------------------------------------------------------
  84. HRESULT
  85. GetObject(
  86. LPWSTR szBuffer,
  87. CCredentials& Credentials,
  88. LPVOID * ppObject
  89. )
  90. {
  91. HRESULT hr;
  92. DWORD dwStatus = NO_ERROR;
  93. DWORD dwNumberEntries = 0;
  94. DWORD dwModificationTime = 0;
  95. WCHAR szObjectClassName[MAX_PATH];
  96. WCHAR szObjectFullName[MAX_PATH];
  97. LPWSTR pszNDSPath = NULL;
  98. WCHAR szParent[MAX_PATH];
  99. WCHAR szCommonName[MAX_PATH];
  100. HANDLE hObject = NULL;
  101. OBJECTINFO ObjectInfo;
  102. POBJECTINFO pObjectInfo = &ObjectInfo;
  103. CLexer Lexer(szBuffer);
  104. IADs * pADs = NULL;
  105. memset(pObjectInfo, 0, sizeof(OBJECTINFO));
  106. hr = ADsObject(&Lexer, pObjectInfo);
  107. BAIL_ON_FAILURE(hr);
  108. //
  109. // Validate that this ADs pathname is to be processed by
  110. // us - as in the provider name is @NDS!
  111. //
  112. hr = ValidateProvider(pObjectInfo);
  113. BAIL_ON_FAILURE(hr);
  114. hr = ValidateObjectType(pObjectInfo);
  115. switch (pObjectInfo->ObjectType) {
  116. case TOKEN_NAMESPACE:
  117. //
  118. // This means that this is a namespace object;
  119. // instantiate the namespace object
  120. //
  121. hr = GetNamespaceObject(
  122. pObjectInfo,
  123. Credentials,
  124. ppObject
  125. );
  126. BAIL_ON_FAILURE(hr);
  127. break;
  128. case TOKEN_SCHEMA:
  129. hr = GetSchemaObject(
  130. pObjectInfo,
  131. Credentials,
  132. ppObject
  133. );
  134. BAIL_ON_FAILURE(hr);
  135. break;
  136. default:
  137. hr = BuildNDSPathFromADsPath(
  138. szBuffer,
  139. &pszNDSPath
  140. );
  141. BAIL_ON_FAILURE(hr);
  142. dwStatus = ADsNwNdsOpenObject(
  143. pszNDSPath,
  144. Credentials,
  145. &hObject,
  146. szObjectFullName,
  147. szObjectClassName,
  148. &dwModificationTime,
  149. &dwNumberEntries
  150. );
  151. CHECK_AND_SET_EXTENDED_ERROR(dwStatus, hr);
  152. hr = BuildADsParentPath(
  153. szBuffer,
  154. szParent,
  155. szCommonName
  156. );
  157. BAIL_ON_FAILURE(hr);
  158. hr = CNDSGenObject::CreateGenericObject(
  159. szParent,
  160. szCommonName,
  161. szObjectClassName,
  162. Credentials,
  163. ADS_OBJECT_BOUND,
  164. IID_IADs,
  165. (void **)&pADs
  166. );
  167. BAIL_ON_FAILURE(hr);
  168. //
  169. // InstantiateDerivedObject should add-ref this pointer for us.
  170. //
  171. hr = InstantiateDerivedObject(
  172. pADs,
  173. Credentials,
  174. IID_IUnknown,
  175. (void **)ppObject
  176. );
  177. if (FAILED(hr)) {
  178. hr = pADs->QueryInterface(
  179. IID_IUnknown,
  180. ppObject
  181. );
  182. BAIL_ON_FAILURE(hr);
  183. }
  184. break;
  185. }
  186. error:
  187. if (hObject) {
  188. NwNdsCloseObject(hObject);
  189. }
  190. if (pszNDSPath) {
  191. FreeADsStr(pszNDSPath);
  192. }
  193. if (pADs) {
  194. pADs->Release();
  195. }
  196. FreeObjectInfo( &ObjectInfo );
  197. RRETURN(hr);
  198. }
  199. HRESULT
  200. BuildADsPathFromNDSPath(
  201. LPWSTR szNDSTreeName,
  202. LPWSTR szNDSDNName,
  203. LPWSTR szADsPathName
  204. )
  205. {
  206. PKEYDATA pKeyData = NULL;
  207. DWORD dwCount = 0;
  208. DWORD i = 0;
  209. LPWSTR pszDisplayTreeName = NULL;
  210. LPWSTR pszDisplayDNName = NULL;
  211. HRESULT hr = S_OK;
  212. if (!szNDSTreeName || !szNDSDNName) {
  213. RRETURN(E_FAIL);
  214. }
  215. hr = GetDisplayName(
  216. szNDSTreeName,
  217. &pszDisplayTreeName
  218. );
  219. BAIL_ON_FAILURE(hr);
  220. wsprintf(szADsPathName,L"%s:%s", szProviderName, szNDSTreeName);
  221. hr = GetDisplayName(
  222. szNDSDNName,
  223. &pszDisplayDNName
  224. );
  225. BAIL_ON_FAILURE(hr);
  226. pKeyData = CreateTokenList(
  227. pszDisplayDNName,
  228. L'.'
  229. );
  230. if (pKeyData) {
  231. dwCount = pKeyData->cTokens;
  232. for (i = 0; i < dwCount; i++) {
  233. wcscat(szADsPathName, L"/");
  234. wcscat(szADsPathName, pKeyData->pTokens[dwCount - 1 - i]);
  235. }
  236. }
  237. if (pKeyData) {
  238. FreeADsMem(pKeyData);
  239. }
  240. error:
  241. if (pszDisplayTreeName) {
  242. FreeADsMem(pszDisplayTreeName);
  243. }
  244. if (pszDisplayDNName) {
  245. FreeADsMem(pszDisplayDNName);
  246. }
  247. RRETURN(hr);
  248. }
  249. HRESULT
  250. BuildNDSPathFromADsPath(
  251. LPWSTR szADsPathName,
  252. LPWSTR * pszNDSPathName
  253. )
  254. {
  255. OBJECTINFO ObjectInfo;
  256. POBJECTINFO pObjectInfo = &ObjectInfo;
  257. CLexer Lexer(szADsPathName);
  258. DWORD i = 0;
  259. DWORD dwNumComponents = 0;
  260. HRESULT hr;
  261. LPWSTR szNDSPathName = NULL;
  262. *pszNDSPathName = NULL;
  263. memset(pObjectInfo, 0, sizeof(OBJECTINFO));
  264. hr = ADsObject(&Lexer, pObjectInfo);
  265. BAIL_ON_FAILURE(hr);
  266. dwNumComponents = pObjectInfo->NumComponents;
  267. szNDSPathName = AllocADsStr(szADsPathName);
  268. if (!szNDSPathName) {
  269. hr = E_OUTOFMEMORY;
  270. BAIL_ON_FAILURE(hr);
  271. }
  272. wcscpy(szNDSPathName, L"\\\\");
  273. wcscat(szNDSPathName, pObjectInfo->TreeName);
  274. if (dwNumComponents) {
  275. wcscat(szNDSPathName, L"\\");
  276. for (i = dwNumComponents; i > 0; i--) {
  277. AppendComponent(
  278. szNDSPathName,
  279. &(pObjectInfo->ComponentArray[i-1])
  280. );
  281. if ((i - 1) > 0){
  282. wcscat(szNDSPathName, L".");
  283. }
  284. }
  285. }
  286. *pszNDSPathName = szNDSPathName;
  287. error:
  288. FreeObjectInfo( &ObjectInfo );
  289. RRETURN(hr);
  290. }
  291. HRESULT
  292. AppendComponent(
  293. LPWSTR szNDSPathName,
  294. PCOMPONENT pComponent
  295. )
  296. {
  297. if (pComponent->szComponent && pComponent->szValue) {
  298. wcscat(szNDSPathName, pComponent->szComponent);
  299. wcscat(szNDSPathName,L"=");
  300. wcscat(szNDSPathName, pComponent->szValue);
  301. }else if (pComponent->szComponent && !pComponent->szValue) {
  302. wcscat(szNDSPathName, pComponent->szComponent);
  303. }else {
  304. //
  305. // we should never hit this case
  306. //
  307. }
  308. RRETURN(S_OK);
  309. }
  310. HRESULT
  311. BuildADsParentPath(
  312. LPWSTR szBuffer,
  313. LPWSTR szParent,
  314. LPWSTR szCommonName
  315. )
  316. {
  317. OBJECTINFO ObjectInfo;
  318. POBJECTINFO pObjectInfo = &ObjectInfo;
  319. CLexer Lexer(szBuffer);
  320. HRESULT hr = S_OK;
  321. memset(pObjectInfo, 0, sizeof(OBJECTINFO));
  322. hr = ADsObject(&Lexer, pObjectInfo);
  323. BAIL_ON_FAILURE(hr);
  324. hr = BuildADsParentPath(
  325. pObjectInfo,
  326. szParent,
  327. szCommonName
  328. );
  329. error:
  330. FreeObjectInfo( &ObjectInfo );
  331. RRETURN(hr);
  332. }
  333. //+---------------------------------------------------------------------------
  334. // Function: GetNamespaceObject
  335. //
  336. // Synopsis: called by GetObject
  337. //
  338. // Arguments: [POBJECTINFO pObjectInfo]
  339. // [LPVOID * ppObject]
  340. //
  341. // Returns: HRESULT
  342. //
  343. // Modifies: -
  344. //
  345. // History: 11-3-95 krishnag Created.
  346. //
  347. //----------------------------------------------------------------------------
  348. HRESULT
  349. GetNamespaceObject(
  350. POBJECTINFO pObjectInfo,
  351. CCredentials& Credentials,
  352. LPVOID * ppObject
  353. )
  354. {
  355. HRESULT hr;
  356. hr = ValidateNamespaceObject(
  357. pObjectInfo
  358. );
  359. BAIL_ON_FAILURE(hr);
  360. hr = CNDSNamespace::CreateNamespace(
  361. L"ADs:",
  362. L"NDS:",
  363. Credentials,
  364. ADS_OBJECT_BOUND,
  365. IID_IUnknown,
  366. ppObject
  367. );
  368. error:
  369. RRETURN(hr);
  370. }
  371. HRESULT
  372. ValidateNamespaceObject(
  373. POBJECTINFO pObjectInfo
  374. )
  375. {
  376. if (!_wcsicmp(pObjectInfo->ProviderName, szProviderName)) {
  377. RRETURN(S_OK);
  378. }
  379. RRETURN(E_FAIL);
  380. }
  381. HRESULT
  382. ValidateProvider(
  383. POBJECTINFO pObjectInfo
  384. )
  385. {
  386. //
  387. // The provider name is case-sensitive. This is a restriction that OLE
  388. // has put on us.
  389. //
  390. if (!(wcscmp(pObjectInfo->ProviderName, szProviderName))) {
  391. RRETURN(S_OK);
  392. }
  393. RRETURN(E_FAIL);
  394. }
  395. //+---------------------------------------------------------------------------
  396. // Function: GetSchemaObject
  397. //
  398. // Synopsis: called by GetObject
  399. //
  400. // Arguments: [POBJECTINFO pObjectInfo]
  401. // [LPVOID * ppObject]
  402. //
  403. // Returns: HRESULT
  404. //
  405. // Modifies: -
  406. //
  407. // History: 11-3-95 krishnag Created.
  408. //
  409. //----------------------------------------------------------------------------
  410. HRESULT
  411. GetSchemaObject(
  412. POBJECTINFO pObjectInfo,
  413. CCredentials& Credentials,
  414. LPVOID * ppObject
  415. )
  416. {
  417. HRESULT hr = S_OK;
  418. WCHAR szParent[MAX_PATH];
  419. WCHAR szCommonName[MAX_PATH];
  420. WCHAR szNDSPathName[MAX_PATH];
  421. DWORD dwObjectType = 0;
  422. DWORD dwStatus;
  423. HANDLE hTree = NULL;
  424. hr = ValidateSchemaObject(
  425. pObjectInfo,
  426. &dwObjectType
  427. );
  428. BAIL_ON_FAILURE(hr);
  429. hr = BuildADsParentPath(
  430. pObjectInfo,
  431. szParent,
  432. szCommonName
  433. );
  434. BAIL_ON_FAILURE(hr);
  435. switch(dwObjectType) {
  436. case NDS_CLASS_ID:
  437. case NDS_PROPERTY_ID:
  438. case NDS_CLASSPROP_ID:
  439. wcscpy(szNDSPathName, L"\\\\");
  440. wcscat(szNDSPathName, pObjectInfo->TreeName);
  441. dwStatus = ADsNwNdsOpenObject(
  442. szNDSPathName,
  443. Credentials,
  444. &hTree,
  445. NULL,
  446. NULL,
  447. NULL,
  448. NULL
  449. );
  450. CHECK_AND_SET_EXTENDED_ERROR(dwStatus, hr);
  451. break;
  452. default:
  453. break;
  454. }
  455. //
  456. // Note: The "error:" tag is at the end of the switch statement,
  457. // so we can simply break out.
  458. //
  459. switch (dwObjectType) {
  460. case NDS_SCHEMA_ID:
  461. hr = CNDSSchema::CreateSchema(
  462. szParent,
  463. szCommonName,
  464. Credentials,
  465. ADS_OBJECT_BOUND,
  466. IID_IUnknown,
  467. ppObject
  468. );
  469. break;
  470. case NDS_CLASSPROP_ID:
  471. hr = CNDSClass::CreateClass(
  472. szParent,
  473. szCommonName,
  474. hTree,
  475. Credentials,
  476. ADS_OBJECT_BOUND,
  477. IID_IUnknown,
  478. ppObject
  479. );
  480. if (FAILED(hr)) {
  481. hr = CNDSProperty::CreateProperty(
  482. szParent,
  483. szCommonName,
  484. hTree,
  485. Credentials,
  486. ADS_OBJECT_BOUND,
  487. IID_IUnknown,
  488. ppObject
  489. );
  490. BAIL_ON_FAILURE(hr);
  491. }
  492. break;
  493. case NDS_CLASS_ID:
  494. hr = CNDSClass::CreateClass(
  495. szParent,
  496. szCommonName,
  497. hTree,
  498. Credentials,
  499. ADS_OBJECT_BOUND,
  500. IID_IUnknown,
  501. ppObject
  502. );
  503. break;
  504. case NDS_PROPERTY_ID:
  505. hr = CNDSProperty::CreateProperty(
  506. szParent,
  507. szCommonName,
  508. hTree,
  509. Credentials,
  510. ADS_OBJECT_BOUND,
  511. IID_IUnknown,
  512. ppObject
  513. );
  514. break;
  515. default:
  516. hr = E_ADS_UNKNOWN_OBJECT;
  517. break;
  518. }
  519. error:
  520. if (hTree) {
  521. NwNdsCloseObject(hTree);
  522. }
  523. RRETURN(hr);
  524. }
  525. HRESULT
  526. ValidateSchemaObject(
  527. POBJECTINFO pObjectInfo,
  528. PDWORD pdwObjectType
  529. )
  530. {
  531. DWORD dwNumComponents = 0;
  532. dwNumComponents = pObjectInfo->NumComponents;
  533. switch (dwNumComponents) {
  534. case 1:
  535. if (!_wcsicmp(pObjectInfo->ComponentArray[0].szComponent, L"schema")) {
  536. *pdwObjectType = NDS_SCHEMA_ID;
  537. RRETURN(S_OK);
  538. }
  539. break;
  540. case 2:
  541. if (pObjectInfo->ClassName) {
  542. if (!_wcsicmp(pObjectInfo->ClassName, L"Property")) {
  543. *pdwObjectType = NDS_PROPERTY_ID;
  544. }
  545. else {
  546. *pdwObjectType = NDS_CLASS_ID;
  547. }
  548. }
  549. else {
  550. *pdwObjectType = NDS_CLASSPROP_ID;
  551. }
  552. RRETURN(S_OK);
  553. /* if (!_wcsicmp(pObjectInfo->ComponentArray[0].szComponent, L"schema")) {
  554. *pdwObjectType = NDS_CLASS_ID;
  555. RRETURN(S_OK);
  556. }
  557. break;
  558. case 3:
  559. if (!_wcsicmp(pObjectInfo->ComponentArray[0].szComponent,SCHEMA_NAME)) {
  560. *pdwObjectType = NDS_PROPERTY_ID;
  561. RRETURN(S_OK);
  562. }
  563. break; */
  564. default:
  565. break;
  566. }
  567. RRETURN(E_FAIL);
  568. }
  569. HRESULT
  570. BuildADsParentPath(
  571. POBJECTINFO pObjectInfo,
  572. LPWSTR szParent,
  573. LPWSTR szCommonName
  574. )
  575. {
  576. DWORD i = 0;
  577. DWORD dwNumComponents = 0;
  578. HRESULT hr;
  579. dwNumComponents = pObjectInfo->NumComponents;
  580. if (!dwNumComponents && !pObjectInfo->DisplayTreeName) {
  581. //
  582. // There are no CNs in this pathname and
  583. // no tree name specified. This is the
  584. // namespace object - its parent is the
  585. // @ADs! object
  586. //
  587. wsprintf(szParent,L"ADs:");
  588. RRETURN(S_OK);
  589. } else if (!dwNumComponents && pObjectInfo->DisplayTreeName) {
  590. //
  591. // There are no CNs in this pathname and a tree
  592. // name has been specified. This is the root
  593. // object - its parent is the @NDS! object
  594. wsprintf(szParent, L"%s:", pObjectInfo->ProviderName);
  595. //
  596. // And the common name is the TreeName. Remember the
  597. // "//" will be added on when we reconstruct the full
  598. // pathname
  599. //
  600. wsprintf(szCommonName,L"%s", pObjectInfo->DisplayTreeName);
  601. RRETURN(S_OK);
  602. }else {
  603. //
  604. // There are one or more CNs, a tree name has been
  605. // specified. In the worst case the parent is the
  606. // root object. In the best case a long CN.
  607. //
  608. wsprintf(
  609. szParent, L"%s://%s",
  610. pObjectInfo->ProviderName,
  611. pObjectInfo->DisplayTreeName
  612. );
  613. for (i = 0; i < dwNumComponents - 1; i++) {
  614. wcscat(szParent, L"/");
  615. AppendComponent(szParent, &(pObjectInfo->DisplayComponentArray[i]));
  616. }
  617. //
  618. // And the common name is the last component
  619. //
  620. szCommonName[0] = '\0';
  621. AppendComponent(szCommonName, &(pObjectInfo->DisplayComponentArray[dwNumComponents-1]));
  622. }
  623. RRETURN(S_OK);
  624. }
  625. HRESULT
  626. ValidateObjectType(
  627. POBJECTINFO pObjectInfo
  628. )
  629. {
  630. pObjectInfo->ObjectType = TOKEN_NDSOBJECT;
  631. if (pObjectInfo->ProviderName && !pObjectInfo->TreeName
  632. && !pObjectInfo->NumComponents) {
  633. pObjectInfo->ObjectType = TOKEN_NAMESPACE;
  634. }else if (pObjectInfo->ProviderName && pObjectInfo->TreeName
  635. && pObjectInfo->NumComponents) {
  636. if (!_wcsicmp(pObjectInfo->ComponentArray[0].szComponent,L"schema")) {
  637. pObjectInfo->ObjectType = TOKEN_SCHEMA;
  638. }
  639. }
  640. RRETURN(S_OK);
  641. }
  642. HRESULT
  643. BuildNDSTreeNameFromADsPath(
  644. LPWSTR szBuffer,
  645. LPWSTR szNDSTreeName
  646. )
  647. {
  648. OBJECTINFO ObjectInfo;
  649. POBJECTINFO pObjectInfo = &ObjectInfo;
  650. CLexer Lexer(szBuffer);
  651. DWORD dwNumComponents = 0;
  652. HRESULT hr;
  653. memset(pObjectInfo, 0, sizeof(OBJECTINFO));
  654. hr = ADsObject(&Lexer, pObjectInfo);
  655. BAIL_ON_FAILURE(hr);
  656. dwNumComponents = pObjectInfo->NumComponents;
  657. if (!dwNumComponents && !pObjectInfo->TreeName) {
  658. //
  659. // There are no CNs in this pathname and
  660. // no tree name specified. This is the
  661. // namespace object - its parent is the
  662. // @ADs! object
  663. //
  664. hr = E_FAIL;
  665. } else if (!dwNumComponents && pObjectInfo->TreeName) {
  666. //
  667. // There are no CNs in this pathname and a tree
  668. // name has been specified. This is the root
  669. // object - its parent is the @NDS! object
  670. wsprintf(szNDSTreeName,L"\\\\%s", pObjectInfo->TreeName);
  671. hr = S_OK;
  672. }else {
  673. //
  674. // There are one or more CNs, a tree name has been
  675. // specified. In the worst case the parent is the
  676. // root object. In the best case a long CN.
  677. //
  678. wsprintf(szNDSTreeName,L"\\\\%s", pObjectInfo->TreeName);
  679. hr = S_OK;
  680. }
  681. error:
  682. FreeObjectInfo( &ObjectInfo );
  683. RRETURN(hr);
  684. }
  685. HRESULT
  686. BuildNDSPathFromADsPath(
  687. LPWSTR szADsPathName,
  688. LPWSTR szNDSTreeName,
  689. LPWSTR szNDSPathName
  690. )
  691. {
  692. OBJECTINFO ObjectInfo;
  693. POBJECTINFO pObjectInfo = &ObjectInfo;
  694. CLexer Lexer(szADsPathName);
  695. DWORD i = 0;
  696. DWORD dwNumComponents = 0;
  697. HRESULT hr;
  698. memset(pObjectInfo, 0, sizeof(OBJECTINFO));
  699. hr = ADsObject(&Lexer, pObjectInfo);
  700. BAIL_ON_FAILURE(hr);
  701. dwNumComponents = pObjectInfo->NumComponents;
  702. wcscpy(szNDSTreeName, L"\\\\");
  703. wcscat(szNDSTreeName, pObjectInfo->TreeName);
  704. *szNDSPathName = L'\0';
  705. if (dwNumComponents) {
  706. for (i = dwNumComponents; i > 0; i--) {
  707. AppendComponent(
  708. szNDSPathName,
  709. &(pObjectInfo->ComponentArray[i-1])
  710. );
  711. if ((i - 1) > 0){
  712. wcscat(szNDSPathName, L".");
  713. }
  714. }
  715. }
  716. error:
  717. FreeObjectInfo( &ObjectInfo );
  718. RRETURN(hr);
  719. }
  720. VOID
  721. FreeObjectInfo(
  722. POBJECTINFO pObjectInfo
  723. )
  724. {
  725. if ( !pObjectInfo )
  726. return;
  727. FreeADsStr( pObjectInfo->ProviderName );
  728. FreeADsStr( pObjectInfo->TreeName );
  729. FreeADsStr( pObjectInfo->DisplayTreeName );
  730. FreeADsStr( pObjectInfo->ClassName);
  731. for ( DWORD i = 0; i < pObjectInfo->NumComponents; i++ ) {
  732. FreeADsStr( pObjectInfo->ComponentArray[i].szComponent );
  733. FreeADsStr( pObjectInfo->ComponentArray[i].szValue );
  734. FreeADsStr( pObjectInfo->DisplayComponentArray[i].szComponent );
  735. FreeADsStr( pObjectInfo->DisplayComponentArray[i].szValue );
  736. }
  737. // We don't need to free pObjectInfo since the object is always a static
  738. // variable on the stack.
  739. }
  740. HRESULT
  741. GetDisplayName(
  742. LPWSTR szName,
  743. LPWSTR *ppszDisplayName
  744. )
  745. {
  746. HRESULT hr = S_OK;
  747. DWORD len = 0;
  748. LPWSTR pch = szName;
  749. LPWSTR pszDisplayCh = NULL, pszDisplay = NULL;
  750. BOOL fQuotingOn = FALSE;
  751. if (!ppszDisplayName ) {
  752. RRETURN (E_INVALIDARG);
  753. }
  754. *ppszDisplayName = NULL;
  755. if (!szName) {
  756. RRETURN (S_OK);
  757. }
  758. pch = szName;
  759. fQuotingOn = FALSE;
  760. for (len=0; *pch; pch++, len++) {
  761. if ((!(pch > szName && *(pch-1) == '\\')) &&
  762. (*pch == L'"') ) {
  763. fQuotingOn = ~fQuotingOn;
  764. }
  765. else if (!fQuotingOn && (!(pch > szName && *(pch-1) == '\\')) &&
  766. (*pch == L'/' || *pch == L'<' || *pch == L'>') ) {
  767. len++;
  768. }
  769. }
  770. pszDisplay = (LPWSTR) AllocADsMem((len+1) * sizeof(WCHAR));
  771. if (!pszDisplay) {
  772. BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
  773. }
  774. pch = szName;
  775. pszDisplayCh = pszDisplay;
  776. fQuotingOn = FALSE;
  777. for (; *pch; pch++, pszDisplayCh++) {
  778. if ((!(pch > szName && *(pch-1) == '\\')) &&
  779. (*pch == L'"') ) {
  780. fQuotingOn = ~fQuotingOn;
  781. }
  782. else if (!fQuotingOn && (!(pch > szName && *(pch-1) == '\\')) &&
  783. (*pch == L'/' || *pch == L'<' || *pch == L'>') ) {
  784. *pszDisplayCh++ = L'\\';
  785. }
  786. *pszDisplayCh = *pch;
  787. }
  788. *pszDisplayCh = L'\0';
  789. *ppszDisplayName = pszDisplay;
  790. error:
  791. RRETURN(hr);
  792. }