Handling Conflicts

A conflict occurs when an object has changed on both the device and the desktop since the last synchronization. To resolve a conflict, the service manager calls IReplObjHandler::GetPacket on the device to send the object to the desktop. The service manager then calls IReplObjHandler::SetPacket on the desktop to create a temporary object. During both the device and the desktop call, the service manager passes RSF_CONFLICT_OBJECT in REPLSETUP::dwFlags.

The following illustration shows the call sequence for conflict resolution.

After the service manager receives the data from the device, it calls IReplStore::GetConflictInfo and passes a handle to both the original desktop object and the temporary device object. Next, the desktop provider module must fill in the CONFINFO structure to customize the description text displayed in a standard Conflict Resolution dialog box, which is supplied by the service manager.

The following code example shows how to implement IReplStore::GetConflictInfo.

STDMETHODIMP CStore::GetConflictInfo
( 
    PCONFINFO pConfInfo         // Oointer to a CONFINFO structure
)
{
    // Verify that you have the right version of OBJUIDATA.
    if ( pConfInfo->cbStruct != sizeof( CONFINFO ) )
        return E_INVALIDARG;

    // Copy "Stock" to szLocalName and szRemoteName. You can use your 
    // own local and remote object names to replace "Stock".
    lstrcpy( pConfInfo->szLocalName, "Stock" );
    lstrcpy( pConfInfo->szRemoteName, "Stock" );

    CItem   *pLocalItem = (CItem *)pConfInfo->hLocalItem;
    CItem   *pRemoteItem = (CItem *)pConfInfo->hRemoteItem;

    // Find the local object, and then the remote object. 
    // pLocalObject points to the local object.
    // pRemoteObject points to the remote object.

    // If both the local and remote objects are found
    if (pLocalObject && pRemoteObject )
    {
        // Compare the local and remote objects.
        // If the local and remote objects are identical
        return RERR_IGNORE;
    }

    // If a local object is found
    if ( pLocalObject )
        // Store information for the local object 
        // in pConfInfo->szLocalDesc.

    // If a remote object is found
    if ( pRemoteObject )
        // Store information for the remote object in 
        // pConfInfo->szRemoteDesc.
 
    return NOERROR;
}

If the desktop provider module cannot write a temporary object on the desktop, it can save the packets into memory and return HREPLITEM containing a pointer to the memory location. In this case, the desktop provider module must implement this handle in all methods in IReplStore that accept an HREPLITEM handle, such as CopyObject or FreeObject. When the service manager calls IReplStore::GetConflictInfo, the handle becomes CONFINFO::hRemoteItem. The desktop provider module then can extract descriptive text from the handle and save it into CONFINFO.

The Conflict Resolution dialog box enables the user to:

In either case, the service manager calls IReplObjHandler::DeleteObject to delete the temporary object.

Conflict situations do not always require a Conflict Resolution dialog box. The following table describes special error values from IReplStore::GetConflictInfo that resolve the conflict automatically.

Error value
Action
RERR_IGNOR The desktop provider module compares two handles in CONFINFO, determines that they are identical, and takes no action.
RERR_DISCARD The service manager detects that the desktop object represented by a handle is already deleted and deletes the device object accordingly.
RERR_DISCARD_LOCAL The service manager resolves a conflict by deleting a desktop object instead of allowing the desktop provider module to delete the object.