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.

887 lines
40 KiB

  1. //--------------------------------------------------------------------------
  2. // Database.h
  3. //--------------------------------------------------------------------------
  4. #pragma once
  5. //--------------------------------------------------------------------------
  6. // Depends
  7. //--------------------------------------------------------------------------
  8. #include "utility.h"
  9. #include "query.h"
  10. #include "listen.h"
  11. //--------------------------------------------------------------------------
  12. // Forward Decls
  13. //--------------------------------------------------------------------------
  14. class CDatabaseQuery;
  15. //--------------------------------------------------------------------------
  16. // DwordAlign
  17. //--------------------------------------------------------------------------
  18. inline DWORD DwordAlign(DWORD cb) {
  19. DWORD dw = (cb % 4); return(0 == dw ? 0 : (4 - dw));
  20. }
  21. //--------------------------------------------------------------------------
  22. // String Constants
  23. //--------------------------------------------------------------------------
  24. #define CCHMAX_DB_FILEPATH (MAX_PATH + MAX_PATH)
  25. //--------------------------------------------------------------------------
  26. // DESCENDING
  27. //--------------------------------------------------------------------------
  28. #define DESCENDING(_nCompare) ((_nCompare < 0) ? 1 : -1)
  29. typedef DWORD TICKCOUNT;
  30. //--------------------------------------------------------------------------
  31. // Version and Signatures
  32. //--------------------------------------------------------------------------
  33. #define BTREE_SIGNATURE 0xfe12adcf
  34. #define BTREE_VERSION 5
  35. //--------------------------------------------------------------------------
  36. // B-Tree Chain Sizes
  37. //--------------------------------------------------------------------------
  38. #define BTREE_ORDER 50
  39. #define BTREE_MIN_CAP 25
  40. //--------------------------------------------------------------------------
  41. // Upper Limit on Various Resources
  42. //--------------------------------------------------------------------------
  43. #define CMAX_OPEN_STREAMS 512
  44. #define CMAX_OPEN_ROWSETS 32
  45. #define CMAX_RECIPIENTS 15
  46. #define CMAX_CLIENTS 32
  47. //--------------------------------------------------------------------------
  48. // Block Allocate Page Sizes
  49. //--------------------------------------------------------------------------
  50. #define CB_CHAIN_PAGE 15900
  51. #define CB_STREAM_PAGE 63360
  52. #define CB_VARIABLE_PAGE 49152
  53. #define CB_STREAM_BLOCK 512
  54. #define CC_MAX_BLOCK_TYPES 16
  55. //--------------------------------------------------------------------------
  56. // Variable Length Block Allocation Sizes
  57. //--------------------------------------------------------------------------
  58. #define CB_ALIGN_LARGE 1024
  59. #define CB_FREE_BUCKET 4
  60. #define CC_FREE_BUCKETS 2048
  61. #define CB_MIN_FREE_BUCKET 32
  62. #define CB_MAX_FREE_BUCKET (CB_MIN_FREE_BUCKET + (CB_FREE_BUCKET * CC_FREE_BUCKETS))
  63. //--------------------------------------------------------------------------
  64. // Heap Block Cache
  65. //--------------------------------------------------------------------------
  66. #define CB_HEAP_BUCKET 8
  67. #define CC_HEAP_BUCKETS 1024
  68. #define CB_MAX_HEAP_BUCKET (CB_HEAP_BUCKET * CC_HEAP_BUCKETS)
  69. //--------------------------------------------------------------------------
  70. // Other Constants
  71. //--------------------------------------------------------------------------
  72. #define MEMORY_GUARD_SIGNATURE 0xdeadbeef
  73. #define DELETE_ON_CLOSE TRUE
  74. //--------------------------------------------------------------------------
  75. // File Mapping Constants
  76. //--------------------------------------------------------------------------
  77. #define CB_MAPPED_VIEW 10485760
  78. //--------------------------------------------------------------------------
  79. // Forward Decls
  80. //--------------------------------------------------------------------------
  81. class CProgress;
  82. class CDatabase;
  83. class CDatabaseStream;
  84. //--------------------------------------------------------------------------
  85. // Locking Values
  86. //--------------------------------------------------------------------------
  87. #define LOCK_VALUE_NONE 0
  88. #define LOCK_VALUE_WRITER -1
  89. //--------------------------------------------------------------------------
  90. // STREAMINDEX
  91. //--------------------------------------------------------------------------
  92. typedef WORD STREAMINDEX;
  93. typedef LPWORD LPSTREAMINDEX;
  94. #define INVALID_STREAMINDEX 0xffff
  95. //--------------------------------------------------------------------------
  96. // ROWSETORDINAL
  97. //--------------------------------------------------------------------------
  98. typedef BYTE ROWSETORDINAL;
  99. //--------------------------------------------------------------------------
  100. // FILEADDRESS
  101. //--------------------------------------------------------------------------
  102. typedef DWORD FILEADDRESS;
  103. typedef LPDWORD LPFILEADDRESS;
  104. //--------------------------------------------------------------------------
  105. // NODEINDEX
  106. //--------------------------------------------------------------------------
  107. typedef BYTE NODEINDEX;
  108. typedef BYTE *LPNODEINDEX;
  109. #define INVALID_NODEINDEX 0xff
  110. //--------------------------------------------------------------------------
  111. // BLOCKTYPE
  112. //--------------------------------------------------------------------------
  113. typedef enum tagBLOCKTYPE {
  114. BLOCK_RECORD,
  115. BLOCK_STRING,
  116. BLOCK_RESERVED1,
  117. BLOCK_TRANSACTION,
  118. BLOCK_CHAIN,
  119. BLOCK_STREAM,
  120. BLOCK_FREE,
  121. BLOCK_ENDOFPAGE,
  122. BLOCK_RESERVED2,
  123. BLOCK_RESERVED3,
  124. BLOCK_LAST
  125. } BLOCKTYPE;
  126. //--------------------------------------------------------------------------
  127. // CHAINDELETETYPE
  128. //--------------------------------------------------------------------------
  129. typedef enum tagCHAINDELETETYPE {
  130. CHAIN_DELETE_SHARE,
  131. CHAIN_DELETE_COALESCE
  132. } CHAINDELETETYPE;
  133. //--------------------------------------------------------------------------
  134. // CHAINSHARETYPE
  135. //--------------------------------------------------------------------------
  136. typedef enum tagCHAINSHARETYPE {
  137. CHAIN_SHARE_LEFT,
  138. CHAIN_SHARE_RIGHT
  139. } CHAINSHARETYPE;
  140. //--------------------------------------------------------------------------
  141. // OPERATIONTYPE - Specifies how _UnlinkRecordFromTable from table works
  142. //--------------------------------------------------------------------------
  143. typedef enum tagOPERATIONTYPE {
  144. OPERATION_DELETE,
  145. OPERATION_UPDATE,
  146. OPERATION_INSERT
  147. } OPERATIONTYPE;
  148. //--------------------------------------------------------------------------
  149. // INVOKETYPE
  150. //--------------------------------------------------------------------------
  151. typedef enum tagINVOKETYPE {
  152. INVOKE_RELEASEMAP = 100,
  153. INVOKE_CREATEMAP = 101,
  154. INVOKE_CLOSEFILE = 102,
  155. INVOKE_OPENFILE = 103,
  156. INVOKE_OPENMOVEDFILE = 104
  157. } INVOKETYPE;
  158. //--------------------------------------------------------------------------
  159. // FINDRESULT
  160. //--------------------------------------------------------------------------
  161. typedef struct tagFINDRESULT {
  162. FILEADDRESS faChain;
  163. NODEINDEX iNode;
  164. BYTE fChanged;
  165. BYTE fFound;
  166. INT nCompare;
  167. } FINDRESULT, *LPFINDRESULT;
  168. //--------------------------------------------------------------------------
  169. // ALLOCATEPAGE
  170. //--------------------------------------------------------------------------
  171. #pragma pack(4)
  172. typedef struct tagALLOCATEPAGE {
  173. FILEADDRESS faPage;
  174. DWORD cbPage;
  175. DWORD cbUsed;
  176. } ALLOCATEPAGE, *LPALLOCATEPAGE;
  177. #pragma pack()
  178. //--------------------------------------------------------------------------
  179. // TABLEHEADER
  180. //--------------------------------------------------------------------------
  181. #pragma pack(4)
  182. typedef struct tagTABLEHEADER {
  183. DWORD dwSignature; // 4
  184. CLSID clsidExtension; // 20
  185. DWORD dwMinorVersion; // 24
  186. DWORD dwMajorVersion; // 28
  187. DWORD cbUserData; // 32
  188. FILEADDRESS faCatalogOld; // 36
  189. ALLOCATEPAGE AllocateRecord; // 48
  190. ALLOCATEPAGE AllocateChain; // 60
  191. ALLOCATEPAGE AllocateStream; // 72
  192. FILEADDRESS faFreeStreamBlock; // 76
  193. FILEADDRESS faFreeChainBlock; // 80
  194. FILEADDRESS faFreeLargeBlock; // 84
  195. DWORD cbAllocated; // 88
  196. DWORD cbFreed; // 92
  197. DWORD dwNextId; // 96
  198. DWORD fCorrupt; // 100
  199. DWORD fCorruptCheck; // 104
  200. DWORD cActiveThreads; // 108
  201. FILEADDRESS faTransactHead; // 112
  202. FILEADDRESS faTransactTail; // 116
  203. DWORD cTransacts; // 120
  204. DWORD cBadCloses; // 124
  205. FILEADDRESS faNextAllocate; // 128
  206. DWORD cIndexes; // 132
  207. FILEADDRESS rgfaFilter[CMAX_INDEXES]; // 164
  208. DWORD rgbReserved5[8]; // 196
  209. DWORD rgcRecords[CMAX_INDEXES]; // 228
  210. FILEADDRESS rgfaIndex[CMAX_INDEXES]; // 260
  211. INDEXORDINAL rgiIndex[CMAX_INDEXES]; // 292
  212. BYTE rgbReserved4[116]; // 408
  213. BYTE fReserved; // 409
  214. DWORD rgbReserved6[8]; // 196
  215. BYTE rgdwReserved2[192]; // 637
  216. DWORD rgcbAllocated[CC_MAX_BLOCK_TYPES]; // 701
  217. FILEADDRESS rgfaFreeBlock[CC_FREE_BUCKETS]; // 8893
  218. TABLEINDEX rgIndexInfo[CMAX_INDEXES]; // 9293
  219. WORD wTransactSize; // 9405
  220. BYTE rgdwReserved3[110];
  221. } TABLEHEADER, *LPTABLEHEADER;
  222. #pragma pack()
  223. //--------------------------------------------------------------------------
  224. // BLOCKHEADER
  225. //--------------------------------------------------------------------------
  226. #pragma pack(4)
  227. typedef struct tagBLOCKHEADER {
  228. FILEADDRESS faBlock;
  229. DWORD cbSize;
  230. } BLOCKHEADER, *LPBLOCKHEADER;
  231. #pragma pack()
  232. //--------------------------------------------------------------------------
  233. // FREEBLOCK
  234. //--------------------------------------------------------------------------
  235. #pragma pack(4)
  236. typedef struct tagFREEBLOCK : public BLOCKHEADER {
  237. DWORD cbBlock;
  238. DWORD dwReserved;
  239. FILEADDRESS faNext;
  240. } FREEBLOCK, *LPFREEBLOCK;
  241. #pragma pack()
  242. //--------------------------------------------------------------------------
  243. // CHAINNODE
  244. //--------------------------------------------------------------------------
  245. #pragma pack(4)
  246. typedef struct tagCHAINNODE {
  247. FILEADDRESS faRecord;
  248. FILEADDRESS faRightChain;
  249. DWORD cRightNodes;
  250. } CHAINNODE, *LPCHAINNODE;
  251. #pragma pack()
  252. //--------------------------------------------------------------------------
  253. // CHAINBLOCK - 636
  254. //--------------------------------------------------------------------------
  255. #pragma pack(4)
  256. typedef struct tagCHAINBLOCK : public BLOCKHEADER {
  257. FILEADDRESS faLeftChain;
  258. FILEADDRESS faParent;
  259. BYTE iParent;
  260. BYTE cNodes;
  261. WORD wReserved;
  262. DWORD cLeftNodes;
  263. CHAINNODE rgNode[BTREE_ORDER + 1];
  264. } CHAINBLOCK, *LPCHAINBLOCK;
  265. #pragma pack()
  266. //--------------------------------------------------------------------------
  267. // STREAMBLOCK
  268. //--------------------------------------------------------------------------
  269. #pragma pack(4)
  270. typedef struct tagSTREAMBLOCK : public BLOCKHEADER {
  271. DWORD cbData;
  272. FILEADDRESS faNext;
  273. } STREAMBLOCK, *LPSTREAMBLOCK;
  274. #pragma pack()
  275. //--------------------------------------------------------------------------
  276. // RECORDBLOCK
  277. //--------------------------------------------------------------------------
  278. #pragma pack(4)
  279. typedef struct tagRECORDBLOCK : public BLOCKHEADER {
  280. WORD wReserved;
  281. BYTE cTags;
  282. BYTE bVersion;
  283. } RECORDBLOCK, *LPRECORDBLOCK;
  284. #pragma pack()
  285. //--------------------------------------------------------------------------
  286. // COLUMNTAG
  287. //--------------------------------------------------------------------------
  288. #define TAG_DATA_MASK 0xFF800000
  289. #pragma pack(4)
  290. typedef struct tagCOLUMNTAG {
  291. unsigned iColumn : 7;
  292. unsigned fData : 1;
  293. unsigned Offset : 24;
  294. } COLUMNTAG, *LPCOLUMNTAG;
  295. #pragma pack()
  296. //--------------------------------------------------------------------------
  297. // RECORDMAP
  298. //--------------------------------------------------------------------------
  299. typedef struct tagRECORDMAP {
  300. LPCTABLESCHEMA pSchema;
  301. BYTE cTags;
  302. LPCOLUMNTAG prgTag;
  303. DWORD cbTags;
  304. DWORD cbData;
  305. LPBYTE pbData;
  306. } RECORDMAP, *LPRECORDMAP;
  307. //--------------------------------------------------------------------------
  308. // OPENSTREAM
  309. //--------------------------------------------------------------------------
  310. typedef struct tagOPENSTREAM {
  311. BYTE fInUse;
  312. FILEADDRESS faStart;
  313. FILEADDRESS faMoved;
  314. DWORD cOpenCount;
  315. LONG lLock;
  316. BYTE fDeleteOnClose;
  317. } OPENSTREAM, *LPOPENSTREAM;
  318. //--------------------------------------------------------------------------
  319. // NOTIFYRECIPIENT
  320. //--------------------------------------------------------------------------
  321. typedef struct tagNOTIFYRECIPIENT {
  322. HWND hwndNotify;
  323. DWORD dwThreadId;
  324. DWORD_PTR dwCookie;
  325. BYTE fSuspended;
  326. BYTE fRelease;
  327. BYTE fOrdinalsOnly;
  328. DWORD_PTR pNotify;
  329. INDEXORDINAL iIndex;
  330. } NOTIFYRECIPIENT, *LPNOTIFYRECIPIENT;
  331. //--------------------------------------------------------------------------
  332. // CLIENTENTRY
  333. //--------------------------------------------------------------------------
  334. typedef struct tagCLIENTENTRY {
  335. HWND hwndListen;
  336. DWORD dwProcessId;
  337. DWORD dwThreadId;
  338. DWORD_PTR pDB;
  339. DWORD cRecipients;
  340. NOTIFYRECIPIENT rgRecipient[CMAX_RECIPIENTS];
  341. } CLIENTENTRY, *LPCLIENTENTRY;
  342. //--------------------------------------------------------------------------
  343. // TRANSACTIONBLOCK
  344. //--------------------------------------------------------------------------
  345. #pragma pack(4)
  346. typedef struct tagTRANSACTIONBLOCK : public BLOCKHEADER {
  347. TRANSACTIONTYPE tyTransaction;
  348. WORD cRefs;
  349. INDEXORDINAL iIndex;
  350. ORDINALLIST Ordinals;
  351. FILEADDRESS faRecord1;
  352. FILEADDRESS faRecord2;
  353. FILEADDRESS faNext;
  354. FILEADDRESS faPrevious;
  355. FILEADDRESS faNextInBatch;
  356. } TRANSACTIONBLOCK, *LPTRANSACTIONBLOCK;
  357. #pragma pack()
  358. //--------------------------------------------------------------------------
  359. // ROWSETINFO
  360. //--------------------------------------------------------------------------
  361. typedef struct tagROWSETINFO {
  362. ROWSETORDINAL iRowset;
  363. INDEXORDINAL iIndex;
  364. ROWORDINAL iRow;
  365. } ROWSETINFO, *LPROWSETINFO;
  366. //--------------------------------------------------------------------------
  367. // ROWSETTABLE
  368. //--------------------------------------------------------------------------
  369. typedef struct tagROWSETTABLE {
  370. BYTE fInitialized;
  371. BYTE cFree;
  372. BYTE cUsed;
  373. ROWSETORDINAL rgiFree[CMAX_OPEN_ROWSETS];
  374. ROWSETORDINAL rgiUsed[CMAX_OPEN_ROWSETS];
  375. ROWSETINFO rgRowset[CMAX_OPEN_ROWSETS];
  376. } ROWSETTABLE, *LPROWSETTABLE;
  377. //--------------------------------------------------------------------------
  378. // SHAREDDATABASE
  379. //--------------------------------------------------------------------------
  380. typedef struct tagSHAREDDATABASE {
  381. WCHAR szFile[CCHMAX_DB_FILEPATH];
  382. LONG cWaitingForLock;
  383. BYTE fCompacting;
  384. DWORD dwVersion;
  385. DWORD dwQueryVersion;
  386. DWORD cNotifyLock;
  387. FILEADDRESS faTransactLockHead;
  388. FILEADDRESS faTransactLockTail;
  389. OPENSTREAM rgStream[CMAX_OPEN_STREAMS];
  390. DWORD cClients;
  391. DWORD cNotifyOrdinalsOnly;
  392. DWORD cNotifyWithData;
  393. DWORD cNotify;
  394. DWORD rgcIndexNotify[CMAX_INDEXES];
  395. CLIENTENTRY rgClient[CMAX_CLIENTS];
  396. ROWSETTABLE Rowsets;
  397. IF_DEBUG(BYTE fRepairing;)
  398. } SHAREDDATABASE, *LPSHAREDDATABASE;
  399. //--------------------------------------------------------------------------
  400. // INVOKEPACKAGE
  401. //--------------------------------------------------------------------------
  402. typedef struct tagINVOKEPACKAGE {
  403. INVOKETYPE tyInvoke;
  404. DWORD_PTR pDB;
  405. } INVOKEPACKAGE, *LPINVOKEPACKAGE;
  406. //--------------------------------------------------------------------------
  407. // MARKBLOCK
  408. //--------------------------------------------------------------------------
  409. typedef struct tagMARKBLOCK {
  410. DWORD cbBlock;
  411. } MARKBLOCK, *LPMARKBLOCK;
  412. //--------------------------------------------------------------------------
  413. // FILEVIEW
  414. //--------------------------------------------------------------------------
  415. typedef struct tagFILEVIEW *LPFILEVIEW;
  416. typedef struct tagFILEVIEW {
  417. FILEADDRESS faView;
  418. LPBYTE pbView;
  419. DWORD cbView;
  420. LPFILEVIEW pNext;
  421. } FILEVIEW, *LPFILEVIEW;
  422. //--------------------------------------------------------------------------
  423. // STORAGEINFO
  424. //--------------------------------------------------------------------------
  425. typedef struct tagSTORAGEINFO {
  426. LPWSTR pszMap;
  427. HANDLE hFile;
  428. HANDLE hMap;
  429. HANDLE hShare;
  430. DWORD cbFile;
  431. #ifdef BACKGROUND_MONITOR
  432. TICKCOUNT tcMonitor;
  433. #endif
  434. DWORD cbMappedViews;
  435. DWORD cbMappedSpecial;
  436. DWORD cAllocated;
  437. DWORD cSpecial;
  438. LPFILEVIEW prgView;
  439. LPFILEVIEW pSpecial;
  440. } STORAGEINFO, *LPSTORAGEINFO;
  441. //--------------------------------------------------------------------------
  442. // MEMORYTAG
  443. //--------------------------------------------------------------------------
  444. typedef struct tagMEMORYTAG {
  445. DWORD dwSignature;
  446. DWORD cbSize;
  447. LPVOID pNext;
  448. } MEMORYTAG, *LPMEMORYTAG;
  449. //--------------------------------------------------------------------------
  450. // CORRUPTREASON
  451. //--------------------------------------------------------------------------
  452. typedef enum tagCORRUPTREASON {
  453. REASON_BLOCKSTARTOUTOFRANGE = 10000,
  454. REASON_UMATCHINGBLOCKADDRESS = 10002,
  455. REASON_BLOCKSIZEOUTOFRANGE = 10003,
  456. REASON_INVALIDFIRSTRECORD = 10035,
  457. REASON_INVALIDLASTRECORD = 10036,
  458. REASON_INVALIDRECORDMAP = 10037
  459. } CORRUPTREASON;
  460. //--------------------------------------------------------------------------
  461. // CDatabase
  462. //--------------------------------------------------------------------------
  463. class CDatabase : public IDatabase
  464. {
  465. public:
  466. //----------------------------------------------------------------------
  467. // Construction - Destruction
  468. //----------------------------------------------------------------------
  469. CDatabase(void);
  470. ~CDatabase(void);
  471. //----------------------------------------------------------------------
  472. // IUnknown Members
  473. //----------------------------------------------------------------------
  474. STDMETHODIMP QueryInterface(REFIID riid, LPVOID *ppv);
  475. STDMETHODIMP_(ULONG) AddRef(void);
  476. STDMETHODIMP_(ULONG) Release(void);
  477. //----------------------------------------------------------------------
  478. // IDatabase Members
  479. //----------------------------------------------------------------------
  480. HRESULT Open(LPCWSTR pszFile, OPENDATABASEFLAGS dwFlags, LPCTABLESCHEMA pSchema, IDatabaseExtension *pExtension);
  481. //----------------------------------------------------------------------
  482. // Locking Methods
  483. //----------------------------------------------------------------------
  484. STDMETHODIMP Lock(LPHLOCK phLock);
  485. STDMETHODIMP Unlock(LPHLOCK phLock);
  486. //----------------------------------------------------------------------
  487. // Data Manipulation Methods
  488. //----------------------------------------------------------------------
  489. STDMETHODIMP InsertRecord(LPVOID pBinding);
  490. STDMETHODIMP UpdateRecord(LPVOID pBinding);
  491. STDMETHODIMP DeleteRecord(LPVOID pBinding);
  492. STDMETHODIMP FindRecord(INDEXORDINAL iIndex, DWORD cColumns, LPVOID pBinding, LPROWORDINAL piRow);
  493. STDMETHODIMP GetRowOrdinal(INDEXORDINAL iIndex, LPVOID pBinding, LPROWORDINAL piRow);
  494. STDMETHODIMP FreeRecord(LPVOID pBinding);
  495. STDMETHODIMP GetUserData(LPVOID pvUserData, ULONG cbUserData);
  496. STDMETHODIMP SetUserData(LPVOID pvUserData, ULONG cbUserData);
  497. STDMETHODIMP GetRecordCount(INDEXORDINAL iIndex, LPDWORD pcRecords);
  498. //----------------------------------------------------------------------
  499. // Indexing Methods
  500. //----------------------------------------------------------------------
  501. STDMETHODIMP GetIndexInfo(INDEXORDINAL iIndex, LPSTR *ppszFilter, LPTABLEINDEX pIndex);
  502. STDMETHODIMP ModifyIndex(INDEXORDINAL iIndex, LPCSTR pszFilter, LPCTABLEINDEX pIndex);
  503. STDMETHODIMP DeleteIndex(INDEXORDINAL iIndex);
  504. //----------------------------------------------------------------------
  505. // Rowset Methods
  506. //----------------------------------------------------------------------
  507. STDMETHODIMP CreateRowset(INDEXORDINAL iIndex, CREATEROWSETFLAGS dwFlags, LPHROWSET phRowset);
  508. STDMETHODIMP SeekRowset(HROWSET hRowset, SEEKROWSETTYPE tySeek, LONG cRows, LPROWORDINAL piRowNew);
  509. STDMETHODIMP QueryRowset(HROWSET hRowset, LONG cWanted, LPVOID *prgpBinding, LPDWORD pcObtained);
  510. STDMETHODIMP CloseRowset(LPHROWSET phRowset);
  511. //----------------------------------------------------------------------
  512. // Streaming Methods
  513. //----------------------------------------------------------------------
  514. STDMETHODIMP CreateStream(LPFILEADDRESS pfaStart);
  515. STDMETHODIMP DeleteStream(FILEADDRESS faStart);
  516. STDMETHODIMP CopyStream(IDatabase *pDst, FILEADDRESS faStream, LPFILEADDRESS pfaNew);
  517. STDMETHODIMP OpenStream(ACCESSTYPE tyAccess, FILEADDRESS faStart, IStream **ppStream);
  518. STDMETHODIMP ChangeStreamLock(IStream *pStream, ACCESSTYPE tyAccessNew);
  519. //----------------------------------------------------------------------
  520. // Notification Methods
  521. //----------------------------------------------------------------------
  522. STDMETHODIMP RegisterNotify(INDEXORDINAL iIndex, REGISTERNOTIFYFLAGS dwFlags, DWORD_PTR dwCookie, IDatabaseNotify *pNotify);
  523. STDMETHODIMP DispatchNotify(IDatabaseNotify *pNotify);
  524. STDMETHODIMP SuspendNotify(IDatabaseNotify *pNotify);
  525. STDMETHODIMP ResumeNotify(IDatabaseNotify *pNotify);
  526. STDMETHODIMP UnregisterNotify(IDatabaseNotify *pNotify);
  527. STDMETHODIMP LockNotify(LOCKNOTIFYFLAGS dwFlags, LPHLOCK phLock);
  528. STDMETHODIMP UnlockNotify(LPHLOCK phLock);
  529. STDMETHODIMP GetTransaction(LPHTRANSACTION phTransaction, LPTRANSACTIONTYPE ptyTransaction, LPVOID pRecord1, LPVOID pRecord2, LPINDEXORDINAL piIndex, LPORDINALLIST pOrdinals);
  530. //----------------------------------------------------------------------
  531. // Maintenence Methods
  532. //----------------------------------------------------------------------
  533. STDMETHODIMP MoveFile(LPCWSTR pszFilePath);
  534. STDMETHODIMP SetSize(DWORD cbSize);
  535. STDMETHODIMP GetFile(LPWSTR *ppszFile);
  536. STDMETHODIMP GetSize(LPDWORD pcbFile, LPDWORD pcbAllocated, LPDWORD pcbFreed, LPDWORD pcbStreams);
  537. STDMETHODIMP Repair(void) { return _CheckForCorruption(); }
  538. //----------------------------------------------------------------------
  539. // Fast-Heap Methods
  540. //----------------------------------------------------------------------
  541. STDMETHODIMP HeapFree(LPVOID pvBuffer);
  542. STDMETHODIMP HeapAllocate(DWORD dwFlags, DWORD cbSize, LPVOID *ppBuffer) {
  543. *ppBuffer = PHeapAllocate(dwFlags, cbSize);
  544. return(*ppBuffer ? S_OK : E_OUTOFMEMORY);
  545. }
  546. //----------------------------------------------------------------------
  547. // General Utility Methods
  548. //----------------------------------------------------------------------
  549. STDMETHODIMP Compact(IDatabaseProgress *pProgress, COMPACTFLAGS dwFlags);
  550. STDMETHODIMP GenerateId(LPDWORD pdwId);
  551. STDMETHODIMP GetClientCount(LPDWORD pcClients);
  552. //----------------------------------------------------------------------
  553. // CDatabase Members
  554. //----------------------------------------------------------------------
  555. HRESULT StreamCompareDatabase(CDatabaseStream *pStream, IDatabase *pDatabase);
  556. HRESULT GetStreamAddress(CDatabaseStream *pStream, LPFILEADDRESS pfaStream);
  557. HRESULT StreamRead(CDatabaseStream *pStream, LPVOID pvData, ULONG cbWanted, ULONG *pcbRead);
  558. HRESULT StreamWrite(CDatabaseStream *pStream, const void *pvData, ULONG cb, ULONG *pcbWrote);
  559. HRESULT StreamSeek(CDatabaseStream *pStream, LARGE_INTEGER liMove, DWORD dwOrigin, ULARGE_INTEGER *pulNew);
  560. HRESULT StreamRelease(CDatabaseStream *pStream);
  561. HRESULT StreamGetAddress(CDatabaseStream *pStream, LPFILEADDRESS pfaStart);
  562. HRESULT DoInProcessInvoke(INVOKETYPE tyInvoke);
  563. #ifdef BACKGROUND_MONITOR
  564. HRESULT DoBackgroundMonitor(void);
  565. #endif
  566. HRESULT BindRecord(LPRECORDMAP pMap, LPVOID pBinding);
  567. LPVOID PHeapAllocate(DWORD dwFlags, DWORD cbSize);
  568. //----------------------------------------------------------------------
  569. // AllocateBinding
  570. //----------------------------------------------------------------------
  571. HRESULT AllocateBinding(LPVOID *ppBinding) {
  572. *ppBinding = PHeapAllocate(HEAP_ZERO_MEMORY, m_pSchema->cbBinding);
  573. return(*ppBinding ? S_OK : E_OUTOFMEMORY);
  574. }
  575. private:
  576. //----------------------------------------------------------------------
  577. // General Btree Methods
  578. //----------------------------------------------------------------------
  579. HRESULT _IsLeafChain(LPCHAINBLOCK pChain);
  580. HRESULT _AdjustParentNodeCount(INDEXORDINAL iIndex, FILEADDRESS faChain, LONG lCount);
  581. HRESULT _ValidateFileVersions(OPENDATABASEFLAGS dwFlags);
  582. HRESULT _ResetTableHeader(void);
  583. HRESULT _RemoveClientFromArray(DWORD dwProcessId, DWORD_PTR pDB);
  584. HRESULT _BuildQueryTable(void);
  585. HRESULT _StreamSychronize(CDatabaseStream *pStream);
  586. HRESULT _InitializeExtension(OPENDATABASEFLAGS dwFlags, IDatabaseExtension *pExtension);
  587. HRESULT _GetRecordMap(BOOL fGoCorrupt, LPRECORDBLOCK pBlock, LPRECORDMAP pMap);
  588. //----------------------------------------------------------------------
  589. // File Mapping / View Utilities
  590. //----------------------------------------------------------------------
  591. HRESULT _InitializeFileViews(void);
  592. HRESULT _CloseFileViews(BOOL fFlush);
  593. HRESULT _AllocateSpecialView(FILEADDRESS faView, DWORD cbView, LPFILEVIEW *ppSpecial);
  594. //----------------------------------------------------------------------
  595. // Btree Search / Virtual Scrolling
  596. //----------------------------------------------------------------------
  597. HRESULT _GetChainByIndex(INDEXORDINAL iIndex, ROWORDINAL iRow, LPFILEADDRESS pfaChain, LPNODEINDEX piNode);
  598. HRESULT _CompareBinding(INDEXORDINAL iIndex, DWORD cColumns, LPVOID pBinding, FILEADDRESS faRecord, INT *pnCompare);
  599. HRESULT _IsVisible(HQUERY hQuery, LPVOID pBinding);
  600. HRESULT _PartialIndexCompare(INDEXORDINAL iIndex, DWORD cColumns, LPVOID pBinding, LPCHAINBLOCK *ppChain, LPNODEINDEX piNode, LPROWORDINAL piRow);
  601. HRESULT _FindRecord(INDEXORDINAL iIndex, DWORD cColumns, LPVOID pBinding, LPFILEADDRESS pfaChain, LPNODEINDEX piNode, LPROWORDINAL piRow=NULL, INT *pnCompare=NULL);
  602. //----------------------------------------------------------------------
  603. // Btree Deletion Methods
  604. //----------------------------------------------------------------------
  605. HRESULT _CollapseChain(LPCHAINBLOCK pChain, NODEINDEX iDelete);
  606. HRESULT _ExpandChain(LPCHAINBLOCK pChain, NODEINDEX iNode);
  607. HRESULT _IndexDeleteRecord(INDEXORDINAL iIndex, FILEADDRESS faDelete, NODEINDEX iDelete);
  608. HRESULT _GetRightSibling(FILEADDRESS faCurrent, LPCHAINBLOCK *ppSibling);
  609. HRESULT _GetLeftSibling(FILEADDRESS faCurrent, LPCHAINBLOCK *ppSibling);
  610. HRESULT _GetInOrderSuccessor(FILEADDRESS faStart, NODEINDEX iDelete, LPCHAINBLOCK *ppSuccessor);
  611. HRESULT _DecideHowToDelete(LPFILEADDRESS pfaShare, FILEADDRESS faDelete, CHAINDELETETYPE *ptyDelete, CHAINSHARETYPE *ptyShare);
  612. HRESULT _ChainDeleteShare(INDEXORDINAL iIndex, FILEADDRESS faDelete, FILEADDRESS faShare, CHAINSHARETYPE tyShare);
  613. HRESULT _ChainDeleteCoalesce(INDEXORDINAL iIndex, FILEADDRESS faDelete, FILEADDRESS faShare, CHAINSHARETYPE tyShare);
  614. //----------------------------------------------------------------------
  615. // Btree Insertion Methods
  616. //----------------------------------------------------------------------
  617. HRESULT _IndexInsertRecord(INDEXORDINAL iIndex, FILEADDRESS faChain, FILEADDRESS faRecord, LPNODEINDEX piNode, INT nCompare);
  618. HRESULT _ChainInsert(INDEXORDINAL iIndex, LPCHAINBLOCK pChain, LPCHAINNODE pNode, LPNODEINDEX piNodeIndex);
  619. HRESULT _SplitChainInsert(INDEXORDINAL iIndex, FILEADDRESS faLeaf);
  620. //----------------------------------------------------------------------
  621. // Record Persistence Methods
  622. //----------------------------------------------------------------------
  623. HRESULT _GetRecordSize(LPVOID pBinding, LPRECORDMAP pMap);
  624. HRESULT _SaveRecord(LPRECORDBLOCK pBlock, LPRECORDMAP pMap, LPVOID pBinding);
  625. HRESULT _ReadRecord(FILEADDRESS faRecord, LPVOID pBinding, BOOL fInternal=FALSE);
  626. HRESULT _LinkRecordIntoTable(LPRECORDMAP pMap, LPVOID pBinding, BYTE bVersion, LPFILEADDRESS pfaRecord);
  627. //----------------------------------------------------------------------
  628. // Notification / Invoke Methods
  629. //----------------------------------------------------------------------
  630. HRESULT _DispatchInvoke(INVOKETYPE tyInvoke);
  631. HRESULT _DispatchNotification(HTRANSACTION hTransaction);
  632. HRESULT _LogTransaction(TRANSACTIONTYPE tyTransaction, INDEXORDINAL iIndex, LPORDINALLIST pOrdinals, FILEADDRESS faRecord1, FILEADDRESS faRecord2);
  633. HRESULT _CloseNotificationWindow(LPNOTIFYRECIPIENT pRecipient);
  634. HRESULT _FindClient(DWORD dwProcessId, DWORD_PTR dwDB, LPDWORD piClient, LPCLIENTENTRY *ppClient);
  635. HRESULT _FindNotifyRecipient(DWORD iClient, IDatabaseNotify *pNotify, LPDWORD piRecipient, LPNOTIFYRECIPIENT *ppRecipient);
  636. HRESULT _DispatchPendingNotifications(void);
  637. HRESULT _AdjustNotifyCounts(LPNOTIFYRECIPIENT pRecipient, LONG lChange);
  638. //----------------------------------------------------------------------
  639. // Rowset Support Methods
  640. //----------------------------------------------------------------------
  641. HRESULT _AdjustOpenRowsets(INDEXORDINAL iIndex, ROWORDINAL iRow, OPERATIONTYPE tyOperation);
  642. //----------------------------------------------------------------------
  643. // Alloctation Methods
  644. //----------------------------------------------------------------------
  645. HRESULT _MarkBlock(BLOCKTYPE tyBlock, FILEADDRESS faBlock, DWORD cbBlock, LPVOID *ppvBlock);
  646. HRESULT _ReuseFixedFreeBlock(LPFILEADDRESS pfaFreeHead, BLOCKTYPE tyBlock, DWORD cbBlock, LPVOID *ppvBlock);
  647. HRESULT _FreeRecordStorage(OPERATIONTYPE tyOperation, FILEADDRESS faRecord);
  648. HRESULT _FreeStreamStorage(FILEADDRESS faStart);
  649. HRESULT _SetStorageSize(DWORD cbSize);
  650. HRESULT _AllocateBlock(BLOCKTYPE tyBlock, DWORD cbExtra, LPVOID *ppBlock);
  651. HRESULT _AllocateFromPage(BLOCKTYPE tyBlock, LPALLOCATEPAGE pPage, DWORD cbPage, DWORD cbBlock, LPVOID *ppvBlock);
  652. HRESULT _FreeBlock(BLOCKTYPE tyBlock, FILEADDRESS faBlock);
  653. HRESULT _AllocatePage(DWORD cbPage, LPFILEADDRESS pfaAddress);
  654. HRESULT _FreeIndex(FILEADDRESS faChain);
  655. HRESULT _CopyRecord(FILEADDRESS faRecord, LPFILEADDRESS pfaCopy);
  656. HRESULT _FreeTransactBlock(LPTRANSACTIONBLOCK pTransact);
  657. HRESULT _CleanupTransactList(void);
  658. //----------------------------------------------------------------------
  659. // Compaction Helpers
  660. //----------------------------------------------------------------------
  661. HRESULT _CompactMoveRecordStreams(CDatabase *pDstDB, LPVOID pBinding);
  662. HRESULT _CompactMoveOpenDeletedStreams(CDatabase *pDstDB);
  663. HRESULT _CompactTransferFilters(CDatabase *pDstDB);
  664. HRESULT _CompactInsertRecord(LPVOID pBinding);
  665. //----------------------------------------------------------------------
  666. // Index Management
  667. //----------------------------------------------------------------------
  668. HRESULT _ValidateIndex(INDEXORDINAL iIndex, FILEADDRESS faChain, ULONG cLeftNodes, ULONG *pcRecords);
  669. HRESULT _RebuildIndex(INDEXORDINAL iIndex);
  670. HRESULT _RecursiveRebuildIndex(INDEXORDINAL iIndex, FILEADDRESS faCurrent, LPVOID pBinding, LPDWORD pcRecords);
  671. //----------------------------------------------------------------------
  672. // Corruption Validation and Repair Methods
  673. //----------------------------------------------------------------------
  674. HRESULT _HandleOpenMovedFile(void);
  675. HRESULT _SetCorrupt(BOOL fGoCorrupt, INT nLine, CORRUPTREASON tyReason, BLOCKTYPE tyBlock, FILEADDRESS faExpected, FILEADDRESS faActual, DWORD cbBlock);
  676. HRESULT _CheckForCorruption(void);
  677. HRESULT _GetBlock(BLOCKTYPE tyExpected, FILEADDRESS faBlock, LPVOID *ppvBlock, LPMARKBLOCK pMark=NULL, BOOL fGoCorrupt=TRUE);
  678. HRESULT _ValidateAndRepairRecord(LPRECORDMAP pMap);
  679. HRESULT _ValidateStream(FILEADDRESS faStart);
  680. //----------------------------------------------------------------------
  681. // Private Debug Methods
  682. //----------------------------------------------------------------------
  683. IF_DEBUG(HRESULT _DebugValidateRecordFormat(void));
  684. IF_DEBUG(HRESULT _DebugValidateUnrefedRecord(FILEADDRESS farecord));
  685. IF_DEBUG(HRESULT _DebugValidateIndexUnrefedRecord(FILEADDRESS faChain, FILEADDRESS faRecord));
  686. private:
  687. //----------------------------------------------------------------------
  688. // Prototypes
  689. //----------------------------------------------------------------------
  690. LONG m_cRef;
  691. LONG m_cExtRefs;
  692. HANDLE m_hMutex;
  693. #ifdef BACKGROUND_MONITOR
  694. HMONITORDB m_hMonitor;
  695. #endif
  696. DWORD m_dwProcessId;
  697. BOOL m_fDirty;
  698. LPCTABLESCHEMA m_pSchema;
  699. LPSTORAGEINFO m_pStorage;
  700. LPTABLEHEADER m_pHeader;
  701. LPSHAREDDATABASE m_pShare;
  702. HANDLE m_hHeap;
  703. BYTE m_fDeconstruct;
  704. BYTE m_fInMoveFile;
  705. BYTE m_fExclusive;
  706. BYTE m_fCompactYield;
  707. DWORD m_dwQueryVersion;
  708. HQUERY m_rghFilter[CMAX_INDEXES];
  709. IDatabaseExtension *m_pExtension;
  710. IUnknown *m_pUnkRelease;
  711. LPBYTE m_rgpRecycle[CC_HEAP_BUCKETS];
  712. CRITICAL_SECTION m_csHeap;
  713. IF_DEBUG(DWORD m_cbHeapAlloc);
  714. IF_DEBUG(DWORD m_cbHeapFree);
  715. //----------------------------------------------------------------------
  716. // Friend
  717. //----------------------------------------------------------------------
  718. friend CDatabaseQuery;
  719. };
  720. //--------------------------------------------------------------------------
  721. // CDatabaseQuery
  722. //--------------------------------------------------------------------------
  723. class CDatabaseQuery : public IDatabaseQuery
  724. {
  725. public:
  726. //----------------------------------------------------------------------
  727. // Construction
  728. //----------------------------------------------------------------------
  729. CDatabaseQuery(void) {
  730. TraceCall("CDatabaseQuery::CDatabaseQuery");
  731. m_cRef = 1;
  732. m_hQuery = NULL;
  733. m_pDatabase = NULL;
  734. }
  735. //----------------------------------------------------------------------
  736. // De-Construction
  737. //----------------------------------------------------------------------
  738. ~CDatabaseQuery(void) {
  739. TraceCall("CDatabaseQuery::~CDatabaseQuery");
  740. CloseQuery(&m_hQuery, m_pDatabase);
  741. SafeRelease(m_pDatabase);
  742. }
  743. //----------------------------------------------------------------------
  744. // IUnknown Members
  745. //----------------------------------------------------------------------
  746. STDMETHODIMP QueryInterface(REFIID riid, LPVOID *ppv) {
  747. TraceCall("CDatabaseQuery::QueryInterface");
  748. *ppv = NULL;
  749. if (IID_IUnknown == riid)
  750. *ppv = (IUnknown *)this;
  751. else if (IID_IDatabaseQuery == riid)
  752. *ppv = (IDatabaseQuery *)this;
  753. else
  754. return TraceResult(E_NOINTERFACE);
  755. ((IUnknown *)*ppv)->AddRef();
  756. return S_OK;
  757. }
  758. //----------------------------------------------------------------------
  759. // IDatabaseQuery::AddRef
  760. //----------------------------------------------------------------------
  761. STDMETHODIMP_(ULONG) AddRef(void) {
  762. TraceCall("CDatabaseQuery::AddRef");
  763. return InterlockedIncrement(&m_cRef);
  764. }
  765. //----------------------------------------------------------------------
  766. // IDatabaseQuery::Release
  767. //----------------------------------------------------------------------
  768. STDMETHODIMP_(ULONG) Release(void) {
  769. TraceCall("CDatabaseQuery::Release");
  770. LONG cRef = InterlockedDecrement(&m_cRef);
  771. if (0 == cRef)
  772. delete this;
  773. return (ULONG)cRef;
  774. }
  775. //----------------------------------------------------------------------
  776. // CDatabaseQuery::Initialize
  777. //----------------------------------------------------------------------
  778. HRESULT Initialize(IDatabase *pDatabase, LPCSTR pszQuery) {
  779. TraceCall("CDatabaseQuery::Initialize");
  780. pDatabase->QueryInterface(IID_CDatabase, (LPVOID *)&m_pDatabase);
  781. return(ParseQuery(pszQuery, m_pDatabase->m_pSchema, &m_hQuery, m_pDatabase));
  782. }
  783. //----------------------------------------------------------------------
  784. // CDatabaseQuery::Evaluate
  785. //----------------------------------------------------------------------
  786. STDMETHODIMP Evaluate(LPVOID pBinding) {
  787. TraceCall("CDatabaseQuery::Evaluate");
  788. return(EvaluateQuery(m_hQuery, pBinding, m_pDatabase->m_pSchema, m_pDatabase, m_pDatabase->m_pExtension));
  789. }
  790. private:
  791. //----------------------------------------------------------------------
  792. // Private Data
  793. //----------------------------------------------------------------------
  794. LONG m_cRef;
  795. HQUERY m_hQuery;
  796. CDatabase *m_pDatabase;
  797. };
  798. //--------------------------------------------------------------------------
  799. // PTagFromOrdinal
  800. //--------------------------------------------------------------------------
  801. inline LPCOLUMNTAG PTagFromOrdinal(LPRECORDMAP pMap, COLUMNORDINAL iColumn);