|
|
/***************************************************************************
* * Copyright (C) 1996 - 2000 Microsoft Corporation. All Rights Reserved. * * File: dinputi.h * Content: DirectInput internal include file *@@BEGIN_MSINTERNAL * History: * Date By Reason * ==== == ====== * 1996.05.07 raymondc Lost a bet * *@@END_MSINTERNAL * ***************************************************************************/
#ifdef __cplusplus
extern "C" { #endif
/***************************************************************************
* * Debug / RDebug / Retail * * If either DEBUG or RDEBUG, set XDEBUG. * * Retail defines nothing. * ***************************************************************************/
#if defined(DEBUG) || defined(RDEBUG)
#define XDEBUG
#endif
/***************************************************************************
* * Turning off stuff... * * Turn off these things, because they confuse the bilingualism macros. * Instead, we call then IMumbleT. * ***************************************************************************/
#undef IDirectInput
#undef IDirectInput2
#undef IDirectInput7
#undef IDirectInput8
#undef IDirectInputDevice
#undef IDirectInputDevice2
#undef IDirectInputDevice7
#undef IDirectInputDevice8
/*
* And <mmsystem.h> defines JOY_POVCENTERED incorrectly... */ #undef JOY_POVCENTERED
#define JOY_POVCENTERED 0xFFFFFFFF
/*
* And older versions of windows.h don't have this definition. */ #ifndef HasOverlappedIoCompleted
#define HasOverlappedIoCompleted(lpOverlapped) \
((lpOverlapped)->Internal != STATUS_PENDING) #endif
/***************************************************************************
* * Abbreviations.... * * Give shorter names to things we talk about frequently. * ***************************************************************************/
typedef LPDIRECTINPUT8 PDI , *PPDI ; typedef LPDIRECTINPUT8A PDIA, *PPDIA; typedef LPDIRECTINPUT8W PDIW, *PPDIW;
typedef LPDIRECTINPUTDEVICE8 PDID , *PPDID ; typedef LPDIRECTINPUTDEVICE8A PDIDA, *PPDIDA; typedef LPDIRECTINPUTDEVICE8W PDIDW, *PPDIDW;
typedef LPDIRECTINPUTEFFECT PDIE , *PPDIE ;
typedef DIOBJECTDATAFORMAT ODF, *PODF; typedef const ODF *PCODF;
typedef LPUNKNOWN PUNK; typedef LPVOID PV, *PPV; typedef CONST VOID *PCV; typedef REFIID RIID; typedef CONST GUID *PCGUID;
/***************************************************************************
* * GetProcAddress'd KERNEL32 and USER32 functions. * ***************************************************************************/ typedef DWORD (WINAPI *OPENVXDHANDLE)(HANDLE); typedef BOOL (WINAPI *CANCELIO)(HANDLE); typedef DWORD (WINAPI *MSGWAITFORMULTIPLEOBJECTSEX) (DWORD, LPHANDLE, DWORD, DWORD, DWORD);
typedef BOOL (WINAPI *TRYENTERCRITICALSECTION)(LPCRITICAL_SECTION);
extern OPENVXDHANDLE _OpenVxDHandle; extern CANCELIO _CancelIO; extern MSGWAITFORMULTIPLEOBJECTSEX _MsgWaitForMultipleObjectsEx; #ifdef XDEBUG
extern TRYENTERCRITICALSECTION _TryEnterCritSec; BOOL WINAPI FakeTryEnterCriticalSection(LPCRITICAL_SECTION lpCrit_sec); #endif
DWORD WINAPI FakeMsgWaitForMultipleObjectsEx(DWORD, LPHANDLE, DWORD, DWORD, DWORD);
BOOL WINAPI FakeCancelIO(HANDLE h);
/***************************************************************************
* * Our global variables - see dinput.c for documentation * ***************************************************************************/
extern HINSTANCE g_hinst; #ifndef WINNT
extern HANDLE g_hVxD; extern HANDLE g_hVjoyd; extern DWORD g_dwLastBonusPoll; #endif
extern DWORD g_flEmulation; extern LPDWORD g_pdwSequence;
#ifdef USE_SLOW_LL_HOOKS
extern HHOOK g_hhkLLHookCheck; #define g_fUseLLHooks ((BOOL)(UINT_PTR)g_hhkLLHookCheck)
#endif
extern HANDLE g_hmtxGlobal; extern HANDLE g_hfm; extern struct SHAREDOBJECTPAGE *g_psop; extern UINT g_wmJoyChanged; extern HANDLE g_hmtxJoy; extern HINSTANCE g_hinstSetupapi; extern LONG g_lWheelGranularity;
extern int g_cdtoMax; extern int g_cdto; extern struct _DEVICETOUSER *g_pdto;
extern BOOL g_fRawInput; #ifdef USE_WM_INPUT
extern HWND g_hwndThread; extern HANDLE g_hEventAcquire; extern HANDLE g_hEventThread; extern HANDLE g_hEventHid; #endif
extern PDWORD g_rgdwCRCTable;
typedef struct _DIAPPHACKS { BOOL fReacquire; BOOL fNoSubClass; int nMaxDeviceNameLength; } DIAPPHACKS, *LPDIAPPHACKS;
extern DIAPPHACKS g_AppHacks; extern DWORD g_dwAppDate; extern DWORD g_dwAppFileLen; extern DWORD g_dwLastMsgSent; extern UINT g_wmDInputNotify;
/*****************************************************************************
* * Baggage * * Stuff I carry everywhere. * *****************************************************************************/
#define INTERNAL NTAPI /* Called only within a translation unit */
#define EXTERNAL NTAPI /* Called from other translation units */
#define INLINE static __inline
#define BEGIN_CONST_DATA data_seg(".text", "CODE")
#define END_CONST_DATA data_seg(".data", "DATA")
/*
* Arithmetic on pointers. */ #define pvSubPvCb(pv, cb) ((PV)((PBYTE)pv - (cb)))
#define pvAddPvCb(pv, cb) ((PV)((PBYTE)pv + (cb)))
#define cbSubPvPv(p1, p2) ((PBYTE)(p1) - (PBYTE)(p2))
/*
* Convert an object (X) to a count of bytes (cb). */ #define cbX(X) sizeof(X)
/*
* Convert an array name (A) to a generic count (c). */ #define cA(a) (cbX(a)/cbX(a[0]))
/*
* Convert a count of X's (cx) into a count of bytes * and vice versa. */ #define cbCxX(cx, X) ((cx) * cbX(X))
#define cxCbX(cb, X) ((cb) / cbX(X))
/*
* Convert a count of chars (cch), tchars (ctch), wchars (cwch), * or dwords (cdw) into a count of bytes, and vice versa. */ #define cbCch(cch) cbCxX( cch, CHAR)
#define cbCwch(cwch) cbCxX(cwch, WCHAR)
#define cbCtch(ctch) cbCxX(ctch, TCHAR)
#define cbCdw(cdw) cbCxX( cdw, DWORD)
#define cchCb(cb) cxCbX(cb, CHAR)
#define cwchCb(cb) cxCbX(cb, WCHAR)
#define ctchCb(cb) cxCbX(cb, TCHAR)
#define cdwCb(cb) cxCbX(cb, DWORD)
/*
* Zero an arbitrary buffer. It is a common error to get the second * and third parameters to memset backwards. */ #define ZeroBuf(pv, cb) memset(pv, 0, cb)
/*
* Zero an arbitrary object. */ #define ZeroX(x) ZeroBuf(&(x), cbX(x))
/*
* land -- Logical and. Evaluate the first. If the first is zero, * then return zero. Otherwise, return the second. */
#define fLandFF(f1, f2) ((f1) ? (f2) : 0)
/*
* lor -- Logical or. Evaluate the first. If the first is nonzero, * return it. Otherwise, return the second. * * Unfortunately, due to the *nature* of the C language, this can * be implemented only with a GNU extension. In the non-GNU case, * we return 1 if the first is nonzero. */
#if defined(__GNUC__)
#define fLorFF(f1, f2) ((f1) ?: (f2))
#else
#define fLorFF(f1, f2) ((f1) ? 1 : (f2))
#endif
/*
* limp - logical implication. True unless the first is nonzero and * the second is zero. */ #define fLimpFF(f1, f2) (!(f1) || (f2))
/*
* leqv - logical equivalence. True if both are zero or both are nonzero. */ #define fLeqvFF(f1, f2) (!(f1) == !(f2))
/*
* fInOrder - checks that i1 <= i2 < i3. */ #define fInOrder(i1, i2, i3) ((unsigned)((i2)-(i1)) < (unsigned)((i3)-(i1)))
/*
* fHasAllBitsFlFl - checks that all bits in fl2 are set in fl1. */ BOOL INLINE fHasAllBitsFlFl(DWORD fl1, DWORD fl2) { return (fl1 & fl2) == fl2; }
/*
* fEqualMask - checks that all masked bits are equal */ BOOL INLINE fEqualMaskFlFl(DWORD flMask, DWORD fl1, DWORD fl2) { return ((fl1 ^ fl2) & flMask) == 0; }
/*
* Words to keep preprocessor happy. */ #define comma ,
#define empty
/*
* Atomically exchange one value for another. */ #if defined(_M_IA64) || defined(_M_AMD64)
#define InterlockedExchange64 _InterlockedExchange64
#ifndef RC_INVOKED
#pragma intrinsic(_InterlockedExchange64)
#endif /*RC_INVOKED*/
#define pvExchangePpvPv(ppv, pv) \
InterlockedExchange((ppv), (pv)) #define pvExchangePpvPv64(ppv, pv) \
InterlockedExchange64((ppv), (pv)) #else /*_M_IA64*/
#define pvExchangePpvPv(ppv, pv) \
(PV)InterlockedExchange((PLONG)(ppv), (LONG)(pv)) #define pvExchangePpvPv64(ppv, pv) \
(PV)InterlockedExchange((PLONG)(ppv), (LONG)(pv)) #endif /*_M_IA64*/
/*
* Creating HRESULTs from a USHORT or from a LASTERROR. */ #define hresUs(us) MAKE_HRESULT(SEVERITY_SUCCESS, 0, (USHORT)(us))
#define hresLe(le) MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, (USHORT)(le))
/*
* or a registry function return code */ HRESULT INLINE hresReg( LONG lRc ) { return( (lRc) ? MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, (USHORT)(lRc)) : S_OK ); }
/***************************************************************************
* * Debugging macros needed by inline functions * * The build of debugging goo is in debug.h * ***************************************************************************/
int EXTERNAL AssertPtszPtszLn(LPCTSTR ptszExpr, LPCTSTR ptszFile, int iLine);
#ifdef DEBUG
#define AssertFPtsz(c, ptsz) \
((c) ? 0 : AssertPtszPtszLn(ptsz, TEXT(__FILE__), __LINE__)) #define ValidateF(c, arg) \
((c) ? 0 : (RPF arg, ValidationException(), 0)) #define ConfirmF(c) \
((c) ? 0 : AssertPtszPtszLn(TEXT(#c), TEXT(__FILE__), __LINE__))
#else /* !DEBUG */
#define AssertFPtsz(c, ptsz)
#define ValidateF(c, arg)
#define ConfirmF(c) (c)
#endif
/*
* CAssertF - compile-time assertion. */ #define CAssertF(c) switch(0) case c: case 0:
#define AssertF(c) AssertFPtsz(c, TEXT(#c))
/***************************************************************************
* * Validation Code.... * * "If it crashes in retail, it must crash in debug." * * What we don't want is an app that works fine under debug, but crashes * under retail. * * So if we find an invalid parameter in debug that would not have been * detected by retail, let it pass through after a warning. That way, * the invalid parameter continues onward through the system and creates * as much (or more) havoc in debug as it would under retail. * * There used to be _fFastValidXxx functions, but the decision was made * to do full validation always, except in inner-loop methods. * * The hresFullValidXxx functions return HRESULTs instead of BOOLs. * * Values for Xxx: * * Hwnd - hwnd = window handle * Pdw - pdw = pointer to a dword * PdwOut - pdw = pointer to a dword that will be set initially to 0 * Pfn - pfn = function pointer * riid - riid = pointer to IID * guid - pguid = pointer to GUID * Esc - pesc = pointer to DIEFFESCAPE * * ReadPx - p -> structure for reading, X = structure name * WritePx - p -> structure for writing, X = structure name * * ReadPxCb - p -> structure for reading, X = structure name * first field of structure is dwSize which must be * equal to cbX(X). * * WritePxCb - p -> structure for writing, X = structure name * first field of structure is dwSize which must be * equal to cbX(X). * * WritePxCb2 - p -> structure for writing, X = structure name * first field of structure is dwSize which must be * equal to cbX(X) or cbX(X2). * * ReadPvCb - p -> buffer, cb = size of buffer * WritePvCb - p -> buffer, cb = size of buffer * * Pobj - p -> internal interface * * fl - fl = incoming flags, flV = valid flags * ***************************************************************************/
#ifndef XDEBUG
/*
* Wrappers that throw away the szProc and iarg info. */
#define hresFullValidHwnd_(hwnd, z, i) \
_hresFullValidHwnd_(hwnd) \
#define hresFullValidPcbOut_(pdw, cb, z, i) \
_hresFullValidPcbOut_(pdw, cb) \
#define hresFullValidReadPxCb_(pv, cb, pszProc, iarg) \
_hresFullValidReadPxCb_(pv, cb) \
#define hresFullValidReadPvCb_(pv, cb, pszProc, iarg) \
_hresFullValidReadPvCb_(pv, cb) \
#define hresFullValidReadPxCb3_(pv, cb, cb2, cb3, pszProc, iarg) \
_hresFullValidReadPxCb3_(pv, cb, cb2, cb3) \
#define hresFullValidWritePxCb_(pv, cb, pszProc, iarg) \
_hresFullValidWritePxCb_(pv, cb) \
#define hresFullValidWritePxCb3_(pv, cb, cb2, cb3, pszProc, iarg) \
_hresFullValidWritePxCb3_(pv, cb, cb2, cb3) \
#define hresFullValidWriteNoScramblePxCb_(pv, cb, pszProc, iarg)\
_hresFullValidWriteNoScramblePxCb_(pv, cb) \
#define hresFullValidWritePvCb_(pv, cb, pszProc, iarg) \
_hresFullValidWritePvCb_(pv, cb) \
#define hresFullValidFl_(fl, flV, pszProc, iarg) \
_hresFullValidFl_(fl, flV) \
#define hresFullValidPfn_(pfn, pszProc, iarg) \
_hresFullValidPfn_(pfn) \
#define hresFullValidPitf_(punk, pszProc, iarg) \
_hresFullValidPitf_(punk) \
#define hresFullValidReadStrA_(psz, cch, pszProc, iarg) \
_hresFullValidReadStrA_(psz, cch) \
#define hresFullValidReadStrW_(pwsz, cwch, pszProc, iarg) \
_hresFullValidReadStrW_(pwsz, cwch) \
#define hresFullValidHwnd0_(hwnd, pszProc, iarg) \
_hresFullValidHwnd0_(hwnd) \
#define hresFullValidPitf0_(punk, pszProc, iarg) \
_hresFullValidPitf0_(punk) \
#define hresFullValidPesc_(pesc, pszProc, iarg) \
_hresFullValidPesc_(pesc) \
#define hresFullValidWriteLargePvCb_(pv, cb, pszProc, iarg) \
_hresFullValidWriteLargePvCb_(pv, cb) \
#endif
/*
* The actual functions. */
STDMETHODIMP hresFullValidHwnd_(HWND hwnd, LPCSTR pszProc, int iarg); STDMETHODIMP hresFullValidPcbOut_(PV pdw, UINT cb, LPCSTR pszProc, int iarg); STDMETHODIMP hresFullValidReadPxCb_(PCV pv, UINT cb, LPCSTR pszProc, int iarg); STDMETHODIMP hresFullValidReadPvCb_(PCV pv, UINT cb, LPCSTR pszProc, int iarg); STDMETHODIMP hresFullValidReadPxCb3_(PV pv, UINT cb, UINT cb2, UINT cb3, LPCSTR pszProc, int iarg); STDMETHODIMP hresFullValidWritePxCb_(PV pv, UINT cb, LPCSTR pszProc, int iarg); STDMETHODIMP hresFullValidWritePxCb3_(PV pv, UINT cb, UINT cb2, UINT cb3, LPCSTR pszProc, int iarg); STDMETHODIMP hresFullValidWritePvCb_(PV pv, UINT cb, LPCSTR pszProc, int iarg); STDMETHODIMP hresFullValidFl_(DWORD fl, DWORD flV, LPCSTR pszProc, int iarg); STDMETHODIMP hresFullValidPfn_(FARPROC pfn, LPCSTR pszProc, int iarg); STDMETHODIMP hresFullValidPitf_(PUNK punk, LPCSTR pszProc, int iarg); STDMETHODIMP hresFullValidReadStrA_(LPCSTR psz, UINT cch, LPCSTR s_szProc, int iarg); STDMETHODIMP hresFullValidReadStrW_(LPCWSTR pwsz, UINT cwch, LPCSTR pszProc, int iarg); STDMETHODIMP hresFullValidPesc_(LPDIEFFESCAPE pesc, LPCSTR pszProc, int iarg); STDMETHODIMP hresFullValidWriteLargePvCb_(PV pv, UINT cb, LPCSTR pszProc, int iarg);
#ifdef XDEBUG
STDMETHODIMP hresFullValidWriteNoScramblePxCb_(PV pv, UINT cb, LPCSTR s_szProc, int iarg);
#define hresFullValidWriteNoScramblePvCb_(pv, cb, pszProc, iarg) \
hresFullValidWritePvCb_(pv, cb, pszProc, MAKELONG(iarg, 1)) \
#else
/*
* Retail doesn't scramble. */ #define _hresFullValidWriteNoScramblePxCb_ \
_hresFullValidWritePxCb_ \
#define _hresFullValidWriteNoScramblePxCb3_ \
_hresFullValidWritePxCb3_ \
#define hresFullValidWriteNoScramblePvCb_ \
hresFullValidWritePvCb_ \
#endif
HRESULT INLINE hresFullValidHwnd0_(HWND hwnd, LPCSTR pszProc, int iarg) { HRESULT hres; if(hwnd) { hres = hresFullValidHwnd_(hwnd, pszProc, iarg); } else { hres = S_OK; } return hres; }
HRESULT INLINE hresFullValidPitf0_(PUNK punk, LPCSTR pszProc, int iarg) { HRESULT hres; if(punk) { hres = hresFullValidPitf_(punk, pszProc, iarg); } else { hres = S_OK; } return hres; }
/*
* Wrappers for derived types. */
#define hresFullValidRiid_(riid, s_szProc, iarg) \
hresFullValidReadPvCb_(riid, cbX(IID), s_szProc, iarg) \
/*
* Wrapers that add the szProc and iarg info. */
#define hresFullValidHwnd(hwnd, iarg) \
hresFullValidHwnd_(hwnd, s_szProc, iarg) \
#define hresFullValidPcbOut(pdw, cb, i) \
hresFullValidPcbOut_(pdw, cb, s_szProc, i) \
#define hresFullValidReadPdw_(pdw, z, i) \
hresFullValidReadPvCb_(pdw, cbX(DWORD), z, i) \
#define hresFullValidRiid(riid, iarg) \
hresFullValidRiid_(riid, s_szProc, iarg) \
#define hresFullValidGuid(pguid, iarg) \
hresFullValidReadPvCb_(pguid, cbX(GUID), s_szProc, iarg) \
#define hresFullValidReadPxCb(pv, X, iarg) \
hresFullValidReadPxCb_(pv, cbX(X), s_szProc, iarg) \
#define hresFullValidReadPxCb2(pv, X, X2, iarg) \
hresFullValidReadPxCb_(pv, MAKELONG(cbX(X), cbX(X2)), \ s_szProc, iarg) \
#define hresFullValidReadPvCb(pv, cb, iarg) \
hresFullValidReadPvCb_(pv, cb, s_szProc, iarg) \
#define hresFullValidReadPx(pv, X, iarg) \
hresFullValidReadPvCb_(pv, cbX(X), s_szProc, iarg) \
#define hresFullValidReadPxCb3(pv, X, X2, X3, iarg) \
hresFullValidReadPxCb3_(pv, cbX(X), cbX(X2), cbX(X3), \ s_szProc, iarg) \
#define hresFullValidWritePxCb(pv, X, iarg) \
hresFullValidWritePxCb_(pv, cbX(X), s_szProc, iarg) \
#define hresFullValidWritePxCb2(pv, X, X2, iarg) \
hresFullValidWritePxCb_(pv, MAKELONG(cbX(X), cbX(X2)), \ s_szProc, iarg) \
#define hresFullValidWritePxCb3(pv, X, X2, X3, iarg) \
hresFullValidWritePxCb3_(pv, cbX(X), cbX(X2), cbX(X3), \ s_szProc, iarg) \
#define hresFullValidWriteNoScramblePxCb(pv, X, iarg) \
hresFullValidWriteNoScramblePxCb_(pv, cbX(X), s_szProc, iarg)\
#define hresFullValidWriteNoScramblePxCb2(pv, X, X2, iarg) \
hresFullValidWriteNoScramblePxCb_(pv, MAKELONG(cbX(X), cbX(X2)),\ s_szProc, iarg)\
#define hresFullValidWritePvCb(pv, cb, iarg) \
hresFullValidWritePvCb_(pv, cb, s_szProc, iarg) \
#define hresFullValidWriteNoScramblePvCb(pv, cb, iarg) \
hresFullValidWriteNoScramblePvCb_(pv, cb, s_szProc, iarg) \
#define hresFullValidWritePx(pv, X, iarg) \
hresFullValidWritePvCb_(pv, cbX(X), s_szProc, iarg) \
#define hresFullValidReadPdw(pdw, iarg) \
hresFullValidReadPdw_(pdw, s_szProc, iarg) \
#define hresFullValidWritePguid(pguid, iarg) \
hresFullValidWritePx(pguid, GUID, iarg) \
#define hresFullValidFl(fl, flV, iarg) \
hresFullValidFl_(fl, flV, s_szProc, iarg) \
#define hresFullValidPfn(pfn, iarg) \
hresFullValidPfn_((FARPROC)(pfn), s_szProc, iarg) \
#define hresFullValidPitf(pitf, iarg) \
hresFullValidPitf_((PUNK)(pitf), s_szProc, iarg) \
#define hresFullValidReadStrA(psz, cch, iarg) \
hresFullValidReadStrA_(psz, cch, s_szProc, iarg) \
#define hresFullValidReadStrW(pwsz, cwch, iarg) \
hresFullValidReadStrW_(pwsz, cwch, s_szProc, iarg) \
#define hresFullValidHwnd0(hwnd, iarg) \
hresFullValidHwnd0_(hwnd, s_szProc, iarg) \
#define hresFullValidPitf0(pitf, iarg) \
hresFullValidPitf0_((PUNK)(pitf), s_szProc, iarg) \
#define hresFullValidPesc(pesc, iarg) \
hresFullValidPesc_(pesc, s_szProc, iarg) \
#define hresFullValidWriteLargePvCb(pv, cb, iarg) \
hresFullValidWriteLargePvCb_(pv, cb, s_szProc, iarg) \
/*****************************************************************************
* * @doc INTERNAL * * @func void | ValidationException | * * Raises a parameter validation exception in XDEBUG. * *****************************************************************************/
#define ecValidation (ERROR_SEVERITY_ERROR | hresLe(ERROR_INVALID_PARAMETER))
#ifdef XDEBUG
#define ValidationException() RaiseException(ecValidation, 0, 0, 0)
#else
#define ValidationException()
#endif
/*****************************************************************************
* * Bilingualism * * Special macros that help writing ANSI and UNICODE versions of * the same underlying interface. * *****************************************************************************/
/*
* _THAT is something you tack onto the end of a "bilingual" interface. * In debug, it expands to the magic third argument which represents * the vtbl the object should have. In retail, it expands to nothing. */ #ifdef XDEBUG
#define _THAT , PV vtblExpected
#define THAT_ , vtblExpected
#else
#define _THAT
#define THAT_
#endif
/*
* CSET_STUBS creates stubs for ANSI and UNICODE versions of the * same procedure that is not character set-sensitive. * * mf - method function name * arg1 - argument list in prototype form * arg2 - argument list for calling (with _riid appended). * * It is assumed that the caller has already defined the symbols * ThisClass and ThisInterface[AWT]. * * This macro should be used only in DEBUG. In retail, the common * procedure handles both character sets directly. */ #ifdef XDEBUG
#define CSET_STUBS(mf, arg1, arg2) \
CSET_STUB(TFORM, mf, arg1, arg2) \ CSET_STUB(SFORM, mf, arg1, arg2) \
#define CSET_STUB(FORM, mf, arg1, arg2) \
_CSET_STUB(FORM, mf, arg1, arg2, ThisClass, ThisInterface) \
#define _CSET_STUB(FORM, mf, arg1, arg2, cls, itf) \
__CSET_STUB(FORM, mf, arg1, arg2, cls, itf) \
#define __CSET_STUB(FORM, mf, arg1, arg2, cls, itf) \
STDMETHODIMP \ FORM(cls##_##mf) arg1 \ { \ PV vtblExpected = Class_Vtbl(ThisClass, FORM(ThisInterfaceT)); \ return cls##_##mf arg2; \ } \
#endif
/*
* TFORM(x) expands to x##A if ANSI or x##W if UNICODE. * This T-izes a symbol, in the sense of TCHAR or PTSTR. * * SFORM(x) expands to x##W if ANSI or x##A if UNICODE. * This anti-T-izes a symbol. */
#ifdef UNICODE
#define _TFORM(x) x##W
#define _SFORM(x) x##A
#else
#define _TFORM(x) x##A
#define _SFORM(x) x##W
#endif
#define TFORM(x) _TFORM(x)
#define SFORM(x) _SFORM(x)
#ifdef UNICODE
typedef CHAR SCHAR; #else
typedef WCHAR SCHAR; #endif
typedef SCHAR * LPSSTR; typedef const SCHAR * LPCSSTR;
/*
* SToT(dst, cchDst, src) - convert S to T * TToS(dst, cchDst, src) - convert T to S * * Remember, "T" means "ANSI if ANSI, or UNICODE if UNICODE", * and "S" is the anti-T. * * So SToT converts to the preferred character set, and TToS converts * to the alternate character set. * */
#define AToU(dst, cchDst, src) \
MultiByteToWideChar(CP_ACP, 0, src, -1, dst, cchDst) #define UToA(dst, cchDst, src) \
WideCharToMultiByte(CP_ACP, 0, src, -1, dst, cchDst, 0, 0)
#ifdef UNICODE
#define SToT AToU
#define TToS UToA
#define AToT AToU
#define TToU(dst, cchDst, src) lstrcpyn(dst, src, cchDst)
#define UToT(dst, cchDst, src) lstrcpyn(dst, src, cchDst)
#else
#define SToT UToA
#define TToS AToU
#define AToT(dst, cchDst, src) lstrcpyn(dst, src, cchDst)
#define TToU AToU
#define UToT UToA
#endif
/*****************************************************************************
* * Unicode wrappers for Win95 * *****************************************************************************/
#ifndef UNICODE
#define LoadStringW _LoadStringW
int EXTERNAL LoadStringW(HINSTANCE hinst, UINT ids, LPWSTR pwsz, int cwch);
#define RegDeleteKeyW _RegDeleteKeyW
LONG EXTERNAL RegDeleteKeyW(HKEY hk, LPCWSTR pwsz);
#endif
/*****************************************************************************
* * Registry access functions * *****************************************************************************/
//our own version of KEY_ALL_ACCESS, that does not use WRITE_DAC and WRITE_OWNER (see Whistler bug 318865)
#define DI_DAC_OWNER (WRITE_DAC | WRITE_OWNER)
#define DI_KEY_ALL_ACCESS (KEY_ALL_ACCESS & ~DI_DAC_OWNER)
LONG EXTERNAL RegQueryString(HKEY hk, LPCTSTR ptszValue, LPTSTR ptszBuf, DWORD ctchBuf);
LONG EXTERNAL RegQueryStringValueW(HKEY hk, LPCTSTR ptszValue, LPWSTR pwszBuf, LPDWORD pcbBuf);
LONG EXTERNAL RegSetStringValueW(HKEY hk, LPCTSTR ptszValue, LPCWSTR pwszBuf);
DWORD EXTERNAL RegQueryDIDword(LPCTSTR ptszPath, LPCTSTR ptszValue, DWORD dwDefault);
STDMETHODIMP hresMumbleKeyEx(HKEY hk, LPCTSTR ptszKey, REGSAM sam, DWORD dwOptions, PHKEY phk);
STDMETHODIMP hresRegCopyValues( HKEY hkSrc, HKEY hkDest );
STDMETHODIMP hresRegCopyKey( HKEY hkSrcRoot, PTCHAR szSrcName, PTCHAR szClass, HKEY hkDestRoot, PTCHAR szDestName, HKEY *phkSub );
STDMETHODIMP hresRegCopyKeys( HKEY hkSrc, HKEY hkRoot, PDWORD OPTIONAL pMaxNameLen );
STDMETHODIMP hresRegCopyBranch( HKEY hkSrc, HKEY hkDest );
/*****************************************************************************
* * Common Object Managers for the Component Object Model * * OLE wrapper macros and structures. For more information, see * the beginning of common.c * *****************************************************************************/
/*****************************************************************************
* * Pre-vtbl structures * * Careful! If you change these structures, you must also adjust * common.c accordingly. * *****************************************************************************/
typedef struct PREVTBL { /* Shared vtbl prefix */ RIID riid; /* Type of this object */ LONG lib; /* offset from start of object */ } PREVTBL, *PPREVTBL;
typedef struct PREVTBLP { /* Prefix for primary vtbl */ #ifdef DEBUG
LPCTSTR tszClass; /* Class name (for squirties) */ #endif
PPV rgvtbl; /* Array of standard vtbls */ UINT cbvtbl; /* Size of vtbl array in bytes */ STDMETHOD(QIHelper)(PV pv, RIID riid, PPV ppvOut); /* QI helper */ STDMETHOD_(void,AppFinalizeProc)(PV pv);/* App finalization procedure */ STDMETHOD_(void,FinalizeProc)(PV pv);/* Finalization procedure */ PREVTBL prevtbl; /* lib must be zero */ } PREVTBLP, *PPREVTBLP;
/*
* A fuller implementation is in common.c. Out here, we need only * concern ourselves with getting to the primary interface. */
#define _thisPv(pitf) \
pvSubPvCb(pitf, (*(PPREVTBL*)(pitf))[-1].lib)
#define _thisPvNm(pitf, nm) \
pvSubPvCb(pitf, FIELD_OFFSET(ThisClass, nm)) \
#ifndef XDEBUG
#define hresPvVtbl_(pv, vtbl, pszProc) \
_hresPvVtbl_(pv, vtbl) \
#endif
HRESULT EXTERNAL hresPvVtbl_(PV pv, PV vtbl, LPCSTR pszProc);
#define hresPvVtbl(pv, vtbl) \
hresPvVtbl_(pv, vtbl, s_szProc) \
#define hresPvI(pv, I) \
hresPvVtbl(pv, Class_Vtbl(ThisClass, I)) \
#define hresPv(pv) \
hresPvI(pv, ThisInterface) \
#define hresPvA(pv) \
hresPvI(pv, ThisInterfaceA) \
#define hresPvW(pv) \
hresPvI(pv, ThisInterfaceW) \
#ifdef XDEBUG
#define hresPvT(pv) \
hresPvVtbl(pv, vtblExpected) \
#else
#define hresPvT(pv) \
hresPv(pv) \
#endif
/*****************************************************************************
* * Declaring interfaces * * The extra level of indirection on _Primary_Interface et al * allow the interface name to be a macro which expands to the * *real* name of the interface. * *****************************************************************************/
#define __Class_Vtbl(C, I) &c_##I##_##C##VI.vtbl
#define _Class_Vtbl(C, I) __Class_Vtbl(C, I)
#define Class_Vtbl(C, I) _Class_Vtbl(C, I)
#define Num_Interfaces(C) cA(c_rgpv##C##Vtbl)
#ifdef DEBUG
#define Simple_Interface(C) Primary_Interface(C, IUnknown); \
Default_QueryInterface(C) \ Default_AddRef(C) \ Default_Release(C) #define Simple_Vtbl(C) Class_Vtbl(C)
#define Simple_Interface_Begin(C) Primary_Interface_Begin(C, IUnknown)
#define Simple_Interface_End(C) Primary_Interface_End(C, IUnknown)
#else
#define Simple_Interface(C) Primary_Interface(C, IUnknown)
#define Simple_Vtbl(C) Class_Vtbl(C)
#define Simple_Interface_Begin(C) \
struct S_##C##Vtbl c_##I##_##C##VI = { { \ c_rgpv##C##Vtbl, \ cbX(c_rgpv##C##Vtbl), \ C##_QIHelper, \ C##_AppFinalize, \ C##_Finalize, \ { &IID_##IUnknown, 0 }, \ }, { \ Common##_QueryInterface, \ Common##_AddRef, \ Common##_Release, \
#define Simple_Interface_End(C) \
} }; \
#endif
#define _Primary_Interface(C, I) \
extern struct S_##C##Vtbl { \ PREVTBLP prevtbl; \ I##Vtbl vtbl; \ } c_##I##_##C##VI \
#define Primary_Interface(C, I) \
_Primary_Interface(C, I) \
#ifdef DEBUG
#define _Primary_Interface_Begin(C, I) \
struct S_##C##Vtbl c_##I##_##C##VI = { { \ TEXT(#C), \ c_rgpv##C##Vtbl, \ cbX(c_rgpv##C##Vtbl), \ C##_QIHelper, \ C##_AppFinalize, \ C##_Finalize, \ { &IID_##I, 0, }, \ }, { \ C##_QueryInterface, \ C##_AddRef, \ C##_Release, \
#else
#define _Primary_Interface_Begin(C, I) \
struct S_##C##Vtbl c_##I##_##C##VI = { { \ c_rgpv##C##Vtbl, \ cbX(c_rgpv##C##Vtbl), \ C##_QIHelper, \ C##_AppFinalize, \ C##_Finalize, \ { &IID_##I, 0, }, \ }, { \ C##_QueryInterface, \ C##_AddRef, \ C##_Release, \
#endif
#define Primary_Interface_Begin(C, I) \
_Primary_Interface_Begin(C, I) \
#define Primary_Interface_End(C, I) \
} }; \
#define _Secondary_Interface(C, I) \
extern struct S_##I##_##C##Vtbl { \ PREVTBL prevtbl; \ I##Vtbl vtbl; \ } c_##I##_##C##VI \
#define Secondary_Interface(C, I) \
_Secondary_Interface(C, I) \
/*
* Secret backdoor for the "private" IUnknown in common.c */ #define _Secondary_Interface_Begin(C, I, ofs, Pfx) \
struct S_##I##_##C##Vtbl c_##I##_##C##VI = { { \ &IID_##I, \ ofs, \ }, { \ Pfx##QueryInterface, \ Pfx##AddRef, \ Pfx##Release, \
#define Secondary_Interface_Begin(C, I, nm) \
_Secondary_Interface_Begin(C, I, FIELD_OFFSET(C, nm), Common_) \
#define _Secondary_Interface_End(C, I) \
} }; \
#define Secondary_Interface_End(C, I, nm) \
_Secondary_Interface_End(C, I) \
#define Interface_Template_Begin(C) \
PV c_rgpv##C##Vtbl[] = { \
#define Primary_Interface_Template(C, I) \
Class_Vtbl(C, I), \
#define Secondary_Interface_Template(C, I) \
Class_Vtbl(C, I), \
#define Interface_Template_End(C) \
}; \
STDMETHODIMP Common_QueryInterface(PV, RIID, PPV); STDMETHODIMP_(ULONG) Common_AddRef(PV pv); STDMETHODIMP_(ULONG) Common_Release(PV pv);
STDMETHODIMP_(void) Common_Hold(PV pv); STDMETHODIMP_(void) Common_Unhold(PV pv);
STDMETHODIMP Common_QIHelper(PV, RIID, PPV); void EXTERNAL Common_Finalize(PV);
#define Common_AppFinalize Common_Finalize
#ifndef XDEBUG
#define _Common_New_(cb, punkOuter, vtbl, pvpObj, z) \
__Common_New_(cb, punkOuter, vtbl, pvpObj) \
#define _Common_NewRiid_(cb, vtbl, punkOuter, riid, pvpObj, z) \
__Common_NewRiid_(cb, vtbl, punkOuter, riid, pvpObj) \
#endif
STDMETHODIMP _Common_New_(ULONG cb, PUNK punkOuter, PV vtbl, PPV ppvObj, LPCSTR s_szProc);
STDMETHODIMP _Common_NewRiid_(ULONG cb, PV vtbl, PUNK punkOuter, RIID riid, PPV pvpObj, LPCSTR s_szProc);
#define Common_NewCb(cb, C, punkOuter, ppvObj) \
_Common_New_(cb, punkOuter, Class_Vtbl(C, ThisInterface), ppvObj, s_szProc)
#define Common_New(C, punkOuter, ppvObj) \
Common_NewCb(cbX(C), C, punkOuter, ppvObj) \
#define Common_NewCbRiid(cb, C, punkOuter, riid, ppvObj) \
_Common_NewRiid_(cb, Class_Vtbl(C, ThisInterface), punkOuter, riid, ppvObj, s_szProc)
#define Common_NewRiid(C, punkOuter, riid, ppvObj) \
_Common_NewRiid_(cbX(C), Class_Vtbl(C, ThisInterface), punkOuter, riid, ppvObj, s_szProc)
#ifdef DEBUG
PV EXTERNAL Common_IsType(PV pv); #else
#define Common_IsType
#endif
#define Assert_CommonType Common_IsType
STDMETHODIMP Forward_QueryInterface(PV pv, RIID riid, PPV ppvObj); STDMETHODIMP_(ULONG) Forward_AddRef(PV pv); STDMETHODIMP_(ULONG) Forward_Release(PV pv);
void EXTERNAL Invoke_Release(PV pv);
#define Common_DumpObjects()
/*****************************************************************************
* * OLE wrappers * * These basically do the same as IUnknown_Mumble, except that they * avoid side-effects in evaluation by being inline functions. * *****************************************************************************/
HRESULT INLINE OLE_QueryInterface(PV pv, RIID riid, PPV ppvObj) { PUNK punk = pv; return punk->lpVtbl->QueryInterface(punk, riid, ppvObj); }
ULONG INLINE OLE_AddRef(PV pv) { PUNK punk = pv; return punk->lpVtbl->AddRef(punk); }
ULONG INLINE OLE_Release(PV pv) { PUNK punk = pv; return punk->lpVtbl->Release(punk); }
/*****************************************************************************
* * Macros that forward to the common handlers after squirting. * Use these only in DEBUG. * * It is assumed that sqfl has been #define'd to the appropriate sqfl. * *****************************************************************************/
#ifdef DEBUG
#define Default_QueryInterface(Class) \
STDMETHODIMP \ Class##_QueryInterface(PV pv, RIID riid, PPV ppvObj) \ { \ SquirtSqflPtszV(sqfl, TEXT(#Class) TEXT("_QueryInterface()")); \ return Common_QueryInterface(pv, riid, ppvObj); \ } \
// 7/19/2000(a-JiTay): IA64: Use %p format specifier for 32/64-bit pointers.
#define Default_AddRef(Class) \
STDMETHODIMP_(ULONG) \ Class##_AddRef(PV pv) \ { \ ULONG ulRc = Common_AddRef(pv); \ SquirtSqflPtszV(sqfl, TEXT(#Class) TEXT("_AddRef(%p) -> %d"), pv, ulRc); \ return ulRc; \ } \
// 7/19/2000(a-JiTay): IA64: Use %p format specifier for 32/64-bit pointers.
#define Default_Release(Class) \
STDMETHODIMP_(ULONG) \ Class##_Release(PV pv) \ { \ ULONG ulRc = Common_Release(pv); \ SquirtSqflPtszV(sqfl, TEXT(#Class) TEXT("_Release(%p) -> %d"), pv, ulRc); \ return ulRc; \ } \
#endif
/*****************************************************************************
* * Paranoid callbacks * * Callback() performs a callback. The callback must accept exactly * two parameters, both pointers. (All our callbacks are like this.) * And it must return a BOOL. * *****************************************************************************/
typedef BOOL (FAR PASCAL * DICALLBACKPROC)(LPVOID, LPVOID);
#ifdef XDEBUG
BOOL EXTERNAL Callback(DICALLBACKPROC, PVOID, PVOID); #else
#define Callback(pec, pv1, pv2) pec(pv1, pv2)
#endif
#if 0
/*****************************************************************************
* * Groveling into a CONTEXT structure. * * This is used to check that a callback procedure is properly * prototyped. We save the stack register before calling the * procedure and compare it with the stack register on the way back. * If they are different, explode! * * ctxEsp is the name of the stack pointer register. * *****************************************************************************/
typedef struct STACKINFO { CONTEXT ctxPre; /* Thread context before call */ CONTEXT ctxPost; /* Thread context after call */ } STACKINFO, *PSTACKINFO;
#ifdef XDEBUG
#if defined(_X86_)
#define ctxEsp Esp
#elif defined(_ALPHA_)
#define ctxEsp IntSp
#elif defined(_MIPS_)
#define ctxEsp IntSp
#elif defined(_PPC_)
#define ctxEsp Gpr1
#else
#pragma message("I don't know what the stack register is called on this platform")
#endif
#endif
#ifdef ctxEsp
#define DECLARE_STACKINFO() \
STACKINFO si \
#define PRE_CALLBACK() \
si.ctxPre.ContextFlags = CONTEXT_CONTROL; \ GetThreadContext(GetCurrentThread(), &si.ctxPre) \
#define POST_CALLBACK() \
si.ctxPost.ContextFlags = CONTEXT_CONTROL; \ if (GetThreadContext(GetCurrentThread(), &si.ctxPost) && \ si.ctxPre.ctxEsp != si.ctxPost.ctxEsp) { \ RPF("DINPUT: Incorrectly prototyped callback! Crash soon!"); \ ValidationException(); \ } \
#else
#define DECLARE_STACKINFO()
#define PRE_CALLBACK()
#define POST_CALLBACK()
#endif
#endif
/*****************************************************************************
* * Alternative message cracker macros * * Basically the same as HANDLE_MSG, except that it stashes the * answer into hres. * *****************************************************************************/
#define HRES_MSG(this, msg, fn) \
case msg: hres = HANDLE_##msg(this, wParam, lParam, fn); break
/*****************************************************************************
* * Registry keys and value names * *****************************************************************************/
#define REGSTR_PATH_DINPUT TEXT("Software\\Microsoft\\DirectInput")
#define REGSTR_KEY_APPHACK TEXT("Compatibility")
#define REGSTR_KEY_TEST TEXT("Test")
#define REGSTR_KEY_KEYBTYPE REGSTR_KEY_TEST TEXT("\\KeyboardType")
#define REGSTR_VAL_EMULATION TEXT("Emulation")
#define REGSTR_VAL_GAMEPADDELAY TEXT("GamepadDelay")
#define REGSTR_VAL_JOYNFFCONFIG TEXT("Joystick%dFFConfiguration")
#define REGSTR_VAL_JOYGAMEPORTEMULATOR TEXT("OEMEmulator")
#define REGSTR_VAL_CPLCLSID TEXT("ConfigCLSID")
#define REGSTR_KEY_JOYPREDEFN TEXT("predef%d")
#define REGSTR_VAL_JOYOEMCALLOUT TEXT("OEMCallout")
#define REGSTR_VAL_JOYOEMHARDWAREID TEXT("OEMHardwareID")
#define REGSTR_VAL_FLAGS1 TEXT("Flags1")
#define REGSTR_VAL_FLAGS2 TEXT("Flags2")
#define REGSTR_PATH_DITYPEPROP REGSTR_PATH_PRIVATEPROPERTIES TEXT("\\DirectInput")
#define REGSTR_VAL_JOYOEMMAPFILE TEXT("OEMMapFile")
/*****************************************************************************
* * Registered window messages * *****************************************************************************/
#define MSGSTR_JOYCHANGED TEXT("MSJSTICK_VJOYD_MSGSTR")
/*****************************************************************************
* * mem.c - Memory management * * Be extremely careful with FreePv, because it doesn't work if * the pointer is null. * *****************************************************************************/
#define NEED_REALLOC
STDMETHODIMP EXTERNAL ReallocCbPpv(UINT cb, PV ppvObj); STDMETHODIMP EXTERNAL AllocCbPpv(UINT cb, PV ppvObj);
#ifdef NEED_REALLOC
#define FreePpv(ppv) (void)ReallocCbPpv(0, ppv)
#else
void EXTERNAL FreePpv(PV ppv); #define FreePpv(ppv) FreePpv(ppv)
#endif
#define FreePv(pv) LocalFree((HLOCAL)(pv))
/*****************************************************************************
* * diutil.c - Misc utilities * *****************************************************************************/
extern GUID GUID_Null;
#define ctchGuid (1 + 8 + 1 + 4 + 1 + 4 + 1 + 4 + 1 + 12 + 1 + 1)
BOOL EXTERNAL ParseGUID(LPGUID pGUID, LPCTSTR ptsz); BOOL EXTERNAL ParseVIDPID(PUSHORT puVID, PUSHORT puPID , LPCWSTR ptsz);
#define ctchNamePrefix 12 /* 12 = strlen("DirectInput.") */
#define ctchNameGuid (ctchNamePrefix + ctchGuid)
void EXTERNAL NameFromGUID(LPTSTR ptszBuf, PCGUID pGUID);
typedef STDMETHOD(CREATEDCB)(PUNK, REFGUID, RIID, PPV);
typedef struct DIOBJECTSTATICDATA { union { PCGUID rguidInstance; /* If a static device */ UINT uiButtons; /* If a HID mouse */ }; DWORD dwDevType; union { CREATEDCB CreateDcb; /* If a static device */ UINT uiAxes; /* If a HID mouse */ }; } DIOBJECTSTATICDATA, *PDIOBJECTSTATICDATA, **PPDIOBJECTSTATICDATA;
HRESULT EXTERNAL hresRunControlPanel(LPCTSTR ptszCpl);
HRESULT EXTERNAL DiActionFormatAtoW(const LPDIACTIONFORMATA lpDiAfA, LPDIACTIONFORMATW* lplpDiAfW); HRESULT EXTERNAL DiActionFormatWtoW(const LPDIACTIONFORMATW lpDiAfW0, LPDIACTIONFORMATW* lplpDiAfW);
void FreeDiActionFormatW(LPDIACTIONFORMATW* lplpDiAfW );
void EXTERNAL ObjectInfoWToA(LPDIDEVICEOBJECTINSTANCEA pdoiA, LPCDIDEVICEOBJECTINSTANCEW pdoiW);
void EXTERNAL EffectInfoWToA(LPDIEFFECTINFOA pdeiA, LPCDIEFFECTINFOW pdeiW);
#ifndef XDEBUG
#define hresFindInstanceGUID_(pGUID, pcdcb, z, i) \
_hresFindInstanceGUID_(pGUID, pcdcb) \
#define hresValidInstanceVer_(hinst, dwVer, z) \
_hresValidInstanceVer_(hinst, dwVer) \
#endif
HRESULT EXTERNAL hresFindInstanceGUID_(PCGUID pGUID, CREATEDCB *pcdcb, LPCSTR s_szProc, int iarg);
HRESULT EXTERNAL hresValidInstanceVer_(HINSTANCE hinst, DWORD dwVersion, LPCSTR s_szProc);
#define hresFindInstanceGUID(pGuid, pcdcb, iarg) \
hresFindInstanceGUID_(pGuid, pcdcb, s_szProc, iarg) \
#define hresValidInstanceVer(hinst, dwVer) \
hresValidInstanceVer_(hinst, dwVer, s_szProc) \
HRESULT EXTERNAL DupEventHandle(HANDLE h, LPHANDLE phOut); DWORD EXTERNAL GetWindowPid(HWND hwnd);
PV EXTERNAL pvFindResource(HINSTANCE hinst, DWORD id, LPCTSTR rt);
void EXTERNAL GetNthString(LPWSTR pwsz, UINT ids, UINT ui);
#define GetNthButtonString(pwsz, ui) \
GetNthString(pwsz, IDS_BUTTONTEMPLATE, ui)
#define GetNthAxisString(pwsz, ui) \
GetNthString(pwsz, IDS_AXISTEMPLATE, ui)
#define GetNthPOVString(pwsz, ui) \
GetNthString(pwsz, IDS_POVTEMPLATE, ui)
HRESULT EXTERNAL hresDupPtszPptsz(LPCTSTR ptszSrc, LPTSTR *pptszDst);
BOOL EXTERNAL fInitializeCriticalSection(LPCRITICAL_SECTION pCritSec);
void EXTERNAL DiCharUpperW(LPWSTR pwsz);
typedef int ( __stdcall * COMP_FUNC )( PV, PV );
void ptrPartialQSort( PPV ppL, PPV ppR, COMP_FUNC fpCompare );
void ptrInsertSort( PPV ppBase, PPV ppLast, COMP_FUNC fpCompare );
void __cdecl shortsort (char *lo,char *hi,unsigned width,int (__cdecl *comp)(const void *, const void *));
STDMETHODIMP GetWideUserName ( LPCSTR lpszUserName, LPCWSTR lpwszUserName, LPWSTR *ppwszGoodUserName );
DWORD EXTERNAL GetValidDI8DevType ( DWORD dwDevType, DWORD dwNumButtons, DWORD dwFlags );
HRESULT DIGetKeyNameText( UINT index, DWORD dwDevType, LPWSTR lpwszName, int nSize );
#define WIN_UNKNOWN_OS 0
#define WIN95_OS 1
#define WIN98_OS 2
#define WINME_OS 3
#define WINNT_OS 4
#define WINWH_OS 5
DWORD INTERNAL DIGetOSVersion();
/*****************************************************************************
* * dilist.c * *****************************************************************************/
/*****************************************************************************
* * @doc INTERNAL * * @struct GPA | * * Growable pointer array. * * @field PPV | rgpv | * * The base of the array of pointers. * * @field int | cpv | * * The number of pointers in use in the array. * * @field int | cpvAlloc | * * The number of pointers allocated in the array. * *****************************************************************************/
typedef struct GPA {
PPV rgpv; int cpv; int cpvAlloc;
} GPA, *HGPA;
void EXTERNAL GPA_Init(HGPA hgpa); void EXTERNAL GPA_Term(HGPA hgpa);
STDMETHODIMP GPA_Append(HGPA hgpa, PV pv); BOOL EXTERNAL GPA_FindPtr(HGPA hgpa, PV pv); STDMETHODIMP GPA_DeletePtr(HGPA hgpa, PV pv); STDMETHODIMP GPA_Clone(HGPA hgpaDst, HGPA hgpaSrc);
/*****************************************************************************
* * @doc INTERNAL * * @func void | GPA_InitFromZero | * * Initialize a GPA structure that is already zero-initialized. * * @parm HGPA | hgpa | * * Handle to pointer array. * *****************************************************************************/
/*
* Nothing needs to be done; zero-init is just fine. * * Note: didev.c also has a global GPA, and it assumes that zero-init * is just fine. */ #define GPA_InitFromZero(hgpa)
/*****************************************************************************
* * dioledup.c * *****************************************************************************/
STDMETHODIMP DICoCreateInstance(LPTSTR ptszClsid, LPUNKNOWN punkOuter, RIID riid, PPV ppvOut, HINSTANCE *phinst);
/*****************************************************************************
* * diexcl.c - Exclusive access management * * We also keep GUID uniqueness goo up here, because it is * diexcl.c that manages shared memory. * *****************************************************************************/
STDMETHODIMP Excl_Acquire(PCGUID pguid, HWND hwnd, DWORD discl); void EXTERNAL Excl_Unacquire(PCGUID pguid, HWND hwnd, DWORD discl); STDMETHODIMP Excl_Init(void);
LONG EXTERNAL Excl_UniqueGuidInteger(void); DWORD EXTERNAL Excl_GetConfigChangedTime(); void EXTERNAL Excl_SetConfigChangedTime(DWORD tm);
/*****************************************************************************
* * @doc INTERNAL * * @struct GLOBALJOYSTATE | * * Structure that records global joystick state information. * * @field DWORD | dwTag | * * Counter used to keep track of how many times each joystick's * force feedback driver has been reset. This is used to make * sure that nobody messes with a joystick that he doesn't own. * * Each time the joystick is reset, the corresponding counter * is incremented. Before we do anything to a device, we check * if the reset counter matches the value stored in the * object. If not, then it means that the device has been * reset in the meantime and no longer belongs to the caller. * * @field DWORD | dwCplGain | * * Control panel (global) gain setting for the joystick. * * @field DWORD | dwDevGain | * * Most recent device (local) gain applied to the joystick. * * This is cached so that when the global gain changes, * we know what physical gain to apply as a result. * *****************************************************************************/
typedef struct GLOBALJOYSTATE { DWORD dwTag; DWORD dwCplGain; DWORD dwDevGain; } GLOBALJOYSTATE, *PGLOBALJOYSTATE;
/*****************************************************************************
* * @doc INTERNAL * * @struct SHAREDOBJECTHEADER | * * A simple header comes in front of the array of objects. * * WARNING! This structure may not change between DEBUG and * RETAIL. Otherwise, you have problems if one DirectInput * app is using DEBUG and another is using RETAIL. * * The global <c g_gsop> variable points to one of these things, * suitably cast. * * @field int | cso | * * Number of <t SHAREDOBJECT>s currently in use. The array * is kept packed for simplicity. * * @field DWORD | dwSequence | * * Global sequence number used during data collection. * (Not used if we have a VxD to manage a "really global" * sequence number.) * * @field int | cguid | * * Unique integer for GUID generation. * * @field DWORD | rgdwJoy[cMaxJoy] | * * Counter used to keep track of how many times each joystick's * force feedback driver has been reset. This is used to make * sure that nobody messes with a joystick that they don't own. * * Each time the joystick is reset, the corresponding counter * is incremented. Before we do anything to a device, we check * if the reset counter matches the value stored in the * object. If not, then it means that the device has been * reset in the meantime and no longer belongs to the caller. * * Note! We support up to 16 joysticks. Hope that'll be enough * for a while. * * @field GLOBALJOYSTATE | rggjs[cMaxJoy] | * * Global settings for each joystick. * * @field DWORD | tmConfigChanged * * The tick count of last config changed. * *****************************************************************************/
#define cJoyMax 16 /* Up to 16 joysticks */
typedef struct SHAREDOBJECTHEADER { int cso; DWORD dwSequence; int cguid; GLOBALJOYSTATE rggjs[cJoyMax]; DWORD tmConfigChanged; } SHAREDOBJECTHEADER, *PSHAREDOBJECTHEADER;
#define g_psoh ((PSHAREDOBJECTHEADER)g_psop)
/*****************************************************************************
* * @doc INTERNAL * * @topic The Worker Thread | * * Some emulation behaviors (low-level hooks, HID) require * a worker thread to do the data collection. We multiplex * all such work onto a single worker thread (known as * simple "the" worker thread). * * The thread is spun up when the first client needs it * and is taken down when the last client has been released. * * To prevent race conditions from crashing us, we addref * our DLL when the thread exists and have the thread * perform a FreeLibrary as its final act. * *****************************************************************************/
#define WORKER_THREAD
/*****************************************************************************
* * diem.c - Emulation * *****************************************************************************/
HRESULT EXTERNAL CEm_AcquireInstance(PVXDINSTANCE *ppvi); HRESULT EXTERNAL CEm_UnacquireInstance(PVXDINSTANCE *ppvi); HRESULT EXTERNAL CEm_SetBufferSize(PVXDDWORDDATA pvdd); HRESULT EXTERNAL CEm_DestroyInstance(PVXDINSTANCE *ppvi);
HRESULT EXTERNAL CEm_SetDataFormat(PVXDDATAFORMAT pvdf);
HRESULT EXTERNAL CEm_Mouse_CreateInstance(PVXDDEVICEFORMAT pdevf, PVXDINSTANCE *ppviOut);
HRESULT EXTERNAL CEm_Mouse_InitButtons(PVXDDWORDDATA pvdd);
HRESULT EXTERNAL CEm_Kbd_CreateInstance(PVXDDEVICEFORMAT pdevf, PVXDINSTANCE *ppviOut);
HRESULT EXTERNAL CEm_Kbd_InitKeys(PVXDDWORDDATA pvdd);
HRESULT EXTERNAL CEm_Joy_CreateInstance(PVXDDEVICEFORMAT pdevf, PVXDINSTANCE *ppviOut);
HRESULT EXTERNAL CEm_Joy_Ping(PVXDINSTANCE *ppvi);
HRESULT EXTERNAL CEm_HID_CreateInstance(PVXDDEVICEFORMAT pdevf, PVXDINSTANCE *ppviOut);
/*****************************************************************************
* * diemm.c - Mouse Emulation * *****************************************************************************/
void EXTERNAL CEm_Mouse_AddState(LPDIMOUSESTATE_INT pms, DWORD tm);
/*****************************************************************************
* * dinput.c - Basic DLL stuff * *****************************************************************************/
void EXTERNAL DllEnterCrit_(LPCTSTR lptszFile, UINT line); void EXTERNAL DllLeaveCrit_(LPCTSTR lptszFile, UINT line);
#ifdef DEBUG
BOOL EXTERNAL DllInCrit(void); #define DllEnterCrit() DllEnterCrit_(TEXT(__FILE__), __LINE__)
#define DllLeaveCrit() DllLeaveCrit_(TEXT(__FILE__), __LINE__)
#else
#define DllEnterCrit() DllEnterCrit_(NULL, 0x0)
#define DllLeaveCrit() DllLeaveCrit_(NULL, 0x0)
#endif
void EXTERNAL DllAddRef(void); void EXTERNAL DllRelease(void);
BOOL EXTERNAL DllLoadLibrary(void); void EXTERNAL DllFreeLibrary(void);
#ifdef DEBUG
extern UINT g_thidCrit;
#define InCrit() (g_thidCrit == GetCurrentThreadId())
#endif
/*
* Describes the CLSIDs we provide to OLE. */
typedef STDMETHOD(CREATEFUNC)(PUNK punkOuter, RIID riid, PPV ppvOut);
typedef struct CLSIDMAP { REFCLSID rclsid; /* The clsid */ CREATEFUNC pfnCreate; /* How to create it */ UINT ids; /* String that describes it */ } CLSIDMAP, *PCLSIDMAP;
#ifdef DEBUG
#define DEMONSTRATION_FFDRIVER
#ifdef DOWNLEVEL_COM
#define cclsidmap 5 /* DirectInput, DirectInputDevice, DirectInput8, DirectInputDevice8, DIEffectDiver */
#else
#define cclsidmap 3 /* DirectInput8, DirectInputDevice8, DIEffectDiver */
#endif
#else
#ifdef DOWNLEVEL_COM
#define cclsidmap 4 /* CLSID_DirectInput, CLSID_DirectInputDevice, CLSID_DirectInput8, CLSID_DirectInputDevice8 */
#else
#define cclsidmap 2 /* CLSID_DirectInput8, CLSID_DirectInputDevice8 */
#endif
#endif
extern CLSIDMAP c_rgclsidmap[cclsidmap];
/*****************************************************************************
* * dicf.c - IClassFactory implementation * *****************************************************************************/
STDMETHODIMP CDIFactory_New(CREATEFUNC pfnCreate, RIID riid, PPV ppvObj);
/*****************************************************************************
* * didenum.c - IDirectInput device enumeration * *****************************************************************************/ typedef struct _CDIDEnum CDIDEnum;
extern GUID rgGUID_Joystick[cJoyMax];
#define GUID_Joystick (rgGUID_Joystick[0])
void EXTERNAL CDIDEnum_Release(CDIDEnum *pde); STDMETHODIMP CDIDEnum_Next(CDIDEnum *pde, LPDIDEVICEINSTANCEW pddiW); STDMETHODIMP CDIDEnum_InternalNext(CDIDEnum *pde, LPDIDEVICEINSTANCEW pddiW, LPDIRECTINPUTDEVICE8W *ppdid8W); STDMETHODIMP CDIDEnum_New(PDIW pdiW, DWORD dwDevType, DWORD edfl, DWORD dwVer, CDIDEnum **);
/*****************************************************************************
* * diobj.c - IDirectInput implementation * *****************************************************************************/
HRESULT EXTERNAL CDIObj_TestDeviceFlags(PDIDW pdidW, DWORD diedfl); HRESULT EXTERNAL CDIObj_TestDeviceFlagsInternal(PDIDW pdidW, DWORD diedfl); HRESULT EXTERNAL CDIObj_FindDeviceInternal(LPCTSTR ptszName, LPGUID pguidOut);
STDMETHODIMP CDIObj_New(PUNK punkOuter, RIID riid, PPV ppvOut);
typedef struct _DIMAPPER { LPCWSTR lpszUserName; LPDIACTIONFORMATW pDiActionFormat; LPDIENUMDEVICESBYSEMANTICSCBW pecW; LPVOID pvRef; DWORD dwFlags; } DIMAPPER, *LPDIMAPPER;
typedef struct _DIORDERDEV { DWORD dwOrder; DWORD dwFlags; LPDIRECTINPUTDEVICE8W pdid8W; DIDEVICEINSTANCEW ddiW; FILETIME ftTimeStamp; } DIORDERDEV, *LPDIORDERDEV;
/*****************************************************************************
* * diaddhw.c - AddNewHardware * *****************************************************************************/
HRESULT EXTERNAL AddNewHardware(HWND hwnd, REFGUID rguid);
/*****************************************************************************
* * dijoycfg.c - IDirectInputJoyConfig implementation * *****************************************************************************/
STDMETHODIMP CJoyCfg_New(PUNK punkOuter, RIID riid, PPV ppvOut);
/*****************************************************************************
* * @doc INLINE * * @method BOOL | IsWriteSam | * * Nonzero if the registry security access mask will * obtain (or attempt to obtain) write access. * * @parm REGSAM | regsam | * * Registry security access mask. * *****************************************************************************/
BOOL INLINE IsWriteSam(REGSAM sam) { return sam & (KEY_SET_VALUE | KEY_CREATE_SUB_KEY | MAXIMUM_ALLOWED); }
/*****************************************************************************
* * dijoyreg.c - Joystick registry services * *****************************************************************************/ extern LPCWSTR c_rghwIdPredef[];
STDMETHODIMP JoyReg_OpenTypeKey(LPCWSTR pwszType, DWORD sam, DWORD dwOptions, PHKEY phk); STDMETHODIMP JoyReg_OpenPropKey(LPCWSTR pwszType, DWORD sam, DWORD dwOptions, PHKEY phk); STDMETHODIMP JoyReg_OpenFFKey(HKEY hkType, REGSAM sam, PHKEY phk);
STDMETHODIMP JoyReg_OpenConfigKey(UINT idJoy, DWORD sam, DWORD dwOptions, PHKEY phk);
STDMETHODIMP JoyReg_GetTypeInfo(LPCWSTR pwszType, LPDIJOYTYPEINFO pjti, DWORD fl); STDMETHODIMP JoyReg_SetTypeInfo(HKEY hkTypesW, LPCWSTR pwszType, LPCDIJOYTYPEINFO pjti, DWORD fl);
STDMETHODIMP JoyReg_GetConfig(UINT idJoy, LPDIJOYCONFIG pcfg, DWORD fl); STDMETHODIMP JoyReg_SetConfig(UINT idJoy, LPJOYREGHWCONFIG phwc, LPCDIJOYCONFIG pcfg, DWORD fl);
STDMETHODIMP JoyReg_GetUserValues(LPDIJOYUSERVALUES pjuv, DWORD fl); STDMETHODIMP JoyReg_SetUserValues(LPCDIJOYUSERVALUES pjuv, DWORD fl);
STDMETHODIMP JoyReg_GetSetConfigValue(HKEY hk, LPCTSTR ptszNValue, UINT idJoy, DWORD reg, PV pvBuf, DWORD cb, BOOL fSet);
#define GSCV_GET 0
#define GSCV_SET 1
#define JoyReg_GetConfigValue(hk, ptsz, id, reg, pv, cb) \
JoyReg_GetSetConfigValue(hk, ptsz, id, reg, pv, cb, GSCV_GET)
#define JoyReg_SetConfigValue(hk, ptsz, id, reg, pv, cb) \
JoyReg_GetSetConfigValue(hk, ptsz, id, reg, (PV)(pv), cb, GSCV_SET)
STDMETHODIMP JoyReg_GetValue(HKEY hk, LPCTSTR ptszValue, DWORD reg, PV pvBuf, DWORD cb);
#ifndef WINNT
STDMETHODIMP JoyReg_IsWdmGameport(HKEY hk); #endif
#if 0
STDMETHODIMP JoyReg_IsWdmGameportFromDeviceInstance( LPTSTR ptszDeviceInst ); #endif
STDMETHODIMP JoyReg_SetValue(HKEY hk, LPCTSTR ptszValue, DWORD reg, PCV pvBuf, DWORD cb);
#ifndef WINNT
LPSTR EXTERNAL JoyReg_JoyIdToDeviceInterface_95(UINT idJoy, PVXDINITPARMS pvip, LPSTR ptszBuf); #endif
HRESULT EXTERNAL JoyReg_GetPredefTypeInfo(LPCWSTR pwszType, LPDIJOYTYPEINFO pjti, DWORD fl);
HRESULT EXTERNAL hResIdJoypInstanceGUID_95( UINT idJoy, LPGUID lpguid);
HRESULT EXTERNAL hResIdJoypInstanceGUID_WDM( UINT idJoy, LPGUID lpguid);
#ifdef WINNT
#define hResIdJoypInstanceGUID(id,lpguid) hResIdJoypInstanceGUID_WDM(id, lpguid)
#else
#define hResIdJoypInstanceGUID(id,lpguid) hResIdJoypInstanceGUID_95(id, lpguid)
#endif
#if 0
HRESULT EXTERNAL JoyReg_GetIDByOemName( LPTSTR szOemName, PUINT pId ); #endif
/*****************************************************************************
* * didev.c - IDirectInputDevice implementation * *****************************************************************************/
void EXTERNAL DeviceInfoWToA(LPDIDEVICEINSTANCEA pdiA, LPCDIDEVICEINSTANCEW pdiW);
void EXTERNAL Device8WTo8A(LPDIRECTINPUTDEVICE8A *ppdid8A, LPDIRECTINPUTDEVICE8W pdid8W);
STDMETHODIMP CDIDev_New(PUNK punkOuter, RIID riid, PPV ppvObj);
/*****************************************************************************
* * CDIDev_Enter/LeaveCrit are secret backdoors to allow emulation * and effects * to take the device critical section when updating buffers. * * CDIDev_InCrit is used for assertion checking. * * CDIDev_IsExclAcquired is used by effects to make sure the parent * is acquired for exclusive before attempting to download. * * CDIDev_SyncShepHandle is used to get the joystick "tag" which * is used by dieshep.c to determine who owns the joystick. * *****************************************************************************/
void EXTERNAL CDIDev_EnterCrit_(struct CDIDev *this, LPCTSTR lptszFile, UINT line); void EXTERNAL CDIDev_LeaveCrit_(struct CDIDev *this, LPCTSTR lptszFile, UINT line);
#ifdef DEBUG
BOOL INTERNAL CDIDev_InCrit(struct CDIDev *this); #define CDIDev_EnterCrit(cdidev) CDIDev_EnterCrit_(cdidev, TEXT(__FILE__), __LINE__)
#define CDIDev_LeaveCrit(cdidev) CDIDev_LeaveCrit_(cdidev, TEXT(__FILE__), __LINE__)
#else
#define CDIDev_EnterCrit(cdidev) CDIDev_EnterCrit_(cdidev, NULL, 0x0);
#define CDIDev_LeaveCrit(cdidev) CDIDev_LeaveCrit_(cdidev, NULL, 0x0);
#endif
#ifndef XDEBUG
#define CDIDev_IsExclAcquired_(pdd, z) \
_CDiDev_IsExclAcquired_(pdd) \
#endif
STDMETHODIMP CDIDev_IsExclAcquired_(struct CDIDev *this, LPCSTR s_szProc);
#define CDIDev_IsExclAcquired(pdd) \
CDIDev_IsExclAcquired_(pdd, s_szProc) \
STDMETHODIMP CDIDev_SyncShepHandle(struct CDIDev *this, PSHEPHANDLE psh);
/*****************************************************************************
* * CDIDev_SetNotifyEvent is used by the emulation code to * notify the application when the state of the device changes. * *****************************************************************************/
void EXTERNAL CDIDev_SetNotifyEvent(struct CDIDev *this); void EXTERNAL CDIDev_SetForcedUnacquiredFlag(struct CDIDev *this);
/*****************************************************************************
* * CDIDev_NotifyCreate/DestroyEvent is used by CDIEff to * let the parent know when a child effect comes or goes. * * CDIDev_FindEffectGUID is used by CDIEff to convert an * effect GUID into an effect cookie dword. * * CDIDev_ConvertObjects converts item identifiers in various ways. * *****************************************************************************/
HRESULT EXTERNAL CDIDev_NotifyCreateEffect(struct CDIDev *this, struct CDIEff *pdeff); HRESULT EXTERNAL CDIDev_NotifyDestroyEffect(struct CDIDev *this, struct CDIEff *pdeff);
/*****************************************************************************
* * @doc INTERNAL * * @struct EFFECTMAPINFO | * * Information about an effect, much like a * <t DIEFFECTINFO>, but containing the * effect ID, too. * * @field DWORD | dwId | * * The effect ID. This comes first so we can copy * an <t EFFECTMAPINFO> into a <t DIEFFECTINFO> * all at one go. * * @field GUID | guid | * * The effect GUID. * * @field DWORD | dwEffType | * * The effect type and flags. * * @field WCHAR | wszName[MAX_PATH] | * * The name for the effect. * *****************************************************************************/
typedef struct EFFECTMAPINFO { DIEFFECTATTRIBUTES attr; GUID guid; WCHAR wszName[MAX_PATH]; } EFFECTMAPINFO, *PEFFECTMAPINFO; typedef const EFFECTMAPINFO *PCEFFECTMAPINFO;
#ifndef XDEBUG
#define CDIDev_FindEffectGUID_(this, rguid, pemi, z, i) \
_CDIDev_FindEffectGUID_(this, rguid, pemi) \
#endif
#define CDIDev_FindEffectGUID(this, rguid, pemi, iarg) \
CDIDev_FindEffectGUID_(this, rguid, pemi, s_szProc, iarg) \
STDMETHODIMP CDIDev_FindEffectGUID_(struct CDIDev *this, REFGUID rguid, PEFFECTMAPINFO pemi, LPCSTR s_szProc, int iarg);
STDMETHODIMP CDIDev_ConvertObjects(struct CDIDev *this, UINT cdw, LPDWORD rgdw, UINT fl);
/*
* Note that the bonus DEVCO flags live inside the DIDFT_INSTANCEMASK. */ #define DEVCO_AXIS DIDFT_AXIS
#define DEVCO_BUTTON DIDFT_BUTTON
#define DEVCO_TYPEMASK DIDFT_TYPEMASK
#define DEVCO_FFACTUATOR DIDFT_FFACTUATOR
#define DEVCO_FFEFFECTTRIGGER DIDFT_FFEFFECTTRIGGER
#define DEVCO_ATTRMASK DIDFT_ATTRMASK
#define DEVCO_FROMID 0x00000100
#define DEVCO_FROMOFFSET 0x00000200
#define DEVCO_FROMMASK 0x00000300
#define DEVCO_TOID 0x00001000
#define DEVCO_TOOFFSET 0x00002000
#define DEVCO_TOMASK 0x00003000
#if ((DEVCO_FROMMASK | DEVCO_TOMASK) & DIDFT_INSTANCEMASK) != \
(DEVCO_FROMMASK | DEVCO_TOMASK) #error DEVCO_FROMMASK and DEVCI_TOMASK should not escape DIDFT_INSTANCEMASK.
#endif
#define DEVCO_VALID (DEVCO_TYPEMASK | \
DEVCO_ATTRMASK | \ DEVCO_FROMMASK | \ DEVCO_TOMASK)
/*****************************************************************************
* * dieffv.c - IDirectInputEffectDriver for VJoyD joysticks * *****************************************************************************/
STDMETHODIMP CEffVxd_New(PUNK punkOuter, RIID riid, PPV ppvOut);
/*****************************************************************************
* * dieshep.c - IDirectInputEffectShepherd * *****************************************************************************/
STDMETHODIMP CEShep_New(HKEY hk, PUNK punkOuter, RIID riid, PPV ppvOut);
/*****************************************************************************
* * digendef.c - Default IDirectInputDeviceCallback * *****************************************************************************/
/*
* We can't call it a DCB because winbase.h already has one for * comm goo. */
typedef IDirectInputDeviceCallback DICB, *PDICB;
STDMETHODIMP CDefDcb_Acquire(PDICB pdcb);
STDMETHODIMP CDefDcb_Unacquire(PDICB pdcb);
STDMETHODIMP CDefDcb_GetProperty(PDICB pdcb, LPCDIPROPINFO ppropi, LPDIPROPHEADER pdiph);
STDMETHODIMP CDefDcb_SetProperty(PDICB pdcb, LPCDIPROPINFO ppropi, LPCDIPROPHEADER pdiph);
STDMETHODIMP CDefDcb_SetEventNotification(PDICB pdcb, HANDLE h);
STDMETHODIMP CDefDcb_SetCooperativeLevel(PDICB pdcb, HWND hwnd, DWORD dwFlags);
STDMETHODIMP CDefDcb_CookDeviceData(PDICB pdcb, DWORD cdod, LPDIDEVICEOBJECTDATA rgdod);
STDMETHODIMP CDefDcb_CreateEffect(PDICB pdcb, LPDIRECTINPUTEFFECTSHEPHERD *ppes);
STDMETHODIMP CDefDcb_GetFFConfigKey(PDICB pdcb, DWORD sam, PHKEY phk);
STDMETHODIMP CDefDcb_SendDeviceData(PDICB pdcb, DWORD cbdod, LPCDIDEVICEOBJECTDATA rgdod, LPDWORD pdwInOut, DWORD fl);
STDMETHODIMP CDefDcb_Poll(IDirectInputDeviceCallback *pdcb);
STDMETHODIMP CDefDcb_GetVersions(IDirectInputDeviceCallback *pdcb, LPDIDRIVERVERSIONS pvers);
STDMETHODIMP CDefDcb_MapUsage(IDirectInputDeviceCallback *pdcb, DWORD dwUsage, PINT piOut);
STDMETHODIMP_(DWORD) CDefDcb_GetUsage(IDirectInputDeviceCallback *pdcb, int iobj);
STDMETHODIMP CDefDcb_SetDIData(PDICB pdcb, DWORD dwVer, LPVOID lpdihacks);
STDMETHODIMP CDefDcb_BuildDefaultActionMap(PDICB pdcb, LPDIACTIONFORMATW pActionFormat, DWORD dwFlags, REFGUID guidInst);
/*****************************************************************************
* * digenx.c - IDirectInputDeviceCallback that does nothing * *****************************************************************************/
extern IDirectInputDeviceCallback c_dcbNil;
#define c_pdcbNil &c_dcbNil
/*****************************************************************************
* * digenm.c - IDirectInputDeviceCallback for mouse * *****************************************************************************/
STDMETHODIMP CMouse_New(PUNK punkOuter, REFGUID rguid, RIID riid, PPV ppvOut);
/*****************************************************************************
* * digenk.c - IDirectInputDeviceCallback for keyboard * *****************************************************************************/ extern BYTE g_rgbKbdRMap[]; STDMETHODIMP CKbd_New(PUNK punkOuter, REFGUID rguid, RIID riid, PPV ppvOut);
/*****************************************************************************
* * digenj.c - IDirectInputDeviceCallback for joystick * *****************************************************************************/
STDMETHODIMP CJoy_New(PUNK punkOuter, REFGUID rguid, RIID riid, PPV ppvOut);
/*****************************************************************************
* * @doc INTERNAL * * @func UINT | ibJoyPosAxisFromPosAxis | * * Returns the offset of the <p iAxis>'th joystick axis * in the <t JOYPOS> structure. * * @parm UINT | uiAxis | * * The index of the requested axis. X, Y, Z, R, U and V are * respctively zero through five. * * @returns * * The offset relative to the structure. * *****************************************************************************/
#define _ibJoyPosAxisFromPosAxis(uiAxis) \
(FIELD_OFFSET(JOYPOS, dwX) + cbX(DWORD) * (uiAxis))
UINT INLINE ibJoyPosAxisFromPosAxis(UINT uiPosAxis) { #define CheckAxis(x) \
CAssertF(_ibJoyPosAxisFromPosAxis(iJoyPosAxis##x) \ == FIELD_OFFSET(JOYPOS, dw##x)) \
CheckAxis(X); CheckAxis(Y); CheckAxis(Z); CheckAxis(R); CheckAxis(U); CheckAxis(V);
#undef CheckAxis
return _ibJoyPosAxisFromPosAxis(uiPosAxis); }
/*****************************************************************************
* * dieffj.c - Dummy IDirectInputEffectDriver for joystick * *****************************************************************************/
STDMETHODIMP CJoyEff_New(PUNK punkOuter, RIID riid, PPV ppvOut);
/*****************************************************************************
* * dihid.c - IDirectInputDeviceCallback for generic HID devices * *****************************************************************************/ STDMETHODIMP CHid_New(PUNK punkOuter, REFGUID rguid, RIID riid, PPV ppvOut);
/*****************************************************************************
* * dieff.c - IDirectInputEffect implementation * *****************************************************************************/
STDMETHODIMP CDIEff_New(struct CDIDev *pdev, LPDIRECTINPUTEFFECTSHEPHERD pes, PUNK punkOuter, RIID riid, PPV ppvObj);
/*****************************************************************************
* * dihidusg.c - HID usage converters * *****************************************************************************/
/*****************************************************************************
* * @doc INTERNAL * * @struct HIDUSAGEMAP | * * This structure maps HID usages to GUIDs * or legacy joystick axes. * * @field DWORD | dwUsage | * * Packed usage via <f DIMAKEUSAGEDWORD>. * * @field BYTE | bPosAxis | * * <t JOYPOS> axis number, where 0 = X, 1 = Y, ..., 5 = V. * * @field BYTE | bSemFlag | * * DISEM_FLAGS_* value for axis. * * @field BYTE | bReserved1 | * * Byte reserved to improve alignment * * @field BYTE | bReserved2 | * * Byte reserved to improve alignment * * @field DWORD | dwSemHint | * * A root of a semantic generally appropriate for this axis. * * @field PCGUID | pguid | * * Corresponding <t GUID>. * *****************************************************************************/
typedef struct HIDUSAGEMAP {
DWORD dwUsage; BYTE bPosAxis; BYTE bSemFlag; BYTE bReserved1; BYTE bReserved2; DWORD dwSemHint; PCGUID pguid;
} HIDUSAGEMAP, *PHIDUSAGEMAP;
PHIDUSAGEMAP EXTERNAL UsageToUsageMap(DWORD dwUsage);
/*
* Flags defined for dwSemHint * The names have the same suffixes as the equivalent HID usages * Values are ORed together for a summary of a device's default semantics */ #define DISEM_HINT_X 0x00000001
#define DISEM_HINT_Y 0x00000002
#define DISEM_HINT_Z 0x00000004
#define DISEM_HINT_WHEEL 0x00000004
#define DISEM_HINT_RX 0x00000008
#define DISEM_HINT_RY 0x00000010
#define DISEM_HINT_RZ 0x00000020
#define DISEM_HINT_SIXDOF 0x0000003F
#define DISEM_HINT_THROTTLE 0x00000040
#define DISEM_HINT_POV 0x00000080
#define DISEM_HINT_HATSWITCH 0x00000080
#define DISEM_HINT_ACCELERATOR 0x00000100
#define DISEM_HINT_BRAKE 0x00000200
#define DISEM_HINT_CLUTCH 0x00000400
#define DISEM_HINT_SHIFTER 0x00000800
#define DISEM_HINT_STEERING 0x00001000
#define DISEM_HINT_RUDDER 0x00002000
#define DISEM_HINT_SLIDER 0x00004000
#define DISEM_HINT_DIAL 0x00004000
#define DISEM_HINT_ABSOLUTE 0x00008000
DWORD EXTERNAL GuidToUsage(PCGUID pguid);
UINT EXTERNAL GetHIDString(DWORD Usage, DWORD UsagePage, LPWSTR pwszBuf, UINT cwch);
void EXTERNAL InsertCollectionNumber(UINT icoll, LPWSTR pwszBuf);
/*****************************************************************************
* * disubcls.c - Subclassing * *****************************************************************************/
typedef LRESULT (CALLBACK *SUBCLASSPROC)(HWND hwnd, UINT wm, WPARAM wp, LPARAM lp, UINT_PTR uId, ULONG_PTR dwRef);
BOOL EXTERNAL SetWindowSubclass(HWND hwnd, SUBCLASSPROC pfnSubclass, UINT_PTR uId, ULONG_PTR dwRef);
BOOL EXTERNAL GetWindowSubclass(HWND hwnd, SUBCLASSPROC pfnSubclass, UINT_PTR uId, ULONG_PTR *pdwRef);
BOOL EXTERNAL RemoveWindowSubclass(HWND hwnd, SUBCLASSPROC pfnSubclass, UINT_PTR uId);
LRESULT EXTERNAL DefSubclassProc(HWND hwnd, UINT wm, WPARAM wp, LPARAM lp);
/*****************************************************************************
* * dical.c - Axis ramps and calibration * * Structure names begin with "Joy" for historical reasons. * *****************************************************************************/
#if defined(_X86_)
LONG EXTERNAL CCal_MulDiv(LONG lA, LONG lB, LONG lC);
#else
#define CCal_MulDiv MulDiv
#endif
/*****************************************************************************
* * @doc INTERNAL * * @struct JOYRAMP | * * Parameters for a "ramp". A ramp looks like this: * * r ! * e dy - *--- * t ! / * u ! / * r ! / * n y ---* * e ! * d +--!---!--- * x dx * * physical position * * * y, dy = baseline and height * * x, dx = initiation level and width * * The mapping is * * * (-infty, x ] -> y * (x, x+dx ) -> (y, y+dy) * [x+dx, infty) -> y+dy * * It is very important that the middle range not be taken * if dx = 0. * * @field int | x | * * Horizontal value below which we return the baseline. * * @field DWORD | dx | * * Width of the ramp. Beyond this point, we return the * full height. * * @field int | y | * * Baseline. * * @field int | dy | * * Total height. * *****************************************************************************/
typedef struct JOYRAMP {
int x; int y; DWORD dx; int dy;
} JOYRAMP, *PJOYRAMP;
typedef const JOYRAMP *PCJOYRAMP;
/*****************************************************************************
* * @doc INTERNAL * * @struct JOYRANGECONVERT | * * Parameters for range conversion. * * The conversion curve is in five sections. * * * * ! * lmax- *---- * r ! / * e ! / * t ! / * u lc- *------* * r ! / * n ! / * e ! / * d lmin-------* * ! * +-!----!---!------!----!----!-- * pmin smin dmin dmax smax pmax * * ! * pc * * * physical position * * * lmin/lmax = logical min/max - This is the smallest/largest * position the app will ever see. * * lc = logical center * * pmin/pmax = physical min/max - This is the position determined by * calibration to be the value which the hardware reports * when the device is physically at its bottom/upper limit. Note * that the hardware might report values outside this range. * * pc = physical center - This is the nominal neutral location for * the axis * * dmin/dmax = dead zone min/max - This is the zone around which * the center is artificially expanded. * * smin/smax = saturation min/max - This is the level at which * we treat the axis as being at its most extreme position. * * @field BOOL | fRaw | * * Is the axis in raw mode? If so, then no cooking is performed. * * @field JOYRAMP | rmpLow | * * The ramp for below-center. * * @field JOYRAMP | rmpHigh | * * The ramp for above-center. * * @field DWORD | dwPmin | * * Physical minimum. * * @field DWORD | dwPmax | * * Physical maximum. * * @field LONG | lMin | * * Logical minimum. * * @field LONG | lCenter | * * Logical center. * * @field LONG | lMax | * * Logical maximum. * * @field DWORD | dwPc | * * Physical center. * * @field DWORD | dwDz | * * Dead zone (in ten thousandths, 10000 = 100%). * * @field DWORD | dwSat | * * Saturation level (in ten thousands, 10000 = 100%). * * @field BOOL | fPolledPOV | * * Whether the axis is a polled POV. Usable only when the axis is a POV. * * @field LONG | lMinPOV[5] | * * Mininum ranges of POV directions. Usable only when the axis is a POV. * * @field LONG | lMaxPOV[5] | * * Maxinum ranges of POV directions. Usable only when the axis is a POV. * * *****************************************************************************/
/*
* Number of range divisions. We work in ten thousandths. */ #define RANGEDIVISIONS 10000
typedef struct JOYRANGECONVERT {
BOOL fRaw; JOYRAMP rmpLow; JOYRAMP rmpHigh;
DWORD dwPmin; DWORD dwPmax; DWORD dwPc; LONG lMin; LONG lMax; LONG lC; DWORD dwDz; DWORD dwSat;
DWORD dwCPointsNum; CPOINT cp[MAXCPOINTSNUM]; //4 is for deadzone(2) and saturation(2)
#ifdef WINNT
BOOL fPolledPOV; LONG lMinPOV[5]; LONG lMaxPOV[5]; #endif
} JOYRANGECONVERT, *PJOYRANGECONVERT;
typedef const JOYRANGECONVERT *PCJOYRANGECONVERT;
/*****************************************************************************
* * dical.c functions * *****************************************************************************/
void EXTERNAL CCal_CookRange(PJOYRANGECONVERT this, LONG UNALIGNED *pl); void EXTERNAL CCal_RecalcRange(PJOYRANGECONVERT this);
STDMETHODIMP CCal_GetProperty(PJOYRANGECONVERT this, REFGUID rguid, LPDIPROPHEADER pdiph);
STDMETHODIMP CCal_SetProperty(PJOYRANGECONVERT this, LPCDIPROPINFO ppropi, LPCDIPROPHEADER pdiph, HKEY hkType);
/*****************************************************************************
* * @doc INTERNAL * * @func LONG | CCal_Midpoint | * * Return the midpoint of two values. Note, however, that * we round <y upward> instead of downward. This is important, * because many people set the ranges to something like * 0 .. 0xFFFF, and we want the midpoint to be 0x8000. * * Care must be taken that the intermediate sum does not overflow. * * @parm LONG | lMin | * * Lower limit. * * @parm LONG | lMax | * * Upper limit. * * @returns * * The midpoint. * *****************************************************************************/
LONG INLINE CCal_Midpoint(LONG lMin, LONG lMax) { /*
* Can't do "lMax + lMin" because that might overflow. */ AssertF(lMax >= lMin); return lMin + (UINT)(lMax - lMin + 1) / 2; }
/*****************************************************************************
* * dijoytyp.c * *****************************************************************************/
STDMETHODIMP CType_OpenIdSubkey(HKEY, DWORD, REGSAM, PHKEY); void EXTERNAL CType_RegGetObjectInfo(HKEY hkType, DWORD dwId, LPDIDEVICEOBJECTINSTANCEW pdidoiW); void EXTERNAL CType_RegGetTypeInfo(HKEY hkType, LPDIOBJECTDATAFORMAT podf, BOOL bHid); void EXTERNAL CType_MakeGameCtrlName(PWCHAR wszOutput, DWORD dwDevType, DWORD dwAxes, DWORD dwButtons, DWORD dwPOVs );
/*****************************************************************************
* * didevdf.c * *****************************************************************************/
HRESULT CDIDev_ActionMap_IsValidMapObject(LPDIACTIONFORMATW paf #ifdef XDEBUG
comma LPCSTR pszProc comma UINT argnum #endif
);
STDMETHODIMP CMap_ValidateActionMapSemantics( LPDIACTIONFORMATW paf, DWORD dwFlags );
STDMETHODIMP CMap_BuildDefaultSysActionMap( LPDIACTIONFORMATW paf, DWORD dwFlags, DWORD dwPhysicalGenre, REFGUID guidDevInst, LPDIDATAFORMAT dfDev, DWORD dwButtonZeroInst );
typedef struct _DIDOBJDEFSEM { DWORD dwID; /* object id of control */ DWORD dwSemantic; /* default semantic match */ } DIDOBJDEFSEM, *PDIDOBJDEFSEM;
STDMETHODIMP CMap_BuildDefaultDevActionMap( LPDIACTIONFORMATW paf, DWORD dwFlags, REFGUID guidDevInst, PDIDOBJDEFSEM rgObjSem, DWORD dwNumAxes, DWORD dwNumPOVs, DWORD dwNumButtons );
STDMETHODIMP CMap_DeviceValidateActionMap( PV pdd, LPDIACTIONFORMATW paf, DWORD dwFlags, PDWORD pdwOut );
STDMETHODIMP CMap_InitializeCRCTable( void );
HRESULT CMap_GetDeviceUserName( REFGUID guidDevInst, LPWSTR wszOwner );
/*****************************************************************************
* * diaphack.c * *****************************************************************************/
BOOL EXTERNAL AhGetAppHacks(LPTSTR tszAppId); HRESULT EXTERNAL AhAppRegister(DWORD dwVer, DWORD dwMapper);
/*****************************************************************************
* * dimapshp.c - IDirectInputMapShepherd * *****************************************************************************/
STDMETHODIMP CMapShep_New(PUNK punkOuter, RIID riid, PPV ppvObj);
HRESULT INTERNAL _CreateInstance(REFCLSID rclsid, LPCTSTR ptszDll, LPUNKNOWN punkOuter, RIID riid, PPV ppvOut, HINSTANCE *phinst);
/*****************************************************************************
* * diraw.c * *****************************************************************************/ #ifdef USE_WM_INPUT
#define DIRAW_NONEXCL 0
#define DIRAW_EXCL 1
#define DIRAW_NOHOTKEYS 2
HRESULT CDIRaw_RegisterRawInputDevice( UINT uirim, DWORD dwOrd, HWND hwnd); HRESULT CDIRaw_UnregisterRawInputDevice( UINT uirim, HWND hwnd ); BOOL CDIRaw_OnInput(MSG *pmsg); HRESULT INTERNAL CDIRaw_Mouse_InitButtons(); int EXTERNAL DIRaw_GetKeyboardType(int nTypeFlag); #endif
#ifdef __cplusplus
}; #endif
|