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.

1609 lines
45 KiB

  1. //---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1995
  5. //
  6. // File: csession.cxx
  7. //
  8. // Contents: Microsoft OleDB/OleDS Session object for ADSI
  9. //
  10. //
  11. // History: 08-01-96 shanksh Created.
  12. //
  13. //----------------------------------------------------------------------------
  14. #include "oleds.hxx"
  15. #pragma hdrstop
  16. #include "atl.h"
  17. #include "row.hxx"
  18. //+---------------------------------------------------------------------------
  19. //
  20. // Function: CSessionObject::GetDataSource
  21. //
  22. // Synopsis: Retrieve an interface pointer on the session object
  23. //
  24. // Arguments:
  25. // riid, IID desired
  26. // ppDSO ptr to interface
  27. //
  28. //
  29. // Returns:
  30. // S_OK Session Object Interface returned
  31. // E_INVALIDARG ppDSO was NULL
  32. // E_NOINTERFACE IID not supported
  33. //
  34. // Modifies:
  35. //
  36. // History: 08-28-96 ShankSh Created.
  37. //
  38. //----------------------------------------------------------------------------
  39. STDMETHODIMP
  40. CSessionObject::GetDataSource (
  41. REFIID riid,
  42. IUnknown ** ppDSO
  43. )
  44. {
  45. //
  46. // Asserts
  47. //
  48. ADsAssert(_pDSO);
  49. if( ppDSO == NULL )
  50. RRETURN( E_INVALIDARG );
  51. RRETURN( _pDSO->QueryInterface(riid, (LPVOID*)ppDSO) );
  52. }
  53. //+---------------------------------------------------------------------------
  54. //
  55. // Function: CSessionObject::GetDataSource
  56. //
  57. // Synopsis: Retrieve an interface pointer on the session object
  58. //
  59. // Arguments:
  60. // riid, IID desired
  61. // ppDSO ptr to interface
  62. //
  63. //
  64. // Returns:
  65. // S_OK Session Object Interface returned
  66. // E_INVALIDARG ppDSO was NULL
  67. // E_NOINTERFACE IID not supported
  68. //
  69. // Modifies:
  70. //
  71. // History: 08-28-96 ShankSh Created.
  72. //
  73. //----------------------------------------------------------------------------
  74. STDMETHODIMP
  75. CSessionObject::OpenRowset(
  76. IUnknown * pUnkOuter,
  77. DBID * pTableID,
  78. DBID * pIndexID,
  79. REFIID riid,
  80. ULONG cPropertySets,
  81. DBPROPSET rgPropertySets[],
  82. IUnknown ** ppRowset
  83. )
  84. {
  85. // Don't pass any credentials (NULL)
  86. RRETURN( OpenRowsetWithCredentials(
  87. pUnkOuter,
  88. pTableID,
  89. pIndexID,
  90. riid,
  91. cPropertySets,
  92. rgPropertySets,
  93. NULL,
  94. ppRowset) );
  95. }
  96. //+---------------------------------------------------------------------------
  97. //
  98. // Function: CSessionObject::OpenRowsetWithCredentials
  99. //
  100. // Synopsis: Opens a rowset. Similar to OpenRowset but takes extra argument
  101. // CCredentials. This function is used when consumer calls
  102. // IBindResource::Bind requesting a rowset.
  103. //
  104. // Returns : HRESULT
  105. //
  106. //----------------------------------------------------------------------------
  107. HRESULT
  108. CSessionObject::OpenRowsetWithCredentials (
  109. IUnknown * pUnkOuter,
  110. DBID * pTableID,
  111. DBID * pIndexID,
  112. REFIID riid,
  113. ULONG cPropertySets,
  114. DBPROPSET rgPropertySets[],
  115. CCredentials * pCredentials,
  116. IUnknown ** ppRowset
  117. )
  118. {
  119. BOOL fWarning = FALSE;
  120. CRowProvider *pRowProvider = NULL;
  121. DWORD cAttrs = 1;
  122. BOOL *pbMultiValue = NULL;
  123. LPWSTR *pAttrs = NULL;
  124. //
  125. // Check in-params and NULL out-params in case of error
  126. //
  127. if( ppRowset )
  128. *ppRowset = NULL;
  129. if( !pTableID && !pIndexID )
  130. RRETURN( E_INVALIDARG );
  131. if( pIndexID )
  132. RRETURN( DB_E_NOINDEX );
  133. //
  134. // Check the PropertySets
  135. //
  136. if( cPropertySets > 0 && !rgPropertySets )
  137. RRETURN ( E_INVALIDARG );
  138. for(ULONG i=0; i<cPropertySets; i++) {
  139. if( rgPropertySets[i].cProperties && !rgPropertySets[i].rgProperties )
  140. RRETURN ( E_INVALIDARG );
  141. }
  142. //
  143. // pwszName field represents the ADsPath of the Directory we have to open;
  144. // Make sure pwszName is meaningful
  145. //
  146. if( !pTableID || pTableID->eKind != DBKIND_NAME ||
  147. !pTableID->uName.pwszName || !(*(pTableID->uName.pwszName)) )
  148. RRETURN( DB_E_NOTABLE );
  149. if( pUnkOuter )//&& !InlineIsEqualGUID(riid, IID_IUnknown) )
  150. RRETURN( DB_E_NOAGGREGATION );
  151. if( riid == IID_NULL )
  152. RRETURN( E_NOINTERFACE );
  153. //
  154. // By default, we use credentials stored in member variable _Credentials
  155. // for binding. Buf if caller passed any credentials through pCredentials,
  156. // these take precedence. This also means that we need to store these
  157. // credentials in the CRowProvider object for future use -
  158. // e.g. GetRowFromHRow will use these credentials.
  159. //
  160. CCredentials * pCreds = &_Credentials;
  161. if( pCredentials )
  162. pCreds = pCredentials;
  163. //
  164. // If integrated security is being used, impersonate the caller
  165. //
  166. BOOL fImpersonating;
  167. fImpersonating = FALSE;
  168. if(_pDSO->IsIntegratedSecurity())
  169. {
  170. HANDLE ThreadToken = _pDSO->GetThreadToken();
  171. ASSERT(ThreadToken != NULL);
  172. if (ThreadToken)
  173. {
  174. if (!ImpersonateLoggedOnUser(ThreadToken))
  175. RRETURN(E_FAIL);
  176. fImpersonating = TRUE;
  177. }
  178. else
  179. RRETURN(E_FAIL);
  180. }
  181. HRESULT hr = GetDSInterface(
  182. pTableID->uName.pwszName,
  183. *pCreds,
  184. IID_IDirectorySearch,
  185. (void **)&_pDSSearch);
  186. if (fImpersonating)
  187. {
  188. RevertToSelf();
  189. fImpersonating = FALSE;
  190. }
  191. if( FAILED(hr) )
  192. RRETURN( hr );
  193. //
  194. // Get ColumnsInfo based on the list of attributes that we want to be
  195. // returned. GetDefaultColumnInfo cleansup memory on failure.
  196. //
  197. ULONG cColumns = 0;
  198. DBCOLUMNINFO * prgInfo = NULL;
  199. WCHAR * pStringBuffer = NULL;
  200. hr = GetDefaultColumnInfo(&cColumns, &prgInfo, &pStringBuffer);
  201. if( FAILED(hr) )
  202. RRETURN( hr );
  203. // Store the properties (which must be in the rowset property group) in
  204. // the property object. OpenRowset is different from methods like
  205. // ICOmmand::SetProperties and ISessionProperties::SetProperties in that
  206. // it returns DB_E_ERROSOCCURRED if any property which is REQUIRED could
  207. // not be set and DB_S_ERROROCCURRED if any property that is OPTIONAL
  208. // could not be set. ICommand::SetProperties returns DB_E_ERROSOCCURRED
  209. // if all properties could not be set and DB_S_ERROSOCCURRED if some
  210. // property could not be set i.e, DBPROPOPTIONS (REQUIRED or OPTIONAL) is
  211. // ignored.
  212. // Use PROPSET_COMMAND as the bitmask below since the properties that are
  213. // going to be set are in the rowset property group. These properties that
  214. // are stored in the property object cannot be retrieved by the client
  215. // since GetProperties on a session object will only return properties in
  216. // the session property group.
  217. hr = _pUtilProp->SetProperties(
  218. cPropertySets,
  219. rgPropertySets,
  220. PROPSET_COMMAND
  221. );
  222. if( (DB_E_ERRORSOCCURRED == hr) || (DB_S_ERRORSOCCURRED == hr) )
  223. // check if a required property could not be set
  224. {
  225. ULONG i, j;
  226. for(i = 0; i < cPropertySets; i++)
  227. for(j = 0; j < rgPropertySets[i].cProperties; j++)
  228. if( rgPropertySets[i].rgProperties[j].dwStatus !=
  229. DBPROPSTATUS_OK )
  230. if( rgPropertySets[i].rgProperties[j].dwOptions !=
  231. DBPROPOPTIONS_OPTIONAL )
  232. {
  233. BAIL_ON_FAILURE( hr = DB_E_ERRORSOCCURRED );
  234. }
  235. else
  236. fWarning = TRUE;
  237. // if we get here, then there was all required properties were set
  238. // successfully. However, hr could still be DB_ERRORSOCCURRED if all
  239. // properties were optional and all of them could not be set. This
  240. // condition is not an error for OpenRowset as noted in the comment
  241. // above. Hence reset hr to S_OK.
  242. hr = S_OK;
  243. }
  244. // we still need to catch other errors like E_INAVLIDARG
  245. BAIL_ON_FAILURE(hr);
  246. hr = SetSearchPrefs();
  247. BAIL_ON_FAILURE( hr );
  248. //
  249. // Create RowProvider object to pass to rowset code
  250. //
  251. pbMultiValue = (BOOL *)AllocADsMem(sizeof(BOOL));
  252. pAttrs = (LPWSTR *)AllocADsMem(cAttrs * sizeof(LPWSTR));
  253. if( pAttrs )
  254. pAttrs[0] = AllocADsStr(L"ADsPath");
  255. if( !pAttrs || !pAttrs[0] || !pbMultiValue )
  256. BAIL_ON_FAILURE( hr=E_OUTOFMEMORY );
  257. *pbMultiValue = FALSE;
  258. _pDSSearch->AddRef();
  259. // Is this an NDS path? If so, set filter appropriately. Fix for #286560.
  260. WCHAR lpszProgId[MAX_PATH];
  261. BOOL fIsNds;
  262. hr = CopyADsProgId(pTableID->uName.pwszName, lpszProgId);
  263. BAIL_ON_FAILURE( hr );
  264. if( !wcscmp(L"NDS", lpszProgId) )
  265. fIsNds = TRUE;
  266. else
  267. fIsNds = FALSE;
  268. hr = CRowProvider::CreateRowProvider(
  269. _pDSSearch,
  270. NULL,
  271. pAttrs,
  272. cAttrs,
  273. cColumns,
  274. prgInfo,
  275. pStringBuffer,
  276. IID_IRowProvider,
  277. pbMultiValue,
  278. TRUE,
  279. pCreds,
  280. (void **) &pRowProvider
  281. );
  282. BAIL_ON_FAILURE( hr );
  283. //
  284. // RowProvider responsible for deallocation
  285. //
  286. pbMultiValue = NULL;
  287. hr= CRowset::CreateRowset(
  288. pRowProvider,
  289. (LPUNKNOWN)(IAccessor FAR *)this ,
  290. this,
  291. NULL,
  292. cPropertySets,
  293. rgPropertySets,
  294. 0,
  295. NULL,
  296. TRUE, // ADsPath is requested
  297. FALSE, // not all attributes are requested
  298. riid,
  299. ppRowset
  300. );
  301. BAIL_ON_FAILURE( hr );
  302. error:
  303. if( _pDSSearch ) {
  304. _pDSSearch->Release();
  305. _pDSSearch = NULL;
  306. }
  307. if( pRowProvider )
  308. pRowProvider->Release();
  309. if( prgInfo )
  310. _pIMalloc->Free(prgInfo);
  311. if( pStringBuffer )
  312. _pIMalloc->Free(pStringBuffer);
  313. if( pbMultiValue )
  314. FreeADsMem(pbMultiValue);
  315. if (pAttrs)
  316. {
  317. for (i = 0; i < cAttrs; i++)
  318. {
  319. if (pAttrs[i])
  320. FreeADsStr(pAttrs[0]);
  321. }
  322. FreeADsMem(pAttrs);
  323. }
  324. if( FAILED(hr) )
  325. RRETURN( hr );
  326. else if( fWarning )
  327. RRETURN( DB_S_ERRORSOCCURRED );
  328. else
  329. RRETURN( hr );
  330. }
  331. //+---------------------------------------------------------------------------
  332. //
  333. // Function: CSessionObject::GetProperties
  334. //
  335. // Synopsis: Returns current settings of all properties in the DBPROPFLAGS_SESSION property
  336. // group
  337. //
  338. // Arguments:
  339. // cPropertySets count of restiction guids
  340. // rgPropertySets restriction guids
  341. // pcProperties count of properties returned
  342. // prgProperties property information returned
  343. //
  344. // Returns:
  345. // S_OK Session Object Interface returned
  346. // E_INVALIDARG pcProperties or prgPropertyInfo was NULL
  347. // E_OUTOFMEMORY Out of memory
  348. //
  349. //
  350. // Modifies:
  351. //
  352. // History: 08-28-96 ShankSh Created.
  353. //
  354. //----------------------------------------------------------------------------
  355. STDMETHODIMP
  356. CSessionObject::GetProperties(
  357. ULONG cPropIDSets,
  358. const DBPROPIDSET rgPropIDSets[],
  359. ULONG * pcPropSets,
  360. DBPROPSET ** pprgPropSets
  361. )
  362. {
  363. //
  364. // Asserts
  365. //
  366. ADsAssert(_pUtilProp);
  367. //
  368. // Check in-params and NULL out-params in case of error
  369. //
  370. HRESULT hr = _pUtilProp->GetPropertiesArgChk(
  371. cPropIDSets,
  372. rgPropIDSets,
  373. pcPropSets,
  374. pprgPropSets,
  375. PROPSET_SESSION);
  376. if( FAILED(hr) )
  377. RRETURN( hr );
  378. //
  379. // Just pass this call on to the utility object that manages our properties
  380. //
  381. RRETURN( _pUtilProp->GetProperties(
  382. cPropIDSets,
  383. rgPropIDSets,
  384. pcPropSets,
  385. pprgPropSets,
  386. PROPSET_SESSION) );
  387. }
  388. //+---------------------------------------------------------------------------
  389. //
  390. // Function: CSessionObject::SetProperties
  391. //
  392. // Synopsis: Set properties in the DBPROPFLAGS_SESSION property group
  393. //
  394. // Arguments:
  395. // cProperties
  396. // rgProperties
  397. //
  398. // Returns:
  399. // S_OK Session Object Interface returned
  400. // E_INVALIDARG pcProperties or prgPropertyInfo was NULL
  401. // E_OUTOFMEMORY Out of memory
  402. //
  403. // Modifies:
  404. //
  405. // History: 08-28-96 ShankSh Created.
  406. //
  407. //----------------------------------------------------------------------------
  408. STDMETHODIMP
  409. CSessionObject::SetProperties(
  410. ULONG cPropertySets,
  411. DBPROPSET rgPropertySets[]
  412. )
  413. {
  414. //
  415. // Asserts
  416. //
  417. ADsAssert(_pUtilProp);
  418. //
  419. // Just pass this call on to the utility object that manages our properties
  420. //
  421. RRETURN( _pUtilProp->SetProperties(
  422. cPropertySets,
  423. rgPropertySets,
  424. PROPSET_SESSION) );
  425. }
  426. //+---------------------------------------------------------------------------
  427. //
  428. // Function: CSessionObject::CreateCommand
  429. //
  430. // Synopsis: Creates a brand new command and returns requested interface
  431. //
  432. // Arguments:
  433. // pUnkOuter outer Unknown
  434. // riid, IID desired
  435. // ppCommand ptr to interface
  436. //
  437. //
  438. // Returns:
  439. // S_OK Command Object Interface returned
  440. // E_INVALIDARG ppCommand was NULL
  441. // E_NOINTERFACE IID not supported
  442. //
  443. // Modifies:
  444. //
  445. // History: 08-28-96 ShankSh Created.
  446. //
  447. //----------------------------------------------------------------------------
  448. STDMETHODIMP
  449. CSessionObject::CreateCommand(
  450. IUnknown * pUnkOuter,
  451. REFIID riid,
  452. IUnknown ** ppCommand
  453. )
  454. {
  455. CCommandObject* pCommand = NULL;
  456. HRESULT hr;
  457. //
  458. // check in-params and NULL out-params in case of error
  459. //
  460. if( ppCommand )
  461. *ppCommand = NULL;
  462. else
  463. RRETURN( E_INVALIDARG );
  464. if( pUnkOuter )//&& !InlineIsEqualGUID(riid, IID_IUnknown) )
  465. RRETURN( DB_E_NOAGGREGATION );
  466. //
  467. // open a CCommand object
  468. //
  469. pCommand = new CCommandObject(pUnkOuter);
  470. if( !pCommand )
  471. RRETURN( E_OUTOFMEMORY );
  472. //
  473. // initialize the object
  474. //
  475. if( !pCommand->FInit(this, _Credentials) ) {
  476. delete pCommand;
  477. RRETURN( E_OUTOFMEMORY );
  478. }
  479. //
  480. // get requested interface pointer on DBSession
  481. //
  482. hr = pCommand->QueryInterface(riid, (void **)ppCommand);
  483. if( FAILED( hr ) ) {
  484. delete pCommand;
  485. RRETURN( hr );
  486. }
  487. pCommand->Release();
  488. //
  489. // all went well
  490. //
  491. RRETURN( S_OK );
  492. }
  493. //+---------------------------------------------------------------------------
  494. //
  495. // Function: CSessionObject::GetDefaultColumnInfo
  496. //
  497. // Synopsis:
  498. //
  499. // Arguments:
  500. //
  501. // Returns:
  502. //
  503. //
  504. // Modifies:
  505. //
  506. // History: 08-28-96 ShankSh Created.
  507. //
  508. //----------------------------------------------------------------------------
  509. STDMETHODIMP
  510. CSessionObject::GetDefaultColumnInfo(
  511. ULONG * pcColumns,
  512. DBCOLUMNINFO ** prgInfo,
  513. OLECHAR ** ppStringBuffer
  514. )
  515. {
  516. //
  517. // Asserts
  518. //
  519. ADsAssert(_pIMalloc);
  520. ADsAssert(pcColumns);
  521. ADsAssert(prgInfo);
  522. ADsAssert(ppStringBuffer);
  523. //
  524. // Allcoate memory for the Bookmark and ADsPath column
  525. //
  526. *prgInfo = (DBCOLUMNINFO*)_pIMalloc->Alloc(2 * sizeof(DBCOLUMNINFO));
  527. *ppStringBuffer = (WCHAR*)_pIMalloc->Alloc((wcslen(L"ADsPath") + 1) * sizeof(WCHAR));
  528. //
  529. // Free memory on a failure
  530. //
  531. if( !(*prgInfo) )
  532. RRETURN( E_OUTOFMEMORY );
  533. if( !(*ppStringBuffer) ) {
  534. _pIMalloc->Free(*prgInfo);
  535. *prgInfo = NULL;
  536. RRETURN( E_OUTOFMEMORY );
  537. }
  538. //
  539. // Initialize the memory
  540. //
  541. ZeroMemory(*prgInfo, 2 * sizeof(DBCOLUMNINFO));
  542. ZeroMemory(*ppStringBuffer, (wcslen(L"ADsPath") + 1) * sizeof(WCHAR));
  543. wcscpy(*ppStringBuffer, OLESTR("ADsPath"));
  544. //
  545. // Fill up the Bookmark column
  546. //
  547. *pcColumns = 2;
  548. (*prgInfo)[0].pwszName = NULL;
  549. (*prgInfo)[0].pTypeInfo = NULL;
  550. (*prgInfo)[0].iOrdinal = 0;
  551. (*prgInfo)[0].ulColumnSize = sizeof(ULONG);
  552. (*prgInfo)[0].wType = DBTYPE_UI4;
  553. (*prgInfo)[0].bPrecision = 10;
  554. (*prgInfo)[0].bScale = (BYTE) ~ 0;
  555. (*prgInfo)[0].columnid.eKind = DBKIND_GUID_PROPID;
  556. (*prgInfo)[0].columnid.uGuid.guid = DBCOL_SPECIALCOL;
  557. (*prgInfo)[0].columnid.uName.ulPropid = 2;
  558. (*prgInfo)[0].dwFlags = DBCOLUMNFLAGS_ISBOOKMARK |
  559. DBCOLUMNFLAGS_ISFIXEDLENGTH;
  560. //
  561. // Fill up the ADsPath column
  562. //
  563. (*prgInfo)[1].pwszName = *ppStringBuffer;
  564. (*prgInfo)[1].pTypeInfo = NULL;
  565. (*prgInfo)[1].iOrdinal = 1;
  566. (*prgInfo)[1].ulColumnSize = (ULONG)256;
  567. (*prgInfo)[1].wType = DBTYPE_WSTR|DBTYPE_BYREF;
  568. (*prgInfo)[1].bPrecision = (BYTE) ~ 0;
  569. (*prgInfo)[1].bScale = (BYTE) ~ 0;
  570. (*prgInfo)[1].columnid.eKind = DBKIND_NAME;
  571. (*prgInfo)[1].columnid.uName.pwszName = *ppStringBuffer;
  572. (*prgInfo)[1].columnid.uGuid.guid = GUID_NULL;
  573. (*prgInfo)[1].dwFlags = DBCOLUMNFLAGS_ISNULLABLE;
  574. RRETURN( S_OK );
  575. }
  576. #if (!defined(BUILD_FOR_NT40))
  577. //IBindResource::Bind
  578. //+---------------------------------------------------------------------------
  579. //
  580. // Function: CSessionObject::CSessionObject
  581. //
  582. // Synopsis: Constructor
  583. //
  584. // Arguments:
  585. //
  586. // Returns:
  587. //
  588. // Modifies:
  589. //
  590. // History: 09-17-1998 mgorti Created.
  591. //
  592. //----------------------------------------------------------------------------
  593. HRESULT CSessionObject::Bind(
  594. IUnknown * punkOuter,
  595. LPCOLESTR pwszURL,
  596. DBBINDURLFLAG dwBindFlags,
  597. REFGUID rguid,
  598. REFIID riid,
  599. IAuthenticate * pAuthenticate,
  600. DBIMPLICITSESSION * pImplSession,
  601. DWORD * pdwBindStatus,
  602. IUnknown ** ppUnk
  603. )
  604. {
  605. HRESULT hr = S_OK;
  606. CComBSTR bstrNewURL;
  607. TRYBLOCK
  608. //Initialize return arguments
  609. if (pdwBindStatus)
  610. *pdwBindStatus = 0;
  611. if (ppUnk)
  612. *ppUnk = NULL;
  613. if (pImplSession)
  614. pImplSession->pSession = NULL;
  615. //if caller passed a null value for dwBindFlags,
  616. //get them from initialization properties.
  617. if (dwBindFlags == 0)
  618. dwBindFlags = BindFlagsFromDbProps();
  619. //Generic argument validation
  620. hr = ValidateBindArgs(punkOuter,
  621. pwszURL,
  622. dwBindFlags,
  623. rguid,
  624. riid,
  625. pAuthenticate,
  626. pImplSession,
  627. pdwBindStatus,
  628. ppUnk);
  629. BAIL_ON_FAILURE(hr);
  630. //Fill in the pImplSession struct.
  631. if (pImplSession)
  632. {
  633. // Our session doesn't support aggregation.
  634. if (pImplSession->pUnkOuter != NULL)
  635. BAIL_ON_FAILURE(hr = DB_E_NOAGGREGATION);
  636. hr = QueryInterface(*pImplSession->piid,
  637. (void**)&(pImplSession->pSession));
  638. if (FAILED(hr))
  639. BAIL_ON_FAILURE(hr = E_NOINTERFACE );
  640. }
  641. //Specific validation checks
  642. //We are currently a read-only provider
  643. if (dwBindFlags & DBBINDURLFLAG_WRITE)
  644. BAIL_ON_FAILURE(hr = DB_E_READONLY);
  645. //We currently don't support aggregation
  646. if (punkOuter != NULL)
  647. BAIL_ON_FAILURE (hr = DB_E_NOAGGREGATION);
  648. //We don't support the following flags
  649. if (dwBindFlags & DBBINDURLFLAG_ASYNCHRONOUS)
  650. BAIL_ON_FAILURE(hr = DB_E_ASYNCNOTSUPPORTED);
  651. if (dwBindFlags & DBBINDURLFLAG_OUTPUT ||
  652. dwBindFlags & DBBINDURLFLAG_RECURSIVE ||
  653. dwBindFlags & DBBINDURLFLAG_DELAYFETCHSTREAM ||
  654. dwBindFlags & DBBINDURLFLAG_DELAYFETCHCOLUMNS)
  655. BAIL_ON_FAILURE(hr = E_INVALIDARG);
  656. //Now Try to Bind.
  657. if (InlineIsEqualGUID(rguid, DBGUID_ROW) ||
  658. InlineIsEqualGUID(rguid, DBGUID_ROWSET))
  659. {
  660. //If the URL is not absolute, build the absolute URL
  661. //using the DBPROP_INIT_PROVIDERSTRING.
  662. if (! bIsAbsoluteURL(pwszURL))
  663. {
  664. hr = BuildAbsoluteURL (pwszURL, bstrNewURL);
  665. if (FAILED(hr))
  666. BAIL_ON_FAILURE(hr = E_INVALIDARG);
  667. }
  668. else
  669. bstrNewURL = pwszURL;
  670. if ( InlineIsEqualGUID(rguid, DBGUID_ROW) )
  671. {
  672. hr = BindToRow(punkOuter,
  673. (PWCHAR)bstrNewURL,
  674. pAuthenticate,
  675. dwBindFlags,
  676. riid,
  677. ppUnk);
  678. }
  679. else
  680. {
  681. hr = BindToRowset(punkOuter,
  682. (PWCHAR)bstrNewURL,
  683. pAuthenticate,
  684. dwBindFlags,
  685. riid,
  686. ppUnk);
  687. }
  688. BAIL_ON_FAILURE(hr);
  689. }
  690. else if (InlineIsEqualGUID(rguid, DBGUID_DSO))
  691. {
  692. ADsAssert(_pDSO);
  693. hr = BindToDataSource(
  694. punkOuter,
  695. pwszURL,
  696. pAuthenticate,
  697. dwBindFlags,
  698. riid,
  699. ppUnk
  700. );
  701. BAIL_ON_FAILURE (hr);
  702. }
  703. else if (InlineIsEqualGUID(rguid, DBGUID_SESSION))
  704. {
  705. hr = QueryInterface(riid, (void**)ppUnk);
  706. BAIL_ON_FAILURE (hr);
  707. }
  708. else
  709. BAIL_ON_FAILURE(hr = E_INVALIDARG);
  710. //Fix for bug Raid-X5#83386 - spec change
  711. //If caller specified any DENY semantics,
  712. //set warning status and return value, since
  713. //we don't support these.
  714. if (dwBindFlags & DBBINDURLFLAG_SHARE_DENY_READ ||
  715. dwBindFlags & DBBINDURLFLAG_SHARE_DENY_WRITE ||
  716. dwBindFlags & DBBINDURLFLAG_SHARE_EXCLUSIVE)
  717. {
  718. if (pdwBindStatus)
  719. *pdwBindStatus = DBBINDURLSTATUS_S_DENYNOTSUPPORTED;
  720. BAIL_ON_FAILURE (hr = DB_S_ERRORSOCCURRED);
  721. }
  722. CATCHBLOCKBAIL(hr)
  723. error:
  724. RRETURN(hr);
  725. }
  726. #endif
  727. //+---------------------------------------------------------------------------
  728. //
  729. // Function: CSessionObject::CSessionObject
  730. //
  731. // Synopsis: Constructor
  732. //
  733. // Arguments:
  734. //
  735. // Returns:
  736. //
  737. // Modifies:
  738. //
  739. // History: 08-28-96 ShankSh Created.
  740. //
  741. //----------------------------------------------------------------------------
  742. CSessionObject::CSessionObject(
  743. LPUNKNOWN pUnkOuter
  744. )
  745. {
  746. //
  747. // Initialize simple member vars
  748. //
  749. _pUnkOuter = pUnkOuter ? pUnkOuter : (IGetDataSource FAR *)this;
  750. _cCommandsOpen = 0;
  751. _pUtilProp = NULL;
  752. _pDSSearch = NULL;
  753. _pIMalloc = NULL;
  754. _pDSO = NULL;
  755. ENLIST_TRACKING(CSessionObject);
  756. }
  757. //+---------------------------------------------------------------------------
  758. //
  759. // Function: CSessionObject::~CSessionObject
  760. //
  761. // Synopsis: Destructor
  762. //
  763. // Arguments:
  764. //
  765. // Returns:
  766. //
  767. // Modifies:
  768. //
  769. // History: 08-28-96 ShankSh Created.
  770. //
  771. //----------------------------------------------------------------------------
  772. CSessionObject::~CSessionObject( )
  773. {
  774. //
  775. // Free properties management object
  776. //
  777. delete _pUtilProp;
  778. if( _pIMalloc )
  779. _pIMalloc->Release();
  780. if( _pDSO ) {
  781. _pDSO->DecrementOpenSessions();
  782. _pDSO->Release();
  783. }
  784. }
  785. //+---------------------------------------------------------------------------
  786. //
  787. // Function: CSessionObject::FInit
  788. //
  789. // Synopsis: Initialize the session Object
  790. //
  791. // Arguments:
  792. //
  793. // Returns:
  794. // TRUE Initialization succeeded
  795. // FALSE Initialization failed
  796. //
  797. // Modifies:
  798. //
  799. // History: 08-28-96 ShankSh Created.
  800. //
  801. //----------------------------------------------------------------------------
  802. BOOL CSessionObject::FInit(
  803. CDSOObject * pDSO,
  804. CCredentials & Credentials
  805. )
  806. {
  807. HRESULT hr;
  808. //
  809. // Asserts
  810. //
  811. ADsAssert(pDSO);
  812. ADsAssert(&Credentials);
  813. //
  814. // Allocate properties management object
  815. //
  816. _pUtilProp = new CUtilProp();
  817. if( !_pUtilProp )
  818. return FALSE;
  819. hr = _pUtilProp->FInit(&Credentials);
  820. BAIL_ON_FAILURE(hr);
  821. //
  822. // IMalloc->Alloc is the way we have to allocate memory for out parameters
  823. //
  824. hr = CoGetMalloc(MEMCTX_TASK, &_pIMalloc);
  825. BAIL_ON_FAILURE(hr);
  826. //
  827. // Establish parent object pointer
  828. //
  829. _pDSO = pDSO;
  830. _Credentials = Credentials;
  831. _pDSO->AddRef();
  832. _pDSO->IncrementOpenSessions();
  833. return( TRUE );
  834. error:
  835. RRETURN( FALSE );
  836. }
  837. STDMETHODIMP
  838. CSessionObject::QueryInterface(REFIID iid, LPVOID FAR* ppv)
  839. {
  840. if( ppv == NULL )
  841. RRETURN( E_INVALIDARG );
  842. if( IsEqualIID(iid, IID_IUnknown) ) {
  843. *ppv = (IGetDataSource FAR *) this;
  844. }
  845. else if( IsEqualIID(iid, IID_IGetDataSource) ) {
  846. *ppv = (IGetDataSource FAR *) this;
  847. }
  848. else if( IsEqualIID(iid, IID_IOpenRowset) ) {
  849. *ppv = (IOpenRowset FAR *) this;
  850. }
  851. else if( IsEqualIID(iid, IID_ISessionProperties) ) {
  852. *ppv = (ISessionProperties FAR *) this;
  853. }
  854. else if( IsEqualIID(iid, IID_IDBCreateCommand) ) {
  855. *ppv = (IDBCreateCommand FAR *) this;
  856. }
  857. #if (!defined(BUILD_FOR_NT40))
  858. else if( IsEqualIID(iid, IID_IBindResource) ) {
  859. *ppv = (IBindResource FAR *) this;
  860. }
  861. #endif
  862. else {
  863. *ppv = NULL;
  864. return E_NOINTERFACE;
  865. }
  866. AddRef();
  867. return NOERROR;
  868. }
  869. #if (!defined(BUILD_FOR_NT40))
  870. //+---------------------------------------------------------------------------
  871. //
  872. // Function: CSessionObject::ValidateBindArgs
  873. //
  874. // Synopsis: Validates IBindResource::Bind function arguments.
  875. //
  876. //----------------------------------------------------------------------------
  877. HRESULT CSessionObject::ValidateBindArgs(
  878. IUnknown * punkOuter,
  879. LPCOLESTR pwszURL,
  880. DBBINDURLFLAG dwBindFlags,
  881. REFGUID rguid,
  882. REFIID riid,
  883. IAuthenticate * pAuthenticate,
  884. DBIMPLICITSESSION * pImplSession,
  885. DWORD * pdwBindStatus,
  886. IUnknown ** ppUnk
  887. )
  888. {
  889. //General validation checks.
  890. if (pwszURL == NULL || InlineIsEqualGUID(rguid,GUID_NULL) ||
  891. InlineIsEqualGUID(riid, GUID_NULL) || ppUnk == NULL )
  892. RRETURN(E_INVALIDARG);
  893. if (pImplSession &&
  894. (pImplSession->pUnkOuter == NULL || pImplSession->piid == NULL))
  895. RRETURN(E_INVALIDARG);
  896. if (punkOuter && !InlineIsEqualGUID(riid, IID_IUnknown))
  897. RRETURN(DB_E_NOAGGREGATION);
  898. if (pImplSession && pImplSession->pUnkOuter &&
  899. pImplSession->piid &&
  900. !InlineIsEqualGUID(*pImplSession->piid, IID_IUnknown))
  901. RRETURN(DB_E_NOAGGREGATION);
  902. if (dwBindFlags & DBBINDURLFLAG_RECURSIVE)
  903. {
  904. //if DBBINDURLFLAG_RECURSIVE is set, at least one of the SHARE_DENY
  905. //flags must have been set.
  906. if (! ( (dwBindFlags & DBBINDURLFLAG_SHARE_DENY_READ) ||
  907. (dwBindFlags & DBBINDURLFLAG_SHARE_DENY_WRITE) ||
  908. (dwBindFlags & DBBINDURLFLAG_SHARE_EXCLUSIVE)
  909. )
  910. )
  911. RRETURN(E_INVALIDARG);
  912. }
  913. if (!(dwBindFlags & DBBINDURLFLAG_READ) &&
  914. !(dwBindFlags & DBBINDURLFLAG_WRITE) ) {
  915. // Must have either read or write access:
  916. RRETURN(E_INVALIDARG);
  917. }
  918. if (InlineIsEqualGUID(rguid, DBGUID_DSO) &&
  919. !((dwBindFlags & DBBINDURLFLAG_READ) ||
  920. (dwBindFlags & DBBINDURLFLAG_ASYNCHRONOUS) ||
  921. (dwBindFlags & DBBINDURLFLAG_WAITFORINIT)
  922. )
  923. )
  924. //if object type is DataSource, only the above flags are allowed
  925. RRETURN(E_INVALIDARG);
  926. if (InlineIsEqualGUID(rguid, DBGUID_SESSION) &&
  927. ! (dwBindFlags == DBBINDURLFLAG_READ))
  928. //if object type is Session, only DBBINDURLFLAG_READ is allowed
  929. RRETURN(E_INVALIDARG);
  930. if (InlineIsEqualGUID(rguid, DBGUID_ROWSET) &&
  931. ((dwBindFlags & DBBINDURLFLAG_DELAYFETCHCOLUMNS) ||
  932. (dwBindFlags & DBBINDURLFLAG_DELAYFETCHSTREAM)
  933. )
  934. )
  935. //if object type is Rowset, DELAYFETCHCOLUMNS and DELAYFETCHSTREAM
  936. //flags are disallowed.
  937. RRETURN ( E_INVALIDARG );
  938. if (InlineIsEqualGUID(rguid, DBGUID_STREAM) &&
  939. ((dwBindFlags & DBBINDURLFLAG_DELAYFETCHCOLUMNS) ||
  940. (dwBindFlags & DBBINDURLFLAG_DELAYFETCHSTREAM)
  941. )
  942. )
  943. //if object type is Stream, DELAYFETCHCOLUMNS and
  944. //DELAYFETCHSTREAM flags are disallowed.
  945. RRETURN(E_INVALIDARG);
  946. RRETURN(S_OK);
  947. }
  948. //+---------------------------------------------------------------------------
  949. //
  950. // Function: CSessionObject::BindToRow
  951. //
  952. // Synopsis: Given a URL, binds to that row object and returns the requested
  953. // interface.
  954. //
  955. //----------------------------------------------------------------------------
  956. HRESULT
  957. CSessionObject::BindToRow(
  958. IUnknown *punkOuter,
  959. LPCOLESTR pwszURL,
  960. IAuthenticate *pAuthenticate,
  961. DWORD dwBindFlags,
  962. REFIID riid,
  963. IUnknown** ppUnk
  964. )
  965. {
  966. CComObject<CRow> *pRow = NULL;
  967. auto_rel<IUnknown> pSession;
  968. auto_rel<IRow> pRowDelete;
  969. HRESULT hr = S_OK;
  970. hr = CComObject<CRow>::CreateInstance(&pRow);
  971. if (FAILED(hr))
  972. BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
  973. //To make sure we delete the row object in
  974. //case we encounter errors after this point.
  975. //Note: this version of auto_rel doesn't addref on assignment.
  976. pRowDelete = pRow;
  977. pRowDelete->AddRef();
  978. hr = QueryInterface(__uuidof(IUnknown), (void **)&pSession);
  979. if (FAILED(hr))
  980. BAIL_ON_FAILURE(hr = E_FAIL);
  981. //Initialize row and bind it to a Directory Object.
  982. hr = pRow->Initialize((PWSTR)pwszURL,
  983. (IUnknown *)pSession,
  984. pAuthenticate,
  985. dwBindFlags,
  986. FALSE, // not a tearoff
  987. FALSE, // don't get column info. from rowset
  988. &_Credentials,
  989. true);
  990. if (FAILED(hr))
  991. {
  992. if (INVALID_CREDENTIALS_ERROR(hr))
  993. {
  994. BAIL_ON_FAILURE(hr = DB_SEC_E_PERMISSIONDENIED);
  995. }
  996. else
  997. {
  998. BAIL_ON_FAILURE(hr = DB_E_NOTFOUND);
  999. }
  1000. }
  1001. hr = pRow->QueryInterface(riid, (void**)ppUnk);
  1002. if (FAILED(hr))
  1003. BAIL_ON_FAILURE (hr = E_NOINTERFACE);
  1004. error:
  1005. RRETURN ( hr );
  1006. }
  1007. //+---------------------------------------------------------------------------
  1008. //
  1009. // Function: CSessionObject::BindToRowset
  1010. //
  1011. // Synopsis: Given a URL, binds to a rowset object that has all its child
  1012. // nodes as rows and returns the requested interface on the rowset.
  1013. //
  1014. //----------------------------------------------------------------------------
  1015. HRESULT
  1016. CSessionObject::BindToRowset(
  1017. IUnknown *pUnkOuter,
  1018. LPCOLESTR pwszURL,
  1019. IAuthenticate *pAuthenticate,
  1020. DWORD dwBindFlags,
  1021. REFIID riid,
  1022. IUnknown** ppUnk
  1023. )
  1024. {
  1025. HRESULT hr;
  1026. DWORD fAuthFlags;
  1027. DBID tableID;
  1028. tableID.eKind = DBKIND_NAME;
  1029. tableID.uName.pwszName = (LPWSTR) pwszURL;
  1030. //Create the rowset.
  1031. // Fix for 351040. First try explicit credentials, then session object's
  1032. // credentials, then default credentials.
  1033. if(pAuthenticate)
  1034. {
  1035. CCredentials creds;
  1036. hr = GetCredentialsFromIAuthenticate(pAuthenticate, creds);
  1037. if (FAILED(hr))
  1038. BAIL_ON_FAILURE(hr = E_INVALIDARG);
  1039. fAuthFlags = creds.GetAuthFlags();
  1040. creds.SetAuthFlags(fAuthFlags |
  1041. ADS_SECURE_AUTHENTICATION);
  1042. hr = OpenRowsetWithCredentials(pUnkOuter, &tableID, NULL, riid,
  1043. 0, NULL, &creds, ppUnk);
  1044. }
  1045. if( (!pAuthenticate) || (INVALID_CREDENTIALS_ERROR(hr)) )
  1046. // try credentials in session object
  1047. hr = OpenRowset(pUnkOuter, &tableID, NULL, riid, 0, NULL, ppUnk);
  1048. if(INVALID_CREDENTIALS_ERROR(hr))
  1049. // try default credentials
  1050. {
  1051. CCredentials creds; // default credentials
  1052. fAuthFlags = creds.GetAuthFlags();
  1053. creds.SetAuthFlags(fAuthFlags |
  1054. ADS_SECURE_AUTHENTICATION);
  1055. hr = OpenRowsetWithCredentials(pUnkOuter, &tableID, NULL, riid,
  1056. 0, NULL, &creds, ppUnk);
  1057. }
  1058. BAIL_ON_FAILURE(hr);
  1059. RRETURN ( S_OK );
  1060. error:
  1061. RRETURN ( hr );
  1062. }
  1063. //+---------------------------------------------------------------------------
  1064. //
  1065. // Function: CSessionObject::BindFlagsFromDbProps
  1066. //
  1067. // Synopsis: Synthesizes bind flags from initialization properties
  1068. // DBPROP_INIT_MODE and DBPROP_INIT_BINDFLAGS
  1069. //
  1070. //----------------------------------------------------------------------------
  1071. DWORD CSessionObject::BindFlagsFromDbProps()
  1072. {
  1073. HRESULT hr = S_OK;
  1074. auto_rel<IDBProperties> pDBProp;
  1075. ULONG i, j, cPropertySets = 0;
  1076. DWORD dwMode = 0, dwBindFlags = 0, dwBindFlagProp = 0;
  1077. DWORD dwResult = 0;
  1078. hr = GetDataSource(__uuidof(IDBProperties), (IUnknown **)&pDBProp);
  1079. BAIL_ON_FAILURE(hr);
  1080. DBPROPID propids[2];
  1081. propids[0] = DBPROP_INIT_MODE;
  1082. propids[1] = DBPROP_INIT_BINDFLAGS;
  1083. DBPROPIDSET rgPropertyIDSets[1];
  1084. rgPropertyIDSets[0].rgPropertyIDs = propids;
  1085. rgPropertyIDSets[0].cPropertyIDs = 2;
  1086. rgPropertyIDSets[0].guidPropertySet = DBPROPSET_DBINIT;
  1087. DBPROPSET *prgPropertySets;
  1088. hr = pDBProp->GetProperties(
  1089. 1,
  1090. rgPropertyIDSets,
  1091. &cPropertySets,
  1092. &prgPropertySets);
  1093. if (hr == DB_E_ERRORSOCCURRED)
  1094. BAIL_ON_FAILURE(hr);
  1095. for (i = 0; i < cPropertySets; i++)
  1096. {
  1097. for (j = 0; j < prgPropertySets[i].cProperties; j++)
  1098. {
  1099. DBPROP *pProp = &prgPropertySets[i].rgProperties[j];
  1100. ADsAssert(pProp);
  1101. if (pProp->dwStatus == S_OK &&
  1102. pProp->dwPropertyID == DBPROP_INIT_MODE)
  1103. dwMode = V_I4(&pProp->vValue);
  1104. else if (pProp->dwStatus == S_OK &&
  1105. pProp->dwPropertyID == DBPROP_INIT_BINDFLAGS)
  1106. dwBindFlagProp = V_I4(&pProp->vValue);
  1107. else
  1108. continue;
  1109. }
  1110. }
  1111. //Now extract bind flags from dwMode and dwBindFlagProp
  1112. {
  1113. DWORD dwModeMask =
  1114. DB_MODE_READ |
  1115. DB_MODE_WRITE |
  1116. DB_MODE_READWRITE |
  1117. DB_MODE_SHARE_DENY_READ |
  1118. DB_MODE_SHARE_DENY_WRITE |
  1119. DB_MODE_SHARE_EXCLUSIVE |
  1120. DB_MODE_SHARE_DENY_NONE;
  1121. dwResult |= dwMode & dwModeMask;
  1122. if ( dwBindFlagProp & DB_BINDFLAGS_DELAYFETCHCOLUMNS ) {
  1123. dwBindFlags |= DBBINDURLFLAG_DELAYFETCHCOLUMNS;
  1124. }
  1125. if ( dwBindFlagProp & DB_BINDFLAGS_DELAYFETCHSTREAM ) {
  1126. dwBindFlags |= DBBINDURLFLAG_DELAYFETCHSTREAM;
  1127. }
  1128. if ( dwBindFlagProp & DB_BINDFLAGS_RECURSIVE ) {
  1129. dwBindFlags |= DBBINDURLFLAG_RECURSIVE;
  1130. }
  1131. if ( dwBindFlagProp & DB_BINDFLAGS_OUTPUT ) {
  1132. dwBindFlags |= DBBINDURLFLAG_OUTPUT;
  1133. }
  1134. dwResult |= dwBindFlagProp | dwBindFlags;
  1135. }
  1136. error:
  1137. for (i = 0; i < cPropertySets; i++)
  1138. {
  1139. for (j = 0; j < prgPropertySets[i].cProperties; j++)
  1140. {
  1141. DBPROP *pProp = &(prgPropertySets[i].rgProperties[j]);
  1142. ADsAssert(pProp);
  1143. FreeDBID(&pProp->colid);
  1144. VariantClear(&pProp->vValue);
  1145. }
  1146. CoTaskMemFree(prgPropertySets[i].rgProperties);
  1147. }
  1148. CoTaskMemFree(prgPropertySets);
  1149. RRETURN ( dwResult );
  1150. }
  1151. //+---------------------------------------------------------------------------
  1152. //
  1153. // Function: CSessionObject::BindToDataSource
  1154. //
  1155. // Synopsis: Initializes the DataSource object if necessary, Sets
  1156. // DBPROP_INIT_PROVIDERSTRING property and returns the requested
  1157. // interface on the datasource.
  1158. //
  1159. //----------------------------------------------------------------------------
  1160. HRESULT
  1161. CSessionObject::BindToDataSource(
  1162. IUnknown *pUnkOuter,
  1163. LPCOLESTR pwszURL,
  1164. IAuthenticate *pAuthenticate,
  1165. DWORD dwBindFlags,
  1166. REFIID riid,
  1167. IUnknown** ppUnk
  1168. )
  1169. {
  1170. HRESULT hr = S_OK;
  1171. auto_rel<IDBProperties> pDBProperties;
  1172. DBPROP props[1];
  1173. DBPROPSET rgPropertySets[1];
  1174. CComBSTR bstrURL(pwszURL);
  1175. //Initialize DBPROP_INIT_PROVIDERSTRING only if the
  1176. //URL is absolute.
  1177. if (bIsAbsoluteURL (pwszURL))
  1178. {
  1179. // Check if the datasource has already been initialized.
  1180. if (_pDSO->IsInitialized())
  1181. BAIL_ON_FAILURE(hr = DB_E_ALREADYINITIALIZED);
  1182. props[0].dwPropertyID = DBPROP_INIT_PROVIDERSTRING;
  1183. props[0].dwOptions = DBPROPOPTIONS_OPTIONAL;
  1184. props[0].vValue.vt = VT_BSTR;
  1185. props[0].vValue.bstrVal = (PWCHAR)bstrURL;
  1186. rgPropertySets[0].rgProperties = props;
  1187. rgPropertySets[0].cProperties = 1;
  1188. rgPropertySets[0].guidPropertySet = DBPROPSET_DBINIT;
  1189. hr = GetDataSource(
  1190. __uuidof(IDBProperties),
  1191. (IUnknown **)&pDBProperties
  1192. );
  1193. BAIL_ON_FAILURE(hr);
  1194. hr = pDBProperties->SetProperties(1, rgPropertySets);
  1195. BAIL_ON_FAILURE(hr);
  1196. }
  1197. // If consumer doesn't specify DBBINDURLFLAG_WAITFORINIT, it
  1198. // means consumer wants an initialized DSO
  1199. //
  1200. if (! (dwBindFlags & DBBINDURLFLAG_WAITFORINIT))
  1201. {
  1202. auto_rel<IDBInitialize> pDBInitialize;
  1203. hr = GetDataSource(__uuidof(IDBInitialize), (IUnknown **)&pDBInitialize);
  1204. BAIL_ON_FAILURE(hr);
  1205. hr = pDBInitialize->Initialize();
  1206. BAIL_ON_FAILURE(hr);
  1207. }
  1208. //Return the requested interface on the DSO.
  1209. hr = GetDataSource(riid, ppUnk);
  1210. BAIL_ON_FAILURE(hr);
  1211. error:
  1212. RRETURN ( hr );
  1213. }
  1214. //+---------------------------------------------------------------------------
  1215. //
  1216. // Function: CSessionObject::BuildAbsoluteURL
  1217. //
  1218. // Synopsis: Given a relative URL, builds absolute URL using the relative URL
  1219. // and the property DBPROP_INIT_PROVIDERSTRING.
  1220. //
  1221. //----------------------------------------------------------------------------
  1222. HRESULT
  1223. CSessionObject::BuildAbsoluteURL(
  1224. CComBSTR bstrLeaf,
  1225. CComBSTR& bstrAbsoluteURL
  1226. )
  1227. {
  1228. HRESULT hr = S_OK;
  1229. auto_rel<IDBProperties> pDBProp;
  1230. auto_rel<IADsPathname> pPathParent;
  1231. auto_rel<IADsPathname> pPathLeaf;
  1232. ULONG cPropertySets = 0;
  1233. long i, j, cElements = 0;
  1234. CComBSTR bstrParent;
  1235. DBPROPSET* prgPropertySets = NULL;
  1236. DBPROPID propids[1];
  1237. DBPROPIDSET rgPropertyIDSets[1];
  1238. hr = GetDataSource(__uuidof(IDBProperties), (IUnknown **)&pDBProp);
  1239. BAIL_ON_FAILURE(hr);
  1240. propids[0] = DBPROP_INIT_PROVIDERSTRING;
  1241. rgPropertyIDSets[0].rgPropertyIDs = propids;
  1242. rgPropertyIDSets[0].cPropertyIDs = 1;
  1243. rgPropertyIDSets[0].guidPropertySet = DBPROPSET_DBINIT;
  1244. hr = pDBProp->GetProperties(
  1245. 1,
  1246. rgPropertyIDSets,
  1247. &cPropertySets,
  1248. &prgPropertySets);
  1249. if (SUCCEEDED(hr) && cPropertySets == 1)
  1250. {
  1251. ADsAssert(prgPropertySets != NULL);
  1252. ADsAssert(prgPropertySets[0].rgProperties != NULL);
  1253. DBPROP* pProp = & (prgPropertySets[0].rgProperties[0]);
  1254. bstrParent = pProp->vValue.bstrVal;
  1255. }
  1256. // Build Absolute Path from Parent and leaf.
  1257. hr = CPathname::CreatePathname(
  1258. __uuidof(IADsPathname),
  1259. (void **)&pPathParent
  1260. );
  1261. BAIL_ON_FAILURE(hr);
  1262. hr = pPathParent->Set(bstrParent, ADS_SETTYPE_FULL);
  1263. BAIL_ON_FAILURE(hr);
  1264. if (bstrLeaf.Length() > 0)
  1265. {
  1266. hr = CPathname::CreatePathname(
  1267. __uuidof(IADsPathname),
  1268. (void **)&pPathLeaf
  1269. );
  1270. BAIL_ON_FAILURE(hr);
  1271. hr = pPathLeaf->Set(bstrLeaf, ADS_SETTYPE_DN);
  1272. BAIL_ON_FAILURE(hr);
  1273. hr = pPathLeaf->GetNumElements(&cElements);
  1274. BAIL_ON_FAILURE(hr);
  1275. //Add leaf elements in reverse order.
  1276. //Ex: if bstrLeaf = "CN=Administrator,CN=Users",
  1277. //we add CN=Users first.
  1278. for (i = cElements-1; i >= 0; i--)
  1279. {
  1280. CComBSTR bstrElement;
  1281. hr = pPathLeaf->GetElement(i, &bstrElement);
  1282. BAIL_ON_FAILURE(hr);
  1283. hr = pPathParent->AddLeafElement(bstrElement);
  1284. BAIL_ON_FAILURE(hr);
  1285. }
  1286. }
  1287. //Read back the fully built path name
  1288. hr = pPathParent->Retrieve(ADS_FORMAT_X500, &bstrAbsoluteURL);
  1289. BAIL_ON_FAILURE(hr);
  1290. error:
  1291. // Free memory allocated by GetProperties
  1292. for (i = 0; i < cPropertySets; i++)
  1293. {
  1294. for (j = 0; j < prgPropertySets[i].cProperties; j++)
  1295. {
  1296. DBPROP *pProp = &(prgPropertySets[i].rgProperties[j]);
  1297. ADsAssert(pProp);
  1298. // We should free the DBID in pProp, but we know that
  1299. // GetProperties always returns DB_NULLID and FreeDBID doesn't
  1300. // handle DB_NULLID. So, DBID is not freed here.
  1301. VariantClear(&pProp->vValue);
  1302. }
  1303. CoTaskMemFree(prgPropertySets[i].rgProperties);
  1304. }
  1305. CoTaskMemFree(prgPropertySets);
  1306. RRETURN(hr);
  1307. }
  1308. extern PROUTER_ENTRY g_pRouterHead;
  1309. extern CRITICAL_SECTION g_csRouterHeadCritSect;
  1310. //+---------------------------------------------------------------------------
  1311. //
  1312. // Function: CSessionObject::bIsAbsoluteURL
  1313. //
  1314. // Synopsis: If the given URL starts with any of the ADS provider prefixes,
  1315. // returns true. Returns false otherwise.
  1316. //
  1317. //----------------------------------------------------------------------------
  1318. bool
  1319. CSessionObject::bIsAbsoluteURL( LPCOLESTR pwszURL)
  1320. {
  1321. if (pwszURL == NULL)
  1322. return false;
  1323. //
  1324. // Make sure the router has been initialized
  1325. //
  1326. EnterCriticalSection(&g_csRouterHeadCritSect);
  1327. if (!g_pRouterHead) {
  1328. g_pRouterHead = InitializeRouter();
  1329. }
  1330. LeaveCriticalSection(&g_csRouterHeadCritSect);
  1331. for (PROUTER_ENTRY pProvider = g_pRouterHead;
  1332. pProvider != NULL;
  1333. pProvider = pProvider->pNext)
  1334. {
  1335. if (pProvider->szProviderProgId == NULL)
  1336. continue;
  1337. size_t strSize = wcslen(pProvider->szProviderProgId);
  1338. if ( _wcsnicmp(pwszURL, pProvider->szProviderProgId, strSize) == 0 )
  1339. return true;
  1340. }
  1341. // Given URL doesn't start with any of the ADSI provider prefixes.
  1342. return false;
  1343. }
  1344. #endif
  1345. //-----------------------------------------------------------------------------
  1346. // SetSearchPrefs
  1347. //
  1348. // Sets ADSI search preferences on the property object.
  1349. //
  1350. //-----------------------------------------------------------------------------
  1351. STDMETHODIMP
  1352. CSessionObject::SetSearchPrefs(
  1353. void
  1354. )
  1355. {
  1356. PROPSET *pPropSet;
  1357. PADS_SEARCHPREF_INFO pSearchPref = NULL;
  1358. HRESULT hr = S_OK;
  1359. ULONG i;
  1360. //
  1361. // Asserts
  1362. //
  1363. ADsAssert(_pUtilProp);
  1364. ADsAssert(_pDSSearch);
  1365. pPropSet = _pUtilProp->GetPropSetFromGuid(DBPROPSET_ADSISEARCH);
  1366. if( !pPropSet || !pPropSet->cProperties )
  1367. RRETURN( S_OK );
  1368. pSearchPref = (PADS_SEARCHPREF_INFO) AllocADsMem(
  1369. pPropSet->cProperties *
  1370. sizeof(ADS_SEARCHPREF_INFO)
  1371. );
  1372. if( !pSearchPref )
  1373. BAIL_ON_FAILURE( hr=E_OUTOFMEMORY );
  1374. for (i=0; i<pPropSet->cProperties; i++) {
  1375. hr = _pUtilProp->GetSearchPrefInfo(
  1376. pPropSet->pUPropInfo[i].dwPropertyID,
  1377. &pSearchPref[i]
  1378. );
  1379. BAIL_ON_FAILURE( hr );
  1380. }
  1381. hr = _pDSSearch->SetSearchPreference(
  1382. pSearchPref,
  1383. pPropSet->cProperties
  1384. );
  1385. _pUtilProp->FreeSearchPrefInfo(pSearchPref, pPropSet->cProperties);
  1386. BAIL_ON_FAILURE( hr );
  1387. error:
  1388. if( pSearchPref )
  1389. FreeADsMem(pSearchPref);
  1390. RRETURN( hr );
  1391. }