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.

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