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.

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