You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
626 lines
14 KiB
626 lines
14 KiB
/*******************************************************************************
|
|
*
|
|
* (C) COPYRIGHT MICROSOFT CORP., 2002
|
|
*
|
|
* TITLE: wiascanr.cpp
|
|
*
|
|
* VERSION: 1.1
|
|
*
|
|
* DATE: 05 March, 2002
|
|
*
|
|
* DESCRIPTION:
|
|
* Implementation of the WIA Sample scanner class factory and IUNKNOWN interface.
|
|
*
|
|
*******************************************************************************/
|
|
|
|
#include "pch.h"
|
|
#ifndef INITGUID
|
|
#include <initguid.h>
|
|
#endif
|
|
|
|
#if !defined(dllexp)
|
|
#define DLLEXPORT __declspec( dllexport )
|
|
#endif
|
|
|
|
HINSTANCE g_hInst; // DLL module instance.
|
|
|
|
//
|
|
// This IID_IStiUSD GUID will eventually be in uuid.lib, at which point it should be removed
|
|
// from here.
|
|
//
|
|
|
|
// {0C9BB460-51AC-11D0-90EA-00AA0060F86C}
|
|
DEFINE_GUID(IID_IStiUSD, 0x0C9BB460L, 0x51AC, 0x11D0, 0x90, 0xEA, 0x00, 0xAA, 0x00, 0x60, 0xF8, 0x6C);
|
|
|
|
// {98B3790C-0D93-4f22-ADAF-51A45B33C998}
|
|
DEFINE_GUID(CLSID_SampleWIAScannerDevice,0x98b3790c, 0xd93, 0x4f22, 0xad, 0xaf, 0x51, 0xa4, 0x5b, 0x33, 0xc9, 0x98);
|
|
|
|
/***************************************************************************\
|
|
*
|
|
* CWIADeviceClassFactory
|
|
*
|
|
\****************************************************************************/
|
|
|
|
class CWIADeviceClassFactory : public IClassFactory {
|
|
private:
|
|
ULONG m_cRef;
|
|
public:
|
|
STDMETHODIMP QueryInterface(REFIID riid, LPVOID *ppv);
|
|
STDMETHODIMP_(ULONG) AddRef(void);
|
|
STDMETHODIMP_(ULONG) Release(void);
|
|
STDMETHODIMP CreateInstance(IUnknown __RPC_FAR *pUnkOuter,REFIID riid,void __RPC_FAR *__RPC_FAR *ppvObject);
|
|
STDMETHODIMP LockServer(BOOL fLock);
|
|
CWIADeviceClassFactory();
|
|
~CWIADeviceClassFactory();
|
|
};
|
|
|
|
/**************************************************************************\
|
|
* CWIADeviceClassFactory::CWIADeviceClassFactory(void)
|
|
*
|
|
*
|
|
*
|
|
* Arguments:
|
|
*
|
|
* None
|
|
*
|
|
* Return Value:
|
|
*
|
|
* None
|
|
*
|
|
* History:
|
|
*
|
|
* 03/05/2002 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
CWIADeviceClassFactory::CWIADeviceClassFactory(void)
|
|
{
|
|
m_cRef = 0;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* CWIADeviceClassFactory::~CWIADeviceClassFactory(void)
|
|
*
|
|
*
|
|
*
|
|
* Arguments:
|
|
*
|
|
* None
|
|
*
|
|
* Return Value:
|
|
*
|
|
* None
|
|
*
|
|
* History:
|
|
*
|
|
* 03/05/2002 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
CWIADeviceClassFactory::~CWIADeviceClassFactory(void)
|
|
{
|
|
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* CWIADeviceClassFactory::QueryInterface
|
|
*
|
|
*
|
|
*
|
|
* Arguments:
|
|
*
|
|
* riid -
|
|
* ppvObject -
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status.
|
|
*
|
|
* History:
|
|
*
|
|
* 03/05/2002 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
STDMETHODIMP CWIADeviceClassFactory::QueryInterface(
|
|
REFIID riid,
|
|
void __RPC_FAR *__RPC_FAR *ppvObject)
|
|
{
|
|
if (!ppvObject) {
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
*ppvObject = NULL;
|
|
|
|
if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IClassFactory)) {
|
|
*ppvObject = (LPVOID)this;
|
|
AddRef();
|
|
return NOERROR;
|
|
}
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* CWIADeviceClassFactory::AddRef
|
|
*
|
|
*
|
|
*
|
|
* Arguments:
|
|
*
|
|
* None
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status.
|
|
*
|
|
* History:
|
|
*
|
|
* 03/05/2002 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
STDMETHODIMP_(ULONG) CWIADeviceClassFactory::AddRef(void)
|
|
{
|
|
return InterlockedIncrement((LPLONG)&m_cRef);
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* CWIADeviceClassFactory::Release
|
|
*
|
|
*
|
|
*
|
|
* Arguments:
|
|
*
|
|
* None
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status.
|
|
*
|
|
* History:
|
|
*
|
|
* 03/05/2002 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
STDMETHODIMP_(ULONG) CWIADeviceClassFactory::Release(void)
|
|
{
|
|
ULONG ulRef = 0;
|
|
ulRef = InterlockedDecrement((LPLONG)&m_cRef);
|
|
|
|
if (!ulRef) {
|
|
delete this;
|
|
}
|
|
return ulRef;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* CWIADeviceClassFactory::CreateInstance
|
|
*
|
|
*
|
|
*
|
|
* Arguments:
|
|
*
|
|
* punkOuter -
|
|
* riid, -
|
|
* ppvObject -
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status.
|
|
*
|
|
* History:
|
|
*
|
|
* 03/05/2002 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
STDMETHODIMP CWIADeviceClassFactory::CreateInstance(
|
|
IUnknown __RPC_FAR *punkOuter,
|
|
REFIID riid,
|
|
void __RPC_FAR *__RPC_FAR *ppvObject)
|
|
{
|
|
|
|
//
|
|
// If the caller is not requesting IID_IUnknown or IID_IStiUsd then
|
|
// return E_NOINTERFACE, letting the caller know that interface
|
|
// is not supported by this COM component.
|
|
//
|
|
|
|
if ((!IsEqualIID(riid, IID_IStiUSD)) && (!IsEqualIID(riid, IID_IUnknown))) {
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
//
|
|
// If the caller is creating for aggregation, only IID_IUnknown can be requested.
|
|
//
|
|
|
|
if ((punkOuter) && (!IsEqualIID(riid, IID_IUnknown))) {
|
|
return CLASS_E_NOAGGREGATION;
|
|
}
|
|
|
|
//
|
|
// allocate the CWIAScannerDevce object. This is the WIA minidriver object which
|
|
// supports the WIA interfaces. If allocation fails for this object, return an
|
|
// E_OUTOFMEMORY error to the caller.
|
|
//
|
|
|
|
CWIADevice *pDev = NULL;
|
|
pDev = new CWIADevice(punkOuter);
|
|
if (!pDev) {
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
//
|
|
// If the allocation is successful, call PrivateInitialize(). This function handles
|
|
// all internal initializing of the WIA minidriver object. The implementation of this
|
|
// function can be found in wiascanr.cpp. If PrivateInitialize fails, then the WIA
|
|
// minidriver object must be destroyed and the entire CreateInstance() muct fail.
|
|
//
|
|
|
|
HRESULT hr = pDev->PrivateInitialize();
|
|
if (S_OK != hr) {
|
|
delete pDev;
|
|
pDev = NULL;
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Call the NonDelegating interface methods to handle nonaggregated requests.
|
|
// Do not do this if we are aggregated or the private IUknown interface will be lost.
|
|
//
|
|
|
|
hr = pDev->NonDelegatingQueryInterface(riid,ppvObject);
|
|
pDev->NonDelegatingRelease();
|
|
|
|
return hr;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* CWIADeviceClassFactory::LockServer
|
|
*
|
|
*
|
|
*
|
|
* Arguments:
|
|
*
|
|
* None
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status.
|
|
*
|
|
* History:
|
|
*
|
|
* 03/05/2002 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
STDMETHODIMP CWIADeviceClassFactory::LockServer(BOOL fLock)
|
|
{
|
|
if (fLock) {
|
|
|
|
//
|
|
// The class factory is being locked
|
|
//
|
|
|
|
} else {
|
|
|
|
//
|
|
// The class factory is being unlocked
|
|
//
|
|
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* CWIADevice::NonDelegatingQueryInterface
|
|
*
|
|
*
|
|
*
|
|
* Arguments:
|
|
*
|
|
* None
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status.
|
|
*
|
|
* History:
|
|
*
|
|
* 03/05/2002 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
STDMETHODIMP CWIADevice::NonDelegatingQueryInterface(
|
|
REFIID riid,
|
|
LPVOID *ppvObj)
|
|
{
|
|
if (!ppvObj) {
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
*ppvObj = NULL;
|
|
|
|
//
|
|
// If the caller is asking for any interfaces supported by this WIA
|
|
// minidriver, IID_IUnknown, IID_IStiUSD, or IID_WiaMiniDrv statis_cast
|
|
// the "this" pointer to the requested interface.
|
|
//
|
|
|
|
if (IsEqualIID( riid, IID_IUnknown )) {
|
|
*ppvObj = static_cast<INonDelegatingUnknown*>(this);
|
|
} else if (IsEqualIID( riid, IID_IStiUSD )) {
|
|
*ppvObj = static_cast<IStiUSD*>(this);
|
|
} else if (IsEqualIID( riid, IID_IWiaMiniDrv )) {
|
|
*ppvObj = static_cast<IWiaMiniDrv*>(this);
|
|
} else {
|
|
return STIERR_NOINTERFACE;
|
|
}
|
|
|
|
(reinterpret_cast<IUnknown*>(*ppvObj))->AddRef();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* CWIADevice::NonDelegatingAddRef
|
|
*
|
|
*
|
|
*
|
|
* Arguments:
|
|
*
|
|
* None
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Object reference count.
|
|
*
|
|
* History:
|
|
*
|
|
* 03/05/2002 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
STDMETHODIMP_(ULONG) CWIADevice::NonDelegatingAddRef(void)
|
|
{
|
|
return InterlockedIncrement((LPLONG)&m_cRef);
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* CWIADevice::NonDelegatingRelease
|
|
*
|
|
*
|
|
*
|
|
* Arguments:
|
|
*
|
|
* None
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Object reference count.
|
|
*
|
|
* History:
|
|
*
|
|
* 03/05/2002 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
STDMETHODIMP_(ULONG) CWIADevice::NonDelegatingRelease(void)
|
|
{
|
|
ULONG ulRef = InterlockedDecrement((LPLONG)&m_cRef);
|
|
if (!ulRef) {
|
|
delete this;
|
|
}
|
|
return ulRef;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* CWIADevice::QueryInterface
|
|
*
|
|
*
|
|
*
|
|
* Arguments:
|
|
*
|
|
* None
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status.
|
|
*
|
|
* History:
|
|
*
|
|
* 03/05/2002 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
STDMETHODIMP CWIADevice::QueryInterface(REFIID riid, LPVOID* ppvObj)
|
|
{
|
|
if(!m_punkOuter){
|
|
return E_NOINTERFACE;
|
|
}
|
|
return m_punkOuter->QueryInterface(riid,ppvObj);
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* CWIADevice::AddRef
|
|
*
|
|
*
|
|
*
|
|
* Arguments:
|
|
*
|
|
* None
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status.
|
|
*
|
|
* History:
|
|
*
|
|
* 03/05/2002 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
STDMETHODIMP_(ULONG) CWIADevice::AddRef(void)
|
|
{
|
|
if(!m_punkOuter){
|
|
return 0;
|
|
}
|
|
return m_punkOuter->AddRef();
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* CWIADevice::Release
|
|
*
|
|
*
|
|
*
|
|
* Arguments:
|
|
*
|
|
* None
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status.
|
|
*
|
|
* History:
|
|
*
|
|
* 03/05/2002 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
STDMETHODIMP_(ULONG) CWIADevice::Release(void)
|
|
{
|
|
if(!m_punkOuter){
|
|
return 0;
|
|
}
|
|
return m_punkOuter->Release();
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* DllEntryPoint
|
|
*
|
|
* Main library entry point. Receives DLL event notification from OS.
|
|
*
|
|
* We are not interested in thread attaches and detaches,
|
|
* so we disable thread notifications for performance reasons.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* hinst -
|
|
* dwReason -
|
|
* lpReserved -
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Returns TRUE to allow the DLL to load.
|
|
*
|
|
* History:
|
|
*
|
|
* 03/05/2002 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
|
|
extern "C" DLLEXPORT BOOL APIENTRY DllEntryPoint(
|
|
HINSTANCE hinst,
|
|
DWORD dwReason,
|
|
LPVOID lpReserved)
|
|
{
|
|
switch (dwReason) {
|
|
case DLL_PROCESS_ATTACH:
|
|
g_hInst = hinst;
|
|
DisableThreadLibraryCalls(hinst);
|
|
break;
|
|
case DLL_PROCESS_DETACH:
|
|
break;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* DllCanUnloadNow
|
|
*
|
|
* Determines whether the DLL has any outstanding interfaces.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* None
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Returns S_OK if the DLL can unload, S_FALSE if it is not safe to unload.
|
|
*
|
|
* History:
|
|
*
|
|
* 03/05/2002 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
extern "C" STDMETHODIMP DllCanUnloadNow(void)
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* DllGetClassObject
|
|
*
|
|
* Retrieves the class object from a DLL object handler or object
|
|
* application.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* rclsid - The object being requested.
|
|
* riid - The desired interface on the object.
|
|
* ppv - Output pointer to object.
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status.
|
|
*
|
|
* History:
|
|
*
|
|
* 03/05/2002 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
extern "C" STDAPI DllGetClassObject(
|
|
REFCLSID rclsid,
|
|
REFIID riid,
|
|
LPVOID *ppv)
|
|
{
|
|
if (!ppv) {
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
//
|
|
// If the caller is not requesting the proper WIA minidriver class
|
|
// then fail the call with CLASS_E_CLASSNOTAVAILABLE.
|
|
//
|
|
|
|
if (!IsEqualCLSID(rclsid, CLSID_SampleWIAScannerDevice) ) {
|
|
return CLASS_E_CLASSNOTAVAILABLE;
|
|
}
|
|
|
|
//
|
|
// If the caller is not requesting IID_IUnknown or IID_IClassFactory
|
|
// then fail the call with E_NOINTERFACE;
|
|
//
|
|
|
|
if ((!IsEqualIID(riid, IID_IUnknown)) && (!IsEqualIID(riid, IID_IClassFactory))) {
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
//
|
|
// Allocate the WIA minidriver class factory that belongs to the WIA minidriver
|
|
// COM object.
|
|
//
|
|
|
|
if (IsEqualCLSID(rclsid, CLSID_SampleWIAScannerDevice)) {
|
|
CWIADeviceClassFactory *pcf = new CWIADeviceClassFactory;
|
|
if (!pcf) {
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
*ppv = (LPVOID)pcf;
|
|
}
|
|
return S_OK;
|
|
}
|