417 lines
11 KiB
C
417 lines
11 KiB
C
|
/*****************************************************************************
|
||
|
*
|
||
|
* 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;
|
||
|
}
|