Understanding Mobile Data Synchronization: Utilizing MS ActiveSync Capabilities at a High Level
Windows CE Services
As you probably very well aware, a whole bunch of data synchronization methods and techniques are bound around one common basis: Windows CE Services. This term combines ActiveSync custom service providers, file filters, connection notifications, and the CeUtil API. An upcoming article will be dedicated to the last two topics. ActiveSync service provider's development will be described later. Most of the discussed topics below are related to the desktop side only.
So, you can start with CeUtil. This DLL exports about a dozen functions that allow you to manage ActiveSync's Registry values. Obviously enough, you can do the same job using regular RegXXX calls. A benefit you get with CeUtil API is that it provides an abstract layer over ActiveSync registry settings, so you don't need to bother with their exact names, which in turn may vary a bit between different OS versions and localizations. Thus far, here is what you can use:
HRESULT __stdcall CeSvcOpen( UINT uSvc, LPTSTR pszPath, BOOL fCreate, PHCESVC phSvc ); HRESULT __stdcall CeSvcOpenEx( HCESVC hSvcRoot, LPTSTR pszPath, BOOL fCreate, PHCESVC phSvc ); HRESULT __stdcall CeSvcClose( HCESVC hSvc ); HRESULT __stdcall CeSvcGetString( HCESVC hSvc, LPCTSTR pszValName, LPTSTR pszVal, DWORD cbVal ); HRESULT __stdcall CeSvcSetString( HCESVC hSvc, LPCTSTR pszValName, LPCTSTR pszVal ); HRESULT __stdcall CeSvcGetDword( HCESVC hSvc, LPCTSTR pszValName, LPDWORD pdwVal ); HRESULT __stdcall CeSvcSetDword( HCESVC hSvc, LPCTSTR pszValName, DWORD dwVal ); HRESULT __stdcall CeSvcGetBinary( HCESVC hSvc, LPCTSTR pszValName, LPBYTE pszVal, LPDWORD pcbVal ); HRESULT __stdcall CeSvcSetBinary( HCESVC hSvc, LPCTSTR pszValName, LPBYTE pszVal, DWORD cbVal ); HRESULT __stdcall CeSvcDeleteVal( HCESVC hSvc, LPCTSTR pszValName ); DEVICEID __stdcall CeGetDeviceId( void ); DEVICEID __stdcall CeGetSelectedDeviceId( void ); HRESULT __stdcall CeSvcEnumProfiles(PHCESVC phSvc, DWORD lProfileIndex, PDWORD plProfile);
- To access Registry keys
- To manipulate values
- To obtain device info
CeUtil offers you a lot of predefined keys touching different aspects of ActiveSync programming. You will find an excerpt from the SDK help in the following table. But prior to this, let me highlight the following point. CeUtil Registry keys are mirrored at several locations. There is "MACHINE_ROOT":
HKEY_LOCAL_MACHINESoftwareMicrosoftWindows CE Services—Used to address settings in general;
There is also "LOCAL_ROOT":
HKEY_CURRENT_USERSoftwareMicrosoftWindows CE Services—Addresses specific device configuration.
So, you have some freedom to configure Windows CE Services at different levels. Having said this all, here is a table:
Registry Key | CEUTIL Constants | Description |
---|---|---|
MACHINE_ROOT | CESVC_ROOT_MACHINE | Windows CE Services root hierarchy under HKEY_LOCAL_MACHINE |
MACHINE_ROOTFilters | CESVC_FILTERS | The Filters Registry root. New filters should register themselves here |
MACHINE_ROOTCustomMenus | CESVC_CUSTOM_MENUS | Custom menus Registry root |
MACHINE_ROOTServices | CESVC_SERVICES_COMMON | Services Registry root |
MACHINE_ROOTServices Synchronization | CESVC_SYNC_COMMON | Synchronization Registry root. New sync services should register here |
LOCAL_ROOT | CESVC_ROOT_USER | Windows CE Services root hierarchy under HKEY_CURRENT_USER |
LOCAL_ROOTPartners | CESVC_DEVICES | Individual device subkeys are created under this key |
LOCAL_ROOTPartners<device id> | CESVC_DEVICEX | Particular device root subkey |
LOCAL_ROOTPartners<selected device id> | CESVC_DEVICE_SELECTED | Root subkey for the currently selected device |
LOCAL_ROOTPartners<device id>Services | CESVC_SERVICES_USER | Root Services subkey for a particular device |
LOCAL_ROOTPartners<device id>ServicesSynchronization | CESVC_SYNC | Synchronization reg root for a particular device |
Thus far, you're getting access to desired Registry key by calling CeSvcOpen. A deeper hierarchy is achieved by subsequent CeSvcOpenEx calls. By playing with their parameters, you can control key access and creation policy.
I will skip a second group of functions dealing with key values themselves due to their simplicity and move forward to a device-related one. It isn't complicated in usage but nevertheless may be pretty helpfull. A code snippet below shows just one simple case of it:
HCESVC hSvc; DWORD dwProfile = 0; DWORD dwProfileInx = 0; TCHAR szDevName[255] = { 0 } , szDevType[255] = { 0 }; HRESULT hr = S_OK; HCESVC hDevice; do { hr = CeSvcEnumProfiles(&hSvc,dwProfileInx,&dwProfile); if ( hr == ERROR_NO_MORE_ITEMS ) break; if ( hr != S_OK ) { // handle an error as needed break; } if ( S_OK == CeSvcOpen(CESVC_DEVICEX, (LPTSTR)dwProfile, FALSE, &hDevice) ) { CeSvcGetString(hDevice,_T("DisplayName"),szDevName, sizeof(szDevName)/sizeof(TCHAR)); CeSvcGetString(hDevice,_T("DeviceType"),szDevType, sizeof(szDevType)/sizeof(TCHAR)); // do whatever you want with this info CeSvcClose(hDevice); } dwProfileInx++; } while ( hr == S_OK );
This is actually all the story about CeUtil. Use it wisely, and leave it in peace for now.
Page 1 of 2