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.

1338 lines
35 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 pNamespace;
  320. delete pDispMgr;
  321. RRETURN(hr);
  322. }
  323. STDMETHODIMP
  324. CLDAPNamespace::OpenDSObject(
  325. BSTR lpszDNName,
  326. BSTR lpszUserName,
  327. BSTR lpszPassword,
  328. LONG lnReserved,
  329. IDispatch FAR * * ppADsObj
  330. )
  331. {
  332. HRESULT hr = S_OK;
  333. IUnknown * pObject = NULL;
  334. // we need to block the invoke on UMI code
  335. lnReserved &= (~ADS_AUTH_RESERVED);
  336. CCredentials Credentials(lpszUserName, lpszPassword, lnReserved);
  337. hr = ::GetObject(
  338. lpszDNName,
  339. Credentials,
  340. (LPVOID *)&pObject
  341. );
  342. BAIL_ON_FAILURE(hr);
  343. hr = pObject->QueryInterface(
  344. IID_IDispatch,
  345. (void **)ppADsObj
  346. );
  347. BAIL_ON_FAILURE(hr);
  348. error:
  349. if (pObject) {
  350. pObject->Release();
  351. }
  352. RRETURN_EXP_IF_ERR(hr);
  353. }
  354. HRESULT
  355. CLDAPNamespace::ParsePath(
  356. BSTR bstrADsPath,
  357. DWORD dwType,
  358. PPATH_OBJECTINFO pObjectInfo
  359. )
  360. /*++
  361. Routine Description:
  362. Parse a path based on the type and return the information in pObjectInfo
  363. Arguments:
  364. bstrADsPath - ads path to be parsed
  365. dwType - the type of path to be parsed:
  366. ADS_PARSE_FULL
  367. ADS_PARSE_DN
  368. ADS_PARSE_COMPONENT
  369. pObjectInfo - The place where the parsed object is stored.
  370. It assumes that this structure is valid and empty, and will
  371. overwrite anything that is in there already.
  372. Return Value:
  373. S_OK on success, error code otherwise.
  374. --*/
  375. {
  376. HRESULT hr = S_OK;
  377. OBJECTINFO ObjInfo;
  378. POBJECTINFO pObjInfo = &ObjInfo;
  379. LPWSTR szPath = NULL;
  380. memset(pObjInfo, 0, sizeof(OBJECTINFO));
  381. switch (dwType) {
  382. case ADS_PARSE_FULL:
  383. {
  384. hr = ADsObject(bstrADsPath, pObjInfo);
  385. BAIL_ON_FAILURE(hr);
  386. break;
  387. }
  388. case ADS_PARSE_DN:
  389. {
  390. WCHAR szToken[MAX_TOKEN_LENGTH];
  391. DWORD dwToken;
  392. hr = GetDisplayName(bstrADsPath, &szPath);
  393. BAIL_ON_FAILURE(hr);
  394. hr = InitObjectInfo(szPath,
  395. pObjInfo);
  396. BAIL_ON_FAILURE(hr);
  397. CLexer Lexer;
  398. hr = Lexer.InitializePath(szPath);
  399. BAIL_ON_FAILURE(hr);
  400. Lexer.SetAtDisabler(TRUE);
  401. hr = PathName(&Lexer,
  402. pObjInfo);
  403. BAIL_ON_FAILURE(hr);
  404. hr = Lexer.GetNextToken(szToken,
  405. &dwToken);
  406. BAIL_ON_FAILURE(hr);
  407. if (dwToken != TOKEN_END) {
  408. hr = E_ADS_BAD_PATHNAME;
  409. goto error;
  410. }
  411. break;
  412. }
  413. case ADS_PARSE_COMPONENT:
  414. {
  415. hr = GetDisplayName(bstrADsPath, &szPath);
  416. BAIL_ON_FAILURE(hr);
  417. CLexer Lexer;
  418. hr = Lexer.InitializePath(szPath);
  419. BAIL_ON_FAILURE(hr);
  420. hr = InitObjectInfo(szPath, pObjInfo);
  421. BAIL_ON_FAILURE(hr);
  422. Lexer.SetAtDisabler(TRUE);
  423. hr = Component(&Lexer,
  424. pObjInfo);
  425. BAIL_ON_FAILURE(hr);
  426. break;
  427. }
  428. default:
  429. break;
  430. }
  431. //
  432. // Setting new info
  433. //
  434. if (pObjInfo->ProviderName) {
  435. pObjectInfo->ProviderName = AllocADsStr(pObjInfo->NamespaceName);
  436. if (!pObjectInfo->ProviderName) {
  437. hr = E_OUTOFMEMORY;
  438. BAIL_ON_FAILURE(hr);
  439. }
  440. }
  441. if (pObjInfo->TreeName) {
  442. pObjectInfo->ServerName = AllocADsStr(pObjInfo->TreeName);
  443. if (!pObjectInfo->ServerName) {
  444. hr = E_OUTOFMEMORY;
  445. BAIL_ON_FAILURE(hr);
  446. }
  447. }
  448. if (pObjInfo->DisplayTreeName) {
  449. pObjectInfo->DisplayServerName = AllocADsStr(pObjInfo->DisplayTreeName);
  450. if (!pObjectInfo->DisplayServerName) {
  451. hr = E_OUTOFMEMORY;
  452. BAIL_ON_FAILURE(hr);
  453. }
  454. }
  455. hr = SetObjInfoComponents(pObjInfo,
  456. pObjectInfo);
  457. BAIL_ON_FAILURE(hr);
  458. pObjectInfo->NumComponents = pObjInfo->NumComponents;
  459. pObjectInfo->dwPathType = (pObjInfo->dwPathType == PATHTYPE_X500) ?
  460. ADS_PATHTYPE_LEAFFIRST : ADS_PATHTYPE_ROOTFIRST;
  461. error:
  462. if (szPath != NULL) {
  463. FreeADsStr(szPath);
  464. }
  465. FreeObjectInfo(pObjInfo);
  466. return (hr);
  467. }
  468. HRESULT
  469. CLDAPNamespace::SetObjInfoComponents(
  470. OBJECTINFO *pObjectInfo,
  471. PATH_OBJECTINFO *pObjectInfoTarget
  472. )
  473. /*++
  474. Routine Description:
  475. Set all the compoents in an objinfo from another objinfo. Assumes that the
  476. components in the target objinfo is empty. Users of this function can call
  477. FreeObjInfo to free that data prior to this function call.
  478. Arguments:
  479. Return Value:
  480. S_OK on success, error code otherwise.
  481. --*/
  482. {
  483. DWORD NumComponents;
  484. HRESULT hr = S_OK;
  485. PWSTR pszPath = NULL;
  486. NumComponents = 0;
  487. while (NumComponents < pObjectInfo->NumComponents) {
  488. if (pObjectInfo->ComponentArray[NumComponents].szComponent) {
  489. pObjectInfoTarget->ComponentArray[NumComponents].szComponent =
  490. AllocADsStr(pObjectInfo->ComponentArray[NumComponents].szComponent);
  491. if (pObjectInfoTarget->ComponentArray[NumComponents].szComponent == NULL) {
  492. pObjectInfoTarget->NumComponents = NumComponents;
  493. hr = E_OUTOFMEMORY;
  494. BAIL_ON_FAILURE(hr);
  495. }
  496. pObjectInfoTarget->ProvSpecComponentArray[NumComponents].szComponent =
  497. AllocADsStr(pObjectInfo->ComponentArray[NumComponents].szComponent);
  498. if (pObjectInfoTarget->ProvSpecComponentArray[NumComponents].szComponent == NULL) {
  499. pObjectInfoTarget->NumComponents = NumComponents;
  500. hr = E_OUTOFMEMORY;
  501. BAIL_ON_FAILURE(hr);
  502. }
  503. }
  504. if (pObjectInfo->ComponentArray[NumComponents].szValue) {
  505. DWORD dwResult;
  506. DWORD dwSize = 0;
  507. pObjectInfoTarget->ComponentArray[NumComponents].szValue =
  508. AllocADsStr(pObjectInfo->ComponentArray[NumComponents].szValue);
  509. if (pObjectInfoTarget->ComponentArray[NumComponents].szValue == NULL) {
  510. pObjectInfoTarget->NumComponents = NumComponents;
  511. hr = E_OUTOFMEMORY;
  512. BAIL_ON_FAILURE(hr);
  513. }
  514. dwSize = wcslen(pObjectInfo->ComponentArray[NumComponents].szValue) + 1;
  515. pszPath = (PWSTR)AllocADsMem(dwSize * sizeof(WCHAR));
  516. if (pszPath == NULL) {
  517. hr = E_OUTOFMEMORY;
  518. BAIL_ON_FAILURE(hr);
  519. }
  520. dwResult = DsUnquoteRdnValueWrapper(
  521. wcslen(pObjectInfo->ComponentArray[NumComponents].szValue),
  522. pObjectInfo->ComponentArray[NumComponents].szValue,
  523. &dwSize,
  524. pszPath);
  525. if (dwResult == NO_ERROR) {
  526. pszPath[dwSize] = NULL;
  527. pObjectInfoTarget->ProvSpecComponentArray[NumComponents].szValue =
  528. AllocADsStr(pszPath);
  529. if (pObjectInfoTarget->ProvSpecComponentArray[NumComponents].szValue == NULL) {
  530. pObjectInfoTarget->NumComponents = NumComponents;
  531. hr = E_OUTOFMEMORY;
  532. BAIL_ON_FAILURE(hr);
  533. }
  534. }
  535. if (pszPath) {
  536. FreeADsMem(pszPath);
  537. pszPath = NULL;
  538. }
  539. }
  540. if (pObjectInfo->DisplayComponentArray[NumComponents].szComponent) {
  541. pObjectInfoTarget->DisplayComponentArray[NumComponents].szComponent =
  542. AllocADsStr(pObjectInfo->DisplayComponentArray[NumComponents].szComponent);
  543. if (pObjectInfoTarget->DisplayComponentArray[NumComponents].szComponent == NULL) {
  544. pObjectInfoTarget->NumComponents = NumComponents;
  545. hr = E_OUTOFMEMORY;
  546. BAIL_ON_FAILURE(hr);
  547. }
  548. }
  549. if (pObjectInfo->DisplayComponentArray[NumComponents].szValue) {
  550. pObjectInfoTarget->DisplayComponentArray[NumComponents].szValue =
  551. AllocADsStr(pObjectInfo->DisplayComponentArray[NumComponents].szValue);
  552. if (pObjectInfoTarget->DisplayComponentArray[NumComponents].szValue == NULL) {
  553. pObjectInfoTarget->NumComponents = NumComponents;
  554. hr = E_OUTOFMEMORY;
  555. BAIL_ON_FAILURE(hr);
  556. }
  557. }
  558. NumComponents++;
  559. }
  560. pObjectInfoTarget->NumComponents = pObjectInfo->NumComponents;
  561. return hr;
  562. error:
  563. FreeObjInfoComponents(pObjectInfoTarget);
  564. if (pszPath) {
  565. FreeADsMem(pszPath);
  566. }
  567. RRETURN_EXP_IF_ERR(hr);
  568. }
  569. void
  570. CLDAPNamespace::FreeObjInfoComponents(
  571. PATH_OBJECTINFO *pObjectInfo
  572. )
  573. /*++
  574. Routine Description:
  575. Free all the compoents in an objinfo
  576. Arguments:
  577. Return Value:
  578. S_OK on success, error code otherwise.
  579. --*/
  580. {
  581. DWORD NumComponents;
  582. while (pObjectInfo->NumComponents > 0) {
  583. pObjectInfo->NumComponents--;
  584. NumComponents = pObjectInfo->NumComponents;
  585. if (pObjectInfo->ComponentArray[NumComponents].szComponent) {
  586. FreeADsStr(
  587. pObjectInfo->ComponentArray[NumComponents].szComponent);
  588. pObjectInfo->ComponentArray[NumComponents].szComponent = NULL;
  589. }
  590. if (pObjectInfo->ComponentArray[NumComponents].szValue) {
  591. FreeADsStr(
  592. pObjectInfo->ComponentArray[NumComponents].szValue);
  593. pObjectInfo->ComponentArray[NumComponents].szValue = NULL;
  594. }
  595. if (pObjectInfo->DisplayComponentArray[NumComponents].szComponent) {
  596. FreeADsStr(
  597. pObjectInfo->DisplayComponentArray[NumComponents].szComponent);
  598. pObjectInfo->DisplayComponentArray[NumComponents].szComponent = NULL;
  599. }
  600. if (pObjectInfo->DisplayComponentArray[NumComponents].szValue) {
  601. FreeADsStr(
  602. pObjectInfo->DisplayComponentArray[NumComponents].szValue);
  603. pObjectInfo->DisplayComponentArray[NumComponents].szValue = NULL;
  604. }
  605. if (pObjectInfo->ProvSpecComponentArray[NumComponents].szComponent) {
  606. FreeADsStr(
  607. pObjectInfo->ProvSpecComponentArray[NumComponents].szComponent);
  608. pObjectInfo->ProvSpecComponentArray[NumComponents].szComponent = NULL;
  609. }
  610. if (pObjectInfo->ProvSpecComponentArray[NumComponents].szValue) {
  611. FreeADsStr(
  612. pObjectInfo->ProvSpecComponentArray[NumComponents].szValue);
  613. pObjectInfo->ProvSpecComponentArray[NumComponents].szValue = NULL;
  614. }
  615. }
  616. }
  617. void
  618. CLDAPNamespace::SetComponent(
  619. LPWSTR szReturn,
  620. DWORD cComponents,
  621. DWORD dwEscapedMode
  622. )
  623. /*++
  624. Routine Description:
  625. Set an individual component in the pathname. For internal use only.
  626. Not exposed.
  627. Arguments:
  628. szReturn - the buffer to store the return value
  629. cComponents - the component number to be set
  630. Return Value:
  631. S_OK on success, error code otherwise.
  632. --*/
  633. {
  634. PATH_COMPONENT* pComponent = NULL;
  635. ASSERT(dwEscapedMode != ADS_ESCAPEDMODE_DEFAULT);
  636. if (dwEscapedMode == ADS_ESCAPEDMODE_OFF){
  637. pComponent = _pObjectInfo->ComponentArray;
  638. }
  639. else if (dwEscapedMode == ADS_ESCAPEDMODE_OFF_EX){
  640. pComponent = _pObjectInfo->ProvSpecComponentArray;
  641. }
  642. else if (dwEscapedMode == ADS_ESCAPEDMODE_ON) {
  643. pComponent = _pObjectInfo->DisplayComponentArray;
  644. }
  645. if (_fNamingAttribute) {
  646. wcscat(szReturn, pComponent[cComponents].szComponent);
  647. if (pComponent[cComponents].szValue) {
  648. wcscat(szReturn,
  649. TEXT("="));
  650. wcscat(szReturn,
  651. pComponent[cComponents].szValue);
  652. }
  653. }
  654. else {
  655. if (pComponent[cComponents].szValue) {
  656. //
  657. // If value exist, only show display value
  658. //
  659. wcscat(szReturn,
  660. pComponent[cComponents].szValue);
  661. }
  662. else {
  663. //
  664. // else value is only stored in Component
  665. //
  666. wcscat(szReturn,
  667. pComponent[cComponents].szComponent);
  668. }
  669. }
  670. }
  671. HRESULT
  672. CLDAPNamespace::SetComponents(
  673. LPWSTR szReturn,
  674. BOOLEAN bIsWindowsPath,
  675. LPWSTR chSeparator,
  676. DWORD dwType,
  677. DWORD dwEscapedMode
  678. )
  679. /*++
  680. Routine Description:
  681. Set components in the pathname. For internal use only. Not exposed.
  682. Arguments:
  683. szReturn - the buffer to store the return value
  684. bIsWindowsPath - whether a windows path is to be returned
  685. chSeparator - separator to be used
  686. dwType - the type to be set
  687. ADS_COMPONENT_LEAF
  688. ADS_COMPONENT_DN
  689. ADS_COMPONENT_PARENT
  690. Return Value:
  691. S_OK on success, error code otherwise.
  692. --*/
  693. {
  694. HRESULT hr = S_OK;
  695. BOOL bReverse;
  696. long cComponents;
  697. long dwLimit;
  698. long dwOtherLimit = 0;
  699. if (dwType == ADS_COMPONENT_LEAF) {
  700. //
  701. // Only returns the leaf component
  702. //
  703. if (_pObjectInfo->dwPathType == ADS_PATHTYPE_ROOTFIRST) {
  704. if (_pObjectInfo->NumComponents > 0) {
  705. SetComponent(szReturn,
  706. _pObjectInfo->NumComponents - 1,
  707. dwEscapedMode);
  708. }
  709. else {
  710. hr = E_ADS_BAD_PATHNAME;
  711. }
  712. }
  713. else {
  714. if (_pObjectInfo->NumComponents != 0) {
  715. SetComponent(szReturn,
  716. 0,
  717. dwEscapedMode);
  718. }
  719. else {
  720. hr = E_ADS_BAD_PATHNAME;
  721. }
  722. }
  723. RRETURN(hr);
  724. }
  725. if (_pObjectInfo->dwPathType == ADS_PATHTYPE_ROOTFIRST) {
  726. bReverse = !bIsWindowsPath;
  727. }
  728. else {
  729. bReverse = bIsWindowsPath;
  730. }
  731. if (!bReverse) {
  732. dwLimit = _pObjectInfo->NumComponents;
  733. if (dwType == ADS_COMPONENT_PARENT) {
  734. if (_pObjectInfo->dwPathType == ADS_PATHTYPE_ROOTFIRST)
  735. dwLimit--;
  736. else
  737. dwOtherLimit++;
  738. }
  739. if (dwOtherLimit >= dwLimit) {
  740. hr = E_ADS_BAD_PATHNAME;
  741. goto error;
  742. }
  743. for (cComponents = dwOtherLimit; cComponents < dwLimit; cComponents++) {
  744. SetComponent(szReturn,
  745. cComponents,
  746. dwEscapedMode);
  747. if (cComponents != dwLimit - 1) {
  748. wcscat(szReturn,
  749. chSeparator);
  750. }
  751. }
  752. }
  753. else {
  754. dwLimit = _pObjectInfo->NumComponents-1;
  755. if (dwType == ADS_COMPONENT_PARENT) {
  756. if (_pObjectInfo->dwPathType == ADS_PATHTYPE_ROOTFIRST)
  757. dwLimit--;
  758. else
  759. dwOtherLimit++;
  760. }
  761. if (dwLimit < dwOtherLimit) {
  762. hr = E_ADS_BAD_PATHNAME;
  763. goto error;
  764. }
  765. for (cComponents = dwLimit ; (long)cComponents >= dwOtherLimit; cComponents--) {
  766. SetComponent(szReturn,
  767. cComponents,
  768. dwEscapedMode);
  769. if (cComponents != dwOtherLimit) {
  770. wcscat(szReturn, chSeparator);
  771. }
  772. }
  773. }
  774. error:
  775. RRETURN(S_OK);
  776. }
  777. DWORD CountPath(
  778. PPATH_OBJECTINFO pObjectInfo
  779. )
  780. {
  781. DWORD dwPath = 4; // Basic needs '://' and '/' for servername
  782. DWORD i;
  783. if (pObjectInfo->ProviderName) {
  784. dwPath += wcslen(pObjectInfo->ProviderName);
  785. }
  786. if (pObjectInfo->DisplayServerName) {
  787. dwPath += wcslen(pObjectInfo->DisplayServerName);
  788. }
  789. for (i=0;i<pObjectInfo->NumComponents;i++) {
  790. if (pObjectInfo->DisplayComponentArray[i].szComponent) {
  791. dwPath += wcslen(pObjectInfo->DisplayComponentArray[i].szComponent);
  792. }
  793. if (pObjectInfo->DisplayComponentArray[i].szValue) {
  794. dwPath += wcslen(pObjectInfo->DisplayComponentArray[i].szValue);
  795. }
  796. //
  797. // Add one for comma separator, one for equal sign
  798. //
  799. dwPath+=2;
  800. }
  801. return dwPath;
  802. }
  803. STDMETHODIMP
  804. CLDAPNamespace::ConstructPath(
  805. PPATH_OBJECTINFO pObjectInfo,
  806. DWORD dwFormatType,
  807. DWORD dwFlag,
  808. DWORD dwEscapedMode,
  809. BSTR *pbstrADsPath
  810. )
  811. /*++
  812. Routine Description:
  813. Given an objectinfo structure, and the settings required, this function
  814. assembles the path and returns it in pbstrADsPath
  815. Arguments:
  816. pObjectInfo - the input object info structure
  817. dwFormatType- The format type passed in from Retrieve.
  818. dwFlag - the flag to be set
  819. ADS_CONSTRUCT_ESCAPED
  820. ADS_CONSTRUCT_NAMINGATTRIBUTE
  821. pbstrADsPath - the returned path
  822. Return Value:
  823. S_OK on success, error code otherwise.
  824. --*/
  825. {
  826. HRESULT hr = S_OK;
  827. PWSTR szReturn = NULL;
  828. long cComponents;
  829. DWORD dwPath = 0;
  830. DWORD dwEscapedInternal;
  831. dwEscapedInternal = dwEscapedMode;
  832. if (dwEscapedMode == ADS_ESCAPEDMODE_DEFAULT) {
  833. dwEscapedInternal = ADS_ESCAPEDMODE_OFF;
  834. }
  835. if (!pbstrADsPath) {
  836. hr = E_INVALIDARG;
  837. goto error;
  838. }
  839. dwPath = CountPath(pObjectInfo);
  840. szReturn = (PWSTR)AllocADsMem((dwPath + 1)* sizeof(WCHAR));
  841. if (szReturn == NULL) {
  842. hr = E_OUTOFMEMORY;
  843. goto error;
  844. }
  845. _fNamingAttribute = (BOOLEAN)(dwFlag & ADS_CONSTRUCT_NAMINGATTRIBUTE);
  846. _pObjectInfo = pObjectInfo; // useful in SetComponet() and SetComponents()
  847. wcscpy(szReturn,TEXT(""));
  848. switch (dwFormatType) {
  849. case ADS_FORMAT_WINDOWS:
  850. case ADS_FORMAT_WINDOWS_NO_SERVER:
  851. if (dwEscapedMode == ADS_ESCAPEDMODE_DEFAULT) {
  852. dwEscapedInternal = ADS_ESCAPEDMODE_ON;
  853. }
  854. if (!pObjectInfo->ProviderName) {
  855. hr = E_FAIL; // Need Error Code
  856. goto error;
  857. }
  858. wcscat(szReturn,pObjectInfo->ProviderName);
  859. wcscat(szReturn,TEXT("://"));
  860. if (dwFormatType == ADS_FORMAT_WINDOWS) {
  861. if (dwEscapedInternal == ADS_ESCAPEDMODE_ON) {
  862. if (pObjectInfo->DisplayServerName && (*(pObjectInfo->DisplayServerName))) {
  863. wcscat(szReturn,pObjectInfo->DisplayServerName);
  864. if (pObjectInfo->NumComponents>0) {
  865. wcscat(szReturn,TEXT("/"));
  866. }
  867. }
  868. }
  869. else {
  870. if (pObjectInfo->ServerName && (*(pObjectInfo->ServerName))) {
  871. wcscat(szReturn,pObjectInfo->ServerName);
  872. if (pObjectInfo->NumComponents>0) {
  873. wcscat(szReturn,TEXT("/"));
  874. }
  875. }
  876. }
  877. }
  878. hr = SetComponents(szReturn,
  879. TRUE,
  880. TEXT("/"),
  881. ADS_COMPONENT_DN,
  882. dwEscapedInternal);
  883. BAIL_ON_FAILURE(hr);
  884. break;
  885. case ADS_FORMAT_WINDOWS_DN:
  886. hr = SetComponents(szReturn,
  887. TRUE,
  888. TEXT("/"),
  889. ADS_COMPONENT_DN,
  890. dwEscapedInternal);
  891. BAIL_ON_FAILURE(hr);
  892. break;
  893. case ADS_FORMAT_WINDOWS_PARENT:
  894. hr = SetComponents(szReturn,
  895. TRUE,
  896. TEXT("/"),
  897. ADS_COMPONENT_PARENT,
  898. dwEscapedInternal);
  899. BAIL_ON_FAILURE(hr);
  900. break;
  901. case ADS_FORMAT_X500:
  902. case ADS_FORMAT_X500_NO_SERVER:
  903. if (dwEscapedMode == ADS_ESCAPEDMODE_DEFAULT) {
  904. dwEscapedInternal = ADS_ESCAPEDMODE_ON;
  905. }
  906. if (!pObjectInfo->ProviderName) {
  907. hr = E_FAIL; // Need Error Code
  908. goto error;
  909. }
  910. wcscat(szReturn,pObjectInfo->ProviderName);
  911. wcscat(szReturn,TEXT("://"));
  912. if (dwFormatType == ADS_FORMAT_X500) {
  913. if (dwEscapedInternal == ADS_ESCAPEDMODE_ON) {
  914. if (pObjectInfo->DisplayServerName && (*(pObjectInfo->DisplayServerName))) {
  915. wcscat(szReturn,pObjectInfo->DisplayServerName);
  916. if (pObjectInfo->NumComponents>0) {
  917. wcscat(szReturn,TEXT("/"));
  918. }
  919. }
  920. }
  921. else {
  922. if (pObjectInfo->ServerName && (*(pObjectInfo->ServerName))) {
  923. wcscat(szReturn,pObjectInfo->ServerName);
  924. if (pObjectInfo->NumComponents>0) {
  925. wcscat(szReturn,TEXT("/"));
  926. }
  927. }
  928. }
  929. }
  930. hr = SetComponents(szReturn,
  931. FALSE,
  932. TEXT(","),
  933. ADS_COMPONENT_DN,
  934. dwEscapedInternal);
  935. BAIL_ON_FAILURE(hr);
  936. break;
  937. case ADS_FORMAT_X500_DN:
  938. hr = SetComponents(szReturn,
  939. FALSE,
  940. TEXT(","),
  941. ADS_COMPONENT_DN,
  942. dwEscapedInternal);
  943. BAIL_ON_FAILURE(hr);
  944. break;
  945. case ADS_FORMAT_X500_PARENT:
  946. hr = SetComponents(szReturn,
  947. FALSE,
  948. TEXT(","),
  949. ADS_COMPONENT_PARENT,
  950. dwEscapedInternal);
  951. BAIL_ON_FAILURE(hr);
  952. break;
  953. case ADS_FORMAT_LEAF:
  954. //
  955. // Reverse only if pathtype is X500. In that case, we need to get
  956. // the first element but not the last
  957. //
  958. hr = SetComponents(szReturn,
  959. NULL,
  960. NULL,
  961. ADS_COMPONENT_LEAF,
  962. dwEscapedInternal);
  963. BAIL_ON_FAILURE(hr);
  964. break;
  965. default:
  966. hr = E_INVALIDARG;
  967. goto error;
  968. }
  969. hr = ADsAllocString(szReturn, pbstrADsPath);
  970. error:
  971. if (szReturn) {
  972. FreeADsMem(szReturn);
  973. }
  974. RRETURN_EXP_IF_ERR(hr);
  975. }
  976. STDMETHODIMP
  977. CLDAPNamespace::GetEscapedElement(
  978. LONG lnReserved,
  979. BSTR bstrInStr,
  980. BSTR* pbstrOutStr
  981. )
  982. {
  983. HRESULT hr = S_OK;
  984. if (FAILED(hr = ValidateOutParameter(pbstrOutStr))){
  985. RRETURN_EXP_IF_ERR(hr);
  986. }
  987. if (!bstrInStr) {
  988. RRETURN_EXP_IF_ERR(E_ADS_BAD_PARAMETER);
  989. }
  990. hr = HelperEscapeRDN(bstrInStr, pbstrOutStr);
  991. RRETURN(hr);
  992. }
  993. /////////////////////////////////////////////////////////////////////
  994. // escape.cpp
  995. //
  996. // routine to escape special characters in an RDN
  997. //
  998. // ASSUMPTIONS/RESTRICTIONS:
  999. // - we assume that the input string is un-escaped in any way
  1000. // - we assume that the input string is a correctly attributed
  1001. // RDN, and we directly copy everything up to and including
  1002. // the first '='
  1003. //
  1004. // HISTORY
  1005. // 3-dec-98 jimharr Creation.
  1006. /////////////////////////////////////////////////////////////////////
  1007. static WCHAR specialChars[] = L",=\r\n+<>#;\"\\/";
  1008. HRESULT
  1009. HelperEscapeRDN (
  1010. IN BSTR bstrIn,
  1011. OUT BSTR * pbstrOut
  1012. )
  1013. {
  1014. //
  1015. // algorithm:
  1016. // create temporary buffer to hold escaped RDN
  1017. // skip up to first '=', to skip attributeType
  1018. // examine each character, if it needs escaping
  1019. // put a '\' in the dest.
  1020. // copy the character
  1021. // continue until done
  1022. //
  1023. // alloc BSTR of correct size to return
  1024. // copy string, delete temp buffer
  1025. //
  1026. HRESULT hr = S_OK;
  1027. WCHAR *pchSource = NULL;
  1028. WCHAR *pchDest = NULL;
  1029. WCHAR *pBuffer = NULL;
  1030. WCHAR *pTmp;
  1031. pBuffer = (WCHAR* ) AllocADsMem((wcslen(bstrIn) * 3 + 1) * sizeof(WCHAR));
  1032. if (pBuffer == NULL)
  1033. BAIL_ON_FAILURE(hr=E_OUTOFMEMORY);
  1034. pchDest = pBuffer;
  1035. pchSource = (WCHAR *)bstrIn;
  1036. // copy up to the equals sign
  1037. do {
  1038. *pchDest = *pchSource;
  1039. pchSource++;
  1040. pchDest++;
  1041. } while ((*pchSource != L'=') && (*pchSource != L'\0'));
  1042. // if we didn't find an '=', bail
  1043. if (*pchSource == L'\0') {
  1044. BAIL_ON_FAILURE(hr=E_INVALIDARG);
  1045. }
  1046. // copy the '='
  1047. *pchDest = *pchSource;
  1048. pchSource++;
  1049. pchDest++;
  1050. //
  1051. // If the first character after the '=' is a space, we'll escape it.
  1052. // According to LDAP, if the value starts with a space, it has to be escaped
  1053. // or else it will be trimmed.
  1054. //
  1055. if (*pchSource == L' ') {
  1056. *pchDest = L'\\';
  1057. pchDest++;
  1058. *pchDest = *pchSource;
  1059. pchDest++;
  1060. pchSource++;
  1061. }
  1062. while (*pchSource != L'\0') {
  1063. //
  1064. // If we have reached the last character and it is a space, we'll escape
  1065. // it
  1066. //
  1067. if ( (*(pchSource+1) == L'\0') &&
  1068. ((*pchSource) == L' ') ) {
  1069. *pchDest = L'\\';
  1070. pchDest++;
  1071. *pchDest = *pchSource;
  1072. pchDest++;
  1073. break;
  1074. }
  1075. if (NeedsEscaping(*pchSource)) {
  1076. *pchDest = L'\\';
  1077. pchDest++;
  1078. }
  1079. pTmp = EscapedVersion(*pchSource);
  1080. if (pTmp != NULL) {
  1081. wcscpy (pchDest, pTmp);
  1082. pchDest += wcslen(pTmp);
  1083. } else {
  1084. *pchDest = *pchSource;
  1085. pchDest++;
  1086. }
  1087. pchSource++;
  1088. }
  1089. *pchDest = L'\0';
  1090. *pbstrOut = SysAllocString (pBuffer);
  1091. error:
  1092. if (pBuffer) {
  1093. FreeADsMem(pBuffer);
  1094. }
  1095. return (hr);
  1096. }
  1097. BOOL
  1098. NeedsEscaping (WCHAR c)
  1099. {
  1100. WCHAR * pSpecial = specialChars;
  1101. while (*pSpecial != L'\0'){
  1102. if (*pSpecial == c) return TRUE;
  1103. pSpecial++;
  1104. }
  1105. return FALSE;
  1106. }
  1107. WCHAR *
  1108. EscapedVersion (WCHAR c)
  1109. {
  1110. if (c == L'\r')
  1111. return L"0D";
  1112. if (c == L'\n')
  1113. return L"0A";
  1114. return NULL;
  1115. }