// @doc /********************************************************************** * * @module USEWheelEffectDriverEntryPoints.cpp | * * Contains DLL Entry points * * History * ---------------------------------------------------------- * Matthew L. Coill (mlc) Original Jul-7-1999 * * (c) 1999 Microsoft Corporation. All right reserved. * * @topic DLL Entry points | * DllMain - Main Entry Point for DLL (Process/Thread Attach/Detach) * DllCanUnloadNow - Can the DLL be removed from memory * DllGetClassObject - Retreive the Class Factory * DllRegisterServer - Insert keys into the system registry * DLLUnRefisterServer - Remove keys from the system registry * **********************************************************************/ #include #include "IDirectInputEffectDriverClassFactory.h" #include "IDirectInputEffectDriver.h" #include "Registry.h" #include // From objbase.h WINOLEAPI CoInitializeEx(LPVOID pvReserved, DWORD dwCoInit); CIDirectInputEffectDriverClassFactory* g_pClassFactoryObject = NULL; LONG g_lObjectCount = 0; HINSTANCE g_hLocalInstance = NULL; GUID g_guidSystemPIDDriver = { // EEC6993A-B3FD-11D2-A916-00C04FB98638 0xEEC6993A, 0xB3FD, 0x11D2, { 0xA9, 0x16, 0x00, 0xC0, 0x4F, 0xB9, 0x86, 0x38 } }; extern TCHAR CLSID_SWPIDDriver_String[] = TEXT("{db11d351-3bf6-4f2c-a82b-b26cb9676d2b}"); #define DRIVER_OBJECT_NAME TEXT("Microsoft SideWinder PID Filter Object") #define THREADING_MODEL_STRING TEXT("Both") /*********************************************************************************** ** ** BOOL DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) ** ** @func Process/Thread is Attaching/Detaching ** ** @rdesc TRUE always ** *************************************************************************************/ BOOL __stdcall DllMain ( HINSTANCE hInstance, //@parm [IN] Instance of the DLL DWORD dwReason, //@parm [IN] Reason for this call LPVOID lpReserved //@parm [IN] Reserved - Ignored ) { if (dwReason == DLL_PROCESS_ATTACH) { g_hLocalInstance = hInstance; } return TRUE; } /*********************************************************************************** ** ** HRESULT DllCanUnloadNow() ** ** @func Query the DLL for Unloadability ** ** @rdesc If there are any object S_FALSE, else S_OK ** *************************************************************************************/ extern "C" HRESULT __stdcall DllCanUnloadNow() { if (g_lObjectCount > 0) { return S_FALSE; } return S_OK; } /*********************************************************************************** ** ** HRESULT DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv) ** ** @func Retrieve the requested Factory ** ** @rdesc E_INVALIDARG: if (ppv == NULL) ** E_NOMEMORY: if can't create the object ** S_OK: if all is well ** E_NOINTERFACE: if interface is not supported ** *************************************************************************************/ extern "C" HRESULT __stdcall DllGetClassObject ( REFCLSID rclsid, REFIID riid, //@parm [IN] ID of requested interface on retrieved object LPVOID* ppv //@parm [OUT] Address of location for returned interface ) { if (ppv == NULL) { return E_INVALIDARG; } *ppv = NULL; if (g_pClassFactoryObject == NULL) { ::CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); // Need to get the PID Class Factory IClassFactory* pIClassFactory = NULL; HRESULT hrGetPIDFactory = ::CoGetClassObject(g_guidSystemPIDDriver, CLSCTX_INPROC_SERVER, NULL, IID_IClassFactory, (void**)&pIClassFactory); if (FAILED(hrGetPIDFactory) || (pIClassFactory == NULL)) { return hrGetPIDFactory; } g_pClassFactoryObject = new CIDirectInputEffectDriverClassFactory(pIClassFactory); pIClassFactory->Release(); // CIDirectInputEffectDriverClassFactory adds a reference if (g_pClassFactoryObject == NULL) { return E_OUTOFMEMORY; } } else { g_pClassFactoryObject->AddRef(); } HRESULT hrQuery = g_pClassFactoryObject->QueryInterface(riid, ppv); g_pClassFactoryObject->Release(); // Force a release (we start with 1) return hrQuery; } /*********************************************************************************** ** ** HRESULT DllRegisterServer() ** ** @func ** ** @rdesc ** *************************************************************************************/ HRESULT __stdcall DllRegisterServer() { RegistryKey classesRootKey(HKEY_CLASSES_ROOT); RegistryKey clsidKey = classesRootKey.OpenSubkey(TEXT("CLSID"), KEY_READ | KEY_WRITE); if (clsidKey == c_InvalidKey) { return E_UNEXPECTED; // No CLSID key???? } // -- If the key is there get it (else Create) RegistryKey driverKey = clsidKey.OpenCreateSubkey(CLSID_SWPIDDriver_String); // -- Set value (if valid key) if (driverKey != c_InvalidKey) { driverKey.SetValue(NULL, (BYTE*)DRIVER_OBJECT_NAME, sizeof(DRIVER_OBJECT_NAME)/sizeof(TCHAR), REG_SZ); RegistryKey inproc32Key = driverKey.OpenCreateSubkey(TEXT("InProcServer32")); if (inproc32Key != c_InvalidKey) { TCHAR rgtcFileName[MAX_PATH]; DWORD dwNameSize = ::GetModuleFileName(g_hLocalInstance, rgtcFileName, MAX_PATH); if (dwNameSize > 0) { rgtcFileName[dwNameSize] = '\0'; inproc32Key.SetValue(NULL, (BYTE*)rgtcFileName, sizeof(rgtcFileName)/sizeof(TCHAR), REG_SZ); } inproc32Key.SetValue(TEXT("ThreadingModel"), (BYTE*)THREADING_MODEL_STRING, sizeof(THREADING_MODEL_STRING)/sizeof(TCHAR), REG_SZ); } } return S_OK; } /*********************************************************************************** ** ** HRESULT DllUnregisterServer() ** ** @func ** ** @rdesc ** *************************************************************************************/ HRESULT __stdcall DllUnregisterServer() { // Unregister CLSID for DIEffectDriver // -- Get HKEY_CLASSES_ROOT\CLSID key RegistryKey classesRootKey(HKEY_CLASSES_ROOT); RegistryKey clsidKey = classesRootKey.OpenSubkey(TEXT("CLSID"), KEY_READ | KEY_WRITE); if (clsidKey == c_InvalidKey) { return E_UNEXPECTED; // No CLSID key???? } DWORD numSubKeys = 0; { // driverKey Destructor will close the key // -- If the key is there get it, else we don't have to remove it RegistryKey driverKey = clsidKey.OpenSubkey(CLSID_SWPIDDriver_String); if (driverKey != c_InvalidKey) { // Is it there driverKey.RemoveSubkey(TEXT("InProcServer32")); numSubKeys = driverKey.GetNumSubkeys(); } else { // Key is not there (I guess removal was successful) return S_OK; } } if (numSubKeys == 0) { return clsidKey.RemoveSubkey(CLSID_SWPIDDriver_String); } // Made it here valid driver key return S_OK; } LONG DllAddRef() { _RPT1(_CRT_WARN, "(DllAddRef)g_lObjectCount: %d\n", g_lObjectCount); return ::InterlockedIncrement(&g_lObjectCount); } LONG DllRelease() { _RPT1(_CRT_WARN, "(DllRelease)g_lObjectCount: %d\n", g_lObjectCount); DWORD dwCount = ::InterlockedDecrement(&g_lObjectCount); if (dwCount == 0) { g_pClassFactoryObject = NULL; ::CoUninitialize(); } return dwCount; }