/***************************************************************************** * * Clsfact.c * * Copyright (c) 1999, 2000 Microsoft Corporation. All Rights Reserved. * * * Abstract: * * Class factory. * *****************************************************************************/ #include "dimapp.h" #include "dimap.h" /***************************************************************************** * * CClassFactory_AddRef * * Optimization: Since the class factory is static, reference * counting can be shunted to the DLL itself. * *****************************************************************************/ STDMETHODIMP_(ULONG) CClassFactory_AddRef(IClassFactory *pcf) { return DllAddRef(); } /***************************************************************************** * * CClassFactory_Release * * Optimization: Since the class factory is static, reference * counting can be shunted to the DLL itself. * *****************************************************************************/ STDMETHODIMP_(ULONG) CClassFactory_Release(IClassFactory *pcf) { return DllRelease(); } /***************************************************************************** * * CClassFactory_QueryInterface * * Our QI is very simple because we support no interfaces beyond * ourselves. * *****************************************************************************/ STDMETHODIMP CClassFactory_QueryInterface(IClassFactory *pcf, REFIID riid, LPVOID *ppvOut) { HRESULT hres; if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IClassFactory)) { CClassFactory_AddRef(pcf); *ppvOut = pcf; hres = S_OK; } else { *ppvOut = 0; hres = E_NOINTERFACE; } return hres; } /***************************************************************************** * * CClassFactory_CreateInstance * * Create the effect driver object itself. * *****************************************************************************/ STDMETHODIMP CClassFactory_CreateInstance(IClassFactory *pcf, IUnknown *punkOuter, REFIID riid, LPVOID *ppvObj) { HRESULT hres; if (punkOuter == 0) { hres = Map_New(riid, ppvObj); } else { /* * We don't support aggregation. */ hres = CLASS_E_NOAGGREGATION; } return hres; } /***************************************************************************** * * CClassFactory_LockServer * *****************************************************************************/ STDMETHODIMP CClassFactory_LockServer(IClassFactory *pcf, BOOL fLock) { if (fLock) { DllAddRef(); } else { DllRelease(); } return S_OK; } /***************************************************************************** * * The VTBL for our Class Factory * *****************************************************************************/ IClassFactoryVtbl CClassFactory_Vtbl = { CClassFactory_QueryInterface, CClassFactory_AddRef, CClassFactory_Release, CClassFactory_CreateInstance, CClassFactory_LockServer, }; /***************************************************************************** * * Our static class factory. * *****************************************************************************/ IClassFactory g_cf = { &CClassFactory_Vtbl }; /***************************************************************************** * * CClassFactory_New * *****************************************************************************/ STDMETHODIMP CClassFactory_New(REFIID riid, LPVOID *ppvOut) { HRESULT hres; /* * Attempt to obtain the desired interface. QueryInterface * will do an AddRef if it succeeds. */ hres = CClassFactory_QueryInterface(&g_cf, riid, ppvOut); return hres; } /*****************************************************************************/ /***************************************************************************** * * Dynamic Globals. There should be as few of these as possible. * * All access to dynamic globals must be thread-safe. * *****************************************************************************/ ULONG g_cRef = 0; /* Global reference count */ CRITICAL_SECTION g_crst; /* Global critical section */ /***************************************************************************** * * DllAddRef / DllRelease * * Adjust the DLL reference count. * *****************************************************************************/ STDAPI_(ULONG) DllAddRef(void) { return (ULONG)InterlockedIncrement((LPLONG)&g_cRef); } STDAPI_(ULONG) DllRelease(void) { return (ULONG)InterlockedDecrement((LPLONG)&g_cRef); } /***************************************************************************** * * DllGetClassObject * * OLE entry point. Produces an IClassFactory for the indicated GUID. * *****************************************************************************/ STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppvObj) { HRESULT hres; if (IsEqualGUID(rclsid, &IID_IDirectInputMapClsFact)) { hres = CClassFactory_New(riid, ppvObj); } else { *ppvObj = 0; hres = CLASS_E_CLASSNOTAVAILABLE; } return hres; } /***************************************************************************** * * DllCanUnloadNow * * OLE entry point. Fail iff there are outstanding refs. * *****************************************************************************/ STDAPI DllCanUnloadNow(void) { return g_cRef ? S_FALSE : S_OK; } /***************************************************************************** * * DllOnProcessAttach * * Initialize the DLL. * *****************************************************************************/ STDAPI_(BOOL) DllOnProcessAttach(HINSTANCE hinst) { /* * Performance tweak: We do not need thread notifications. */ DisableThreadLibraryCalls(hinst); __try { InitializeCriticalSection(&g_crst); return TRUE; } __except( EXCEPTION_EXECUTE_HANDLER ) { return FALSE; // usually out of memory condition } return TRUE; } /***************************************************************************** * * DllOnProcessDetach * * De-initialize the DLL. * *****************************************************************************/ STDAPI_(void) DllOnProcessDetach(void) { DeleteCriticalSection(&g_crst); } /***************************************************************************** * * MapDllEntryPoint * * DLL entry point. * *****************************************************************************/ /*STDAPI_(BOOL) MapDllEntryPoint*/ BOOL APIENTRY DllMain (HINSTANCE hinst, DWORD dwReason, LPVOID lpReserved) { switch (dwReason) { case DLL_PROCESS_ATTACH: return DllOnProcessAttach(hinst); case DLL_PROCESS_DETACH: DllOnProcessDetach(); break; } return 1; }