/***************************************************************************** * * DIDev.h * * Copyright (c) 1996-1997 Microsoft Corporation. All Rights Reserved. * * Abstract: * * Common header file for IDirectInputDevice implementation. * * The original didev.c file was getting too big, so the * stuff that supports IDirectInputEffect has been split out * into didevef.c. Since both files need to access the * internal structure of an IDirectInputDevice, we need this * common header file. * *****************************************************************************/ /***************************************************************************** * * The sqiffle for this file. * *****************************************************************************/ #define sqfl sqflDev /***************************************************************************** * * Declare the interfaces we will be providing. * *****************************************************************************/ #define ThisClass CDIDev #define ThisInterface TFORM(IDirectInputDevice8) #define ThisInterfaceA IDirectInputDevice8A #define ThisInterfaceW IDirectInputDevice8W #define ThisInterfaceT IDirectInputDevice8 Primary_Interface(CDIDev, TFORM(ThisInterfaceT)); Secondary_Interface(CDIDev, SFORM(ThisInterfaceT)); /***************************************************************************** * * @doc INTERNAL * * @enum DIOPT | * * Device data format optimization levels. * * @emem dioptNone | * * Device data format is not optimized at all. We must read * the device data into a private buffer and copy each field * into the application buffer. * * @emem dioptMatch | * * Application data format matches the device data format * in the places where the application requests data at all. * We can read the device data into a private buffer, then * block copy the data into the application buffer. * * * @emem dioptDirect | * * , plus the entire device data * format fits inside the application format. * We can read the device data directly into the application * buffer. * * @emem dioptEqual | * * , plus the device data format * and application data formats are completely equal * (except for fields that the app doesn't explicitly * ask for). * We can issue buffered reads directly into the application * buffer. * *****************************************************************************/ typedef enum DIOPT { dioptNone = 0, dioptMatch = 1, dioptDirect = 2, dioptEqual = 3, } DIOPT; /***************************************************************************** * * @doc INTERNAL * * @struct CDIDev | * * The generic object. * * The A and W versions are simply alternate interfaces on the same * underlying object. * * @field IDirectInputDeviceA | ddA | * * ANSI DirectInputDevice object (containing vtbl). * * @field IDirectInputDeviceW | ddW | * * UNICODE DirectInputDevice object (containing vtbl). * * @field IDirectInputDeviceCallback * | pdcb | * * Callback object which handles the low-level device access. * * @field BOOL | fAcquired:1 | * * Set if the device has been acquired. Before the device * can be acquired, the must be set. * * @field BOOL | fAcquiredInstance:1 | * * Set if the device instance has been acquired by us. * This lets us know how much needs to be done on the * unacquire. * * @field BOOL | fCritInited:1 | * * Set if the critical section has been initialized. * * @field BOOL | fCook:1 | * * Set if the device requires that data be cooked. * * @field BOOL | fPolledDataFormat:1 | * * Set if the device's data format requires explicit polling. * * @field BOOL | fOnceAcquired:1 | * * Set once the device is acquired. * * @field BOOL | fOnceForcedUnacquired:1 | * * Set once the device is forced unacquired. * * @field BOOL | fUnacqiredWhenIconic:1 | * * Set once the device is unacquired (in CDIDev_CallWndProc) when the app is minimized. * * @field HWND | hwnd | * * Window that has requested exclusive access when acquired. * * @field DWORD | discl | * * Current value of * flags. * * @field HANDLE | hNotify | * * The notification handle that should be set when the * state of the device changes. Note that this is actually * a copy of the original handle supplied by the application, * so the handle should be closed when no longer needed. * * @field FARPROC | GetState | * * Function that transfers the device data in response * to . This field * is computed when the data format is set. * * @field PDIXLAT | pdix | * * Pointer to table used for data format translation. * It is indexed by device object; the dwOfs value is the location * in the application data format where the data should be stored, * the uAppData is the application specified data associated with * the object. * * For example, if the object described by * should be placed at offset 8 in the application data format, * then = 8. * * * @field PING | rgiobj | * * The inverse of . Given an offset, * converts it to the device object index. * * For example, if the object described by * should be placed at offset 8 in the application data format, * then = 3. * Entries for invalid offsets are -1. * * @field DWORD | dwDataSize | * * Size of the data, as requested by the application. * * @field DIDATAFORMAT | df | * * Device data format. * * @field DIOPT | diopt | * * Device optimization level. * * @field int | ibDelta | * * If is at least , * contains the shift necessary in order to align the * application data format with the device data format. * * @field int | ibMin | * * If is at least , * contains the offset of the first field in the device * format which is valid in both the application and * device data formats. * * @field DWORD | cbMatch | * * If is at least , * contains the number of bytes which matched. This is the * number of bytes that can be block-copied. * * @field PV | pvBuffer | * * if is or less, * then contains a scratch buffer equal in size to the * device data format which is used when an unoptimized * data format has been selected. * * @field PV | pvLastBuffer | * * Last instantaneous device state received. This is used * to emulate relative axes. Only the axis fields of the * structure are valid. * * @field PVXDINSTANCE | pvi | * * Instance handle for talking to the VxD. * * @field DWORD | cAxes | * * Number of axes on the device. This in turn yields the * size of the axis offset table. * * @field LPDWORD | rgdwAxesOfs | * * Axis offset table. This is used during relative axis * acquisition mode to convert the absolute numbers into * relative numbers. * * @field HRESULT | hresPolled | * * if the device is interrupt-driven. * if the device is polled. * * @field HRESULT | hresNotAcquired | * * if the device was unacquired without * the application's consent. if * the application should have known better. * * @field DWORD | celtBuf | * * Size of the device buffer. * * @field DWORD | celtBufMax | * * The largest buffer size we will permit. There is * a secret property that lets you increase the value, * in case an ISV comes up with a good reason for having * a larger buffer. * * @field LPDWORD | rgdwPOV | * * An array of DWORDs listing the locations (data offsets) * of all the optional POVs that were in the app's requested * data format and which we were unable to satisfy. We * need this so we can set them to -1 in the device state * because most apps are lazy and don't check if the object * actually exists before reading from it. To keep them safe, * we normally return zeros in nonexistent objects, but for * POVs, the "safe" value is -1, not zero. * * @field DWORD | cdwPOV | * * Number of failed optional POVs in the array. * * * @field LPDIRECTINPUTEFFECTSHEPHERD | pes | * * The * object which does the * low-level goo related to the force feedback part of the device. * * @field SHEPHANDLE | sh | * * The joystick "tag" which is used by dieshep.c * to determine who owns the joystick. * The field is permanently * zero, so that we can pass it to * * to perform a device escape. * * @field DWORD | dwVersion | * * Version number of DirectInput we are emulating. * * @field GPA | gpaEff | * * Pointer array of (held) objects * that have been created for this device. * * @field PEFFECTMAPINFO | rgemi | * * Array of structures, one for each * effect supported by the device. * * @field UINT | cemi | * * Number of elements in the array. * * @field DWORD | didcFF | * * Cached device capability flags related to force-feedback. * * @field DIFFDEVICEATTRIBUTES | ffattr | * * Contains force feedback device attributes. * * @field DWORD | dwGain | * * The gain setting for the device. * * @field DWORD | dwAutoCenter | * * The autocenter setting for the device. * * @field BOOL | fNotifiedNotBuffered:1 | * * Used only in XDEBUG to remember whether we * notified the caller that the device isn't buffered. * * @field LONG | cCrit | * * Number of times the critical section has been taken. * Used only in XDEBUG to check whether the caller is * releasing the object while another method is using it. * * @field DWORD | thidCrit | * * The thread that is currently in the critical section. * Used only in DEBUG for internal consistency checking. * * @field CRITICAL_SECTION | crst | * * Object critical section. Must be taken when accessing * volatile member variables. * * @field GUID | guid | * * The instance GUID of the device we are. * *****************************************************************************/ typedef struct DIXLAT { DWORD dwOfs; UINT_PTR uAppData; } DIXLAT, *PDIXLAT; typedef struct CDIDev { /* Supported interfaces */ TFORM(IDirectInputDevice) TFORM(dd); SFORM(IDirectInputDevice) SFORM(dd); /* * All interfaces currently have vtbls that are unmodified supersets of * all previous versions of the interface, so we use the latest interface * for all versions and do not need to keep multiple interfaces. */ IDirectInputDeviceCallback *pdcb; BOOL fAcquired:1; BOOL fAcquiredInstance:1; BOOL fCritInited:1; BOOL fCook:1; BOOL fPolledDataFormat:1; BOOL fOnceAcquired:1; BOOL fOnceForcedUnacquired:1; #ifdef WINNT BOOL fUnacquiredWhenIconic:1; #endif /* WARNING! EVERYTHING AFTER THIS LINE IS ZERO'd ON A RESET */ HWND hwnd; DWORD discl; HANDLE hNotify; STDMETHOD(GetState)(struct CDIDev *, PV); STDMETHOD(GetDeviceState)(struct CDIDev *, PV); PDIXLAT pdix; PINT rgiobj; DWORD dwDataSize; DIDATAFORMAT df; DIOPT diopt; int ibDelta; int ibMin; DWORD cbMatch; PV pvBuffer; PV pvLastBuffer; PVXDINSTANCE pvi; PV pvData; DWORD cAxes; LPDWORD rgdwAxesOfs; HRESULT hresPolled; HRESULT hresNotAcquired; DWORD celtBuf; LPDWORD rgdwPOV; DWORD cdwPOV; PEFFECTMAPINFO rgemi; UINT cemi; DWORD didcFF; SHEPHANDLE sh; DIFFDEVICEATTRIBUTES ffattr; DIDEVCAPS_DX3 dc3; /* WARNING! EVERYTHING ABOVE THIS LINE IS ZERO'd ON A RESET */ DWORD celtBufMax; /* Must be first field after zero'd region */ LPDIRECTINPUTEFFECTSHEPHERD pes; DWORD dwVersion; GPA gpaEff; DWORD dwGain; DWORD dwAutoCenter; RD(BOOL fNotifiedNotBuffered:1;) LONG cCrit; DWORD thidCrit; CRITICAL_SECTION crst; GUID guid; /* This is also zero'd on a reset */ DIAPPHACKS diHacks; LPDIRECTINPUTMAPSHEPHERD pMS; } CDIDev, DD, *PDD; typedef IDirectInputDeviceA DDA, *PDDA; typedef IDirectInputDeviceW DDW, *PDDW; typedef DIDEVICEOBJECTDATA DOD, *PDOD; typedef LPCDIDEVICEOBJECTDATA PCDOD; /***************************************************************************** * * Methods that live outside didev.c * *****************************************************************************/ /***************************************************************************** * * IDirectInputDevice8::SetDataFormat * *****************************************************************************/ STDMETHODIMP CDIDev_SetDataFormat(PV pdd, LPCDIDATAFORMAT lpdf _THAT); #ifdef INCLUDED_BY_DIDEV #ifdef XDEBUG CSET_STUBS(SetDataFormat, (PV pdd, LPCDIDATAFORMAT lpdf), (pdd, lpdf THAT_)) #else #define CDIDev_SetDataFormatA CDIDev_SetDataFormat #define CDIDev_SetDataFormatW CDIDev_SetDataFormat #endif #endif /***************************************************************************** * * IDirectInputDevice8::GetDeviceState * *****************************************************************************/ STDMETHODIMP CDIDev_GetDeviceState(PV pdd, DWORD cbDataSize, LPVOID pvData _THAT); #ifdef INCLUDED_BY_DIDEV #ifdef XDEBUG CSET_STUBS(GetDeviceState, (PV pdd, DWORD cbDataSize, LPVOID pvData), (pdd, cbDataSize, pvData THAT_)) #else #define CDIDev_GetDeviceStateA CDIDev_GetDeviceState #define CDIDev_GetDeviceStateW CDIDev_GetDeviceState #endif #endif /***************************************************************************** * * IDirectInputDevice8::GetDeviceData * *****************************************************************************/ STDMETHODIMP CDIDev_GetDeviceData(PV pdd, DWORD cbdod, PDOD rgdod, LPDWORD pdwInOut, DWORD fl _THAT); #ifdef INCLUDED_BY_DIDEV #ifdef XDEBUG CSET_STUBS(GetDeviceData, (PV pdd, DWORD cbdod, PDOD rgdod, LPDWORD pdwInOut, DWORD fl), (pdd, cbdod, rgdod, pdwInOut, fl THAT_)) #else #define CDIDev_GetDeviceDataA CDIDev_GetDeviceData #define CDIDev_GetDeviceDataW CDIDev_GetDeviceData #endif #endif /***************************************************************************** * * IDirectInputDevice8::CreateEffect * *****************************************************************************/ STDMETHODIMP CDIDev_CreateEffect(PV pdd, REFGUID rguid, LPCDIEFFECT peff, LPDIRECTINPUTEFFECT *ppdeff, LPUNKNOWN punkOuter _THAT); #ifdef INCLUDED_BY_DIDEV #ifdef XDEBUG CSET_STUBS(CreateEffect, (PV pdd, REFGUID rguid, LPCDIEFFECT peff, LPDIRECTINPUTEFFECT *ppdeff, LPUNKNOWN punkOuter), (pdd, rguid, peff, ppdeff, punkOuter THAT_)) #else #define CDIDev_CreateEffectA CDIDev_CreateEffect #define CDIDev_CreateEffectW CDIDev_CreateEffect #endif #endif /***************************************************************************** * * IDirectInputDevice8::EnumEffects * *****************************************************************************/ STDMETHODIMP CDIDev_EnumEffectsW(PV pdd, LPDIENUMEFFECTSCALLBACKW pecW, PV pvRef, DWORD fl); STDMETHODIMP CDIDev_EnumEffectsA(PV pdd, LPDIENUMEFFECTSCALLBACKA pecA, PV pvRef, DWORD fl); /***************************************************************************** * * IDirectInputDevice8::GetEffectInfo * *****************************************************************************/ STDMETHODIMP CDIDev_GetEffectInfoW(PV pddW, LPDIEFFECTINFOW peiW, REFGUID rguid); STDMETHODIMP CDIDev_GetEffectInfoA(PV pddA, LPDIEFFECTINFOA peiA, REFGUID rguid); /***************************************************************************** * * IDirectInputDevice8::GetForceFeedbackState * *****************************************************************************/ STDMETHODIMP CDIDev_GetForceFeedbackState(PV pdd, LPDWORD pdwOut _THAT); #ifdef INCLUDED_BY_DIDEV #ifdef XDEBUG CSET_STUBS(GetForceFeedbackState, (PV pdd, LPDWORD pdwOut), (pdd, pdwOut THAT_)) #else #define CDIDev_GetForceFeedbackStateA CDIDev_GetForceFeedbackState #define CDIDev_GetForceFeedbackStateW CDIDev_GetForceFeedbackState #endif #endif /***************************************************************************** * * IDirectInputDevice8::SendForceFeedbackCommand * *****************************************************************************/ STDMETHODIMP CDIDev_SendForceFeedbackCommand(PV pdd, DWORD dwCmd _THAT); #ifdef INCLUDED_BY_DIDEV #ifdef XDEBUG CSET_STUBS(SendForceFeedbackCommand, (PV pdd, DWORD dwCmd), (pdd, dwCmd THAT_)) #else #define CDIDev_SendForceFeedbackCommandA CDIDev_SendForceFeedbackCommand #define CDIDev_SendForceFeedbackCommandW CDIDev_SendForceFeedbackCommand #endif #endif /***************************************************************************** * * IDirectInputDevice8::EnumCreatedEffects * *****************************************************************************/ STDMETHODIMP CDIDev_EnumCreatedEffectObjects(PV pdd, LPDIENUMCREATEDEFFECTOBJECTSCALLBACK pec, LPVOID pvRef, DWORD dwFlags _THAT); #ifdef INCLUDED_BY_DIDEV #ifdef XDEBUG CSET_STUBS(EnumCreatedEffectObjects, (PV pdd, LPDIENUMCREATEDEFFECTOBJECTSCALLBACK pec, LPVOID pvRef, DWORD dwFlags), (pdd, pec, pvRef, dwFlags THAT_)) #else #define CDIDev_EnumCreatedEffectObjectsA CDIDev_EnumCreatedEffectObjects #define CDIDev_EnumCreatedEffectObjectsW CDIDev_EnumCreatedEffectObjects #endif #endif /***************************************************************************** * * IDirectInputDevice8::Escape * *****************************************************************************/ STDMETHODIMP CDIDev_Escape(PV pdd, LPDIEFFESCAPE pesc _THAT); #ifdef INCLUDED_BY_DIDEV #ifdef XDEBUG CSET_STUBS(Escape, (PV pdd, LPDIEFFESCAPE pesc), (pdd, pesc THAT_)) #else #define CDIDev_EscapeA CDIDev_Escape #define CDIDev_EscapeW CDIDev_Escape #endif #endif /***************************************************************************** * * IDirectInputDevice8::Poll * *****************************************************************************/ STDMETHODIMP CDIDev_Poll(PV pdd _THAT); #ifdef INCLUDED_BY_DIDEV #ifdef XDEBUG CSET_STUBS(Poll, (PV pdd), (pdd THAT_)) #else #define CDIDev_PollA CDIDev_Poll #define CDIDev_PollW CDIDev_Poll #endif #endif /***************************************************************************** * * IDirectInputDevice8::SendDeviceData * *****************************************************************************/ STDMETHODIMP CDIDev_SendDeviceData(PV pdd, DWORD cbdod, LPCDIDEVICEOBJECTDATA rgdod, LPDWORD pdwInOut, DWORD fl _THAT); #ifdef INCLUDED_BY_DIDEV #ifdef XDEBUG CSET_STUBS(SendDeviceData, (PV pdd, DWORD cbdod, LPCDIDEVICEOBJECTDATA rgdod, LPDWORD pdwInOut, DWORD fl), (pdd, cbdod, rgdod, pdwInOut, fl THAT_)) #else #define CDIDev_SendDeviceDataA CDIDev_SendDeviceData #define CDIDev_SendDeviceDataW CDIDev_SendDeviceData #endif #endif /***************************************************************************** * * IDirectInputDevice8::CDIDev_BuildActionMap * *****************************************************************************/ STDMETHODIMP CDIDev_BuildActionMapW( PV pdd, LPDIACTIONFORMATW pAFW, LPCWSTR wszName, DWORD fl); STDMETHODIMP CDIDev_BuildActionMapA( PV pdd, LPDIACTIONFORMATA pAFA, LPCSTR szName, DWORD fl); /***************************************************************************** * * IDirectInputDevice8::CDIDev_SetActionMap * *****************************************************************************/ STDMETHODIMP CDIDev_SetActionMapW( PV pdd, LPDIACTIONFORMATW pAFW, LPCWSTR wszName, DWORD fl); STDMETHODIMP CDIDev_SetActionMapA( PV pdd, LPDIACTIONFORMATA pAFA, LPCSTR szName, DWORD fl); /***************************************************************************** * * IDirectInputDevice8::CDIDev_GetImageInfo * *****************************************************************************/ STDMETHODIMP CDIDev_GetImageInfoW( PV pdd, LPDIDEVICEIMAGEINFOHEADERW piih); STDMETHODIMP CDIDev_GetImageInfoA( PV pdd, LPDIDEVICEIMAGEINFOHEADERA piih); /***************************************************************************** * * Methods in didev.c needed in supporting files * *****************************************************************************/ /***************************************************************************** * * IDirectInputDevice8::GetProperty * *****************************************************************************/ STDMETHODIMP CDIDev_GetProperty(PV pdd, REFGUID rguid, LPDIPROPHEADER pdiph _THAT); #ifdef XDEBUG STDMETHODIMP CDIDev_GetPropertyA(PV pdd, REFGUID rguid, LPDIPROPHEADER pdiph); STDMETHODIMP CDIDev_GetPropertyW(PV pdd, REFGUID rguid, LPDIPROPHEADER pdiph); #else #define CDIDev_GetPropertyA CDIDev_GetProperty #define CDIDev_GetPropertyW CDIDev_GetProperty #endif /***************************************************************************** * * More internal worker functions. * * IsConsists is used for assertion checking. * * Finalize calls Unacquire to clean up in the case where the * caller forgot. * * Similarly, Reset needs to reset the GetDeviceState pointer. * * SetDataFormat needs to set the axis mode property. * * CDIDev_InitFF is used by CDIDev_Initialize to initialize * the force-feedback portion of the device. * *****************************************************************************/ #ifdef DEBUG BOOL INTERNAL CDIDev_IsConsistent(PDD this); #endif STDMETHODIMP CDIDev_InternalUnacquire(PV pdd); STDMETHODIMP CDIDev_GetAbsDeviceState(PDD this, LPVOID pvData); STDMETHODIMP CDIDev_GetRelDeviceState(PDD this, LPVOID pvData); STDMETHODIMP CDIDev_RealSetProperty(PDD this, REFGUID rguid, LPCDIPROPHEADER pdiph); STDMETHODIMP CDIDev_FFAcquire(PDD this); STDMETHODIMP CDIDev_InitFF(PDD this); STDMETHODIMP CDIDev_GetLoad(PDD this, LPDWORD pdw); STDMETHODIMP CDIDev_RefreshGain(PDD this); HRESULT INTERNAL CDIDev_CreateEffectDriver(PDD this);