#include #include #include #include "resource.h" #include "shpriv.h" #define ARRAYSIZE(a) (sizeof(a)/sizeof(a[0])) HINSTANCE g_hinst = 0; // {4456E541-7CAB-45ee-AB09-3FF379FA9AA4} static const CLSID CLSID_App = { 0x4456e541, 0x7cab, 0x45ee, { 0xab, 0x9, 0x3f, 0xf3, 0x79, 0xfa, 0x9a, 0xa4}}; #define INVALID_DWORD ((DWORD)-1) class CAppDialog : public IClassFactory, public IHWEventHandler, public IQueryCancelAutoPlay { public: CAppDialog(); HRESULT DoModal(HWND hwnd); // IUnknown STDMETHODIMP QueryInterface(REFIID riid, void **ppvObj); STDMETHODIMP_(ULONG) AddRef(void); STDMETHODIMP_(ULONG) Release(void); // IClassFactory STDMETHODIMP CreateInstance(IUnknown *punkOuter, REFIID riid, void **ppv); STDMETHODIMP LockServer(BOOL fLock); // IHWEventHandler STDMETHODIMP Initialize(LPCWSTR pszParams); STDMETHODIMP HandleEvent(LPCWSTR pszDeviceID, LPCWSTR pszAltDeviceID, LPCWSTR pszEventType); STDMETHODIMP HandleEventWithContent(LPCWSTR pszDeviceID, LPCWSTR pszAltDeviceID, LPCWSTR pszEventType, LPCWSTR pszContentTypeHandler, IDataObject* pdataobject); // IQueryCancelAutoPlay STDMETHODIMP AllowAutoPlay(LPCWSTR pszPath, DWORD dwContentType, LPCWSTR pszLabel, DWORD dwSerialNumber); private: ~CAppDialog(); static INT_PTR CALLBACK s_DlgProc(HWND hdlg, UINT uMsg, WPARAM wParam, LPARAM lParam); INT_PTR CALLBACK DlgProc(UINT uMsg, WPARAM wParam, LPARAM lParam); void _OnInitDlg(); void _OnDestroyDlg(); LRESULT _OnQueryCancelAutoplay(WPARAM wParam, LPARAM lParam); void _OnQueryCancelAutoplayWindowsMessageChanged(); void _OnQueryCancelAutoplayIntfChanged(); void _OnAutoplayChanged(); void _PrintMsg(LPCWSTR pszMsg); LONG _cRef; DWORD _dwRegisterClass; DWORD _dwRegisterROT; DWORD _dwRegisterROT2; HWND _hdlg; }; CAppDialog::CAppDialog() : _cRef(1), _dwRegisterClass(INVALID_DWORD), _dwRegisterROT(INVALID_DWORD), _dwRegisterROT2(INVALID_DWORD), _hdlg(NULL)//, _hdlgLV(NULL) { InitCommonControls(); } CAppDialog::~CAppDialog() { } HRESULT CAppDialog::QueryInterface(REFIID riid, void **ppv) { HRESULT hr; if (riid == IID_IUnknown) { *ppv = static_cast(this); AddRef(); hr = S_OK; } else if (riid == IID_IClassFactory) { *ppv = static_cast(this); AddRef(); hr = S_OK; } else if (riid == IID_IHWEventHandler) { *ppv = static_cast(this); AddRef(); hr = S_OK; } else if (riid == IID_IQueryCancelAutoPlay) { *ppv = static_cast(this); AddRef(); hr = S_OK; } else { *ppv = NULL; hr = E_NOINTERFACE; } return hr; } STDMETHODIMP_(ULONG) CAppDialog::AddRef(void) { return InterlockedIncrement(&_cRef); } STDMETHODIMP_(ULONG) CAppDialog::Release() { if (InterlockedDecrement(&_cRef)) return _cRef; delete this; return 0; } STDMETHODIMP CAppDialog::CreateInstance(IUnknown *punkOuter, REFIID riid, void **ppv) { if (punkOuter) { *ppv = NULL; return CLASS_E_NOAGGREGATION; } return QueryInterface(riid, ppv); } STDMETHODIMP CAppDialog::LockServer(BOOL /*fLock*/) { return S_OK; } STDMETHODIMP CAppDialog::Initialize(LPCWSTR /*pszParams*/) { return S_OK; } STDMETHODIMP CAppDialog::HandleEvent(LPCWSTR pszDeviceID, LPCWSTR pszAltDeviceID, LPCWSTR pszEventType) { WCHAR szText[4096]; wsprintf(szText, TEXT("%s, %s, %s"), pszDeviceID, pszAltDeviceID, pszEventType); _PrintMsg(szText); return S_OK; } STDMETHODIMP CAppDialog::HandleEventWithContent(LPCWSTR /*pszDeviceID*/, LPCWSTR /*pszAltDeviceID*/, LPCWSTR /*pszEventType*/, LPCWSTR /*pszContentTypeHandler*/, IDataObject* /*pdataobject*/) { return S_OK; } void CAppDialog::_PrintMsg(LPCWSTR pszMsg) { SendMessage(GetDlgItem(_hdlg, IDC_EDIT1), EM_SETSEL, (WPARAM)-2, (WPARAM)-2); SendMessage(GetDlgItem(_hdlg, IDC_EDIT1), EM_REPLACESEL, 0, (LPARAM)pszMsg); SendMessage(GetDlgItem(_hdlg, IDC_EDIT1), EM_SETSEL, (WPARAM)-2, (WPARAM)-2); SendMessage(GetDlgItem(_hdlg, IDC_EDIT1), EM_REPLACESEL, 0, (LPARAM)TEXT("\r\n")); } DWORD _BuildFilterFlag(HWND hwndDlg, int iResourceBase) { DWORD dwRet = 0; for (int i = 0; i < 5; ++i) { if (BST_CHECKED == Button_GetCheck(GetDlgItem(hwndDlg, iResourceBase + (1 << (i + 1))))) { dwRet |= (1 << (i + 1)); } } return dwRet; } STDMETHODIMP CAppDialog::AllowAutoPlay(LPCWSTR pszPath, DWORD dwContentType, LPCWSTR /*pszLabel*/, DWORD /*dwSerialNumber*/) { HRESULT hr = S_OK; WCHAR szText[4096]; wsprintf(szText, TEXT("IQueryCancelAutoPlay::AllowAutoPlay called for drive '%s' and ContentType (0x%08X)"), pszPath, dwContentType); _PrintMsg(szText); // Are we registered? if (INVALID_DWORD != _dwRegisterROT2) { // Yes WCHAR szDrive[MAX_PATH]; if (GetDlgItemText(_hdlg, IDC_IQCA_EDIT, szDrive, ARRAYSIZE(szDrive))) { // Same drive? if (!lstrcmpi(szDrive, pszPath)) { // Yes DWORD dwFilter = _BuildFilterFlag(_hdlg, 3000); if (dwFilter & dwContentType) { wsprintf(szText, TEXT(" Filter (0x%08X) matches ContentType -> Cancel AutoRun! (S_FALSE)"), dwFilter); hr = S_FALSE; } else { wsprintf(szText, TEXT(" Filter (0x%08X) does *NOT* match ContentType -> No cancel (S_OK)")); } _PrintMsg(szText); } } } return hr; } HRESULT CAppDialog::DoModal(HWND hwnd) { DialogBoxParam(g_hinst, MAKEINTRESOURCE(IDD_DIALOG1), hwnd, s_DlgProc, (LPARAM)this); return S_OK; } typedef HRESULT (*CREATEHARDWAREEVENTMONIKER)(REFCLSID clsid, LPCTSTR pszEventHandler, IMoniker **ppmoniker); void CAppDialog::_OnInitDlg() { SetDlgItemText(_hdlg, IDC_AUTOPLAY_CLSID_EDIT, TEXT("{4456E541-7CAB-45ee-AB09-3FF379FA9AA4}")); } void CAppDialog::_OnDestroyDlg() { if (INVALID_DWORD != _dwRegisterClass) { CoRevokeClassObject(_dwRegisterClass); _dwRegisterClass = INVALID_DWORD; } if (INVALID_DWORD != _dwRegisterROT) { IRunningObjectTable *prot; if (SUCCEEDED(GetRunningObjectTable(0, &prot))) { prot->Revoke(_dwRegisterROT); _dwRegisterROT = INVALID_DWORD; prot->Release(); } } if (INVALID_DWORD != _dwRegisterROT2) { IRunningObjectTable *prot; if (SUCCEEDED(GetRunningObjectTable(0, &prot))) { prot->Revoke(_dwRegisterROT2); _dwRegisterROT2 = INVALID_DWORD; prot->Release(); } } } INT_PTR CALLBACK CAppDialog::s_DlgProc(HWND hdlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { CAppDialog *pcd = (CAppDialog*) GetWindowLongPtr(hdlg, DWLP_USER); if (uMsg == WM_INITDIALOG) { pcd = (CAppDialog *) lParam; pcd->_hdlg = hdlg; SetWindowLongPtr(hdlg, DWLP_USER, (LONG_PTR) pcd); } return pcd ? pcd->DlgProc(uMsg, wParam, lParam) : FALSE; } LRESULT CAppDialog::_OnQueryCancelAutoplay(WPARAM wParam, LPARAM lParam) { LRESULT lRet = 0; WCHAR szText[4096]; wsprintf(szText, TEXT("QueryCancelAutoPlay Windows Message Received for drive '0x%08X' and ContentType (0x%08X)"), wParam, lParam); _PrintMsg(szText); if (BST_CHECKED == Button_GetCheck(GetDlgItem(_hdlg, IDC_QCA_CHECKBOX))) { WCHAR szDrive[MAX_PATH]; if (GetDlgItemText(_hdlg, IDC_QCA_EDIT, szDrive, ARRAYSIZE(szDrive))) { int iDrive = -1; if ((TEXT('a') <= szDrive[0]) && (TEXT('z') >= szDrive[0])) { iDrive = szDrive[0] - TEXT('a'); } else { if ((TEXT('A') <= szDrive[0]) && (TEXT('Z') >= szDrive[0])) { iDrive = szDrive[0] - TEXT('A'); } } if (-1 != iDrive) { if (wParam == (WPARAM)iDrive) { DWORD dwFilter = _BuildFilterFlag(_hdlg, IDC_QCA_CHECKBOX); lRet = (lParam & dwFilter); if (lRet) { wsprintf(szText, TEXT(" Filter (0x%08X) matches ContentType -> Cancel AutoRun! (ret = 0x%08X)"), dwFilter, lRet); } else { wsprintf(szText, TEXT(" Filter (0x%08X) does *NOT* match ContentType -> No cancel (ret = 0x%08X)"), dwFilter, lRet); } } _PrintMsg(szText); } } } return lRet; } typedef HRESULT (*SHCREATEQUERYCANCELAUTOPLAYMONIKER)(IMoniker** ppmoniker); void CAppDialog::_OnQueryCancelAutoplayIntfChanged() { BOOL fEnable = (BST_CHECKED == Button_GetCheck(GetDlgItem(_hdlg, IDC_IQCA_CHECKBOX))); EnableWindow(GetDlgItem(_hdlg, IDC_IQCA_EDIT ), fEnable); EnableWindow(GetDlgItem(_hdlg, IDC_IQCA_AUTORUNINF_CHECKBOX), fEnable); EnableWindow(GetDlgItem(_hdlg, IDC_IQCA_AUDIOCD_CHECKBOX ), fEnable); EnableWindow(GetDlgItem(_hdlg, IDC_IQCA_DVDMOVIE_CHECKBOX ), fEnable); EnableWindow(GetDlgItem(_hdlg, IDC_IQCA_BLANKCD_CHECKBOX ), fEnable); EnableWindow(GetDlgItem(_hdlg, IDC_IQCA_BLANKDVD_CHECKBOX ), fEnable); // Are we registered? if (INVALID_DWORD == _dwRegisterROT2) { // Nope // Do we need to register? if (fEnable) { // Yes HINSTANCE hinstShell32 = LoadLibrary(TEXT("shell32.dll")); if (hinstShell32) { SHCREATEQUERYCANCELAUTOPLAYMONIKER fct = (SHCREATEQUERYCANCELAUTOPLAYMONIKER)GetProcAddress( hinstShell32, "SHCreateQueryCancelAutoPlayMoniker"); if (fct) { IMoniker* pmoniker; HRESULT hr = fct(&pmoniker); if (SUCCEEDED(hr)) { IRunningObjectTable *prot; if (SUCCEEDED(GetRunningObjectTable(0, &prot))) { prot->Register(ROTFLAGS_REGISTRATIONKEEPSALIVE, static_cast(this), pmoniker, &_dwRegisterROT2); _PrintMsg(TEXT("Registered for IQueryCancelAutoplay!")); prot->Release(); } pmoniker->Release(); } } FreeLibrary(hinstShell32); } } } else { // Yes // Do we need to unregister? if (!fEnable) { // Yes IRunningObjectTable *prot; if (SUCCEEDED(GetRunningObjectTable(0, &prot))) { prot->Revoke(_dwRegisterROT2); _PrintMsg(TEXT("Unregistered for IQueryCancelAutoplay!")); _dwRegisterROT2 = INVALID_DWORD; prot->Release(); } } } } void CAppDialog::_OnQueryCancelAutoplayWindowsMessageChanged() { BOOL fEnable = (BST_CHECKED == Button_GetCheck(GetDlgItem(_hdlg, IDC_QCA_CHECKBOX))); EnableWindow(GetDlgItem(_hdlg, IDC_QCA_EDIT ), fEnable); EnableWindow(GetDlgItem(_hdlg, IDC_QCA_AUTORUNINF_CHECKBOX), fEnable); EnableWindow(GetDlgItem(_hdlg, IDC_QCA_AUDIOCD_CHECKBOX ), fEnable); EnableWindow(GetDlgItem(_hdlg, IDC_QCA_DVDMOVIE_CHECKBOX ), fEnable); EnableWindow(GetDlgItem(_hdlg, IDC_QCA_BLANKCD_CHECKBOX ), fEnable); EnableWindow(GetDlgItem(_hdlg, IDC_QCA_BLANKDVD_CHECKBOX ), fEnable); } void CAppDialog::_OnAutoplayChanged() { BOOL fEnable = (BST_CHECKED == Button_GetCheck(GetDlgItem(_hdlg, IDC_AUTOPLAY_CHECKBOX))); BOOL fRegister = (BST_CHECKED == Button_GetCheck(GetDlgItem(_hdlg, IDC_AUTOPLAY_ONOFF_CHECKBOX))); EnableWindow(GetDlgItem(_hdlg, IDC_AUTOPLAY_EVENTHANDLER_EDIT), fEnable); EnableWindow(GetDlgItem(_hdlg, IDC_AUTOPLAY_CLSID_EDIT), fEnable); EnableWindow(GetDlgItem(_hdlg, IDC_AUTOPLAY_ONOFF_CHECKBOX), fEnable); // Are we registered? if (INVALID_DWORD == _dwRegisterROT) { // Nope // Do we need to register? if (fEnable && fRegister) { // Yes HINSTANCE hinstShSvcs = LoadLibrary(TEXT("shsvcs.dll")); if (hinstShSvcs) { CREATEHARDWAREEVENTMONIKER fct = (CREATEHARDWAREEVENTMONIKER)GetProcAddress( hinstShSvcs, "CreateHardwareEventMoniker"); if (fct) { WCHAR szEventHandler[64]; WCHAR szCLSID[39]; IMoniker* pmoniker; if (GetDlgItemText(_hdlg, IDC_AUTOPLAY_EVENTHANDLER_EDIT, szEventHandler, ARRAYSIZE(szEventHandler))) { if (GetDlgItemText(_hdlg, IDC_AUTOPLAY_CLSID_EDIT, szCLSID, ARRAYSIZE(szCLSID))) { CLSID clsid; HRESULT hr = CLSIDFromString(szCLSID, &clsid); if (SUCCEEDED(hr)) { hr = fct(clsid, szEventHandler, &pmoniker); if (SUCCEEDED(hr)) { IRunningObjectTable *prot; if (SUCCEEDED(GetRunningObjectTable(0, &prot))) { if (SUCCEEDED(prot->Register(ROTFLAGS_ALLOWANYCLIENT | ROTFLAGS_REGISTRATIONKEEPSALIVE, static_cast(this), pmoniker, &_dwRegisterROT))) { _PrintMsg(TEXT("Registered to Cancel Autoplay!")); } prot->Release(); } pmoniker->Release(); } /* CoRegisterClassObject(CLSID_App, static_cast(this), CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &_dwRegisterClass);*/ } } } } FreeLibrary(hinstShSvcs); } } } else { // Yes // Do we need to unregister? if (!(fEnable && fRegister)) { // Yes IRunningObjectTable *prot; if (SUCCEEDED(GetRunningObjectTable(0, &prot))) { prot->Revoke(_dwRegisterROT); _PrintMsg(TEXT("Unregistered to Cancel Autoplay!")); _dwRegisterROT = INVALID_DWORD; prot->Release(); } } } } INT_PTR CAppDialog::DlgProc(UINT uMsg, WPARAM wParam, LPARAM lParam) { static UINT uQCA = 0; if (!uQCA) { uQCA = RegisterWindowMessage(TEXT("QueryCancelAutoPlay")); } if (uMsg == uQCA) { INT_PTR iRet= _OnQueryCancelAutoplay(wParam, lParam); SetWindowLongPtr(_hdlg, DWLP_MSGRESULT, iRet); return TRUE; } else { switch (uMsg) { case WM_INITDIALOG: _OnInitDlg(); break; case WM_COMMAND: switch (LOWORD(wParam)) { case IDCANCEL: return EndDialog(_hdlg, TRUE); case IDC_QCA_CHECKBOX: _OnQueryCancelAutoplayWindowsMessageChanged(); return FALSE; case IDC_IQCA_CHECKBOX: _OnQueryCancelAutoplayIntfChanged(); return FALSE; case IDC_AUTOPLAY_CHECKBOX: _OnAutoplayChanged(); return FALSE; case IDC_AUTOPLAY_ONOFF_CHECKBOX: _OnAutoplayChanged(); return FALSE; } break; case WM_DESTROY: _OnDestroyDlg(); break; default: return FALSE; } } return TRUE; } int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPSTR /*lpCmdLine*/, int /*nCmdShow*/) { g_hinst = hInstance; HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); if (SUCCEEDED(hr)) { CAppDialog *pdlg = new CAppDialog(); if (pdlg) { pdlg->DoModal(NULL); pdlg->Release(); } CoUninitialize(); } return 0; }