I need to seek a Database which I build in wince 5.0's "cemail.vol" volume Database file. It's the CEDB so I have to use the CEDB's winapi.
My develop&test entironment is vs2005 vc8 + CF .NET 2.0(not yet install sp1) + WM5 PPC SDK + CHS WM5 pocket PC.
At first, I used CeCreateDatabaseEx() create my database in cemail.vol with one sort column. Code like that:
#define PKEY_PHONENUM MAKELONG(CEVT_LPWSTR,2)
#define PKEY_VALUE MAKELONG(CEVT_LPWSTR,3)
CEGUID m_ceguidDB;
CEDBASEINFO m_MyDB;
HANDLE dbMyDB = NULL;
CEOID oidDb = 0;
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
int ret;
CREATE_INVALIDGUID(&m_ceguidDB);
...
if (!CeMountDBVol(&m_ceguidDB, L"cemail.vol", OPEN_EXISTING ))
{
DWORD dwErr = GetLastError();
CeUnmountDBVol(&m_ceguidDB);
return false;
}
else
{
memset(&m_MyDB, 0, sizeof(m_MyDB));
m_MyDB.dwDbaseType = 0;
m_MyDB.dwFlags = CEDB_VALIDNAME | CEDB_NOCOMPRESS;
m_MyDB.wNumSortOrder = 1;
m_MyDB.rgSortSpecs[0].propid = PKEY_ID;
m_MyDB.rgSortSpecs[0].dwFlags = CEDB_SORT_NONNULL;
wcscpy(m_MyDB.szDbaseName,L"MyDB");
CeCreateDatabaseEx(&m_ceguidDB,&m_MyDB);
ret = GetLastError();
}
}
Then I write a function to add 2 record for testing seek:
{
CEPROPVAL *pProps;
dbMyDB = CeOpenDatabaseEx(&m_ceguidDB, &oidDb, L"MyDB", NULL, CEDB_AUTOINCREMENT, NULL);
if (dbMyDB == 0)
return false;
pProps = new CEPROPVAL[3];
memset(pProps,0,sizeof(pProps));
pProps->propid = PKEY_ID;
pProps->wFlags = 0;
pProps->wLenData = 0;
pProps->val.ulVal = 1;
pProps++;
memset(pProps,0,sizeof(pProps));
pProps->propid = PKEY_TYPE;
pProps->wFlags = 0;
pProps->wLenData = 0;
pProps->val.lpwstr = L"11";
pProps++;
memset(pProps,0,sizeof(pProps));
pProps->propid = PKEY_VALUE;
pProps->wFlags = 0;
pProps->wLenData = 0;
pProps->val.lpwstr = L"111111";
pProps = pProps - 2;
oidDb = CeWriteRecordProps(dbMyDB, 0, 3, pProps);
if (oidDb == 0)
{
CloseHandle(dbMyDB);
return false;
}
memset(pProps,0,sizeof(pProps));
pProps->propid = PKEY_ID;
pProps->wFlags = 0;
pProps->wLenData = 0;
pProps->val.ulVal = 2;
pProps++;
memset(pProps,0,sizeof(pProps));
pProps->propid = PKEY_TYPE;
pProps->wFlags = 0;
pProps->wLenData = 0;
pProps->val.lpwstr = L"22";
pProps++;
memset(pProps,0,sizeof(pProps));
pProps->propid = PKEY_VALUE;
pProps->wFlags = 0;
pProps->wLenData = 0;
pProps->val.lpwstr = L"222222";
pProps = pProps - 2;
oidDb = CeWriteRecordProps(dbMyDB, 0, 3, pProps);
if (oidDb == 0)
{
CloseHandle(dbMyDB);
return false;
}
return true;
}
Now I can seek the DB like that:
{
WORD wProp;
PBYTE pBuff = NULL;
DWORD dwRecSize;
DWORD dwSize = 0;
CEOID m_ceoid=0;
CEOID tempOid = 0;
PCEPROPVAL pProp = new CEPROPVAL;
pProp->propid = PKEY_ID;
pProp->wFlags = 0;
pProp->wLenData = 0;
pProp->val.ulVal = 1;
dbMyDB = CeOpenDatabaseEx(&m_ceguidDB, &m_ceoid, L"MyDB", NULL, 0, NULL);
//dbMyDB = CeOpenDatabaseEx(&m_ceguidDB, &m_ceoid, L"MyDB", PKEY_ID, 0, NULL);
ret= GetLastError();
if (dbMyDB == 0)
return false;
else
{
tempOid = CeSeekDatabase(dbMyDB, EDB_SEEK_BEGINNING,0,NULL);
//tempOid = CeSeekDatabase(dbMyDB, CEDB_SEEK_VALUEFIRSTEQUAL, DWORD)&pProp, &dwSize);
ret = GetLastError();
if (tempOid != 0)
{
tempOid = CeReadRecordPropsdbMyDB, CEDB_ALLOWREALLOC, &wProp, NULL, &(LPBYTE)pBuff, &dwRecSize);
pProp = (PCEPROPVAL)pBuff;
for (int i=0;i<WPROP;I++)
{
if (pProp->propid == PKEY_VALUE)
{
//do something here
return true;
}
pProp++;
}
}
}
return false;
}
When I use CeOpenDatabaseEx(&m_ceguidDB, &m_ceoid, L"MyDB", NULL, 0, NULL), it returns the first record correctly.But when I use CeOpenDatabaseEx(&m_ceguidDB, &m_ceoid, L"MyDB", PKEY_ID, 0, NULL), the handle "dbMyDB" is 0xffffffff, the result of GetLastError() after CeOpenDatabaseEx() is 0x00000057 and CeSeekDatabase(dbMyDB, CEDB_SEEK_VALUEFIRSTEQUAL, (DWORD)&pProp, &dwSize) returns 0 always.
I try to search with Google, see many people ask with the same question but nobody get a correct answer. At last I find something in MSDN: CeOpenDatabaseEx (CEDB) is obsolete. Applications should call CeOpenDatabaseEx2 instead.
So I think CeOpenDatabaseEx()(CEDB) with CEDB_SEEK_VALUEFIRSTEQUAL Parameter is abandoned and always return 0 in WM5. Then I try to use CeOpenDatabaseEx2()(CEDB). Also I noticed I have to use the function CeOpenDatabaseEx2()(CEDB) to open the database first. So I modified the TestSeek() function like that:
{
WORD wProp;
PBYTE pBuff = NULL;
DWORD dwRecSize;
DWORD dwSize = 0;
CEOID m_ceoid=0;
CEOID tempOid = 0;
SORTORDERSPECEX sortkey;
sortkey.wVersion = 1;
sortkey.wNumProps = 1;
sortkey.wKeyFlags = 0;
sortkey.rgPropID[0] = PKEY_ID;
sortkey.rgdwFlags[0] = CEDB_SORT_NONNULL;
PCEPROPVAL pProp = new CEPROPVAL;
pProp->propid = PKEY_ID;
pProp->wFlags = 0;
pProp->wLenData = 0;
pProp->val.ulVal = 1;
dbMyDB = CeOpenDatabaseEx2(&m_ceguidDB, &m_ceoid, L"MyDB", &sortkey, 0, NULL);
ret= GetLastError();
if (dbMyDB == 0)
return false;
else
{
tempOid = CeSeekDatabaseEx(dbMyDB, CEDB_SEEK_VALUEFIRSTEQUAL, (DWORD)&pProp, 1, &dwSize);
ret = GetLastError();
if (tempOid != 0)
{
tempOid = CeReadRecordPropsdbMyDB, CEDB_ALLOWREALLOC, &wProp, NULL, &(LPBYTE)pBuff, &dwRecSize);
pProp = (PCEPROPVAL)pBuff;
for (int i=0;i<WPROP;I++)&NBSP;
{
if (pProp->propid == PKEY_VALUE)
{
//do something here
return true;
}
pProp++;
}
}
}
return false;
}
Unluckly the result is the same, the handle "dbMyDB" is 0xffffffff, the result of GetLastError() after CeOpenDatabaseEx2() is 0x00000057 and CeSeekDatabaseEx(dbMyDB, CEDB_SEEK_VALUEFIRSTEQUAL, (DWORD)&pProp, 1, &dwSize) returns 0.
So maybe it is the last chance for me to approach the goal. I should use CeCreateDatabaseEx2() to create database at the beginning. After every inch search from Google&MSDN, I write the code behind:
{
int ret;
CREATE_INVALIDGUID(&m_ceguidDB);
...
if (!CeMountDBVol(&m_ceguidDB, L"cemail.vol", OPEN_EXISTING ))
{
DWORD dwErr = GetLastError();
CeUnmountDBVol(&m_ceguidDB);
return false;
}
else
{
CEDBASEINFOEX dbinfo;
ZeroMemory(&dbinfo, sizeof(CEDBASEINFOEX));
dbinfo.wVersion = 1;
wcscpy(dbinfo.szDbaseName, L"MyDB");
dbinfo.dwFlags = CEDB_VALIDCREATE;
dbinfo.wNumSortOrder = 1;
dbinfo.rgSortSpecs[0].wVersion = 1;
dbinfo.rgSortSpecs[0].wNumProps = 1;
dbinfo.rgSortSpecs[0].wKeyFlags = 0;
dbinfo.rgSortSpecs[0].rgPropID[0] = MAKELONG(CEVT_I4, 1);
dbinfo.rgSortSpecs[0].rgdwFlags[0] = CEDB_SORT_NONNULL;
CeCreateDatabaseEx2(&m_ceguidDB, &dbinfo);
ret = GetLastError();
}
}
The code pass the compile&build&run perfectly. But fateful error is: It can not create the database in fact. GetLastError() returns 0x00000057 always. I check the "windbase.h" for the last time, and find something different with MSDN. It is the definition of SORTORDERSPECEX. In CEDB it should has 5 properties, instead of EDB, it has 6 properties. But in "windbase.h" just have one define with 6 properties. Maybe that's the reason why I failed to create CEDB database with SORTORDERSPECEX property?
Finally I tried all the ways I can think out, now I admitted my defeat. Does anybody know how to seek CEDB database use with CEDB_SEEK_VALUEFIRSTEQUAL Parameter? If you known it exactly and may post the correct code, I will be great thanks for your kindness. And I think many developer will also thank for your help.