Microsoft KB Archive/300928

= HOW TO: Use a Windows CE Database in VC++ =

PSS ID Number: 300928

Article Last Modified on 10/27/2002

-

The information in this article applies to:


 * Microsoft Windows CE Toolkit for Visual C++ 6.0

-



This article was previously published under Q300928





IN THIS TASK

 * SUMMARY
 * ** Requirements
 * How to Use a Windows CE Database
 * Troubleshooting
 * REFERENCES



SUMMARY
Databases provide storage, access, and sorting of property-set records. The Microsoft(r) Windows(r) CE database model is a small, flat structure that is optimized for small, efficient storage. This article illustrates how to use a Windows CE database.

back to the top

Requirements
The following list outlines the recommended hardware, software, network infrastructure, and service packs that you will need:
 * Microsoft Windows CE device
 * Microsoft Windows 2000 or Windows NT(r) 4.0 Workstation, Service Pack 5 or later.
 * Microsoft eMbedded Visual C++(r) (eVC) version 3.0 (formerly known as the Microsoft Windows CE Toolkit for Visual C++ version 6.0)

back to the top

How to Use a Windows CE Database
Using a Windows CE database is a multi-step activity and includes many options within each step. At its simplest level, follow these steps:
 * 1) Mount a volume that can store Windows CE databases.Create a database (first time only).Open a database.Find a record or location in the database.Read a record, or write a record.Unmount the database volume.
 * 2) Create a database (first time only).Open a database.Find a record or location in the database.Read a record, or write a record.Unmount the database volume.
 * 3) Open a database.Find a record or location in the database.Read a record, or write a record.Unmount the database volume.
 * 4) Find a record or location in the database.Read a record, or write a record.Unmount the database volume.
 * 5) Read a record, or write a record.Unmount the database volume.
 * 6) Unmount the database volume.

The details for these steps are as follows:    Call the CeMountDBVol function to mount a volume that can store Windows CE databases on any file system, including the object store or an installed file system such as the FAT file system on a PC Card. CeMountDBVol accepts the location of the file that is the database volume and returns a PCEGUID structure.   Use the CeCreateDatabaseEx function to create a database in any volume. CeCreateDatabaseEx identifies the volume, names the database, identifies the sort order, and allows you to pass in a user-defined type identifier.

The following code sample shows how an application opens an address database: HANDLE OpenDatabase (     HWND hwndNotify,  // Handle to the window to which                        // notification messages are posted.      PCEGUID pceguid,  // Pointer to the mounted database                        // volume in which the database that                        // will be opened resides.      CEOID CeOid)      // Object identifier of the database // to be opened. { int index; DWORD dwError;             // Return value from GetLastError HANDLE hDataBase;          // Open handle to the address database CENOTIFYREQUEST *pRequest; // CENOTIFYREQUEST structure CEDBASEINFO CEDBInfo;      // Structure containing the // database data TCHAR szError[100];        // String to use with error messages

// Allocate memory for pRequest. pRequest = (CENOTIFYREQUEST *) LocalAlloc (LPTR,                                       sizeof (CENOTIFYREQUEST)); pRequest->dwSize = sizeof (CENOTIFYREQUEST); pRequest->hwnd = hwndNotify; pRequest->hHeap = NULL; // Let system allocate memory properly. pRequest->dwFlags = 0; // Notifications are handled as they // were in Windows CE version 1.0. hDataBase = CeOpenDatabaseEx (         pceguid,            // Pointer to the mounted volume          &CeOid,             // Location for the database identifier          TEXT(&quot;MyDBase&quot;),    // Database name          0,                  // Sort order; 0 indicates to ignore          CEDB_AUTOINCREMENT, // Automatically increase seek pointer          pRequest);          // Pointer to a CENOTIFYREQUEST // structure if (hDataBase == INVALID_HANDLE_VALUE) {   dwError = GetLastError ; if (dwError == ERROR_NOT_ENOUGH_MEMORY) {     wsprintf (szError, TEXT(&quot;Not enough memory&quot;)); }   else {     // Possibility of non-existent database; create it. // Initialize structure CEDBInfo memset (&CEDBInfo, 0, sizeof(CEDBInfo));

// Create the database with the following specified flags. // Create the database as uncompressed. // You can use CeSetDataBaseInfoEx to compress the database. CEDBInfo.dwFlags = CEDB_VALIDNAME       // szDbaseName is valid | CEDB_VALIDTYPE     // dwDbaseType is valid | CEDB_VALIDDBFLAGS  // HIWORD of dwFlag is valid | CEDB_VALIDSORTSPEC // rgSortSpecs is valid | CEDB_NOCOMPRESS;   // The database is not compressed.

// Assign the database name as MyDBase. wcscpy (CEDBInfo.szDbaseName, TEXT(&quot;MyDBase&quot;));

// Assign the database type. CEDBInfo.dwDbaseType = 0;

// Set the number of active sort orders to 4. // This is the maximum number allowed. CEDBInfo.wNumSortOrder = 4;

// Initialize the array of sort-order descriptions. for (index = 0; index < CEDBInfo.wNumSortOrder; ++index) {       // Sort in descending order. CEDBInfo.rgSortSpecs[index].dwFlags = CEDB_SORT_DESCENDING;

// Assign the identifier of the properties by which to sort. // CEDBInfo.rgSortSpecs[index].propid = ...; }

// Create database &quot;MyDBase&quot;. CeOid = CeCreateDatabaseEx (pceguid, &CEDBInfo);

if (CeOid == NULL) {       wsprintf (szError,                  TEXT(&quot;ERROR: CeCreateDatabaseEx failed (%ld)&quot;),                  GetLastError ); }     else  // Succeeded in creating the database; open it. {       hDataBase = CeOpenDatabaseEx (pceguid, &CeOid,                          TEXT(&quot;MyDBase&quot;), 0, 0, pRequest); }   }  }

// Return the database handle. return hDataBase; } // End of OpenDatabase sample code /*   After you create a database, use the CeOpenDatabaseEx function to open it. The preceding code sample demonstrates this.   Before you can read and write a record in a database, you must find the record. Use the CeSeekDatabase function to move the database seek pointer to the record that you want to read from or write to.

The following code sample shows how to use CeSeekDatabase to search for a record: void UsingCeSeekDatabase (void) { CEOID CeOid;          // Object identifier CEOID CeOidSeek;     // Object identifier DWORD dwIndex;       // Index of record to seek TCHAR szError[100];  // String for displaying error messages HANDLE hDataBase;    // Handle to a user-allocated heap

// Assign to CeOidSeek the object identifier of the record // being searched for. // ... // Call CeOpenDatabaseEx to open the database. // hDataBase = CeOpenDatabaseEx {...}

// Perform the seek. This type of seek operation is very efficient. if ((CeOid = CeSeekDatabase(             hDataBase,        // Handle of the database              CEDB_SEEK_CEOID,  // Finding an object with the                                // same identifier              CeOidSeek,        // Specifies the record to seek              &dwIndex          // If successful, moves the database                                // pointer to point to the record                )) == 0) {   wsprintf (szError, TEXT(&quot;ERROR: CeSeekDatabase failed (%ld)&quot;),                          GetLastError ); } } // End of UsingCeSeekDatabase sample code   After a record is found, call the CeReadRecordPropsEx function to read the properties of the record as follows: void ReadingDBRecords (void) { CEOID CeOid;            // Object identifier of the record read PCEGUID pceguid;       // Pointer to the mounted database volume WORD wcPropID;         // Number of properties retrieved DWORD dwcbBuffer,      // Count of bytes of the *lpBuffer dwError;         // Return value of the GetLastError function TCHAR szMsg[100];      // String for displaying the error message LPBYTE lpBuffer = NULL; // Pointer to a buffer that receives record- // property data HANDLE hDataBase,      // Handle to a database to be opened hHeap;          // Handle to the heap for allocating records

// Assign to pceguid the GUID of the mounted volume // in which the database resides. // ... // Create the heap by calling HeapCreate to allocate the database // records. // ... // Open the database with the current seek position to be  // incremented automatically with each call.

hDataBase = CeOpenDatabaseEx (         pceguid,            // Pointer to the mounted volume          &CeOid,             // Location of the database identifier          TEXT(&quot;MyDBase&quot;),    // Database name          0,                  // Sort order; 0 indicates to ignore.          CEDB_AUTOINCREMENT, // Automatically increase seek pointer          NULL);              // Does not need to receive notification

// Check for errors on the hDataBase handle before continuing. if (hDataBase == INVALID_HANDLE_VALUE) {   // Your error-handling code goes here. return; } while ((CeOid = CeReadRecordPropsEx (            hDataBase,          // Handle of the database            CEDB_ALLOWREALLOC,  // Use LocalAlloc to get the buffer            &wcPropID,          // Number of properties retrieved            NULL,               // NULL means retrieve all properties            &lpBuffer,          // Buffer receives property data            &dwcbBuffer,        // Count of bytes in *lpBuffer            hHeap)) != 0)       // Handle to the heap for allocating // the record when // CEDB_ALLOWREALLOC is specified {   // The record is now available in the lpBuffer. Add code here to   // manipulate the properties in this record. // ... }

// Error handling if CeReadRecordPropsEx fails dwError = GetLastError ; if (dwError == ERROR_NO_MORE_ITEMS) {   wsprintf (szMsg,              TEXT(&quot;Read through all records in the database.&quot;)); } else if (dwError == ERROR_INSUFFICIENT_BUFFER) {   wsprintf (szMsg,              TEXT(&quot;Re-allocation of database records failed.&quot;)); } else {   wsprintf (szMsg, TEXT(&quot;Other errors.&quot;)); } // Close the database handle. CloseHandle (hDataBase); } // End of ReadingDBRecords sample code. </li> Call the CeWriteRecordProps function to write to a record. Similar to CeReadRecordPropsEx, CeWriteRecordProps uses an array of CEPROPVAL structures to pass property information into the record. To create a new record, call CeWriteRecordProps with the oidRecord parameter set to 0. </li>  Call the CeUnmountDBVol function to unmount a database volume, which flushes the database volume so that you do not have to call CeFlushDBVol to save any data. void UnmountingDBs (PCEGUID pceguid) { TCHAR szMsg[100]; if (!CeUnmountDBVol (pceguid)) {   wsprintf (szMsg, TEXT(&quot;Failed unmounting the database.&quot;)); // Your error-handling code goes here. } } // End of UnmountingDBs sample code </li></ol>

back to the top

Troubleshooting
Because Windows CE is designed to operate in a relatively volatile environment, the Windows CE database does not update automatically when the database opens or closes. Instead, the database updates after each individual transaction, such as a call to the CeWriteRecordProps function.

back to the top

<div class="references_section">