September 1, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

Developing ActiveSync Service Providers: Desktop Part Implementation

  • October 10, 2005
  • By Alex Gusev
  • Send Email »
  • More Articles »

What You Already Know

Here, you have reached a point where all your last coding will result in some viewable outcome. In the previous article, you covered the device part of ActiveSync Service Provider implementation. Now, you are ready to conquer its desktop components.

Desktop stuff requires much more effort and coding to get it working. As usual, you have to implement fully functional COM components to interface with MS ActiveSync. Partially, you saw it in previous article, but here you will add some new stuff. The following sections will guide you through all required stages.

Due to the fact that your ASP DLL will be loaded by ActiveSync, debugging may be a bit painful because you will need to restart ActiveSync every time you have new version of the DLL.

MS ActiveSync Data Storage

As noted earlier, MS ActiveSync has no idea about what your data is. It uses a generic approach to access and manipulate such data via HREPLFLDR and HREPLITEM pointers. ActiveSync places all such data to one single file named repl.dat for each device.

Usually, you will have many items and few folders, so you have to keep in mind not to break some rational limits of the information you define for each item or folder. Here is a typical implementation:

class CBaseFolder;
//
// ================== class CReplObject =========================
//
class CReplObject
{
public:
   enum IDD_OBJ_TYPE{ ASPSIMPLE_OBJ_FOLDER = 1,
                      ASPSIMPLE_OBJ_ITEM = 2 };
protected:
   IDD_OBJ_TYPE m_eType;    // type of this object folder/item
public:
   CReplObject(IDD_OBJ_TYPE eType) { m_eType = eType;}
   IDD_OBJ_TYPE GetType(){ return m_eType;}
   virtual ~CReplObject(){};
};
//
// ================== class CReplFolder ==========================
//
class CReplFolder: public CReplObject
{
protected:
   TCHAR m_szName[_MAX_PATH];
   CBaseFolder *m_pFolder;
public:
   CReplFolder(LPTSTR pszName, CBaseFolder *pFolder) :
      CReplObject(ASPSIMPLE_OBJ_FOLDER)
   {
      ::_tcscpy(m_szName, pszName);
      m_pFolder = pFolder;    // stores ptr to real folder
      return;
   }
   virtual ~CReplFolder(){}
   const LPTSTR GetName(){ return m_szName;}
   CBaseFolder* GetFolder(){ return m_pFolder;}
   CReplFolder& operator=(const CReplFolder& rhs)    // overloaded
                                                     // operator=
   {
      //
      // TODO: If you add/modify the members of this class,
      // you will also need to modify the code below.
      //
      ::_tcscpy(m_szName, rhs.m_szName);
      m_pFolder = rhs.m_pFolder;
      return *this;
   }
};
//
// ================== class CReplItem ===========================
//
class CReplItem: public CReplObject
{
protected:
   TCHAR       m_szId[_MAX_PATH];    // unique id to identify
                                     // this object
   FILETIME    m_ftModified;         // stores the last modified
                                     // time of this item
public:
   CReplItem(LPTSTR pszId) : CReplObject(ASPSIMPLE_OBJ_ITEM)
   {
      ::_tcscpy(m_szId, pszId);
      return;
   }
   virtual ~CReplItem(){}
   FILETIME& GetModified(){ return m_ftModified;}
   void SetModified(FILETIME& ft){ m_ftModified = ft;}
   CReplItem& operator=(const CReplItem&rhs)    // overloaded
                                                // operator=
   {
      //
      // TODO: If you add/modify the members of this class,
      // you will also need to modify the code below.
      //
      ::_tcscpy(m_szId, rhs.m_szId);
      m_ftModified = rhs.m_ftModified;
      return *this;
   }
   //
   // Compare function compares this object with another one
   //of the same type. Returns -1, 0 or 1 accordingly.
   //
   int Compare(const CReplItem* prhs)
   {
      return ::_tcscmp(m_szId, prhs->m_szId);
   }
   const LPTSTR GetId()
   {
      return m_szId;
   }
};

Folders are usually characterized by their names, whereas Items have a modification time stamp.

IReplStore Implementation

The IReplStore interface allows ActiveSync to obtain relevant info and manipulate all synchronized entities such as stores, folders, and items. Let me place your sample implementation's declaration here, categorized by functionality:

class CBaseFolder;
class CASPSimpleStore: public IReplStore
{
protected:
   long m_cRef;
   BOOL m_fInitialized;
   IReplNotify *m_pNotify;
   CBaseFolder *m_pFolders[ASPSIMPLE_NUM_FOLDERS];
private:
   static const LPTSTR m_pszCLSID;
   static const LPTSTR m_pszProgId;
   static const LPTSTR m_pszDesc;
public:
   static const LPTSTR GetCLSID(){ return m_pszCLSID;}
   static const LPTSTR GetProgId(){ return m_pszProgId;}
   static const LPTSTR GetDesc(){ return m_pszDesc;}
private:
   ~CASPSimpleStore();
public:
   CASPSimpleStore();
   CBaseFolder* GetFolderByName(LPTSTR szName);
   //========= IUnknown methods ==========//
   STDMETHODIMP         QueryInterface(const IID& iid,
                                       void **ppvObject);
   STDMETHODIMP_(ULONG) AddRef(void);
   STDMETHODIMP_(ULONG) Release(void);
   //========= IReplStore methods ==========//
   STDMETHODIMP        Initialize(IReplNotify *, UINT uFlags);
   STDMETHODIMP        GetStoreInfo(PSTOREINFO pStoreInfo);
   STDMETHODIMP        ReportStatus(HREPLFLD hFolder,
                                    HREPLITEM hItem,
                                    UINT uStatus,
                                    UINT uReserved);
   STDMETHODIMP_(int)  CompareStoreIDs(LPBYTE lpbID1, UINT cbID1,
                                       LPBYTE lpbID2, UINT cbID2);
   // ============ Object related routines ===========//
   STDMETHODIMP_(int)  CompareItem(HREPLITEM hItem1,
                                   HREPLITEM hItem2);
   STDMETHODIMP_(BOOL) IsItemChanged(HREPLFLD hFolder,
                                     HREPLITEM hItem,
                                     HREPLITEM hItemComp);
   STDMETHODIMP_(BOOL) IsItemReplicated(HREPLFLD hFolder,
                                        HREPLITEM hItem);
   STDMETHODIMP_(void) UpdateItem(HREPLFLD hFolder,
                                  HREPLITEM hItemDst,
                                  HREPLITEM hItemSrc);
   // ============ Folder related routines ===========//
   STDMETHODIMP GetFolderInfo(LPSTR lpszName, HREPLFLD *phFolder,
                              IUnknown **ppObjHandler);
   STDMETHODIMP IsFolderChanged(HREPLFLD hFolder, BOOL *pfChanged);
   // ============ Enumeration of folder objects =======//
   STDMETHODIMP FindFirstItem(HREPLFLD hFolder, HREPLITEM *phItem,
                              BOOL *pfExist);
   STDMETHODIMP FindNextItem(HREPLFLD hFolder, HREPLITEM *phItem,
                             BOOL *pfExist);
   STDMETHODIMP FindItemClose(HREPLFLD hFolder);
   // ============ Standard management routines ===========//
   STDMETHODIMP_(UINT)     ObjectToBytes(HREPLOBJ hObject,
                                         LPBYTE lpb);
   STDMETHODIMP_(HREPLOBJ) BytesToObject(LPBYTE lpb, UINT cb);
   STDMETHODIMP_(void)     FreeObject(HREPLOBJ hObject);
   STDMETHODIMP_(BOOL)     CopyObject(HREPLOBJ hObjSrc,
                                      HREPLOBJ hObjDst);
   STDMETHODIMP            IsValidObject(HREPLFLD hFolder,
                                         HREPLITEM hObject,
                                         UINT uFlags);
   // ============ UI related routines ================//
   STDMETHODIMP ActivateDialog(UINT uDlg, HWND hWnd,
                               HREPLFLD hFolder,
                               IEnumReplItem *penum);
   STDMETHODIMP GetObjTypeUIData(HREPLFLD hFolder,
                                 POBJUIDATA pData);
   STDMETHODIMP GetConflictInfo(PCONFINFO pConfInfo);
   STDMETHODIMP RemoveDuplicates(LPSTR lpszObjType, UINT uFlags);
};

Let's discuss some of the above categories (I'll skip the IUnknown part). You will find more details in the accompanying sample project.





Page 1 of 3



Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Sitemap | Contact Us

Rocket Fuel