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.

432 lines
12 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1994 - 1994.
  5. //
  6. // File: tablecur.cxx
  7. //
  8. // Contents: Large table row cursor
  9. //
  10. // Classes: CTableCursor - basic row cursor
  11. // CTableCursorSet - set of row cursors
  12. //
  13. // Functions:
  14. //
  15. // History: 16 Jun 1994 AlanW Created
  16. //
  17. //--------------------------------------------------------------------------
  18. #include "pch.cxx"
  19. #pragma hdrstop
  20. #include <query.hxx> // SBindSizes
  21. #include <tblvarnt.hxx>
  22. #include "tblrowal.hxx"
  23. #include "tabledbg.hxx"
  24. //
  25. // Generate the implementation of the cursor set base class
  26. //
  27. IMPL_DYNARRAY( CTableCursorArray, CTableCursor )
  28. //+-------------------------------------------------------------------------
  29. //
  30. // Member: CTableCursor::CTableCursor, public
  31. //
  32. // Synopsis: Constructor for a table cursor
  33. //
  34. // Notes:
  35. //
  36. //--------------------------------------------------------------------------
  37. CTableCursor::CTableCursor( void ) :
  38. _hUnique( 0 ),
  39. _cbRowWidth( 0 ),
  40. _BoundColumns( 0 )
  41. {
  42. }
  43. //+-------------------------------------------------------------------------
  44. //
  45. // Member: CTableCursor::~CTableCursor, public
  46. //
  47. // Synopsis: Destructor for a table cursor
  48. //
  49. // Notes:
  50. //
  51. //--------------------------------------------------------------------------
  52. CTableCursor::~CTableCursor( void )
  53. {
  54. }
  55. //+---------------------------------------------------------------------------
  56. //
  57. // Member: CTableCursor::SetBindings, public
  58. //
  59. // Synopsis: Set new column bindings on the cursor
  60. //
  61. // Arguments: [cbRowLength] - width of output rows
  62. // [NewColumns] - CTableColumnSet giving new bindings
  63. //
  64. // Returns: SCODE - S_OK if succeeded, E_FAIL if cbRowLength exceeds
  65. // length we're willing to transfer, otherwise according
  66. // to spec.
  67. //
  68. // Notes:
  69. //
  70. //----------------------------------------------------------------------------
  71. SCODE
  72. CTableCursor::SetBindings(
  73. ULONG cbRowLength,
  74. XPtr<CTableColumnSet> & NewColumns
  75. ) {
  76. //
  77. // Do some simple checks first
  78. //
  79. if (0 == cbRowLength || cbRowLength > TBL_MAX_OUTROWLENGTH)
  80. return E_INVALIDARG; // provider-specific error
  81. //
  82. // Check bindings in case they have been hacked. Ordinarily, it would
  83. // be a bug if they were wrong.
  84. // Check that each column is valid and doesn't overlap some other
  85. // column.
  86. //
  87. {
  88. CTableRowAlloc RowMap(cbRowLength);
  89. SCODE scResult = _CheckBindings(NewColumns.GetReference(),
  90. RowMap,
  91. (USHORT) cbRowLength);
  92. if (FAILED(scResult))
  93. return scResult;
  94. }
  95. //
  96. // All the proposed bindings check out. Set them as the
  97. // currently bound columns, and delete any old bindings.
  98. //
  99. unsigned iNewCol = 0;
  100. CTableColumnSet * pOldCols = _BoundColumns.Acquire();
  101. _BoundColumns.Set( NewColumns.Acquire() );
  102. delete pOldCols;
  103. _cbRowWidth = (USHORT) cbRowLength;
  104. return S_OK;
  105. }
  106. //+-------------------------------------------------------------------------
  107. //
  108. // Member: CTableCursor::_CheckBinding, public
  109. // CTableCursor::_CheckBindings, public
  110. //
  111. // Synopsis: Check that a column binding is legal. _CheckBindings does
  112. // the same for an entire set of column bindings.
  113. //
  114. // Arguments: [rCol] - A reference to the column binding to be checked
  115. // [rRowAlloc] - a reference to a row allocation map
  116. // [maxRow] - maximum allowed size of a row
  117. //
  118. // Returns: SCODE - S_OK if no problems, otherwise the appropriate
  119. // error code for the failure.
  120. //
  121. // Notes:
  122. //
  123. //--------------------------------------------------------------------------
  124. SCODE CTableCursor::_CheckBinding(
  125. CTableColumn const & rCol,
  126. CTableRowAlloc& rRowAlloc,
  127. USHORT maxRow
  128. ) {
  129. //
  130. // Check some static things about the binding structure
  131. //
  132. if (0 == rCol.IsValueStored() &&
  133. 0 == rCol.IsStatusStored() &&
  134. 0 == rCol.IsLengthStored() )
  135. {
  136. tbDebugOut((DEB_IWARN,
  137. "CTableCursor::_CheckBinding - no value, length or status stored\n"));
  138. return DB_E_BADBINDINFO;
  139. }
  140. ULONG cbData = rCol.GetValueSize();
  141. USHORT cbWidth, cbAlign, gfFlags;
  142. //
  143. // Look up required width of field.
  144. //
  145. CTableVariant::VartypeInfo(rCol.GetStoredType(), cbWidth, cbAlign, gfFlags);
  146. if (cbData != cbWidth && !(gfFlags & CTableVariant::MultiSize))
  147. {
  148. tbDebugOut((DEB_IWARN, "CTableCursor::_CheckBinding - incorrect field width\n"));
  149. return DB_E_BADBINDINFO;
  150. }
  151. if ( rCol.GetStoredType() & VT_VECTOR )
  152. {
  153. tbDebugOut((DEB_IWARN, "CTableCursor::_CheckBinding - direct vector\n"));
  154. return DB_E_BADBINDINFO;
  155. }
  156. if (rCol.GetValueOffset() + cbData > maxRow)
  157. {
  158. tbDebugOut((DEB_IWARN, "CTableCursor::_CheckBinding - bad data offset\n"));
  159. return DB_E_BADBINDINFO;
  160. }
  161. if (rCol.IsStatusStored() &&
  162. rCol.GetStatusOffset() + rCol.GetStatusSize() > maxRow)
  163. {
  164. tbDebugOut((DEB_IWARN, "CTableCursor::_CheckBinding - bad status offset\n"));
  165. return DB_E_BADBINDINFO;
  166. }
  167. if (rCol.IsLengthStored() &&
  168. rCol.GetLengthOffset() + rCol.GetLengthSize() > maxRow)
  169. {
  170. tbDebugOut((DEB_IWARN, "CTableCursor::_CheckBinding - bad length offset\n"));
  171. return DB_E_BADBINDINFO;
  172. }
  173. //
  174. // Check to see if any fields overlap with previously allocated ones
  175. //
  176. if (rCol.IsValueStored() &&
  177. ! rRowAlloc.ReserveRowSpace( rCol.GetValueOffset(), cbData ))
  178. {
  179. tbDebugOut((DEB_IWARN, "CTableCursor::_CheckBinding - value data overlap\n"));
  180. return DB_E_BADBINDINFO;
  181. }
  182. if (rCol.IsStatusStored() &&
  183. ! rRowAlloc.ReserveRowSpace( rCol.GetStatusOffset(), rCol.GetStatusSize() ))
  184. {
  185. tbDebugOut((DEB_IWARN, "CTableCursor::_CheckBinding - status data overlap\n"));
  186. return DB_E_BADBINDINFO;
  187. }
  188. if (rCol.IsLengthStored() &&
  189. ! rRowAlloc.ReserveRowSpace( rCol.GetLengthOffset(), rCol.GetLengthSize() ))
  190. {
  191. tbDebugOut((DEB_IWARN, "CTableCursor::_CheckBinding - length data overlap\n"));
  192. return DB_E_BADBINDINFO;
  193. }
  194. return S_OK;
  195. }
  196. SCODE CTableCursor::_CheckBindings(
  197. CTableColumnSet const & rCols,
  198. CTableRowAlloc& rRowAlloc,
  199. USHORT maxRow
  200. ) {
  201. Win4Assert(maxRow > 0);
  202. for (unsigned i = 0; i < rCols.Count(); i++)
  203. {
  204. SCODE sc = _CheckBinding(*rCols.Get(i), rRowAlloc, maxRow);
  205. if (FAILED(sc))
  206. return sc;
  207. }
  208. return S_OK;
  209. }
  210. //+-------------------------------------------------------------------------
  211. //
  212. // Member: CTableCursorSet::~CTableCursorSet, public
  213. //
  214. // Synopsis: Destroy a table cursor set
  215. //
  216. // Arguments: [hCursor] -- The handle of the cursor to be looked up
  217. //
  218. // Returns: - nothing -
  219. //
  220. // Notes:
  221. //
  222. //--------------------------------------------------------------------------
  223. CTableCursorSet::~CTableCursorSet( )
  224. {
  225. #if CIDBG
  226. for (unsigned i = 0; i < Size(); i++) {
  227. if (Get(i) && Get(i)->_hUnique != 0) {
  228. tbDebugOut((DEB_WARN, "Unreleased table cursor\n"));
  229. }
  230. }
  231. #endif // CIDBG
  232. }
  233. //+-------------------------------------------------------------------------
  234. //
  235. // Member: CTableCursorSet::Lookup, public
  236. //
  237. // Synopsis: Find a table cursor given its handle
  238. //
  239. // Arguments: [hCursor] -- The handle of the cursor to be looked up
  240. //
  241. // Returns: CTableCursor& - reference to cursor
  242. //
  243. // Signals: Throws E_FAIL if error.
  244. //
  245. // Notes:
  246. //
  247. //--------------------------------------------------------------------------
  248. CTableCursor&
  249. CTableCursorSet::Lookup( ULONG hCursor )
  250. {
  251. USHORT iCursor = (USHORT) (hCursor & 0xFFFF);
  252. USHORT hUnique = (USHORT) (hCursor >> 16);
  253. Win4Assert(hUnique > 0 && iCursor < Size());
  254. if (hUnique == 0 || iCursor >= Size()) {
  255. THROW(CException(E_FAIL));
  256. }
  257. if (Get(iCursor) == 0 || Get(iCursor)->_hUnique != hUnique)
  258. THROW(CException(E_FAIL));
  259. return *Get(iCursor);
  260. }
  261. //+-------------------------------------------------------------------------
  262. //
  263. // Member: CTableCursorSet::Add, public
  264. //
  265. // Synopsis: Add a table cursor to a table cursor set.
  266. //
  267. // Arguments: [pCursorIn] -- A pointer to the cursor description to be
  268. // added.
  269. // [rhCursor] -- on return, the handle value assigned to the
  270. // cursor.
  271. //
  272. // Returns: -Nothing-
  273. //
  274. // Notes:
  275. //
  276. //--------------------------------------------------------------------------
  277. void
  278. CTableCursorSet::Add( CTableCursor * const pCursorIn, ULONG &rhCursor )
  279. {
  280. //
  281. // Find an unused handle uniquifier. The for loop may be
  282. // overkill since we also use the array index in the real handle.
  283. //
  284. USHORT hUnique;
  285. do {
  286. hUnique = ++_hKeyGenerator;
  287. if (hUnique == 0)
  288. continue;
  289. for (unsigned j = 0; j < Size(); j++) {
  290. if (Get(j) && hUnique == Get(j)->_hUnique) {
  291. hUnique = 0;
  292. break; // break for, continue do-while
  293. }
  294. }
  295. } while (hUnique == 0);
  296. unsigned i;
  297. for (i = 0; i < Size(); i++) {
  298. if ( Get(i) == 0 )
  299. break;
  300. }
  301. //
  302. // Add the new entry to the set.
  303. //
  304. pCursorIn->_hUnique = hUnique;
  305. CTableCursorArray::Add(pCursorIn, i);
  306. Win4Assert( i < 0x10000 );
  307. rhCursor = (hUnique << 16) | i;
  308. return;
  309. }
  310. //+-------------------------------------------------------------------------
  311. //
  312. // Member: CTableCursorSet::Release, public
  313. //
  314. // Synopsis: Free an allocated table cursor
  315. //
  316. // Arguments: [hCursor] -- The handle of the cursor to be released
  317. //
  318. // Returns: SCODE - S_OK if lookup succeeded, E_FAIL if problems.
  319. //
  320. // Notes:
  321. //
  322. //--------------------------------------------------------------------------
  323. SCODE
  324. CTableCursorSet::Release(ULONG hCursor)
  325. {
  326. USHORT iCursor = (USHORT) (hCursor & 0xFFFF);
  327. USHORT hUnique = (USHORT) (hCursor >> 16);
  328. Win4Assert(hUnique > 0 && iCursor < Size());
  329. if (hUnique == 0 || iCursor >= Size() || Get(iCursor) == 0) {
  330. return E_FAIL;
  331. }
  332. CTableCursor * pCursor = Get(iCursor);
  333. if (pCursor->_hUnique != hUnique)
  334. return E_FAIL;
  335. //
  336. // Found the cursor, now free it and its location in the array.
  337. //
  338. pCursor = CTableCursorArray::Acquire( iCursor );
  339. delete pCursor;
  340. return S_OK;
  341. }
  342. //+-------------------------------------------------------------------------
  343. //
  344. // Member: CTableCursorSet::Count, public
  345. //
  346. // Synopsis: Counts the number of cursors in the set
  347. //
  348. // Returns: # of cursors in the set
  349. //
  350. //--------------------------------------------------------------------------
  351. unsigned CTableCursorSet::Count()
  352. {
  353. unsigned cCursors = 0;
  354. for ( unsigned i = 0; i < Size(); i++)
  355. {
  356. if ( 0 != Get(i) )
  357. cCursors++;
  358. }
  359. return cCursors;
  360. }