Accessing Folders

For the service manager to access a folder, you must implement HREPLFLD, which is a handle that identifies a folder. This handle contains the filter for the object type and other object-specific information.

The service manager calls IReplStore::GetFolderInfo to obtain the folder handle. The service manager also calls IReplStore::IsFolderChanged, IReplStore::CopyObject, IReplStore::IsValidObject, and IReplStore::FreeObject to manipulate folder and item handles.

Because the service manager saves the data that is stored in the HREPLITEM or HREPLFLD handles to Repl.dat, which is a file that the service manager creates and maintains, you must also implement IReplStore::ObjectToBytes and IReplStore::ObjectToBytes.

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

STDMETHODIMP CStore::GetFolderInfo
(
    LPSTR lpszName,            // Name of the object type taken from 
                            // the registry
    HREPLFLD *phFolder,        // Output pointers to the handle of the 
                            // new folder 
    IUnknown **ppObjHandler    // Output pointers to the pointer of 
                            // the IReplObjHandler interface
)
{
    // Check if phFolder points to a handle that has NULL value.
    CFolder *pFolder = (CFolder *)*phFolder;
    BOOL fNew = (pFolder == NULL);

    // Create a new handle for the specific folder.
    if ( fNew )
        pFolder = new CFolder;

    // Either set up the new CFolder class (when fNew is TRUE) or 
    // reinitialize the class (when fNew is FALSE).
    // ...


    *phFolder = (HREPLFLD)pFolder;
    *ppObjHandler = m_pObjHandler;

    return NOERROR;
}

To determine if any object contained in a folder has changed, the service manager calls IReplStore::IsFolderChanged. The service manager also can call the following methods to manipulate folder or item handles:

The following code examples show how to implement each of these methods.

STDMETHODIMP_(BOOL) CStore::CopyObject
(
    HREPLOBJ    hObjSrc,    // Handle to the source object
    HREPLOBJ    hObjDst     // Handle to the destination object
)
{
    CReplObject *pObjSrc = (CReplObject *)hObjSrc;
    CReplObject *pObjDst = (CReplObject *)hObjDst;

    // Check to see if the source and destination types are the same.
    if ( pObjSrc->m_uType != pObjDst->m_uType )
        return FALSE;

    switch( pObjSrc->m_uType )
    {
    case OT_ITEM:            // If the source object is an item
        ((CItem *)pObjDst)->m_uid = ((CItem *)pObjSrc)->m_uid;
        ((CItem *)pObjDst)->m_ftModified = 
                            ((CItem *)pObjSrc)->m_ftModified;
        break;

    case OT_FOLDER:            // If the source object is a folder
        break;
    }
    return TRUE;
}

STDMETHODIMP CStore::IsValidObject
( 
    HREPLFLD hFolder,    // Handle of the folder where this 
                        // item belongs.
    HREPLITEM hItem,        // Handle of the object; could be NULL.
    UINT uFlags            // Reserved; must be 0.
)
{
    CFolder *pFolder = (CFolder *)hFolder;
    CItem   *pItem = (CItem *)hItem;

    if ( pFolder )
    {
        // Check whether hFolder is a valid folder handle.
        if ( pFolder->m_uType != OT_FOLDER )
            return HRESULT_FROM_WIN32( ERROR_INVALID_HANDLE );
    }

    if ( pItem )
    {
        // Check whether hItem is a valid item handle.
        if ( pFolder->m_uType != OT_ITEM )
            return HRESULT_FROM_WIN32( ERROR_INVALID_HANDLE );

         // Search for the item. If the item is not found, return 
        // to HRESULT_FROM_WIN32( ERROR_FILE_NOT_FOUND ).
        // ...
    }

    return NOERROR;
}

STDMETHODIMP_(void) CStore::FreeObject
(
    HREPLOBJ        hObject        // Handle of the object whose contents 
                            // need to be freed.
)
{
    delete (CReplObject *)hObject;
}

The service manager saves the data stored in the HREPLITEM or HREPLFLD handles to Repl.dat. The desktop provider module must implement IReplStore::ObjectToBytes to convert an HREPLITEM object or HREPLFLD object into a series of bytes so that the service manager can save the data. The desktop provider module also must implement IReplStore::BytesToObject to convert the same series of bytes back to an object.

When a user connects a device to a desktop, the service manager reads Repl.dat and restores all handles that were used in the previous synchronization. As long as a device is connected, the service manager continues to save handles into Repl.dat.

The following code examples show how to implement IReplStore::ObjectToBytes and IReplStore::BytesToObject.

STDMETHODIMP_(UINT) CStore::ObjectToBytes
(
    HREPLOBJ    hObject,        // Handle to the object.
    LPBYTE      lpb           // Points to a buffer where the array of 
                            // bytes should be stored; could be NULL.
)
{
    LPBYTE      lpbStart = lpb;
    CReplObject *pObject = (CReplObject *)hObject;
    CFolder     *pFolder = (CFolder *)pObject;
    CItem       *pItem = (CItem *)pObject;

    if ( lpbStart )
        *lpb = OBJECT_VERSION;
    lpb++;

    if ( lpbStart )
        *(PUINT)lpb = pObject->m_uType;
    lpb += sizeof( pObject->m_uType );

    switch( pObject->m_uType )
    {
    case OT_FOLDER:            // If the object is a folder
        break;

    case OT_ITEM:            // If the object is an item
        if ( lpbStart )
            *(PUINT)lpb = pItem->m_uid;
        lpb += sizeof( pItem->m_uid );

        if ( lpbStart )
            *(FILETIME *)lpb = pItem->m_ftModified;
        lpb += sizeof( pItem->m_ftModified );
        break;
    }
    return lpb - lpbStart;
}

STDMETHODIMP_(HREPLOBJ) CStore::BytesToObject
(
    LPBYTE  lpb,        // Points to a buffer where the array of bytes 
                        // should be stored; could be NULL.
    UINT    cb          // The size of the buffer.
)
{
     CReplObject *pObject = NULL;
    CFolder *pFolder;
    CItem *pItem;

    BYTE bVersion = *lpb++;
    UINT uType = *(PUINT)lpb;

    lpb += sizeof( uType );

    if ( bVersion != OBJECT_VERSION )
    {
        // Convert the data based on bVersion.
    }

    switch( uType )
    {
    case OT_FOLDER:        // If the object is a folder
        pObject = pFolder = new CFolder;
        break;

    case OT_ITEM:        // If the object is an item
        pObject = pItem = new CItem;

        pItem->m_uid = *(PUINT)lpb;
        lpb += sizeof( pItem->m_uid );

        pItem->m_ftModified = *(FILETIME *)lpb;
        lpb += sizeof( pItem->m_ftModified );

        break;
    }

    return (HREPLOBJ)pObject;
}