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.

1328 lines
34 KiB

  1. //---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1996
  5. //
  6. // File: cnamesp.cxx
  7. //
  8. // Contents: LDAP Namespace Object
  9. //
  10. //
  11. // History: 06-15-96 yihsins Created.
  12. //
  13. //----------------------------------------------------------------------------
  14. #include "LDAP.hxx"
  15. #pragma hdrstop
  16. #include <ntdsapi.h>
  17. DEFINE_IDispatch_Implementation(CLDAPNamespace)
  18. DEFINE_IADs_Implementation(CLDAPNamespace)
  19. DEFINE_IADsPutGet_UnImplementation(CLDAPNamespace)
  20. // Class CLDAPNamespace
  21. CLDAPNamespace::CLDAPNamespace()
  22. {
  23. VariantInit(&_vFilter);
  24. ENLIST_TRACKING(CLDAPNamespace);
  25. _pObjectInfo = NULL;
  26. }
  27. HRESULT
  28. CLDAPNamespace::CreateNamespace(
  29. BSTR Parent,
  30. BSTR NamespaceName,
  31. CCredentials& Credentials,
  32. DWORD dwObjectState,
  33. REFIID riid,
  34. void **ppvObj
  35. )
  36. {
  37. CLDAPNamespace FAR * pNamespace = NULL;
  38. HRESULT hr = S_OK;
  39. hr = AllocateNamespaceObject(
  40. Credentials,
  41. &pNamespace
  42. );
  43. BAIL_ON_FAILURE(hr);
  44. hr = pNamespace->InitializeCoreObject(
  45. Parent,
  46. NamespaceName,
  47. NAMESPACE_CLASS_NAME,
  48. CLSID_LDAPNamespace,
  49. dwObjectState
  50. );
  51. BAIL_ON_FAILURE(hr);
  52. if (Credentials.GetAuthFlags() & ADS_AUTH_RESERVED) {
  53. //
  54. // Umi Object is going to be the owner, so we need to
  55. // initilaize the umi object and return.
  56. //
  57. hr = ((CCoreADsObject*)pNamespace)->InitUmiObject(
  58. IntfPropsSchema,
  59. NULL,
  60. (IADs *) pNamespace,
  61. (IADs *) pNamespace,
  62. riid,
  63. ppvObj,
  64. &(pNamespace->_Credentials)
  65. );
  66. BAIL_ON_FAILURE(hr);
  67. RRETURN(S_OK);
  68. }
  69. hr = pNamespace->QueryInterface(riid, ppvObj);
  70. BAIL_ON_FAILURE(hr);
  71. pNamespace->Release();
  72. RRETURN(hr);
  73. error:
  74. *ppvObj = NULL;
  75. delete pNamespace;
  76. RRETURN_EXP_IF_ERR(hr);
  77. }
  78. CLDAPNamespace::~CLDAPNamespace( )
  79. {
  80. VariantClear(&_vFilter);
  81. delete _pDispMgr;
  82. }
  83. STDMETHODIMP
  84. CLDAPNamespace::QueryInterface(REFIID iid, LPVOID FAR* ppv)
  85. {
  86. if (ppv == NULL) {
  87. RRETURN(E_POINTER);
  88. }
  89. if (IsEqualIID(iid, IID_IUnknown))
  90. {
  91. *ppv = (IADs FAR *)this;
  92. }else if (IsEqualIID(iid, IID_IDispatch))
  93. {
  94. *ppv = (IADs FAR *)this;
  95. }
  96. else if (IsEqualIID(iid, IID_IADsContainer))
  97. {
  98. *ppv = (IADsContainer FAR *) this;
  99. }
  100. else if (IsEqualIID(iid, IID_IADs))
  101. {
  102. *ppv = (IADs FAR *) this;
  103. }
  104. else if (IsEqualIID(iid, IID_IADsOpenDSObject))
  105. {
  106. *ppv = (IADsOpenDSObject FAR *) this;
  107. }
  108. else if (IsEqualIID(iid, IID_ISupportErrorInfo))
  109. {
  110. *ppv = (ISupportErrorInfo FAR *) this;
  111. }
  112. else if (IsEqualIID(iid, IID_IADsPathnameProvider))
  113. {
  114. *ppv = (IADsPathnameProvider FAR *) this;
  115. }
  116. else
  117. {
  118. *ppv = NULL;
  119. return E_NOINTERFACE;
  120. }
  121. AddRef();
  122. return NOERROR;
  123. }
  124. /* ISupportErrorInfo method */
  125. STDMETHODIMP
  126. CLDAPNamespace::InterfaceSupportsErrorInfo(THIS_ REFIID riid)
  127. {
  128. if (IsEqualIID(riid, IID_IADs) ||
  129. IsEqualIID(riid, IID_IADsContainer) ||
  130. IsEqualIID(riid, IID_IADsOpenDSObject)) {
  131. RRETURN(S_OK);
  132. } else {
  133. RRETURN(S_FALSE);
  134. }
  135. }
  136. STDMETHODIMP
  137. CLDAPNamespace::SetInfo(THIS)
  138. {
  139. RRETURN_EXP_IF_ERR(E_NOTIMPL);
  140. }
  141. STDMETHODIMP
  142. CLDAPNamespace::GetInfo(THIS)
  143. {
  144. RRETURN_EXP_IF_ERR(E_NOTIMPL);
  145. }
  146. STDMETHODIMP
  147. CLDAPNamespace::GetInfoEx(THIS_ VARIANT vProperties, long lnReserved)
  148. {
  149. RRETURN_EXP_IF_ERR(E_NOTIMPL);
  150. }
  151. /* IADsContainer methods */
  152. STDMETHODIMP
  153. CLDAPNamespace::get_Count(long FAR* retval)
  154. {
  155. RRETURN(E_NOTIMPL);
  156. }
  157. STDMETHODIMP
  158. CLDAPNamespace::get_Filter(THIS_ VARIANT FAR* pVar)
  159. {
  160. HRESULT hr;
  161. VariantInit(pVar);
  162. hr = VariantCopy(pVar, &_vFilter);
  163. RRETURN_EXP_IF_ERR(hr);
  164. }
  165. STDMETHODIMP
  166. CLDAPNamespace::put_Filter(THIS_ VARIANT Var)
  167. {
  168. HRESULT hr;
  169. hr = VariantCopy(&_vFilter, &Var);
  170. RRETURN_EXP_IF_ERR(hr);
  171. }
  172. STDMETHODIMP
  173. CLDAPNamespace::get_Hints(THIS_ VARIANT FAR* pVar)
  174. {
  175. RRETURN_EXP_IF_ERR(E_NOTIMPL);
  176. }
  177. STDMETHODIMP
  178. CLDAPNamespace::put_Hints(THIS_ VARIANT Var)
  179. {
  180. RRETURN_EXP_IF_ERR(E_NOTIMPL);
  181. }
  182. STDMETHODIMP
  183. CLDAPNamespace::GetObject(
  184. THIS_ BSTR ClassName,
  185. BSTR RelativeName,
  186. IDispatch * FAR* ppObject
  187. )
  188. {
  189. DWORD dwBufferSize = 0;
  190. TCHAR *pszBuffer = NULL;
  191. HRESULT hr = S_OK;
  192. if (!RelativeName || !*RelativeName) {
  193. RRETURN_EXP_IF_ERR(E_ADS_UNKNOWN_OBJECT);
  194. }
  195. dwBufferSize = ( _tcslen(_ADsPath) + _tcslen(RelativeName)
  196. + 3 ) * sizeof(TCHAR); // includes "//"
  197. pszBuffer = (LPTSTR) AllocADsMem( dwBufferSize );
  198. if ( pszBuffer == NULL )
  199. {
  200. hr = E_OUTOFMEMORY;
  201. BAIL_ON_FAILURE(hr);
  202. }
  203. _tcscpy(pszBuffer, _ADsPath);
  204. _tcscat(pszBuffer, TEXT("//"));
  205. _tcscat(pszBuffer, RelativeName);
  206. hr = ::GetObject(
  207. pszBuffer,
  208. _Credentials,
  209. (LPVOID *)ppObject
  210. );
  211. BAIL_ON_FAILURE(hr);
  212. error:
  213. if ( pszBuffer )
  214. FreeADsStr( pszBuffer );
  215. RRETURN_EXP_IF_ERR(hr);
  216. }
  217. STDMETHODIMP
  218. CLDAPNamespace::get__NewEnum(THIS_ IUnknown * FAR* retval)
  219. {
  220. HRESULT hr;
  221. IUnknown FAR* punkEnum=NULL;
  222. IEnumVARIANT * penum = NULL;
  223. *retval = NULL;
  224. //
  225. // Create new enumerator for items currently
  226. // in collection and QI for IUnknown
  227. //
  228. hr = CLDAPNamespaceEnum::Create(
  229. (CLDAPNamespaceEnum **)&penum,
  230. _vFilter,
  231. _Credentials,
  232. _ADsPath
  233. );
  234. if (FAILED(hr)){
  235. goto error;
  236. }
  237. hr = penum->QueryInterface(
  238. IID_IUnknown,
  239. (VOID FAR* FAR*)retval
  240. );
  241. if (FAILED(hr)){
  242. goto error;
  243. }
  244. if (penum) {
  245. penum->Release();
  246. }
  247. return NOERROR;
  248. error:
  249. if (penum) {
  250. delete penum;
  251. }
  252. RRETURN_EXP_IF_ERR(hr);
  253. }
  254. STDMETHODIMP
  255. CLDAPNamespace::Create(THIS_ BSTR ClassName, BSTR RelativeName, IDispatch * FAR* ppObject)
  256. {
  257. RRETURN_EXP_IF_ERR(E_NOTIMPL);
  258. }
  259. STDMETHODIMP
  260. CLDAPNamespace::Delete(THIS_ BSTR SourceName, BSTR Type)
  261. {
  262. RRETURN_EXP_IF_ERR(E_NOTIMPL);
  263. }
  264. STDMETHODIMP
  265. CLDAPNamespace::CopyHere(THIS_ BSTR SourceName, BSTR NewName, IDispatch * FAR* ppObject)
  266. {
  267. RRETURN_EXP_IF_ERR(E_NOTIMPL);
  268. }
  269. STDMETHODIMP
  270. CLDAPNamespace::MoveHere(THIS_ BSTR SourceName, BSTR NewName, IDispatch * FAR* ppObject)
  271. {
  272. RRETURN_EXP_IF_ERR(E_NOTIMPL);
  273. }
  274. HRESULT
  275. CLDAPNamespace::AllocateNamespaceObject(
  276. CCredentials& Credentials,
  277. CLDAPNamespace ** ppNamespace
  278. )
  279. {
  280. CLDAPNamespace FAR * pNamespace = NULL;
  281. CAggregatorDispMgr FAR * pDispMgr = NULL;
  282. HRESULT hr = S_OK;
  283. pNamespace = new CLDAPNamespace();
  284. if (pNamespace == NULL) {
  285. hr = E_OUTOFMEMORY;
  286. }
  287. BAIL_ON_FAILURE(hr);
  288. pDispMgr = new CAggregatorDispMgr(Credentials);
  289. if (pDispMgr == NULL) {
  290. hr = E_OUTOFMEMORY;
  291. }
  292. BAIL_ON_FAILURE(hr);
  293. hr = LoadTypeInfoEntry(pDispMgr,
  294. LIBID_ADs,
  295. IID_IADs,
  296. (IADs *)pNamespace,
  297. DISPID_REGULAR
  298. );
  299. BAIL_ON_FAILURE(hr);
  300. hr = LoadTypeInfoEntry(pDispMgr,
  301. LIBID_ADs,
  302. IID_IADsOpenDSObject,
  303. (IADsOpenDSObject *)pNamespace,
  304. DISPID_REGULAR
  305. );
  306. BAIL_ON_FAILURE(hr);
  307. hr = LoadTypeInfoEntry(pDispMgr,
  308. LIBID_ADs,
  309. IID_IADsContainer,
  310. (IADsContainer *)pNamespace,
  311. DISPID_NEWENUM
  312. );
  313. BAIL_ON_FAILURE(hr);
  314. pNamespace->_Credentials = Credentials;
  315. pNamespace->_pDispMgr = pDispMgr;
  316. *ppNamespace = pNamespace;
  317. RRETURN(hr);
  318. error:
  319. delete pDispMgr;
  320. RRETURN(hr);
  321. }
  322. STDMETHODIMP
  323. CLDAPNamespace::OpenDSObject(
  324. BSTR lpszDNName,
  325. BSTR lpszUserName,
  326. BSTR lpszPassword,
  327. LONG lnReserved,
  328. IDispatch FAR * * ppADsObj
  329. )
  330. {
  331. HRESULT hr = S_OK;
  332. IUnknown * pObject = NULL;
  333. CCredentials Credentials(lpszUserName, lpszPassword, lnReserved);
  334. hr = ::GetObject(
  335. lpszDNName,
  336. Credentials,
  337. (LPVOID *)&pObject
  338. );
  339. BAIL_ON_FAILURE(hr);
  340. hr = pObject->QueryInterface(
  341. IID_IDispatch,
  342. (void **)ppADsObj
  343. );
  344. BAIL_ON_FAILURE(hr);
  345. error:
  346. if (pObject) {
  347. pObject->Release();
  348. }
  349. RRETURN_EXP_IF_ERR(hr);
  350. }
  351. HRESULT
  352. CLDAPNamespace::ParsePath(
  353. BSTR bstrADsPath,
  354. DWORD dwType,
  355. PPATH_OBJECTINFO pObjectInfo
  356. )
  357. /*++
  358. Routine Description:
  359. Parse a path based on the type and return the information in pObjectInfo
  360. Arguments:
  361. bstrADsPath - ads path to be parsed
  362. dwType - the type of path to be parsed:
  363. ADS_PARSE_FULL
  364. ADS_PARSE_DN
  365. ADS_PARSE_COMPONENT
  366. pObjectInfo - The place where the parsed object is stored.
  367. It assumes that this structure is valid and empty, and will
  368. overwrite anything that is in there already.
  369. Return Value:
  370. S_OK on success, error code otherwise.
  371. --*/
  372. {
  373. HRESULT hr = S_OK;
  374. OBJECTINFO ObjInfo;
  375. POBJECTINFO pObjInfo = &ObjInfo;
  376. LPWSTR szPath = NULL;
  377. memset(pObjInfo, 0, sizeof(OBJECTINFO));
  378. switch (dwType) {
  379. case ADS_PARSE_FULL:
  380. {
  381. hr = ADsObject(bstrADsPath, pObjInfo);
  382. BAIL_ON_FAILURE(hr);
  383. break;
  384. }
  385. case ADS_PARSE_DN:
  386. {
  387. WCHAR szToken[MAX_TOKEN_LENGTH];
  388. DWORD dwToken;
  389. hr = GetDisplayName(bstrADsPath, &szPath);
  390. BAIL_ON_FAILURE(hr);
  391. hr = InitObjectInfo(szPath,
  392. pObjInfo);
  393. BAIL_ON_FAILURE(hr);
  394. CLexer Lexer(szPath);
  395. Lexer.SetAtDisabler(TRUE);
  396. hr = PathName(&Lexer,
  397. pObjInfo);
  398. BAIL_ON_FAILURE(hr);
  399. hr = Lexer.GetNextToken(szToken,
  400. &dwToken);
  401. BAIL_ON_FAILURE(hr);
  402. if (dwToken != TOKEN_END) {
  403. hr = E_ADS_BAD_PATHNAME;
  404. goto error;
  405. }
  406. break;
  407. }
  408. case ADS_PARSE_COMPONENT:
  409. {
  410. hr = GetDisplayName(bstrADsPath, &szPath);
  411. BAIL_ON_FAILURE(hr);
  412. CLexer Lexer(szPath);
  413. hr = InitObjectInfo(szPath, pObjInfo);
  414. BAIL_ON_FAILURE(hr);
  415. Lexer.SetAtDisabler(TRUE);
  416. hr = Component(&Lexer,
  417. pObjInfo);
  418. BAIL_ON_FAILURE(hr);
  419. break;
  420. }
  421. default:
  422. break;
  423. }
  424. //
  425. // Setting new info
  426. //
  427. if (pObjInfo->ProviderName) {
  428. pObjectInfo->ProviderName = AllocADsStr(pObjInfo->NamespaceName);
  429. if (!pObjectInfo->ProviderName) {
  430. hr = E_OUTOFMEMORY;
  431. BAIL_ON_FAILURE(hr);
  432. }
  433. }
  434. if (pObjInfo->TreeName) {
  435. pObjectInfo->ServerName = AllocADsStr(pObjInfo->TreeName);
  436. if (!pObjectInfo->ServerName) {
  437. hr = E_OUTOFMEMORY;
  438. BAIL_ON_FAILURE(hr);
  439. }
  440. }
  441. if (pObjInfo->DisplayTreeName) {
  442. pObjectInfo->DisplayServerName = AllocADsStr(pObjInfo->DisplayTreeName);
  443. if (!pObjectInfo->DisplayServerName) {
  444. hr = E_OUTOFMEMORY;
  445. BAIL_ON_FAILURE(hr);
  446. }
  447. }
  448. hr = SetObjInfoComponents(pObjInfo,
  449. pObjectInfo);
  450. BAIL_ON_FAILURE(hr);
  451. pObjectInfo->NumComponents = pObjInfo->NumComponents;
  452. pObjectInfo->dwPathType = (pObjInfo->dwPathType == PATHTYPE_X500) ?
  453. ADS_PATHTYPE_LEAFFIRST : ADS_PATHTYPE_ROOTFIRST;
  454. error:
  455. if (szPath != NULL) {
  456. FreeADsStr(szPath);
  457. }
  458. FreeObjectInfo(pObjInfo);
  459. return (hr);
  460. }
  461. HRESULT
  462. CLDAPNamespace::SetObjInfoComponents(
  463. OBJECTINFO *pObjectInfo,
  464. PATH_OBJECTINFO *pObjectInfoTarget
  465. )
  466. /*++
  467. Routine Description:
  468. Set all the compoents in an objinfo from another objinfo. Assumes that the
  469. components in the target objinfo is empty. Users of this function can call
  470. FreeObjInfo to free that data prior to this function call.
  471. Arguments:
  472. Return Value:
  473. S_OK on success, error code otherwise.
  474. --*/
  475. {
  476. DWORD NumComponents;
  477. HRESULT hr = S_OK;
  478. PWSTR pszPath = NULL;
  479. NumComponents = 0;
  480. while (NumComponents < pObjectInfo->NumComponents) {
  481. if (pObjectInfo->ComponentArray[NumComponents].szComponent) {
  482. pObjectInfoTarget->ComponentArray[NumComponents].szComponent =
  483. AllocADsStr(pObjectInfo->ComponentArray[NumComponents].szComponent);
  484. if (pObjectInfoTarget->ComponentArray[NumComponents].szComponent == NULL) {
  485. pObjectInfoTarget->NumComponents = NumComponents;
  486. hr = E_OUTOFMEMORY;
  487. BAIL_ON_FAILURE(hr);
  488. }
  489. pObjectInfoTarget->ProvSpecComponentArray[NumComponents].szComponent =
  490. AllocADsStr(pObjectInfo->ComponentArray[NumComponents].szComponent);
  491. if (pObjectInfoTarget->ProvSpecComponentArray[NumComponents].szComponent == NULL) {
  492. pObjectInfoTarget->NumComponents = NumComponents;
  493. hr = E_OUTOFMEMORY;
  494. BAIL_ON_FAILURE(hr);
  495. }
  496. }
  497. if (pObjectInfo->ComponentArray[NumComponents].szValue) {
  498. DWORD dwResult;
  499. DWORD dwSize = 0;
  500. pObjectInfoTarget->ComponentArray[NumComponents].szValue =
  501. AllocADsStr(pObjectInfo->ComponentArray[NumComponents].szValue);
  502. if (pObjectInfoTarget->ComponentArray[NumComponents].szValue == NULL) {
  503. pObjectInfoTarget->NumComponents = NumComponents;
  504. hr = E_OUTOFMEMORY;
  505. BAIL_ON_FAILURE(hr);
  506. }
  507. dwSize = wcslen(pObjectInfo->ComponentArray[NumComponents].szValue) + 1;
  508. pszPath = (PWSTR)AllocADsMem(dwSize * sizeof(WCHAR));
  509. if (pszPath == NULL) {
  510. hr = E_OUTOFMEMORY;
  511. BAIL_ON_FAILURE(hr);
  512. }
  513. dwResult = DsUnquoteRdnValueWrapper(
  514. wcslen(pObjectInfo->ComponentArray[NumComponents].szValue),
  515. pObjectInfo->ComponentArray[NumComponents].szValue,
  516. &dwSize,
  517. pszPath);
  518. if (dwResult == NO_ERROR) {
  519. pszPath[dwSize] = NULL;
  520. pObjectInfoTarget->ProvSpecComponentArray[NumComponents].szValue =
  521. AllocADsStr(pszPath);
  522. if (pObjectInfoTarget->ProvSpecComponentArray[NumComponents].szValue == NULL) {
  523. pObjectInfoTarget->NumComponents = NumComponents;
  524. hr = E_OUTOFMEMORY;
  525. BAIL_ON_FAILURE(hr);
  526. }
  527. }
  528. if (pszPath) {
  529. FreeADsMem(pszPath);
  530. pszPath = NULL;
  531. }
  532. }
  533. if (pObjectInfo->DisplayComponentArray[NumComponents].szComponent) {
  534. pObjectInfoTarget->DisplayComponentArray[NumComponents].szComponent =
  535. AllocADsStr(pObjectInfo->DisplayComponentArray[NumComponents].szComponent);
  536. if (pObjectInfoTarget->DisplayComponentArray[NumComponents].szComponent == NULL) {
  537. pObjectInfoTarget->NumComponents = NumComponents;
  538. hr = E_OUTOFMEMORY;
  539. BAIL_ON_FAILURE(hr);
  540. }
  541. }
  542. if (pObjectInfo->DisplayComponentArray[NumComponents].szValue) {
  543. pObjectInfoTarget->DisplayComponentArray[NumComponents].szValue =
  544. AllocADsStr(pObjectInfo->DisplayComponentArray[NumComponents].szValue);
  545. if (pObjectInfoTarget->DisplayComponentArray[NumComponents].szValue == NULL) {
  546. pObjectInfoTarget->NumComponents = NumComponents;
  547. hr = E_OUTOFMEMORY;
  548. BAIL_ON_FAILURE(hr);
  549. }
  550. }
  551. NumComponents++;
  552. }
  553. pObjectInfoTarget->NumComponents = pObjectInfo->NumComponents;
  554. return hr;
  555. error:
  556. FreeObjInfoComponents(pObjectInfoTarget);
  557. if (pszPath) {
  558. FreeADsMem(pszPath);
  559. }
  560. RRETURN_EXP_IF_ERR(hr);
  561. }
  562. void
  563. CLDAPNamespace::FreeObjInfoComponents(
  564. PATH_OBJECTINFO *pObjectInfo
  565. )
  566. /*++
  567. Routine Description:
  568. Free all the compoents in an objinfo
  569. Arguments:
  570. Return Value:
  571. S_OK on success, error code otherwise.
  572. --*/
  573. {
  574. DWORD NumComponents;
  575. while (pObjectInfo->NumComponents > 0) {
  576. pObjectInfo->NumComponents--;
  577. NumComponents = pObjectInfo->NumComponents;
  578. if (pObjectInfo->ComponentArray[NumComponents].szComponent) {
  579. FreeADsStr(
  580. pObjectInfo->ComponentArray[NumComponents].szComponent);
  581. pObjectInfo->ComponentArray[NumComponents].szComponent = NULL;
  582. }
  583. if (pObjectInfo->ComponentArray[NumComponents].szValue) {
  584. FreeADsStr(
  585. pObjectInfo->ComponentArray[NumComponents].szValue);
  586. pObjectInfo->ComponentArray[NumComponents].szValue = NULL;
  587. }
  588. if (pObjectInfo->DisplayComponentArray[NumComponents].szComponent) {
  589. FreeADsStr(
  590. pObjectInfo->DisplayComponentArray[NumComponents].szComponent);
  591. pObjectInfo->DisplayComponentArray[NumComponents].szComponent = NULL;
  592. }
  593. if (pObjectInfo->DisplayComponentArray[NumComponents].szValue) {
  594. FreeADsStr(
  595. pObjectInfo->DisplayComponentArray[NumComponents].szValue);
  596. pObjectInfo->DisplayComponentArray[NumComponents].szValue = NULL;
  597. }
  598. if (pObjectInfo->ProvSpecComponentArray[NumComponents].szComponent) {
  599. FreeADsStr(
  600. pObjectInfo->ProvSpecComponentArray[NumComponents].szComponent);
  601. pObjectInfo->ProvSpecComponentArray[NumComponents].szComponent = NULL;
  602. }
  603. if (pObjectInfo->ProvSpecComponentArray[NumComponents].szValue) {
  604. FreeADsStr(
  605. pObjectInfo->ProvSpecComponentArray[NumComponents].szValue);
  606. pObjectInfo->ProvSpecComponentArray[NumComponents].szValue = NULL;
  607. }
  608. }
  609. }
  610. void
  611. CLDAPNamespace::SetComponent(
  612. LPWSTR szReturn,
  613. DWORD cComponents,
  614. DWORD dwEscapedMode
  615. )
  616. /*++
  617. Routine Description:
  618. Set an individual component in the pathname. For internal use only.
  619. Not exposed.
  620. Arguments:
  621. szReturn - the buffer to store the return value
  622. cComponents - the component number to be set
  623. Return Value:
  624. S_OK on success, error code otherwise.
  625. --*/
  626. {
  627. PATH_COMPONENT* pComponent = NULL;
  628. ASSERT(dwEscapedMode != ADS_ESCAPEDMODE_DEFAULT);
  629. if (dwEscapedMode == ADS_ESCAPEDMODE_OFF){
  630. pComponent = _pObjectInfo->ComponentArray;
  631. }
  632. else if (dwEscapedMode == ADS_ESCAPEDMODE_OFF_EX){
  633. pComponent = _pObjectInfo->ProvSpecComponentArray;
  634. }
  635. else if (dwEscapedMode == ADS_ESCAPEDMODE_ON) {
  636. pComponent = _pObjectInfo->DisplayComponentArray;
  637. }
  638. if (_fNamingAttribute) {
  639. wcscat(szReturn, pComponent[cComponents].szComponent);
  640. if (pComponent[cComponents].szValue) {
  641. wcscat(szReturn,
  642. TEXT("="));
  643. wcscat(szReturn,
  644. pComponent[cComponents].szValue);
  645. }
  646. }
  647. else {
  648. if (pComponent[cComponents].szValue) {
  649. //
  650. // If value exist, only show display value
  651. //
  652. wcscat(szReturn,
  653. pComponent[cComponents].szValue);
  654. }
  655. else {
  656. //
  657. // else value is only stored in Component
  658. //
  659. wcscat(szReturn,
  660. pComponent[cComponents].szComponent);
  661. }
  662. }
  663. }
  664. HRESULT
  665. CLDAPNamespace::SetComponents(
  666. LPWSTR szReturn,
  667. BOOLEAN bIsWindowsPath,
  668. LPWSTR chSeparator,
  669. DWORD dwType,
  670. DWORD dwEscapedMode
  671. )
  672. /*++
  673. Routine Description:
  674. Set components in the pathname. For internal use only. Not exposed.
  675. Arguments:
  676. szReturn - the buffer to store the return value
  677. bIsWindowsPath - whether a windows path is to be returned
  678. chSeparator - separator to be used
  679. dwType - the type to be set
  680. ADS_COMPONENT_LEAF
  681. ADS_COMPONENT_DN
  682. ADS_COMPONENT_PARENT
  683. Return Value:
  684. S_OK on success, error code otherwise.
  685. --*/
  686. {
  687. HRESULT hr = S_OK;
  688. BOOL bReverse;
  689. long cComponents;
  690. long dwLimit;
  691. long dwOtherLimit = 0;
  692. if (dwType == ADS_COMPONENT_LEAF) {
  693. //
  694. // Only returns the leaf component
  695. //
  696. if (_pObjectInfo->dwPathType == ADS_PATHTYPE_ROOTFIRST) {
  697. if (_pObjectInfo->NumComponents > 0) {
  698. SetComponent(szReturn,
  699. _pObjectInfo->NumComponents - 1,
  700. dwEscapedMode);
  701. }
  702. else {
  703. hr = E_ADS_BAD_PATHNAME;
  704. }
  705. }
  706. else {
  707. if (_pObjectInfo->NumComponents != 0) {
  708. SetComponent(szReturn,
  709. 0,
  710. dwEscapedMode);
  711. }
  712. else {
  713. hr = E_ADS_BAD_PATHNAME;
  714. }
  715. }
  716. RRETURN(hr);
  717. }
  718. if (_pObjectInfo->dwPathType == ADS_PATHTYPE_ROOTFIRST) {
  719. bReverse = !bIsWindowsPath;
  720. }
  721. else {
  722. bReverse = bIsWindowsPath;
  723. }
  724. if (!bReverse) {
  725. dwLimit = _pObjectInfo->NumComponents;
  726. if (dwType == ADS_COMPONENT_PARENT) {
  727. if (_pObjectInfo->dwPathType == ADS_PATHTYPE_ROOTFIRST)
  728. dwLimit--;
  729. else
  730. dwOtherLimit++;
  731. }
  732. if (dwOtherLimit >= dwLimit) {
  733. hr = E_ADS_BAD_PATHNAME;
  734. goto error;
  735. }
  736. for (cComponents = dwOtherLimit; cComponents < dwLimit; cComponents++) {
  737. SetComponent(szReturn,
  738. cComponents,
  739. dwEscapedMode);
  740. if (cComponents != dwLimit - 1) {
  741. wcscat(szReturn,
  742. chSeparator);
  743. }
  744. }
  745. }
  746. else {
  747. dwLimit = _pObjectInfo->NumComponents-1;
  748. if (dwType == ADS_COMPONENT_PARENT) {
  749. if (_pObjectInfo->dwPathType == ADS_PATHTYPE_ROOTFIRST)
  750. dwLimit--;
  751. else
  752. dwOtherLimit++;
  753. }
  754. if (dwLimit < dwOtherLimit) {
  755. hr = E_ADS_BAD_PATHNAME;
  756. goto error;
  757. }
  758. for (cComponents = dwLimit ; (long)cComponents >= dwOtherLimit; cComponents--) {
  759. SetComponent(szReturn,
  760. cComponents,
  761. dwEscapedMode);
  762. if (cComponents != dwOtherLimit) {
  763. wcscat(szReturn, chSeparator);
  764. }
  765. }
  766. }
  767. error:
  768. RRETURN(S_OK);
  769. }
  770. DWORD CountPath(
  771. PPATH_OBJECTINFO pObjectInfo
  772. )
  773. {
  774. DWORD dwPath = 4; // Basic needs '://' and '/' for servername
  775. DWORD i;
  776. if (pObjectInfo->ProviderName) {
  777. dwPath += wcslen(pObjectInfo->ProviderName);
  778. }
  779. if (pObjectInfo->DisplayServerName) {
  780. dwPath += wcslen(pObjectInfo->DisplayServerName);
  781. }
  782. for (i=0;i<pObjectInfo->NumComponents;i++) {
  783. if (pObjectInfo->DisplayComponentArray[i].szComponent) {
  784. dwPath += wcslen(pObjectInfo->DisplayComponentArray[i].szComponent);
  785. }
  786. if (pObjectInfo->DisplayComponentArray[i].szValue) {
  787. dwPath += wcslen(pObjectInfo->DisplayComponentArray[i].szValue);
  788. }
  789. //
  790. // Add one for comma separator, one for equal sign
  791. //
  792. dwPath+=2;
  793. }
  794. return dwPath;
  795. }
  796. STDMETHODIMP
  797. CLDAPNamespace::ConstructPath(
  798. PPATH_OBJECTINFO pObjectInfo,
  799. DWORD dwFormatType,
  800. DWORD dwFlag,
  801. DWORD dwEscapedMode,
  802. BSTR *pbstrADsPath
  803. )
  804. /*++
  805. Routine Description:
  806. Given an objectinfo structure, and the settings required, this function
  807. assembles the path and returns it in pbstrADsPath
  808. Arguments:
  809. pObjectInfo - the input object info structure
  810. dwFormatType- The format type passed in from Retrieve.
  811. dwFlag - the flag to be set
  812. ADS_CONSTRUCT_ESCAPED
  813. ADS_CONSTRUCT_NAMINGATTRIBUTE
  814. pbstrADsPath - the returned path
  815. Return Value:
  816. S_OK on success, error code otherwise.
  817. --*/
  818. {
  819. HRESULT hr = S_OK;
  820. PWSTR szReturn = NULL;
  821. long cComponents;
  822. DWORD dwPath = 0;
  823. DWORD dwEscapedInternal;
  824. dwEscapedInternal = dwEscapedMode;
  825. if (dwEscapedMode == ADS_ESCAPEDMODE_DEFAULT) {
  826. dwEscapedInternal = ADS_ESCAPEDMODE_OFF;
  827. }
  828. if (!pbstrADsPath) {
  829. hr = E_INVALIDARG;
  830. goto error;
  831. }
  832. dwPath = CountPath(pObjectInfo);
  833. szReturn = (PWSTR)AllocADsMem((dwPath + 1)* sizeof(WCHAR));
  834. if (szReturn == NULL) {
  835. hr = E_OUTOFMEMORY;
  836. goto error;
  837. }
  838. _fNamingAttribute = (BOOLEAN)(dwFlag & ADS_CONSTRUCT_NAMINGATTRIBUTE);
  839. _pObjectInfo = pObjectInfo; // useful in SetComponet() and SetComponents()
  840. wcscpy(szReturn,TEXT(""));
  841. switch (dwFormatType) {
  842. case ADS_FORMAT_WINDOWS:
  843. case ADS_FORMAT_WINDOWS_NO_SERVER:
  844. if (dwEscapedMode == ADS_ESCAPEDMODE_DEFAULT) {
  845. dwEscapedInternal = ADS_ESCAPEDMODE_ON;
  846. }
  847. if (!pObjectInfo->ProviderName) {
  848. hr = E_FAIL; // Need Error Code
  849. goto error;
  850. }
  851. wcscat(szReturn,pObjectInfo->ProviderName);
  852. wcscat(szReturn,TEXT("://"));
  853. if (dwFormatType == ADS_FORMAT_WINDOWS) {
  854. if (dwEscapedInternal == ADS_ESCAPEDMODE_ON) {
  855. if (pObjectInfo->DisplayServerName && (*(pObjectInfo->DisplayServerName))) {
  856. wcscat(szReturn,pObjectInfo->DisplayServerName);
  857. if (pObjectInfo->NumComponents>0) {
  858. wcscat(szReturn,TEXT("/"));
  859. }
  860. }
  861. }
  862. else {
  863. if (pObjectInfo->ServerName && (*(pObjectInfo->ServerName))) {
  864. wcscat(szReturn,pObjectInfo->ServerName);
  865. if (pObjectInfo->NumComponents>0) {
  866. wcscat(szReturn,TEXT("/"));
  867. }
  868. }
  869. }
  870. }
  871. hr = SetComponents(szReturn,
  872. TRUE,
  873. TEXT("/"),
  874. ADS_COMPONENT_DN,
  875. dwEscapedInternal);
  876. BAIL_ON_FAILURE(hr);
  877. break;
  878. case ADS_FORMAT_WINDOWS_DN:
  879. hr = SetComponents(szReturn,
  880. TRUE,
  881. TEXT("/"),
  882. ADS_COMPONENT_DN,
  883. dwEscapedInternal);
  884. BAIL_ON_FAILURE(hr);
  885. break;
  886. case ADS_FORMAT_WINDOWS_PARENT:
  887. hr = SetComponents(szReturn,
  888. TRUE,
  889. TEXT("/"),
  890. ADS_COMPONENT_PARENT,
  891. dwEscapedInternal);
  892. BAIL_ON_FAILURE(hr);
  893. break;
  894. case ADS_FORMAT_X500:
  895. case ADS_FORMAT_X500_NO_SERVER:
  896. if (dwEscapedMode == ADS_ESCAPEDMODE_DEFAULT) {
  897. dwEscapedInternal = ADS_ESCAPEDMODE_ON;
  898. }
  899. if (!pObjectInfo->ProviderName) {
  900. hr = E_FAIL; // Need Error Code
  901. goto error;
  902. }
  903. wcscat(szReturn,pObjectInfo->ProviderName);
  904. wcscat(szReturn,TEXT("://"));
  905. if (dwFormatType == ADS_FORMAT_X500) {
  906. if (dwEscapedInternal == ADS_ESCAPEDMODE_ON) {
  907. if (pObjectInfo->DisplayServerName && (*(pObjectInfo->DisplayServerName))) {
  908. wcscat(szReturn,pObjectInfo->DisplayServerName);
  909. if (pObjectInfo->NumComponents>0) {
  910. wcscat(szReturn,TEXT("/"));
  911. }
  912. }
  913. }
  914. else {
  915. if (pObjectInfo->ServerName && (*(pObjectInfo->ServerName))) {
  916. wcscat(szReturn,pObjectInfo->ServerName);
  917. if (pObjectInfo->NumComponents>0) {
  918. wcscat(szReturn,TEXT("/"));
  919. }
  920. }
  921. }
  922. }
  923. hr = SetComponents(szReturn,
  924. FALSE,
  925. TEXT(","),
  926. ADS_COMPONENT_DN,
  927. dwEscapedInternal);
  928. BAIL_ON_FAILURE(hr);
  929. break;
  930. case ADS_FORMAT_X500_DN:
  931. hr = SetComponents(szReturn,
  932. FALSE,
  933. TEXT(","),
  934. ADS_COMPONENT_DN,
  935. dwEscapedInternal);
  936. BAIL_ON_FAILURE(hr);
  937. break;
  938. case ADS_FORMAT_X500_PARENT:
  939. hr = SetComponents(szReturn,
  940. FALSE,
  941. TEXT(","),
  942. ADS_COMPONENT_PARENT,
  943. dwEscapedInternal);
  944. BAIL_ON_FAILURE(hr);
  945. break;
  946. case ADS_FORMAT_LEAF:
  947. //
  948. // Reverse only if pathtype is X500. In that case, we need to get
  949. // the first element but not the last
  950. //
  951. hr = SetComponents(szReturn,
  952. NULL,
  953. NULL,
  954. ADS_COMPONENT_LEAF,
  955. dwEscapedInternal);
  956. BAIL_ON_FAILURE(hr);
  957. break;
  958. default:
  959. hr = E_INVALIDARG;
  960. goto error;
  961. }
  962. hr = ADsAllocString(szReturn, pbstrADsPath);
  963. error:
  964. if (szReturn) {
  965. FreeADsMem(szReturn);
  966. }
  967. RRETURN_EXP_IF_ERR(hr);
  968. }
  969. STDMETHODIMP
  970. CLDAPNamespace::GetEscapedElement(
  971. LONG lnReserved,
  972. BSTR bstrInStr,
  973. BSTR* pbstrOutStr
  974. )
  975. {
  976. HRESULT hr = S_OK;
  977. if (FAILED(hr = ValidateOutParameter(pbstrOutStr))){
  978. RRETURN_EXP_IF_ERR(hr);
  979. }
  980. if (!bstrInStr) {
  981. RRETURN_EXP_IF_ERR(E_ADS_BAD_PARAMETER);
  982. }
  983. hr = HelperEscapeRDN(bstrInStr, pbstrOutStr);
  984. RRETURN(hr);
  985. }
  986. /////////////////////////////////////////////////////////////////////
  987. // escape.cpp
  988. //
  989. // routine to escape special characters in an RDN
  990. //
  991. // ASSUMPTIONS/RESTRICTIONS:
  992. // - we assume that the input string is un-escaped in any way
  993. // - we assume that the input string is a correctly attributed
  994. // RDN, and we directly copy everything up to and including
  995. // the first '='
  996. //
  997. // HISTORY
  998. // 3-dec-98 jimharr Creation.
  999. /////////////////////////////////////////////////////////////////////
  1000. static WCHAR specialChars[] = L",=\r\n+<>#;\"\\/";
  1001. HRESULT
  1002. HelperEscapeRDN (
  1003. IN BSTR bstrIn,
  1004. OUT BSTR * pbstrOut
  1005. )
  1006. {
  1007. //
  1008. // algorithm:
  1009. // create temporary buffer to hold escaped RDN
  1010. // skip up to first '=', to skip attributeType
  1011. // examine each character, if it needs escaping
  1012. // put a '\' in the dest.
  1013. // copy the character
  1014. // continue until done
  1015. //
  1016. // alloc BSTR of correct size to return
  1017. // copy string, delete temp buffer
  1018. //
  1019. HRESULT hr = S_OK;
  1020. WCHAR *pchSource = NULL;
  1021. WCHAR *pchDest = NULL;
  1022. WCHAR *pBuffer = NULL;
  1023. WCHAR *pTmp;
  1024. pBuffer = (WCHAR* ) AllocADsMem((wcslen(bstrIn) * 3 + 1) * sizeof(WCHAR));
  1025. if (pBuffer == NULL)
  1026. BAIL_ON_FAILURE(hr=E_OUTOFMEMORY);
  1027. pchDest = pBuffer;
  1028. pchSource = (WCHAR *)bstrIn;
  1029. // copy up to the equals sign
  1030. do {
  1031. *pchDest = *pchSource;
  1032. pchSource++;
  1033. pchDest++;
  1034. } while ((*pchSource != L'=') && (*pchSource != L'\0'));
  1035. // if we didn't find an '=', bail
  1036. if (*pchSource == L'\0') {
  1037. BAIL_ON_FAILURE(hr=E_INVALIDARG);
  1038. }
  1039. // copy the '='
  1040. *pchDest = *pchSource;
  1041. pchSource++;
  1042. pchDest++;
  1043. //
  1044. // If the first character after the '=' is a space, we'll escape it.
  1045. // According to LDAP, if the value starts with a space, it has to be escaped
  1046. // or else it will be trimmed.
  1047. //
  1048. if (*pchSource == L' ') {
  1049. *pchDest = L'\\';
  1050. pchDest++;
  1051. *pchDest = *pchSource;
  1052. pchDest++;
  1053. pchSource++;
  1054. }
  1055. while (*pchSource != L'\0') {
  1056. //
  1057. // If we have reached the last character and it is a space, we'll escape
  1058. // it
  1059. //
  1060. if ( (*(pchSource+1) == L'\0') &&
  1061. ((*pchSource) == L' ') ) {
  1062. *pchDest = L'\\';
  1063. pchDest++;
  1064. *pchDest = *pchSource;
  1065. pchDest++;
  1066. break;
  1067. }
  1068. if (NeedsEscaping(*pchSource)) {
  1069. *pchDest = L'\\';
  1070. pchDest++;
  1071. }
  1072. pTmp = EscapedVersion(*pchSource);
  1073. if (pTmp != NULL) {
  1074. wcscpy (pchDest, pTmp);
  1075. pchDest += wcslen(pTmp);
  1076. } else {
  1077. *pchDest = *pchSource;
  1078. pchDest++;
  1079. }
  1080. pchSource++;
  1081. }
  1082. *pchDest = L'\0';
  1083. *pbstrOut = SysAllocString (pBuffer);
  1084. error:
  1085. if (pBuffer) {
  1086. FreeADsMem(pBuffer);
  1087. }
  1088. return (hr);
  1089. }
  1090. BOOL
  1091. NeedsEscaping (WCHAR c)
  1092. {
  1093. WCHAR * pSpecial = specialChars;
  1094. while (*pSpecial != L'\0'){
  1095. if (*pSpecial == c) return TRUE;
  1096. pSpecial++;
  1097. }
  1098. return FALSE;
  1099. }
  1100. WCHAR *
  1101. EscapedVersion (WCHAR c)
  1102. {
  1103. if (c == L'\r')
  1104. return L"0D";
  1105. if (c == L'\n')
  1106. return L"0A";
  1107. return NULL;
  1108. }