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.

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