summaryrefslogtreecommitdiff
path: root/wia/ProdScan/Server.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'wia/ProdScan/Server.cpp')
-rw-r--r--wia/ProdScan/Server.cpp476
1 files changed, 476 insertions, 0 deletions
diff --git a/wia/ProdScan/Server.cpp b/wia/ProdScan/Server.cpp
new file mode 100644
index 00000000..95debdf8
--- /dev/null
+++ b/wia/ProdScan/Server.cpp
@@ -0,0 +1,476 @@
+/**************************************************************************
+*
+* Copyright � Microsoft Corporation
+*
+* File Name: Server.cpp
+*
+* Description: Contains various COM server infrastructure implemented by
+* the Production Scanner Driver Sample: INonDelegating and
+* IUnknown implementations, IClassFactory interface declaration
+* and implementation, DLL entry points including DllMain.
+*
+***************************************************************************/
+
+#include "stdafx.h"
+
+extern HINSTANCE g_hInst;
+
+//
+// Production Scanner Driver Sample GUID
+//
+// {EB135F56-B088-4bc7-9733-422F324B3A09}
+//
+DEFINE_GUID(CLSID_ProdScan, 0xeb135f56, 0xb088, 0x4bc7, 0x97, 0x33, 0x42, 0x2f, 0x32, 0x4b, 0x3a, 0x9);
+
+//
+// CWiaDriver::INonDelegating interface implementation
+//
+
+HRESULT CWiaDriver::NonDelegatingQueryInterface(
+ REFIID riid,
+ LPVOID* ppvObj)
+{
+ HRESULT hr = S_OK;
+
+ if (!ppvObj)
+ {
+ hr = E_INVALIDARG;
+ WIAEX_ERROR((g_hInst, "Invalid parameter, hr = 0x%08X", hr));
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ *ppvObj = NULL;
+
+ //
+ // The Production Scanner Driver Sample object exports the standard WIA mini-driver COM interfaces:
+ //
+ // - IUnknown
+ // - IStiUSD
+ // - IWiaMiniDrv
+ //
+ 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
+ {
+ hr = E_NOINTERFACE;
+ WIAEX_ERROR((g_hInst,
+ "Unsupported interface (0x%08X, 0x%04X, 0x%04X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X), hr = 0x%08X",
+ riid.Data1, riid.Data2, riid.Data3, riid.Data4[0], riid.Data4[1], riid.Data4[2], riid.Data4[3],
+ riid.Data4[4], riid.Data4[5], riid.Data4[6], riid.Data4[7], hr));
+ }
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ reinterpret_cast<IUnknown*>(*ppvObj)->AddRef();
+ }
+
+ return hr;
+}
+
+ULONG CWiaDriver::NonDelegatingAddRef()
+{
+ return InterlockedIncrement(&m_cRef);
+}
+
+ULONG CWiaDriver::NonDelegatingRelease()
+{
+ ULONG ulRef = InterlockedDecrement(&m_cRef);
+ if (!ulRef)
+ {
+ WIAS_TRACE((g_hInst, "INonDelegating::NonDelegatingRelease, deleting main driver object (%p, process: %u)..",
+ this, GetCurrentProcessId()));
+ delete this;
+ }
+
+ return ulRef;
+}
+
+//
+// CWiaDriver::IClassFactory interface declaration and implementation
+//
+
+class CWiaDriverClassFactory : public IClassFactory
+{
+public:
+ CWiaDriverClassFactory()
+ : m_cRef(1)
+ {
+ return;
+ }
+
+ ~CWiaDriverClassFactory()
+ {
+ return;
+ }
+
+ HRESULT __stdcall
+ QueryInterface(
+ REFIID riid,
+ _COM_Outptr_ LPVOID* ppv)
+ {
+ HRESULT hr = S_OK;
+
+ if (!ppv)
+ {
+ hr = E_INVALIDARG;
+ WIAEX_ERROR((g_hInst, "Invalid parameter, hr = 0x%08X", hr));
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ *ppv = NULL;
+ if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IClassFactory))
+ {
+ *ppv = static_cast<IClassFactory*>(this);
+ reinterpret_cast<IUnknown*>(*ppv)->AddRef();
+ }
+ else
+ {
+ hr = E_NOINTERFACE;
+ WIAEX_ERROR((g_hInst,
+ "Unsupported interface (0x%08X, 0x%04X, 0x%04X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X), hr = 0x%08X",
+ riid.Data1, riid.Data2, riid.Data3, riid.Data4[0], riid.Data4[1], riid.Data4[2], riid.Data4[3],
+ riid.Data4[4], riid.Data4[5], riid.Data4[6], riid.Data4[7], hr));
+
+ }
+ }
+
+ return hr;
+ }
+
+ ULONG __stdcall
+ AddRef()
+ {
+ return InterlockedIncrement(&m_cRef);
+ }
+
+ ULONG __stdcall
+ Release()
+ {
+ ULONG ulRef = InterlockedDecrement(&m_cRef);
+ if (!ulRef)
+ {
+ WIAS_TRACE((g_hInst, "IClassFactory::Release, deleting driver class factory object.."));
+ delete this;
+ }
+ return ulRef;
+ }
+
+ HRESULT __stdcall
+#pragma prefast(suppress:__WARNING_INVALID_PARAM_VALUE_2, "Set ppvObject to NULL if failed.")
+ CreateInstance(
+ _In_opt_ IUnknown* pUnkOuter,
+ _In_ REFIID riid,
+ _COM_Outptr_ void** ppvObject)
+ {
+ HRESULT hr = S_OK;
+ CWiaDriver *pNewDriverObject = NULL;
+
+ WIAEX_TRACE_BEGIN;
+
+ if (!ppvObject)
+ {
+ hr = E_INVALIDARG;
+ WIAEX_ERROR((g_hInst, "Invalid parameter, hr = 0x%08X", hr));
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ *ppvObject = NULL;
+
+ if ((pUnkOuter) && (!IsEqualIID(riid, IID_IUnknown)))
+ {
+ hr = CLASS_E_NOAGGREGATION;
+ WIAEX_ERROR((g_hInst,
+ "NULL outer IUnknown* and not requesting IID_IUnknown, hr = 0x%08X (CLASS_E_NOAGGREGATION)", hr));
+ }
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ #pragma prefast(suppress:__WARNING_ALIASED_MEMORY_LEAK, "The main driver object instance is freed when the driver is unloaded")
+ pNewDriverObject = new CWiaDriver(pUnkOuter);
+ if (pNewDriverObject)
+ {
+ hr = pNewDriverObject->NonDelegatingQueryInterface(riid, ppvObject);
+ pNewDriverObject->NonDelegatingRelease();
+
+ if (SUCCEEDED(hr))
+ {
+ WIAS_TRACE((g_hInst, "IClassFactory::CreateInstance, created main driver object (%p, process: %u)",
+ pNewDriverObject, GetCurrentProcessId()));
+ }
+ }
+ else
+ {
+ hr = E_OUTOFMEMORY;
+ WIAEX_ERROR((g_hInst, "Failed to allocate WIA driver class object, hr = 0x%08X", hr));
+ }
+ }
+
+ WIAEX_TRACE_FUNC_HR;
+
+ return hr;
+ }
+
+ HRESULT __stdcall
+ LockServer(
+ BOOL fLock)
+ {
+ UNREFERENCED_PARAMETER(fLock);
+ return S_OK;
+ }
+
+private:
+ LONG m_cRef;
+};
+
+//
+// IUnknown implementation for CWiaDriver:
+//
+
+HRESULT CWiaDriver::QueryInterface(
+ REFIID riid,
+ _COM_Outptr_ LPVOID *ppvObj)
+{
+ HRESULT hr = S_OK;
+
+ if (!ppvObj)
+ {
+ hr = E_INVALIDARG;
+ WIAEX_ERROR((g_hInst, "Invalid parameter, hr = 0x%08X", hr));
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ *ppvObj = NULL;
+
+ if (!m_punkOuter)
+ {
+ hr = E_NOINTERFACE;
+ WIAEX_ERROR((g_hInst, "NULL outer IUnknown*, hr = 0x%08X", hr));
+ }
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ hr = m_punkOuter->QueryInterface(riid, ppvObj);
+ }
+
+ return hr;
+}
+
+ULONG CWiaDriver::AddRef()
+{
+ ULONG ulRef = 0;
+
+ if (!m_punkOuter)
+ {
+ WIAEX_ERROR((g_hInst, "NULL outer IUnknown*, returning 0"));
+ }
+ else
+ {
+ ulRef = m_punkOuter->AddRef();
+ }
+
+ return ulRef;
+}
+
+ULONG CWiaDriver::Release()
+{
+ ULONG ulRef = 0;
+
+ if (!m_punkOuter)
+ {
+ WIAEX_ERROR((g_hInst, "NULL outer IUnknown*, returning 0"));
+ }
+ else
+ {
+ ulRef = m_punkOuter->Release();
+ }
+
+ return ulRef;
+}
+
+/**************************************************************************\
+* DllMain
+*
+* Main DLL entry point
+*
+* Parameters:
+*
+* hInst - handle to the DLL module
+* dwReason - indicates why the DLL entry-point function is being called
+* lpReserved - if fdwReason is DLL_PROCESS_ATTACH lpvReserved is NULL for
+* dynamic loads and non-NULL for static loads; if fdwReason
+* is DLL_PROCESS_DETACH, lpvReserved is NULL if DllMain has
+* been called by using FreeLibrary and non-NULL if DllMain
+* has been called during process termination.
+*
+* Return Value:
+*
+* When the system calls the DllMain function with the DLL_PROCESS_ATTACH
+* value in this particular case the function returns TRUE every time
+* indicating it succeeds.
+*
+\**************************************************************************/
+
+extern "C" __declspec(dllexport) BOOL APIENTRY DllMain(
+ HINSTANCE hInst,
+ DWORD dwReason,
+ _Reserved_ LPVOID lpReserved)
+{
+ UNREFERENCED_PARAMETER(lpReserved);
+
+ g_hInst = hInst;
+
+ switch(dwReason)
+ {
+ case DLL_PROCESS_ATTACH:
+ DisableThreadLibraryCalls(g_hInst);
+ WIAS_TRACE((g_hInst, "DLL_PROCESS_ATTACH (process: %u, thread: %u)",
+ GetCurrentProcessId(), GetCurrentThreadId()));
+ break;
+
+ case DLL_PROCESS_DETACH:
+ WIAS_TRACE((g_hInst, "DLL_PROCESS_DETACH (process: %u, thread: %u)",
+ GetCurrentProcessId(), GetCurrentThreadId()));
+ break;
+ }
+
+ return TRUE;
+}
+
+/**************************************************************************\
+* DllCanUnloadNow
+*
+* Parameters: none
+*
+* Determines whether the DLL that implements this function is in use.
+* If not, the caller can unload the DLL from memory.
+*
+* Return Value: S_OK (indicating the DLL can be unloaded at any time)
+*
+\**************************************************************************/
+
+extern "C" HRESULT __stdcall DllCanUnloadNow(void)
+{
+ return S_OK;
+}
+
+/**************************************************************************\
+* DllGetClassObject
+*
+* Retrieves the class object from a DLL object handler or object application.
+* DllGetClassObject is called from within the CoGetClassObject function
+* when the class context is a DLL.
+*
+* Parameters:
+*
+* rclsid - CLSID that will associate the correct data and code
+* riid - reference to the identifier of the interface that the caller
+* is to use to communicate with the class object. Usually, this
+* is IID_IClassFactory (the interface identifier for IClassFactory)
+* ppv - [out] address of pointer variable that receives the interface
+* pointer requested in riid; upon successful return, *ppv contains
+* the requested interface pointer; if an error occurs, this is NULL.
+*
+* Return Values:
+*
+* S_OK
+* E_INVALIDARG
+* CLASS_E_CLASSNOTAVAILABLE
+* E_OUTOFMEMORY
+*
+\**************************************************************************/
+
+extern "C" HRESULT __stdcall DllGetClassObject(
+ _In_ REFCLSID rclsid,
+ _In_ REFIID riid,
+ _Outptr_ LPVOID* ppv)
+{
+ HRESULT hr = S_OK;
+ CWiaDriverClassFactory *pNewClassFactory = NULL;
+
+ WIAEX_TRACE_BEGIN;
+
+ if (!ppv)
+ {
+ hr = E_INVALIDARG;
+ WIAEX_ERROR((g_hInst, "Invalid parameters, hr = 0x%08X", hr));
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ *ppv = NULL;
+
+ if (IsEqualCLSID(rclsid, CLSID_ProdScan))
+ {
+ #pragma prefast(suppress:__WARNING_ALIASED_MEMORY_LEAK, "The final CWiaDriverClassFactory::Release frees the memory")
+ pNewClassFactory = new CWiaDriverClassFactory;
+ if (pNewClassFactory)
+ {
+ hr = pNewClassFactory->QueryInterface(riid, ppv);
+ pNewClassFactory->Release();
+ }
+ else
+ {
+ hr = E_OUTOFMEMORY;
+ WIAEX_ERROR((g_hInst, "Failed to allocate WIA driver class factory object, hr = 0x%08X", hr));
+ }
+ }
+ else
+ {
+ hr = CLASS_E_CLASSNOTAVAILABLE;
+ WIAEX_ERROR((g_hInst, "Class not available, hr = 0x%08X (CLASS_E_CLASSNOTAVAILABLE)", hr));
+ }
+ }
+
+ return hr;
+}
+
+/**************************************************************************\
+* DllRegisterServer
+*
+* Instructs an in-process server to create its registry entries for all
+* classes supported in this server module.
+*
+* Parameters: none
+*
+* Return Value: S_OK (registry entries - none - were created successfully)
+*
+\**************************************************************************/
+
+extern "C" HRESULT __stdcall DllRegisterServer()
+{
+ return S_OK;
+}
+
+/**************************************************************************\
+* DllUnregisterServer
+*
+* Instructs an in-process server to remove only those entries created
+* through DllRegisterServer.
+*
+* Parameters: none
+*
+* Return Value: S_OK (registry entries - none - were removed successfully)
+*
+\**************************************************************************/
+
+extern "C" HRESULT __stdcall DllUnregisterServer()
+{
+ return S_OK;
+}