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.

1331 lines
31 KiB

  1. //+--------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1996-1998
  5. //
  6. // File: tlsdb.h
  7. //
  8. // Contents: basic class for license table
  9. //
  10. // History:
  11. //
  12. //---------------------------------------------------------------------------
  13. #ifndef __TLSDB_H__
  14. #define __TLSDB_H__
  15. #include "JetBlue.h"
  16. #include "locks.h"
  17. #include "tlsrpc.h"
  18. #define ENUMERATE_COMPARE_NO_FIELDS 0x00000000
  19. #define PROCESS_ALL_COLUMNS 0xFFFFFFFF
  20. #define TLSTABLE_INDEX_DEFAULT_DENSITY TLS_TABLE_INDEX_DEFAULT_DENSITY
  21. #define TLSTABLE_MAX_BINARY_LENGTH 8192
  22. #define RECORD_ENTRY_DELETED 0x01
  23. #if DBG
  24. #define REPORT_IF_FETCH_FAILED( Table, Column, ErrCode ) \
  25. if(ErrCode < JET_errSuccess) { \
  26. DebugOutput(_TEXT("Table %s, Column %s - fetch failed with error code %d\n"), \
  27. Table, Column, ErrCode ); \
  28. }
  29. #define REPORT_IF_INSERT_FAILED( Table, Column, ErrCode ) \
  30. if(ErrCode < JET_errSuccess) { \
  31. DebugOutput(_TEXT("Table %s, Column %s - insert failed with error code %d\n"), \
  32. Table, Column, ErrCode ); \
  33. }
  34. #define REPORTPROCESSFAILED(bFetch, tablename, columnname, jeterror) \
  35. if(bFetch) \
  36. { \
  37. REPORT_IF_FETCH_FAILED(tablename, columnname, jeterror); \
  38. } \
  39. else \
  40. { \
  41. REPORT_IF_INSERT_FAILED(tablename, columnname, jeterror); \
  42. }
  43. #else
  44. #define REPORT_IF_FETCH_FAILED( a, b, c )
  45. #define REPORT_IF_INSERT_FAILED( a, b, c )
  46. #define REPORTPROCESSFAILED( a, b, c, d)
  47. #endif
  48. //
  49. ////////////////////////////////////////////////////////////////
  50. //
  51. // This is to force compiler to check for require member
  52. // function
  53. //
  54. struct TLSColumnBase {
  55. virtual JET_ERR
  56. FetchColumnValue(
  57. PVOID pbData,
  58. DWORD cbData,
  59. DWORD offset,
  60. PDWORD pcbReturnData
  61. ) = 0;
  62. virtual JET_ERR
  63. InsertColumnValue(
  64. PVOID pbData,
  65. DWORD cbData,
  66. DWORD offset
  67. ) = 0;
  68. };
  69. //
  70. ////////////////////////////////////////////////////////////////
  71. //
  72. template<class Type, JET_COLTYP JetColType>
  73. struct TLSColumn : public JBColumnBufferBase, TLSColumnBase {
  74. private:
  75. JBColumn* m_JetColumn;
  76. //--------------------------------------------
  77. JET_ERR
  78. RetrieveColumnValue(
  79. PVOID pbData,
  80. DWORD cbData,
  81. DWORD offset
  82. )
  83. /*
  84. */
  85. {
  86. JB_ASSERT(IsValid() == TRUE);
  87. if(m_JetColumn == NULL)
  88. {
  89. #ifdef DBG
  90. OutputDebugString(
  91. _TEXT("Column buffer not attach to any table...\n")
  92. );
  93. #endif
  94. return JET_errNotInitialized;
  95. }
  96. //JB_ASSERT(pbData != NULL);
  97. //
  98. // TODO - supply conversion routine ???
  99. //
  100. if(m_JetColumn->GetJetColumnType() != JB_COLTYPE_TEXT)
  101. {
  102. // we are using long binary type as long text so ignore
  103. // this one
  104. if(m_JetColumn->GetJetColumnType() != JetColType)
  105. {
  106. //
  107. // this is an internal error
  108. //
  109. JB_ASSERT(m_JetColumn->GetJetColumnType() == JetColType);
  110. m_JetColumn->SetLastJetError(
  111. JET_errInvalidParameter
  112. );
  113. return FALSE;
  114. }
  115. }
  116. BOOL bSuccess;
  117. bSuccess = m_JetColumn->FetchColumn(
  118. pbData,
  119. cbData,
  120. offset
  121. );
  122. return (bSuccess == TRUE) ? JET_errSuccess : m_JetColumn->GetLastJetError();
  123. }
  124. public:
  125. //--------------------------------------------
  126. TLSColumn(
  127. TLSColumn& src
  128. ) :
  129. m_JetColumn(src.m_JetColumn)
  130. /*
  131. */
  132. {
  133. }
  134. //--------------------------------------------
  135. TLSColumn(
  136. JBTable& jbTable,
  137. LPCTSTR pszColumnName
  138. )
  139. /*
  140. */
  141. {
  142. if(AttachToTable(jbTable, pszColumnName) == FALSE)
  143. {
  144. JB_ASSERT(FALSE);
  145. }
  146. }
  147. //--------------------------------------------
  148. TLSColumn() : m_JetColumn(NULL) {}
  149. //--------------------------------------------
  150. JET_ERR
  151. AttachToTable(
  152. JBTable& jbTable,
  153. LPCTSTR pszColumnName
  154. )
  155. /*
  156. */
  157. {
  158. m_JetColumn = jbTable.FindColumnByName(pszColumnName);
  159. return (m_JetColumn != NULL) ? JET_errSuccess : jbTable.GetLastJetError();
  160. }
  161. //--------------------------------------------
  162. BOOL
  163. IsValid()
  164. {
  165. return (m_JetColumn != NULL);
  166. }
  167. //--------------------------------------------
  168. virtual JET_ERR
  169. FetchColumnValue(
  170. PVOID pbData, // buffer for returning data
  171. DWORD cbData, // size of buffer
  172. DWORD offset,
  173. PDWORD pcbReturnData // actual data returned.
  174. )
  175. /*
  176. */
  177. {
  178. JET_ERR jetErr;
  179. jetErr = RetrieveColumnValue(
  180. pbData,
  181. cbData,
  182. offset
  183. );
  184. if(pcbReturnData)
  185. {
  186. *pcbReturnData = GetActualDataSize();
  187. }
  188. return jetErr;
  189. }
  190. //--------------------------------------------
  191. virtual JET_ERR
  192. InsertColumnValue(
  193. PVOID pbData,
  194. DWORD cbData,
  195. DWORD offset
  196. )
  197. /*
  198. */
  199. {
  200. JB_ASSERT(IsValid() == TRUE);
  201. if(m_JetColumn == NULL)
  202. {
  203. #ifdef DBG
  204. OutputDebugString(
  205. _TEXT("Column buffer not attach to any table...\n")
  206. );
  207. #endif
  208. return JET_errNotInitialized;
  209. }
  210. BOOL bSuccess;
  211. bSuccess = m_JetColumn->InsertColumn(
  212. pbData,
  213. cbData,
  214. offset
  215. );
  216. return (bSuccess == TRUE) ? JET_errSuccess : m_JetColumn->GetLastJetError();
  217. }
  218. //--------------------------------------------
  219. JET_ERR
  220. GetLastJetError()
  221. {
  222. return (m_JetColumn) ? m_JetColumn->GetLastJetError() : JET_errNotInitialized;
  223. }
  224. //--------------------------------------------
  225. DWORD
  226. GetActualDataSize()
  227. {
  228. return m_JetColumn->GetDataSize();
  229. }
  230. //-------------------------------------------
  231. JET_COLTYP
  232. GetJetColumnType()
  233. {
  234. return JetColType;
  235. }
  236. //
  237. // Always require calling function to pass in buffer
  238. //
  239. PVOID
  240. GetInputBuffer()
  241. {
  242. JB_ASSERT(FALSE);
  243. return NULL;
  244. }
  245. //-----------------------------------------
  246. PVOID
  247. GetOutputBuffer()
  248. {
  249. JB_ASSERT(FALSE);
  250. return NULL;
  251. }
  252. //-----------------------------------------
  253. DWORD
  254. GetInputBufferLength()
  255. {
  256. return 0;
  257. }
  258. //-----------------------------------------
  259. DWORD
  260. GetOutputBufferLength()
  261. {
  262. return 0;
  263. }
  264. };
  265. // ----------------------------------------------------------
  266. //
  267. // Out text is unicode, JetBlue only support fix length text up
  268. // to 255 characters so we use Long text instead.
  269. //
  270. // JET_coltypBinary
  271. // JET_coltypText
  272. // JET_coltypLongBinary
  273. // JET_coltypLongText
  274. //
  275. // See esent.h
  276. //
  277. typedef TLSColumn<LPTSTR, JET_coltypLongText> TLSColumnText;
  278. typedef TLSColumn<PVOID, JET_coltypLongBinary> TLSColumnBinary;
  279. //
  280. // unsigned byte
  281. typedef TLSColumn<UCHAR, JET_coltypUnsignedByte> TLSColumnUchar;
  282. //
  283. // 2-byte integer, signed
  284. typedef TLSColumn<WORD, JET_coltypShort> TLSColumnShort;
  285. //
  286. // 4-byte integer, signed
  287. typedef TLSColumn<LONG, JET_coltypLong> TLSColumnLong;
  288. //
  289. //
  290. typedef TLSColumn<DWORD, JET_coltypLong> TLSColumnDword;
  291. //
  292. // 4-byte IEEE single precision
  293. typedef TLSColumn<float, JET_coltypIEEESingle> TLSColumnFloat;
  294. //
  295. // 8-byte IEEE double precision
  296. typedef TLSColumn<double, JET_coltypIEEEDouble> TLSColumnDouble;
  297. //
  298. // File Time
  299. typedef TLSColumn<FILETIME, JET_coltypBinary> TLSColumnFileTime;
  300. //--------------------------------------------------------------
  301. JET_ERR
  302. TLSColumnText::InsertColumnValue(
  303. PVOID pbData,
  304. DWORD cbData,
  305. DWORD offset
  306. )
  307. /*
  308. */
  309. {
  310. JB_ASSERT(IsValid() == TRUE);
  311. JET_ERR jetErr;
  312. jetErr = m_JetColumn->InsertColumn(
  313. pbData,
  314. _tcslen((LPTSTR) pbData) * sizeof(TCHAR),
  315. offset
  316. );
  317. return jetErr;
  318. }
  319. //--------------------------------------------------------------
  320. JET_ERR
  321. TLSColumnText::FetchColumnValue(
  322. PVOID pbData,
  323. DWORD cbData,
  324. DWORD offset,
  325. PDWORD pcbDataReturn
  326. )
  327. /*
  328. */
  329. {
  330. PVOID pbBuffer = pbData;
  331. DWORD cbBuffer = cbData;
  332. // Cause recursive call - stack overflow
  333. // if(TLSColumn<Type>::FetchColumnValue(offset, pbData, cbData) == FALSE)
  334. // return m_JetColumn->GetLastJetError();
  335. JET_ERR jetErr = RetrieveColumnValue( pbBuffer, cbBuffer, offset );
  336. if(jetErr == JET_errSuccess)
  337. {
  338. ((LPTSTR)pbBuffer)[(min(cbBuffer, GetActualDataSize())) / sizeof(TCHAR)] = _TEXT('\0');
  339. }
  340. if(pcbDataReturn)
  341. {
  342. *pcbDataReturn = _tcslen((LPTSTR)pbBuffer);
  343. }
  344. return jetErr;
  345. }
  346. //---------------------------------------------------
  347. JET_ERR
  348. TLSColumnFileTime::InsertColumnValue(
  349. PVOID pbData,
  350. DWORD cbData,
  351. DWORD offset
  352. )
  353. /*
  354. */
  355. {
  356. FILETIME ft;
  357. SYSTEMTIME sysTime;
  358. JB_ASSERT(IsValid() == TRUE);
  359. JB_ASSERT(cbData == sizeof(FILETIME));
  360. JET_ERR jetErr;
  361. if(IsValid() == FALSE)
  362. {
  363. jetErr = JET_errNotInitialized;
  364. }
  365. else if(cbData != sizeof(FILETIME) || pbData == NULL)
  366. {
  367. m_JetColumn->SetLastJetError(jetErr = JET_errInvalidParameter);
  368. }
  369. else
  370. {
  371. memset(&ft, 0, sizeof(ft));
  372. if(CompareFileTime(&ft, (FILETIME *)pbData) == 0)
  373. {
  374. GetSystemTime(&sysTime);
  375. SystemTimeToFileTime(&sysTime, &ft);
  376. ((FILETIME *)pbData)->dwLowDateTime = ft.dwLowDateTime;
  377. ((FILETIME *)pbData)->dwHighDateTime = ft.dwHighDateTime;
  378. }
  379. else
  380. {
  381. ft.dwLowDateTime = ((FILETIME *)pbData)->dwLowDateTime;
  382. ft.dwHighDateTime = ((FILETIME *)pbData)->dwHighDateTime;
  383. }
  384. jetErr = m_JetColumn->InsertColumn(
  385. (PVOID)&ft,
  386. sizeof(ft),
  387. 0
  388. );
  389. }
  390. return jetErr;
  391. }
  392. //---------------------------------------------------
  393. JET_ERR
  394. TLSColumnBinary::FetchColumnValue(
  395. PVOID pbData,
  396. DWORD cbData,
  397. DWORD offset,
  398. PDWORD pcbDataReturn
  399. )
  400. /*
  401. */
  402. {
  403. //
  404. // don't worry about buffer size, calling function
  405. // should trap it.
  406. JET_ERR jetErr = RetrieveColumnValue( pbData, cbData, offset );
  407. if(jetErr == JET_errSuccess && pcbDataReturn != NULL)
  408. {
  409. *pcbDataReturn = GetActualDataSize();
  410. }
  411. return jetErr;
  412. }
  413. //
  414. /////////////////////////////////////////////////////////////
  415. //
  416. typedef enum {
  417. RECORD_ENUM_ERROR=0,
  418. RECORD_ENUM_MORE_DATA,
  419. RECORD_ENUM_END
  420. } RECORD_ENUM_RETCODE;
  421. template<class T>
  422. class TLSTable : public JBTable {
  423. /*
  424. Virtual base template class for table used in TLSLicensing
  425. database, template is due to
  426. 1) Static member variable which include column and indexes
  427. in the table.
  428. 2) Type checking - KEYPACK structure only good for one
  429. table.
  430. Class derive from this template must define
  431. 1) static g_Columns, g_NumColumns.
  432. 2) static g_TableIndex, g_NumTableIndex.
  433. 3) static g_TableLock (Might not be necessary)
  434. 4) GetTableName()
  435. 5) FetchRecord
  436. 6) InsertRecord
  437. 7) ResolveToTableColumn()
  438. 8) EnumerationBegin()
  439. 9) EqualValue().
  440. See comment for each member function.
  441. */
  442. protected:
  443. //
  444. // Class derive or inst. from TLSTable<> must define following
  445. //
  446. static TLSJBColumn g_Columns[];
  447. static int g_NumColumns;
  448. static TLSJBIndex g_TableIndex[];
  449. static int g_NumTableIndex;
  450. T m_EnumValue;
  451. BOOL m_EnumMatchAll;
  452. DWORD m_EnumParam;
  453. DWORD m_EnumState; // HIWORD - in enumeration, TRUE/FALSE
  454. // LOWORD - MoveToNext record before fetch.
  455. BYTE m_Key[sizeof(T)];
  456. DWORD m_KeyLength;
  457. BOOL m_bCompareKey; // should we compare key?
  458. BOOL
  459. IsInEnumeration() {
  460. return HIWORD(m_EnumState);
  461. }
  462. BOOL
  463. IsMoveBeforeFetch() {
  464. return LOWORD(m_EnumState);
  465. }
  466. void
  467. SetInEnumeration(
  468. BOOL b
  469. )
  470. {
  471. m_EnumState = MAKELONG(LOWORD(m_EnumState), b);
  472. }
  473. void
  474. SetMoveBeforeFetch(
  475. BOOL b
  476. )
  477. {
  478. m_EnumState = MAKELONG(b, HIWORD(m_EnumState));
  479. }
  480. public:
  481. //
  482. // JetBlue has its own locking
  483. //
  484. static CCriticalSection g_TableLock;
  485. CCriticalSection&
  486. GetTableLock()
  487. {
  488. return g_TableLock;
  489. }
  490. //-------------------------------------------------------
  491. static void
  492. LockTable()
  493. /*
  494. Lock table for exclusive access, JBTable provides
  495. ReadLock/WriteLock for current record
  496. */
  497. {
  498. g_TableLock.Lock();
  499. }
  500. //-------------------------------------------------------
  501. static void
  502. UnlockTable()
  503. /*
  504. Unlock table.
  505. */
  506. {
  507. g_TableLock.UnLock();
  508. }
  509. //-------------------------------------------------------
  510. TLSTable(
  511. JBDatabase& database
  512. ) :
  513. JBTable(database),
  514. m_EnumMatchAll(FALSE),
  515. m_EnumParam(0),
  516. m_EnumState(0),
  517. m_KeyLength(0)
  518. /*
  519. Constructor, must have JBDatabase object.
  520. */
  521. {
  522. memset(&m_EnumValue, 0, sizeof(T));
  523. memset(m_Key, 0, sizeof(m_Key));
  524. }
  525. //-------------------------------------------------------
  526. virtual BOOL
  527. CreateTable()
  528. /*
  529. Create the table, must have g_Columns and g_NumColumns
  530. defined.
  531. */
  532. {
  533. DebugOutput(
  534. _TEXT("TLSTable - Creating Table %s...\n"),
  535. GetTableName()
  536. );
  537. if(BeginTransaction() == FALSE)
  538. return FALSE;
  539. if(CreateOpenTable(GetTableName()) == TRUE)
  540. {
  541. //
  542. // AddColumn() return num of col. created if successful
  543. //
  544. if(AddColumn(g_NumColumns, g_Columns) == g_NumColumns)
  545. {
  546. //
  547. // AddIndex() return 0 if success
  548. //
  549. AddIndex(g_NumTableIndex, g_TableIndex);
  550. }
  551. }
  552. if(IsSuccess() == TRUE)
  553. {
  554. CloseTable();
  555. CommitTransaction();
  556. }
  557. else
  558. {
  559. RollbackTransaction();
  560. }
  561. return IsSuccess();
  562. }
  563. //--------------------------------------------------------
  564. virtual BOOL
  565. UpgradeTable(
  566. IN DWORD dwOldVersion,
  567. IN DWORD dwNewVersion
  568. )
  569. /*++
  570. ++*/
  571. {
  572. if(dwOldVersion == 0)
  573. {
  574. if(OpenTable(TRUE, JET_bitTableUpdatable) == FALSE)
  575. return FALSE;
  576. return CloseTable();
  577. }
  578. else if(dwOldVersion == dwNewVersion)
  579. {
  580. return TRUE;
  581. }
  582. // We only have one version.
  583. JB_ASSERT(FALSE);
  584. return FALSE;
  585. }
  586. //--------------------------------------------------------
  587. virtual BOOL
  588. OpenTable(
  589. IN BOOL bCreateIfNotExist,
  590. IN JET_GRBIT grbit
  591. )
  592. /*
  593. Abstract:
  594. Open the table for access.
  595. Parameter:
  596. bCreateIfNoExist - TRUE, if table does not exist, create it,
  597. FALSE return error if table not exist
  598. */
  599. {
  600. if( JBTable::OpenTable(GetTableName(), NULL, 0, grbit) == FALSE &&
  601. GetLastJetError() == JET_errObjectNotFound &&
  602. bCreateIfNotExist)
  603. {
  604. //
  605. // Close table after it created it
  606. //
  607. if( CreateTable() == FALSE ||
  608. JBTable::OpenTable(GetTableName(), NULL, 0, grbit) == FALSE )
  609. {
  610. return FALSE;
  611. }
  612. }
  613. if(IsSuccess() == TRUE)
  614. {
  615. ResolveToTableColumn();
  616. }
  617. return IsSuccess();
  618. }
  619. //---------------------------------------------------------
  620. //
  621. // pure virtual function to return table name
  622. //
  623. virtual LPCTSTR
  624. GetTableName() = 0;
  625. //---------------------------------------------------------
  626. virtual BOOL
  627. UpdateTable(
  628. IN DWORD dwOldVersion, // unuse
  629. IN DWORD dwNewVersion
  630. )
  631. /*
  632. Abstract:
  633. Upgrade the table.
  634. Parameter:
  635. dwOldVersion - previous table version.
  636. dwNewVersion - current table version.
  637. */
  638. {
  639. // currently nothing to upgrade.
  640. return TRUE;
  641. }
  642. //
  643. // should have fetch/insert record with buffer passed in
  644. //
  645. //---------------------------------------------------------
  646. virtual BOOL
  647. InsertRecord(
  648. T& value,
  649. DWORD dwParam = PROCESS_ALL_COLUMNS
  650. ) = 0;
  651. virtual BOOL
  652. UpdateRecord(
  653. T& value,
  654. DWORD dwParam = PROCESS_ALL_COLUMNS
  655. ) = 0;
  656. //--------------------------------------------------------
  657. virtual BOOL
  658. FetchRecord(
  659. T& value,
  660. DWORD dwParam = PROCESS_ALL_COLUMNS
  661. ) = 0;
  662. //---------------------------------------------------------
  663. virtual BOOL
  664. Cleanup()
  665. {
  666. EnumerateEnd();
  667. return TRUE;
  668. }
  669. //---------------------------------------------------------
  670. virtual BOOL
  671. ResolveToTableColumn() = 0;
  672. //---------------------------------------------------------
  673. virtual JBKeyBase*
  674. EnumerationIndex(
  675. BOOL bMatchAll,
  676. DWORD dwParam,
  677. T* value,
  678. BOOL* bCompareKey
  679. ) = 0;
  680. //------------------------------------------------------
  681. virtual BOOL
  682. EqualValue(
  683. T& src,
  684. T& dest,
  685. BOOL bMatchAll,
  686. DWORD dwMatchParam
  687. ) = 0;
  688. //-------------------------------------------------------
  689. //
  690. // Use user defined comparision function instead of calling
  691. // EqualValue() ???
  692. //
  693. virtual BOOL
  694. EnumerateBegin(
  695. BOOL bMatchAll,
  696. DWORD dwParam,
  697. T* start_value
  698. )
  699. /*
  700. */
  701. {
  702. return EnumerateBegin(
  703. bMatchAll,
  704. dwParam,
  705. start_value,
  706. JET_bitSeekGE
  707. );
  708. }
  709. virtual BOOL
  710. EnumerateBegin(
  711. BOOL bMatchAll,
  712. DWORD dwParam,
  713. T* start_value,
  714. JET_GRBIT jet_seek_grbit
  715. )
  716. /*
  717. */
  718. {
  719. BOOL bRetCode = FALSE;
  720. if(dwParam != ENUMERATE_COMPARE_NO_FIELDS && start_value == NULL)
  721. {
  722. SetLastJetError(JET_errInvalidParameter);
  723. JB_ASSERT(FALSE);
  724. return FALSE;
  725. }
  726. if(IsInEnumeration() == TRUE)
  727. {
  728. SetLastJetError(JET_errInvalidObject);
  729. JB_ASSERT(FALSE);
  730. return FALSE;
  731. }
  732. JBKeyBase* index;
  733. index = EnumerationIndex(
  734. bMatchAll,
  735. dwParam,
  736. start_value,
  737. &m_bCompareKey
  738. );
  739. if(index == NULL)
  740. {
  741. SetLastJetError(JET_errInvalidParameter);
  742. return FALSE;
  743. }
  744. if(start_value == NULL || dwParam == ENUMERATE_COMPARE_NO_FIELDS)
  745. {
  746. //
  747. // position the cursor to first record
  748. //
  749. bRetCode = JBTable::EnumBegin(index);
  750. m_EnumParam = ENUMERATE_COMPARE_NO_FIELDS;
  751. m_EnumMatchAll = FALSE;
  752. // enumerate all record
  753. m_bCompareKey = FALSE;
  754. }
  755. else
  756. {
  757. bRetCode = JBTable::SeekToKey(
  758. index,
  759. dwParam,
  760. jet_seek_grbit
  761. );
  762. if(bRetCode == TRUE && m_bCompareKey)
  763. {
  764. bRetCode = JBTable::RetrieveKey(
  765. m_Key,
  766. sizeof(m_Key),
  767. &m_KeyLength
  768. );
  769. JB_ASSERT(bRetCode == TRUE);
  770. }
  771. }
  772. if(bRetCode == FALSE)
  773. {
  774. if(GetLastJetError() == JET_errRecordNotFound)
  775. {
  776. //
  777. // reset error code to provide same functionality as SQL
  778. //
  779. SetLastJetError(JET_errSuccess);
  780. bRetCode = TRUE;
  781. }
  782. else
  783. {
  784. DebugOutput(
  785. _TEXT("Enumeration on table %s failed with error %d\n"),
  786. GetTableName(),
  787. GetLastJetError()
  788. );
  789. JB_ASSERT(bRetCode);
  790. }
  791. }
  792. if(bRetCode == TRUE)
  793. {
  794. m_EnumParam = dwParam;
  795. m_EnumMatchAll = bMatchAll;
  796. if(start_value)
  797. {
  798. m_EnumValue = *start_value;
  799. }
  800. SetInEnumeration(TRUE);
  801. // cursor in on the the record we want.
  802. SetMoveBeforeFetch(FALSE);
  803. }
  804. delete index;
  805. return bRetCode;
  806. }
  807. //------------------------------------------------------
  808. virtual RECORD_ENUM_RETCODE
  809. EnumerateNext(
  810. IN OUT T& retBuffer,
  811. IN BOOL bReverse=FALSE,
  812. IN BOOL bAnyRecord = FALSE
  813. )
  814. /*
  815. */
  816. {
  817. if(IsInEnumeration() == FALSE)
  818. {
  819. SetLastJetError(JET_errInvalidParameter);
  820. return RECORD_ENUM_ERROR;
  821. }
  822. //CCriticalSectionLocker Lock(GetTableLock());
  823. RECORD_ENUM_RETCODE retCode=RECORD_ENUM_MORE_DATA;
  824. BYTE current_key[sizeof(T)];
  825. unsigned long current_key_length=0;
  826. //
  827. // Support for matching
  828. //
  829. while(TRUE)
  830. {
  831. if(IsMoveBeforeFetch() == TRUE)
  832. {
  833. //
  834. // Position the cursor to next record for next fetch
  835. //
  836. JBTable::ENUM_RETCODE enumCode;
  837. enumCode = EnumNext(
  838. (bReverse == TRUE) ? JET_MovePrevious : JET_MoveNext
  839. );
  840. switch(enumCode)
  841. {
  842. case JBTable::ENUM_SUCCESS:
  843. retCode = RECORD_ENUM_MORE_DATA;
  844. break;
  845. case JBTable::ENUM_ERROR:
  846. retCode = RECORD_ENUM_ERROR;
  847. break;
  848. case JBTable::ENUM_END:
  849. retCode = RECORD_ENUM_END;
  850. }
  851. if(retCode != RECORD_ENUM_MORE_DATA)
  852. break;
  853. }
  854. // fetch entire record
  855. // TODO - fetch necessary fields for comparision, if
  856. // equal then fetch remaining fields
  857. if(FetchRecord(retBuffer, PROCESS_ALL_COLUMNS) == FALSE)
  858. {
  859. retCode = (GetLastJetError() == JET_errNoCurrentRecord ||
  860. GetLastJetError() == JET_errRecordNotFound) ? RECORD_ENUM_END : RECORD_ENUM_ERROR;
  861. break;
  862. }
  863. SetMoveBeforeFetch(TRUE);
  864. // compare the value
  865. if( bAnyRecord == TRUE ||
  866. m_EnumParam == ENUMERATE_COMPARE_NO_FIELDS ||
  867. EqualValue(retBuffer, m_EnumValue, m_EnumMatchAll, m_EnumParam) == TRUE )
  868. {
  869. break;
  870. }
  871. if(m_bCompareKey == TRUE)
  872. {
  873. // compare key to break out of loop
  874. if(JBTable::RetrieveKey(current_key, sizeof(current_key), &current_key_length) == FALSE)
  875. {
  876. retCode = RECORD_ENUM_ERROR;
  877. break;
  878. }
  879. if(memcmp(current_key, m_Key, min(m_KeyLength, current_key_length)) != 0)
  880. {
  881. retCode = RECORD_ENUM_END;
  882. break;
  883. }
  884. }
  885. }
  886. //
  887. // Terminate enumeration if end
  888. //
  889. //if(retCode != RECORD_ENUM_MORE_DATA)
  890. //{
  891. // EnumerateEnd();
  892. //}
  893. return retCode;
  894. }
  895. //------------------------------------------------------
  896. virtual BOOL
  897. EnumerateEnd() {
  898. SetInEnumeration(FALSE);
  899. SetMoveBeforeFetch(FALSE);
  900. m_bCompareKey = FALSE;
  901. return TRUE;
  902. }
  903. //-------------------------------------------------------
  904. virtual DWORD
  905. GetCount(
  906. BOOL bMatchAll,
  907. DWORD dwParam,
  908. T* searchValue
  909. )
  910. /*
  911. */
  912. {
  913. DWORD count = 0;
  914. T value;
  915. RECORD_ENUM_RETCODE retCode;
  916. if(EnumerateBegin(bMatchAll, dwParam, searchValue) == TRUE)
  917. {
  918. while( (retCode=EnumerateNext(value)) == RECORD_ENUM_MORE_DATA )
  919. {
  920. count++;
  921. }
  922. if(retCode == RECORD_ENUM_ERROR)
  923. {
  924. DebugOutput(
  925. _TEXT("GetCount for table %s : EnumerationNext() return %d\n"),
  926. GetTableName(),
  927. GetLastJetError()
  928. );
  929. JB_ASSERT(FALSE);
  930. }
  931. EnumerateEnd();
  932. }
  933. else
  934. {
  935. DebugOutput(
  936. _TEXT("GetCount for table %s : EnumerationBegin return %d\n"),
  937. GetTableName(),
  938. GetLastJetError()
  939. );
  940. JB_ASSERT(FALSE);
  941. }
  942. return count;
  943. }
  944. //-----------------------------------------------------
  945. virtual BOOL
  946. FindRecord(
  947. BOOL bMatchAll,
  948. DWORD dwParam,
  949. T& seachValue,
  950. T& retValue
  951. )
  952. /*
  953. */
  954. {
  955. RECORD_ENUM_RETCODE retCode;
  956. BOOL bSuccess=TRUE;
  957. //CCriticalSectionLocker Lock(GetTableLock());
  958. if(EnumerateBegin(bMatchAll, dwParam, &seachValue) == FALSE)
  959. {
  960. DebugOutput(
  961. _TEXT("SearchValue for table %s : EnumerationBegin return %d\n"),
  962. GetTableName(),
  963. GetLastJetError()
  964. );
  965. JB_ASSERT(FALSE);
  966. bSuccess = FALSE;
  967. goto cleanup;
  968. }
  969. retCode = EnumerateNext(retValue);
  970. EnumerateEnd();
  971. if(retCode == RECORD_ENUM_ERROR)
  972. {
  973. DebugOutput(
  974. _TEXT("SearchValue for table %s : EnumerationNext() return %d\n"),
  975. GetTableName(),
  976. GetLastJetError()
  977. );
  978. bSuccess = FALSE;
  979. JB_ASSERT(FALSE);
  980. }
  981. else if(retCode == RECORD_ENUM_END)
  982. {
  983. SetLastJetError(JET_errRecordNotFound);
  984. bSuccess = FALSE;
  985. }
  986. cleanup:
  987. return bSuccess;
  988. }
  989. //-------------------------------------------------
  990. virtual BOOL
  991. DeleteRecord()
  992. {
  993. //CCriticalSectionLocker Lock(GetTableLock());
  994. return JBTable::DeleteRecord();
  995. }
  996. //-------------------------------------------------
  997. virtual BOOL
  998. DeleteRecord(
  999. DWORD dwParam,
  1000. T& value
  1001. )
  1002. /*
  1003. */
  1004. {
  1005. BOOL bSuccess;
  1006. T Dummy;
  1007. //CCriticalSectionLocker Lock(GetTableLock());
  1008. //
  1009. // Position the current record
  1010. bSuccess = FindRecord(
  1011. TRUE,
  1012. dwParam,
  1013. value,
  1014. Dummy
  1015. );
  1016. if(bSuccess == FALSE)
  1017. return FALSE;
  1018. //
  1019. // Delete the record
  1020. bSuccess = JBTable::DeleteRecord();
  1021. return bSuccess;
  1022. }
  1023. //----------------------------------------------
  1024. virtual BOOL
  1025. DeleteAllRecord(
  1026. BOOL bMatchAll,
  1027. DWORD dwParam,
  1028. T& searchValue
  1029. )
  1030. /*
  1031. */
  1032. {
  1033. int count=0;
  1034. BOOL bSuccess;
  1035. JET_ERR jetErr=JET_errSuccess;
  1036. RECORD_ENUM_RETCODE retCode;
  1037. T value;
  1038. //CCriticalSectionLocker Lock(GetTableLock());
  1039. if(EnumerateBegin(bMatchAll, dwParam, &searchValue) == TRUE)
  1040. {
  1041. while( (retCode=EnumerateNext(value)) == RECORD_ENUM_MORE_DATA )
  1042. {
  1043. count++;
  1044. if(JBTable::DeleteRecord() == FALSE)
  1045. {
  1046. DebugOutput(
  1047. _TEXT("DeleteAllRecord for table %s : return %d\n"),
  1048. GetTableName(),
  1049. GetLastJetError()
  1050. );
  1051. JB_ASSERT(FALSE);
  1052. jetErr = GetLastJetError();
  1053. break;
  1054. }
  1055. }
  1056. //
  1057. // End the enumeration
  1058. //
  1059. if(retCode == RECORD_ENUM_ERROR)
  1060. {
  1061. DebugOutput(
  1062. _TEXT("DeleteAllRecord for table %s : EnumerationNext() return %d\n"),
  1063. GetTableName(),
  1064. GetLastJetError()
  1065. );
  1066. JB_ASSERT(FALSE);
  1067. }
  1068. if(EnumerateEnd() == TRUE)
  1069. {
  1070. // restore error code from DeleteRecord();
  1071. SetLastJetError(jetErr);
  1072. }
  1073. }
  1074. else
  1075. {
  1076. DebugOutput(
  1077. _TEXT("DeleteAllRecord for table %s : EnumerationBegin return %d\n"),
  1078. GetTableName(),
  1079. GetLastJetError()
  1080. );
  1081. }
  1082. // return code is based on number of record deleted and its operation
  1083. if(IsSuccess() == TRUE)
  1084. {
  1085. if(count == 0)
  1086. SetLastJetError(JET_errRecordNotFound);
  1087. }
  1088. return IsSuccess();
  1089. }
  1090. };
  1091. #ifdef __cplusplus
  1092. extern "C" {
  1093. #endif
  1094. BOOL
  1095. TLSDBCopySid(
  1096. PSID pbSrcSid,
  1097. DWORD cbSrcSid,
  1098. PSID* pbDestSid,
  1099. DWORD* cbDestSid
  1100. );
  1101. BOOL
  1102. TLSDBCopyBinaryData(
  1103. PBYTE pbSrcData,
  1104. DWORD cbSrcData,
  1105. PBYTE* ppbDestData,
  1106. DWORD* pcbDestData
  1107. );
  1108. #ifdef __cplusplus
  1109. }
  1110. #endif
  1111. #endif