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.

1406 lines
35 KiB

  1. /*++
  2. Copyright (c) 1998-1999 Microsoft Corporation
  3. Module Name:
  4. path.cxx
  5. Abstract:
  6. This file contains the PathCracker Functionality
  7. Environment:
  8. User mode
  9. Revision History:
  10. 12/07/98 -felixw-
  11. Created it
  12. --*/
  13. #include "oleds.hxx"
  14. #pragma hdrstop
  15. DEFINE_IDispatch_Implementation(CPathname)
  16. CPathname::CPathname():
  17. _pDispMgr(NULL),
  18. m_pPathnameProvider(NULL),
  19. _fNamingAttribute(TRUE),
  20. _dwEscaped(ADS_ESCAPEDMODE_DEFAULT)
  21. /*++
  22. Routine Description:
  23. Constructor for CPathname
  24. Arguments:
  25. Return Value:
  26. None
  27. --*/
  28. {
  29. ENLIST_TRACKING(CPathname);
  30. memset(&_PathObjectInfo,
  31. 0x0,
  32. sizeof(PATH_OBJECTINFO));
  33. _PathObjectInfo.dwPathType = ADS_PATHTYPE_ROOTFIRST;
  34. }
  35. HRESULT
  36. CPathname::CreatePathname(
  37. REFIID riid,
  38. void **ppvObj
  39. )
  40. /*++
  41. Routine Description:
  42. Create the pathname object
  43. Arguments:
  44. riid - IID to query for
  45. ppvObj - object to be returned
  46. Return Value:
  47. S_OK on success, error code otherwise
  48. --*/
  49. {
  50. CPathname * pPathname = NULL;
  51. HRESULT hr = S_OK;
  52. hr = AllocatePathnameObject(&pPathname);
  53. BAIL_ON_FAILURE(hr);
  54. hr = pPathname->QueryInterface(riid, ppvObj);
  55. BAIL_ON_FAILURE(hr);
  56. pPathname->Release();
  57. RRETURN(hr);
  58. error:
  59. delete pPathname;
  60. RRETURN(hr);
  61. }
  62. CPathname::~CPathname( )
  63. /*++
  64. Routine Description:
  65. Destructor for Pathname object
  66. Arguments:
  67. Return Value:
  68. None
  69. --*/
  70. {
  71. FreePathInfo(&_PathObjectInfo);
  72. delete _pDispMgr;
  73. if (m_pPathnameProvider) {
  74. m_pPathnameProvider->Release();
  75. }
  76. }
  77. STDMETHODIMP
  78. CPathname::QueryInterface(
  79. REFIID iid,
  80. LPVOID FAR* ppv
  81. )
  82. {
  83. if (ppv == NULL) {
  84. RRETURN(E_POINTER);
  85. }
  86. if (IsEqualIID(iid, IID_IUnknown))
  87. {
  88. *ppv = (IADsPathname *) this;
  89. }
  90. else if (IsEqualIID(iid, IID_IADsPathname))
  91. {
  92. *ppv = (IADsPathname *) this;
  93. }
  94. else if (IsEqualIID(iid, IID_IDispatch))
  95. {
  96. *ppv = (IADsPathname *) this;
  97. }
  98. else if (IsEqualIID(iid, IID_ISupportErrorInfo))
  99. {
  100. *ppv = (ISupportErrorInfo *) this;
  101. }
  102. else
  103. {
  104. *ppv = NULL;
  105. return E_NOINTERFACE;
  106. }
  107. AddRef();
  108. return NOERROR;
  109. }
  110. HRESULT
  111. CPathname::AllocatePathnameObject(
  112. CPathname ** ppPathname
  113. )
  114. /*++
  115. Routine Description:
  116. Allocate a pathname object
  117. Arguments:
  118. ppPathname - constructed object
  119. Return Value:
  120. S_OK on success, error code otherwise.
  121. --*/
  122. {
  123. CPathname * pPathname = NULL;
  124. CDispatchMgr * pDispMgr = NULL;
  125. HRESULT hr = S_OK;
  126. pPathname = new CPathname();
  127. if (pPathname == NULL) {
  128. hr = E_OUTOFMEMORY;
  129. }
  130. BAIL_ON_FAILURE(hr);
  131. pDispMgr = new CDispatchMgr;
  132. if (pDispMgr == NULL) {
  133. hr = E_OUTOFMEMORY;
  134. }
  135. BAIL_ON_FAILURE(hr);
  136. hr = LoadTypeInfoEntry(
  137. pDispMgr,
  138. LIBID_ADs,
  139. IID_IADsPathname,
  140. (IADsPathname *)pPathname,
  141. DISPID_REGULAR
  142. );
  143. BAIL_ON_FAILURE(hr);
  144. pPathname->_pDispMgr = pDispMgr;
  145. //
  146. // By default, the pathname is set to the LDAP provider
  147. //
  148. hr = ADsGetObject(L"LDAP:",
  149. IID_IADsPathnameProvider,
  150. (void**)&(pPathname->m_pPathnameProvider));
  151. BAIL_ON_FAILURE(hr);
  152. pPathname->_PathObjectInfo.ProviderName = AllocADsStr(L"LDAP");
  153. if (pPathname->_PathObjectInfo.ProviderName == NULL) {
  154. hr = E_OUTOFMEMORY;
  155. BAIL_ON_FAILURE(hr);
  156. }
  157. *ppPathname = pPathname;
  158. RRETURN(hr);
  159. error:
  160. delete pDispMgr;
  161. RRETURN_EXP_IF_ERR(hr);
  162. }
  163. HRESULT
  164. CPathname::InterfaceSupportsErrorInfo(
  165. THIS_ REFIID riid
  166. )
  167. {
  168. if (IsEqualIID(riid, IID_IADsPathname)) {
  169. RRETURN(S_OK);
  170. } else {
  171. RRETURN(S_FALSE);
  172. }
  173. }
  174. HRESULT
  175. CPathname::SetAll(
  176. BSTR bstrADsPath
  177. )
  178. /*++
  179. Routine Description:
  180. Set the internal variables using the full ADSPath
  181. Arguments:
  182. bstrADsPath - the passed in Full ADSPath
  183. Return Value:
  184. S_OK on success, error code otherwise.
  185. --*/
  186. {
  187. HRESULT hr = S_OK;
  188. //
  189. // Freeing existing info
  190. //
  191. FreePathInfo(&_PathObjectInfo);
  192. //
  193. // Collecting new info
  194. //
  195. hr = m_pPathnameProvider->ParsePath(
  196. bstrADsPath,
  197. ADS_PARSE_FULL,
  198. &_PathObjectInfo);
  199. BAIL_ON_FAILURE(hr);
  200. RRETURN(hr);
  201. error:
  202. FreePathInfo(&_PathObjectInfo);
  203. RRETURN(hr);
  204. }
  205. HRESULT
  206. CPathname::GetNamespace(
  207. BSTR bstrADsPath,
  208. PWSTR *ppszName
  209. )
  210. /*++
  211. Routine Description:
  212. Get a namespace from a full ADsPath
  213. Arguments:
  214. bstrADsPath - passed in ADsPath
  215. ppszName - returned namespace, must be freed by caller
  216. Return Value:
  217. S_OK on success, E_ADS_BAD_PATHNAME if the path is bad, error code
  218. otherwise.
  219. --*/
  220. {
  221. DWORD dwPath = 0; // Length of namespace
  222. BOOLEAN fFound = FALSE;
  223. PWSTR szPath = bstrADsPath;
  224. HRESULT hr = S_OK;
  225. while (*szPath) {
  226. if (*szPath == ':') {
  227. dwPath++;
  228. fFound = TRUE;
  229. break;
  230. }
  231. szPath++;
  232. dwPath++;
  233. }
  234. if (fFound) {
  235. *ppszName = (LPWSTR)AllocADsMem(sizeof(WCHAR) * (dwPath + 1));
  236. if (*ppszName == NULL) {
  237. hr = E_OUTOFMEMORY;
  238. goto error;
  239. }
  240. memcpy(*ppszName, bstrADsPath, (dwPath * sizeof(WCHAR)));
  241. (*ppszName)[dwPath] = '\0';
  242. }
  243. else {
  244. hr = E_ADS_BAD_PATHNAME;
  245. }
  246. error:
  247. return hr;
  248. }
  249. STDMETHODIMP
  250. CPathname::Set(
  251. BSTR bstrADsPath,
  252. long dwSetType
  253. )
  254. /*++
  255. Routine Description:
  256. Set the path with the type specified
  257. Arguments:
  258. bstrADsPath - the path to be set
  259. dwSetType - the type :
  260. ADS_SETTYPE_FULL
  261. ADS_SETTYPE_PROVIDER
  262. ADS_SETTYPE_SERVER
  263. ADS_SETTYPE_DN
  264. Return Value:
  265. S_OK on success, error code otherwise.
  266. --*/
  267. {
  268. HRESULT hr = E_FAIL;
  269. LPWSTR szPath = NULL;
  270. WCHAR szNamespace[MAX_PATH];
  271. LPWSTR pszName = NULL;
  272. IADsPathnameProvider *pPathnameProvider = NULL;
  273. switch (dwSetType) {
  274. case ADS_SETTYPE_FULL:
  275. if ((bstrADsPath == NULL) || ((*bstrADsPath) == NULL)) {
  276. hr = E_INVALIDARG;
  277. goto error;
  278. }
  279. hr = GetNamespace(bstrADsPath, &pszName);
  280. BAIL_ON_FAILURE(hr);
  281. if ((_PathObjectInfo.ProviderName == NULL) ||
  282. (wcscmp(_PathObjectInfo.ProviderName, bstrADsPath) != 0)) {
  283. //
  284. // If provider not set, or if the provider is different
  285. // we reset the provider
  286. //
  287. pPathnameProvider = NULL;
  288. hr = ADsGetObject(pszName,
  289. IID_IADsPathnameProvider,
  290. (void**)&(pPathnameProvider));
  291. BAIL_ON_FAILURE(hr);
  292. if (pPathnameProvider) {
  293. if (m_pPathnameProvider) {
  294. m_pPathnameProvider->Release();
  295. }
  296. m_pPathnameProvider = pPathnameProvider;
  297. }
  298. }
  299. hr = SetAll(bstrADsPath);
  300. break;
  301. case ADS_SETTYPE_PROVIDER:
  302. if ((bstrADsPath == NULL) || ((*bstrADsPath) == NULL)) {
  303. hr = E_INVALIDARG;
  304. goto error;
  305. }
  306. //
  307. // If it is the same as the namespace that is stored inside already,
  308. // ignore it
  309. //
  310. if (_PathObjectInfo.ProviderName &&
  311. (wcscmp(_PathObjectInfo.ProviderName, bstrADsPath) == 0)) {
  312. hr = S_OK;
  313. break;
  314. }
  315. wcscpy(szNamespace,bstrADsPath);
  316. wcscat(szNamespace,L":");
  317. pPathnameProvider = NULL;
  318. hr = ADsGetObject(szNamespace,
  319. IID_IADsPathnameProvider,
  320. (void**)&(pPathnameProvider));
  321. BAIL_ON_FAILURE(hr);
  322. if (pPathnameProvider) {
  323. if (m_pPathnameProvider) {
  324. m_pPathnameProvider->Release();
  325. }
  326. m_pPathnameProvider = pPathnameProvider;
  327. }
  328. FreePathInfo(&_PathObjectInfo);
  329. _PathObjectInfo.ProviderName = AllocADsStr(bstrADsPath);
  330. if (_PathObjectInfo.ProviderName == NULL) {
  331. hr = E_OUTOFMEMORY;
  332. break;
  333. }
  334. hr = S_OK;
  335. break;
  336. case ADS_SETTYPE_SERVER:
  337. if (m_pPathnameProvider == NULL) {
  338. hr = E_ADS_BAD_PATHNAME;
  339. goto error;
  340. }
  341. if (_PathObjectInfo.ServerName) {
  342. FreeADsStr( _PathObjectInfo.ServerName);
  343. _PathObjectInfo.ServerName = NULL;
  344. }
  345. if (_PathObjectInfo.DisplayServerName) {
  346. FreeADsStr( _PathObjectInfo.DisplayServerName);
  347. _PathObjectInfo.DisplayServerName = NULL;
  348. }
  349. //
  350. // If the input path is not NULL, we'll set it to the new one. Or
  351. // else we will just ignore it 'cause it has been set to 0 earlier
  352. //
  353. if (bstrADsPath && (*bstrADsPath)) {
  354. _PathObjectInfo.ServerName = AllocADsStr(bstrADsPath);
  355. if (_PathObjectInfo.ServerName == NULL) {
  356. hr = E_OUTOFMEMORY;
  357. break;
  358. }
  359. _PathObjectInfo.DisplayServerName = AllocADsStr(bstrADsPath);
  360. if (_PathObjectInfo.DisplayServerName == NULL) {
  361. hr = E_OUTOFMEMORY;
  362. break;
  363. }
  364. }
  365. hr = S_OK;
  366. break;
  367. case ADS_SETTYPE_DN:
  368. {
  369. if (m_pPathnameProvider == NULL) {
  370. hr = E_ADS_BAD_PATHNAME;
  371. goto error;
  372. }
  373. //
  374. // Free the existing ones first
  375. //
  376. FreeObjInfoComponents(&_PathObjectInfo);
  377. _PathObjectInfo.dwPathType = 0;
  378. //
  379. // If the input path is not NULL, we'll set it to the new one.
  380. // Or else we will just ignore it 'cause it has been set to 0
  381. // earlier
  382. //
  383. if (bstrADsPath && (*bstrADsPath)) {
  384. hr = m_pPathnameProvider->ParsePath(
  385. bstrADsPath,
  386. ADS_PARSE_DN,
  387. &_PathObjectInfo);
  388. BAIL_ON_FAILURE(hr);
  389. }
  390. break;
  391. }
  392. default:
  393. hr = E_INVALIDARG;
  394. break;
  395. }
  396. error:
  397. if (pszName) {
  398. FreeADsStr(pszName);
  399. }
  400. RRETURN_EXP_IF_ERR(hr);
  401. }
  402. STDMETHODIMP
  403. CPathname::SetDisplayType(
  404. long lnSetType
  405. )
  406. /*++
  407. Routine Description:
  408. Set the Display type of the Pathname object. It can either display the whole
  409. string cn=xxx or just the value xxx.
  410. Arguments:
  411. lnSetType - the passed in set type
  412. ADS_DISPLAY_FULL=1,
  413. ADS_DISPLAY_VALUE_ONLY=2
  414. Return Value:
  415. S_OK on success, error code otherwise.
  416. --*/
  417. {
  418. if (lnSetType == ADS_DISPLAY_FULL) {
  419. _fNamingAttribute = TRUE;
  420. RRETURN (S_OK);
  421. }
  422. else if (lnSetType == ADS_DISPLAY_VALUE_ONLY) {
  423. _fNamingAttribute = FALSE;
  424. RRETURN (S_OK);
  425. }
  426. RRETURN(E_INVALIDARG);
  427. }
  428. HRESULT CPathname::SetComponent(
  429. DWORD cComponents,
  430. BSTR *pbstrElement
  431. )
  432. /*++
  433. Routine Description:
  434. Set an individual component in the pathname. For internal use only.
  435. Not exposed.
  436. Arguments:
  437. cComponents - the component number to be set
  438. pbstrElement - the return value
  439. Return Value:
  440. S_OK on success, error code otherwise.
  441. --*/
  442. {
  443. HRESULT hr = S_OK;
  444. PWSTR szReturn = NULL;
  445. PATH_COMPONENT* pComponent = NULL;
  446. DWORD dwLength = 2; // for null termination and the equal sign
  447. if (_dwEscaped == ADS_ESCAPEDMODE_OFF_EX) {
  448. pComponent = _PathObjectInfo.ProvSpecComponentArray;
  449. if (pComponent[cComponents].szValue == NULL) {
  450. pComponent = _PathObjectInfo.ComponentArray;
  451. }
  452. }
  453. else if (_dwEscaped == ADS_ESCAPEDMODE_ON) {
  454. pComponent = _PathObjectInfo.DisplayComponentArray;
  455. }
  456. //
  457. // Either default or OFF, we do not turn on escaping
  458. //
  459. else {
  460. pComponent = _PathObjectInfo.ComponentArray;
  461. }
  462. //
  463. // allocate space for szReturn
  464. //
  465. if (pComponent[cComponents].szValue) {
  466. dwLength += wcslen(pComponent[cComponents].szValue);
  467. }
  468. if (pComponent[cComponents].szComponent) {
  469. dwLength += wcslen(pComponent[cComponents].szComponent);
  470. }
  471. szReturn = (PWSTR)AllocADsMem(sizeof(WCHAR) * dwLength);
  472. if (szReturn == NULL) {
  473. hr = E_OUTOFMEMORY;
  474. goto error;
  475. }
  476. szReturn[0] = NULL;
  477. if (_fNamingAttribute) {
  478. wcscat(szReturn, pComponent[cComponents].szComponent);
  479. if (pComponent[cComponents].szValue) {
  480. wcscat(szReturn,
  481. TEXT("="));
  482. wcscat(szReturn,
  483. pComponent[cComponents].szValue);
  484. }
  485. }
  486. else {
  487. if (pComponent[cComponents].szValue) {
  488. //
  489. // If value exist, only show display value
  490. //
  491. wcscat(szReturn,
  492. pComponent[cComponents].szValue);
  493. }
  494. else {
  495. //
  496. // else value is only stored in Component
  497. //
  498. wcscat(szReturn,
  499. pComponent[cComponents].szComponent);
  500. }
  501. }
  502. hr = ADsAllocString(szReturn, pbstrElement);
  503. error:
  504. if (szReturn) {
  505. FreeADsMem(szReturn);
  506. }
  507. return hr;
  508. }
  509. STDMETHODIMP
  510. CPathname::Retrieve(
  511. THIS_ long dwFormatType,
  512. BSTR *pbstrADsPath
  513. )
  514. /*++
  515. Routine Description:
  516. Retrive the pathname as different formats
  517. Arguments:
  518. dwFormatType - the input format type
  519. pbstrADsPath - the returned path
  520. Return Value:
  521. S_OK on success, error code otherwise.
  522. --*/
  523. {
  524. HRESULT hr = S_OK;
  525. if (!pbstrADsPath) {
  526. hr = E_INVALIDARG;
  527. goto error;
  528. }
  529. if (m_pPathnameProvider == NULL) {
  530. hr = E_ADS_BAD_PATHNAME;
  531. goto error;
  532. }
  533. switch (dwFormatType) {
  534. case ADS_FORMAT_SERVER:
  535. if (!_PathObjectInfo.DisplayServerName) {
  536. hr = E_ADS_BAD_PATHNAME;
  537. goto error;
  538. }
  539. hr = ADsAllocString(_PathObjectInfo.DisplayServerName, pbstrADsPath);
  540. break;
  541. case ADS_FORMAT_PROVIDER:
  542. if (!_PathObjectInfo.ProviderName) {
  543. hr = E_ADS_BAD_PATHNAME;
  544. goto error;
  545. }
  546. hr = ADsAllocString(_PathObjectInfo.ProviderName, pbstrADsPath);
  547. break;
  548. default:
  549. //
  550. DWORD dwFlag = 0;
  551. if (_fNamingAttribute)
  552. dwFlag |= ADS_CONSTRUCT_NAMINGATTRIBUTE;
  553. hr = m_pPathnameProvider->ConstructPath(&_PathObjectInfo,
  554. dwFormatType,
  555. dwFlag,
  556. _dwEscaped,
  557. pbstrADsPath);
  558. BAIL_ON_FAILURE(hr);
  559. }
  560. error:
  561. RRETURN_EXP_IF_ERR(hr);
  562. }
  563. STDMETHODIMP
  564. CPathname::GetNumElements(
  565. THIS_ long *pdwNumPathElements
  566. )
  567. /*++
  568. Routine Description:
  569. Get the number of elements in the DN
  570. Arguments:
  571. pdwNumPathElements - the number of elements
  572. Return Value:
  573. S_OK on success, error code otherwise.
  574. --*/
  575. {
  576. HRESULT hr = S_OK;
  577. if (m_pPathnameProvider == NULL) {
  578. hr = E_ADS_BAD_PATHNAME;
  579. goto error;
  580. }
  581. if (!pdwNumPathElements) {
  582. hr = E_INVALIDARG;
  583. goto error;
  584. }
  585. *pdwNumPathElements = _PathObjectInfo.NumComponents;
  586. error:
  587. RRETURN_EXP_IF_ERR(hr);
  588. }
  589. STDMETHODIMP
  590. CPathname::GetElement(
  591. THIS_ long dwElementIndex,
  592. BSTR *pbstrElement
  593. )
  594. /*++
  595. Routine Description:
  596. Get a particular element using an index
  597. Arguments:
  598. Return Value:
  599. S_OK on success, error code otherwise.
  600. --*/
  601. {
  602. HRESULT hr = E_FAIL;
  603. if (m_pPathnameProvider == NULL) {
  604. hr = E_ADS_BAD_PATHNAME;
  605. goto error;
  606. }
  607. if (!pbstrElement) {
  608. hr = E_INVALIDARG;
  609. goto error;
  610. }
  611. if ((DWORD)dwElementIndex >= _PathObjectInfo.NumComponents) {
  612. hr = HRESULT_FROM_WIN32(ERROR_INVALID_INDEX);
  613. goto error;
  614. }
  615. if (_PathObjectInfo.dwPathType != ADS_PATHTYPE_LEAFFIRST) {
  616. dwElementIndex = _PathObjectInfo.NumComponents - 1 - dwElementIndex;
  617. }
  618. hr = SetComponent(dwElementIndex,
  619. pbstrElement);
  620. error:
  621. RRETURN_EXP_IF_ERR(hr);
  622. }
  623. VOID MoveLastComponentToFront(
  624. PPATH_OBJECTINFO pObjectInfo
  625. )
  626. /*++
  627. Routine Description:
  628. Move the last component to the front. Used after adding leaf
  629. Arguments:
  630. Return Value:
  631. S_OK on success, error code otherwise.
  632. --*/
  633. {
  634. DWORD cComponent;
  635. ADsAssert(pObjectInfo->NumComponents > 1);
  636. LPTSTR szComponentLast =
  637. pObjectInfo->ComponentArray[pObjectInfo->NumComponents-1].szComponent;
  638. LPTSTR szValueLast =
  639. pObjectInfo->ComponentArray[pObjectInfo->NumComponents-1].szValue;
  640. LPTSTR szDisplayComponentLast =
  641. pObjectInfo->DisplayComponentArray[pObjectInfo->NumComponents-1].szComponent;
  642. LPTSTR szDisplayValueLast =
  643. pObjectInfo->DisplayComponentArray[pObjectInfo->NumComponents-1].szValue;
  644. LPTSTR szProvSpecComponentLast =
  645. pObjectInfo->ProvSpecComponentArray[pObjectInfo->NumComponents-1].szComponent;
  646. LPTSTR szProvSpecValueLast =
  647. pObjectInfo->ProvSpecComponentArray[pObjectInfo->NumComponents-1].szValue;
  648. for (cComponent=pObjectInfo->NumComponents-1;cComponent>=1;cComponent--) {
  649. pObjectInfo->ComponentArray[cComponent].szComponent =
  650. pObjectInfo->ComponentArray[cComponent-1].szComponent;
  651. pObjectInfo->ComponentArray[cComponent].szValue =
  652. pObjectInfo->ComponentArray[cComponent-1].szValue;
  653. pObjectInfo->DisplayComponentArray[cComponent].szComponent =
  654. pObjectInfo->DisplayComponentArray[cComponent-1].szComponent;
  655. pObjectInfo->DisplayComponentArray[cComponent].szValue =
  656. pObjectInfo->DisplayComponentArray[cComponent-1].szValue;
  657. pObjectInfo->ProvSpecComponentArray[cComponent].szComponent =
  658. pObjectInfo->ProvSpecComponentArray[cComponent-1].szComponent;
  659. pObjectInfo->ProvSpecComponentArray[cComponent].szValue =
  660. pObjectInfo->ProvSpecComponentArray[cComponent-1].szValue;
  661. }
  662. pObjectInfo->ComponentArray[0].szComponent = szComponentLast;
  663. pObjectInfo->ComponentArray[0].szValue = szValueLast;
  664. pObjectInfo->DisplayComponentArray[0].szComponent = szDisplayComponentLast;
  665. pObjectInfo->DisplayComponentArray[0].szValue = szDisplayValueLast;
  666. pObjectInfo->ProvSpecComponentArray[0].szComponent = szProvSpecComponentLast;
  667. pObjectInfo->ProvSpecComponentArray[0].szValue = szProvSpecValueLast;
  668. return;
  669. }
  670. HRESULT
  671. RemoveFirstElement(
  672. PPATH_OBJECTINFO pObjectInfo
  673. )
  674. /*++
  675. Routine Description:
  676. Remove first element from the list
  677. Arguments:
  678. Return Value:
  679. S_OK on success, error code otherwise.
  680. --*/
  681. {
  682. DWORD cComponent;
  683. if (pObjectInfo->NumComponents <= 0) {
  684. RRETURN(E_ADS_BAD_PATHNAME);
  685. }
  686. FreeADsStr(pObjectInfo->ComponentArray[0].szComponent);
  687. FreeADsStr(pObjectInfo->ComponentArray[0].szValue);
  688. FreeADsStr(pObjectInfo->DisplayComponentArray[0].szComponent);
  689. FreeADsStr(pObjectInfo->DisplayComponentArray[0].szValue);
  690. if (pObjectInfo->ProvSpecComponentArray[0].szComponent)
  691. FreeADsStr(pObjectInfo->ProvSpecComponentArray[0].szComponent);
  692. if (pObjectInfo->ProvSpecComponentArray[0].szValue)
  693. FreeADsStr(pObjectInfo->ProvSpecComponentArray[0].szValue);
  694. for (cComponent = 0;cComponent < pObjectInfo->NumComponents - 1;cComponent++) {
  695. pObjectInfo->ComponentArray[cComponent].szComponent =
  696. pObjectInfo->ComponentArray[cComponent+1].szComponent;
  697. pObjectInfo->ComponentArray[cComponent].szValue =
  698. pObjectInfo->ComponentArray[cComponent+1].szValue;
  699. pObjectInfo->DisplayComponentArray[cComponent].szComponent =
  700. pObjectInfo->DisplayComponentArray[cComponent+1].szComponent;
  701. pObjectInfo->DisplayComponentArray[cComponent].szValue =
  702. pObjectInfo->DisplayComponentArray[cComponent+1].szValue;
  703. pObjectInfo->ProvSpecComponentArray[cComponent].szComponent =
  704. pObjectInfo->ProvSpecComponentArray[cComponent+1].szComponent;
  705. pObjectInfo->ProvSpecComponentArray[cComponent].szValue =
  706. pObjectInfo->ProvSpecComponentArray[cComponent+1].szValue;
  707. }
  708. pObjectInfo->ComponentArray[cComponent].szComponent = NULL;
  709. pObjectInfo->ComponentArray[cComponent].szValue = NULL;
  710. pObjectInfo->DisplayComponentArray[cComponent].szComponent = NULL;
  711. pObjectInfo->DisplayComponentArray[cComponent].szValue = NULL;
  712. pObjectInfo->ProvSpecComponentArray[cComponent].szComponent = NULL;
  713. pObjectInfo->ProvSpecComponentArray[cComponent].szValue = NULL;
  714. pObjectInfo->NumComponents--;
  715. RRETURN(S_OK);
  716. }
  717. STDMETHODIMP
  718. CPathname::AddLeafElement(
  719. THIS_ BSTR bstrLeafElement
  720. )
  721. /*++
  722. Routine Description:
  723. Add a leaf element to the DN
  724. Arguments:
  725. Return Value:
  726. S_OK on success, error code otherwise.
  727. --*/
  728. {
  729. HRESULT hr = E_FAIL;
  730. DWORD NumComponents;
  731. BOOL fStartAllocation = FALSE;
  732. PATH_OBJECTINFO ObjectInfoLocal;
  733. memset(&ObjectInfoLocal, 0, sizeof(PATH_OBJECTINFO));
  734. if ((bstrLeafElement == NULL) || ((*bstrLeafElement) == NULL)) {
  735. hr = E_INVALIDARG;
  736. goto error;
  737. }
  738. if (m_pPathnameProvider == NULL) {
  739. hr = E_ADS_BAD_PATHNAME;
  740. goto error;
  741. }
  742. //
  743. // MAX size limitation exist in parser.cxx, so, it's not
  744. // worth to implement the inc in size dynamically
  745. //
  746. if ((_PathObjectInfo.NumComponents+1) > MAXCOMPONENTS ) {
  747. hr = E_NOTIMPL;
  748. goto error;
  749. }
  750. hr = m_pPathnameProvider->ParsePath(
  751. bstrLeafElement,
  752. ADS_PARSE_COMPONENT,
  753. (PPATH_OBJECTINFO)&ObjectInfoLocal
  754. );
  755. BAIL_ON_FAILURE(hr);
  756. NumComponents = _PathObjectInfo.NumComponents;
  757. fStartAllocation = TRUE;
  758. if (ObjectInfoLocal.ComponentArray[0].szComponent) {
  759. _PathObjectInfo.ComponentArray[NumComponents].szComponent =
  760. AllocADsStr(ObjectInfoLocal.ComponentArray[0].szComponent);
  761. if (_PathObjectInfo.ComponentArray[NumComponents].szComponent == NULL) {
  762. hr = E_OUTOFMEMORY;
  763. BAIL_ON_FAILURE(hr);
  764. }
  765. }
  766. if (ObjectInfoLocal.ComponentArray[0].szValue) {
  767. _PathObjectInfo.ComponentArray[NumComponents].szValue =
  768. AllocADsStr(ObjectInfoLocal.ComponentArray[0].szValue);
  769. if (_PathObjectInfo.ComponentArray[NumComponents].szValue== NULL) {
  770. hr = E_OUTOFMEMORY;
  771. BAIL_ON_FAILURE(hr);
  772. }
  773. }
  774. if (ObjectInfoLocal.DisplayComponentArray[0].szComponent) {
  775. _PathObjectInfo.DisplayComponentArray[NumComponents].szComponent =
  776. AllocADsStr(ObjectInfoLocal.DisplayComponentArray[0].szComponent);
  777. if (_PathObjectInfo.DisplayComponentArray[NumComponents].szComponent == NULL) {
  778. hr = E_OUTOFMEMORY;
  779. BAIL_ON_FAILURE(hr);
  780. }
  781. }
  782. if (ObjectInfoLocal.DisplayComponentArray[0].szValue) {
  783. _PathObjectInfo.DisplayComponentArray[NumComponents].szValue=
  784. AllocADsStr(ObjectInfoLocal.DisplayComponentArray[0].szValue);
  785. if (_PathObjectInfo.DisplayComponentArray[NumComponents].szValue== NULL) {
  786. hr = E_OUTOFMEMORY;
  787. BAIL_ON_FAILURE(hr);
  788. }
  789. }
  790. if (ObjectInfoLocal.ProvSpecComponentArray[0].szComponent) {
  791. _PathObjectInfo.ProvSpecComponentArray[NumComponents].szComponent =
  792. AllocADsStr(ObjectInfoLocal.ProvSpecComponentArray[0].szComponent);
  793. if (_PathObjectInfo.ProvSpecComponentArray[NumComponents].szComponent == NULL) {
  794. hr = E_OUTOFMEMORY;
  795. BAIL_ON_FAILURE(hr);
  796. }
  797. }
  798. if (ObjectInfoLocal.ProvSpecComponentArray[0].szValue) {
  799. _PathObjectInfo.ProvSpecComponentArray[NumComponents].szValue =
  800. AllocADsStr(ObjectInfoLocal.ProvSpecComponentArray[0].szValue);
  801. if (_PathObjectInfo.ProvSpecComponentArray[NumComponents].szValue== NULL) {
  802. hr = E_OUTOFMEMORY;
  803. BAIL_ON_FAILURE(hr);
  804. }
  805. }
  806. _PathObjectInfo.NumComponents++;
  807. if (_PathObjectInfo.dwPathType == ADS_PATHTYPE_LEAFFIRST) {
  808. MoveLastComponentToFront(&_PathObjectInfo);
  809. }
  810. FreePathInfo(&ObjectInfoLocal);
  811. RRETURN(hr);
  812. error:
  813. FreePathInfo(&ObjectInfoLocal);
  814. if (fStartAllocation) {
  815. if (_PathObjectInfo.ComponentArray[NumComponents].szComponent) {
  816. FreeADsStr(_PathObjectInfo.ComponentArray[NumComponents].szComponent);
  817. _PathObjectInfo.ComponentArray[NumComponents].szComponent = NULL;
  818. }
  819. if (_PathObjectInfo.ComponentArray[NumComponents].szValue) {
  820. FreeADsStr(_PathObjectInfo.ComponentArray[NumComponents].szValue);
  821. _PathObjectInfo.ComponentArray[NumComponents].szValue = NULL;
  822. }
  823. if (_PathObjectInfo.DisplayComponentArray[NumComponents].szComponent) {
  824. FreeADsStr(_PathObjectInfo.DisplayComponentArray[NumComponents].szComponent);
  825. _PathObjectInfo.DisplayComponentArray[NumComponents].szComponent = NULL;
  826. }
  827. if (_PathObjectInfo.DisplayComponentArray[NumComponents].szValue) {
  828. FreeADsStr(_PathObjectInfo.DisplayComponentArray[NumComponents].szValue);
  829. _PathObjectInfo.DisplayComponentArray[NumComponents].szValue = NULL;
  830. }
  831. if (_PathObjectInfo.ProvSpecComponentArray[NumComponents].szComponent) {
  832. FreeADsStr(_PathObjectInfo.ProvSpecComponentArray[NumComponents].szComponent);
  833. _PathObjectInfo.ProvSpecComponentArray[NumComponents].szComponent = NULL;
  834. }
  835. if (_PathObjectInfo.ProvSpecComponentArray[NumComponents].szValue) {
  836. FreeADsStr(_PathObjectInfo.ProvSpecComponentArray[NumComponents].szValue);
  837. _PathObjectInfo.ProvSpecComponentArray[NumComponents].szValue = NULL;
  838. }
  839. }
  840. RRETURN_EXP_IF_ERR(hr);
  841. }
  842. STDMETHODIMP
  843. CPathname::RemoveLeafElement(void)
  844. /*++
  845. Routine Description:
  846. Remove the leaf element from the DN
  847. Arguments:
  848. Return Value:
  849. S_OK on success, error code otherwise.
  850. --*/
  851. {
  852. HRESULT hr = E_FAIL;
  853. DWORD NumComponents;
  854. if (m_pPathnameProvider == NULL) {
  855. hr = E_ADS_BAD_PATHNAME;
  856. goto error;
  857. }
  858. if (_PathObjectInfo.dwPathType == ADS_PATHTYPE_LEAFFIRST) {
  859. hr = RemoveFirstElement(&_PathObjectInfo);
  860. }
  861. else {
  862. if (_PathObjectInfo.NumComponents > 0) {
  863. _PathObjectInfo.NumComponents--;
  864. NumComponents = _PathObjectInfo.NumComponents;
  865. FreeADsStr(_PathObjectInfo.ComponentArray[NumComponents].szComponent);
  866. FreeADsStr(_PathObjectInfo.ComponentArray[NumComponents].szValue);
  867. FreeADsStr(_PathObjectInfo.DisplayComponentArray[NumComponents].szComponent);
  868. FreeADsStr(_PathObjectInfo.DisplayComponentArray[NumComponents].szValue);
  869. if (_PathObjectInfo.ProvSpecComponentArray[NumComponents].szComponent)
  870. FreeADsStr(_PathObjectInfo.ProvSpecComponentArray[NumComponents].szComponent);
  871. if (_PathObjectInfo.ProvSpecComponentArray[NumComponents].szValue)
  872. FreeADsStr(_PathObjectInfo.ProvSpecComponentArray[NumComponents].szValue);
  873. _PathObjectInfo.ComponentArray[NumComponents].szComponent = NULL;
  874. _PathObjectInfo.ComponentArray[NumComponents].szValue = NULL;
  875. _PathObjectInfo.DisplayComponentArray[NumComponents].szComponent = NULL;
  876. _PathObjectInfo.DisplayComponentArray[NumComponents].szValue = NULL;
  877. _PathObjectInfo.ProvSpecComponentArray[NumComponents].szComponent = NULL;
  878. _PathObjectInfo.ProvSpecComponentArray[NumComponents].szValue = NULL;
  879. hr = S_OK;
  880. }
  881. }
  882. error:
  883. RRETURN_EXP_IF_ERR(hr);
  884. }
  885. STDMETHODIMP
  886. CPathname::CopyPath(THIS_ IDispatch **ppAdsPath)
  887. /*++
  888. Routine Description:
  889. Copy the pathname object and return a pointer to the new one
  890. Arguments:
  891. Return Value:
  892. S_OK on success, error code otherwise.
  893. --*/
  894. {
  895. HRESULT hr = E_FAIL;
  896. IADsPathname *pPathname = NULL;
  897. BSTR bstrResult = NULL;
  898. DWORD dwLength;
  899. long lNameType; // Storage for old values
  900. DWORD dwEscaped;
  901. BOOL fValueChanged = FALSE; // indicate whether value has been changed
  902. if (m_pPathnameProvider == NULL) {
  903. hr = E_ADS_BAD_PATHNAME;
  904. goto error;
  905. }
  906. if (!ppAdsPath) {
  907. hr = E_INVALIDARG;
  908. goto error;
  909. }
  910. //
  911. // Storing the old values
  912. //
  913. dwEscaped = _dwEscaped;
  914. if (_fNamingAttribute) {
  915. lNameType = ADS_DISPLAY_FULL;
  916. }
  917. else {
  918. lNameType = ADS_DISPLAY_VALUE_ONLY;
  919. }
  920. //
  921. // Setting the type to 'show all' for retrieval
  922. //
  923. fValueChanged = TRUE;
  924. hr = SetDisplayType(ADS_DISPLAY_FULL);
  925. BAIL_ON_FAILURE(hr);
  926. hr = put_EscapedMode(ADS_ESCAPEDMODE_DEFAULT);
  927. BAIL_ON_FAILURE(hr);
  928. //
  929. // Retrieve path
  930. //
  931. hr = Retrieve(ADS_FORMAT_WINDOWS, &bstrResult);
  932. BAIL_ON_FAILURE(hr);
  933. //
  934. // This is a workaround for the namespace path that we return. We are
  935. // currently getting 'LDAP://' back instead of 'LDAP:'. There are users who
  936. // are dependent on this and thus we cannot change it to return 'LDAP://'.
  937. // The code below takes out the '//' if the path trails with '://' so that
  938. // the path is settable.
  939. //
  940. dwLength = wcslen(bstrResult);
  941. if (wcscmp((PWSTR)(&bstrResult[dwLength-3]),L"://") == 0) {
  942. bstrResult[dwLength-2] = NULL;
  943. }
  944. hr = CoCreateInstance(
  945. CLSID_Pathname,
  946. NULL,
  947. CLSCTX_ALL,
  948. IID_IADsPathname,
  949. (void**)&pPathname
  950. );
  951. BAIL_ON_FAILURE(hr);
  952. hr = pPathname->Set(bstrResult, ADS_SETTYPE_FULL);
  953. BAIL_ON_FAILURE(hr);
  954. hr = pPathname->SetDisplayType(lNameType);
  955. BAIL_ON_FAILURE(hr);
  956. hr = pPathname->put_EscapedMode(dwEscaped);
  957. BAIL_ON_FAILURE(hr);
  958. *ppAdsPath = (IDispatch*)pPathname;
  959. pPathname = NULL;
  960. error:
  961. if (fValueChanged) {
  962. SetDisplayType(lNameType);
  963. put_EscapedMode(dwEscaped);
  964. }
  965. if (pPathname) {
  966. pPathname->Release();
  967. }
  968. if (bstrResult) {
  969. SysFreeString(bstrResult);
  970. }
  971. RRETURN_EXP_IF_ERR(hr);
  972. }
  973. void
  974. CPathname::FreeObjInfoComponents(
  975. PATH_OBJECTINFO *pObjectInfo
  976. )
  977. /*++
  978. Routine Description:
  979. Free all the compoents in an objinfo
  980. Arguments:
  981. Return Value:
  982. S_OK on success, error code otherwise.
  983. --*/
  984. {
  985. DWORD NumComponents;
  986. while (pObjectInfo->NumComponents > 0) {
  987. pObjectInfo->NumComponents--;
  988. NumComponents = pObjectInfo->NumComponents;
  989. if (pObjectInfo->ComponentArray[NumComponents].szComponent) {
  990. FreeADsStr(
  991. pObjectInfo->ComponentArray[NumComponents].szComponent);
  992. pObjectInfo->ComponentArray[NumComponents].szComponent = NULL;
  993. }
  994. if (pObjectInfo->ComponentArray[NumComponents].szValue) {
  995. FreeADsStr(
  996. pObjectInfo->ComponentArray[NumComponents].szValue);
  997. pObjectInfo->ComponentArray[NumComponents].szValue = NULL;
  998. }
  999. if (pObjectInfo->DisplayComponentArray[NumComponents].szComponent) {
  1000. FreeADsStr(
  1001. pObjectInfo->DisplayComponentArray[NumComponents].szComponent);
  1002. pObjectInfo->DisplayComponentArray[NumComponents].szComponent = NULL;
  1003. }
  1004. if (pObjectInfo->DisplayComponentArray[NumComponents].szValue) {
  1005. FreeADsStr(
  1006. pObjectInfo->DisplayComponentArray[NumComponents].szValue);
  1007. pObjectInfo->DisplayComponentArray[NumComponents].szValue = NULL;
  1008. }
  1009. if (pObjectInfo->ProvSpecComponentArray[NumComponents].szComponent) {
  1010. FreeADsStr(
  1011. pObjectInfo->ProvSpecComponentArray[NumComponents].szComponent);
  1012. pObjectInfo->ProvSpecComponentArray[NumComponents].szComponent = NULL;
  1013. }
  1014. if (pObjectInfo->ProvSpecComponentArray[NumComponents].szValue) {
  1015. FreeADsStr(
  1016. pObjectInfo->ProvSpecComponentArray[NumComponents].szValue);
  1017. pObjectInfo->ProvSpecComponentArray[NumComponents].szValue = NULL;
  1018. }
  1019. }
  1020. }
  1021. void
  1022. CPathname::FreePathInfo(
  1023. PPATH_OBJECTINFO pPathObjectInfo
  1024. )
  1025. {
  1026. if (pPathObjectInfo->ProviderName) {
  1027. FreeADsStr(pPathObjectInfo->ProviderName);
  1028. pPathObjectInfo->ProviderName = NULL;
  1029. }
  1030. if (pPathObjectInfo->ServerName) {
  1031. FreeADsStr(pPathObjectInfo->ServerName);
  1032. pPathObjectInfo->ServerName = NULL;
  1033. }
  1034. if (pPathObjectInfo->DisplayServerName) {
  1035. FreeADsStr(pPathObjectInfo->DisplayServerName);
  1036. pPathObjectInfo->DisplayServerName = NULL;
  1037. }
  1038. FreeObjInfoComponents(pPathObjectInfo);
  1039. pPathObjectInfo->dwPathType = ADS_PATHTYPE_ROOTFIRST;
  1040. }
  1041. HRESULT
  1042. CPathname::put_EscapedMode(
  1043. long lEscaped
  1044. )
  1045. {
  1046. _dwEscaped = lEscaped;
  1047. return S_OK;
  1048. }
  1049. HRESULT
  1050. CPathname::get_EscapedMode(
  1051. long *plEscaped
  1052. )
  1053. {
  1054. *plEscaped = _dwEscaped;
  1055. return S_OK;
  1056. }
  1057. //+---------------------------------------------------------------------------
  1058. // Function: CPathname::GetEscapedElement
  1059. //
  1060. // Synopsis: Takes the input string, escapes it assuming it is an RDN
  1061. // and returns the output.
  1062. // The first cut will be empty as in input string = output
  1063. // string. Once the code to do this is added please change this
  1064. // comment appropriately.
  1065. //
  1066. // Arguments: lnReserved (= 0 for now),
  1067. //
  1068. //
  1069. // Returns: HRESULT
  1070. //
  1071. // Modifies: -
  1072. //
  1073. // History: 11-10-98 AjayR Created.
  1074. //
  1075. //----------------------------------------------------------------------------
  1076. STDMETHODIMP
  1077. CPathname::GetEscapedElement(
  1078. LONG lnReserved,
  1079. BSTR bstrInStr,
  1080. BSTR* pbstrOutStr
  1081. )
  1082. {
  1083. HRESULT hr = S_OK;
  1084. if (m_pPathnameProvider == NULL) {
  1085. hr = E_ADS_BAD_PATHNAME;
  1086. goto error;
  1087. }
  1088. hr = m_pPathnameProvider->GetEscapedElement(lnReserved,
  1089. bstrInStr,
  1090. pbstrOutStr);
  1091. error:
  1092. return hr;
  1093. }