📄 db.cpp
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this sample source code is subject to the terms of the Microsoft
// license agreement under which you licensed this sample source code. If
// you did not accept the terms of the license agreement, you are not
// authorized to use this sample source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the LICENSE.RTF on your install media or the root of your tools installation.
// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
//DB.cpp: Implementation of CVoipDB
#include "DB.h"
BOOL operator==(const SORTORDERSPEC &c_sort1, const SORTORDERSPEC &c_sort2)
{
return !memcmp(&c_sort1, &c_sort2, sizeof(SORTORDERSPEC));
}
BOOL operator!=(const SORTORDERSPEC &c_sort1, const SORTORDERSPEC &c_sort2)
{
return !(c_sort1 == c_sort2);
}
//Destructor: Closes db handle and cleans up resources
CVoipDB::~CVoipDB()
{
if (m_Database != INVALID_HANDLE_VALUE)
{
CloseHandle(m_Database);
}
CEGUID Zeros = {0};
if (memcmp(&Zeros, &m_guidDB, sizeof(CEGUID)) != 0)
{
CeUnmountDBVol(&m_guidDB);
}
}
/*--------------------
Constructor
Params: [in]Database Name, [in] Number of properties in a record
Makes a new instance of this database, that must be initialized to work
----------------------*/
CVoipDB::CVoipDB(
DWORD dwNumProps
)
{
//Set default properties - not initialized, no entries, max entries, handle is invalid
//And no versioning number yet
m_Initialized = FALSE;
m_CurrentNumEntries = 0;
m_MaxNumEntries = INFINITE;
m_NumProps = dwNumProps;
m_Database = INVALID_HANDLE_VALUE;
m_oidDB = 0;
m_CurrentSeek = 0;
ZeroMemory(&m_guidDB, sizeof(m_guidDB));
ZeroMemory(m_pName, sizeof(m_pName));
}
/*-------------------
Function: Initialize
Performs underlying CE DB functions to initialize the underlying DB and member variables
returns: TRUE on success, FALSE on failure
-------------------*/
HRESULT CVoipDB::Initialize(
const WCHAR* pName,
SORTORDERSPECEX* pSort
)
{
if (! pName)
{
ASSERT(FALSE);
return E_POINTER;
}
if (m_Initialized)
{
return HRESULT_FROM_WIN32(ERROR_ALREADY_INITIALIZED);
}
//copy the name
StringCchCopy(
m_pName,
_countof(m_pName),
pName
);
//mount the volume
if (! CeMountDBVol(&m_guidDB, VOIP_DB_VOL_NAME, OPEN_ALWAYS))
{
ASSERT(FALSE);
return HRESULT_FROM_WIN32(GetLastError());
}
//Open the database
HRESULT hr = Open(pSort);
if (FAILED(hr))
{
CeUnmountDBVol(&m_guidDB);
ZeroMemory(&m_guidDB, sizeof(m_guidDB));
return hr;
}
m_Initialized = true;
return S_OK;
}
HRESULT
CVoipDB::Open(
SORTORDERSPECEX* pSort
)
{
//try to open the existing database
m_Database = CeOpenDatabaseEx2(
&m_guidDB,
&m_oidDB,
m_pName,
pSort,
0,
NULL
);
if (m_Database == INVALID_HANDLE_VALUE)
{
//failed to open - is it because the database doesn't exist?
if (GetLastError() != ERROR_FILE_NOT_FOUND)
{
ASSERT(FALSE);
return HRESULT_FROM_WIN32(GetLastError());
}
//database doesn't exist - create it first
CEDBASEINFOEX Info = {0};
Info.wVersion = 1;
Info.dwFlags = CEDB_VALIDCREATE;
Info.dwDbaseType = OBJTYPE_DATABASE;
Info.wNumSortOrder = 1;
StringCchCopy(
Info.szDbaseName,
_countof(Info.szDbaseName),
m_pName
);
memcpy(
&Info.rgSortSpecs[0],
pSort,
sizeof(SORTORDERSPECEX)
);
//create the DB and check return val
m_oidDB = CeCreateDatabaseEx2(
&m_guidDB,
&Info
);
if (! m_oidDB)
{
ASSERT(FALSE);
return HRESULT_FROM_WIN32(GetLastError());
}
m_Database = CeOpenDatabaseEx2(
&m_guidDB,
&m_oidDB,
m_pName,
pSort,
0,
NULL
);
if (m_Database == INVALID_HANDLE_VALUE)
{
ASSERT(FALSE);
return HRESULT_FROM_WIN32(GetLastError());
}
}
//read the existing properties from the database
CEOIDINFO OidInfo = {0};
if (! CeOidGetInfoEx(&m_guidDB, m_oidDB, &OidInfo))
{
goto error;
}
if (OidInfo.wObjType != OBJTYPE_DATABASE || OidInfo.infDatabase.wNumRecords < 0)
{
ASSERT(FALSE);
SetLastError(ERROR_DATABASE_FAILURE);
goto error;
}
//record the current number of entries...
m_CurrentNumEntries = OidInfo.infDatabase.wNumRecords;
m_CurrentSeek = 0;
return S_OK;
error:
CloseHandle(m_Database);
m_Database = INVALID_HANDLE_VALUE;
return HRESULT_FROM_WIN32(GetLastError());
}
/*-------------------
Function: AddNewRecord
Params: [in] CEPROPVAL* (a record) - array of cepropvals
Adds a new recod to the DB
returns: a valid CEOID (of the records location in the DB) on success, 0 on failure
-------------------*/
HRESULT CVoipDB::AddNewRecord(
CEPROPVAL *pcpv,
CEOID* pOid
)
{
//Check Params
if (pcpv == NULL || ! pOid)
{
ASSERT(FALSE);
return E_POINTER;
}
//Initialize the out parameter
*pOid = NULL;
//Write the record to the DB
*pOid = CeWriteRecordProps(
m_Database,
0,
(WORD)(m_NumProps),
pcpv
);
if (*pOid)
{
m_CurrentNumEntries++;
if (m_CurrentNumEntries > m_MaxNumEntries)
{
RemoveOldest();
}
return S_OK;
}
return HRESULT_FROM_WIN32(GetLastError());
} //AddNewRecord
/*-------------------
Function: FindRecord
Params: [in] CEPROPVAL (propid and value to search for)
Finds a record in the DB by searching on a cepropval
returns: CEOID of matching record on success, 0 on failure
-------------------*/
CEOID CVoipDB::FindRecord(
CEPROPVAL* pVal
)
{
//Seek to the first value that matches this property
DWORD dwIndex = 0;
return CeSeekDatabase(
m_Database,
CEDB_SEEK_VALUEFIRSTEQUAL,
(DWORD)pVal,
&dwIndex
);
} //FindRecord
/*-------------------
Function: DeleteRecord
Params: [in] CEOID the record to delete
Deletes the record
returns: TRUE on success, FALSE on failure
-------------------*/
BOOL CVoipDB::DeleteRecord(CEOID ceoid)
{
if (CeDeleteRecord(m_Database, ceoid))
{
m_CurrentNumEntries--;
return TRUE;
}
return FALSE;
} //DeleteRecord
/*-------------------
Function: EditRecord
Params: [in]CEOID ceoid to rewrite, [in]CEPROPVAL* record, [in]int number of props
ReWrites a record's properties to the DB using a CEOID as index
returns: TRUE on success, FALSE on failure
-------------------*/
BOOL CVoipDB::EditRecord(CEOID ceoid, CEPROPVAL *pcpvNew, int cProps)
{
return (CeWriteRecordProps(m_Database, ceoid, cProps, pcpvNew) == ceoid);
} //Edit Record
/*-------------------
Function: ReadCurrentRecord
Params: [out]CEPROPVAL**, [out]int*, [out]ceoid*
1. Fills in cepropval** with contents of current record
2. Fills int* with size of cepropval** in ints
returns: TRUE on success, FALSE on failure
Note: ppcpvFill needs to be freed by LocalFree after this is called.
-------------------*/
BOOL CVoipDB::ReadCurrentRecord(CEPROPVAL **ppcpvFill, int *pcSize, CEOID *pceoid)
{
int cb = 0;
WORD wCount = 0;
//Check params
if (ppcpvFill == NULL || pcSize == NULL || pceoid == NULL)
{
ASSERT(FALSE);
return FALSE;
}
//Initialize filling array
*ppcpvFill = NULL;
//Read props from DB with all defaults, and allow the DB to reallocate memory, return ceoid
*pceoid = CeReadRecordProps(
m_Database,
CEDB_ALLOWREALLOC,
&wCount,
NULL,
(BYTE **)ppcpvFill,
(ULONG*)&cb
);
*pcSize = wCount;
return (*pceoid != 0);
} //ReadRecord
/*-------------------
Function: SeekTo Next
Params: [in] int cElts
Seeks to the next cElt'th element
returns: TRUE on success, FALSE on failure
-------------------*/
BOOL CVoipDB::SeekToNext(
int cElts
)
{
CEOID ceoid;
DWORD dwIndex = 0;
//Check param
if (cElts < 0)
{
return FALSE;
}
//If you seek 0 elements forward, nothing can go wrong.
if (cElts == 0)
{
return TRUE;
}
//If we are not at the begnining of the db, seek from current
if (m_CurrentSeek != 0)
{
ceoid = CeSeekDatabase(m_Database, CEDB_SEEK_CURRENT, cElts, &dwIndex);
}
else
{
//else seek from beginning-1 (for 0th element)
ceoid = CeSeekDatabase(m_Database, CEDB_SEEK_BEGINNING, cElts-1, &dwIndex);
}
if (ceoid != 0)
{
m_CurrentSeek += cElts;
return TRUE;
}
return FALSE;
}
//Resets the seek member variable, so that an enumerator will seek from
//the beginning of the DB
BOOL CVoipDB::ResetSeek()
{
m_CurrentSeek = 0;
return TRUE;
}
int CVoipDB::GetCapacity()
{
if (!m_Initialized)
return -1;
return m_MaxNumEntries;
}
BOOL CVoipDB::RemoveOldest()
{
DWORD dwIndex = 0;
CEOID ceoid = 0;
//If we are allowing infinite number of records, we don't need to ever
//remove the oldest
if (m_MaxNumEntries == INFINITE)
{
return TRUE;
}
//Seek to the end of the DB as the records are in descending order by timestamp
ceoid = CeSeekDatabase(m_Database, CEDB_SEEK_END, 0, &dwIndex);
if (! ceoid)
{
return FALSE;
}
//Reset seek
m_CurrentSeek = 0;
//Delete oldest - also updates version number
DeleteRecord(ceoid);
return TRUE;
}
/*-------------------
Function: Resize
Params: [in] int newMax
1. If there are more entries in the DB than newMax
remove the records over the threshold value.
returns: TRUE on success, FALSE on failure
-------------------*/
BOOL CVoipDB::Resize(int dwMaxNew)
{
//if we are allowing infinite records, no need to resize
if (dwMaxNew == INFINITE)
{
return TRUE;
}
//continually remove the oldest record until we have the desired number of records
if (m_CurrentNumEntries > dwMaxNew)
{
while (m_CurrentNumEntries > dwMaxNew)
{
//Changes the version number for us.
if (!RemoveOldest())
return FALSE;
m_MaxNumEntries = m_CurrentNumEntries;
}
}
m_MaxNumEntries = dwMaxNew;
return TRUE;
}//Resize
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -