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.

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