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

//--------------------------------------------------------------------------
// Database.h
//--------------------------------------------------------------------------
#pragma once
//--------------------------------------------------------------------------
// Depends
//--------------------------------------------------------------------------
#include "utility.h"
#include "query.h"
#include "listen.h"
//--------------------------------------------------------------------------
// Forward Decls
//--------------------------------------------------------------------------
class CDatabaseQuery;
//--------------------------------------------------------------------------
// DwordAlign
//--------------------------------------------------------------------------
inline DWORD DwordAlign(DWORD cb) {
DWORD dw = (cb % 4); return(0 == dw ? 0 : (4 - dw));
}
//--------------------------------------------------------------------------
// String Constants
//--------------------------------------------------------------------------
#define CCHMAX_DB_FILEPATH (MAX_PATH + MAX_PATH)
//--------------------------------------------------------------------------
// DESCENDING
//--------------------------------------------------------------------------
#define DESCENDING(_nCompare) ((_nCompare < 0) ? 1 : -1)
typedef DWORD TICKCOUNT;
//--------------------------------------------------------------------------
// Version and Signatures
//--------------------------------------------------------------------------
#define BTREE_SIGNATURE 0xfe12adcf
#define BTREE_VERSION 5
//--------------------------------------------------------------------------
// B-Tree Chain Sizes
//--------------------------------------------------------------------------
#define BTREE_ORDER 50
#define BTREE_MIN_CAP 25
//--------------------------------------------------------------------------
// Upper Limit on Various Resources
//--------------------------------------------------------------------------
#define CMAX_OPEN_STREAMS 512
#define CMAX_OPEN_ROWSETS 32
#define CMAX_RECIPIENTS 15
#define CMAX_CLIENTS 32
//--------------------------------------------------------------------------
// Block Allocate Page Sizes
//--------------------------------------------------------------------------
#define CB_CHAIN_PAGE 15900
#define CB_STREAM_PAGE 63360
#define CB_VARIABLE_PAGE 49152
#define CB_STREAM_BLOCK 512
#define CC_MAX_BLOCK_TYPES 16
//--------------------------------------------------------------------------
// Variable Length Block Allocation Sizes
//--------------------------------------------------------------------------
#define CB_ALIGN_LARGE 1024
#define CB_FREE_BUCKET 4
#define CC_FREE_BUCKETS 2048
#define CB_MIN_FREE_BUCKET 32
#define CB_MAX_FREE_BUCKET (CB_MIN_FREE_BUCKET + (CB_FREE_BUCKET * CC_FREE_BUCKETS))
//--------------------------------------------------------------------------
// Heap Block Cache
//--------------------------------------------------------------------------
#define CB_HEAP_BUCKET 8
#define CC_HEAP_BUCKETS 1024
#define CB_MAX_HEAP_BUCKET (CB_HEAP_BUCKET * CC_HEAP_BUCKETS)
//--------------------------------------------------------------------------
// Other Constants
//--------------------------------------------------------------------------
#define MEMORY_GUARD_SIGNATURE 0xdeadbeef
#define DELETE_ON_CLOSE TRUE
//--------------------------------------------------------------------------
// File Mapping Constants
//--------------------------------------------------------------------------
#define CB_MAPPED_VIEW 10485760
//--------------------------------------------------------------------------
// Forward Decls
//--------------------------------------------------------------------------
class CProgress;
class CDatabase;
class CDatabaseStream;
//--------------------------------------------------------------------------
// Locking Values
//--------------------------------------------------------------------------
#define LOCK_VALUE_NONE 0
#define LOCK_VALUE_WRITER -1
//--------------------------------------------------------------------------
// STREAMINDEX
//--------------------------------------------------------------------------
typedef WORD STREAMINDEX;
typedef LPWORD LPSTREAMINDEX;
#define INVALID_STREAMINDEX 0xffff
//--------------------------------------------------------------------------
// ROWSETORDINAL
//--------------------------------------------------------------------------
typedef BYTE ROWSETORDINAL;
//--------------------------------------------------------------------------
// FILEADDRESS
//--------------------------------------------------------------------------
typedef DWORD FILEADDRESS;
typedef LPDWORD LPFILEADDRESS;
//--------------------------------------------------------------------------
// NODEINDEX
//--------------------------------------------------------------------------
typedef BYTE NODEINDEX;
typedef BYTE *LPNODEINDEX;
#define INVALID_NODEINDEX 0xff
//--------------------------------------------------------------------------
// BLOCKTYPE
//--------------------------------------------------------------------------
typedef enum tagBLOCKTYPE {
BLOCK_RECORD,
BLOCK_STRING,
BLOCK_RESERVED1,
BLOCK_TRANSACTION,
BLOCK_CHAIN,
BLOCK_STREAM,
BLOCK_FREE,
BLOCK_ENDOFPAGE,
BLOCK_RESERVED2,
BLOCK_RESERVED3,
BLOCK_LAST
} BLOCKTYPE;
//--------------------------------------------------------------------------
// CHAINDELETETYPE
//--------------------------------------------------------------------------
typedef enum tagCHAINDELETETYPE {
CHAIN_DELETE_SHARE,
CHAIN_DELETE_COALESCE
} CHAINDELETETYPE;
//--------------------------------------------------------------------------
// CHAINSHARETYPE
//--------------------------------------------------------------------------
typedef enum tagCHAINSHARETYPE {
CHAIN_SHARE_LEFT,
CHAIN_SHARE_RIGHT
} CHAINSHARETYPE;
//--------------------------------------------------------------------------
// OPERATIONTYPE - Specifies how _UnlinkRecordFromTable from table works
//--------------------------------------------------------------------------
typedef enum tagOPERATIONTYPE {
OPERATION_DELETE,
OPERATION_UPDATE,
OPERATION_INSERT
} OPERATIONTYPE;
//--------------------------------------------------------------------------
// INVOKETYPE
//--------------------------------------------------------------------------
typedef enum tagINVOKETYPE {
INVOKE_RELEASEMAP = 100,
INVOKE_CREATEMAP = 101,
INVOKE_CLOSEFILE = 102,
INVOKE_OPENFILE = 103,
INVOKE_OPENMOVEDFILE = 104
} INVOKETYPE;
//--------------------------------------------------------------------------
// FINDRESULT
//--------------------------------------------------------------------------
typedef struct tagFINDRESULT {
FILEADDRESS faChain;
NODEINDEX iNode;
BYTE fChanged;
BYTE fFound;
INT nCompare;
} FINDRESULT, *LPFINDRESULT;
//--------------------------------------------------------------------------
// ALLOCATEPAGE
//--------------------------------------------------------------------------
#pragma pack(4)
typedef struct tagALLOCATEPAGE {
FILEADDRESS faPage;
DWORD cbPage;
DWORD cbUsed;
} ALLOCATEPAGE, *LPALLOCATEPAGE;
#pragma pack()
//--------------------------------------------------------------------------
// TABLEHEADER
//--------------------------------------------------------------------------
#pragma pack(4)
typedef struct tagTABLEHEADER {
DWORD dwSignature; // 4
CLSID clsidExtension; // 20
DWORD dwMinorVersion; // 24
DWORD dwMajorVersion; // 28
DWORD cbUserData; // 32
FILEADDRESS faCatalogOld; // 36
ALLOCATEPAGE AllocateRecord; // 48
ALLOCATEPAGE AllocateChain; // 60
ALLOCATEPAGE AllocateStream; // 72
FILEADDRESS faFreeStreamBlock; // 76
FILEADDRESS faFreeChainBlock; // 80
FILEADDRESS faFreeLargeBlock; // 84
DWORD cbAllocated; // 88
DWORD cbFreed; // 92
DWORD dwNextId; // 96
DWORD fCorrupt; // 100
DWORD fCorruptCheck; // 104
DWORD cActiveThreads; // 108
FILEADDRESS faTransactHead; // 112
FILEADDRESS faTransactTail; // 116
DWORD cTransacts; // 120
DWORD cBadCloses; // 124
FILEADDRESS faNextAllocate; // 128
DWORD cIndexes; // 132
FILEADDRESS rgfaFilter[CMAX_INDEXES]; // 164
DWORD rgbReserved5[8]; // 196
DWORD rgcRecords[CMAX_INDEXES]; // 228
FILEADDRESS rgfaIndex[CMAX_INDEXES]; // 260
INDEXORDINAL rgiIndex[CMAX_INDEXES]; // 292
BYTE rgbReserved4[116]; // 408
BYTE fReserved; // 409
DWORD rgbReserved6[8]; // 196
BYTE rgdwReserved2[192]; // 637
DWORD rgcbAllocated[CC_MAX_BLOCK_TYPES]; // 701
FILEADDRESS rgfaFreeBlock[CC_FREE_BUCKETS]; // 8893
TABLEINDEX rgIndexInfo[CMAX_INDEXES]; // 9293
WORD wTransactSize; // 9405
BYTE rgdwReserved3[110];
} TABLEHEADER, *LPTABLEHEADER;
#pragma pack()
//--------------------------------------------------------------------------
// BLOCKHEADER
//--------------------------------------------------------------------------
#pragma pack(4)
typedef struct tagBLOCKHEADER {
FILEADDRESS faBlock;
DWORD cbSize;
} BLOCKHEADER, *LPBLOCKHEADER;
#pragma pack()
//--------------------------------------------------------------------------
// FREEBLOCK
//--------------------------------------------------------------------------
#pragma pack(4)
typedef struct tagFREEBLOCK : public BLOCKHEADER {
DWORD cbBlock;
DWORD dwReserved;
FILEADDRESS faNext;
} FREEBLOCK, *LPFREEBLOCK;
#pragma pack()
//--------------------------------------------------------------------------
// CHAINNODE
//--------------------------------------------------------------------------
#pragma pack(4)
typedef struct tagCHAINNODE {
FILEADDRESS faRecord;
FILEADDRESS faRightChain;
DWORD cRightNodes;
} CHAINNODE, *LPCHAINNODE;
#pragma pack()
//--------------------------------------------------------------------------
// CHAINBLOCK - 636
//--------------------------------------------------------------------------
#pragma pack(4)
typedef struct tagCHAINBLOCK : public BLOCKHEADER {
FILEADDRESS faLeftChain;
FILEADDRESS faParent;
BYTE iParent;
BYTE cNodes;
WORD wReserved;
DWORD cLeftNodes;
CHAINNODE rgNode[BTREE_ORDER + 1];
} CHAINBLOCK, *LPCHAINBLOCK;
#pragma pack()
//--------------------------------------------------------------------------
// STREAMBLOCK
//--------------------------------------------------------------------------
#pragma pack(4)
typedef struct tagSTREAMBLOCK : public BLOCKHEADER {
DWORD cbData;
FILEADDRESS faNext;
} STREAMBLOCK, *LPSTREAMBLOCK;
#pragma pack()
//--------------------------------------------------------------------------
// RECORDBLOCK
//--------------------------------------------------------------------------
#pragma pack(4)
typedef struct tagRECORDBLOCK : public BLOCKHEADER {
WORD wReserved;
BYTE cTags;
BYTE bVersion;
} RECORDBLOCK, *LPRECORDBLOCK;
#pragma pack()
//--------------------------------------------------------------------------
// COLUMNTAG
//--------------------------------------------------------------------------
#define TAG_DATA_MASK 0xFF800000
#pragma pack(4)
typedef struct tagCOLUMNTAG {
unsigned iColumn : 7;
unsigned fData : 1;
unsigned Offset : 24;
} COLUMNTAG, *LPCOLUMNTAG;
#pragma pack()
//--------------------------------------------------------------------------
// RECORDMAP
//--------------------------------------------------------------------------
typedef struct tagRECORDMAP {
LPCTABLESCHEMA pSchema;
BYTE cTags;
LPCOLUMNTAG prgTag;
DWORD cbTags;
DWORD cbData;
LPBYTE pbData;
} RECORDMAP, *LPRECORDMAP;
//--------------------------------------------------------------------------
// OPENSTREAM
//--------------------------------------------------------------------------
typedef struct tagOPENSTREAM {
BYTE fInUse;
FILEADDRESS faStart;
FILEADDRESS faMoved;
DWORD cOpenCount;
LONG lLock;
BYTE fDeleteOnClose;
} OPENSTREAM, *LPOPENSTREAM;
//--------------------------------------------------------------------------
// NOTIFYRECIPIENT
//--------------------------------------------------------------------------
typedef struct tagNOTIFYRECIPIENT {
HWND hwndNotify;
DWORD dwThreadId;
DWORD_PTR dwCookie;
BYTE fSuspended;
BYTE fRelease;
BYTE fOrdinalsOnly;
DWORD_PTR pNotify;
INDEXORDINAL iIndex;
} NOTIFYRECIPIENT, *LPNOTIFYRECIPIENT;
//--------------------------------------------------------------------------
// CLIENTENTRY
//--------------------------------------------------------------------------
typedef struct tagCLIENTENTRY {
HWND hwndListen;
DWORD dwProcessId;
DWORD dwThreadId;
DWORD_PTR pDB;
DWORD cRecipients;
NOTIFYRECIPIENT rgRecipient[CMAX_RECIPIENTS];
} CLIENTENTRY, *LPCLIENTENTRY;
//--------------------------------------------------------------------------
// TRANSACTIONBLOCK
//--------------------------------------------------------------------------
#pragma pack(4)
typedef struct tagTRANSACTIONBLOCK : public BLOCKHEADER {
TRANSACTIONTYPE tyTransaction;
WORD cRefs;
INDEXORDINAL iIndex;
ORDINALLIST Ordinals;
FILEADDRESS faRecord1;
FILEADDRESS faRecord2;
FILEADDRESS faNext;
FILEADDRESS faPrevious;
FILEADDRESS faNextInBatch;
} TRANSACTIONBLOCK, *LPTRANSACTIONBLOCK;
#pragma pack()
//--------------------------------------------------------------------------
// ROWSETINFO
//--------------------------------------------------------------------------
typedef struct tagROWSETINFO {
ROWSETORDINAL iRowset;
INDEXORDINAL iIndex;
ROWORDINAL iRow;
} ROWSETINFO, *LPROWSETINFO;
//--------------------------------------------------------------------------
// ROWSETTABLE
//--------------------------------------------------------------------------
typedef struct tagROWSETTABLE {
BYTE fInitialized;
BYTE cFree;
BYTE cUsed;
ROWSETORDINAL rgiFree[CMAX_OPEN_ROWSETS];
ROWSETORDINAL rgiUsed[CMAX_OPEN_ROWSETS];
ROWSETINFO rgRowset[CMAX_OPEN_ROWSETS];
} ROWSETTABLE, *LPROWSETTABLE;
//--------------------------------------------------------------------------
// SHAREDDATABASE
//--------------------------------------------------------------------------
typedef struct tagSHAREDDATABASE {
WCHAR szFile[CCHMAX_DB_FILEPATH];
LONG cWaitingForLock;
BYTE fCompacting;
DWORD dwVersion;
DWORD dwQueryVersion;
DWORD cNotifyLock;
FILEADDRESS faTransactLockHead;
FILEADDRESS faTransactLockTail;
OPENSTREAM rgStream[CMAX_OPEN_STREAMS];
DWORD cClients;
DWORD cNotifyOrdinalsOnly;
DWORD cNotifyWithData;
DWORD cNotify;
DWORD rgcIndexNotify[CMAX_INDEXES];
CLIENTENTRY rgClient[CMAX_CLIENTS];
ROWSETTABLE Rowsets;
IF_DEBUG(BYTE fRepairing;)
} SHAREDDATABASE, *LPSHAREDDATABASE;
//--------------------------------------------------------------------------
// INVOKEPACKAGE
//--------------------------------------------------------------------------
typedef struct tagINVOKEPACKAGE {
INVOKETYPE tyInvoke;
DWORD_PTR pDB;
} INVOKEPACKAGE, *LPINVOKEPACKAGE;
//--------------------------------------------------------------------------
// MARKBLOCK
//--------------------------------------------------------------------------
typedef struct tagMARKBLOCK {
DWORD cbBlock;
} MARKBLOCK, *LPMARKBLOCK;
//--------------------------------------------------------------------------
// FILEVIEW
//--------------------------------------------------------------------------
typedef struct tagFILEVIEW *LPFILEVIEW;
typedef struct tagFILEVIEW {
FILEADDRESS faView;
LPBYTE pbView;
DWORD cbView;
LPFILEVIEW pNext;
} FILEVIEW, *LPFILEVIEW;
//--------------------------------------------------------------------------
// STORAGEINFO
//--------------------------------------------------------------------------
typedef struct tagSTORAGEINFO {
LPWSTR pszMap;
HANDLE hFile;
HANDLE hMap;
HANDLE hShare;
DWORD cbFile;
#ifdef BACKGROUND_MONITOR
TICKCOUNT tcMonitor;
#endif
DWORD cbMappedViews;
DWORD cbMappedSpecial;
DWORD cAllocated;
DWORD cSpecial;
LPFILEVIEW prgView;
LPFILEVIEW pSpecial;
} STORAGEINFO, *LPSTORAGEINFO;
//--------------------------------------------------------------------------
// MEMORYTAG
//--------------------------------------------------------------------------
typedef struct tagMEMORYTAG {
DWORD dwSignature;
DWORD cbSize;
LPVOID pNext;
} MEMORYTAG, *LPMEMORYTAG;
//--------------------------------------------------------------------------
// CORRUPTREASON
//--------------------------------------------------------------------------
typedef enum tagCORRUPTREASON {
REASON_BLOCKSTARTOUTOFRANGE = 10000,
REASON_UMATCHINGBLOCKADDRESS = 10002,
REASON_BLOCKSIZEOUTOFRANGE = 10003,
REASON_INVALIDFIRSTRECORD = 10035,
REASON_INVALIDLASTRECORD = 10036,
REASON_INVALIDRECORDMAP = 10037
} CORRUPTREASON;
//--------------------------------------------------------------------------
// CDatabase
//--------------------------------------------------------------------------
class CDatabase : public IDatabase
{
public:
//----------------------------------------------------------------------
// Construction - Destruction
//----------------------------------------------------------------------
CDatabase(void);
~CDatabase(void);
//----------------------------------------------------------------------
// IUnknown Members
//----------------------------------------------------------------------
STDMETHODIMP QueryInterface(REFIID riid, LPVOID *ppv);
STDMETHODIMP_(ULONG) AddRef(void);
STDMETHODIMP_(ULONG) Release(void);
//----------------------------------------------------------------------
// IDatabase Members
//----------------------------------------------------------------------
HRESULT Open(LPCWSTR pszFile, OPENDATABASEFLAGS dwFlags, LPCTABLESCHEMA pSchema, IDatabaseExtension *pExtension);
//----------------------------------------------------------------------
// Locking Methods
//----------------------------------------------------------------------
STDMETHODIMP Lock(LPHLOCK phLock);
STDMETHODIMP Unlock(LPHLOCK phLock);
//----------------------------------------------------------------------
// Data Manipulation Methods
//----------------------------------------------------------------------
STDMETHODIMP InsertRecord(LPVOID pBinding);
STDMETHODIMP UpdateRecord(LPVOID pBinding);
STDMETHODIMP DeleteRecord(LPVOID pBinding);
STDMETHODIMP FindRecord(INDEXORDINAL iIndex, DWORD cColumns, LPVOID pBinding, LPROWORDINAL piRow);
STDMETHODIMP GetRowOrdinal(INDEXORDINAL iIndex, LPVOID pBinding, LPROWORDINAL piRow);
STDMETHODIMP FreeRecord(LPVOID pBinding);
STDMETHODIMP GetUserData(LPVOID pvUserData, ULONG cbUserData);
STDMETHODIMP SetUserData(LPVOID pvUserData, ULONG cbUserData);
STDMETHODIMP GetRecordCount(INDEXORDINAL iIndex, LPDWORD pcRecords);
//----------------------------------------------------------------------
// Indexing Methods
//----------------------------------------------------------------------
STDMETHODIMP GetIndexInfo(INDEXORDINAL iIndex, LPSTR *ppszFilter, LPTABLEINDEX pIndex);
STDMETHODIMP ModifyIndex(INDEXORDINAL iIndex, LPCSTR pszFilter, LPCTABLEINDEX pIndex);
STDMETHODIMP DeleteIndex(INDEXORDINAL iIndex);
//----------------------------------------------------------------------
// Rowset Methods
//----------------------------------------------------------------------
STDMETHODIMP CreateRowset(INDEXORDINAL iIndex, CREATEROWSETFLAGS dwFlags, LPHROWSET phRowset);
STDMETHODIMP SeekRowset(HROWSET hRowset, SEEKROWSETTYPE tySeek, LONG cRows, LPROWORDINAL piRowNew);
STDMETHODIMP QueryRowset(HROWSET hRowset, LONG cWanted, LPVOID *prgpBinding, LPDWORD pcObtained);
STDMETHODIMP CloseRowset(LPHROWSET phRowset);
//----------------------------------------------------------------------
// Streaming Methods
//----------------------------------------------------------------------
STDMETHODIMP CreateStream(LPFILEADDRESS pfaStart);
STDMETHODIMP DeleteStream(FILEADDRESS faStart);
STDMETHODIMP CopyStream(IDatabase *pDst, FILEADDRESS faStream, LPFILEADDRESS pfaNew);
STDMETHODIMP OpenStream(ACCESSTYPE tyAccess, FILEADDRESS faStart, IStream **ppStream);
STDMETHODIMP ChangeStreamLock(IStream *pStream, ACCESSTYPE tyAccessNew);
//----------------------------------------------------------------------
// Notification Methods
//----------------------------------------------------------------------
STDMETHODIMP RegisterNotify(INDEXORDINAL iIndex, REGISTERNOTIFYFLAGS dwFlags, DWORD_PTR dwCookie, IDatabaseNotify *pNotify);
STDMETHODIMP DispatchNotify(IDatabaseNotify *pNotify);
STDMETHODIMP SuspendNotify(IDatabaseNotify *pNotify);
STDMETHODIMP ResumeNotify(IDatabaseNotify *pNotify);
STDMETHODIMP UnregisterNotify(IDatabaseNotify *pNotify);
STDMETHODIMP LockNotify(LOCKNOTIFYFLAGS dwFlags, LPHLOCK phLock);
STDMETHODIMP UnlockNotify(LPHLOCK phLock);
STDMETHODIMP GetTransaction(LPHTRANSACTION phTransaction, LPTRANSACTIONTYPE ptyTransaction, LPVOID pRecord1, LPVOID pRecord2, LPINDEXORDINAL piIndex, LPORDINALLIST pOrdinals);
//----------------------------------------------------------------------
// Maintenence Methods
//----------------------------------------------------------------------
STDMETHODIMP MoveFile(LPCWSTR pszFilePath);
STDMETHODIMP SetSize(DWORD cbSize);
STDMETHODIMP GetFile(LPWSTR *ppszFile);
STDMETHODIMP GetSize(LPDWORD pcbFile, LPDWORD pcbAllocated, LPDWORD pcbFreed, LPDWORD pcbStreams);
STDMETHODIMP Repair(void) { return _CheckForCorruption(); }
//----------------------------------------------------------------------
// Fast-Heap Methods
//----------------------------------------------------------------------
STDMETHODIMP HeapFree(LPVOID pvBuffer);
STDMETHODIMP HeapAllocate(DWORD dwFlags, DWORD cbSize, LPVOID *ppBuffer) {
*ppBuffer = PHeapAllocate(dwFlags, cbSize);
return(*ppBuffer ? S_OK : E_OUTOFMEMORY);
}
//----------------------------------------------------------------------
// General Utility Methods
//----------------------------------------------------------------------
STDMETHODIMP Compact(IDatabaseProgress *pProgress, COMPACTFLAGS dwFlags);
STDMETHODIMP GenerateId(LPDWORD pdwId);
STDMETHODIMP GetClientCount(LPDWORD pcClients);
//----------------------------------------------------------------------
// CDatabase Members
//----------------------------------------------------------------------
HRESULT StreamCompareDatabase(CDatabaseStream *pStream, IDatabase *pDatabase);
HRESULT GetStreamAddress(CDatabaseStream *pStream, LPFILEADDRESS pfaStream);
HRESULT StreamRead(CDatabaseStream *pStream, LPVOID pvData, ULONG cbWanted, ULONG *pcbRead);
HRESULT StreamWrite(CDatabaseStream *pStream, const void *pvData, ULONG cb, ULONG *pcbWrote);
HRESULT StreamSeek(CDatabaseStream *pStream, LARGE_INTEGER liMove, DWORD dwOrigin, ULARGE_INTEGER *pulNew);
HRESULT StreamRelease(CDatabaseStream *pStream);
HRESULT StreamGetAddress(CDatabaseStream *pStream, LPFILEADDRESS pfaStart);
HRESULT DoInProcessInvoke(INVOKETYPE tyInvoke);
#ifdef BACKGROUND_MONITOR
HRESULT DoBackgroundMonitor(void);
#endif
HRESULT BindRecord(LPRECORDMAP pMap, LPVOID pBinding);
LPVOID PHeapAllocate(DWORD dwFlags, DWORD cbSize);
//----------------------------------------------------------------------
// AllocateBinding
//----------------------------------------------------------------------
HRESULT AllocateBinding(LPVOID *ppBinding) {
*ppBinding = PHeapAllocate(HEAP_ZERO_MEMORY, m_pSchema->cbBinding);
return(*ppBinding ? S_OK : E_OUTOFMEMORY);
}
private:
//----------------------------------------------------------------------
// General Btree Methods
//----------------------------------------------------------------------
HRESULT _IsLeafChain(LPCHAINBLOCK pChain);
HRESULT _AdjustParentNodeCount(INDEXORDINAL iIndex, FILEADDRESS faChain, LONG lCount);
HRESULT _ValidateFileVersions(OPENDATABASEFLAGS dwFlags);
HRESULT _ResetTableHeader(void);
HRESULT _RemoveClientFromArray(DWORD dwProcessId, DWORD_PTR pDB);
HRESULT _BuildQueryTable(void);
HRESULT _StreamSychronize(CDatabaseStream *pStream);
HRESULT _InitializeExtension(OPENDATABASEFLAGS dwFlags, IDatabaseExtension *pExtension);
HRESULT _GetRecordMap(BOOL fGoCorrupt, LPRECORDBLOCK pBlock, LPRECORDMAP pMap);
//----------------------------------------------------------------------
// File Mapping / View Utilities
//----------------------------------------------------------------------
HRESULT _InitializeFileViews(void);
HRESULT _CloseFileViews(BOOL fFlush);
HRESULT _AllocateSpecialView(FILEADDRESS faView, DWORD cbView, LPFILEVIEW *ppSpecial);
//----------------------------------------------------------------------
// Btree Search / Virtual Scrolling
//----------------------------------------------------------------------
HRESULT _GetChainByIndex(INDEXORDINAL iIndex, ROWORDINAL iRow, LPFILEADDRESS pfaChain, LPNODEINDEX piNode);
HRESULT _CompareBinding(INDEXORDINAL iIndex, DWORD cColumns, LPVOID pBinding, FILEADDRESS faRecord, INT *pnCompare);
HRESULT _IsVisible(HQUERY hQuery, LPVOID pBinding);
HRESULT _PartialIndexCompare(INDEXORDINAL iIndex, DWORD cColumns, LPVOID pBinding, LPCHAINBLOCK *ppChain, LPNODEINDEX piNode, LPROWORDINAL piRow);
HRESULT _FindRecord(INDEXORDINAL iIndex, DWORD cColumns, LPVOID pBinding, LPFILEADDRESS pfaChain, LPNODEINDEX piNode, LPROWORDINAL piRow=NULL, INT *pnCompare=NULL);
//----------------------------------------------------------------------
// Btree Deletion Methods
//----------------------------------------------------------------------
HRESULT _CollapseChain(LPCHAINBLOCK pChain, NODEINDEX iDelete);
HRESULT _ExpandChain(LPCHAINBLOCK pChain, NODEINDEX iNode);
HRESULT _IndexDeleteRecord(INDEXORDINAL iIndex, FILEADDRESS faDelete, NODEINDEX iDelete);
HRESULT _GetRightSibling(FILEADDRESS faCurrent, LPCHAINBLOCK *ppSibling);
HRESULT _GetLeftSibling(FILEADDRESS faCurrent, LPCHAINBLOCK *ppSibling);
HRESULT _GetInOrderSuccessor(FILEADDRESS faStart, NODEINDEX iDelete, LPCHAINBLOCK *ppSuccessor);
HRESULT _DecideHowToDelete(LPFILEADDRESS pfaShare, FILEADDRESS faDelete, CHAINDELETETYPE *ptyDelete, CHAINSHARETYPE *ptyShare);
HRESULT _ChainDeleteShare(INDEXORDINAL iIndex, FILEADDRESS faDelete, FILEADDRESS faShare, CHAINSHARETYPE tyShare);
HRESULT _ChainDeleteCoalesce(INDEXORDINAL iIndex, FILEADDRESS faDelete, FILEADDRESS faShare, CHAINSHARETYPE tyShare);
//----------------------------------------------------------------------
// Btree Insertion Methods
//----------------------------------------------------------------------
HRESULT _IndexInsertRecord(INDEXORDINAL iIndex, FILEADDRESS faChain, FILEADDRESS faRecord, LPNODEINDEX piNode, INT nCompare);
HRESULT _ChainInsert(INDEXORDINAL iIndex, LPCHAINBLOCK pChain, LPCHAINNODE pNode, LPNODEINDEX piNodeIndex);
HRESULT _SplitChainInsert(INDEXORDINAL iIndex, FILEADDRESS faLeaf);
//----------------------------------------------------------------------
// Record Persistence Methods
//----------------------------------------------------------------------
HRESULT _GetRecordSize(LPVOID pBinding, LPRECORDMAP pMap);
HRESULT _SaveRecord(LPRECORDBLOCK pBlock, LPRECORDMAP pMap, LPVOID pBinding);
HRESULT _ReadRecord(FILEADDRESS faRecord, LPVOID pBinding, BOOL fInternal=FALSE);
HRESULT _LinkRecordIntoTable(LPRECORDMAP pMap, LPVOID pBinding, BYTE bVersion, LPFILEADDRESS pfaRecord);
//----------------------------------------------------------------------
// Notification / Invoke Methods
//----------------------------------------------------------------------
HRESULT _DispatchInvoke(INVOKETYPE tyInvoke);
HRESULT _DispatchNotification(HTRANSACTION hTransaction);
HRESULT _LogTransaction(TRANSACTIONTYPE tyTransaction, INDEXORDINAL iIndex, LPORDINALLIST pOrdinals, FILEADDRESS faRecord1, FILEADDRESS faRecord2);
HRESULT _CloseNotificationWindow(LPNOTIFYRECIPIENT pRecipient);
HRESULT _FindClient(DWORD dwProcessId, DWORD_PTR dwDB, LPDWORD piClient, LPCLIENTENTRY *ppClient);
HRESULT _FindNotifyRecipient(DWORD iClient, IDatabaseNotify *pNotify, LPDWORD piRecipient, LPNOTIFYRECIPIENT *ppRecipient);
HRESULT _DispatchPendingNotifications(void);
HRESULT _AdjustNotifyCounts(LPNOTIFYRECIPIENT pRecipient, LONG lChange);
//----------------------------------------------------------------------
// Rowset Support Methods
//----------------------------------------------------------------------
HRESULT _AdjustOpenRowsets(INDEXORDINAL iIndex, ROWORDINAL iRow, OPERATIONTYPE tyOperation);
//----------------------------------------------------------------------
// Alloctation Methods
//----------------------------------------------------------------------
HRESULT _MarkBlock(BLOCKTYPE tyBlock, FILEADDRESS faBlock, DWORD cbBlock, LPVOID *ppvBlock);
HRESULT _ReuseFixedFreeBlock(LPFILEADDRESS pfaFreeHead, BLOCKTYPE tyBlock, DWORD cbBlock, LPVOID *ppvBlock);
HRESULT _FreeRecordStorage(OPERATIONTYPE tyOperation, FILEADDRESS faRecord);
HRESULT _FreeStreamStorage(FILEADDRESS faStart);
HRESULT _SetStorageSize(DWORD cbSize);
HRESULT _AllocateBlock(BLOCKTYPE tyBlock, DWORD cbExtra, LPVOID *ppBlock);
HRESULT _AllocateFromPage(BLOCKTYPE tyBlock, LPALLOCATEPAGE pPage, DWORD cbPage, DWORD cbBlock, LPVOID *ppvBlock);
HRESULT _FreeBlock(BLOCKTYPE tyBlock, FILEADDRESS faBlock);
HRESULT _AllocatePage(DWORD cbPage, LPFILEADDRESS pfaAddress);
HRESULT _FreeIndex(FILEADDRESS faChain);
HRESULT _CopyRecord(FILEADDRESS faRecord, LPFILEADDRESS pfaCopy);
HRESULT _FreeTransactBlock(LPTRANSACTIONBLOCK pTransact);
HRESULT _CleanupTransactList(void);
//----------------------------------------------------------------------
// Compaction Helpers
//----------------------------------------------------------------------
HRESULT _CompactMoveRecordStreams(CDatabase *pDstDB, LPVOID pBinding);
HRESULT _CompactMoveOpenDeletedStreams(CDatabase *pDstDB);
HRESULT _CompactTransferFilters(CDatabase *pDstDB);
HRESULT _CompactInsertRecord(LPVOID pBinding);
//----------------------------------------------------------------------
// Index Management
//----------------------------------------------------------------------
HRESULT _ValidateIndex(INDEXORDINAL iIndex, FILEADDRESS faChain, ULONG cLeftNodes, ULONG *pcRecords);
HRESULT _RebuildIndex(INDEXORDINAL iIndex);
HRESULT _RecursiveRebuildIndex(INDEXORDINAL iIndex, FILEADDRESS faCurrent, LPVOID pBinding, LPDWORD pcRecords);
//----------------------------------------------------------------------
// Corruption Validation and Repair Methods
//----------------------------------------------------------------------
HRESULT _HandleOpenMovedFile(void);
HRESULT _SetCorrupt(BOOL fGoCorrupt, INT nLine, CORRUPTREASON tyReason, BLOCKTYPE tyBlock, FILEADDRESS faExpected, FILEADDRESS faActual, DWORD cbBlock);
HRESULT _CheckForCorruption(void);
HRESULT _GetBlock(BLOCKTYPE tyExpected, FILEADDRESS faBlock, LPVOID *ppvBlock, LPMARKBLOCK pMark=NULL, BOOL fGoCorrupt=TRUE);
HRESULT _ValidateAndRepairRecord(LPRECORDMAP pMap);
HRESULT _ValidateStream(FILEADDRESS faStart);
//----------------------------------------------------------------------
// Private Debug Methods
//----------------------------------------------------------------------
IF_DEBUG(HRESULT _DebugValidateRecordFormat(void));
IF_DEBUG(HRESULT _DebugValidateUnrefedRecord(FILEADDRESS farecord));
IF_DEBUG(HRESULT _DebugValidateIndexUnrefedRecord(FILEADDRESS faChain, FILEADDRESS faRecord));
private:
//----------------------------------------------------------------------
// Prototypes
//----------------------------------------------------------------------
LONG m_cRef;
LONG m_cExtRefs;
HANDLE m_hMutex;
#ifdef BACKGROUND_MONITOR
HMONITORDB m_hMonitor;
#endif
DWORD m_dwProcessId;
BOOL m_fDirty;
LPCTABLESCHEMA m_pSchema;
LPSTORAGEINFO m_pStorage;
LPTABLEHEADER m_pHeader;
LPSHAREDDATABASE m_pShare;
HANDLE m_hHeap;
BYTE m_fDeconstruct;
BYTE m_fInMoveFile;
BYTE m_fExclusive;
BYTE m_fCompactYield;
DWORD m_dwQueryVersion;
HQUERY m_rghFilter[CMAX_INDEXES];
IDatabaseExtension *m_pExtension;
IUnknown *m_pUnkRelease;
LPBYTE m_rgpRecycle[CC_HEAP_BUCKETS];
CRITICAL_SECTION m_csHeap;
IF_DEBUG(DWORD m_cbHeapAlloc);
IF_DEBUG(DWORD m_cbHeapFree);
//----------------------------------------------------------------------
// Friend
//----------------------------------------------------------------------
friend CDatabaseQuery;
};
//--------------------------------------------------------------------------
// CDatabaseQuery
//--------------------------------------------------------------------------
class CDatabaseQuery : public IDatabaseQuery
{
public:
//----------------------------------------------------------------------
// Construction
//----------------------------------------------------------------------
CDatabaseQuery(void) {
TraceCall("CDatabaseQuery::CDatabaseQuery");
m_cRef = 1;
m_hQuery = NULL;
m_pDatabase = NULL;
}
//----------------------------------------------------------------------
// De-Construction
//----------------------------------------------------------------------
~CDatabaseQuery(void) {
TraceCall("CDatabaseQuery::~CDatabaseQuery");
CloseQuery(&m_hQuery, m_pDatabase);
SafeRelease(m_pDatabase);
}
//----------------------------------------------------------------------
// IUnknown Members
//----------------------------------------------------------------------
STDMETHODIMP QueryInterface(REFIID riid, LPVOID *ppv) {
TraceCall("CDatabaseQuery::QueryInterface");
*ppv = NULL;
if (IID_IUnknown == riid)
*ppv = (IUnknown *)this;
else if (IID_IDatabaseQuery == riid)
*ppv = (IDatabaseQuery *)this;
else
return TraceResult(E_NOINTERFACE);
((IUnknown *)*ppv)->AddRef();
return S_OK;
}
//----------------------------------------------------------------------
// IDatabaseQuery::AddRef
//----------------------------------------------------------------------
STDMETHODIMP_(ULONG) AddRef(void) {
TraceCall("CDatabaseQuery::AddRef");
return InterlockedIncrement(&m_cRef);
}
//----------------------------------------------------------------------
// IDatabaseQuery::Release
//----------------------------------------------------------------------
STDMETHODIMP_(ULONG) Release(void) {
TraceCall("CDatabaseQuery::Release");
LONG cRef = InterlockedDecrement(&m_cRef);
if (0 == cRef)
delete this;
return (ULONG)cRef;
}
//----------------------------------------------------------------------
// CDatabaseQuery::Initialize
//----------------------------------------------------------------------
HRESULT Initialize(IDatabase *pDatabase, LPCSTR pszQuery) {
TraceCall("CDatabaseQuery::Initialize");
pDatabase->QueryInterface(IID_CDatabase, (LPVOID *)&m_pDatabase);
return(ParseQuery(pszQuery, m_pDatabase->m_pSchema, &m_hQuery, m_pDatabase));
}
//----------------------------------------------------------------------
// CDatabaseQuery::Evaluate
//----------------------------------------------------------------------
STDMETHODIMP Evaluate(LPVOID pBinding) {
TraceCall("CDatabaseQuery::Evaluate");
return(EvaluateQuery(m_hQuery, pBinding, m_pDatabase->m_pSchema, m_pDatabase, m_pDatabase->m_pExtension));
}
private:
//----------------------------------------------------------------------
// Private Data
//----------------------------------------------------------------------
LONG m_cRef;
HQUERY m_hQuery;
CDatabase *m_pDatabase;
};
//--------------------------------------------------------------------------
// PTagFromOrdinal
//--------------------------------------------------------------------------
inline LPCOLUMNTAG PTagFromOrdinal(LPRECORDMAP pMap, COLUMNORDINAL iColumn);