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.

1112 lines
40 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1994 - 2000.
  5. //
  6. // File: proprst.cxx
  7. //
  8. // Contents: This object handles rowset/command properties
  9. //
  10. // Classes: CMRowsetProps : public CUtlProps
  11. //
  12. // History: 10-28-97 danleg Created
  13. //
  14. //----------------------------------------------------------------------------
  15. #include <pch.cxx>
  16. #pragma hdrstop
  17. #define DBINITCONSTANTS
  18. #include <propglob.hxx>
  19. #undef DBINITCONSTANTS
  20. #include <ocidl.h>
  21. #include <ntverp.h>
  22. #include <proprst.hxx>
  23. #include <rstprop.hxx>
  24. #include "propinfr.h"
  25. #include "proptbl.hxx"
  26. //
  27. // Constants
  28. //
  29. static const LCID InvalidLCID = 0xFFFFFFFF;
  30. //
  31. // This array describes all the known rowset properties
  32. //
  33. const SPropDescription CMRowsetProps::aPropDescriptions[] = {
  34. { DBPROP_ABORTPRESERVE, FALSE, eNotSupported, -1 },
  35. { DBPROP_APPENDONLY, FALSE, eNotSupported, -1 },
  36. { DBPROP_BLOCKINGSTORAGEOBJECTS, FALSE, eDefaultFalse, -1 },
  37. { DBPROP_BOOKMARKS, TRUE, eLocatable, eid_PROPVAL_BOOKMARKS },
  38. { DBPROP_BOOKMARKSKIPPED, FALSE, eDefaultFalse, -1 },
  39. { DBPROP_BOOKMARKTYPE, FALSE, eNumeric, -1 },
  40. { DBPROP_CACHEDEFERRED, FALSE, eColumnProp, -1 },
  41. { DBPROP_CANFETCHBACKWARDS, FALSE, eLocatable, -1 },
  42. { DBPROP_CANHOLDROWS, TRUE, eHoldRows, eid_PROPVAL_CANHOLDROWS },
  43. { DBPROP_CANSCROLLBACKWARDS, FALSE, eLocatable, -1 },
  44. { DBPROP_CHANGEINSERTEDROWS, FALSE, eNotSupported, -1 },
  45. { DBPROP_COLUMNRESTRICT, FALSE, eDefaultFalse, -1 },
  46. // { DBPROP_CHAPTERED, FALSE, eChaptered, -1 },
  47. { DBPROP_COMMANDTIMEOUT, TRUE, eNumeric, eid_PROPVAL_COMMANDTIMEOUT },
  48. { DBPROP_COMMITPRESERVE, FALSE, eNotSupported, -1 },
  49. { DBPROP_DEFERRED, FALSE, eColumnProp, -1 },
  50. { DBPROP_DELAYSTORAGEOBJECTS, FALSE, eNotSupported, -1 },
  51. { DBPROP_IMMOBILEROWS, FALSE, eNotSupported, -1 },
  52. { DBPROP_LITERALBOOKMARKS, FALSE, eDefaultFalse, -1 },
  53. { DBPROP_LITERALIDENTITY, FALSE, eLocatable, -1 },
  54. { DBPROP_MAXOPENROWS, FALSE, eNumeric, -1 },
  55. { DBPROP_MAXPENDINGROWS, FALSE, eNotSupported, -1 },
  56. { DBPROP_MAXROWS, TRUE, eNumeric, eid_PROPVAL_MAXROWS },
  57. { DBPROP_FIRSTROWS, TRUE, eFirstRows, eid_PROPVAL_FIRSTROWS },
  58. { DBPROP_MAYWRITECOLUMN, FALSE, eColumnProp, -1 },
  59. { DBPROP_MEMORYUSAGE, TRUE, eNumeric, eid_PROPVAL_MEMORYUSAGE },
  60. // { DBPROP_MULTICHAPTERED, FALSE, eChaptered, -1 },
  61. // { DBPROP_MULTIPLEACCESSORS, FALSE, eDefaultTrue, -1 },
  62. // { DBPROP_MULTIPLERESULTSETS, FALSE, eNotSupported, -1 },
  63. // { DBPROP_NOTIFICATIONGRANULARITY, FALSE, eNumeric, -1 },
  64. { DBPROP_NOTIFICATIONPHASES, FALSE, eNumeric, -1 },
  65. { DBPROP_NOTIFYROWSETRELEASE, FALSE, eNumeric, -1 },
  66. { DBPROP_NOTIFYROWSETFETCHPOSITIONCHANGE,FALSE, eNumeric, -1 },
  67. // 9 additional notification properties, all unsupported
  68. { DBPROP_ORDEREDBOOKMARKS, FALSE, eLocatable, -1 },
  69. { DBPROP_OTHERINSERT, FALSE, eAsynchronous, -1 },
  70. { DBPROP_OTHERUPDATEDELETE, FALSE, eAsynchronous, -1 },
  71. { DBPROP_OWNINSERT, FALSE, eNotSupported, -1 },
  72. { DBPROP_OWNUPDATEDELETE, FALSE, eNotSupported, -1 },
  73. { DBPROP_QUICKRESTART, FALSE, eLocatable, -1 },
  74. { DBPROP_REENTRANTEVENTS, FALSE, eDefaultFalse, -1 },
  75. { DBPROP_REMOVEDELETED, FALSE, eDefaultTrue, -1 },
  76. { DBPROP_REPORTMULTIPLECHANGES, FALSE, eNotSupported, -1 },
  77. { DBPROP_RETURNPENDINGINSERTS, FALSE, eNotSupported, -1 },
  78. { DBPROP_ROWRESTRICT, FALSE, eDefaultTrue, -1 },
  79. { DBPROP_ROWTHREADMODEL, FALSE, eNumeric, -1 },
  80. { DBPROP_SERVERCURSOR, FALSE, eDefaultTrue, -1 },
  81. { DBPROP_STRONGIDENTITY, FALSE, eLocatable, -1 },
  82. { DBPROP_TRANSACTEDOBJECT, FALSE, eColumnProp, -1 },
  83. { DBPROP_UPDATABILITY, FALSE, eNumeric, -1 },
  84. { DBPROP_ROWSET_ASYNCH, TRUE, eNumeric, eid_PROPVAL_ROWSET_ASYNCH },
  85. //
  86. // Supported interfaces
  87. //
  88. { DBPROP_IAccessor, FALSE, eDefaultTrue, -1 },
  89. { DBPROP_IColumnsInfo, FALSE, eDefaultTrue, -1 },
  90. { DBPROP_IColumnsRowset, FALSE, eNotSupported, -1 },
  91. { DBPROP_IConnectionPointContainer, FALSE, eDefaultTrue, -1 },
  92. { DBPROP_IConvertType, FALSE, eDefaultTrue, -1 },
  93. { DBPROP_IRowset, FALSE, eDefaultTrue, -1 },
  94. { DBPROP_IRowsetIdentity, TRUE, eLocatable, eid_PROPVAL_IRowsetIdentity },
  95. { DBPROP_IRowsetInfo, FALSE, eDefaultTrue, -1 },
  96. { DBPROP_IRowsetLocate, TRUE, eLocatable, eid_PROPVAL_IRowsetLocate },
  97. { DBPROP_IRowsetScroll, TRUE, eScrollable, eid_PROPVAL_IRowsetScroll },
  98. { DBPROP_IRowsetExactScroll, TRUE, eScrollable, eid_PROPVAL_IRowsetExactScroll },
  99. { DBPROP_IDBAsynchStatus, TRUE, eAsynchronous, eid_PROPVAL_IDBAsynchStatus },
  100. { DBPROP_IRowsetAsynch, TRUE, eAsynchronous, eid_PROPVAL_IRowsetAsynch }, // deprecated
  101. { DBPROP_IRowsetWatchAll, TRUE, eWatchable, eid_PROPVAL_IRowsetWatchAll },
  102. { DBPROP_IRowsetWatchRegion, TRUE, eWatchable, eid_PROPVAL_IRowsetWatchRegion },
  103. { DBPROP_ISupportErrorInfo, FALSE, eDefaultTrue, -1 },
  104. { DBPROP_IChapteredRowset, FALSE, eChaptered, -1 },
  105. };
  106. const ULONG CMRowsetProps::cPropDescriptions =
  107. sizeof CMRowsetProps::aPropDescriptions /
  108. sizeof CMRowsetProps::aPropDescriptions[0];
  109. //
  110. // This array gives the Index Server property extensions
  111. //
  112. const SPropDescription CMRowsetProps::aQueryExtPropDescriptions[] = {
  113. { DBPROP_USECONTENTINDEX, TRUE, eUseCI, eid_PROPVAL_USECONTENTINDEX },
  114. { DBPROP_DEFERNONINDEXEDTRIMMING, TRUE, eDeferTrimming, eid_PROPVAL_DEFERNONINDEXEDTRIMMING },
  115. { DBPROP_USEEXTENDEDDBTYPES, TRUE, eExtendedTypes, eid_PROPVAL_USEEXTENDEDDBTYPES },
  116. };
  117. const ULONG CMRowsetProps::cQueryExtPropDescriptions =
  118. sizeof CMRowsetProps::aQueryExtPropDescriptions /
  119. sizeof CMRowsetProps::aQueryExtPropDescriptions[0];
  120. //
  121. // This is used by CMRowsetProps.
  122. //
  123. static const UPROPSET s_rgRowsetPropSets[] =
  124. {
  125. &DBPROPSET_ROWSET, NUMELEM(s_rgdbPropRowset), s_rgdbPropRowset, 0,
  126. &DBPROPSET_MSIDXS_ROWSET_EXT, NUMELEM(s_rgdbPropMSIDXSExt), s_rgdbPropMSIDXSExt, 0,
  127. &DBPROPSET_QUERY_EXT, NUMELEM(s_rgdbPropQueryExt), s_rgdbPropQueryExt, 0,
  128. };
  129. //
  130. // CMRowsetProps methods
  131. //
  132. //+---------------------------------------------------------------------------
  133. //
  134. // Method: CMRowsetProps::CMRowsetProps, public
  135. //
  136. // Synopsis: Constructor
  137. //
  138. // History: 11-12-97 danleg Created from Monarch
  139. //
  140. //----------------------------------------------------------------------------
  141. CMRowsetProps::CMRowsetProps
  142. (
  143. LCID lcidInit
  144. )
  145. : CUtlProps(ARGCHK_PROPERTIESINERROR),
  146. _dwBooleanOptions ( 0)
  147. {
  148. if ( lcidInit )
  149. _lcidInit = lcidInit;
  150. else
  151. _lcidInit = GetSystemDefaultLCID();
  152. FInit();
  153. }
  154. //+---------------------------------------------------------------------------
  155. //
  156. // Method: CMRowsetProps::CMRowsetProps, public
  157. //
  158. // Synopsis: Copy Constructor
  159. //
  160. // History: 11-12-97 danleg Created from Monarch
  161. //
  162. //----------------------------------------------------------------------------
  163. CMRowsetProps::CMRowsetProps
  164. (
  165. const CMRowsetProps & propSrc
  166. )
  167. : CUtlProps(ARGCHK_PROPERTIESINERROR)
  168. {
  169. FInit( (CUtlProps*) &propSrc );
  170. _lcidInit = propSrc._lcidInit;
  171. _dwBooleanOptions = propSrc._dwBooleanOptions;
  172. }
  173. //+---------------------------------------------------------------------------
  174. //
  175. // Method: CMRowsetProps::SetChaptered, public
  176. //
  177. // Arguments: [fSet] - set or unset this property
  178. //
  179. // Synopsis:
  180. //
  181. // History: 02-20-98 danleg Created
  182. //
  183. //----------------------------------------------------------------------------
  184. DWORD CMRowsetProps::SetChaptered( BOOL fSet )
  185. {
  186. SetValBool( CMRowsetProps::eid_DBPROPSET_ROWSET,
  187. CMRowsetProps::eid_PROPVAL_IChapteredRowset,
  188. fSet ? VARIANT_TRUE : VARIANT_FALSE );
  189. if ( fSet )
  190. _dwBooleanOptions |= eChaptered;
  191. else
  192. _dwBooleanOptions &= ~eChaptered;
  193. return _dwBooleanOptions;
  194. }
  195. //+---------------------------------------------------------------------------
  196. //
  197. // Method: CMRowsetProps::SetFirstRows, public
  198. //
  199. // Arguments: [ulFirstRows] - value of first rows
  200. //
  201. // Synopsis: Sets the FirstRows property
  202. //
  203. // History: 07-11-2000 KitmanH Created
  204. //
  205. //----------------------------------------------------------------------------
  206. void CMRowsetProps::SetFirstRows( ULONG ulFirstRows )
  207. {
  208. SetValLong( CMRowsetProps::eid_DBPROPSET_ROWSET,
  209. CMRowsetProps::eid_PROPVAL_FIRSTROWS,
  210. ulFirstRows );
  211. _dwBooleanOptions |= eFirstRows;
  212. }
  213. //+---------------------------------------------------------------------------
  214. //
  215. // Method: CMRowsetProps::SetImpliedProperties, public
  216. //
  217. // Arguments: [riidRowset] - iid requested
  218. // [cRowsets] - indication on whethere this is a chaptered
  219. // rowset
  220. // Synopsis: This routine does not set any properties in the property table.
  221. //
  222. // History: 02-20-98 danleg Created
  223. //
  224. //----------------------------------------------------------------------------
  225. DWORD CMRowsetProps::SetImpliedProperties
  226. (
  227. REFIID riidRowset,
  228. ULONG cRowsets
  229. )
  230. {
  231. SPropDescription const * pPropDesc = FindInterfaceDescription( riidRowset );
  232. if ( pPropDesc == 0 )
  233. THROW( CException(E_NOINTERFACE) );
  234. if ( pPropDesc->fSettable )
  235. {
  236. Win4Assert( pPropDesc->dwIndicator >= eSequential &&
  237. pPropDesc->dwIndicator <= eWatchable );
  238. _dwBooleanOptions |= pPropDesc->dwIndicator;
  239. // make sure that the eid_ in aPropDescriptions is in the range
  240. Win4Assert( pPropDesc->uIndex < eid_PROPVAL_ROWSET_NUM );
  241. //
  242. // Set this property in the CMRowsetProps cache so we can later return it.
  243. //
  244. SetValBool( eid_DBPROPSET_ROWSET, pPropDesc->uIndex, VARIANT_TRUE );
  245. }
  246. else if ( pPropDesc->dwIndicator != eDefaultTrue &&
  247. !(pPropDesc->dwIndicator & _dwBooleanOptions) )
  248. {
  249. THROW( CException(E_NOINTERFACE) );
  250. }
  251. else
  252. {
  253. Win4Assert( pPropDesc->dwProp == DBPROP_IRowset ||
  254. riidRowset == IID_IRowsetIdentity ||
  255. riidRowset == IID_IRowsetInfo ||
  256. riidRowset == IID_IColumnsInfo ||
  257. riidRowset == IID_IConvertType ||
  258. riidRowset == IID_IAccessor ||
  259. riidRowset == IID_IConnectionPointContainer );
  260. _dwBooleanOptions |= eSequential;
  261. }
  262. if ( cRowsets > 1 )
  263. _dwBooleanOptions |= eChaptered;
  264. //
  265. // Interface indicators are arranged in a hierarchy from most general
  266. // to most specialized. Arrange that all more general interfaces are
  267. // included in the properties.
  268. //
  269. for ( unsigned i = eWatchable; i > eSequential;
  270. i = (i >> 1) )
  271. {
  272. if ( _dwBooleanOptions & i )
  273. _dwBooleanOptions |= (i >> 1);
  274. }
  275. Win4Assert( _dwBooleanOptions & eSequential );
  276. //
  277. // Scrollable
  278. // IRowsetScroll or IRowsetExactScroll were set. IRowsetLocate is implied.
  279. //
  280. if ( _dwBooleanOptions & eScrollable )
  281. {
  282. // IRowsetScroll is user settable. Make sure that it wasn't explicitly unset.
  283. if ( DBPROPOPTIONS_REQUIRED != GetPropOption( eid_DBPROPSET_ROWSET, eid_PROPVAL_IRowsetScroll) )
  284. {
  285. SetValBool( eid_DBPROPSET_ROWSET, eid_PROPVAL_IRowsetScroll, VARIANT_TRUE );
  286. SetPropOption( eid_DBPROPSET_ROWSET, eid_PROPVAL_IRowsetScroll, DBPROPOPTIONS_REQUIRED );
  287. }
  288. // IRowsetLocate is settable. Make sure it wasn't explicitly unset.
  289. if ( DBPROPOPTIONS_REQUIRED != GetPropOption( eid_DBPROPSET_ROWSET, eid_PROPVAL_IRowsetLocate) )
  290. {
  291. DWORD dwOption = GetPropOption( eid_DBPROPSET_ROWSET, eid_PROPVAL_IRowsetScroll);
  292. SetValBool( eid_DBPROPSET_ROWSET, eid_PROPVAL_IRowsetLocate, VARIANT_TRUE );
  293. SetPropOption( eid_DBPROPSET_ROWSET, eid_PROPVAL_IRowsetLocate, dwOption );
  294. }
  295. }
  296. //
  297. // Locatable
  298. //
  299. if ( _dwBooleanOptions & eLocatable )
  300. {
  301. // these are not user settable
  302. SetValBool( eid_DBPROPSET_ROWSET, eid_PROPVAL_CANFETCHBACKWARDS, VARIANT_TRUE );
  303. SetValBool( eid_DBPROPSET_ROWSET, eid_PROPVAL_CANSCROLLBACKWARDS, VARIANT_TRUE );
  304. SetValBool( eid_DBPROPSET_ROWSET, eid_PROPVAL_LITERALIDENTITY, VARIANT_TRUE );
  305. SetValBool( eid_DBPROPSET_ROWSET, eid_PROPVAL_ORDEREDBOOKMARKS, VARIANT_TRUE );
  306. SetValBool( eid_DBPROPSET_ROWSET, eid_PROPVAL_QUICKRESTART, VARIANT_TRUE );
  307. SetValBool( eid_DBPROPSET_ROWSET, eid_PROPVAL_STRONGIDENTITY, VARIANT_TRUE );
  308. // eLocateable (IRowsetLocate or IRowsetIdentity are set). IRowsetLocate implies BOOKMARKS
  309. if ( VARIANT_TRUE == GetValBool(eid_DBPROPSET_ROWSET, eid_PROPVAL_IRowsetLocate) )
  310. {
  311. // BOOKMARKs is settable. Make sure it hasn't already been set to FALSE/REQUIRED
  312. if ( DBPROPOPTIONS_REQUIRED != GetPropOption( eid_DBPROPSET_ROWSET, eid_PROPVAL_BOOKMARKS) )
  313. {
  314. DWORD dwOption = GetPropOption( eid_DBPROPSET_ROWSET, eid_PROPVAL_IRowsetLocate );
  315. SetValBool( eid_DBPROPSET_ROWSET, eid_PROPVAL_BOOKMARKS, VARIANT_TRUE );
  316. SetPropOption( eid_DBPROPSET_ROWSET, eid_PROPVAL_BOOKMARKS, dwOption );
  317. }
  318. }
  319. }
  320. else
  321. {
  322. SetValBool( eid_DBPROPSET_ROWSET, eid_PROPVAL_CANFETCHBACKWARDS, VARIANT_FALSE );
  323. SetValBool( eid_DBPROPSET_ROWSET, eid_PROPVAL_CANSCROLLBACKWARDS, VARIANT_FALSE );
  324. SetValBool( eid_DBPROPSET_ROWSET, eid_PROPVAL_LITERALIDENTITY, VARIANT_FALSE );
  325. SetValBool( eid_DBPROPSET_ROWSET, eid_PROPVAL_ORDEREDBOOKMARKS, VARIANT_FALSE );
  326. SetValBool( eid_DBPROPSET_ROWSET, eid_PROPVAL_QUICKRESTART, VARIANT_FALSE );
  327. SetValBool( eid_DBPROPSET_ROWSET, eid_PROPVAL_STRONGIDENTITY, VARIANT_FALSE );
  328. }
  329. //
  330. // Asynchronous
  331. //
  332. if ( _dwBooleanOptions & eAsynchronous )
  333. {
  334. SetValBool( eid_DBPROPSET_ROWSET, eid_PROPVAL_OTHERINSERT, VARIANT_TRUE );
  335. SetValBool( eid_DBPROPSET_ROWSET, eid_PROPVAL_OTHERUPDATEDELETE, VARIANT_TRUE );
  336. }
  337. else
  338. {
  339. SetValBool( eid_DBPROPSET_ROWSET, eid_PROPVAL_OTHERINSERT, VARIANT_FALSE );
  340. SetValBool( eid_DBPROPSET_ROWSET, eid_PROPVAL_OTHERUPDATEDELETE, VARIANT_FALSE );
  341. }
  342. return _dwBooleanOptions;
  343. }
  344. //+---------------------------------------------------------------------------
  345. //
  346. // Method: CMRowsetProps::FindPropertyDescription, private
  347. //
  348. // Synopsis: Return description of a propery.
  349. //
  350. // Arguments: [rgPropDesc] - array of property descriptions for propset
  351. // [cPropDesc] - count of property descriptions in rgPropDesc
  352. // [dwPropId] - ID of the property description desired
  353. //
  354. // Returns: pointer to SPropDescription or NULL
  355. //
  356. // History: 19 Nov 95 AlanW Created
  357. //
  358. //----------------------------------------------------------------------------
  359. SPropDescription const * CMRowsetProps::FindPropertyDescription(
  360. SPropDescription const * rgPropDesc,
  361. unsigned cPropDesc,
  362. DBPROPID dwPropId )
  363. {
  364. SPropDescription const * pPropDesc = rgPropDesc;
  365. for (unsigned i=0; i < cPropDesc; i++, pPropDesc++)
  366. {
  367. if (pPropDesc->dwProp == dwPropId)
  368. return pPropDesc;
  369. }
  370. return 0;
  371. }
  372. const struct SIidLookup {
  373. const GUID * riid;
  374. DBPROPID dwPropId;
  375. } aIidLookup[] = {
  376. { &IID_IAccessor, DBPROP_IAccessor },
  377. { &IID_IColumnsInfo, DBPROP_IColumnsInfo },
  378. { &IID_IColumnsRowset, DBPROP_IColumnsRowset },
  379. { &IID_IConnectionPointContainer, DBPROP_IConnectionPointContainer },
  380. { &IID_IConvertType, DBPROP_IConvertType },
  381. // { &IID_ICopyColumn, DBPROP_ICopyColumn },
  382. { &IID_IRowset, DBPROP_IRowset },
  383. { &IID_IRowsetIdentity, DBPROP_IRowsetIdentity },
  384. { &IID_IRowsetInfo, DBPROP_IRowsetInfo },
  385. { &IID_IRowsetLocate, DBPROP_IRowsetLocate },
  386. { &IID_IRowsetScroll, DBPROP_IRowsetScroll },
  387. { &IID_IRowsetExactScroll, DBPROP_IRowsetExactScroll }, // deprecated
  388. { &IID_IDBAsynchStatus, DBPROP_IDBAsynchStatus },
  389. { &IID_IRowsetAsynch, DBPROP_IRowsetAsynch }, // deprecated
  390. { &IID_IRowsetWatchAll, DBPROP_IRowsetWatchAll },
  391. { &IID_IRowsetWatchRegion, DBPROP_IRowsetWatchRegion },
  392. { &IID_IUnknown, DBPROP_IRowset },
  393. { &IID_NULL, DBPROP_IRowset },
  394. };
  395. const unsigned cIidLookup = sizeof aIidLookup / sizeof aIidLookup[0];
  396. //+---------------------------------------------------------------------------
  397. //
  398. // Method: CMRowsetProps::FindInterfaceDescription, private
  399. //
  400. // Synopsis: Return property description corresponding to an interface
  401. //
  402. // Arguments: [riid] - REFIID of interface to be looked up
  403. //
  404. // Returns: pointer to SPropDescription or NULL
  405. //
  406. // History: 26 Sep 96 AlanW Created
  407. //
  408. //----------------------------------------------------------------------------
  409. SPropDescription const * CMRowsetProps::FindInterfaceDescription(
  410. REFIID riid )
  411. {
  412. for (unsigned i=0; i < cIidLookup; i++)
  413. {
  414. if (riid == *aIidLookup[i].riid)
  415. return FindPropertyDescription( aPropDescriptions,
  416. cPropDescriptions,
  417. aIidLookup[i].dwPropId );
  418. }
  419. return 0;
  420. }
  421. //+---------------------------------------------------------------------------
  422. //
  423. // Method: CMRowsetProps::UpdateBooleanOptions, private
  424. //
  425. // Synopsis: Update _dwBooleanOptions to reflect newly set properties.
  426. // Look for conflicting properties and mark them as such.
  427. //
  428. // History: 03-02-98 danleg Created
  429. //
  430. //----------------------------------------------------------------------------
  431. void CMRowsetProps::UpdateBooleanOptions
  432. (
  433. const ULONG cPropertySets,
  434. const DBPROPSET rgPropertySets[]
  435. )
  436. {
  437. SCODE sc = S_OK;
  438. DWORD dwSetOptions = 0;
  439. DWORD dwUnsetOptions = 0;
  440. DWORD dwOption = 0;
  441. //
  442. // table for boolean options
  443. //
  444. for ( unsigned i=0; i<cPropertySets; i++ )
  445. {
  446. SPropDescription const * pPropDesc = 0;
  447. unsigned cPropDesc = 0;
  448. unsigned cProp = rgPropertySets[i].cProperties;
  449. DBPROP * pProp = rgPropertySets[i].rgProperties;
  450. if ( DBPROPSET_ROWSET == rgPropertySets[i].guidPropertySet )
  451. {
  452. pPropDesc = aPropDescriptions;
  453. cPropDesc = cPropDescriptions;
  454. }
  455. else if ( DBPROPSET_QUERY_EXT == rgPropertySets[i].guidPropertySet )
  456. {
  457. pPropDesc = aQueryExtPropDescriptions;
  458. cPropDesc = cQueryExtPropDescriptions;
  459. }
  460. else
  461. {
  462. // no properties here of interest to boolean options
  463. continue;
  464. }
  465. for ( unsigned j=0; j<cProp; j++, pProp++ )
  466. {
  467. if ( DBPROPSTATUS_OK == pProp->dwStatus )
  468. {
  469. //
  470. // determine the flag to set for this property
  471. //
  472. SPropDescription const * pFoundDesc =
  473. FindPropertyDescription ( pPropDesc,
  474. cPropDesc,
  475. pProp->dwPropertyID );
  476. if ( 0 != pFoundDesc )
  477. {
  478. // Setting read-only props to their default value succeeds
  479. if ( !pFoundDesc->fSettable )
  480. continue;
  481. dwOption = pFoundDesc->dwIndicator;
  482. //
  483. // Settable properties with special option flags
  484. //
  485. switch ( pProp->dwPropertyID )
  486. {
  487. case DBPROP_COMMANDTIMEOUT:
  488. case DBPROP_MAXROWS:
  489. case DBPROP_MEMORYUSAGE:
  490. continue;
  491. case DBPROP_FIRSTROWS:
  492. dwOption = eFirstRows;
  493. break;
  494. case DBPROP_ROWSET_ASYNCH:
  495. dwOption = eAsynchronous;
  496. break;
  497. default:
  498. // no other settable props that need special handling
  499. break;
  500. }
  501. //
  502. // determine if the property was set or unset
  503. //
  504. switch ( V_VT(&(pProp->vValue)) )
  505. {
  506. case VT_BOOL:
  507. if ( VARIANT_FALSE == V_BOOL(&(pProp->vValue)) )
  508. dwUnsetOptions |= dwOption;
  509. else
  510. dwSetOptions |= dwOption;
  511. break;
  512. case VT_I4:
  513. if ( DBPROPSET_ROWSET == rgPropertySets[i].guidPropertySet &&
  514. ( DBPROP_ROWSET_ASYNCH == pProp->dwPropertyID ||
  515. DBPROP_FIRSTROWS == pProp->dwPropertyID ) )
  516. {
  517. if ( 0 == V_I4(&(pProp->vValue)) )
  518. dwUnsetOptions |= dwOption;
  519. else
  520. dwSetOptions |= dwOption;
  521. }
  522. break;
  523. case VT_EMPTY:
  524. // assume to mean unset
  525. dwUnsetOptions |= dwOption;
  526. break;
  527. default:
  528. break;
  529. }
  530. }
  531. else
  532. {
  533. // This should never get hit since the property was set successfully.
  534. Win4Assert( ! "_rgdbPropRowset and aPropDescriptions are out of sync." );
  535. }
  536. }
  537. }
  538. }
  539. Win4Assert( (dwSetOptions & dwUnsetOptions) == 0 );
  540. if ( dwSetOptions & eScrollable )
  541. {
  542. dwUnsetOptions |= eSequential;
  543. }
  544. else if ( dwSetOptions & eSequential )
  545. {
  546. dwUnsetOptions |= eScrollable;
  547. }
  548. //
  549. // If IRowsetLocate and/or BOOKMARKS were explicitly set, and
  550. // IRowsetIdentity is being unset, don't take of the eLocatable bit
  551. //
  552. if ( dwUnsetOptions & eLocatable )
  553. {
  554. if ( VARIANT_TRUE == GetValBool(eid_DBPROPSET_ROWSET, eid_PROPVAL_IRowsetLocate) ||
  555. VARIANT_TRUE == GetValBool(eid_DBPROPSET_ROWSET, eid_PROPVAL_BOOKMARKS) )
  556. dwUnsetOptions &= ~eLocatable;
  557. }
  558. _dwBooleanOptions &= ~dwUnsetOptions;
  559. _dwBooleanOptions |= dwSetOptions;
  560. }
  561. //+---------------------------------------------------------------------------
  562. //
  563. // Method: CMRowsetProps::SetProperties, public
  564. //
  565. // Synopsis:
  566. //
  567. // History: 02-15-98 danleg Created
  568. //
  569. //----------------------------------------------------------------------------
  570. SCODE CMRowsetProps::SetProperties
  571. (
  572. const ULONG cPropertySets,
  573. const DBPROPSET rgPropertySets[]
  574. )
  575. {
  576. SCODE sc = S_OK;
  577. ULONG cPropSets = cPropertySets;
  578. sc = CUtlProps::SetProperties( cPropertySets, rgPropertySets );
  579. if ( FAILED(sc) )
  580. return sc;
  581. //
  582. // Some or all of the properties were set successfully.
  583. // Update _dwBooleanOptions.
  584. //
  585. UpdateBooleanOptions( cPropertySets, rgPropertySets );
  586. return sc;
  587. }
  588. //+---------------------------------------------------------------------------
  589. //
  590. // Method: CMRowsetProps::ArePropsInError, public
  591. //
  592. // Synopsis: Update _dwBooleanOptions to reflect newly set properties.
  593. // Look for conflicting properties and mark them as such.
  594. //
  595. // History: 03-02-98 danleg Created
  596. //
  597. //----------------------------------------------------------------------------
  598. SCODE CMRowsetProps::ArePropsInError
  599. (
  600. CMRowsetProps & rProps
  601. )
  602. {
  603. unsigned cErrors = 0;
  604. //
  605. // DBPROP_IRowsetScroll --> DBPROP_IRowsetLocate
  606. //
  607. if( VARIANT_TRUE == GetValBool(eid_DBPROPSET_ROWSET,eid_PROPVAL_IRowsetScroll) &&
  608. DBPROPOPTIONS_REQUIRED == GetPropOption(eid_DBPROPSET_ROWSET, eid_PROPVAL_IRowsetScroll) )
  609. {
  610. // IRowsetLocate should also be set to TRUE/REQUIRED
  611. if ( VARIANT_FALSE == GetValBool(eid_DBPROPSET_ROWSET, eid_PROPVAL_IRowsetLocate) &&
  612. DBPROPOPTIONS_REQUIRED == GetPropOption(eid_DBPROPSET_ROWSET, eid_PROPVAL_IRowsetLocate) )
  613. {
  614. rProps.SetPropertyInError( eid_DBPROPSET_ROWSET, eid_PROP_IRowsetScroll );
  615. rProps.SetPropertyInError( eid_DBPROPSET_ROWSET, eid_PROP_IRowsetLocate );
  616. cErrors++;
  617. }
  618. // BOOKMARKS should also be set to TRUE/REQUIRED
  619. if ( VARIANT_FALSE == GetValBool(eid_DBPROPSET_ROWSET, eid_PROPVAL_BOOKMARKS) &&
  620. DBPROPOPTIONS_REQUIRED == GetPropOption(eid_DBPROPSET_ROWSET, eid_PROPVAL_BOOKMARKS) )
  621. {
  622. rProps.SetPropertyInError( eid_DBPROPSET_ROWSET, eid_PROP_BOOKMARKS );
  623. rProps.SetPropertyInError( eid_DBPROPSET_ROWSET, eid_PROP_IRowsetScroll );
  624. cErrors++;
  625. }
  626. }
  627. //
  628. // DBPROP_IRowsteLocate --> DBPROP_BOOKMARKS
  629. //
  630. if( VARIANT_TRUE == GetValBool(eid_DBPROPSET_ROWSET,eid_PROPVAL_IRowsetLocate) &&
  631. DBPROPOPTIONS_REQUIRED == GetPropOption(eid_DBPROPSET_ROWSET, eid_PROPVAL_IRowsetLocate) )
  632. {
  633. // BOOKMARKS should also be set to TRUE/REQUIRED
  634. if ( VARIANT_FALSE == GetValBool(eid_DBPROPSET_ROWSET, eid_PROPVAL_BOOKMARKS) &&
  635. DBPROPOPTIONS_REQUIRED == GetPropOption(eid_DBPROPSET_ROWSET, eid_PROPVAL_BOOKMARKS) )
  636. {
  637. rProps.SetPropertyInError( eid_DBPROPSET_ROWSET, eid_PROP_BOOKMARKS );
  638. rProps.SetPropertyInError( eid_DBPROPSET_ROWSET, eid_PROP_IRowsetLocate );
  639. cErrors++;
  640. }
  641. }
  642. return ( cErrors ) ? DB_E_ERRORSOCCURRED
  643. : S_OK;
  644. }
  645. //+---------------------------------------------------------------------------
  646. //
  647. // Method: CMRowsetProps::InitAvailUPropsets, private
  648. //
  649. // Synopsis: Provide property set information to the base class
  650. //
  651. // History: 11-12-97 danleg Created from Monarch
  652. //
  653. //----------------------------------------------------------------------------
  654. SCODE CMRowsetProps::InitAvailUPropSets
  655. (
  656. ULONG* pcUPropSet,
  657. UPROPSET** ppUPropSet,
  658. ULONG* pcElemPerSupported
  659. )
  660. {
  661. Win4Assert( pcUPropSet && ppUPropSet);
  662. Win4Assert( NUMELEM(s_rgdbPropRowset) == eid_ROWSET_PROPS_NUM );
  663. Win4Assert( NUMELEM(s_rgdbPropQueryExt) == eid_QUERYEXT_PROPS_NUM );
  664. Win4Assert( NUMELEM(s_rgdbPropMSIDXSExt) == eid_MSIDXS_PROPS_NUM );
  665. *pcUPropSet = NUMELEM(s_rgRowsetPropSets);
  666. *ppUPropSet = (UPROPSET*)s_rgRowsetPropSets;
  667. *pcElemPerSupported = DWORDSNEEDEDPERSET;
  668. return S_OK;
  669. }
  670. //+---------------------------------------------------------------------------
  671. //
  672. // Method: CMRowsetProps::InitUPropSetsSupported, private
  673. //
  674. // Synopsis: Build the required supported property bitmask for the property
  675. // set supported by this class
  676. //
  677. // History: 11-12-97 danleg Created from Monarch
  678. //
  679. //----------------------------------------------------------------------------
  680. SCODE CMRowsetProps::InitUPropSetsSupported
  681. (
  682. DWORD* rgdwSupported
  683. )
  684. {
  685. Win4Assert( rgdwSupported );
  686. // Initialize the bitmask to indicate all properties are supported
  687. RtlFillMemory( rgdwSupported,
  688. DWORDSNEEDEDPERSET * NUMELEM(s_rgRowsetPropSets) * sizeof(DWORD),
  689. 0xFF );
  690. return S_OK;
  691. }
  692. //+---------------------------------------------------------------------------
  693. //
  694. // Method: CMRowsetProps::GetDefaultValue, private
  695. //
  696. // Synopsis: Retrieve the initial value for a propid.
  697. // DEVNOTE: Using the index from 0 to (GetCountofAvailPropSets-1)
  698. // and an index of 0 to (GetCountofAvailPropidsInPropset-1)
  699. // within that propertyset, return the correct information.
  700. // NOTE: pVar should be initialized prior to this routine.
  701. //
  702. // History: 11-12-97 danleg Created from Monarch
  703. //
  704. //----------------------------------------------------------------------------
  705. SCODE CMRowsetProps::GetDefaultValue
  706. (
  707. ULONG iCurSet,
  708. DBPROPID dwPropId,
  709. DWORD* pdwOption,
  710. VARIANT* pvValue
  711. )
  712. {
  713. Win4Assert( V_VT(pvValue) == VT_EMPTY );
  714. switch( iCurSet )
  715. {
  716. case eid_DBPROPSET_ROWSET:
  717. *pdwOption = DBPROPOPTIONS_REQUIRED;
  718. switch ( dwPropId )
  719. {
  720. // default TRUE values, non-writable
  721. case DBPROP_IAccessor:
  722. case DBPROP_IColumnsInfo:
  723. case DBPROP_IConnectionPointContainer:
  724. case DBPROP_IConvertType:
  725. case DBPROP_IRowset:
  726. case DBPROP_IRowsetInfo:
  727. case DBPROP_ISupportErrorInfo:
  728. case DBPROP_REMOVEDELETED:
  729. case DBPROP_ROWRESTRICT:
  730. case DBPROP_SERVERCURSOR:
  731. V_VT( pvValue ) = VT_BOOL;
  732. V_BOOL( pvValue ) = VARIANT_TRUE;
  733. break;
  734. case DBPROP_IChapteredRowset:
  735. V_VT( pvValue ) = VT_BOOL;
  736. V_BOOL( pvValue ) = VARIANT_FALSE;
  737. break;
  738. // default FALSE non-writable
  739. case DBPROP_BLOCKINGSTORAGEOBJECTS:
  740. case DBPROP_BOOKMARKSKIPPED:
  741. case DBPROP_CANFETCHBACKWARDS:
  742. case DBPROP_CANSCROLLBACKWARDS:
  743. case DBPROP_COLUMNRESTRICT:
  744. case DBPROP_LITERALBOOKMARKS:
  745. case DBPROP_LITERALIDENTITY:
  746. case DBPROP_ORDEREDBOOKMARKS:
  747. case DBPROP_OTHERINSERT:
  748. case DBPROP_OTHERUPDATEDELETE:
  749. case DBPROP_REENTRANTEVENTS:
  750. case DBPROP_STRONGIDENTITY:
  751. case DBPROP_QUICKRESTART:
  752. V_VT( pvValue ) = VT_BOOL;
  753. V_BOOL( pvValue ) = VARIANT_FALSE;
  754. break;
  755. // default FALSE, writable
  756. case DBPROP_BOOKMARKS:
  757. case DBPROP_CANHOLDROWS:
  758. case DBPROP_IDBAsynchStatus:
  759. case DBPROP_IRowsetAsynch:
  760. case DBPROP_IRowsetExactScroll:
  761. case DBPROP_IRowsetIdentity:
  762. case DBPROP_IRowsetScroll:
  763. case DBPROP_IRowsetWatchAll:
  764. case DBPROP_IRowsetWatchRegion:
  765. case DBPROP_IRowsetLocate:
  766. *pdwOption = DBPROPOPTIONS_OPTIONAL;
  767. V_VT( pvValue ) = VT_BOOL;
  768. V_BOOL( pvValue ) = VARIANT_FALSE;
  769. break;
  770. case DBPROP_BOOKMARKTYPE:
  771. V_VT( pvValue ) = VT_I4;
  772. V_I4( pvValue ) = DBPROPVAL_BMK_NUMERIC;
  773. break;
  774. case DBPROP_COMMANDTIMEOUT:
  775. case DBPROP_MAXOPENROWS:
  776. case DBPROP_MAXROWS:
  777. case DBPROP_FIRSTROWS:
  778. case DBPROP_MEMORYUSAGE:
  779. case DBPROP_ROWSET_ASYNCH:
  780. case DBPROP_UPDATABILITY:
  781. V_VT( pvValue ) = VT_I4;
  782. V_I4( pvValue ) = 0;
  783. break;
  784. case DBPROP_ROWTHREADMODEL:
  785. V_VT( pvValue ) = VT_I4;
  786. V_I4( pvValue ) = DBPROPVAL_RT_FREETHREAD;
  787. break;
  788. case DBPROP_NOTIFICATIONPHASES:
  789. V_VT( pvValue ) = VT_I4;
  790. V_I4( pvValue ) = DBPROPVAL_NP_OKTODO |
  791. DBPROPVAL_NP_ABOUTTODO |
  792. DBPROPVAL_NP_FAILEDTODO |
  793. DBPROPVAL_NP_DIDEVENT;
  794. break;
  795. case DBPROP_NOTIFYROWSETRELEASE:
  796. V_VT( pvValue ) = VT_I4;
  797. V_I4( pvValue ) = 0;
  798. break;
  799. case DBPROP_NOTIFYROWSETFETCHPOSITIONCHANGE:
  800. V_VT( pvValue ) = VT_I4;
  801. V_I4( pvValue ) = DBPROPVAL_NP_OKTODO |
  802. DBPROPVAL_NP_ABOUTTODO;
  803. break;
  804. case DBPROP_CACHEDEFERRED:
  805. case DBPROP_DEFERRED:
  806. default:
  807. // one of the unsupported properties
  808. VariantClear( pvValue );
  809. break;
  810. }
  811. break;
  812. case eid_DBPROPSET_QUERY_EXT:
  813. *pdwOption = DBPROPOPTIONS_REQUIRED;
  814. //
  815. // All three properties under this property set are BOOL/FALSE by default
  816. //
  817. V_VT( pvValue ) = VT_BOOL;
  818. V_BOOL( pvValue ) = VARIANT_FALSE;
  819. break;
  820. case eid_DBPROPSET_MSIDXS_ROWSET_EXT:
  821. *pdwOption = DBPROPOPTIONS_REQUIRED;
  822. switch( dwPropId )
  823. {
  824. case MSIDXSPROP_ROWSETQUERYSTATUS:
  825. V_VT(pvValue) = VT_I4;
  826. V_I4(pvValue) = 0;
  827. break;
  828. case MSIDXSPROP_COMMAND_LOCALE_STRING:
  829. *pdwOption = DBPROPOPTIONS_OPTIONAL;
  830. V_VT(pvValue) = VT_BSTR;
  831. WCHAR awcLocale[100];
  832. GetStringFromLCID(_lcidInit, awcLocale );
  833. V_BSTR(pvValue) = SysAllocString( awcLocale );
  834. if ( 0 == V_BSTR(pvValue) )
  835. return E_OUTOFMEMORY;
  836. break;
  837. case MSIDXSPROP_QUERY_RESTRICTION:
  838. V_VT(pvValue) = VT_BSTR;
  839. V_BSTR(pvValue) = SysAllocString(L"");
  840. if ( 0 == V_BSTR(pvValue) )
  841. return E_OUTOFMEMORY;
  842. break;
  843. default:
  844. //Indicate that value is unknown
  845. VariantClear(pvValue);
  846. break;
  847. }
  848. break;
  849. default:
  850. // Invalid Property Set
  851. Win4Assert( ! "Invalid property set in GetDefaultValue.");
  852. return E_FAIL;
  853. }
  854. return S_OK;
  855. }
  856. //+---------------------------------------------------------------------------
  857. //
  858. // Method: CMRowsetProps::IsValidValue, private
  859. //
  860. // Synopsis: Validate that the variant contains legal values for its
  861. // particular type and for the particular PROPID in this propset.
  862. // Devnote: This routine has to apply to writable properties only.
  863. //
  864. // History: 11-12-97 danleg Created from Monarch
  865. // 02-01-98 danleg Added support for DBPROPSET_ROWSET
  866. // and DBPROPSET_QUERYEXT
  867. //
  868. //----------------------------------------------------------------------------
  869. SCODE CMRowsetProps::IsValidValue
  870. (
  871. ULONG iCurSet,
  872. DBPROP* pDBProp
  873. )
  874. {
  875. switch ( V_VT(&(pDBProp->vValue)) )
  876. {
  877. case VT_BOOL:
  878. if ( !( VARIANT_TRUE == V_BOOL(&(pDBProp->vValue)) ||
  879. VARIANT_FALSE == V_BOOL(&(pDBProp->vValue)) ) )
  880. return S_FALSE;
  881. break;
  882. case VT_I4:
  883. switch ( iCurSet )
  884. {
  885. case eid_DBPROPSET_ROWSET:
  886. switch ( pDBProp->dwPropertyID )
  887. {
  888. case DBPROP_BOOKMARKTYPE:
  889. if ( !(DBPROPVAL_BMK_NUMERIC == V_I4(&(pDBProp->vValue)) ||
  890. DBPROPVAL_BMK_KEY == V_I4(&(pDBProp->vValue)) ) )
  891. return S_FALSE;
  892. break;
  893. case DBPROP_ROWSET_ASYNCH:
  894. switch ( V_I4(&(pDBProp->vValue)) )
  895. {
  896. case ( DBPROPVAL_ASYNCH_SEQUENTIALPOPULATION |
  897. DBPROPVAL_ASYNCH_RANDOMPOPULATION ):
  898. case DBPROPVAL_ASYNCH_RANDOMPOPULATION:
  899. case 0: // means sequential init and population
  900. break;
  901. case DBPROPVAL_ASYNCH_INITIALIZE:
  902. case DBPROPVAL_ASYNCH_SEQUENTIALPOPULATION:
  903. default:
  904. return S_FALSE;
  905. }
  906. break;
  907. case DBPROP_ROWTHREADMODEL:
  908. // this is a r/o property, set to FREETHREAD by default.
  909. switch ( V_I4(&(pDBProp->vValue)) )
  910. {
  911. case DBPROPVAL_RT_FREETHREAD:
  912. case DBPROPVAL_RT_APTMTTHREAD:
  913. case DBPROPVAL_RT_SINGLETHREAD:
  914. break;
  915. default:
  916. return S_FALSE;
  917. }
  918. break;
  919. case DBPROP_MEMORYUSAGE:
  920. if ( 0 > V_I4(&(pDBProp->vValue)) ||
  921. 99 < V_I4(&(pDBProp->vValue)) )
  922. return S_FALSE;
  923. break;
  924. case DBPROP_COMMANDTIMEOUT:
  925. case DBPROP_MAXROWS:
  926. case DBPROP_FIRSTROWS:
  927. if ( 0 > V_I4(&(pDBProp->vValue)) )
  928. return S_FALSE;
  929. break;
  930. case DBPROP_UPDATABILITY:
  931. // this is the only other supported VT_I4 property
  932. break;
  933. default:
  934. // no other VT_I4 properties in DBPROPSET_ROWSET
  935. return S_FALSE;
  936. }
  937. break;
  938. case eid_DBPROPSET_MSIDXS_ROWSET_EXT:
  939. if ( MSIDXSPROP_ROWSETQUERYSTATUS != pDBProp->dwPropertyID )
  940. return S_FALSE;
  941. break;
  942. default:
  943. return S_FALSE;
  944. }
  945. break; // VT_I4
  946. case VT_BSTR:
  947. switch ( iCurSet )
  948. {
  949. case eid_DBPROPSET_MSIDXS_ROWSET_EXT:
  950. switch ( pDBProp->dwPropertyID )
  951. {
  952. case MSIDXSPROP_COMMAND_LOCALE_STRING:
  953. if ( 0 == V_BSTR(&(pDBProp->vValue)) ||
  954. InvalidLCID == GetLCIDFromString(V_BSTR(&(pDBProp->vValue))) )
  955. return S_FALSE;
  956. break;
  957. case MSIDXSPROP_QUERY_RESTRICTION:
  958. // any bstr is valid
  959. break;
  960. default:
  961. // there are no other bstr properties in this property set
  962. return S_FALSE;
  963. }
  964. break;
  965. default:
  966. // the other two prop sets don't have any VT_BSTR properties
  967. return S_FALSE;
  968. }
  969. break;
  970. case VT_EMPTY:
  971. // always valid
  972. break;
  973. default:
  974. // no other types are supported
  975. return S_FALSE;
  976. }
  977. return S_OK; // Is valid
  978. }