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.

893 lines
21 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 pNamespace;
  312. delete pDispMgr;
  313. RRETURN(hr);
  314. }
  315. HRESULT
  316. CNWCOMPATNamespace::ParsePath(
  317. BSTR bstrADsPath,
  318. DWORD dwType,
  319. PPATH_OBJECTINFO pObjectInfo
  320. )
  321. /*++
  322. Routine Description:
  323. Parse a path based on the type and return the information in pObjectInfo
  324. Arguments:
  325. bstrADsPath - ads path to be parsed
  326. dwType - the type of path to be parsed:
  327. ADS_PARSE_FULL
  328. ADS_PARSE_DN
  329. ADS_PARSE_COMPONENT
  330. pObjectInfo - the place where the parsed object is stored
  331. Return Value:
  332. S_OK on success, error code otherwise.
  333. --*/
  334. {
  335. HRESULT hr = S_OK;
  336. OBJECTINFO ObjInfo;
  337. POBJECTINFO pObjInfo = &ObjInfo;
  338. PWSTR szPath = NULL;
  339. memset(pObjInfo, 0, sizeof(OBJECTINFO));
  340. switch (dwType) {
  341. case ADS_PARSE_FULL:
  342. {
  343. CLexer Lexer(bstrADsPath);
  344. hr = Object(&Lexer, pObjInfo);
  345. BAIL_ON_FAILURE(hr);
  346. break;
  347. }
  348. case ADS_PARSE_DN:
  349. {
  350. WCHAR szToken[MAX_TOKEN_LENGTH];
  351. DWORD dwToken;
  352. //
  353. // Collecting new information
  354. //
  355. CLexer Lexer(bstrADsPath);
  356. Lexer.SetAtDisabler(TRUE);
  357. hr = PathName(&Lexer,
  358. pObjInfo);
  359. BAIL_ON_FAILURE(hr);
  360. hr = Lexer.GetNextToken(szToken,
  361. &dwToken);
  362. BAIL_ON_FAILURE(hr);
  363. if (dwToken != TOKEN_END) {
  364. hr = E_ADS_BAD_PATHNAME;
  365. }
  366. break;
  367. }
  368. case ADS_PARSE_COMPONENT:
  369. {
  370. CLexer Lexer(bstrADsPath);
  371. Lexer.SetAtDisabler(TRUE);
  372. hr = Component(&Lexer,
  373. pObjInfo);
  374. BAIL_ON_FAILURE(hr);
  375. break;
  376. }
  377. default:
  378. break;
  379. }
  380. //
  381. // Setting new info
  382. //
  383. if (pObjInfo->ProviderName) {
  384. pObjectInfo->ProviderName = AllocADsStr(pObjInfo->ProviderName);
  385. if (!pObjectInfo->ProviderName) {
  386. hr = E_OUTOFMEMORY;
  387. BAIL_ON_FAILURE(hr);
  388. }
  389. }
  390. hr = SetObjInfoComponents(pObjInfo,
  391. pObjectInfo);
  392. BAIL_ON_FAILURE(hr);
  393. pObjectInfo->NumComponents = pObjInfo->NumComponents;
  394. pObjectInfo->dwPathType = ADS_PATHTYPE_ROOTFIRST;
  395. error:
  396. FreeObjectInfo(pObjInfo,TRUE);
  397. if (szPath != NULL) {
  398. FreeADsStr(szPath);
  399. }
  400. return (hr);
  401. }
  402. HRESULT
  403. CNWCOMPATNamespace::SetObjInfoComponents(
  404. OBJECTINFO *pObjectInfo,
  405. PATH_OBJECTINFO *pObjectInfoTarget
  406. )
  407. /*++
  408. Routine Description:
  409. Set all the compoents in an objinfo from another objinfo. Assumes that the
  410. components in the target objinfo is empty. Users of this function can call
  411. FreeObjInfo to free that data prior to this function call.
  412. Arguments:
  413. Return Value:
  414. S_OK on success, error code otherwise.
  415. --*/
  416. {
  417. DWORD NumComponents;
  418. HRESULT hr = S_OK;
  419. NumComponents = 0;
  420. while (NumComponents < pObjectInfo->NumComponents) {
  421. if (pObjectInfo->ComponentArray[NumComponents]) {
  422. pObjectInfoTarget->ComponentArray[NumComponents].szComponent =
  423. AllocADsStr(pObjectInfo->ComponentArray[NumComponents]);
  424. if (pObjectInfoTarget->ComponentArray[NumComponents].szComponent == NULL) {
  425. pObjectInfoTarget->NumComponents = NumComponents;
  426. hr = E_OUTOFMEMORY;
  427. BAIL_ON_FAILURE(hr);
  428. }
  429. }
  430. if (pObjectInfo->DisplayComponentArray[NumComponents]) {
  431. pObjectInfoTarget->DisplayComponentArray[NumComponents].szComponent =
  432. AllocADsStr(pObjectInfo->DisplayComponentArray[NumComponents]);
  433. if (pObjectInfoTarget->DisplayComponentArray[NumComponents].szComponent == NULL) {
  434. pObjectInfoTarget->NumComponents = NumComponents;
  435. hr = E_OUTOFMEMORY;
  436. BAIL_ON_FAILURE(hr);
  437. }
  438. }
  439. NumComponents++;
  440. }
  441. pObjectInfoTarget->NumComponents = pObjectInfo->NumComponents;
  442. return hr;
  443. error:
  444. FreeObjInfoComponents(pObjectInfoTarget);
  445. RRETURN_EXP_IF_ERR(hr);
  446. }
  447. void
  448. CNWCOMPATNamespace::FreeObjInfoComponents(
  449. PATH_OBJECTINFO *pObjectInfo
  450. )
  451. /*++
  452. Routine Description:
  453. Free all the compoents in an objinfo
  454. Arguments:
  455. Return Value:
  456. S_OK on success, error code otherwise.
  457. --*/
  458. {
  459. DWORD NumComponents;
  460. while (pObjectInfo->NumComponents > 0) {
  461. pObjectInfo->NumComponents--;
  462. NumComponents = pObjectInfo->NumComponents;
  463. if (pObjectInfo->ComponentArray[NumComponents].szComponent) {
  464. FreeADsStr(
  465. pObjectInfo->ComponentArray[NumComponents].szComponent);
  466. pObjectInfo->ComponentArray[NumComponents].szComponent = NULL;
  467. }
  468. if (pObjectInfo->ComponentArray[NumComponents].szValue) {
  469. FreeADsStr(
  470. pObjectInfo->ComponentArray[NumComponents].szValue);
  471. pObjectInfo->ComponentArray[NumComponents].szValue = NULL;
  472. }
  473. if (pObjectInfo->DisplayComponentArray[NumComponents].szComponent) {
  474. FreeADsStr(
  475. pObjectInfo->DisplayComponentArray[NumComponents].szComponent);
  476. pObjectInfo->DisplayComponentArray[NumComponents].szComponent = NULL;
  477. }
  478. if (pObjectInfo->DisplayComponentArray[NumComponents].szValue) {
  479. FreeADsStr(
  480. pObjectInfo->DisplayComponentArray[NumComponents].szValue);
  481. pObjectInfo->DisplayComponentArray[NumComponents].szValue = NULL;
  482. }
  483. }
  484. }
  485. void
  486. CNWCOMPATNamespace::SetComponent(
  487. LPWSTR szReturn,
  488. DWORD cComponents,
  489. BOOL fEscaped
  490. )
  491. /*++
  492. Routine Description:
  493. Set an individual component in the pathname. For internal use only.
  494. Not exposed.
  495. Arguments:
  496. szReturn - the buffer to store the return value
  497. cComponents - the component number to be set
  498. Return Value:
  499. S_OK on success, error code otherwise.
  500. --*/
  501. {
  502. PATH_COMPONENT* pComponent = NULL;
  503. if (fEscaped) {
  504. pComponent = _pObjectInfo->DisplayComponentArray;
  505. }
  506. else {
  507. pComponent = _pObjectInfo->ComponentArray;
  508. }
  509. if (pComponent[cComponents].szValue) {
  510. //
  511. // If value exist, only show display value
  512. //
  513. wcscat(szReturn,
  514. pComponent[cComponents].szValue);
  515. }
  516. else {
  517. //
  518. // else value is only stored in Component
  519. //
  520. wcscat(szReturn,
  521. pComponent[cComponents].szComponent);
  522. }
  523. }
  524. HRESULT
  525. CNWCOMPATNamespace::SetComponents(
  526. LPWSTR szReturn,
  527. LPWSTR chSeparator,
  528. DWORD dwType,
  529. BOOL fEscaped
  530. )
  531. /*++
  532. Routine Description:
  533. Set components in the pathname. For internal use only. Not exposed.
  534. Arguments:
  535. szReturn - the buffer to store the return value
  536. chSeparator - separator to be used
  537. dwType - the type to be set
  538. ADS_COMPONENT_LEAF
  539. ADS_COMPONENT_DN
  540. ADS_COMPONENT_PARENT
  541. Return Value:
  542. S_OK on success, error code otherwise.
  543. --*/
  544. {
  545. HRESULT hr = S_OK;
  546. long cComponents;
  547. long dwLimit;
  548. long dwOtherLimit = 0;
  549. if (dwType == ADS_COMPONENT_LEAF) {
  550. //
  551. // Only returns the leaf component
  552. //
  553. if (_pObjectInfo->dwPathType == ADS_PATHTYPE_ROOTFIRST) {
  554. if (_pObjectInfo->NumComponents > 0) {
  555. SetComponent(szReturn,
  556. _pObjectInfo->NumComponents - 1,
  557. fEscaped);
  558. }
  559. else {
  560. hr = E_ADS_BAD_PATHNAME;
  561. }
  562. }
  563. else {
  564. if (_pObjectInfo->NumComponents != 0) {
  565. SetComponent(szReturn,
  566. 0,
  567. fEscaped);
  568. }
  569. else {
  570. hr = E_ADS_BAD_PATHNAME;
  571. }
  572. }
  573. RRETURN(hr);
  574. }
  575. dwLimit = _pObjectInfo->NumComponents;
  576. if (dwType == ADS_COMPONENT_PARENT) {
  577. dwLimit--;
  578. }
  579. if (dwOtherLimit >= dwLimit) {
  580. hr = E_ADS_BAD_PATHNAME;
  581. goto error;
  582. }
  583. for (cComponents = dwOtherLimit; cComponents < dwLimit; cComponents++) {
  584. SetComponent(szReturn,
  585. cComponents,
  586. fEscaped);
  587. if (cComponents != dwLimit - 1) {
  588. wcscat(szReturn,
  589. chSeparator);
  590. }
  591. }
  592. error:
  593. RRETURN(S_OK);
  594. }
  595. DWORD CountPath(
  596. PPATH_OBJECTINFO pObjectInfo
  597. )
  598. {
  599. DWORD dwPath = 4; // Basic needs '://' and '/' for servername
  600. DWORD i;
  601. if (pObjectInfo->ProviderName) {
  602. dwPath += wcslen(pObjectInfo->ProviderName);
  603. }
  604. if (pObjectInfo->DisplayServerName) {
  605. dwPath += wcslen(pObjectInfo->DisplayServerName);
  606. }
  607. for (i=0;i<pObjectInfo->NumComponents;i++) {
  608. if (pObjectInfo->DisplayComponentArray[i].szComponent) {
  609. dwPath += wcslen(pObjectInfo->DisplayComponentArray[i].szComponent);
  610. }
  611. if (pObjectInfo->DisplayComponentArray[i].szValue) {
  612. dwPath += wcslen(pObjectInfo->DisplayComponentArray[i].szValue);
  613. }
  614. //
  615. // Add one for comma separator, one for equal sign
  616. //
  617. dwPath+=2;
  618. }
  619. return dwPath;
  620. }
  621. STDMETHODIMP
  622. CNWCOMPATNamespace::ConstructPath(
  623. PPATH_OBJECTINFO pObjectInfo,
  624. DWORD dwFormatType,
  625. DWORD dwFlag,
  626. DWORD dwEscapedMode,
  627. BSTR *pbstrADsPath
  628. )
  629. {
  630. HRESULT hr = S_OK;
  631. PWSTR szReturn = NULL;
  632. long cComponents;
  633. DWORD dwPath = 0;
  634. BOOL fEscaped = FALSE;
  635. switch (dwEscapedMode) {
  636. case ADS_ESCAPEDMODE_OFF:
  637. case ADS_ESCAPEDMODE_DEFAULT:
  638. case ADS_ESCAPEDMODE_OFF_EX:
  639. fEscaped = FALSE;
  640. break;
  641. case ADS_ESCAPEDMODE_ON:
  642. fEscaped = TRUE;
  643. break;
  644. default:
  645. hr = E_INVALIDARG;
  646. goto error;
  647. }
  648. if (!pbstrADsPath) {
  649. hr = E_INVALIDARG;
  650. goto error;
  651. }
  652. dwPath = CountPath(pObjectInfo);
  653. szReturn = (PWSTR)AllocADsMem((dwPath + 1)* sizeof(WCHAR));
  654. if (szReturn == NULL) {
  655. hr = E_OUTOFMEMORY;
  656. goto error;
  657. }
  658. _pObjectInfo = pObjectInfo;
  659. wcscpy(szReturn,TEXT(""));
  660. switch (dwFormatType) {
  661. case ADS_FORMAT_WINDOWS:
  662. case ADS_FORMAT_WINDOWS_NO_SERVER:
  663. if (dwEscapedMode == ADS_ESCAPEDMODE_DEFAULT) {
  664. fEscaped = TRUE;
  665. }
  666. if (!pObjectInfo->ProviderName) {
  667. hr = E_FAIL; // Need Error Code
  668. goto error;
  669. }
  670. wcscat(szReturn,pObjectInfo->ProviderName);
  671. wcscat(szReturn,TEXT("://"));
  672. if (dwFormatType == ADS_FORMAT_WINDOWS) {
  673. if (pObjectInfo->DisplayServerName && (*(pObjectInfo->DisplayServerName))) {
  674. wcscat(szReturn,pObjectInfo->DisplayServerName);
  675. if (pObjectInfo->NumComponents>0) {
  676. wcscat(szReturn,TEXT("/"));
  677. }
  678. }
  679. }
  680. hr = SetComponents(szReturn,
  681. TEXT("/"),
  682. ADS_COMPONENT_DN,
  683. fEscaped);
  684. BAIL_ON_FAILURE(hr);
  685. break;
  686. case ADS_FORMAT_WINDOWS_DN:
  687. hr = SetComponents(szReturn,
  688. TEXT("/"),
  689. ADS_COMPONENT_DN,
  690. fEscaped);
  691. BAIL_ON_FAILURE(hr);
  692. break;
  693. case ADS_FORMAT_WINDOWS_PARENT:
  694. hr = SetComponents(szReturn,
  695. TEXT("/"),
  696. ADS_COMPONENT_PARENT,
  697. fEscaped);
  698. BAIL_ON_FAILURE(hr);
  699. break;
  700. case ADS_FORMAT_X500:
  701. case ADS_FORMAT_X500_NO_SERVER:
  702. case ADS_FORMAT_X500_DN:
  703. case ADS_FORMAT_X500_PARENT:
  704. hr = E_NOTIMPL;
  705. BAIL_ON_FAILURE(hr);
  706. break;
  707. case ADS_FORMAT_LEAF:
  708. //
  709. // Reverse only if pathtype is X500. In that case, we need to get
  710. // the first element but not the last
  711. //
  712. hr = SetComponents(szReturn,
  713. NULL,
  714. ADS_COMPONENT_LEAF,
  715. fEscaped);
  716. BAIL_ON_FAILURE(hr);
  717. break;
  718. default:
  719. hr = E_INVALIDARG;
  720. goto error;
  721. }
  722. hr = ADsAllocString(szReturn, pbstrADsPath);
  723. error:
  724. if (szReturn) {
  725. FreeADsMem(szReturn);
  726. }
  727. RRETURN_EXP_IF_ERR(hr);
  728. }
  729. STDMETHODIMP
  730. CNWCOMPATNamespace::GetEscapedElement(
  731. LONG lnReserved,
  732. BSTR bstrInStr,
  733. BSTR* pbstrOutStr
  734. )
  735. {
  736. RRETURN(E_NOTIMPL);
  737. }