windows-nt/Source/XPSP1/NT/multimedia/directx/dinput/pid/main.c
2020-09-26 16:20:57 +08:00

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;
}