//#define PLUGIN_NAME "Nullsoft ActiveSync Plug-in" #define PLUGIN_VERSION L"0.25" #include "ASDevice.h" int init(); void quit(); intptr_t MessageProc(int msg, intptr_t param1, intptr_t param2, intptr_t param3); extern PMPDevicePlugin plugin = {PMPHDR_VER,0,init,quit,MessageProc}; static HANDLE killEvent=0, hThread=0; static DWORD WINAPI ThreadFunc(LPVOID lpParam); IRAPIDesktop *pIRapiDesktop = NULL; // wasabi based services for localisation support api_language *WASABI_API_LNG = 0; HINSTANCE WASABI_API_LNG_HINST = 0, WASABI_API_ORIG_HINST = 0; std::vector devices; std::vector ejected; static RAPIDEVICEID lastDevId; class MyRAPISink : public IRAPISink { public: virtual HRESULT STDMETHODCALLTYPE OnDeviceConnected(IRAPIDevice *pIDevice) { RAPI_DEVICEINFO devInfo; if(!SUCCEEDED(pIDevice->GetDeviceInfo(&devInfo))) return S_OK; SysFreeString(devInfo.bstrName); SysFreeString(devInfo.bstrPlatform); EnterCriticalSection(&cs); lastDevId = devInfo.DeviceId; for(unsigned int i=0; iid) { ejected[i]->marked=true; LeaveCriticalSection(&cs); return S_OK; } } for(unsigned int i=0; idevInfo.DeviceId || devices[i]->pIDevice == pIDevice) { LeaveCriticalSection(&cs); return S_OK; } } IRAPISession *pISession = NULL; if (SUCCEEDED(pIDevice->CreateSession(&pISession))) { if (SUCCEEDED(pISession->CeRapiInit())) devices.push_back(new ASDevice(pIDevice,pISession)); else pISession->Release(); } LeaveCriticalSection(&cs); return S_OK; } virtual HRESULT STDMETHODCALLTYPE OnDeviceDisconnected(IRAPIDevice *pIDevice) { EnterCriticalSection(&cs); RAPI_DEVICEINFO devInfo; if(!SUCCEEDED(pIDevice->GetDeviceInfo(&devInfo))) return S_OK; for(unsigned int i=0; idevInfo.DeviceId || devices[i]->pIDevice == pIDevice) { SendMessage(plugin.hwndPortablesParent,WM_PMP_IPC,(intptr_t)devices[i],PMP_IPC_DEVICEDISCONNECTED); delete devices[i]; } } SysFreeString(devInfo.bstrName); SysFreeString(devInfo.bstrPlatform); LeaveCriticalSection(&cs); return S_OK; } DWORD RAPISinkContext; CRITICAL_SECTION cs; ULONG refs; MyRAPISink() {refs=1; InitializeCriticalSection(&cs);} ~MyRAPISink() { DeleteCriticalSection(&cs); } #define IMPLEMENTS(ifc) if (riid == IID_ ## ifc) { ++refs; *ppvObject = static_cast(this); return S_OK; } virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid,void __RPC_FAR *__RPC_FAR *ppvObject) { IMPLEMENTS(IRAPISink); IMPLEMENTS(IUnknown); *ppvObject = NULL; return E_NOINTERFACE; } virtual ULONG STDMETHODCALLTYPE AddRef() { return ++refs; } virtual ULONG STDMETHODCALLTYPE Release() { int x = --refs; if(!x) delete this; return x; } #undef IMPLEMENTS }; MyRAPISink *pMyRapiSink=NULL; int init() { CoInitializeEx(NULL, COINIT_MULTITHREADED); HRESULT hr = CoCreateInstance(CLSID_RAPI,NULL,CLSCTX_INPROC_SERVER,IID_IRAPIDesktop,(void**)&pIRapiDesktop); if(!SUCCEEDED(hr) || !pIRapiDesktop) return -1; // no activesync on this computer! // loader so that we can get the localisation service api for use waServiceFactory *sf = plugin.service->service_getServiceByGuid(languageApiGUID); if (sf) WASABI_API_LNG = reinterpret_cast(sf->getInterface()); // need to have this initialised before we try to do anything with localisation features WASABI_API_START_LANG(plugin.hDllInstance,PmpACTIVESYNCLangGUID); static wchar_t szDescription[256]; swprintf(szDescription, ARRAYSIZE(szDescription), WASABI_API_LNGSTRINGW(IDS_NULLSOFT_ACTIVESYNC_PLUGIN), PLUGIN_VERSION); plugin.description = szDescription; killEvent = CreateEvent(NULL,TRUE,FALSE,NULL); DWORD dwThreadId; hThread = CreateThread(NULL, 0, ThreadFunc, NULL, 0, &dwThreadId); return 0; } static void enumDevices() { // find all the currently connected devices IRAPIEnumDevices* pIRapiEnumDevices = NULL; HRESULT hr = pIRapiDesktop->EnumDevices(&pIRapiEnumDevices); for (unsigned int i = 0; i < ejected.size(); i++) ejected[i]->marked = false; while (SUCCEEDED(hr) && pIRapiEnumDevices) { IRAPIDevice* pIRapiDevice = NULL; hr = pIRapiEnumDevices->Next(&pIRapiDevice); if (SUCCEEDED(hr) && pIRapiDevice) { pMyRapiSink->OnDeviceConnected(pIRapiDevice); pIRapiDevice->Release(); } else { pIRapiEnumDevices->Release(); pIRapiEnumDevices = NULL; } } //for (unsigned int i = 0; i < ejected.size(); i++) //{ // if (!ejected[i]->marked) // { // free(ejected[i]); // ejected.eraseindex(i); // } //} auto it = ejected.begin(); while (it != ejected.end()) { ejectedDevice* dev = *it; if (!dev->marked) { free(dev); it = ejected.erase(it); } else { it++; } } } static void init2() { // set up device connection/disconnection notifications pMyRapiSink = new MyRAPISink(); pIRapiDesktop->Advise(pMyRapiSink,(DWORD_PTR*)&pMyRapiSink->RAPISinkContext); // find currently attached devices enumDevices(); } void quit() { SetEvent(killEvent); if (hThread) { for(;;) { int val = WaitForSingleObjectEx(hThread,15000,TRUE); if(val == WAIT_OBJECT_0) { CloseHandle(hThread); break; } else if(val == WAIT_TIMEOUT) { TerminateThread(hThread, 0); break; } else continue; } } CloseHandle(killEvent); pIRapiDesktop->UnAdvise(pMyRapiSink->RAPISinkContext); pIRapiDesktop->Release(); pMyRapiSink->Release(); CoUninitialize(); for(unsigned int i=0; i 0) devices[i]->Close(); return PMP_PLUGIN_UNINSTALL_NOW; } };