/***************************************************************************** * * Main.c * Copyright (c) 1999 Microsoft Corporation. All Rights Reserved. * * Abstract: * * Template effect driver that doesn't actually do anything. * *****************************************************************************/ #include "PIDpr.h" /***************************************************************************** * * Static globals: Initialized at PROCESS_ATTACH and never modified. * *****************************************************************************/ HINSTANCE g_hinst = NULL; /* This DLL's instance handle */ PSHAREDMEMORY g_pshmem = NULL; /* Our shared memory block */ HANDLE g_hfm = NULL; /* Handle to file mapping object */ HANDLE g_hmtxShared = NULL; /* Handle to mutex that protects g_pshmem */ CANCELIO CancelIo_ = FakeCancelIO; #ifdef DEBUG LONG g_cCrit = 0; ULONG g_thidCrit = 0; PTCHAR g_rgUsageTxt[PIDUSAGETXT_MAX]; // Cheat sheet for PID usages #endif TRYENTERCRITICALSECTION TryEnterCriticalSection_ = FakeTryEnterCriticalSection; /***************************************************************************** * * Dynamic Globals. There should be as few of these as possible. * * All access to dynamic globals must be thread-safe. * *****************************************************************************/ LONG 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); } /***************************************************************************** * * @doc INTERNAL * * @func void | DllEnterCrit | * * Take the DLL critical section. * * The DLL critical section is the lowest level critical section. * You may not attempt to acquire any other critical sections or * yield while the DLL critical section is held. Failure to * comply is a violation of the semaphore hierarchy and will * lead to deadlocks. * *****************************************************************************/ void EXTERNAL DllEnterCrit_(LPCTSTR lptszFile, UINT line) { #ifdef DEBUG if( ! TryEnterCriticalSection_(&g_crst) ) { SquirtSqflPtszV(sqflCrit, TEXT("Dll CritSec blocked @%s,%d"), lptszFile, line); EnterCriticalSection(&g_crst); } if (g_cCrit++ == 0) { g_thidCrit = GetCurrentThreadId(); SquirtSqflPtszV(sqflCrit, TEXT("Dll CritSec Entered @%s,%d"), lptszFile, line); } AssertF(g_thidCrit == GetCurrentThreadId()); #else EnterCriticalSection(&g_crst); #endif } /***************************************************************************** * * @doc INTERNAL * * @func void | DllLeaveCrit | * * Leave the DLL critical section. * *****************************************************************************/ void EXTERNAL DllLeaveCrit_(LPCTSTR lptszFile, UINT line) { #ifdef DEBUG AssertF(g_thidCrit == GetCurrentThreadId()); AssertF(g_cCrit >= 0); if (--g_cCrit < 0) { g_thidCrit = 0; } SquirtSqflPtszV(sqflCrit, TEXT("Dll CritSec Leaving @%s,%d"), lptszFile, line); #endif LeaveCriticalSection(&g_crst); } /***************************************************************************** * * @doc INTERNAL * * @func void | DllInCrit | * * Nonzero if we are in the DLL critical section. * *****************************************************************************/ #ifdef DEBUG BOOL INTERNAL DllInCrit(void) { return g_cCrit >= 0 && g_thidCrit == GetCurrentThreadId(); } #endif /***************************************************************************** * * 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_IDirectInputPIDDriver)) { 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; } /***************************************************************************** * * DllNameFromGuid * * Create the string version of a GUID. * *****************************************************************************/ STDAPI_(void) DllNameFromGuid(LPTSTR ptszBuf, LPCGUID pguid) { wsprintf(ptszBuf, TEXT("{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}"), pguid->Data1, pguid->Data2, pguid->Data3, pguid->Data4[0], pguid->Data4[1], pguid->Data4[2], pguid->Data4[3], pguid->Data4[4], pguid->Data4[5], pguid->Data4[6], pguid->Data4[7]); } /***************************************************************************** * * @doc INTERNAL * * @func BOOL | FakeCancelIO | * * Stub function which doesn't do anything but * keeps us from crashing. * * @parm HANDLE | h | * * The handle whose I/O is supposed to be cancelled. * *****************************************************************************/ BOOL WINAPI FakeCancelIO(HANDLE h) { AssertF(0); return FALSE; } /***************************************************************************** * * @doc INTERNAL * * @func BOOL | FakeTryEnterCriticalSection | * * We use TryEnterCriticalSection in DEBUG to detect deadlock * If the function does not exist, just enter CritSection and report * true. This compromises some debug functionality. * * @parm LPCRITICAL_SECTION | lpCriticalSection | * * Address of Critical Section to be entered. * *****************************************************************************/ BOOL WINAPI FakeTryEnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection) { EnterCriticalSection(lpCriticalSection); return TRUE; } /***************************************************************************** * * DllOnProcessAttach * * Initialize the DLL. * *****************************************************************************/ STDAPI_(BOOL) DllOnProcessAttach(HINSTANCE hinst) { TCHAR tszName[256]; HINSTANCE hinstK32; TCHAR c_tszKernel32[] = TEXT("KERNEL32"); // Cache the instance handle g_hinst = hinst; hinstK32 = GetModuleHandle( c_tszKernel32 ); if(hinstK32 != INVALID_HANDLE_VALUE) { CANCELIO tmp; TRYENTERCRITICALSECTION tmpCrt; tmp = (CANCELIO)GetProcAddress(hinstK32, "CancelIo"); if (tmp) { CancelIo_ = tmp; } else { AssertF(CancelIo_ == FakeCancelIO); } tmpCrt = (TRYENTERCRITICALSECTION)GetProcAddress(hinstK32, "TryEnterCriticalSection"); if(tmpCrt) { TryEnterCriticalSection_ = tmpCrt; }else { AssertF(TryEnterCriticalSection_ == FakeTryEnterCriticalSection); } } #ifdef DEBUG Sqfl_Init(); #endif /* * Performance tweak: We do not need thread notifications. */ DisableThreadLibraryCalls(hinst); /* * !!IHV!! Initialize your DLL here. */ __try { InitializeCriticalSection(&g_crst); } __except( EXCEPTION_EXECUTE_HANDLER ) { return FALSE; // usually out of memory condition } /* * Create our mutex that protects the shared memory block. * If it already exists, then we get access to the one that * already exists. * * The name of the shared memory block is GUID_MyMutex. */ DllNameFromGuid(tszName, &GUID_MyMutex); g_hmtxShared = CreateMutex(NULL, FALSE, tszName); if (g_hmtxShared == NULL) { return FALSE; } /* * Create our shared memory block. If it already exists, * then we get access to the one that already exists. * If it doesn't already exist, then it gets created * zero-filled (which is what we want anyway). * * The name of the shared memory block is GUID_MySharedMemory. */ DllNameFromGuid(tszName, &GUID_MySharedMemory); g_hfm = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(SHAREDMEMORY), tszName); if (g_hfm == NULL) { CloseHandle(g_hmtxShared); g_hmtxShared = NULL; return FALSE; } g_pshmem = MapViewOfFile(g_hfm, FILE_MAP_WRITE | FILE_MAP_READ, 0, 0, 0); if (g_pshmem == NULL) { CloseHandle(g_hmtxShared); g_hmtxShared = NULL; CloseHandle(g_hfm); g_hfm = NULL; return FALSE; } return TRUE; } /***************************************************************************** * * DllOnProcessDetach * * De-initialize the DLL. * *****************************************************************************/ STDAPI_(void) DllOnProcessDetach(void) { /* * !!IHV!! De-initialize your DLL here. */ if (g_pshmem != NULL) { UnmapViewOfFile(g_pshmem); g_pshmem = NULL; } if (g_hfm != NULL) { CloseHandle(g_hfm); g_hfm = NULL; } if (g_hmtxShared != NULL) { CloseHandle(g_hmtxShared); g_hmtxShared = NULL; } DeleteCriticalSection(&g_crst); } /***************************************************************************** * * DllEntryPoint * * DLL entry point. * *****************************************************************************/ STDAPI_(BOOL) DllEntryPoint(HINSTANCE hinst, DWORD dwReason, LPVOID lpReserved) { switch (dwReason) { case DLL_PROCESS_ATTACH: return DllOnProcessAttach(hinst); case DLL_PROCESS_DETACH: DllOnProcessDetach(); break; } return 1; }