The ActiveSync Manager provides the desktop with two different ways of receiving notifications when a Pocket PC device is either connected or disconnected from it:
Although using the registry to launch an application is the easiest way to handle a connection notification, no other information about the connection event is provided to you. You should create a COM object notification if more details are required. Using the Desktop Registry for Connection NotificationsTo have an application launch when a connection is made with the desktop, you need to create a new string value underneath the following registry entry: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows CE Services\ AutoStartOnConnect It is recommended that the key name for the new string value should uniquely represent the application you are launching, along with the company name. The data value should point to the full path and name, and include any command-line arguments for the application you want to launch. If you include any arguments, you must also wrap the full path in double quotes. For example, to launch the application devicebackup.exe when a connection is established, the registry will look like the following: [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows CE Services\AutoStartOnConnect] "BionicFrogDeviceBackup"="\"C:\\Program Files\\BionicFrog\\devicebackup.exe\"" To have an application launch when a device is disconnected from the desktop, you can place a new registry string value underneath the following key: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows CE Services\ AutoStartOnDisconnect Like the AutoStartOnConnect key, the disconnect registry key also takes a string value with the application path in order to run. COM Desktop NotificationsTwo interfaces are used to perform notification of connection events when using COM:
The interfaces that you will use to work with the notification objects are prototyped in the dccole.h header file. Implementing IDccManSinkThe IDccManSink interface is the only interface that your application needs to implement in order to receive notifications from the ActiveSync Manager. Table 9.27 describes the methods supported by IDccManSink that are called during the various states of a device's connection to the desktop. All of the methods that IDccManSink supports are pretty self-explanatory each is called by IDccMan whenever a particular event takes place. The only method that has any useful additional information is the IDccManSink::OnLogIpAddr(DWORD dwIpAddr) method, which will pass you the connecting device's IP address when a communications link has been established.
The IDccMan ObjectThe IDccMan interface is implemented by the ActiveSync Manager, and enables you to register your own IDccManSink interface to receive notifications from it. Table 9.28 describes the methods that are implemented by the IDccMan object.
To register a new notification object with ActiveSync, you must pass a pointer to the IDccManSink interface that you implemented to the IDccMan::Advise() function. It is defined as follows: HRESULT IDccMan::Advise(IDccManSink *pDccSink, DWORD *pdwContext); The first parameter is a pointer to the notification object that will be used by IDccMan to send notifications to. The pdwContext parameter will be filled in with a DWORD value that uniquely identifies the object you passed into pDccSink. The value that you are returned must be used to call the IDccMan::Unadvise() function when you are finished receiving notifications. You can also tell ActiveSync to display the Communication Configuration dialog box by using the following function: HRESULT IDccMan::ShowCommSettings(); The only other function that IDccMan provides is what you use to let ActiveSync know you are no longer interested in receiving notification. The IDccMan::Unadvise() function takes a single parameter, which is the context value that was returned from your call to IDccMan::Advise(). The function is defined as follows: HRESULT IDccMan::Unadvise(DWORD dwContext); Using COM-Based NotificationsThe process for using COM-based notification is relatively simple. Your application needs to first call CoInitializeEx() and CoCreateInstance() in order to get a pointer to the IDccMan object that ActiveSync has implemented. The code for getting the IDccMan interface pointer is as follows: // Get the IDccMan Interface IDccMan *pDccMan = NULL; HRESULT hr = S_OK; hr = CoCreateInstance(CLSID_DccMan, NULL, CLSCTX_SERVER, IID_IDccMan, (LPVOID *)&pDccMan); if(FAILED(hr)) return 0; Once you have received the pointer, you can call into the IDccMan::Advise() function to register the IDccManSink you have implemented in your application. For example, you can register your object for notification as follows: // Hook up the notification DWORD dwContext = 0; hr = pDccMan->Advise(pDccManSink, &dwContext); Once the application is ready to stop receiving notifications, remember to call the IDccMan::UnAdvise() function, as well as clean up the other COM objects you used: // Clean up if(pDccMan) { pDccMan->Unadvise(dwContext); pDccMan->Release(); } The implementation for a basic IDccManSink interface is shown in the following example code: // CeNotify.h #include <windows.h> #include <initguid.h> #include <dccole.h> #include "resource.h" INT_PTR CALLBACK DlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); // IDccManSink class CDccSink:public IDccManSink { private: long m_lRef; public: CDccSink(); ~CDccSink(); // IUnknown STDMETHODIMP QueryInterface(REFIID riid, LPVOID *ppv); STDMETHODIMP_(ULONG) AddRef(); STDMETHODIMP_(ULONG) Release(); // IDccManSink STDMETHODIMP OnLogIpAddr(DWORD dwIpAddr); STDMETHODIMP OnLogTerminated(); STDMETHODIMP OnLogActive(); STDMETHODIMP OnLogInactive(); STDMETHODIMP OnLogAnswered(); STDMETHODIMP OnLogListen(); STDMETHODIMP OnLogDisconnection(); STDMETHODIMP OnLogError(); }; ///////////////////////////////////////////////// // CeNotify.cpp #include "cenotify.h" int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) { // Initalize COM CoInitialize(NULL); // Get the IDccMan interface IDccMan *pDccMan = NULL; HRESULT hr = S_OK; hr = CoCreateInstance(CLSID_DccMan, NULL, CLSCTX_SERVER, IID_IDccMan, (LPVOID *)&pDccMan); if(FAILED(hr)) return 0; // Get an instance of our IDccManSink CDccSink *pDccSink = new CDccSink(); IDccManSink *pDccManSink = NULL; hr = pDccSink->QueryInterface(IID_IDccManSink, (void **)&pDccManSink); if(FAILED(hr)) { pDccMan->Release(); return 0; } // Hook up the notification DWORD dwContext = 0; hr = pDccMan->Advise(pDccManSink, &dwContext); // Do something while getting notifications DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG), NULL, (DLGPROC)DlgProc); // Clean up if(pDccMan) { pDccMan->Unadvise(dwContext); pDccMan->Release(); } return 0; } INT_PTR CALLBACK DlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_COMMAND: switch (LOWORD(wParam)) { case IDOK: case IDCANCEL: EndDialog(hwndDlg, wParam); return TRUE; } } return FALSE; } // DccSink object CDccSink::CDccSink() { m_lRef = 1; return; } CDccSink::~CDccSink() { return; } // IDccManSink's IUnknown interface STDMETHODIMP CDccSink::QueryInterface(REFIID riid, LPVOID *ppv) { if(IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IDccManSink)) { *ppv = (IDccManSink *)this; AddRef(); return NO_ERROR; } *ppv = NULL; return E_NOINTERFACE; } STDMETHODIMP_(ULONG) CDccSink::AddRef() { return (ULONG)InterlockedIncrement(&m_lRef); } STDMETHODIMP_(ULONG) CDccSink::Release() { ULONG ulCount = (ULONG)InterlockedDecrement(&m_lRef); if(ulCount == 0) delete this; return ulCount; } // IDccManSink implementation STDMETHODIMP CDccSink::OnLogIpAddr(DWORD dwIpAddr) { OutputDebugString(TEXT("Received a new IP Address\r\n")); return NO_ERROR; } STDMETHODIMP CDccSink::OnLogTerminated() { OutputDebugString(TEXT("On Log Terminated\r\n")); return NO_ERROR; } STDMETHODIMP CDccSink::OnLogActive() { OutputDebugString(TEXT("On Log Active\r\n")); return NO_ERROR; } STDMETHODIMP CDccSink::OnLogInactive() { OutputDebugString(TEXT("On Log InActive\r\n")); return NO_ERROR; } STDMETHODIMP CDccSink::OnLogAnswered() { OutputDebugString(TEXT("On Log Answered\r\n")); return NO_ERROR; } STDMETHODIMP CDccSink::OnLogListen() { OutputDebugString(TEXT("On Log Listen\r\n")); return NO_ERROR; } STDMETHODIMP CDccSink::OnLogDisconnection() { OutputDebugString(TEXT("On Log Disconnection\r\n")); return NO_ERROR; } STDMETHODIMP CDccSink::OnLogError() { OutputDebugString(TEXT("On Log Error\r\n")); return NO_ERROR; |