http://www.developer.com/ws/pc/article.php/3527946/Understanding-Mobile-Data-Synchronization-Utilizing-MS-ActiveSync-Capabilities-at-a-High-Level.htm
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: As you see, there are three logical functional groups: 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:
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: This is actually all the story about CeUtil. Use it wisely, and leave it in peace for now. If all you need is to launch some application when a PDA is connected or disconnected, this is really a piece-of-cake task. ActiveSync uses two keys in the Registry to keep a list of all programs to run upon the above events: So, to execute your own application, simply add a value as in the following sample: In this sample, notepad.exe will be called when the PDA connects successfully, either through its cradle or remotely. In your real environment, you then may recognize such a device by its ID and handle it somehow specifically. For more complicated cases, you have another opportunity—connection notifications. Windows helps you here and implements IDccMan, one of two interfaces responsible for this task. You in turn have to implement one of additional interfaces, IDccManSink or IDccManSink2. They are identical, but IDccManSink2 also supports the IPv6 protocol. Take a look at the usual working flow. It is really simple: Now let's take a closer look at IDccManSink declarations: You will find a short description of above methods in the following table: Now we can code our IDccManSink implementation. I left it pretty simple just to shape the idea. Full source you will find in article's sample project. Here I want to place only main loop: Our implementation of IDccManSink interface simply fakes a regular COM object. If you need to develop separate component which will be used by other applications, then you will have to add all standard COM stuff like ClassFactory and so forth. The sample's output is presented in Figure 1: As you see, the connection manager informs your application about various phases of connection process. If you are going to use IP-based communications, you have PDA's address handy. Moreover, if WinCE device is connected via a cradle, the IP will indicate "localhost;" in other words, 127.0.0.1, so you will always know how device is connected. This article has discussed simple yet useful techniques of managing a connectivity between Windows CE device and a desktop computer. I still haven't touched data synchronization itself, but anyway even now your application can use; for example, RAPI or WinSock to pass data back and forth. I'll describe more complicated data exchange and synchronization methods in coming articles. Download the accompanying code's zip file here Alex Gusev started to play with mainframes at the end of the 1980s, using Pascal and REXX, but soon switched to C/C++ and Java on different platforms. When mobile PDAs seriously rose their heads in the IT market, Alex did it too. Now, he works at an international retail software company as a team leader of the Mobile R department, making programmers' lives in the mobile jungles a little bit simpler.
Understanding Mobile Data Synchronization: Utilizing MS ActiveSync Capabilities at a High Level
August 17, 2005
Windows CE Services
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);
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
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 );
Getting Your Application AutoStarted
HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindows CE Services
AutoStartOnConnect
HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindows CE Services
AutoStartOnDisconnect
; Here, put the full path to your app, possibly with a command
; line to designate that it was launched on a device connection
[HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindows CE Services
AutoStartOnConnect]
YourCompanyApp=notepad.exe
Using Notifications to Control the Device's Connection
DECLARE_INTERFACE_ (IDccManSink, IUnknown)
{
STDMETHOD(OnLogIpAddr) (THIS_ DWORD dwIpAddr) PURE;
STDMETHOD(OnLogTerminated) (THIS) PURE;
STDMETHOD(OnLogActive) (THIS) PURE;
STDMETHOD(OnLogInactive) (THIS) PURE;
STDMETHOD(OnLogAnswered) (THIS) PURE;
STDMETHOD(OnLogListen) (THIS) PURE;
STDMETHOD(OnLogDisconnection) (THIS) PURE;
STDMETHOD(OnLogError) (THIS) PURE;
};
DECLARE_INTERFACE_ (IDccManSink2, IDccManSink)
{
STDMETHOD(OnLogIpAddrEx) (THIS_ const SOCKADDR_STORAGE*
pIpAddr) PURE;
};
Method
Description OnLogListen
Indicates that the connection manager listens for incoming connections OnLogTerminated
Indicates that the connection manager has been shut down OnLogAnswered
Indicates that the connection manager has detected the communications interface OnLogActive
Indicates that a connection is established and fully operational OnLogInactive
Indicates a disconnection, or disconnected state OnLogDisconnection
Indicates that the connection manager has terminated the connection. It may be sent several seconds after actual disconnection OnLogError
Indicates that the connection manager failed to start communications OnLogIpAddr
Indicates that an IP address has been established for communications OnLogIpAddrEx
Indicates that an IP address has been established for communications, IDccManSink2 only
CoInitialize(0);
IDccMan *pIDccMan = NULL;
HRESULT hr = CoCreateInstance(CLSID_DccMan,NULL,CLSCTX_SERVER,
IID_IDccMan,(void**)&pIDccMan);
if ( SUCCEEDED(hr) )
{
CDevComDccSync DccSync;
DWORD dwContext = 0;
pIDccMan->Advise(&DccSync,&dwContext);
SetConsoleTitle("Developer.com IDccManSink Sample");
while (!kbhit());
pIDccMan->Unadvise(dwContext);
pIDccMan->Release();
}
else
{
cout << "Failed to create IDccMan object: " << std::hex
<< hr << std::dec << endl;
}
CoUninitialize();

Conclusion
Download
About the Author