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.

617 lines
14 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 2000.
  5. //
  6. // File: cconnect.cxx
  7. //
  8. // Contents: LDAP Connection object - this object implements the
  9. // IUmiConnection interface.
  10. //
  11. // Functions: TBD.
  12. //
  13. // History: 03-03-00 AjayR Created.
  14. //
  15. //----------------------------------------------------------------------------
  16. #include "ldap.hxx"
  17. //+---------------------------------------------------------------------------
  18. // Function: CLDAPConObject::CLDAPConObject
  19. //
  20. // Synopsis: Constructor
  21. //
  22. // Arguments: None
  23. //
  24. // Returns: N/A
  25. //
  26. // Modifies: N/A
  27. //
  28. //----------------------------------------------------------------------------
  29. CLDAPConObject::CLDAPConObject():
  30. _pPropMgr(NULL),
  31. _fConnected(FALSE),
  32. _pLdapHandle(NULL),
  33. _ulErrorStatus(0)
  34. {
  35. }
  36. //+---------------------------------------------------------------------------
  37. // Function: CLDAPConObject::~CLDAPConObject
  38. //
  39. // Synopsis: Destructor
  40. //
  41. // Arguments: None
  42. //
  43. // Returns: N/A
  44. //
  45. // Modifies: N/A
  46. //
  47. //----------------------------------------------------------------------------
  48. CLDAPConObject::~CLDAPConObject()
  49. {
  50. delete _pPropMgr;
  51. //
  52. // Close the handle if needed - this will deref and free if appropriate.
  53. //
  54. if (_pLdapHandle) {
  55. LdapCloseObject(_pLdapHandle);
  56. _pLdapHandle = NULL;
  57. }
  58. }
  59. //+---------------------------------------------------------------------------
  60. // Function: CLDAPConObject::CreateConnectionObject
  61. //
  62. // Synopsis: Static allocation routine for connection object.
  63. //
  64. // Arguments: CLDAPConObject * --- contains new connection object
  65. // PADSLDP --- ldap handle defaulted NULL.
  66. //
  67. // Returns: HRESULT - S_OK or any failure error code.
  68. //
  69. // Modifies: CLDAPConObject ** - ptr to newly created object.
  70. //
  71. //----------------------------------------------------------------------------
  72. HRESULT
  73. CLDAPConObject::CreateConnectionObject(
  74. CLDAPConObject FAR * FAR * ppConnectionObject,
  75. PADSLDP pLdapHandle // defaulted to NULL
  76. )
  77. {
  78. HRESULT hr = S_OK;
  79. CLDAPConObject FAR * pConObj = NULL;
  80. CPropertyManager FAR * pIntfPropMgr = NULL;
  81. pConObj = new CLDAPConObject();
  82. if (!pConObj) {
  83. RRETURN_EXP_IF_ERR(E_OUTOFMEMORY);
  84. }
  85. //
  86. // Add a ref to the ldap handle if one was passed in.
  87. //
  88. if (pLdapHandle) {
  89. pConObj->_pLdapHandle = pLdapHandle;
  90. pConObj->_fConnected = TRUE;
  91. LdapCacheAddRef(pConObj->_pLdapHandle);
  92. }
  93. hr = CPropertyManager::CreatePropertyManager(
  94. (IUmiConnection *) pConObj,
  95. NULL, // outer unk
  96. NULL, // credentials
  97. IntfPropsConnection,
  98. &pIntfPropMgr
  99. );
  100. BAIL_ON_FAILURE(hr);
  101. pConObj->_pPropMgr = pIntfPropMgr;
  102. *ppConnectionObject = pConObj;
  103. RRETURN(S_OK);
  104. error:
  105. //
  106. // If we get here, we likely could not create the property manager.
  107. //
  108. if (pConObj) {
  109. delete pConObj;
  110. }
  111. RRETURN(hr);
  112. }
  113. STDMETHODIMP
  114. CLDAPConObject::QueryInterface(REFIID iid, LPVOID FAR* ppv)
  115. {
  116. HRESULT hr = S_OK;
  117. SetLastStatus(0);
  118. if (ppv == NULL) {
  119. RRETURN(E_POINTER);
  120. }
  121. if (IsEqualIID(iid, IID_IUnknown)){
  122. *ppv = (IUnknown FAR *) this;
  123. }
  124. else if (IsEqualIID(iid, IID_IUmiPropList)) {
  125. *ppv = (IUmiConnection FAR *) this;
  126. }
  127. else if (IsEqualIID(iid, IID_IUmiBaseObject)) {
  128. *ppv = (IUmiConnection FAR *) this;
  129. }
  130. else if (IsEqualIID(iid, IID_IUmiConnection)) {
  131. *ppv = (IUmiConnection FAR *) this;
  132. }
  133. else {
  134. *ppv = NULL;
  135. SetLastStatus(E_NOINTERFACE);
  136. return E_NOINTERFACE;
  137. }
  138. AddRef();
  139. return NOERROR;
  140. }
  141. //
  142. // IUmiConnection methods.
  143. //
  144. //+---------------------------------------------------------------------------
  145. // Function: CLDAPConObject::Open
  146. //
  147. // Synopsis: Opens a connection to the server (either implicityly
  148. // specified in the url or explicitly in the interface
  149. // properties. If there is already an underlyng ldap connection,
  150. // subsequent open operations will fail if they do not use the same
  151. // underlying connection.
  152. //
  153. // Arguments: pUrl - IUmiUrl object pointing to object to be fetched.
  154. // uFlags - Flags for the operation (currently on 0).
  155. // TargetIID - IID requested on the target object.
  156. // ppvRes - ptr to return the target object.
  157. //
  158. // Returns: HRESULT - S_OK or any failure error code.
  159. //
  160. // Modifies: The status of the object and underlying ldap handle ptr.
  161. //
  162. //----------------------------------------------------------------------------
  163. STDMETHODIMP
  164. CLDAPConObject::Open(
  165. IUmiURL *pURL,
  166. ULONG uFlags,
  167. REFIID TargetIID,
  168. void ** ppvRes
  169. )
  170. {
  171. HRESULT hr = S_OK;
  172. LPWSTR pszUrl = NULL;
  173. IUnknown *pUnk = NULL;
  174. IADsObjOptPrivate * pPrivOpt = NULL;
  175. PADSLDP pLdapTmpHandle = NULL;
  176. //
  177. // Default values for credentials.
  178. //
  179. LPWSTR pszUserName = NULL;
  180. LPWSTR pszPassword = NULL;
  181. LPWSTR pszLdapPath = NULL;
  182. DWORD dwFlags = 0;
  183. BOOL fFlag;
  184. SetLastStatus(0);
  185. if (!ppvRes || !pURL) {
  186. BAIL_ON_FAILURE(hr = E_INVALIDARG);
  187. }
  188. if (uFlags != 0) {
  189. BAIL_ON_FAILURE(hr = UMI_E_INVALID_FLAGS);
  190. }
  191. *ppvRes = NULL;
  192. //
  193. // UrlToLDAPPath can handle both native and umi paths.
  194. //
  195. hr = UrlToLDAPPath(
  196. pURL,
  197. &pszLdapPath
  198. );
  199. BAIL_ON_FAILURE(hr);
  200. //
  201. // Prepare the credentials if applicable.
  202. //
  203. if (!_pCredentials) {
  204. //
  205. // Get the params from the property mgr.
  206. //
  207. hr = _pPropMgr->GetStringProperty(L"__UserId", &pszUserName);
  208. if (hr == E_OUTOFMEMORY) {
  209. BAIL_ON_FAILURE(hr);
  210. }
  211. hr = _pPropMgr->GetStringProperty(L"__Password", &pszPassword);
  212. if (hr == E_OUTOFMEMORY) {
  213. BAIL_ON_FAILURE(hr);
  214. }
  215. hr = _pPropMgr->GetBoolProperty(
  216. L"__SECURE_AUTHENTICATION",
  217. &fFlag
  218. );
  219. BAIL_ON_FAILURE(hr);
  220. if (fFlag) {
  221. dwFlags |= ADS_SECURE_AUTHENTICATION;
  222. }
  223. hr = _pPropMgr->GetBoolProperty(
  224. L"__NO_AUTHENTICATION",
  225. &fFlag
  226. );
  227. BAIL_ON_FAILURE(hr);
  228. if (fFlag) {
  229. dwFlags |= ADS_NO_AUTHENTICATION;
  230. }
  231. hr = _pPropMgr->GetBoolProperty(
  232. L"__PADS_READONLY_SERVER",
  233. &fFlag
  234. );
  235. BAIL_ON_FAILURE(hr);
  236. if (fFlag) {
  237. dwFlags |= ADS_READONLY_SERVER;
  238. }
  239. hr = _pPropMgr->GetBoolProperty(
  240. L"__PADS_PROMPT_CREDENTIALS",
  241. &fFlag
  242. );
  243. BAIL_ON_FAILURE(hr);
  244. if (fFlag) {
  245. dwFlags |= ADS_PROMPT_CREDENTIALS;
  246. }
  247. hr = _pPropMgr->GetBoolProperty(
  248. L"__PADS_SERVER_BIND",
  249. &fFlag
  250. );
  251. BAIL_ON_FAILURE(hr);
  252. if (fFlag) {
  253. dwFlags |= ADS_SERVER_BIND;
  254. }
  255. hr = _pPropMgr->GetBoolProperty(
  256. L"__PADS_FAST_BIND",
  257. &fFlag
  258. );
  259. BAIL_ON_FAILURE(hr);
  260. if (fFlag) {
  261. dwFlags |= ADS_FAST_BIND;
  262. }
  263. hr = _pPropMgr->GetBoolProperty(
  264. L"__PADS_USE_SIGNING",
  265. &fFlag
  266. );
  267. BAIL_ON_FAILURE(hr);
  268. if (fFlag) {
  269. dwFlags |= ADS_USE_SIGNING;
  270. }
  271. hr = _pPropMgr->GetBoolProperty(
  272. L"__PADS_USE_SEALING",
  273. &fFlag
  274. );
  275. BAIL_ON_FAILURE(hr);
  276. if (fFlag) {
  277. dwFlags |= ADS_USE_SEALING;
  278. }
  279. // hr = _pPropMgr->GetLongProperty(L"__USE_ENCRYPTION", &lVal);
  280. // BAIL_ON_FAILURE(hr);
  281. // Spec needs to be resolved before we can do this.
  282. //
  283. // Always do this as this is what tells us we are in UMI mode.
  284. //
  285. dwFlags |= ADS_AUTH_RESERVED;
  286. _pCredentials = new CCredentials(
  287. pszUserName,
  288. pszPassword,
  289. dwFlags
  290. );
  291. if (!_pCredentials) {
  292. BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
  293. }
  294. }
  295. //
  296. // In the future we might want to add some sanity check before
  297. // making this call. That might save some network traffic in the
  298. // rare cases.
  299. // Note that currently, we always get the object and then we compare
  300. // the handles to see if we have inded got an object on the same
  301. // connection (and fail appropriately if not).
  302. //
  303. hr = ::GetObject(
  304. pszLdapPath,
  305. *_pCredentials,
  306. (LPVOID *) &pUnk
  307. ) ;
  308. BAIL_ON_FAILURE(hr);
  309. //
  310. // By default we get back IADs, so we need to QI for intf.
  311. //
  312. hr = pUnk->QueryInterface(TargetIID, ppvRes);
  313. BAIL_ON_FAILURE(hr);
  314. //
  315. // At this point copy over the handle if applicable. If the handle is
  316. // already set, then we need to make sure we are using the same
  317. // connection.
  318. // If do not get the handle for whatever reason, we will use the
  319. // defaulted NULL value and in that case we wont save the handle or
  320. // compare the value.
  321. //
  322. hr = pUnk->QueryInterface(IID_IADsObjOptPrivate, (LPVOID *) &pPrivOpt);
  323. if (SUCCEEDED(hr)) {
  324. //
  325. // If we succeeded then we want to try and compare handles.
  326. //
  327. hr = pPrivOpt->GetOption(
  328. LDP_CACHE_ENTRY,
  329. (void*) &pLdapTmpHandle
  330. );
  331. }
  332. //
  333. // Reset hr just in case the above failed.
  334. //
  335. hr = S_OK;
  336. if (_fConnected) {
  337. //
  338. // Verify that the handles are the same.
  339. //
  340. if (_pLdapHandle
  341. && pLdapTmpHandle
  342. && (_pLdapHandle != pLdapTmpHandle)) {
  343. BAIL_ON_FAILURE(hr = E_ADS_BAD_PARAMETER);
  344. }
  345. }
  346. else {
  347. //
  348. // New connection.
  349. //
  350. if (pLdapTmpHandle) {
  351. _pLdapHandle = pLdapTmpHandle;
  352. _fConnected = TRUE;
  353. LdapCacheAddRef(_pLdapHandle);
  354. }
  355. }
  356. error:
  357. //
  358. // Release the ref in all cases. If QI failed that will del the obj.
  359. //
  360. if (pUnk) {
  361. pUnk->Release();
  362. }
  363. if (pPrivOpt) {
  364. pPrivOpt->Release();
  365. }
  366. if (FAILED(hr)) {
  367. //
  368. // Update the error status.
  369. //
  370. SetLastStatus(hr);
  371. hr = MapHrToUmiError(hr);
  372. if (*ppvRes) {
  373. //
  374. // We got the object but a subsequent operation failed.
  375. //
  376. *ppvRes = NULL;
  377. pUnk->Release();
  378. }
  379. }
  380. if (pszUserName) {
  381. FreeADsStr(pszUserName);
  382. }
  383. if (pszPassword) {
  384. FreeADsStr(pszPassword);
  385. }
  386. if (pszLdapPath) {
  387. FreeADsMem(pszLdapPath);
  388. }
  389. RRETURN(hr);
  390. }
  391. //
  392. // IUmiBaseObject methods.
  393. //
  394. STDMETHODIMP
  395. CLDAPConObject::GetLastStatus(
  396. ULONG uFlags,
  397. ULONG *puSpecificStatus,
  398. REFIID riid,
  399. LPVOID *pStatusObj
  400. )
  401. {
  402. if (pStatusObj) {
  403. *pStatusObj = NULL;
  404. }
  405. if (puSpecificStatus) {
  406. *puSpecificStatus = 0;
  407. }
  408. else {
  409. RRETURN(E_INVALIDARG);
  410. }
  411. if (uFlags) {
  412. RRETURN(UMI_E_INVALID_FLAGS);
  413. }
  414. *puSpecificStatus = _ulErrorStatus;
  415. RRETURN(S_OK);
  416. }
  417. STDMETHODIMP
  418. CLDAPConObject::GetInterfacePropList(
  419. ULONG uFlags,
  420. IUmiPropList **pPropList
  421. )
  422. {
  423. RRETURN(_pPropMgr->QueryInterface(IID_IUmiPropList, (void **) pPropList));
  424. }
  425. //
  426. // Methods defined on the proplist interface - none are implemented.
  427. // All the properties need to be set on the interface property list.
  428. //
  429. STDMETHODIMP
  430. CLDAPConObject::Put(
  431. IN LPCWSTR pszName,
  432. IN ULONG uFlags,
  433. IN UMI_PROPERTY_VALUES *pProp
  434. )
  435. {
  436. RRETURN(E_NOTIMPL);
  437. }
  438. STDMETHODIMP
  439. CLDAPConObject::Get(
  440. IN LPCWSTR pszName,
  441. IN ULONG uFlags,
  442. OUT UMI_PROPERTY_VALUES **pProp
  443. )
  444. {
  445. RRETURN(E_NOTIMPL);
  446. }
  447. STDMETHODIMP
  448. CLDAPConObject::GetAt(
  449. IN LPCWSTR pszName,
  450. IN ULONG uFlags,
  451. IN ULONG uBufferLength,
  452. OUT LPVOID pExisitingMem
  453. )
  454. {
  455. RRETURN(E_NOTIMPL);
  456. }
  457. STDMETHODIMP
  458. CLDAPConObject::Delete(
  459. IN LPCWSTR pszName,
  460. IN ULONG ulFlags
  461. )
  462. {
  463. RRETURN(E_NOTIMPL);
  464. }
  465. STDMETHODIMP
  466. CLDAPConObject::GetAs(
  467. IN LPCWSTR pszName,
  468. IN ULONG uFlags,
  469. IN ULONG uCoercionType,
  470. IN OUT UMI_PROPERTY_VALUES **pProp
  471. )
  472. {
  473. RRETURN(E_NOTIMPL);
  474. }
  475. STDMETHODIMP
  476. CLDAPConObject::FreeMemory(
  477. ULONG uReserved,
  478. LPVOID pMem
  479. )
  480. {
  481. if (pMem) {
  482. //
  483. // At this time this has to be a pUmiProperty. Ideally we should
  484. // tag this in some way so that we can check to make sure.
  485. //
  486. RRETURN(FreeUmiPropertyValues((UMI_PROPERTY_VALUES *)pMem));
  487. }
  488. RRETURN(S_OK);
  489. }
  490. STDMETHODIMP
  491. CLDAPConObject::GetProps(
  492. IN LPCWSTR* pszNames,
  493. IN ULONG uNameCount,
  494. IN ULONG uFlags,
  495. OUT UMI_PROPERTY_VALUES **pProps
  496. )
  497. {
  498. RRETURN(E_NOTIMPL);
  499. }
  500. HRESULT
  501. CLDAPConObject::PutProps(
  502. IN LPCWSTR* pszNames,
  503. IN ULONG uNameCount,
  504. IN ULONG uFlags,
  505. IN UMI_PROPERTY_VALUES *pProps
  506. )
  507. {
  508. RRETURN(E_NOTIMPL);
  509. }
  510. STDMETHODIMP
  511. CLDAPConObject::PutFrom(
  512. IN LPCWSTR pszName,
  513. IN ULONG uFlags,
  514. IN ULONG uBufferLength,
  515. IN LPVOID pExistingMem
  516. )
  517. {
  518. RRETURN(E_NOTIMPL);
  519. }