windows-nt/Source/XPSP1/NT/shell/services/hdsrv/apsample/main.cpp
2020-09-26 16:20:57 +08:00

611 lines
16 KiB
C++

#include <windows.h>
#include <windowsx.h>
#include <commctrl.h>
#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<IClassFactory *>(this);
AddRef();
hr = S_OK;
}
else if (riid == IID_IClassFactory)
{
*ppv = static_cast<IClassFactory *>(this);
AddRef();
hr = S_OK;
}
else if (riid == IID_IHWEventHandler)
{
*ppv = static_cast<IHWEventHandler *>(this);
AddRef();
hr = S_OK;
}
else if (riid == IID_IQueryCancelAutoPlay)
{
*ppv = static_cast<IQueryCancelAutoPlay *>(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<IClassFactory *>(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<IClassFactory *>(this), pmoniker, &_dwRegisterROT)))
{
_PrintMsg(TEXT("Registered to Cancel Autoplay!"));
}
prot->Release();
}
pmoniker->Release();
}
/* CoRegisterClassObject(CLSID_App, static_cast<IClassFactory *>(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;
}