#include <windows.h>
#include <shobjidl.h>
#include <shlobj.h>
#include <assert.h>
bool CancelRemoveDriverAutoPlay( bool b );
static HRESULT _RegisterForIQueryCancelAutoplay( DWORD* pdwRegisterROT);
static HRESULT _UnregisterForIQueryCancelAutoplay(DWORD dwRegisterROT);
static bool IsWindowsXPOrGreater();
bool CancelRemoveDriverAutoPlay( bool b )
{
if( !IsWindowsXPOrGreater() )
{
return false;
}
static bool s_bAutoPlayCanceled = false;
static DWORD s_dwRot=0;
if( s_bAutoPlayCanceled == b )
{
return true;
}
if( 0 == s_dwRot )
{
if( b )
{
HRESULT hr = _RegisterForIQueryCancelAutoplay(&s_dwRot );
if( SUCCEEDED(hr) )
{
s_bAutoPlayCanceled = true;
return true;
}
else
{
assert(0);
return false;
}
}
else
{
return true;
}
}
else
{
if( b )
{
return true;
}
else
{
HRESULT hr = _UnregisterForIQueryCancelAutoplay( s_dwRot );
if( SUCCEEDED(hr) )
{
s_dwRot = 0;
s_bAutoPlayCanceled = false;
return true;
}
else
{
assert(0);
return false;
}
}
}
}
static bool IsWindowsXPOrGreater()
{
OSVERSIONINFOEXA osvi = {0};
osvi.dwOSVersionInfoSize = sizeof(osvi);
if (!GetVersionExA((OSVERSIONINFOA*)&osvi))
{
// If it failed, it must be a down level platform
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
GetVersionExA((OSVERSIONINFOA*)&osvi);
}
return (VER_PLATFORM_WIN32_NT == osvi.dwPlatformId &&
((osvi.dwMajorVersion > 5) ||
(osvi.dwMajorVersion == 5 && (osvi.dwMinorVersion > 0 ||
(osvi.dwMinorVersion == 0 && LOWORD(osvi.dwBuildNumber) > 2195)))));
}
class CQueryCancelAutoplay : public IQueryCancelAutoPlay
{
public:
// IUnknown interface
STDMETHODIMP QueryInterface(REFIID riid, void** ppv);
STDMETHODIMP_(ULONG) AddRef();
STDMETHODIMP_(ULONG) Release();
// IQueryCancelAutoPlay interface
STDMETHODIMP AllowAutoPlay(LPCWSTR pszPath, DWORD dwContentType,
LPCWSTR pszLabel, DWORD dwSerialNumber);
public:
CQueryCancelAutoplay() : m_cRef(1){}
~CQueryCancelAutoplay(){}
private:
ULONG m_cRef;
};
static HRESULT GetCancelAutoPlayMoniker(IMoniker** ppmoniker)
{
// Create the moniker that we'll put in the ROT
return CreateClassMoniker(CLSID_QueryCancelAutoPlay, ppmoniker);
}
HRESULT _RegisterForIQueryCancelAutoplay( DWORD* pdwRegisterROT)
{
IMoniker* pmoniker =NULL;
HRESULT hr = GetCancelAutoPlayMoniker( &pmoniker);
if (SUCCEEDED(hr))
{
IRunningObjectTable* prot = NULL;
hr = GetRunningObjectTable(0, &prot);
if (SUCCEEDED(hr))
{
CQueryCancelAutoplay* pQCA = new CQueryCancelAutoplay();
if ( NULL != pQCA )
{
IUnknown* punk=NULL;
hr = pQCA->QueryInterface(IID_IUnknown, (void**)&punk);
if (SUCCEEDED(hr))
{
// Register...
hr = prot->Register(ROTFLAGS_REGISTRATIONKEEPSALIVE,
punk, pmoniker, pdwRegisterROT);
punk->Release();
}
pQCA->Release();
}
else
{
hr = E_OUTOFMEMORY;
}
prot->Release();
}
pmoniker->Release();
}
return hr;
}
HRESULT _UnregisterForIQueryCancelAutoplay(DWORD dwRegisterROT)
{
IRunningObjectTable *prot;
if (SUCCEEDED(GetRunningObjectTable(0, &prot)))
{
// Remove our instance from the ROT
prot->Revoke(dwRegisterROT);
prot->Release();
}
return S_OK;
}
STDMETHODIMP CQueryCancelAutoplay::QueryInterface(REFIID riid, void** ppv)
{
IUnknown* punk = NULL;
HRESULT hr = S_OK;
if (IID_IUnknown == riid)
{
punk = static_cast<IUnknown*>(this);
punk->AddRef();
}
else
{
if (IID_IQueryCancelAutoPlay == riid)
{
punk = static_cast<IQueryCancelAutoPlay*>(this);
punk->AddRef();
}
else
{
hr = E_NOINTERFACE;
}
}
*ppv = punk;
return hr;
}
STDMETHODIMP_(ULONG) CQueryCancelAutoplay::AddRef()
{
return ::InterlockedIncrement((LONG*)&m_cRef);
}
STDMETHODIMP_(ULONG) CQueryCancelAutoplay::Release()
{
ULONG cRef = ::InterlockedDecrement((LONG*)&m_cRef);
if (!cRef)
{
delete this;
}
return cRef;
}
STDMETHODIMP CQueryCancelAutoplay::AllowAutoPlay(LPCWSTR pszPath,
DWORD dwContentType, LPCWSTR pszLabel, DWORD dwSerialNumber)
{
HRESULT hr = S_OK;
//do what you want to do
//return S_FALSE to cancel the autoplay
//return S_OK to do autoplay
return hr;
}