Comparing Store Identifiers

When a user connects a device to a desktop:

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

    This number is stored in Repl.dat.

  2. The service manager reads the store identifier for the store to be synchronized and passes this identifier number to IReplStore::CompareStoreIDs.
  3. The desktop provider module determines whether this store identifier matches the one loaded from Repl.dat, which identifies the store that was used in the previous synchronization.

If the identifiers do not match, the service manager reestablishes the mapping between the desktop and device objects by issuing a request to the user either to combine two sets of data or to discard the device data and send all desktop objects to the device.

The combine and discard process is required when Repl.dat is corrupt and cannot be read, as well as when the user:

If a user chooses to combine the data, all objects on both the device and the desktop are marked as changed. If a user chooses to discard the data, all objects on the device are marked as deleted and all desktop objects are marked as changed. Synchronization occurs immediately after a user makes a selection.

Combining data typically creates duplicate objects in the desktop store. To find the duplicate objects in the desktop store and remove them, use IReplStore::RemoveDuplicates. The service manager calls this method after the first successful synchronization occurs. Once duplicated objects are removed, the desktop provider module returns control to the service manager to begin enumerating the store. Through enumeration, the service manager determines which desktop objects are deleted and informs the device to remove the corresponding device objects.

In addition to using IReplStore::GetStoreInfo to provide identification information, you can use this method to perform other tasks, such as changing the size of an object store or the time interval between enumerations. When the service manager calls IReplStore::GetStoreInfo, it passes the structure STOREINFO. Use STOREINFO to change store information:

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

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

    // If the size of the first store identifier is larger than 
    // the size of the second store 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 the store. You can change this to match your company 
    // and your product. 
    lstrcpy( pInfo->szProgId, "MyCompany.WinCE.DeskSamp" );

    // The description of the store. This will be displayed to the user. 
    // You can change this to suit your requirements.
    lstrcpy( pInfo->szStoreDesc, "Files" );

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

    // Construct something that uniquely identifies 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 the pointer to the store identifier is NULL.
    if ( pInfo->lpbStoreId == NULL )
        return E_POINTER;

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