Share via


Comparing Store Identifiers

A version of this page is also available for

Windows Embedded CE 6.0 R3

4/8/2010

After a store is initialized, the provider must compare store identifiers and handle mismapped store identifiers by prompting the user to either combine the two sets of objects or replace the device objects with objects from the desktop.

When a user connects a device to a desktop

  1. The desktop service manager calls IReplStore::GetStoreInfo to retrieve the device store's identifier.

  2. This number is stored in the service manager's persistent file.

  3. The service manager reads the identifier for the store to be synchronized and passes this identifier to IReplStore::CompareStoreIDs.

  4. The desktop provider determines whether this store identifier matches the store identifier loaded from the service manager's persistent file, which identifies the store used in the previous synchronization.

If the identifiers do not match, the service manager reestablishes the mapping between the desktop and device objects by prompting the user to either combine the two sets of objects or replace the device objects with objects from the desktop.

The combine/replace process is required when the user performs any of the following actions.

  • Synchronizes a Windows Mobile device with existing data for the first time.
  • Deletes a device profile without also deleting the accompanying profile information on the Windows Mobile device, and then reconnects the device to create a new partnership.
  • Chooses a desktop store that is different from the one that was used in the last synchronization. The service manager detects the new selection by comparing store identifiers.
  • Restores the device data from a backup file.
  • Performs a replace operation on one computer, and then synchronizes the Windows Mobile device with a second computer.

If the user chooses to combine the data, all objects on both the Windows Mobile device and the desktop are marked as changed. If the user chooses to replace the data, all device objects are marked as deleted and all desktop objects are marked as changed. Synchronization occurs immediately after the choice is made.

Combining data usually creates duplicate objects in the desktop store. The service manager calls IReplStore::RemoveDuplicates to find and remove the duplicates after the first successful synchronization. Once duplicated objects are removed, the desktop provider returns control to the service manager to enumerate the store. The service manager determines which desktop objects are deleted and informs the Windows Mobile device to remove the corresponding device objects.

Besides supplying identification information, IReplStore::GetStoreInfo can do other things, such as changing the size of an object store or the time interval between enumerations. The STOREINFO structure is passed through IReplStore::GetStoreInfo, and is used to change store information in the following manner.

  • To receive an identifier for a variable-sized store, set STOREINFO::cbMaxStoreId to 0. This call should prompt the desktop provider to set the requested size for the store identifier in STOREINFO::cbStoreId and return E_OUTOFMEMORY. In response, the service manager allocates the required memory and passes a pointer to the store identifier in STOREINFO::lpbStoreId. The desktop provider can then use this pointer to save the store identifier.
  • If you choose to write a desktop provider that does not support real-time notification of changes, you should enable automatic enumeration by setting STOREINFO::uTimerRes.
    • To automatically enumerate the store at a specified interval, set STOREINFO::uTimerRes to the non-zero interval, in microseconds. The interval should be at least several times as long as it takes to perform an enumeration. Otherwise, the service manager will be enumerating "continuously."
    • If STOREINFO::uTimerRes is set to 0, the service manager begins enumeration immediately before synchronization, or when the user activates the ActiveSync status window.

The following code example shows how to implement the STOREINFO structure and the IReplStore::CompareStoreIDs and IReplStore::GetStoreInfo methods.

Note

To make the following code example easier to read, error checking is not included. This code example should not be used in a release configuration unless it has been modified to include secure error handling.

STDMETHODIMP_(int) CStore::CompareStoreIDs
(
   LPBYTE  lpbID1,  // points to first  store identifier
   UINT    cbID1,   // size of   first  store identifier
   LPBYTE  lpbID2,  // points to second store identifier
   UINT    cbID2    // size of   second store identifier
)
{
   // if first identifier is smaller than second identifier
   if (cbID1 < cbID2)
      return -1;

   // if first identifier is larger  than second identifier
   if (cbID1 > cbID2)
      return  1;

   return memcmp (lpbID1, lpbID2, cbID1);
}

STDMETHODIMP CStore::GetStoreInfo
(
   PSTOREINFO pInfo  // pointers to the STOREINFO structure
)
{
   if (pInfo->cbStruct != sizeof (STOREINFO))
      return E_INVALIDARG;

   pInfo->uFlags = SCF_SINGLE_THREAD | SCF_SIMULATE_RTS;

   // ProgId of store.      Change to match company and product.
   lstrcpyn (pInfo->szProgId,
             "MyCompany.WinCE.DeskSamp",
             sizeof(pInfo->szProgId));

   // Description of store. Change to fit requirements.
   lstrcpyn (pInfo->szStoreDesc, 
             "Files",
             sizeof(pInfo->szStoreDesc));

   // Let replication scan the store every 5 seconds.
   pInfo->uTimerRes = 5000;

   // Choose a unique identifier for the store. In this example,
   // because the differences in the stores are inconsequential,
   // set the size of the store identifier to any value.
   pInfo->cbStoreId = 10;

   // Compare the size of the the store identifier with the maximum
   // size of the store identifier.
   if (pInfo->cbStoreId > pInfo->cbMaxStoreId)
       return E_OUTOFMEMORY;

   // Check if pointer to store identifier is NULL.
   if (pInfo->lpbStoreId == NULL)
       return E_POINTER;

   memset (pInfo->lpbStoreId, 0, 10);
   return NOERROR;
}

See Also

Concepts

Developing the Desktop Provider