|
|
/*****************************************************************************
* * DIJoyTyp.c * * Copyright (c) 1996 Microsoft Corporation. All Rights Reserved. * * Abstract: * * Functions that pull data out of the joystick type key * (wherever it is). * * Contents: * * ? * *****************************************************************************/
#include "dinputpr.h"
/*****************************************************************************
* * The sqiffle for this file. * *****************************************************************************/
#define sqfl sqflJoyType
/*****************************************************************************
* * @doc INTERNAL * * @func HRESULT | CType_OpenIdSubkey | * * Given an object ID, attempt to open the subkey that * corresponds to it for reading. * * @parm HKEY | hkType | * * The joystick type key, possibly <c NULL> if we don't * have a type key. (For example, if it was never created.) * * @parm DWORD | dwId | * * Object id. * * @parm REGSAM | regsam | * * Registry security access mask. * * @parm PHKEY | phk | * * Receives the object key on success. * * @returns * * Returns a COM error code. * *****************************************************************************/
STDMETHODIMP CType_OpenIdSubkey(HKEY hkType, DWORD dwId, REGSAM sam, PHKEY phk) { HRESULT hres;
EnterProc(CType_OpenIdSubkey, (_ "xx", hkType, dwId));
*phk = 0;
if(hkType) { /*
* Worst case is "Actuators\65535" which has length 15. */ TCHAR tsz[32]; LPCTSTR ptszType;
if(dwId & DIDFT_AXIS) { ptszType = TEXT("Axes"); } else if(dwId & DIDFT_BUTTON) { ptszType = TEXT("Buttons"); } else if(dwId & DIDFT_POV) { ptszType = TEXT("POVs"); } else if(dwId & DIDFT_NODATA) { ptszType = TEXT("Actuators"); } else { hres = E_NOTIMPL; goto done; }
// ISSUE-2001/03/29-timgill Need to scale back for pos vs state
// MarcAnd -- I believe this means: if you're trying to
// look for the X axis, we should use the position
// instance, not the velocity one.
wsprintf(tsz, TEXT("%s\\%u"), ptszType, DIDFT_GETINSTANCE(dwId));
hres = hresMumbleKeyEx(hkType, tsz, sam, REG_OPTION_NON_VOLATILE, phk);
} else { hres = DIERR_NOTFOUND; }
done:; if(hres == DIERR_NOTFOUND) { ExitBenignOleProcPpv(phk); } else { ExitOleProcPpv(phk); } return hres; }
/*****************************************************************************
* * @doc INTERNAL * * @func void | CType_RegGetObjectInfo | * * Given an object ID, look into the registry subkey for the * object and extract anything we can find. * * If we find nothing, then do nothing. * * @parm HKEY | hkType | * * The joystick type key, possibly <c NULL> if we don't * have a type key. (For example, if it was never created.) * * @parm DWORD | dwId | * * Object id. * * @parm LPDIDEVICEOBJECTINSTANCEW | pdidoiW | * * Structure to receive information. The * <e DIDEVICEOBJECTINSTANCE.guidType>, * <e DIDEVICEOBJECTINSTANCE.dwOfs>, * and * <e DIDEVICEOBJECTINSTANCE.dwType> * <e DIDEVICEOBJECTINSTANCE.dwFlags> * fields have already been filled in so we should only not override * these with default data. * *****************************************************************************/
void EXTERNAL CType_RegGetObjectInfo(HKEY hkType, DWORD dwId, LPDIDEVICEOBJECTINSTANCEW pdidoiW) { HRESULT hres; HKEY hk; EnterProc(CType_RegKeyObjectInfo, (_ "xx", hkType, dwId));
/*
* Extract information about this item from the registry. */ hres = CType_OpenIdSubkey(hkType, dwId, KEY_QUERY_VALUE, &hk);
if(SUCCEEDED(hres)) {
DIOBJECTATTRIBUTES attr;
/*
* Read the regular and HID attributes. */
hres = JoyReg_GetValue(hk, TEXT("Attributes"), REG_BINARY, &attr, cbX(attr));
if(SUCCEEDED(hres)) { /*
* Copy the bit fields. * PREFIX warns (333540) that attr.dwFlags is not initialized * however JoyReg_GetValue zeroes any part of the buffer after * the bytes read from the registry if the buffer size is larger * than what was read. */ pdidoiW->dwFlags |= (attr.dwFlags & ~DIDOI_ASPECTMASK);
/*
* Don't add FF if the dwId did not have it. * (See comment on FF attrs below for why.) */ if( ( dwId & ( DIDFT_FFEFFECTTRIGGER | DIDFT_FFACTUATOR ) ) == 0 ) { pdidoiW->dwFlags &= ~( DIDOI_FFACTUATOR | DIDOI_FFEFFECTTRIGGER ); }
/*
* Copy the aspect, but don't change * the aspect from "known" to "unknown". If the * registry doesn't have an aspect, then use the * aspect we got from the caller. */ if((attr.dwFlags & DIDOI_ASPECTMASK) != DIDOI_ASPECTUNKNOWN) { pdidoiW->dwFlags = (pdidoiW->dwFlags & ~DIDOI_ASPECTMASK) | (attr.dwFlags & DIDOI_ASPECTMASK); } }
/*
* If the caller wants force feedback info, * then get it. */ if(pdidoiW->dwSize >= cbX(DIDEVICEOBJECTINSTANCE_DX5W)) { /*
* Only copy the usages if they are valid. * JoyReg_GetValue zeros any buffer beyond what is read. */ if(SUCCEEDED(hres) && attr.wUsagePage && attr.wUsage ) { pdidoiW->wUsagePage = attr.wUsagePage; pdidoiW->wUsage = attr.wUsage; }
/*
* Only try to read the FF attributes if the object supports FF * This may save time but is primarily to allow us to ignore FF * attributes in the registry for objects (such as FF driving * controller pedals) which IHVs mark incorrectly. */ if( dwId & ( DIDFT_FFEFFECTTRIGGER | DIDFT_FFACTUATOR ) ) { /*
* Assert that we can read the DIFFOBJECTATTRIBUTES * directly into the DIDEVICEOBJECTINSTANCE_DX5. */ CAssertF(FIELD_OFFSET(DIFFOBJECTATTRIBUTES, dwFFMaxForce) == 0); CAssertF(FIELD_OFFSET(DIFFOBJECTATTRIBUTES, dwFFForceResolution) == 4); CAssertF(FIELD_OFFSET(DIDEVICEOBJECTINSTANCE_DX5, dwFFMaxForce) + 4 == FIELD_OFFSET(DIDEVICEOBJECTINSTANCE_DX5, dwFFForceResolution)); CAssertF(cbX(DIFFOBJECTATTRIBUTES) == 8);
/*
* If this doesn't work, gee that's too bad. * JoyReg_GetValue will zero-fill the error parts. */ JoyReg_GetValue(hk, TEXT("FFAttributes"), REG_BINARY, &pdidoiW->dwFFMaxForce, cbX(DIFFOBJECTATTRIBUTES)); } else { AssertF( ( pdidoiW->dwFFMaxForce | pdidoiW->dwFFForceResolution ) == 0 ); } }
/*
* Read the optional custom name. * * Note that JoyReg_GetValue(REG_SZ) uses * RegQueryStringValueW, which sets the * string to null on error so we don't have to. */ hres = JoyReg_GetValue(hk, 0, REG_SZ, pdidoiW->tszName, cbX(pdidoiW->tszName));
if(SUCCEEDED(hres)) { } else { AssertF(pdidoiW->tszName[0] == L'\0'); }
RegCloseKey(hk); } else { AssertF(pdidoiW->tszName[0] == L'\0'); }
}
/*****************************************************************************
* * @doc INTERNAL * * @func void | CType_RegGetTypeInfo | * * Given an object ID, look into the registry subkey for the * object and extract attribute bits that should be OR'd * into the object ID. * * This needs to be done during device initialization to * establish the attributes in the data format so that * * 1. <mf IDirectInputDevice::EnumObjects> filters properly, and * * 2. >mf IDirectInputEffect::SetParameters> can validate properly. * * @parm HKEY | hkType | * * The joystick type key, possibly <c NULL> if we don't * have a type key. (For example, if it was never created.) * * @parm LPDIOBJECTDATAFORMAT | podf | * * Structure to receive more information. The * <e DIOBJECTDATAFORMAT.dwType> field identifies the object. * * On return the * <e DIOBJECTDATAFORMAT.dwType> * and * <e DIOBJECTDATAFORMAT.dwFlags> * fields are updated. * *****************************************************************************/
void EXTERNAL CType_RegGetTypeInfo(HKEY hkType, LPDIOBJECTDATAFORMAT podf, BOOL fPidDevice) { HRESULT hres; HKEY hk; EnterProc(CType_RegKeyObjectInfo, (_ "xx", hkType, podf->dwType));
hres = CType_OpenIdSubkey(hkType, podf->dwType, KEY_QUERY_VALUE, &hk);
if(SUCCEEDED(hres)) { DWORD dwFlags;
CAssertF(FIELD_OFFSET(DIOBJECTATTRIBUTES, dwFlags) == 0);
hres = JoyReg_GetValue(hk, TEXT("Attributes"), REG_BINARY, &dwFlags, cbX(dwFlags));
if(SUCCEEDED(hres)) { /*
* Propagate the attributes into the type code. */ CAssertF(DIDOI_FFACTUATOR == DIDFT_GETATTR(DIDFT_FFACTUATOR)); CAssertF(DIDOI_FFEFFECTTRIGGER == DIDFT_GETATTR(DIDFT_FFEFFECTTRIGGER));
/*
* PREFIX warns (333539) that dwFlags is not initialized however * JoyReg_GetValue zeroes any part of the buffer after the bytes * read from the registry if the buffer size is larger than what * was read. */ podf->dwType |= DIDFT_MAKEATTR(dwFlags);
podf->dwFlags |= (dwFlags & ~DIDOI_ASPECTMASK);
/*
* Copy the aspect, but don't change * the aspect from "known" to "unknown". If the * registry doesn't have an aspect, then use the * aspect we got from the caller. */ if((dwFlags & DIDOI_ASPECTMASK) != DIDOI_ASPECTUNKNOWN) { podf->dwFlags = (podf->dwFlags & ~DIDOI_ASPECTMASK) | (dwFlags & DIDOI_ASPECTMASK); } }
RegCloseKey(hk); }else { #ifndef WINNT
// Post Dx7Gold Patch
// This is for Win9x only.
// On Win9x, a device that is being accessed through the vjoyd path
// will not get forces, as the attributes necessary for FF have not
// been appropriately marked.
// THe following code will mark the
DWORD dwFlags = DIDFT_GETATTR( podf->dwType & ~DIDFT_ATTRMASK ) | ( podf->dwFlags & ~DIDOI_ASPECTMASK);
if( dwFlags != 0x0 && fPidDevice ) { hres = CType_OpenIdSubkey(hkType, podf->dwType, DI_KEY_ALL_ACCESS, &hk);
if(SUCCEEDED(hres) ) {
hres = JoyReg_SetValue(hk, TEXT("Attributes"), REG_BINARY, &dwFlags, cbX(dwFlags));
RegCloseKey(hk); } } #endif // ! WINNT
} }
/*****************************************************************************
* * @doc INTERNAL * * @func void | CType_MakeGameCtrlName | * * Make a game controller name from the attributes of the controller. * Used as a last resort when a name is needed but none is available. * * @parm PWCHAR | wszName | * * Output buffer where name will be generated. * * @parm DWORD | dwType | * * DI8DEVTYPE value for the controller. * * @parm DWORD | dwAxes | * * The number of axes the device has. * * @parm DWORD | dwButtons | * * The numer of buttons the device has. * * @parm DWORD | dwPOVs | * * The number of POVs the device has. * *****************************************************************************/
void EXTERNAL CType_MakeGameCtrlName ( PWCHAR wszOutput, DWORD dwDevType, DWORD dwAxes, DWORD dwButtons, DWORD dwPOVs ) { TCHAR tsz[64]; TCHAR tszPOV[64]; TCHAR tszFormat[64]; #ifndef UNICODE
TCHAR tszOut[cA(tsz)+cA(tszFormat)+cA(tszPOV)]; #endif
/* tszFormat = %d axis, %d button %s */ LoadString(g_hinst, IDS_TEXT_TEMPLATE, tszFormat, cA(tszFormat));
/* tsz = joystick, gamepad, etc. */
if( ( GET_DIDEVICE_TYPE( dwDevType ) >= DI8DEVTYPE_JOYSTICK ) && ( GET_DIDEVICE_TYPE( dwDevType ) <= DI8DEVTYPE_FLIGHT ) ) { LoadString(g_hinst, GET_DIDEVICE_TYPE( dwDevType ) + IDS_PLAIN_STICK - DI8DEVTYPE_JOYSTICK, tsz, cA(tsz)); } else if( GET_DIDEVICE_TYPEANDSUBTYPE( dwDevType ) == MAKE_DIDEVICE_TYPE( DI8DEVTYPE_SUPPLEMENTAL, DI8DEVTYPESUPPLEMENTAL_HEADTRACKER ) ) { LoadString(g_hinst, IDS_HEAD_TRACKER, tsz, cA(tsz)); } else { LoadString(g_hinst, IDS_DEVICE_NAME, tsz, cA(tsz)); }
if( dwPOVs ) { LoadString(g_hinst, IDS_WITH_POV, tszPOV, cA(tszPOV)); } else { tszPOV[0] = TEXT( '\0' ); }
#ifdef UNICODE
wsprintfW(wszOutput, tszFormat, dwAxes, dwButtons, tsz, tszPOV); #else
wsprintfA(tszOut, tszFormat, dwAxes, dwButtons, tsz, tszPOV); TToU(wszOutput, cA(tszOut), tszOut); #endif
}
|