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;
}