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.

1037 lines
25 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 pNamespace;
  282. delete pDispMgr;
  283. RRETURN(hr);
  284. }
  285. STDMETHODIMP
  286. CNDSNamespace::Get(
  287. THIS_ BSTR bstrName,
  288. VARIANT FAR* pvProp
  289. )
  290. {
  291. //
  292. // retrieve dataobject from cache; if one exists
  293. //
  294. //
  295. //
  296. //
  297. RRETURN_EXP_IF_ERR(E_NOTIMPL);
  298. }
  299. STDMETHODIMP
  300. CNDSNamespace::Put(
  301. THIS_ BSTR bstrName,
  302. VARIANT vProp
  303. )
  304. {
  305. RRETURN_EXP_IF_ERR(E_NOTIMPL);
  306. }
  307. STDMETHODIMP
  308. CNDSNamespace::GetEx(
  309. THIS_ BSTR bstrName,
  310. VARIANT FAR* pvProp
  311. )
  312. {
  313. RRETURN_EXP_IF_ERR(E_NOTIMPL);
  314. }
  315. STDMETHODIMP
  316. CNDSNamespace::PutEx(
  317. THIS_ long lnControlCode,
  318. BSTR bstrName,
  319. VARIANT vProp
  320. )
  321. {
  322. RRETURN_EXP_IF_ERR(E_NOTIMPL);
  323. }
  324. STDMETHODIMP
  325. CNDSNamespace::OpenDSObject(
  326. BSTR lpszDNName,
  327. BSTR lpszUserName,
  328. BSTR lpszPassword,
  329. LONG lnReserved,
  330. IDispatch FAR * * ppADsObj
  331. )
  332. {
  333. HRESULT hr = S_OK;
  334. IUnknown * pObject = NULL;
  335. CCredentials Credentials(lpszUserName, lpszPassword, 0L);
  336. hr = ::GetObject(
  337. lpszDNName,
  338. Credentials,
  339. (LPVOID *)&pObject
  340. );
  341. BAIL_ON_FAILURE(hr);
  342. hr = pObject->QueryInterface(
  343. IID_IDispatch,
  344. (void **)ppADsObj
  345. );
  346. BAIL_ON_FAILURE(hr);
  347. error:
  348. if (pObject) {
  349. pObject->Release();
  350. }
  351. RRETURN_EXP_IF_ERR(hr);
  352. }
  353. HRESULT
  354. CNDSNamespace::ParsePath(
  355. BSTR bstrADsPath,
  356. DWORD dwType,
  357. PPATH_OBJECTINFO pObjectInfo
  358. )
  359. /*++
  360. Routine Description:
  361. Parse a path based on the type and return the information in pObjectInfo
  362. Arguments:
  363. bstrADsPath - ads path to be parsed
  364. dwType - the type of path to be parsed:
  365. ADS_PARSE_FULL
  366. ADS_PARSE_DN
  367. ADS_PARSE_COMPONENT
  368. pObjectInfo - the place where the parsed object is stored
  369. Return Value:
  370. S_OK on success, error code otherwise.
  371. --*/
  372. {
  373. HRESULT hr = S_OK;
  374. OBJECTINFO ObjInfo;
  375. POBJECTINFO pObjInfo = &ObjInfo;
  376. PWSTR szPath = NULL;
  377. memset(pObjInfo, 0, sizeof(OBJECTINFO));
  378. switch (dwType) {
  379. case ADS_PARSE_FULL:
  380. {
  381. CLexer Lexer(bstrADsPath);
  382. hr = ADsObject(&Lexer, pObjInfo);
  383. BAIL_ON_FAILURE(hr);
  384. break;
  385. }
  386. case ADS_PARSE_DN:
  387. {
  388. WCHAR szToken[MAX_TOKEN_LENGTH];
  389. DWORD dwToken;
  390. CLexer Lexer(bstrADsPath);
  391. Lexer.SetAtDisabler(TRUE);
  392. hr = PathName(&Lexer,
  393. pObjInfo);
  394. BAIL_ON_FAILURE(hr);
  395. hr = Lexer.GetNextToken(szToken,
  396. &dwToken);
  397. BAIL_ON_FAILURE(hr);
  398. if (dwToken != TOKEN_END) {
  399. hr = E_ADS_BAD_PATHNAME;
  400. }
  401. break;
  402. }
  403. case ADS_PARSE_COMPONENT:
  404. {
  405. CLexer Lexer(bstrADsPath);
  406. Lexer.SetAtDisabler(TRUE);
  407. hr = Component(&Lexer,
  408. pObjInfo);
  409. BAIL_ON_FAILURE(hr);
  410. break;
  411. }
  412. default:
  413. break;
  414. }
  415. //
  416. // Setting new info
  417. //
  418. if (pObjInfo->ProviderName) {
  419. pObjectInfo->ProviderName = AllocADsStr(pObjInfo->ProviderName);
  420. if (!pObjectInfo->ProviderName) {
  421. hr = E_OUTOFMEMORY;
  422. BAIL_ON_FAILURE(hr);
  423. }
  424. }
  425. if (pObjInfo->TreeName) {
  426. pObjectInfo->ServerName = AllocADsStr(pObjInfo->TreeName);
  427. if (!pObjectInfo->ServerName) {
  428. hr = E_OUTOFMEMORY;
  429. BAIL_ON_FAILURE(hr);
  430. }
  431. }
  432. if (pObjInfo->DisplayTreeName) {
  433. pObjectInfo->DisplayServerName = AllocADsStr(pObjInfo->DisplayTreeName);
  434. if (!pObjectInfo->DisplayServerName) {
  435. hr = E_OUTOFMEMORY;
  436. BAIL_ON_FAILURE(hr);
  437. }
  438. }
  439. hr = SetObjInfoComponents(pObjInfo,
  440. pObjectInfo);
  441. BAIL_ON_FAILURE(hr);
  442. pObjectInfo->NumComponents = pObjInfo->NumComponents;
  443. pObjectInfo->dwPathType = ADS_PATHTYPE_ROOTFIRST;
  444. error:
  445. FreeObjectInfo(pObjInfo);
  446. if (szPath != NULL) {
  447. FreeADsStr(szPath);
  448. }
  449. return (hr);
  450. }
  451. HRESULT
  452. CNDSNamespace::SetObjInfoComponents(
  453. OBJECTINFO *pObjectInfo,
  454. PATH_OBJECTINFO *pObjectInfoTarget
  455. )
  456. /*++
  457. Routine Description:
  458. Set all the compoents in an objinfo from another objinfo. Assumes that the
  459. components in the target objinfo is empty. Users of this function can call
  460. FreeObjInfo to free that data prior to this function call.
  461. Arguments:
  462. Return Value:
  463. S_OK on success, error code otherwise.
  464. --*/
  465. {
  466. DWORD NumComponents;
  467. HRESULT hr = S_OK;
  468. NumComponents = 0;
  469. while (NumComponents < pObjectInfo->NumComponents) {
  470. if (pObjectInfo->ComponentArray[NumComponents].szComponent) {
  471. pObjectInfoTarget->ComponentArray[NumComponents].szComponent =
  472. AllocADsStr(pObjectInfo->ComponentArray[NumComponents].szComponent);
  473. if (pObjectInfoTarget->ComponentArray[NumComponents].szComponent == NULL) {
  474. pObjectInfoTarget->NumComponents = NumComponents;
  475. hr = E_OUTOFMEMORY;
  476. BAIL_ON_FAILURE(hr);
  477. }
  478. }
  479. if (pObjectInfo->ComponentArray[NumComponents].szValue) {
  480. pObjectInfoTarget->ComponentArray[NumComponents].szValue =
  481. AllocADsStr(pObjectInfo->ComponentArray[NumComponents].szValue);
  482. if (pObjectInfoTarget->ComponentArray[NumComponents].szValue == NULL) {
  483. pObjectInfoTarget->NumComponents = NumComponents;
  484. hr = E_OUTOFMEMORY;
  485. BAIL_ON_FAILURE(hr);
  486. }
  487. }
  488. if (pObjectInfo->DisplayComponentArray[NumComponents].szComponent) {
  489. pObjectInfoTarget->DisplayComponentArray[NumComponents].szComponent =
  490. AllocADsStr(pObjectInfo->DisplayComponentArray[NumComponents].szComponent);
  491. if (pObjectInfoTarget->DisplayComponentArray[NumComponents].szComponent == NULL) {
  492. pObjectInfoTarget->NumComponents = NumComponents;
  493. hr = E_OUTOFMEMORY;
  494. BAIL_ON_FAILURE(hr);
  495. }
  496. }
  497. if (pObjectInfo->DisplayComponentArray[NumComponents].szValue) {
  498. pObjectInfoTarget->DisplayComponentArray[NumComponents].szValue =
  499. AllocADsStr(pObjectInfo->DisplayComponentArray[NumComponents].szValue);
  500. if (pObjectInfoTarget->DisplayComponentArray[NumComponents].szValue == NULL) {
  501. pObjectInfoTarget->NumComponents = NumComponents;
  502. hr = E_OUTOFMEMORY;
  503. BAIL_ON_FAILURE(hr);
  504. }
  505. }
  506. NumComponents++;
  507. }
  508. pObjectInfoTarget->NumComponents = pObjectInfo->NumComponents;
  509. return hr;
  510. error:
  511. FreeObjInfoComponents(pObjectInfoTarget);
  512. RRETURN_EXP_IF_ERR(hr);
  513. }
  514. void
  515. CNDSNamespace::FreeObjInfoComponents(
  516. PATH_OBJECTINFO *pObjectInfo
  517. )
  518. /*++
  519. Routine Description:
  520. Free all the compoents in an objinfo
  521. Arguments:
  522. Return Value:
  523. S_OK on success, error code otherwise.
  524. --*/
  525. {
  526. DWORD NumComponents;
  527. while (pObjectInfo->NumComponents > 0) {
  528. pObjectInfo->NumComponents--;
  529. NumComponents = pObjectInfo->NumComponents;
  530. if (pObjectInfo->ComponentArray[NumComponents].szComponent) {
  531. FreeADsStr(
  532. pObjectInfo->ComponentArray[NumComponents].szComponent);
  533. pObjectInfo->ComponentArray[NumComponents].szComponent = NULL;
  534. }
  535. if (pObjectInfo->ComponentArray[NumComponents].szValue) {
  536. FreeADsStr(
  537. pObjectInfo->ComponentArray[NumComponents].szValue);
  538. pObjectInfo->ComponentArray[NumComponents].szValue = NULL;
  539. }
  540. if (pObjectInfo->DisplayComponentArray[NumComponents].szComponent) {
  541. FreeADsStr(
  542. pObjectInfo->DisplayComponentArray[NumComponents].szComponent);
  543. pObjectInfo->DisplayComponentArray[NumComponents].szComponent = NULL;
  544. }
  545. if (pObjectInfo->DisplayComponentArray[NumComponents].szValue) {
  546. FreeADsStr(
  547. pObjectInfo->DisplayComponentArray[NumComponents].szValue);
  548. pObjectInfo->DisplayComponentArray[NumComponents].szValue = NULL;
  549. }
  550. }
  551. }
  552. void
  553. CNDSNamespace::SetComponent(
  554. LPWSTR szReturn,
  555. DWORD cComponents,
  556. BOOL fEscaped
  557. )
  558. /*++
  559. Routine Description:
  560. Set an individual component in the pathname. For internal use only.
  561. Not exposed.
  562. Arguments:
  563. szReturn - the buffer to store the return value
  564. cComponents - the component number to be set
  565. Return Value:
  566. S_OK on success, error code otherwise.
  567. --*/
  568. {
  569. PATH_COMPONENT* pComponent = NULL;
  570. if (fEscaped) {
  571. pComponent = _pObjectInfo->DisplayComponentArray;
  572. }
  573. else {
  574. pComponent = _pObjectInfo->ComponentArray;
  575. }
  576. if (_fNamingAttribute) {
  577. wcscat(szReturn, pComponent[cComponents].szComponent);
  578. if (pComponent[cComponents].szValue) {
  579. wcscat(szReturn,
  580. TEXT("="));
  581. wcscat(szReturn,
  582. pComponent[cComponents].szValue);
  583. }
  584. }
  585. else {
  586. if (pComponent[cComponents].szValue) {
  587. //
  588. // If value exist, only show display value
  589. //
  590. wcscat(szReturn,
  591. pComponent[cComponents].szValue);
  592. }
  593. else {
  594. //
  595. // else value is only stored in Component
  596. //
  597. wcscat(szReturn,
  598. pComponent[cComponents].szComponent);
  599. }
  600. }
  601. }
  602. HRESULT
  603. CNDSNamespace::SetComponents(
  604. LPWSTR szReturn,
  605. BOOLEAN bIsWindowsPath,
  606. LPWSTR chSeparator,
  607. DWORD dwType,
  608. BOOL fEscaped
  609. )
  610. /*++
  611. Routine Description:
  612. Set components in the pathname. For internal use only. Not exposed.
  613. Arguments:
  614. szReturn - the buffer to store the return value
  615. bIsWindowsPath - whether a windows path is to be returned
  616. chSeparator - separator to be used
  617. dwType - the type to be set
  618. ADS_COMPONENT_LEAF
  619. ADS_COMPONENT_DN
  620. ADS_COMPONENT_PARENT
  621. Return Value:
  622. S_OK on success, error code otherwise.
  623. --*/
  624. {
  625. HRESULT hr = S_OK;
  626. BOOL bReverse;
  627. long cComponents;
  628. long dwLimit;
  629. long dwOtherLimit = 0;
  630. if (dwType == ADS_COMPONENT_LEAF) {
  631. //
  632. // Only returns the leaf component
  633. //
  634. if (_pObjectInfo->dwPathType == ADS_PATHTYPE_ROOTFIRST) {
  635. if (_pObjectInfo->NumComponents > 0) {
  636. SetComponent(szReturn,
  637. _pObjectInfo->NumComponents - 1,
  638. fEscaped);
  639. }
  640. else {
  641. hr = E_ADS_BAD_PATHNAME;
  642. }
  643. }
  644. else {
  645. if (_pObjectInfo->NumComponents != 0) {
  646. SetComponent(szReturn,
  647. 0,
  648. fEscaped);
  649. }
  650. else {
  651. hr = E_ADS_BAD_PATHNAME;
  652. }
  653. }
  654. RRETURN(hr);
  655. }
  656. if (_pObjectInfo->dwPathType == ADS_PATHTYPE_ROOTFIRST) {
  657. bReverse = !bIsWindowsPath;
  658. }
  659. else {
  660. bReverse = bIsWindowsPath;
  661. }
  662. if (!bReverse) {
  663. dwLimit = _pObjectInfo->NumComponents;
  664. if (dwType == ADS_COMPONENT_PARENT) {
  665. if (_pObjectInfo->dwPathType == ADS_PATHTYPE_ROOTFIRST)
  666. dwLimit--;
  667. else
  668. dwOtherLimit++;
  669. }
  670. if (dwOtherLimit >= dwLimit) {
  671. hr = E_ADS_BAD_PATHNAME;
  672. goto error;
  673. }
  674. for (cComponents = dwOtherLimit; cComponents < dwLimit; cComponents++) {
  675. SetComponent(szReturn,
  676. cComponents,
  677. fEscaped);
  678. if (cComponents != dwLimit - 1) {
  679. wcscat(szReturn,
  680. chSeparator);
  681. }
  682. }
  683. }
  684. else {
  685. dwLimit = _pObjectInfo->NumComponents-1;
  686. if (dwType == ADS_COMPONENT_PARENT) {
  687. if (_pObjectInfo->dwPathType == ADS_PATHTYPE_ROOTFIRST)
  688. dwLimit--;
  689. else
  690. dwOtherLimit++;
  691. }
  692. if (dwLimit < dwOtherLimit) {
  693. hr = E_ADS_BAD_PATHNAME;
  694. goto error;
  695. }
  696. for (cComponents = dwLimit ; (long)cComponents >= dwOtherLimit; cComponents--) {
  697. SetComponent(szReturn,
  698. cComponents,
  699. fEscaped);
  700. if (cComponents != dwOtherLimit) {
  701. wcscat(szReturn, chSeparator);
  702. }
  703. }
  704. }
  705. error:
  706. RRETURN(S_OK);
  707. }
  708. DWORD CountPath(
  709. PPATH_OBJECTINFO pObjectInfo
  710. )
  711. {
  712. DWORD dwPath = 4; // Basic needs '://' and '/' for servername
  713. DWORD i;
  714. if (pObjectInfo->ProviderName) {
  715. dwPath += wcslen(pObjectInfo->ProviderName);
  716. }
  717. if (pObjectInfo->DisplayServerName) {
  718. dwPath += wcslen(pObjectInfo->DisplayServerName);
  719. }
  720. for (i=0;i<pObjectInfo->NumComponents;i++) {
  721. if (pObjectInfo->DisplayComponentArray[i].szComponent) {
  722. dwPath += wcslen(pObjectInfo->DisplayComponentArray[i].szComponent);
  723. }
  724. if (pObjectInfo->DisplayComponentArray[i].szValue) {
  725. dwPath += wcslen(pObjectInfo->DisplayComponentArray[i].szValue);
  726. }
  727. //
  728. // Add one for comma separator, one for equal sign
  729. //
  730. dwPath+=2;
  731. }
  732. return dwPath;
  733. }
  734. STDMETHODIMP
  735. CNDSNamespace::ConstructPath(
  736. PPATH_OBJECTINFO pObjectInfo,
  737. DWORD dwFormatType,
  738. DWORD dwFlag,
  739. DWORD dwEscapedMode,
  740. BSTR *pbstrADsPath
  741. )
  742. {
  743. HRESULT hr = S_OK;
  744. PWSTR szReturn = NULL;
  745. long cComponents;
  746. DWORD dwPath = 0;
  747. BOOL fEscaped = FALSE;
  748. switch (dwEscapedMode) {
  749. case ADS_ESCAPEDMODE_OFF:
  750. case ADS_ESCAPEDMODE_OFF_EX:
  751. case ADS_ESCAPEDMODE_DEFAULT:
  752. fEscaped = FALSE;
  753. break;
  754. case ADS_ESCAPEDMODE_ON:
  755. fEscaped = TRUE;
  756. break;
  757. default:
  758. hr = E_INVALIDARG;
  759. goto error;
  760. }
  761. if (!pbstrADsPath) {
  762. hr = E_INVALIDARG;
  763. goto error;
  764. }
  765. dwPath = CountPath(pObjectInfo);
  766. szReturn = (PWSTR)AllocADsMem((dwPath + 1)* sizeof(WCHAR));
  767. if (szReturn == NULL) {
  768. hr = E_OUTOFMEMORY;
  769. goto error;
  770. }
  771. _fNamingAttribute = (BOOLEAN)(dwFlag & ADS_CONSTRUCT_NAMINGATTRIBUTE);
  772. _pObjectInfo = pObjectInfo;
  773. wcscpy(szReturn,TEXT(""));
  774. switch (dwFormatType) {
  775. case ADS_FORMAT_WINDOWS:
  776. case ADS_FORMAT_WINDOWS_NO_SERVER:
  777. if (dwEscapedMode == ADS_ESCAPEDMODE_DEFAULT) {
  778. fEscaped = TRUE;
  779. }
  780. if (!pObjectInfo->ProviderName) {
  781. hr = E_FAIL; // Need Error Code
  782. goto error;
  783. }
  784. wcscat(szReturn,pObjectInfo->ProviderName);
  785. wcscat(szReturn,TEXT("://"));
  786. if (dwFormatType == ADS_FORMAT_WINDOWS) {
  787. if (pObjectInfo->DisplayServerName && (*(pObjectInfo->DisplayServerName))) {
  788. wcscat(szReturn,pObjectInfo->DisplayServerName);
  789. if (pObjectInfo->NumComponents>0) {
  790. wcscat(szReturn,TEXT("/"));
  791. }
  792. }
  793. }
  794. hr = SetComponents(szReturn,
  795. TRUE,
  796. TEXT("/"),
  797. ADS_COMPONENT_DN,
  798. fEscaped);
  799. BAIL_ON_FAILURE(hr);
  800. break;
  801. case ADS_FORMAT_WINDOWS_DN:
  802. hr = SetComponents(szReturn,
  803. TRUE,
  804. TEXT("/"),
  805. ADS_COMPONENT_DN,
  806. fEscaped);
  807. BAIL_ON_FAILURE(hr);
  808. break;
  809. case ADS_FORMAT_WINDOWS_PARENT:
  810. hr = SetComponents(szReturn,
  811. TRUE,
  812. TEXT("/"),
  813. ADS_COMPONENT_PARENT,
  814. fEscaped);
  815. BAIL_ON_FAILURE(hr);
  816. break;
  817. case ADS_FORMAT_X500:
  818. case ADS_FORMAT_X500_NO_SERVER:
  819. case ADS_FORMAT_X500_DN:
  820. case ADS_FORMAT_X500_PARENT:
  821. hr = E_NOTIMPL;
  822. BAIL_ON_FAILURE(hr);
  823. break;
  824. case ADS_FORMAT_LEAF:
  825. //
  826. // Reverse only if pathtype is X500. In that case, we need to get
  827. // the first element but not the last
  828. //
  829. hr = SetComponents(szReturn,
  830. NULL,
  831. NULL,
  832. ADS_COMPONENT_LEAF,
  833. fEscaped);
  834. BAIL_ON_FAILURE(hr);
  835. break;
  836. default:
  837. hr = E_INVALIDARG;
  838. goto error;
  839. }
  840. hr = ADsAllocString(szReturn, pbstrADsPath);
  841. error:
  842. if (szReturn) {
  843. FreeADsMem(szReturn);
  844. }
  845. RRETURN_EXP_IF_ERR(hr);
  846. }
  847. STDMETHODIMP
  848. CNDSNamespace::GetEscapedElement(
  849. LONG lnReserved,
  850. BSTR bstrInStr,
  851. BSTR* pbstrOutStr
  852. )
  853. {
  854. RRETURN(E_NOTIMPL);
  855. }