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.

892 lines
20 KiB

  1. //---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1995
  5. //
  6. // File: cnamesp.cxx
  7. //
  8. // Contents: Windows NT 3.5 Namespace Object
  9. //
  10. //
  11. // History: 01-30-95 krishnag Created.
  12. //
  13. //----------------------------------------------------------------------------
  14. #include "NWCOMPAT.hxx"
  15. #pragma hdrstop
  16. DEFINE_IDispatch_Implementation(CNWCOMPATNamespace)
  17. DEFINE_IADs_Implementation(CNWCOMPATNamespace)
  18. // Class CNWCOMPATNamespace
  19. CNWCOMPATNamespace::CNWCOMPATNamespace()
  20. {
  21. VariantInit(&_vFilter);
  22. ENLIST_TRACKING(CNWCOMPATNamespace);
  23. }
  24. HRESULT
  25. CNWCOMPATNamespace::CreateNamespace(
  26. BSTR Parent,
  27. BSTR NamespaceName,
  28. DWORD dwObjectState,
  29. REFIID riid,
  30. void **ppvObj
  31. )
  32. {
  33. CNWCOMPATNamespace FAR * pNamespace = NULL;
  34. HRESULT hr = S_OK;
  35. hr = AllocateNamespaceObject(&pNamespace);
  36. BAIL_ON_FAILURE(hr);
  37. hr = pNamespace->InitializeCoreObject(
  38. Parent,
  39. NamespaceName,
  40. NAMESPACE_CLASS_NAME,
  41. NO_SCHEMA,
  42. CLSID_NWCOMPATNamespace,
  43. dwObjectState
  44. );
  45. BAIL_ON_FAILURE(hr);
  46. hr = pNamespace->QueryInterface(riid, ppvObj);
  47. BAIL_ON_FAILURE(hr);
  48. pNamespace->Release(); // <- WHY?
  49. RRETURN(hr);
  50. error:
  51. delete pNamespace;
  52. RRETURN_EXP_IF_ERR(hr);
  53. }
  54. CNWCOMPATNamespace::~CNWCOMPATNamespace( )
  55. {
  56. delete _pDispMgr;
  57. VariantClear(&_vFilter);
  58. }
  59. STDMETHODIMP
  60. CNWCOMPATNamespace::QueryInterface(
  61. REFIID iid,
  62. LPVOID FAR* ppv
  63. )
  64. {
  65. if (ppv == NULL) {
  66. RRETURN(E_POINTER);
  67. }
  68. if (IsEqualIID(iid, IID_IUnknown))
  69. {
  70. *ppv = (IADs FAR *)this;
  71. }else if (IsEqualIID(iid, IID_IDispatch))
  72. {
  73. *ppv = (IADs FAR *)this;
  74. }
  75. else if (IsEqualIID(iid, IID_ISupportErrorInfo))
  76. {
  77. *ppv = (ISupportErrorInfo *) this;
  78. }
  79. else if (IsEqualIID(iid, IID_IADsContainer))
  80. {
  81. *ppv = (IADsContainer FAR *) this;
  82. }
  83. else if (IsEqualIID(iid, IID_IADs))
  84. {
  85. *ppv = (IADs FAR *) this;
  86. }
  87. else if (IsEqualIID(iid, IID_IADsPathnameProvider))
  88. {
  89. *ppv = (IADsPathnameProvider FAR *) this;
  90. }
  91. else
  92. {
  93. *ppv = NULL;
  94. return E_NOINTERFACE;
  95. }
  96. AddRef();
  97. return NOERROR;
  98. }
  99. STDMETHODIMP
  100. CNWCOMPATNamespace::InterfaceSupportsErrorInfo(
  101. THIS_ REFIID riid
  102. )
  103. {
  104. if (IsEqualIID(riid, IID_IADs) ||
  105. IsEqualIID(riid, IID_IADsContainer)) {
  106. RRETURN(S_OK);
  107. } else {
  108. RRETURN(S_FALSE);
  109. }
  110. }
  111. STDMETHODIMP
  112. CNWCOMPATNamespace::SetInfo(
  113. THIS
  114. )
  115. {
  116. RRETURN_EXP_IF_ERR(E_NOTIMPL);
  117. }
  118. STDMETHODIMP
  119. CNWCOMPATNamespace::GetInfo(
  120. THIS
  121. )
  122. {
  123. RRETURN_EXP_IF_ERR(E_NOTIMPL);
  124. }
  125. /* IADsContainer methods */
  126. STDMETHODIMP
  127. CNWCOMPATNamespace::get_Count(
  128. long FAR* retval
  129. )
  130. {
  131. RRETURN_EXP_IF_ERR(E_NOTIMPL);
  132. }
  133. STDMETHODIMP
  134. CNWCOMPATNamespace::get_Filter(
  135. THIS_ VARIANT FAR* pVar
  136. )
  137. {
  138. HRESULT hr;
  139. VariantInit(pVar);
  140. hr = VariantCopy(pVar, &_vFilter);
  141. RRETURN_EXP_IF_ERR(hr);
  142. }
  143. STDMETHODIMP
  144. CNWCOMPATNamespace::put_Filter(
  145. THIS_ VARIANT Var
  146. )
  147. {
  148. HRESULT hr;
  149. hr = VariantCopy(&_vFilter, &Var);
  150. RRETURN_EXP_IF_ERR(hr);
  151. }
  152. STDMETHODIMP
  153. CNWCOMPATNamespace::put_Hints(THIS_ VARIANT Var)
  154. {
  155. RRETURN_EXP_IF_ERR( E_NOTIMPL);
  156. }
  157. STDMETHODIMP
  158. CNWCOMPATNamespace::get_Hints(THIS_ VARIANT FAR* pVar)
  159. {
  160. RRETURN_EXP_IF_ERR(E_NOTIMPL);
  161. }
  162. STDMETHODIMP
  163. CNWCOMPATNamespace::GetObject(
  164. THIS_ BSTR ClassName,
  165. BSTR RelativeName,
  166. IDispatch * FAR* ppObject
  167. )
  168. {
  169. WCHAR szBuffer[MAX_PATH];
  170. DWORD dwLength = 0;
  171. HRESULT hr = S_OK;
  172. if (!RelativeName || !*RelativeName) {
  173. RRETURN_EXP_IF_ERR(E_ADS_UNKNOWN_OBJECT);
  174. }
  175. //
  176. // Make sure we are not going to overflow the string buffer.
  177. // +3 for // and \0
  178. //
  179. dwLength = wcslen(_ADsPath) + wcslen(RelativeName) + 3;
  180. if (dwLength > MAX_PATH) {
  181. BAIL_ON_FAILURE(hr = E_ADS_BAD_PARAMETER);
  182. }
  183. memset(szBuffer, 0, sizeof(szBuffer));
  184. wcscpy(szBuffer, _ADsPath);
  185. wcscat(szBuffer, L"//");
  186. wcscat(szBuffer, RelativeName);
  187. if (ClassName && *ClassName) {
  188. //
  189. // +1 for the ",".
  190. //
  191. dwLength += wcslen(ClassName) + 1;
  192. if (dwLength > MAX_PATH) {
  193. BAIL_ON_FAILURE(hr = E_ADS_BAD_PARAMETER);
  194. }
  195. wcscat(szBuffer,L",");
  196. wcscat(szBuffer, ClassName);
  197. }
  198. hr = ::GetObject(
  199. szBuffer,
  200. (LPVOID *)ppObject
  201. );
  202. BAIL_ON_FAILURE(hr);
  203. error:
  204. RRETURN_EXP_IF_ERR(hr);
  205. }
  206. STDMETHODIMP
  207. CNWCOMPATNamespace::get__NewEnum(
  208. THIS_ IUnknown * FAR* retval
  209. )
  210. {
  211. HRESULT hr;
  212. IUnknown FAR* punkEnum=NULL;
  213. IEnumVARIANT * penum = NULL;
  214. *retval = NULL;
  215. //
  216. // Create new enumerator for items currently
  217. // in collection and QI for IUnknown
  218. //
  219. hr = CNWCOMPATNamespaceEnum::Create(
  220. (CNWCOMPATNamespaceEnum **)&penum
  221. );
  222. BAIL_ON_FAILURE(hr);
  223. hr = penum->QueryInterface(
  224. IID_IUnknown,
  225. (VOID FAR* FAR*)retval
  226. );
  227. BAIL_ON_FAILURE(hr);
  228. if (penum) {
  229. penum->Release();
  230. }
  231. return NOERROR;
  232. error:
  233. if (penum) {
  234. delete penum;
  235. }
  236. RRETURN_EXP_IF_ERR(hr);
  237. }
  238. STDMETHODIMP
  239. CNWCOMPATNamespace::Create(
  240. THIS_ BSTR ClassName,
  241. BSTR RelativeName,
  242. IDispatch * FAR* ppObject
  243. )
  244. {
  245. RRETURN_EXP_IF_ERR(E_NOTIMPL);
  246. }
  247. STDMETHODIMP
  248. CNWCOMPATNamespace::Delete(
  249. THIS_ BSTR SourceName,
  250. BSTR Type
  251. )
  252. {
  253. RRETURN_EXP_IF_ERR(E_NOTIMPL);
  254. }
  255. STDMETHODIMP
  256. CNWCOMPATNamespace::CopyHere(
  257. THIS_ BSTR SourceName,
  258. BSTR NewName,
  259. IDispatch * FAR* ppObject
  260. )
  261. {
  262. RRETURN_EXP_IF_ERR(E_NOTIMPL);
  263. }
  264. STDMETHODIMP
  265. CNWCOMPATNamespace::MoveHere(
  266. THIS_ BSTR SourceName,
  267. BSTR NewName,
  268. IDispatch * FAR* ppObject
  269. )
  270. {
  271. RRETURN_EXP_IF_ERR(E_NOTIMPL);
  272. }
  273. HRESULT
  274. CNWCOMPATNamespace::AllocateNamespaceObject(
  275. CNWCOMPATNamespace ** ppNamespace
  276. )
  277. {
  278. CNWCOMPATNamespace FAR * pNamespace = NULL;
  279. CAggregatorDispMgr FAR * pDispMgr = NULL;
  280. HRESULT hr = S_OK;
  281. pNamespace = new CNWCOMPATNamespace();
  282. if (pNamespace == NULL) {
  283. hr = E_OUTOFMEMORY;
  284. }
  285. BAIL_ON_FAILURE(hr);
  286. pDispMgr = new CAggregatorDispMgr;
  287. if (pDispMgr == NULL) {
  288. hr = E_OUTOFMEMORY;
  289. }
  290. BAIL_ON_FAILURE(hr);
  291. hr = LoadTypeInfoEntry(
  292. pDispMgr,
  293. LIBID_ADs,
  294. IID_IADs,
  295. (IADs *)pNamespace,
  296. DISPID_REGULAR
  297. );
  298. BAIL_ON_FAILURE(hr);
  299. hr = LoadTypeInfoEntry(
  300. pDispMgr,
  301. LIBID_ADs,
  302. IID_IADsContainer,
  303. (IADsContainer *)pNamespace,
  304. DISPID_NEWENUM
  305. );
  306. BAIL_ON_FAILURE(hr);
  307. pNamespace->_pDispMgr = pDispMgr;
  308. *ppNamespace = pNamespace;
  309. RRETURN(hr);
  310. error:
  311. delete pDispMgr;
  312. RRETURN(hr);
  313. }
  314. HRESULT
  315. CNWCOMPATNamespace::ParsePath(
  316. BSTR bstrADsPath,
  317. DWORD dwType,
  318. PPATH_OBJECTINFO pObjectInfo
  319. )
  320. /*++
  321. Routine Description:
  322. Parse a path based on the type and return the information in pObjectInfo
  323. Arguments:
  324. bstrADsPath - ads path to be parsed
  325. dwType - the type of path to be parsed:
  326. ADS_PARSE_FULL
  327. ADS_PARSE_DN
  328. ADS_PARSE_COMPONENT
  329. pObjectInfo - the place where the parsed object is stored
  330. Return Value:
  331. S_OK on success, error code otherwise.
  332. --*/
  333. {
  334. HRESULT hr = S_OK;
  335. OBJECTINFO ObjInfo;
  336. POBJECTINFO pObjInfo = &ObjInfo;
  337. PWSTR szPath = NULL;
  338. memset(pObjInfo, 0, sizeof(OBJECTINFO));
  339. switch (dwType) {
  340. case ADS_PARSE_FULL:
  341. {
  342. CLexer Lexer(bstrADsPath);
  343. hr = Object(&Lexer, pObjInfo);
  344. BAIL_ON_FAILURE(hr);
  345. break;
  346. }
  347. case ADS_PARSE_DN:
  348. {
  349. WCHAR szToken[MAX_TOKEN_LENGTH];
  350. DWORD dwToken;
  351. //
  352. // Collecting new information
  353. //
  354. CLexer Lexer(bstrADsPath);
  355. Lexer.SetAtDisabler(TRUE);
  356. hr = PathName(&Lexer,
  357. pObjInfo);
  358. BAIL_ON_FAILURE(hr);
  359. hr = Lexer.GetNextToken(szToken,
  360. &dwToken);
  361. BAIL_ON_FAILURE(hr);
  362. if (dwToken != TOKEN_END) {
  363. hr = E_ADS_BAD_PATHNAME;
  364. }
  365. break;
  366. }
  367. case ADS_PARSE_COMPONENT:
  368. {
  369. CLexer Lexer(bstrADsPath);
  370. Lexer.SetAtDisabler(TRUE);
  371. hr = Component(&Lexer,
  372. pObjInfo);
  373. BAIL_ON_FAILURE(hr);
  374. break;
  375. }
  376. default:
  377. break;
  378. }
  379. //
  380. // Setting new info
  381. //
  382. if (pObjInfo->ProviderName) {
  383. pObjectInfo->ProviderName = AllocADsStr(pObjInfo->ProviderName);
  384. if (!pObjectInfo->ProviderName) {
  385. hr = E_OUTOFMEMORY;
  386. BAIL_ON_FAILURE(hr);
  387. }
  388. }
  389. hr = SetObjInfoComponents(pObjInfo,
  390. pObjectInfo);
  391. BAIL_ON_FAILURE(hr);
  392. pObjectInfo->NumComponents = pObjInfo->NumComponents;
  393. pObjectInfo->dwPathType = ADS_PATHTYPE_ROOTFIRST;
  394. error:
  395. FreeObjectInfo(pObjInfo,TRUE);
  396. if (szPath != NULL) {
  397. FreeADsStr(szPath);
  398. }
  399. return (hr);
  400. }
  401. HRESULT
  402. CNWCOMPATNamespace::SetObjInfoComponents(
  403. OBJECTINFO *pObjectInfo,
  404. PATH_OBJECTINFO *pObjectInfoTarget
  405. )
  406. /*++
  407. Routine Description:
  408. Set all the compoents in an objinfo from another objinfo. Assumes that the
  409. components in the target objinfo is empty. Users of this function can call
  410. FreeObjInfo to free that data prior to this function call.
  411. Arguments:
  412. Return Value:
  413. S_OK on success, error code otherwise.
  414. --*/
  415. {
  416. DWORD NumComponents;
  417. HRESULT hr = S_OK;
  418. NumComponents = 0;
  419. while (NumComponents < pObjectInfo->NumComponents) {
  420. if (pObjectInfo->ComponentArray[NumComponents]) {
  421. pObjectInfoTarget->ComponentArray[NumComponents].szComponent =
  422. AllocADsStr(pObjectInfo->ComponentArray[NumComponents]);
  423. if (pObjectInfoTarget->ComponentArray[NumComponents].szComponent == NULL) {
  424. pObjectInfoTarget->NumComponents = NumComponents;
  425. hr = E_OUTOFMEMORY;
  426. BAIL_ON_FAILURE(hr);
  427. }
  428. }
  429. if (pObjectInfo->DisplayComponentArray[NumComponents]) {
  430. pObjectInfoTarget->DisplayComponentArray[NumComponents].szComponent =
  431. AllocADsStr(pObjectInfo->DisplayComponentArray[NumComponents]);
  432. if (pObjectInfoTarget->DisplayComponentArray[NumComponents].szComponent == NULL) {
  433. pObjectInfoTarget->NumComponents = NumComponents;
  434. hr = E_OUTOFMEMORY;
  435. BAIL_ON_FAILURE(hr);
  436. }
  437. }
  438. NumComponents++;
  439. }
  440. pObjectInfoTarget->NumComponents = pObjectInfo->NumComponents;
  441. return hr;
  442. error:
  443. FreeObjInfoComponents(pObjectInfoTarget);
  444. RRETURN_EXP_IF_ERR(hr);
  445. }
  446. void
  447. CNWCOMPATNamespace::FreeObjInfoComponents(
  448. PATH_OBJECTINFO *pObjectInfo
  449. )
  450. /*++
  451. Routine Description:
  452. Free all the compoents in an objinfo
  453. Arguments:
  454. Return Value:
  455. S_OK on success, error code otherwise.
  456. --*/
  457. {
  458. DWORD NumComponents;
  459. while (pObjectInfo->NumComponents > 0) {
  460. pObjectInfo->NumComponents--;
  461. NumComponents = pObjectInfo->NumComponents;
  462. if (pObjectInfo->ComponentArray[NumComponents].szComponent) {
  463. FreeADsStr(
  464. pObjectInfo->ComponentArray[NumComponents].szComponent);
  465. pObjectInfo->ComponentArray[NumComponents].szComponent = NULL;
  466. }
  467. if (pObjectInfo->ComponentArray[NumComponents].szValue) {
  468. FreeADsStr(
  469. pObjectInfo->ComponentArray[NumComponents].szValue);
  470. pObjectInfo->ComponentArray[NumComponents].szValue = NULL;
  471. }
  472. if (pObjectInfo->DisplayComponentArray[NumComponents].szComponent) {
  473. FreeADsStr(
  474. pObjectInfo->DisplayComponentArray[NumComponents].szComponent);
  475. pObjectInfo->DisplayComponentArray[NumComponents].szComponent = NULL;
  476. }
  477. if (pObjectInfo->DisplayComponentArray[NumComponents].szValue) {
  478. FreeADsStr(
  479. pObjectInfo->DisplayComponentArray[NumComponents].szValue);
  480. pObjectInfo->DisplayComponentArray[NumComponents].szValue = NULL;
  481. }
  482. }
  483. }
  484. void
  485. CNWCOMPATNamespace::SetComponent(
  486. LPWSTR szReturn,
  487. DWORD cComponents,
  488. BOOL fEscaped
  489. )
  490. /*++
  491. Routine Description:
  492. Set an individual component in the pathname. For internal use only.
  493. Not exposed.
  494. Arguments:
  495. szReturn - the buffer to store the return value
  496. cComponents - the component number to be set
  497. Return Value:
  498. S_OK on success, error code otherwise.
  499. --*/
  500. {
  501. PATH_COMPONENT* pComponent = NULL;
  502. if (fEscaped) {
  503. pComponent = _pObjectInfo->DisplayComponentArray;
  504. }
  505. else {
  506. pComponent = _pObjectInfo->ComponentArray;
  507. }
  508. if (pComponent[cComponents].szValue) {
  509. //
  510. // If value exist, only show display value
  511. //
  512. wcscat(szReturn,
  513. pComponent[cComponents].szValue);
  514. }
  515. else {
  516. //
  517. // else value is only stored in Component
  518. //
  519. wcscat(szReturn,
  520. pComponent[cComponents].szComponent);
  521. }
  522. }
  523. HRESULT
  524. CNWCOMPATNamespace::SetComponents(
  525. LPWSTR szReturn,
  526. LPWSTR chSeparator,
  527. DWORD dwType,
  528. BOOL fEscaped
  529. )
  530. /*++
  531. Routine Description:
  532. Set components in the pathname. For internal use only. Not exposed.
  533. Arguments:
  534. szReturn - the buffer to store the return value
  535. chSeparator - separator to be used
  536. dwType - the type to be set
  537. ADS_COMPONENT_LEAF
  538. ADS_COMPONENT_DN
  539. ADS_COMPONENT_PARENT
  540. Return Value:
  541. S_OK on success, error code otherwise.
  542. --*/
  543. {
  544. HRESULT hr = S_OK;
  545. long cComponents;
  546. long dwLimit;
  547. long dwOtherLimit = 0;
  548. if (dwType == ADS_COMPONENT_LEAF) {
  549. //
  550. // Only returns the leaf component
  551. //
  552. if (_pObjectInfo->dwPathType == ADS_PATHTYPE_ROOTFIRST) {
  553. if (_pObjectInfo->NumComponents > 0) {
  554. SetComponent(szReturn,
  555. _pObjectInfo->NumComponents - 1,
  556. fEscaped);
  557. }
  558. else {
  559. hr = E_ADS_BAD_PATHNAME;
  560. }
  561. }
  562. else {
  563. if (_pObjectInfo->NumComponents != 0) {
  564. SetComponent(szReturn,
  565. 0,
  566. fEscaped);
  567. }
  568. else {
  569. hr = E_ADS_BAD_PATHNAME;
  570. }
  571. }
  572. RRETURN(hr);
  573. }
  574. dwLimit = _pObjectInfo->NumComponents;
  575. if (dwType == ADS_COMPONENT_PARENT) {
  576. dwLimit--;
  577. }
  578. if (dwOtherLimit >= dwLimit) {
  579. hr = E_ADS_BAD_PATHNAME;
  580. goto error;
  581. }
  582. for (cComponents = dwOtherLimit; cComponents < dwLimit; cComponents++) {
  583. SetComponent(szReturn,
  584. cComponents,
  585. fEscaped);
  586. if (cComponents != dwLimit - 1) {
  587. wcscat(szReturn,
  588. chSeparator);
  589. }
  590. }
  591. error:
  592. RRETURN(S_OK);
  593. }
  594. DWORD CountPath(
  595. PPATH_OBJECTINFO pObjectInfo
  596. )
  597. {
  598. DWORD dwPath = 4; // Basic needs '://' and '/' for servername
  599. DWORD i;
  600. if (pObjectInfo->ProviderName) {
  601. dwPath += wcslen(pObjectInfo->ProviderName);
  602. }
  603. if (pObjectInfo->DisplayServerName) {
  604. dwPath += wcslen(pObjectInfo->DisplayServerName);
  605. }
  606. for (i=0;i<pObjectInfo->NumComponents;i++) {
  607. if (pObjectInfo->DisplayComponentArray[i].szComponent) {
  608. dwPath += wcslen(pObjectInfo->DisplayComponentArray[i].szComponent);
  609. }
  610. if (pObjectInfo->DisplayComponentArray[i].szValue) {
  611. dwPath += wcslen(pObjectInfo->DisplayComponentArray[i].szValue);
  612. }
  613. //
  614. // Add one for comma separator, one for equal sign
  615. //
  616. dwPath+=2;
  617. }
  618. return dwPath;
  619. }
  620. STDMETHODIMP
  621. CNWCOMPATNamespace::ConstructPath(
  622. PPATH_OBJECTINFO pObjectInfo,
  623. DWORD dwFormatType,
  624. DWORD dwFlag,
  625. DWORD dwEscapedMode,
  626. BSTR *pbstrADsPath
  627. )
  628. {
  629. HRESULT hr = S_OK;
  630. PWSTR szReturn = NULL;
  631. long cComponents;
  632. DWORD dwPath = 0;
  633. BOOL fEscaped = FALSE;
  634. switch (dwEscapedMode) {
  635. case ADS_ESCAPEDMODE_OFF:
  636. case ADS_ESCAPEDMODE_DEFAULT:
  637. case ADS_ESCAPEDMODE_OFF_EX:
  638. fEscaped = FALSE;
  639. break;
  640. case ADS_ESCAPEDMODE_ON:
  641. fEscaped = TRUE;
  642. break;
  643. default:
  644. hr = E_INVALIDARG;
  645. goto error;
  646. }
  647. if (!pbstrADsPath) {
  648. hr = E_INVALIDARG;
  649. goto error;
  650. }
  651. dwPath = CountPath(pObjectInfo);
  652. szReturn = (PWSTR)AllocADsMem((dwPath + 1)* sizeof(WCHAR));
  653. if (szReturn == NULL) {
  654. hr = E_OUTOFMEMORY;
  655. goto error;
  656. }
  657. _pObjectInfo = pObjectInfo;
  658. wcscpy(szReturn,TEXT(""));
  659. switch (dwFormatType) {
  660. case ADS_FORMAT_WINDOWS:
  661. case ADS_FORMAT_WINDOWS_NO_SERVER:
  662. if (dwEscapedMode == ADS_ESCAPEDMODE_DEFAULT) {
  663. fEscaped = TRUE;
  664. }
  665. if (!pObjectInfo->ProviderName) {
  666. hr = E_FAIL; // Need Error Code
  667. goto error;
  668. }
  669. wcscat(szReturn,pObjectInfo->ProviderName);
  670. wcscat(szReturn,TEXT("://"));
  671. if (dwFormatType == ADS_FORMAT_WINDOWS) {
  672. if (pObjectInfo->DisplayServerName && (*(pObjectInfo->DisplayServerName))) {
  673. wcscat(szReturn,pObjectInfo->DisplayServerName);
  674. if (pObjectInfo->NumComponents>0) {
  675. wcscat(szReturn,TEXT("/"));
  676. }
  677. }
  678. }
  679. hr = SetComponents(szReturn,
  680. TEXT("/"),
  681. ADS_COMPONENT_DN,
  682. fEscaped);
  683. BAIL_ON_FAILURE(hr);
  684. break;
  685. case ADS_FORMAT_WINDOWS_DN:
  686. hr = SetComponents(szReturn,
  687. TEXT("/"),
  688. ADS_COMPONENT_DN,
  689. fEscaped);
  690. BAIL_ON_FAILURE(hr);
  691. break;
  692. case ADS_FORMAT_WINDOWS_PARENT:
  693. hr = SetComponents(szReturn,
  694. TEXT("/"),
  695. ADS_COMPONENT_PARENT,
  696. fEscaped);
  697. BAIL_ON_FAILURE(hr);
  698. break;
  699. case ADS_FORMAT_X500:
  700. case ADS_FORMAT_X500_NO_SERVER:
  701. case ADS_FORMAT_X500_DN:
  702. case ADS_FORMAT_X500_PARENT:
  703. hr = E_NOTIMPL;
  704. BAIL_ON_FAILURE(hr);
  705. break;
  706. case ADS_FORMAT_LEAF:
  707. //
  708. // Reverse only if pathtype is X500. In that case, we need to get
  709. // the first element but not the last
  710. //
  711. hr = SetComponents(szReturn,
  712. NULL,
  713. ADS_COMPONENT_LEAF,
  714. fEscaped);
  715. BAIL_ON_FAILURE(hr);
  716. break;
  717. default:
  718. hr = E_INVALIDARG;
  719. goto error;
  720. }
  721. hr = ADsAllocString(szReturn, pbstrADsPath);
  722. error:
  723. if (szReturn) {
  724. FreeADsMem(szReturn);
  725. }
  726. RRETURN_EXP_IF_ERR(hr);
  727. }
  728. STDMETHODIMP
  729. CNWCOMPATNamespace::GetEscapedElement(
  730. LONG lnReserved,
  731. BSTR bstrInStr,
  732. BSTR* pbstrOutStr
  733. )
  734. {
  735. RRETURN(E_NOTIMPL);
  736. }