Accessing Folders
A version of this page is also available for
4/8/2010
The service manager requires the HREPLFLD handle to access a folder. This handle contains the conversion 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 HREPLITEM or HREPLFLD data to the service manager's persistent file, you must also implement IReplStore::ObjectToBytes and IReplStore::BytesToObject.
The following code example shows how to implement IReplStore::GetFolderInfo.
STDMETHODIMP CStore::GetFolderInfo
(
LPSTR lpszName, // name of object type taken from registry
HREPLFLD *phFolder, // pointer to handle of the new folder
IUnknown **ppObjHandler // pointer to pointer to IReplObjHandler interface
)
{
// Check if phFolder points to a NULL-valued handle.
CFolder *pFolder = (CFolder*)*phFolder;
BOOL fNew = (pFolder == NULL);
// Create a new handle for the specific folder.
if (fNew)
pFolder = new CFolder;
// When fNew is FALSE reinitialize the class.
// When fNew is TRUE set up the new CFolder class.
// ...
*phFolder = (HREPLFLD)pFolder;
*ppObjHandler = m_pObjHandler;
return NOERROR;
}
To determine if any object in a folder has changed, the service manager calls IReplStore::IsFolderChanged. The service manager can also call the following methods to manipulate folder or item handles.
- IReplStore::CopyObject copies the data from one handle to another handle that represents the same object.
- IReplStore::IsValidObject verifies the handle still represents a valid object, not a deleted object.
- IReplStore::FreeObject removes a handle from memory, allowing the desktop provider to free the handle's memory resources.
The following code examples show how to implement 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 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 item. If item not found, return.
// HRESULT_FROM_WIN32 (ERROR_FILE_NOT_FOUND)
// ...
}
return NOERROR;
}
STDMETHODIMP_(void) CStore::FreeObject
(
HREPLOBJ hObject // handle of object whose contents need to be freed
)
{
delete (CReplObject*) hObject;
}
The desktop provider must implement IReplStore::ObjectToBytes to convert an HREPLITEM object or HREPLFLD object into a byte sequence so the service manager can store the data in the service manager's persistent file. The desktop provider must also implement IReplStore::BytesToObject to convert the same byte sequence back to an object.
When a user connects a Windows Mobile device to a desktop, the service manager reads the persistent file and restores all handles that were used in the previous synchronization.
The following code examples show how to implement IReplStore::ObjectToBytes and IReplStore::BytesToObject.
STDMETHODIMP_(UINT) CStore::ObjectToBytes
(
HREPLOBJ hObject, // handle to object
LPBYTE lpb // The engine calls ObjectToBytes first with lpb
// set to NULL. The provider should return the
// count of bytes needed. The engine then
// allocates that much space and calls the method
// again with lpb pointing to the allocated data.)
{
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:
break;
case OT_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, // Pointer to buffer where byte array
// should be stored; can be NULL.
UINT cb // buffer size
)
{
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:
pObject = pFolder = new CFolder;
break;
case OT_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;
}