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.

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