📄 errhandler.cpp
字号:
/*****************************************************************************
*
* errhandler.cpp
*
* Copyright (c) 2003 Microsoft Corporation. All Rights Reserved.
*
* DESCRIPTION:
*
* CErrHandler is a simple error handler, which works together with
* the wiadriver.
*
*******************************************************************************/
#include "stdafx.h"
#define MYDESCSTRING TEXT("Special driver device status error (only for testing purposes). Press 'Ok' to continue. Hitting 'Cancel' will abort the transfer.")
#define HANDLED_PRIVATE_STATUS_ERROR_1 MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 1001)
// {CFC1A4D4-5F27-4881-81E4-1BE314EB22F7}
static const GUID CLSID_WiaErrorHandler =
{ 0xcfc1a4d4, 0x5f27, 0x4881, { 0x81, 0xe4, 0x1b, 0xe3, 0x14, 0xeb, 0x22, 0xf7 } };
static LONG g_cLocks = 0;
void LockModule(void) { InterlockedIncrement(&g_cLocks); }
void UnlockModule(void) { InterlockedDecrement(&g_cLocks); }
class CErrHandler : public IWiaErrorHandler
{
public:
STDMETHODIMP
QueryInterface(const IID& iid_requested, void** ppInterfaceOut);
STDMETHODIMP_(ULONG)
AddRef(void);
STDMETHODIMP_(ULONG)
Release(void);
STDMETHODIMP
ReportStatus(
IN LONG lFlags,
IN HWND hwndParent,
IN IWiaItem2 *pWiaItem2,
IN HRESULT hrStatus,
IN LONG lPercentComplete);
STDMETHODIMP
GetStatusDescription(
IN LONG lFlags,
IN IWiaItem2 *pWiaItem2,
IN HRESULT hrStatus,
OUT BSTR *pbstrDescription);
private:
LONG m_nRefCount;
};
///
/// QueryInterface
///
STDMETHODIMP
CErrHandler::QueryInterface(const IID& iid_requested, void** ppInterfaceOut)
{
HRESULT hr = S_OK;
hr = ppInterfaceOut ? S_OK : E_POINTER;
if (SUCCEEDED(hr))
{
*ppInterfaceOut = NULL;
}
//
// We support IID_IUnknown and IID_IWiaErrorHandler
//
if (SUCCEEDED(hr))
{
if (IID_IUnknown == iid_requested)
{
*ppInterfaceOut = static_cast<IUnknown*>(this);
}
else if (IID_IWiaErrorHandler == iid_requested)
{
*ppInterfaceOut = static_cast<IWiaErrorHandler*>(this);
}
else
{
hr = E_NOINTERFACE;
}
}
if (SUCCEEDED(hr))
{
reinterpret_cast<IUnknown*>(*ppInterfaceOut)->AddRef();
}
return hr;
}
///
/// AddRef
///
STDMETHODIMP_(ULONG)
CErrHandler::AddRef(void)
{
if (m_nRefCount == 0)
{
LockModule();
}
return InterlockedIncrement(&m_nRefCount);
}
///
/// Release
///
STDMETHODIMP_(ULONG)
CErrHandler::Release(void)
{
ULONG nRetval = InterlockedDecrement(&m_nRefCount);
if (0 == nRetval)
{
delete this;
UnlockModule();
}
return nRetval;
}
/*****************************************************************************
*
* @doc INTERNAL
*
* @func STDMETHODIMP | CErrHandler::ReportStatus | ReportStatus implementation
*
* @parm LONG | lFlags |
* Flags - currently unused.
*
* @parm HWND | hwndParent |
* Window handle provided by the application
*
* @parm IWiaItem2 | pWiaItem2 |
* The item which is currently being transferred
*
* @parm HRESULT | hrStatus |
* Status code
*
* @parm LONG | lPercentComplete
* Percent of operation completed (e.g. warming up device)
*
*
* @comm
* ReportStatus handles HANDLED_PRIVATE_STATUS_ERROR_1 for which it displays a modal
* dialog box which enables a user to cancel the transfer or to continue.
* For all other messages we return WIA_STATUS_NOT_HANDLED
*
* @rvalue S_OK |
* The function successfully handled the device status message.
*
* @rvalue WIA_STATUS_NOT_HANDLED |
* The function does not handle this device status message
*
* @rvalue E_XXX |
* Error
*
*****************************************************************************/
STDMETHODIMP
CErrHandler::ReportStatus(
IN LONG lFlags,
IN HWND hwndParent,
IN IWiaItem2 *pWiaItem2,
IN HRESULT hrStatus,
IN LONG lPercentComplete)
{
HRESULT hr = pWiaItem2 ? WIA_STATUS_NOT_HANDLED : E_INVALIDARG;
if ((WIA_STATUS_NOT_HANDLED == hr) && (HANDLED_PRIVATE_STATUS_ERROR_1 == hrStatus))
{
int i = MessageBox(hwndParent, MYDESCSTRING,TEXT("Driver UI Extension - Handling HANDLED_PRIVATE_STATUS_ERROR_1 message"),MB_OKCANCEL|MB_TASKMODAL|MB_ICONERROR);
if (IDOK == i)
{
hr = S_OK;
}
else
{
hr = HANDLED_PRIVATE_STATUS_ERROR_1;
}
}
return hr;
}
/*****************************************************************************
*
* @doc INTERNAL
*
* @func STDMETHODIMP | CErrHandler::GetStatusDescription | GetStatusDescription implementation
*
* @parm LONG | lFlags |
* Flags - currently unused.
*
* @parm IWiaItem2 | pWiaItem2 |
* The item which is currently being transferred
*
* @parm HRESULT | hrStatus |
* Status code
*
* @parm BSTR* | pbstrDescription |
* On S_OK this pbstrDescription will point to string with status description
*
*
* @comm
* GetStatusDescription handles HANDLED_PRIVATE_STATUS_ERROR_1 for which it returns
* a description string. It returns WIA_STATUS_NOT_HANDLED for all other messages
*
* @rvalue S_OK |
* The function successfully handled the device status message.
*
* @rvalue WIA_STATUS_NOT_HANDLED |
* The function does not handle this device status message
*
* @rvalue E_XXX |
* Error
*
*****************************************************************************/
STDMETHODIMP
CErrHandler::GetStatusDescription(
IN LONG lFlags,
IN IWiaItem2 *pWiaItem2,
IN HRESULT hrStatus,
OUT BSTR *pbstrDescription)
{
HRESULT hr = (pbstrDescription && pWiaItem2) ? WIA_STATUS_NOT_HANDLED : E_INVALIDARG;
if ((WIA_STATUS_NOT_HANDLED == hr) && (HANDLED_PRIVATE_STATUS_ERROR_1 == hrStatus))
{
BSTR bstrDescription = NULL;
bstrDescription = SysAllocString(MYDESCSTRING);
if (bstrDescription)
{
*pbstrDescription = bstrDescription;
hr = S_OK;
}
else
{
hr = E_OUTOFMEMORY;
}
}
return hr;
}
/*****************************************************************************
*
* Class Object
*
*******************************************************************************/
class CErrClassObject : public IClassFactory
{
public:
STDMETHODIMP
QueryInterface(const IID& iid_requested, void** ppInterfaceOut)
{
HRESULT hr = S_OK;
hr = ppInterfaceOut ? S_OK : E_POINTER;
if (SUCCEEDED(hr))
{
*ppInterfaceOut = NULL;
}
//
// We only support IID_IUnknown and IID_IClassFactory
//
if (SUCCEEDED(hr))
{
if (IID_IUnknown == iid_requested)
{
*ppInterfaceOut = static_cast<IUnknown*>(this);
}
else if (IID_IClassFactory == iid_requested)
{
*ppInterfaceOut = static_cast<IClassFactory*>(this);
}
else
{
hr = E_NOINTERFACE;
}
}
if (SUCCEEDED(hr))
{
reinterpret_cast<IUnknown*>(*ppInterfaceOut)->AddRef();
}
return hr;
}
STDMETHODIMP_(ULONG)
AddRef(void)
{
LockModule();
return 2;
}
STDMETHODIMP_(ULONG)
Release(void)
{
UnlockModule();
return 1;
}
STDMETHODIMP
CreateInstance(IUnknown *pUnkOuter,
REFIID riid,
void **ppv)
{
CErrHandler *pErrHandler = NULL;
HRESULT hr;
hr = ppv ? S_OK : E_POINTER;
if (SUCCEEDED(hr))
{
*ppv = 0;
}
if (SUCCEEDED(hr))
{
if (pUnkOuter)
{
hr = CLASS_E_NOAGGREGATION;
}
}
if (SUCCEEDED(hr))
{
pErrHandler = new CErrHandler();
hr = pErrHandler ? S_OK : E_OUTOFMEMORY;
}
if (SUCCEEDED(hr))
{
pErrHandler->AddRef();
hr = pErrHandler->QueryInterface(riid, ppv);
pErrHandler->Release();
}
return hr;
}
STDMETHODIMP
LockServer(BOOL bLock)
{
if (bLock)
{
LockModule();
}
else
{
UnlockModule();
}
return S_OK;
}
};
STDAPI DllCanUnloadNow(void)
{
return (g_cLocks == 0) ? S_OK : S_FALSE;
}
STDAPI DllGetClassObject(REFCLSID rclsid,
REFIID riid,
void **ppv)
{
static CErrClassObject s_FilterClass;
HRESULT hr;
hr = ppv ? S_OK : E_INVALIDARG;
if (SUCCEEDED(hr))
{
if (rclsid == CLSID_WiaErrorHandler)
{
hr = s_FilterClass.QueryInterface(riid, ppv);
}
else
{
*ppv = 0;
hr = CLASS_E_CLASSNOTAVAILABLE;
}
}
return hr;
}
STDAPI DllUnregisterServer()
{
return S_OK;
}
STDAPI DllRegisterServer()
{
return S_OK;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -