|
|
/*****************************************************************************
* * DIJoyReg.c * * Copyright (c) 1996 Microsoft Corporation. All Rights Reserved. * * Abstract: * * Registry access services for joystick configuration. * * Contents: * * JoyReg_GetConfig * *****************************************************************************/
#include "dinputpr.h"
/*****************************************************************************
* * The sqiffle for this file. * *****************************************************************************/
#define sqfl sqflJoyReg
#pragma BEGIN_CONST_DATA
/*****************************************************************************
* * @doc INTERNAL * * @global JOYREGHWSETTINGS | c_rghwsPredef[] | * * Array of predefined hardware settings. * *****************************************************************************/
JOYREGHWSETTINGS c_rghwsPredef[] = { /* dwFlags dwNumButtons */ { 0, 2}, /* JOY_HW_2A_2B_GENERIC */ { 0, 4}, /* JOY_HW_2A_4B_GENERIC */ { JOY_HWS_ISGAMEPAD, 2}, /* JOY_HW_2B_GAMEPAD */ { JOY_HWS_ISYOKE, 2}, /* JOY_HW_2B_FLIGHTYOKE */ { JOY_HWS_HASZ | JOY_HWS_ISYOKE, 2}, /* JOY_HW_2B_FLIGHTYOKETHROTTLE */ { JOY_HWS_HASZ, 2}, /* JOY_HW_3A_2B_GENERIC */ { JOY_HWS_HASZ, 4}, /* JOY_HW_3A_4B_GENERIC */ { JOY_HWS_ISGAMEPAD, 4}, /* JOY_HW_4B_GAMEPAD */ { JOY_HWS_ISYOKE, 4}, /* JOY_HW_4B_FLIGHTYOKE */ { JOY_HWS_HASZ | JOY_HWS_ISYOKE, 4}, /* JOY_HW_4B_FLIGHTYOKETHROTTLE */ { JOY_HWS_HASR , 2}, /* JOY_HW_TWO_2A_2B_WITH_Y */ /* To prevent the CPL from allowing
a user to add a rudder to to JOY_HWS_TWO_2A_2B_WITH_Y case, we will pretend that it already has a rudder. This should not be a problem as this struct is internal to DInput */ };
/* Hardware IDs for Predefined Joystick types */ LPCWSTR c_rghwIdPredef[] = { L"GAMEPORT\\VID_045E&PID_0102", // L"GAMEPORT\\Generic2A2B",
L"GAMEPORT\\VID_045E&PID_0103", // L"GAMEPORT\\Generic2A4B",
L"GAMEPORT\\VID_045E&PID_0104", // L"GAMEPORT\\Gamepad2B",
L"GAMEPORT\\VID_045E&PID_0105", // L"GAMEPORT\\FlightYoke2B",
L"GAMEPORT\\VID_045E&PID_0106", // L"GAMEPORT\\FlightYokeThrottle2B",
L"GAMEPORT\\VID_045E&PID_0107", // L"GAMEPORT\\Generic3A2B",
L"GAMEPORT\\VID_045E&PID_0108", // L"GAMEPORT\\Generic3A4B",
L"GAMEPORT\\VID_045E&PID_0109", // L"GAMEPORT\\Gamepad4B",
L"GAMEPORT\\VID_045E&PID_010A", // L"GAMEPORT\\FlightYoke4B",
L"GAMEPORT\\VID_045E&PID_010B", // L"GAMEPORT\\FlightYokeThrottle4B",
L"GAMEPORT\\VID_045E&PID_010C", // L"GAMEPORT\\YConnectTwo2A2B",
};
WCHAR c_hwIdPrefix[] = L"GAMEPORT\\"; // Prefix for custom devices
/*****************************************************************************
* * The default global port driver. * *****************************************************************************/
WCHAR c_wszDefPortDriver[] = L"MSANALOG.VXD";
#ifdef WINNT
#define REGSTR_SZREGKEY TEXT("\\DINPUT.DLL\\")
#endif
/*****************************************************************************
* * @doc INTERNAL * * @func HRESULT | JoyReg_GetValue | * * Retrieve registry information. If the data is short, and * the type is <c REG_BINARY>, then the extra is zero-filled. * * @parm HKEY | hk | * * Registry key containing fun values. * * @parm LPCTSTR | ptszValue | * * Registry value name. * * @parm DWORD | reg | * * Registry data type expected. * * @parm LPVOID | pvBuf | * * Buffer to receive information from registry. * * @parm DWORD | cb | * * Size of recipient buffer, in bytes. * * @returns * * Returns a COM error code. The following error codes are * intended to be illustrative and not necessarily comprehensive. * * <c DI_OK> = <c S_OK>: The operation completed successfully. * * <c S_FALSE>: The binary read was short. The remainder of the * buffer is zero-filled. * * <c E_FAIL>: Error reading value from registry. * *****************************************************************************/
STDMETHODIMP JoyReg_GetValue(HKEY hk, LPCTSTR ptszValue, DWORD reg, PV pvBuf, DWORD cb) { HRESULT hres; DWORD cbOut; LONG lRc;
/*
* Strings must be handled differently from binaries. * * Strings are retrieved in UNICODE and may be short. * * Binaries are retrieved as binary (duh) and may be long. * */
cbOut = cb;
if (reg == REG_SZ) { lRc = RegQueryStringValueW(hk, ptszValue, pvBuf, &cbOut); if (lRc == ERROR_SUCCESS) { hres = S_OK; } else { hres = hresLe(lRc); /* Else, something bad happened */ }
} else {
AssertF(reg == REG_BINARY);
lRc = RegQueryValueEx(hk, ptszValue, 0, NULL, pvBuf, &cbOut); if (lRc == ERROR_SUCCESS) { if (cb == cbOut) { hres = S_OK; } else {
/*
* Zero out the extra. */ ZeroBuf(pvAddPvCb(pvBuf, cbOut), cb - cbOut); hres = S_FALSE; }
} else if (lRc == ERROR_MORE_DATA) {
/*
* Need to double-buffer the call and throw away * the extra... */ LPVOID pv;
hres = AllocCbPpv(cbOut, &pv); // prefix 29344, odd chance that cbOut is 0x0
if (SUCCEEDED(hres) && ( pv != NULL) ) { lRc = RegQueryValueEx(hk, ptszValue, 0, NULL, pv, &cbOut); if (lRc == ERROR_SUCCESS) { CopyMemory(pvBuf, pv, cb); hres = S_OK; } else { ZeroBuf(pvBuf, cb); hres = hresLe(lRc); /* Else, something bad happened */ } FreePv(pv); }
} else { if (lRc == ERROR_KEY_DELETED || lRc == ERROR_BADKEY) { lRc = ERROR_FILE_NOT_FOUND; } hres = hresLe(lRc); ZeroBuf(pvBuf, cb); } }
#ifdef DEBUG
/*
* Don't whine if the key we couldn't find was * REGSTR_VAL_JOYUSERVALUES, because almost no one has it. */ if (FAILED(hres) && lstrcmpi(ptszValue, REGSTR_VAL_JOYUSERVALUES) ) {
SquirtSqflPtszV(sqfl | sqflVerbose, TEXT("Unable to read %s from registry"), ptszValue); } #endif
return hres;
}
#ifndef WINNT
/*****************************************************************************
* * @doc INTERNAL * * @func HRESULT | JoyReg_IsWdmGameport | * * To test whether the joy type is WDM device or not. * * @parm HKEY | hk | * * Registry key containing fun values. * * @returns * * S_OK: if it uses WDM driver * * E_FAIL>: Not uses WDM driver * *****************************************************************************/
STDMETHODIMP JoyReg_IsWdmGameport( HKEY hk ) { HRESULT hres = E_FAIL;
if ( hk ) { WCHAR wsz[MAX_JOYSTRING];
// Whistler PREFIX Bug # 45075, 45076
// Wsz is not initialized
ZeroX(wsz);
if ( ( SUCCEEDED( JoyReg_GetValue( hk, REGSTR_VAL_JOYOEMHARDWAREID, REG_SZ, &wsz, cbX(wsz) ) ) ) &&( wsz[0] ) ) { hres = S_OK; } else if ( SUCCEEDED( JoyReg_GetValue( hk, REGSTR_VAL_JOYOEMCALLOUT, REG_SZ, &wsz, cbX(wsz) ) ) ) { static WCHAR wszJoyhid[] = L"joyhid.vxd"; int Idx; #define WLOWER 0x0020
CAssertF( cbX(wszJoyhid) <= cbX(wsz) );
/*
* Since neither CharUpperW nor lstrcmpiW are really * implemented on 9x, do it by hand. */
for ( Idx=cA(wszJoyhid)-2; Idx>=0; Idx-- ) { if ( ( wsz[Idx] | WLOWER ) != wszJoyhid[Idx] ) { break; } }
if ( ( Idx < 0 ) && ( wsz[cA(wszJoyhid)-1] == 0 ) ) { hres = S_OK; }
#undef WLOWER
}
}
return hres; } #endif /* ndef WINNT */
#if 0
/*
* This function should be in diutil.c Putting here is just to keep it together with * JoyReg_IsWdmGameport(); */ STDMETHODIMP JoyReg_IsWdmGameportFromDeviceInstance( LPTSTR ptszDeviceInst ) { /*
* ptszDeviceInst's format is like this: * HID\VID_045E&PID_0102\0000GAMEPORT&PVID_.... */
WCHAR wszDeviceInst[MAX_PATH]; HRESULT hres = E_FAIL;
if ( ptszDeviceInst ) { memset( wszDeviceInst, 0, cbX(wszDeviceInst) ); TToU( wszDeviceInst, MAX_PATH, ptszDeviceInst ); wszDeviceInst[34] = 0;
if ( memcmp( &wszDeviceInst[26], c_hwIdPrefix, 16 ) == 0 ) { hres = S_OK; } }
return hres; } #endif
/*****************************************************************************
* * @doc INTERNAL * * @func HRESULT | JoyReg_SetValue | * * Write registry information. * * @parm HKEY | hk | * * Registry key containing fun values. * * @parm LPCTSTR | ptszValue | * * Registry value name. * * @parm DWORD | reg | * * Registry data type to set. * * @parm LPCVOID | pvBuf | * * Buffer containing information to write to registry. * * @parm DWORD | cb | * * Size of buffer, in bytes. Ignored if writing a string. * * @returns * * Returns a COM error code. The following error codes are * intended to be illustrative and not necessarily comprehensive. * * <c DI_OK> = <c S_OK>: The operation completed successfully. * * <c E_FAIL>: Error writing value to registry. * *****************************************************************************/
STDMETHODIMP JoyReg_SetValue(HKEY hk, LPCTSTR ptszValue, DWORD reg, PCV pvBuf, DWORD cb) { HRESULT hres; LONG lRc;
/*
* Strings must be handled differently from binaries. * * A null string translates into deleting the key. */
if (reg == REG_SZ) { lRc = RegSetStringValueW(hk, ptszValue, pvBuf); } else { lRc = RegSetValueEx(hk, ptszValue, 0, reg, pvBuf, cb); }
if (lRc == ERROR_SUCCESS) { hres = S_OK; } else { RPF("Unable to write %s to registry", ptszValue); hres = E_FAIL; /* Else, something bad happened */ }
return hres;
}
/*****************************************************************************
* * @doc INTERNAL * * @func HRESULT | JoyReg_OpenTypeKey | * * Open the joystick registry key that corresponds to a * joystick type. * * @parm LPCWSTR | pwszTypeName | * * The name of the type. * * @parm DWORD | sam | * * Desired security access mask. * * @parm OUT PHKEY | phk | * * Receives the opened registry key on success. * * @returns * * Returns a COM error code. The following error codes are * intended to be illustrative and not necessarily comprehensive. * * <c DI_OK> = <c S_OK>: The operation completed successfully. * * <c DIERR_NOTFOUND>: The joystick type was not found. * *****************************************************************************/
STDMETHODIMP JoyReg_OpenTypeKey(LPCWSTR pwszType, DWORD sam, DWORD dwOptions, PHKEY phk) { HRESULT hres; HKEY hkTypes; EnterProc(JoyReg_OpenTypeKey, (_ "W", pwszType));
/*
* Note that it is not safe to cache the registry key. * If somebody deletes the registry key, our handle * goes stale and becomes useless. */
hres = hresMumbleKeyEx(HKEY_LOCAL_MACHINE, REGSTR_PATH_JOYOEM, sam, REG_OPTION_NON_VOLATILE, &hkTypes);
if ( SUCCEEDED(hres) ) { #ifndef UNICODE
TCHAR tszType[MAX_PATH]; UToA( tszType, cA(tszType), pwszType );
hres = hresMumbleKeyEx(hkTypes, tszType, sam, dwOptions, phk); #else
hres = hresMumbleKeyEx(hkTypes, pwszType, sam, dwOptions, phk); #endif
RegCloseKey(hkTypes); }
if (FAILED(hres)) { *phk = 0; }
ExitBenignOleProcPpv(phk); return hres; }
/*****************************************************************************
* * @doc INTERNAL * * @func HRESULT | JoyReg_OpenPropKey | * * Open the Dinput properties registry key that corresponds to a * device type. This key contains the OEMMapFile and dwFlags2 information * Nominally the location HKLM/REGSTR_PATH_PRIVATEPROPERTIES/DirectInput. * * @parm LPCWSTR | pwszTypeName | * * The name of the type. * * @parm DWORD | sam | * * Desired security access mask. * * @parm OUT PHKEY | phk | * * Receives the opened registry key on success. * * @returns * * Returns a COM error code. The following error codes are * intended to be illustrative and not necessarily comprehensive. * * <c DI_OK> = <c S_OK>: The operation completed successfully. * * <c DIERR_NOTFOUND>: The type was not found. * *****************************************************************************/
STDMETHODIMP JoyReg_OpenPropKey(LPCWSTR pwszType, DWORD sam, DWORD dwOptions, PHKEY phk) { HRESULT hres; HKEY hkTypes; EnterProc(JoyReg_OpenTypeKey, (_ "W", pwszType));
/*
* Note that it is not safe to cache the registry key. * If somebody deletes the registry key, our handle * goes stale and becomes useless. */
hres = hresMumbleKeyEx(HKEY_LOCAL_MACHINE, REGSTR_PATH_DITYPEPROP, sam, REG_OPTION_NON_VOLATILE, &hkTypes);
if ( SUCCEEDED(hres) ) { #ifndef UNICODE
TCHAR tszType[MAX_PATH]; UToA( tszType, cA(tszType), pwszType );
hres = hresMumbleKeyEx(hkTypes, tszType, sam, dwOptions, phk); #else
hres = hresMumbleKeyEx(hkTypes, pwszType, sam, dwOptions, phk); #endif
RegCloseKey(hkTypes); }
if (FAILED(hres)) { *phk = 0; }
ExitBenignOleProcPpv(phk); return hres; }
/*****************************************************************************
* * @doc INTERNAL * * @func HRESULT | JoyReg_GetTypeInfo | * * Obtain information about a non-predefined joystick type. * * @parm LPCWSTR | pwszTypeName | * * The name of the type. * * @parm OUT LPDIJOYTYPEINFO | pjti | * * Receives information about the joystick type. * The caller is assumed to have validated the * <e DIJOYCONFIG.dwSize> field. * * @parm DWORD | fl | * * Zero or more <c DITC_*> flags * which specify which parts of the structure pointed * to by <p pjti> are to be filled in. * * @returns * * Returns a COM error code. The following error codes are * intended to be illustrative and not necessarily comprehensive. * * <c DI_OK> = <c S_OK>: The operation completed successfully. * <c S_FALSE> if some of the data was not available. * * <c DIERR_NOTFOUND>: The joystick type was not found. * *****************************************************************************/
STDMETHODIMP JoyReg_GetTypeInfo(LPCWSTR pwszType, LPDIJOYTYPEINFO pjti, DWORD fl) { HRESULT hres = S_FALSE; HKEY hk; BOOL fPartialData = FALSE; EnterProc(JoyReg_GetTypeInfo, (_ "Wx", pwszType, fl));
ZeroX(pjti->clsidConfig);
if( fl & ( DITC_FLAGS2 | DITC_MAPFILE ) ) { /*
* The new registry branch is likely to be empty for many devices * so don't fail for anything here. */
hres = JoyReg_OpenPropKey(pwszType, KEY_QUERY_VALUE, REG_OPTION_NON_VOLATILE, &hk);
if( SUCCEEDED( hres ) ) { if( fl & DITC_FLAGS2 ) { hres = JoyReg_GetValue(hk, REGSTR_VAL_FLAGS2, REG_BINARY, &pjti->dwFlags2, cbX(pjti->dwFlags2) );
pjti->dwFlags2 &= JOYTYPE_FLAGS2_GETVALID;
if( FAILED( hres ) ) { pjti->dwFlags2 = 0x0; fPartialData = TRUE; } }
if( fl & DITC_MAPFILE ) { hres = JoyReg_GetValue(hk, REGSTR_VAL_JOYOEMMAPFILE, REG_SZ, pjti->wszMapFile, cbX(pjti->wszMapFile)); if( FAILED( hres ) ) { ZeroX(pjti->wszMapFile); fPartialData = TRUE; } }
RegCloseKey(hk); } else { pjti->dwFlags2 = 0x0; ZeroX(pjti->wszMapFile); fPartialData = TRUE; }
hres = S_OK; }
if( fl & DITC_INREGISTRY_DX6 ) { hres = JoyReg_OpenTypeKey(pwszType, KEY_QUERY_VALUE, REG_OPTION_NON_VOLATILE, &hk);
if (SUCCEEDED(hres)) {
if (fl & DITC_REGHWSETTINGS) { hres = JoyReg_GetValue(hk, REGSTR_VAL_JOYOEMDATA, REG_BINARY, &pjti->hws, cbX(pjti->hws)); if (FAILED(hres)) { goto closedone; } }
/*
* Note that this never fails. */ if (fl & DITC_CLSIDCONFIG) { TCHAR tszGuid[ctchGuid]; LONG lRc;
lRc = RegQueryString(hk, REGSTR_VAL_CPLCLSID, tszGuid, cA(tszGuid));
if (lRc == ERROR_SUCCESS && ParseGUID(&pjti->clsidConfig, tszGuid)) { /* Guid is good */ } else { ZeroX(pjti->clsidConfig); } }
if (fl & DITC_DISPLAYNAME) { hres = JoyReg_GetValue(hk, REGSTR_VAL_JOYOEMNAME, REG_SZ, pjti->wszDisplayName, cbX(pjti->wszDisplayName)); if (FAILED(hres)) { goto closedone; } }
#ifndef WINNT
if (fl & DITC_CALLOUT) { hres = JoyReg_GetValue(hk, REGSTR_VAL_JOYOEMCALLOUT, REG_SZ, pjti->wszCallout, cbX(pjti->wszCallout)); if (FAILED(hres)) { ZeroX(pjti->wszCallout); hres = S_FALSE; fPartialData = TRUE; } } #endif
if ( fl & DITC_HARDWAREID ) { hres = JoyReg_GetValue(hk, REGSTR_VAL_JOYOEMHARDWAREID, REG_SZ, pjti->wszHardwareId, cbX(pjti->wszHardwareId)); if ( FAILED(hres)) { ZeroX(pjti->wszHardwareId); hres = S_FALSE; fPartialData = TRUE; } }
if ( fl & DITC_FLAGS1 ) { hres = JoyReg_GetValue(hk, REGSTR_VAL_FLAGS1, REG_BINARY, &pjti->dwFlags1, cbX(pjti->dwFlags1) ); if ( FAILED(hres) ) { pjti->dwFlags1 = 0x0; hres = S_FALSE; fPartialData = TRUE; } pjti->dwFlags1 &= JOYTYPE_FLAGS1_GETVALID; } hres = S_OK;
closedone:; RegCloseKey(hk);
} else { // ISSUE-2001/03/29-timgill debug string code should be higher
// (MarcAnd) this really should be at least sqflError but
// this happens a lot, probably due to not filtering out predefs
SquirtSqflPtszV(sqfl | sqflBenign, TEXT( "IDirectInputJoyConfig::GetTypeInfo: Nonexistent type %lS" ), pwszType); hres = DIERR_NOTFOUND; } }
if( SUCCEEDED( hres ) && fPartialData ) { hres = S_FALSE; }
ExitOleProc(); return hres; }
/*****************************************************************************
* * @doc INTERNAL * * @func HRESULT | JoyReg_SetTypeInfo | * * Store information about a non-predefined joystick type * into the registry. * * @parm HKEY | hkTypeW | * * Registry key to the types branch with write access. * * @parm LPCWSTR | pwszTypeName | * * The name of the type. * * @parm IN LPCDIJOYTYPEINFO | pjti | * * Contains information about the joystick type. * * @parm DWORD | fl | * * Zero or more <c DITC_*> flags * which specify which parts of the structure pointed * to by <p pjti> contain values which are to be set. * * @returns * * Returns a COM error code. The following error codes are * intended to be illustrative and not necessarily comprehensive. * * <c DI_OK> = <c S_OK>: The operation completed successfully. * * <c DIERR_NOTFOUND>: The joystick type was not found. * *****************************************************************************/
STDMETHODIMP JoyReg_SetTypeInfo(HKEY hkTypesW, LPCWSTR pwszType, LPCDIJOYTYPEINFO pjti, DWORD fl) { HRESULT hres = S_OK; /* Vacuous success in case of no flags set */ ULONG lRc; EnterProc(JoyRegSetTypeInfo, (_ "Wx", pwszType, fl));
if( fl & ( DITC_FLAGS2 | DITC_MAPFILE ) ) { HKEY hkProp;
hres = JoyReg_OpenPropKey(pwszType, DI_KEY_ALL_ACCESS, REG_OPTION_NON_VOLATILE, &hkProp);
if( SUCCEEDED( hres ) ) { if( fl & DITC_FLAGS2 ) { DWORD dwTemp; LONG lRc;
/*
* Read and merge any current value so that bits unused in * DX8 can be preserved. Although this is more work now it * should save adding Flags3 support next time. */ AssertF( (pjti->dwFlags2 & ~JOYTYPE_FLAGS2_SETVALID) == 0x0 );
/*
* PREFIX warns (259898) that RegQueryValueEx reads the value * of dwTemp before it is set but then it checks lpData and * zeroes the value before it is used. */ lRc = RegQueryValueEx( hkProp, REGSTR_VAL_FLAGS2, 0, 0, 0, &dwTemp );
if( lRc == ERROR_FILE_NOT_FOUND ) { lRc = ERROR_SUCCESS; dwTemp = cbX( pjti->dwFlags2 ); }
if( lRc == ERROR_SUCCESS ) { if( dwTemp <= cbX( pjti->dwFlags2 ) ) { CAssertF( cbX( dwTemp ) == cbX( pjti->dwFlags2 ) ); JoyReg_GetValue( hkProp, REGSTR_VAL_FLAGS2, REG_BINARY, &dwTemp, cbX( dwTemp ) );
dwTemp &= ~JOYTYPE_FLAGS2_SETVALID; dwTemp |= pjti->dwFlags2;
if( dwTemp ) { hres = JoyReg_SetValue( hkProp, REGSTR_VAL_FLAGS2, REG_BINARY, (PV)&dwTemp, cbX( dwTemp ) ); } else { lRc = RegDeleteValue( hkProp, REGSTR_VAL_FLAGS2 ); if (lRc == ERROR_FILE_NOT_FOUND) { lRc = ERROR_SUCCESS; } hres = hresLe( lRc ); } } else { /*
* Need to double buffer for the extra bytes */ PBYTE pbFlags2;
hres = AllocCbPpv( dwTemp, &pbFlags2 ); if( SUCCEEDED( hres ) ) { if ( ERROR_SUCCESS == RegQueryValueEx( hkProp, REGSTR_VAL_FLAGS2, 0, NULL, pbFlags2, &dwTemp ) ) { CAssertF( JOYTYPE_FLAGS2_SETVALID == JOYTYPE_FLAGS2_GETVALID ); *(PDWORD)pbFlags2 &= ~JOYTYPE_FLAGS2_SETVALID; *(PDWORD)pbFlags2 |= pjti->dwFlags2;
if ( ERROR_SUCCESS == RegSetValueEx( hkProp, REGSTR_VAL_FLAGS2, 0, REG_BINARY, pbFlags2, dwTemp ) ) { hres = S_OK; } else { SquirtSqflPtszV(sqfl | sqflError, TEXT( "IDIJC::SetTypeInfo: failed to write extended Flags2" ) ); hres = E_FAIL; } } else { SquirtSqflPtszV(sqfl | sqflError, TEXT( "IDIJC::SetTypeInfo: failed to read extended Flags2" ) ); hres = E_FAIL; /* Else, something bad happened */ } FreePv( pbFlags2 ); } } } else { SquirtSqflPtszV(sqfl | sqflError, TEXT( "IDIJC::SetTypeInfo: failed to read size of Flags2, error %d" ), lRc ); hres = hresLe( lRc ); }
if( FAILED( hres ) ) { hres = S_FALSE; goto closedoneprop; } }
if( fl & DITC_MAPFILE ) { hres = JoyReg_SetValue(hkProp, REGSTR_VAL_JOYOEMMAPFILE, REG_SZ, pjti->wszMapFile, cbX(pjti->wszMapFile)); if( FAILED(hres) ) { hres = S_FALSE; goto closedoneprop; } }
hres = S_OK; closedoneprop:;
RegCloseKey(hkProp); } else { RPF( "Failed to open DirectInput type property key" ); } }
if( hres == S_OK ) { if( fl & DITC_INREGISTRY_DX6 ) { HKEY hk; DWORD dwOptions = 0;
if ( fl & DITC_VOLATILEREGKEY ) { dwOptions = REG_OPTION_VOLATILE; } else { dwOptions = REG_OPTION_NON_VOLATILE; }
#ifndef UNICODE
{ TCHAR tszType[MAX_PATH];
UToA(tszType, cA(tszType), pwszType);
hres = hresMumbleKeyEx(hkTypesW, tszType, DI_KEY_ALL_ACCESS, dwOptions, &hk);
} #else
hres = hresMumbleKeyEx(hkTypesW, pwszType, DI_KEY_ALL_ACCESS, dwOptions, &hk); #endif
if ( SUCCEEDED(hres) ) {
if (fl & DITC_REGHWSETTINGS) { hres = JoyReg_SetValue(hk, REGSTR_VAL_JOYOEMDATA, REG_BINARY, (PV)&pjti->hws, cbX(pjti->hws)); if (FAILED(hres)) { goto closedone; } }
if (fl & DITC_CLSIDCONFIG) { if (IsEqualGUID(&pjti->clsidConfig, &GUID_Null)) { lRc = RegDeleteValue(hk, REGSTR_VAL_CPLCLSID);
/*
* It is not an error if the key does not already exist. */ if (lRc == ERROR_FILE_NOT_FOUND) { lRc = ERROR_SUCCESS; } } else { TCHAR tszGuid[ctchNameGuid]; NameFromGUID(tszGuid, &pjti->clsidConfig); lRc = RegSetValueEx(hk, REGSTR_VAL_CPLCLSID, 0, REG_SZ, (PV)&tszGuid[ctchNamePrefix], ctchGuid * cbX(tszGuid[0]) ); } if (lRc == ERROR_SUCCESS) { } else { hres = E_FAIL; goto closedone; } }
/* ISSUE-2001/03/29-timgill Needs more data checking
Should make sure string is terminated properly */ if (fl & DITC_DISPLAYNAME) { hres = JoyReg_SetValue(hk, REGSTR_VAL_JOYOEMNAME, REG_SZ, pjti->wszDisplayName, cbX(pjti->wszDisplayName)); if (FAILED(hres)) { goto closedone; } }
#ifndef WINNT
/* ISSUE-2001/03/29-timgill Needs more data checking
Should make sure string is terminated properly */ if (fl & DITC_CALLOUT) { hres = JoyReg_SetValue(hk, REGSTR_VAL_JOYOEMCALLOUT, REG_SZ, pjti->wszCallout, cbX(pjti->wszCallout)); if (FAILED(hres)) { hres = S_FALSE; //continue to go
} } #endif
if ( fl & DITC_HARDWAREID ) { hres = JoyReg_SetValue(hk, REGSTR_VAL_JOYOEMHARDWAREID, REG_SZ, pjti->wszHardwareId, cbX(pjti->wszHardwareId) ); if ( FAILED(hres) ) { hres = S_FALSE; goto closedone; } }
if ( fl & DITC_FLAGS1 ) { AssertF( (pjti->dwFlags1 & ~JOYTYPE_FLAGS1_SETVALID) == 0x0 ); hres = JoyReg_SetValue(hk, REGSTR_VAL_FLAGS1, REG_BINARY, (PV)&pjti->dwFlags1, cbX(pjti->dwFlags1) ); if ( FAILED(hres) ) { hres = S_FALSE; goto closedone; } }
hres = S_OK;
closedone:; RegCloseKey(hk);
} else { hres = E_FAIL; /* Registry problem */ } } }
ExitOleProc(); return hres; }
/*****************************************************************************
* * @doc INTERNAL * * @func HRESULT | JoyReg_OpenConfigKey | * * Open the registry key that accesses joystick configuration data. * * Warning! Do not cache this regkey. * * If the user deletes the key and then re-creates it, * the opened key will go stale and will become useless. * You have to close the key and reopen it. * To avoid worrying about that case, merely open it every time. * * @parm UINT | idJoy | * * Joystick number. * * @parm DWORD | sam | * * Access level desired. * * @parm IN DWORD | dwOptions | * Option flags to RegCreateEx * * @parm PHKEY | phk | * * Receives created registry key. * * @returns * * Returns a COM error code. The following error codes are * intended to be illustrative and not necessarily comprehensive. * * <c DI_OK> = <c S_OK>: The operation completed successfully. * * hresLe(ERROR_FILE_NOT_FOUND): The key does not exist. * *****************************************************************************/
STDMETHODIMP JoyReg_OpenConfigKey(UINT idJoy, DWORD sam, DWORD dwOptions, PHKEY phk) { HRESULT hres; EnterProc(JoyReg_OpenConfigKey, (_ "uxx", idJoy, sam, dwOptions));
#ifdef WINNT
hres = hresMumbleKeyEx(HKEY_LOCAL_MACHINE, REGSTR_PATH_JOYCONFIG REGSTR_SZREGKEY REGSTR_KEY_JOYCURR, sam, REG_OPTION_VOLATILE, phk); #else
{ MMRESULT mmrc = MMSYSERR_ERROR; JOYCAPS caps; /*
* If we can't get the dev caps for the specified joystick, * then use the magic joystick id "-1" to get non-specific * caps. */ mmrc = joyGetDevCaps(idJoy, &caps, cbX(caps)); if ( mmrc != JOYERR_NOERROR ) { mmrc = joyGetDevCaps((DWORD)-1, &caps, cbX(caps)); }
if (mmrc == JOYERR_NOERROR) {
TCHAR tsz[cA(REGSTR_PATH_JOYCONFIG) + 1 + /* backslash */ cA(caps.szRegKey) + 1 + /* backslash */ cA(REGSTR_KEY_JOYCURR) + 1];
/* tsz = MediaResources\Joystick\<drv>\CurrentJoystickSettings */ wsprintf(tsz, TEXT("%s\\%s\\") REGSTR_KEY_JOYCURR, REGSTR_PATH_JOYCONFIG, caps.szRegKey);
hres = hresMumbleKeyEx(HKEY_LOCAL_MACHINE, tsz, sam, REG_OPTION_VOLATILE, phk);
} else { hres = E_FAIL; } } #endif
ExitBenignOleProc(); return hres; }
/*****************************************************************************
* * @doc INTERNAL * * @func HRESULT | JoyReg_OpenSaveKey | * * Open the registry key that accesses joystick saved configurations * * Warning! Do not cache this regkey. * * If the user deletes the key and then re-creates it, * the opened key will go stale and will become useless. * You have to close the key and reopen it. * To avoid worrying about that case, merely open it every time. * * @parm DWORD | dwType | * * Joystick type. * * This is either one of the standard ones in the range * * @parm IN LPCDIJOYCONFIG | pcfg | * * If the dwType represents an OEM type, this should point to a * configuration data structure containing a valid wszType. * * @parm DWORD | sam | * * Access level desired. * * @parm PHKEY | phk | * * Receives created registry key. * * @returns * * Returns a COM error code. The following error codes are * intended to be illustrative and not necessarily comprehensive. * * <c DI_OK> = <c S_OK>: The operation completed successfully. * * hresLe(ERROR_FILE_NOT_FOUND): The key does not exist. * *****************************************************************************/
STDMETHODIMP JoyReg_OpenSaveKey(DWORD dwType, LPCDIJOYCONFIG pcfg, DWORD sam, PHKEY phk) { HRESULT hres; JOYCAPS caps; DWORD dwOptions = 0; EnterProc(JoyReg_OpenSaveKey, (_ "upx", dwType, pcfg, sam));
#ifdef WINNT
lstrcpy(caps.szRegKey, REGSTR_SZREGKEY ); #else
/*
* use the magic joystick id "-1" to get non-specific caps. */
if ( joyGetDevCaps((DWORD)-1, &caps, cbX(caps)) != JOYERR_NOERROR ) { hres = E_FAIL; } else #endif
{ TCHAR tsz[cA(REGSTR_PATH_JOYCONFIG) + 1 + /* backslash */ cA(caps.szRegKey) + 1 + /* backslash */ cA(REGSTR_KEY_JOYSETTINGS) + 1 + /* backslash */ max( cA(REGSTR_KEY_JOYPREDEFN), cA(pcfg->wszType) ) + 1 ];
/* tsz = MediaResources\Joystick\<drv>\JoystickSettings\<Type> */ if ( dwType >= JOY_HW_PREDEFMAX ) { wsprintf(tsz, TEXT("%s\\%s\\%s\\%ls"), REGSTR_PATH_JOYCONFIG, caps.szRegKey, REGSTR_KEY_JOYSETTINGS, pcfg->wszType); } else { /*
* We will probably never have more than the current 11 predefined * joysticks. Assume no more than 99 so %d is as many characters. */ wsprintf(tsz, TEXT("%s\\%s\\%s\\" REGSTR_KEY_JOYPREDEFN), REGSTR_PATH_JOYCONFIG, caps.szRegKey, REGSTR_KEY_JOYSETTINGS, dwType ); }
if ( pcfg->hwc.dwUsageSettings & JOY_US_VOLATILE ) dwOptions = REG_OPTION_VOLATILE; else dwOptions = REG_OPTION_NON_VOLATILE;
hres = hresMumbleKeyEx(HKEY_LOCAL_MACHINE, tsz, sam, dwOptions, phk);
}
ExitOleProc(); return hres; }
/*****************************************************************************
* * @doc INTERNAL * * @func HRESULT | JoyReg_GetSetConfigValue | * * Retrieve or update configuration information about a joystick, * as stored in the registry instance key. * * @parm HKEY | hk | * * Registry key containing fun values. * * @parm LPCTSTR | ptszNValue | * * Registry value name, with "%d" where a joystick number * should be. * * @parm UINT | idJoy | * * Zero-based joystick number. * * @parm DWORD | reg | * * Registry data type expected. * * @parm LPVOID | pvBuf | * * Buffer to receive information from registry (if getting) * or containing value to set. * * @parm DWORD | cb | * * Size of buffer, in bytes. * * @parm BOOL | fSet | * * Nonzer if the value should be set; otherwise, it will be * retrieved. * * @returns * * Returns a COM error code. The following error codes are * intended to be illustrative and not necessarily comprehensive. * * <c DI_OK> = <c S_OK>: The operation completed successfully. * * <c E_FAIL>: Error reading/writing value to/from registry. * *****************************************************************************/
STDMETHODIMP JoyReg_GetSetConfigValue(HKEY hk, LPCTSTR ptszNValue, UINT idJoy, DWORD reg, PV pvBuf, DWORD cb, BOOL fSet) { HRESULT hres; int ctch;
/* Extra +12 because a UINT can be as big as 4 billion */ TCHAR tsz[max( max( max(cA(REGSTR_VAL_JOYNCONFIG), cA(REGSTR_VAL_JOYNOEMNAME)), cA(REGSTR_VAL_JOYNOEMCALLOUT)), cA(REGSTR_VAL_JOYNFFCONFIG)) + 12 + 1];
ctch = wsprintf(tsz, ptszNValue, idJoy + 1); AssertF(ctch < cA(tsz));
if (fSet) { hres = JoyReg_SetValue(hk, tsz, reg, pvBuf, cb); } else { hres = JoyReg_GetValue(hk, tsz, reg, pvBuf, cb); }
return hres;
}
/*****************************************************************************
* * @doc INTERNAL * * @func HRESULT | hresIdJoypInstanceGUID | * * Given a joystick ID obtain the corresponding GUID. * This routine differs in implementation on WINNT and WIN9x * On WINNT there are no predefined GUID for Joystick IDs. * * @parm IN UINT | idJoy | * * Joystick identification number. * * @parm OUT LPGUID | lpguid | * * Receives the joystick GUID. If no mapping exists, * GUID_NULL is passed back * * On Windows NT all joysticks are HID devices. The corresponding function * for WINNT is defined in diWinnt.c * *****************************************************************************/
HRESULT EXTERNAL hResIdJoypInstanceGUID_95 ( UINT idJoy, LPGUID lpguid ) { HRESULT hRes;
hRes = S_OK; if ( idJoy < cA(rgGUID_Joystick) ) { *lpguid = rgGUID_Joystick[idJoy]; } else { hRes = DIERR_NOTFOUND; ZeroX(*lpguid); } return hRes; }
/*****************************************************************************
* * @doc INTERNAL * * @func HRESULT | JoyReg_GetConfigInternal | * * Obtain information about a joystick's configuration. * * @parm UINT | uiJoy | * * Joystick identification number. * * @parm OUT LPDIJOYCONFIG | pcfg | * * Receives information about the joystick configuration. * The caller is assumed to have validated the * <e DIJOYCONFIG.dwSize> field. * * @parm DWORD | fl | * * Zero or more <c DIJC_*> flags * which specify which parts of the structure pointed * to by <p pjc> are to be filled in. * * @returns * * Returns a COM error code. The following error codes are * intended to be illustrative and not necessarily comprehensive. * * <c DI_OK> = <c S_OK>: The operation completed successfully. * * <c DIERR_NOMOREITEMS>: No more joysticks. * *****************************************************************************/
STDMETHODIMP JoyReg_GetConfigInternal(UINT idJoy, LPDIJOYCONFIG pcfg, DWORD fl) { HRESULT hres = E_FAIL;
EnterProc(JoyReg_GetConfigInternal, (_ "upx", idJoy, pcfg, fl));
AssertF((fl & ~DIJC_GETVALID) == 0);
/* We only support (0/16) joysticks */ if ( idJoy < cJoyMax ) { /* Force a rescan of all HID device list
* Some device may have been attached * since we last looked */ DIHid_BuildHidList(FALSE); if (fl & DIJC_GUIDINSTANCE) { hres = hResIdJoypInstanceGUID_WDM(idJoy, &pcfg->guidInstance);
#ifndef WINNT
if ( FAILED(hres) ) { hres = hResIdJoypInstanceGUID_95(idJoy, &pcfg->guidInstance); } #endif
if ( FAILED(hres) ) { goto done; } }
if ( fl & DIJC_INREGISTRY ) { HKEY hk; /* Does the registry entry exist ? */ hres = JoyReg_OpenConfigKey(idJoy, KEY_QUERY_VALUE, REG_OPTION_NON_VOLATILE , &hk); if (SUCCEEDED(hres)) { if (fl & DIJC_REGHWCONFIGTYPE) { hres = JoyReg_GetConfigValue( hk, REGSTR_VAL_JOYNCONFIG, idJoy, REG_BINARY, &pcfg->hwc, cbX(pcfg->hwc)); if (FAILED(hres)) { goto closedone; }
pcfg->wszType[0] = TEXT('\0'); if ( (pcfg->hwc.dwUsageSettings & JOY_US_ISOEM) #ifndef WINNT
||( (pcfg->hwc.dwType >= JOY_HW_PREDEFMIN) &&(pcfg->hwc.dwType < JOY_HW_PREDEFMAX) ) #endif
) { hres = JoyReg_GetConfigValue( hk, REGSTR_VAL_JOYNOEMNAME, idJoy, REG_SZ, pcfg->wszType, cbX(pcfg->wszType)); if (FAILED(hres)) { goto closedone; } } }
#ifndef WINNT
if (fl & DIJC_CALLOUT) { pcfg->wszCallout[0] = TEXT('\0'); hres = JoyReg_GetConfigValue( hk, REGSTR_VAL_JOYNOEMCALLOUT, idJoy, REG_SZ, pcfg->wszCallout, cbX(pcfg->wszCallout)); if (FAILED(hres)) { ZeroX(pcfg->wszCallout); hres = S_FALSE; /* Note that we fall through and let hres = S_OK */ } } #endif
if (fl & DIJC_GAIN) { /*
* If there is no FF configuration, then * default to DI_FFNOMINALMAX gain. */ hres = JoyReg_GetConfigValue(hk, REGSTR_VAL_JOYNFFCONFIG, idJoy, REG_BINARY, &pcfg->dwGain, cbX(pcfg->dwGain));
if (SUCCEEDED(hres) && ISVALIDGAIN(pcfg->dwGain)) { /* Leave it alone; it's good */ } else { hres = S_FALSE; pcfg->dwGain = DI_FFNOMINALMAX; /* Note that we fall through and let hres = S_OK */ } }
if ( fl & DIJC_WDMGAMEPORT ) { PBUSDEVICEINFO pbdi; /*
* If there is no Gameport Associated with this device * then it must be a USB device */
DllEnterCrit(); if ( pbdi = pbdiFromJoyId(idJoy) ) { pcfg->guidGameport = pbdi->guid; //lstrcpyW(pcfg->wszGameport, pbdi->wszDisplayName);
} else { ZeroX(pcfg->guidGameport); //pcfg->wszGameport[0] = TEXT('\0');
}
DllLeaveCrit(); }
}
closedone: RegCloseKey(hk); } } else { hres = DIERR_NOMOREITEMS; }
done: ExitBenignOleProc(); return hres; }
/*****************************************************************************
* * @doc INTERNAL * * @func HRESULT | JoyReg_GetConfig | * * Obtain information about a joystick's configuration, * taking the *naive* MSGAME.VXD driver into account. * * @parm UINT | uiJoy | * * Joystick identification number. * * @parm OUT LPDIJOYCONFIG | pcfg | * * Receives information about the joystick configuration. * The caller is assumed to have validated the * <e DIJOYCONFIG.dwSize> field. * * @parm DWORD | fl | * * Zero or more <c DIJC_*> flags * which specify which parts of the structure pointed * to by <p pjc> are to be filled in. * * @returns * * Returns a COM error code. The following error codes are * intended to be illustrative and not necessarily comprehensive. * * <c DI_OK> = <c S_OK>: The operation completed successfully. * * <c DIERR_NOMOREITEMS>: No more joysticks. * *****************************************************************************/
STDMETHODIMP JoyReg_GetConfig(UINT idJoy, LPDIJOYCONFIG pcfg, DWORD fl) { HRESULT hres; GUID guid;
EnterProc(JoyReg_GetConfig, (_ "upx", idJoy, pcfg, fl));
AssertF((fl & ~DIJC_GETVALID) == 0);
/*
* First determine if the joystick exits * On NT, we use WDM driver. * On Win9x, if WDM fails, use static guids. */ hres = hResIdJoypInstanceGUID_WDM(idJoy, &guid);
#ifndef WINNT
if ( FAILED(hres) ) { hres = hResIdJoypInstanceGUID_95(idJoy, &guid); } #endif
if ( SUCCEEDED( hres) ) {
hres = JoyReg_GetConfigInternal(idJoy, pcfg, fl);
#ifndef WINNT
/***************************************************
* * Beginning of hack for *naive* Sidewinder Gamepad. * * The gamepad needs to be polled sixteen times * before it realizes what is going on. * ***************************************************/
if (SUCCEEDED(hres) && (fl & DIJC_CALLOUT)) {
static WCHAR s_wszMSGAME[] = L"MSGAME.VXD";
if (memcmp(pcfg->wszCallout, s_wszMSGAME, cbX(s_wszMSGAME)) == 0) { SquirtSqflPtszV(sqfl, TEXT("Making bonus polls for Sidewinder"));
/*
* Sigh. It's a Sidewinder. Make sixteen * bonus polls to shake the stick into submission. * * There's no point in doing this over and over if we're * in some kind of loop so make sure a "reasonable" * length of time has passed since last time we tried. * 3 seconds is a little less than the current CPL * background refresh rate. */
if ( !g_dwLastBonusPoll || ( GetTickCount() - g_dwLastBonusPoll > 3000 ) ) { JOYINFOEX ji; int i; DWORD dwWait;
ji.dwSize = cbX(ji); ji.dwFlags = JOY_RETURNALL; for (i = 0; i < 16; i++) { MMRESULT mmrc = joyGetPosEx(idJoy, &ji); SquirtSqflPtszV(sqfl, TEXT("joyGetPosEx(%d) = %d"), idJoy, mmrc); /*
* Sleep 10ms between each poll because that * seems to help a bit. */ Sleep(10); }
/*
* Bonus hack! Now sleep for some time. * The amount of time we need to sleep is CPU-speed * dependent, so we'll grab the sleep time from the * registry to allow us to tweak it later. * * What a shame. */ dwWait = RegQueryDIDword(NULL, REGSTR_VAL_GAMEPADDELAY, 100); if (dwWait > 10 * 1000) { dwWait = 10 * 1000; }
Sleep(dwWait);
/*
* And then check again. */ hres = JoyReg_GetConfigInternal(idJoy, pcfg, fl);
g_dwLastBonusPoll = GetTickCount(); } }
} /***************************************************
* * End of hack for *naive* Sidewinder Gamepad. * ***************************************************/
#endif
}
return hres; }
#ifndef WINNT
/*****************************************************************************
* * @doc INTERNAL * * @func HRESULT | JoyReg_JoyIdToDeviceInterface_95 | * * Given a joystick ID number, obtain the device interface * corresponding to it. * * @parm UINT | idJoy | * * Joystick ID number, zero-based. * * @parm PVXDINITPARMS | pvip | * * Receives init parameters from the driver. * * @parm LPTSTR | ptszBuf | * * A buffer of size <c MAX_PATH> in which the device interface * path is built. Note that we can get away with a buffer of * this size, since the code path exists only on Windows 95, * and Windows 95 does not support paths longer than <c MAX_PATH>. * (I.e., there ain't no \\?\ support in Win95.) * * @returns * * A pointer to the part of the <p ptszBuf> buffer that * contains the actual device interface path. * *****************************************************************************/
LPSTR EXTERNAL JoyReg_JoyIdToDeviceInterface_95(UINT idJoy, PVXDINITPARMS pvip, LPSTR ptszBuf) { UINT cwch; HRESULT hres; LPSTR ptszRc;
hres = Hel_Joy_GetInitParms(idJoy, pvip); if (SUCCEEDED(hres)) {
/*
* The length counter includes the terminating null. */ cwch = LOWORD(pvip->dwFilenameLengths);
/*
* The name that comes from HID is "\DosDevices\blah" * but we want to use "\\.\blah". So check if it indeed * of the form "\DosDevices\blah" and if so, convert it. * If not, then give up. * * For the string to possibly be a "\DosDevices\", it * needs to be of length 12 or longer. */
if (cwch >= 12 && cwch < MAX_PATH) {
/*
* WideCharToMultiByte does parameter validation so we * don't have to. */ WideCharToMultiByte(CP_ACP, 0, pvip->pFilenameBuffer, cwch, ptszBuf, MAX_PATH, 0, 0);
/*
* The 11th (zero-based) character must be a backslash. * And the value of cwch had better be right. */ if (ptszBuf[cwch-1] == ('\0') && ptszBuf[11] == ('\\')) {
/*
* Wipe out the backslash and make sure the lead-in * is "\DosDevices". */ ptszBuf[11] = ('\0'); if (lstrcmpiA(ptszBuf, ("\\DosDevices")) == 0) { /*
* Create a "\\.\" at the start of the string. * Note! This code never runs on Alphas so we * can do evil unaligned data accesses. * * (Actually, 8 is a multiple of 4, so everything * is aligned after all.) */ *(LPDWORD)&ptszBuf[8] = 0x5C2E5C5C;
ptszRc = &ptszBuf[8]; } else { ptszRc = NULL; } } else { ptszRc = NULL; } } else { ptszRc = NULL; } } else { ptszRc = NULL; }
return ptszRc; }
/*****************************************************************************
* * @doc INTERNAL * * @func void | JoyReg_SetCalibration | * * Store information about a joystick's configuration, * shadowing the information back into the HID side of * things as well. * * @parm UINT | uiJoy | * * Joystick identification number. * * @parm LPJOYREGHWCONFIG | phwc | * * Contains information about the joystick capabilities. * This value supercedes the value in the <p pcfg>. * * @parm LPCDIJOYCONFIG | pcfg | * * Contains information about the joystick configuration. * The caller is assumed to have validated all fields. * *****************************************************************************/
STDMETHODIMP TFORM(CDIObj_FindDevice)(PV pdiT, REFGUID rguid, LPCTSTR ptszName, LPGUID pguidOut);
void EXTERNAL JoyReg_SetCalibration(UINT idJoy, LPJOYREGHWCONFIG phwc) { HRESULT hres; VXDINITPARMS vip; GUID guid; CHAR tsz[MAX_PATH]; LPSTR pszPath; TCHAR ptszPath[MAX_PATH]; EnterProc(JoyReg_SetCalibration, (_ "up", idJoy, phwc));
pszPath = JoyReg_JoyIdToDeviceInterface_95(idJoy, &vip, tsz);
if ( pszPath ) #ifdef UNICODE
AToU( ptszPath, MAX_PATH, pszPath ); #else
lstrcpy( (LPSTR)ptszPath, pszPath ); #endif
if (pszPath && SUCCEEDED(CDIObj_FindDeviceInternal(ptszPath, &guid))) { IDirectInputDeviceCallback *pdcb; #ifdef DEBUG
CREATEDCB CreateDcb; #endif
#ifdef DEBUG
/*
* If the associated HID device got unplugged, then * the instance GUID is no more. So don't get upset * if we can't find it. But if we do find it, then * it had better be a HID device. * * CHid_New will properly fail if the associated * device is not around. */ hres = hresFindInstanceGUID(&guid, &CreateDcb, 1); AssertF(fLimpFF(SUCCEEDED(hres), CreateDcb == CHid_New)); #endif
if (SUCCEEDED(hres = CHid_New(0, &guid, &IID_IDirectInputDeviceCallback, (PPV)&pdcb))) { LPDIDATAFORMAT pdf;
/*
* The VXDINITPARAMS structure tells us where JOYHID * decided to place each of the axes. Follow that * table to put them into their corresponding location * in the HID side. */ hres = pdcb->lpVtbl->GetDataFormat(pdcb, &pdf); if (SUCCEEDED(hres)) { UINT uiAxis; DIPROPINFO propi;
propi.pguid = DIPROP_SPECIFICCALIBRATION;
/*
* For each axis... */ for (uiAxis = 0; uiAxis < 6; uiAxis++) { DWORD dwUsage = vip.Usages[uiAxis]; /*
* If the axis is mapped to a usage... */ if (dwUsage) { /*
* Convert the usage into an object index. */ hres = pdcb->lpVtbl->MapUsage(pdcb, dwUsage, &propi.iobj); if (SUCCEEDED(hres)) { DIPROPCAL cal;
/*
* Convert the old-style calibration into * a new-style calibration. */ #define CopyCalibration(f, ui) \
cal.l##f = (&phwc->hwv.jrvHardware.jp##f.dwX)[ui]
CopyCalibration(Min, uiAxis); CopyCalibration(Max, uiAxis); CopyCalibration(Center, uiAxis);
#undef CopyCalibration
/*
* Set the calibration property on the object. */ propi.dwDevType = pdf->rgodf[propi.iobj].dwType; hres = pdcb->lpVtbl->SetProperty(pdcb, &propi, &cal.diph); } } } }
Invoke_Release(&pdcb); } }
ExitProc(); } #endif
/*****************************************************************************
* * @doc INTERNAL * * @func HRESULT | JoyReg_SetHWConfig | * * Store information about a joystick's <t JOYREGHWCONFIG>. * * @parm UINT | uiJoy | * * Joystick identification number. * * @parm LPJOYREGHWCONFIG | phwc | * * Contains information about the joystick capabilities. * This value supercedes the value in the <p pcfg>. * * @parm LPCDIJOYCONFIG | pcfg | * * Contains information about the joystick configuration. * The caller is assumed to have validated all fields. * * @parm HKEY | hk | * * The type key we are munging. * * * @returns * * Returns a COM error code. The following error codes are * intended to be illustrative and not necessarily comprehensive. * * <c DI_OK> = <c S_OK>: The operation completed successfully. * *****************************************************************************/
HRESULT INTERNAL JoyReg_SetHWConfig(UINT idJoy, LPJOYREGHWCONFIG phwc, LPCDIJOYCONFIG pcfg, HKEY hk) { HRESULT hres; HKEY hkSave; DWORD dwSam;
/*
* The caller has set phwc->dwType, so use it to determine * where the data comes from or goes to. */ if ( phwc->dwType == JOY_HW_NONE ) { /*
* Nothing to do */ } else if ( phwc->dwType == JOY_HW_CUSTOM ) { /*
/* ISSUE-2001/03/29-timgill Custom HWConfig not handled correctly
* We don't know the type name and the only time we can look * it up is when were modifying an existing config so although we * could store the config, we'd never be able to get it back. * Should return no better than S_FALSE. This will have to wait. */ } else { /*
* Try to access saved values */
// ISSUE-2001/03/29-timgill Dangerous type cast
PDWORD pdw = (PDWORD)&phwc->hwv;
dwSam = KEY_QUERY_VALUE;
while ( pdw < &phwc->dwType ) { if ( *pdw ) { /*
* Real config data so write it */ dwSam = KEY_SET_VALUE; break; } pdw++; }
/*
* If the device is autoloaded and yet the user is manually assigning it * to an ID, set the volatile flag. The flag will be set to the driver * defined value if a driver ever gets hotplug assigned to this ID but if * not, this makes sure that the settings are removed on next reboot. */ if (phwc->hws.dwFlags & JOY_HWS_AUTOLOAD) { phwc->dwUsageSettings |= JOY_US_VOLATILE; }
hres = JoyReg_OpenSaveKey( phwc->dwType, pcfg, dwSam, &hkSave );
if ( SUCCEEDED(hres) ) { if ( dwSam == KEY_SET_VALUE ) { hres = JoyReg_SetConfigValue(hkSave, REGSTR_VAL_JOYNCONFIG, idJoy, REG_BINARY, phwc, cbX(*phwc)); if ( FAILED(hres) ) { // Report the error but live with it
RPF("JoyReg_SetConfig: failed to set saved config %08x", hres ); } } else { JOYREGHWCONFIG hwc;
/*
* Read it into an extra buffer because we only want it * if it's complete. */ hres = JoyReg_GetConfigValue(hkSave, REGSTR_VAL_JOYNCONFIG, idJoy, REG_BINARY, &hwc, cbX(hwc)); if ( hres == S_OK ) { // Assert hws is first and no gap before dwUsageSettings
CAssertF( FIELD_OFFSET( JOYREGHWCONFIG, hws ) == 0 ); CAssertF( FIELD_OFFSET( JOYREGHWCONFIG, dwUsageSettings ) == sizeof( hwc.hws ) );
// Copy the whole structure except the hws
memcpy( &phwc->dwUsageSettings, &hwc.dwUsageSettings, sizeof( hwc ) - sizeof( hwc.hws ) ); } }
RegCloseKey( hkSave ); } /*
* If we failed to read, there's probably nothing there and the * structure is set up already for a blank config. * If we failed to write there probably not much we can do */ }
hres = JoyReg_SetConfigValue(hk, REGSTR_VAL_JOYNCONFIG, idJoy, REG_BINARY, phwc, cbX(*phwc)); if (FAILED(hres)) { goto done; }
if (phwc->dwUsageSettings & JOY_US_ISOEM) {
hres = JoyReg_SetConfigValue( hk, REGSTR_VAL_JOYNOEMNAME, idJoy, REG_SZ, pcfg->wszType, cbX(pcfg->wszType));
} else { hres = JoyReg_SetConfigValue( hk, REGSTR_VAL_JOYNOEMNAME, idJoy, REG_SZ, 0, 0); }
done:;
return hres; }
/*****************************************************************************
* * @doc INTERNAL * * @func HRESULT | JoyReg_SetConfig | * * Store information about a joystick's configuration. * * @parm UINT | uiJoy | * * Joystick identification number. * * @parm JOYREGHWCONFIG | phwc | * * Contains information about the joystick capabilities. * This value supercedes the value in the <p pcfg>. * It may be modified if we needed to load the config * info from the saved settings. * * @parm LPCDIJOYCONFIG | pcfg | * * Contains information about the joystick configuration. * The caller is assumed to have validated all fields. * * @parm DWORD | fl | * * Zero or more <c DIJC_*> flags * which specify which parts of the structures pointed * to by <p phwc> and <p pjc> are to be written out. * * @returns * * Returns a COM error code. The following error codes are * intended to be illustrative and not necessarily comprehensive. * * <c DI_OK> = <c S_OK>: The operation completed successfully. * *****************************************************************************/
JOYREGHWVALUES null_hwv = { 0};
STDMETHODIMP JoyReg_SetConfig(UINT idJoy, LPJOYREGHWCONFIG phwc, LPCDIJOYCONFIG pcfg, DWORD fl) { HRESULT hres; EnterProc(JoyReg_SetConfig, (_ "uppx", idJoy, phwc, pcfg, fl));
AssertF((fl & ~DIJC_INTERNALSETVALID) == 0);
if (idJoy < cJoyMax ) {
if (fl & DIJC_INREGISTRY) { HKEY hk; DWORD dwOptions = 0;
hres = JoyReg_OpenConfigKey(idJoy, KEY_SET_VALUE, dwOptions, &hk);
if (SUCCEEDED(hres)) {
if (fl & DIJC_REGHWCONFIGTYPE) { hres = JoyReg_SetHWConfig(idJoy, phwc, pcfg, hk);
if (FAILED(hres)) { goto closedone; }
#ifndef WINNT
if (fl & DIJC_UPDATEALIAS) { JoyReg_SetCalibration(idJoy, phwc); } #endif
}
#ifndef WINNT
if (fl & DIJC_CALLOUT) { hres = JoyReg_SetConfigValue( hk, REGSTR_VAL_JOYNOEMCALLOUT, idJoy, REG_SZ, pcfg->wszCallout, cbX(pcfg->wszCallout)); if (FAILED(hres)) { hres = S_FALSE; //continue to go
} } #endif
if (fl & DIJC_GAIN) { if (ISVALIDGAIN(pcfg->dwGain)) {
/*
* If restoring to nominal, then the key * can be deleted; the default value will * be assumed subsequently. */ if (pcfg->dwGain == DI_FFNOMINALMAX) { hres = JoyReg_SetConfigValue(hk, TEXT("Joystick%dFFConfiguration"), idJoy, REG_SZ, 0, 0); } else { hres = JoyReg_SetConfigValue(hk, TEXT("Joystick%dFFConfiguration"), idJoy, REG_BINARY, &pcfg->dwGain, cbX(pcfg->dwGain)); }
if (FAILED(hres)) { hres = S_FALSE; goto closedone; } } else { RPF("ERROR: SetConfig: Invalid dwGain"); hres = E_INVALIDARG; goto closedone; } }
hres = S_OK;
closedone:; RegCloseKey(hk); } } else { hres = S_OK; }
} else { hres = E_FAIL; }
ExitOleProc(); return hres; }
/*****************************************************************************
* * @doc INTERNAL * * @func int | ibJoyPosAxis | * * Returns the offset of the <p iAxis>'th joystick axis * in the <t JOYPOS> structure. * * @parm int | iAxis | * * 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 ibJoyPosAxis(iAxis) \
(FIELD_OFFSET(JOYPOS, dwX) + cbX(DWORD) * (iAxis)) \
#define pJoyValue(jp, i) \
(LPDWORD)pvAddPvCb(&(jp), ibJoyPosAxis(i)) \
/*
* The following doesn't do anything at runtime. It is a compile-time * check that everything is okay. */ void INLINE JoyReg_CheckJoyPosAxis(void) { #define CheckAxis(x) \
CAssertF(ibJoyPosAxis(iJoyPosAxis##x) == FIELD_OFFSET(JOYPOS, dw##x))
CheckAxis(X); CheckAxis(Y); CheckAxis(Z); CheckAxis(R); CheckAxis(U); CheckAxis(V);
#undef CheckAxis
}
/*****************************************************************************
* * @doc INTERNAL * * @func HRESULT | JoyReg_IsValidUserValues | * * Retermine whether the values are ostensibly valid. * * @parm IN LPCDIJOYUSERVALUES | pjuv | * * Contains information about the user joystick configuration. * * @returns * * Returns a COM error code. The following error codes are * intended to be illustrative and not necessarily comprehensive. * * <c DI_OK> = <c S_OK>: The operation completed successfully. * * <c DIERR_INVALIDPARAM> = <c E_INVALIDARG>: * Something looks bad. * *****************************************************************************/
STDMETHODIMP JoyReg_IsValidUserValues(LPCDIJOYUSERVALUES pjuv) { HRESULT hres; int iAxis;
/*
* First set up the values to values that are out of range so * that we will fall back to defaults. */ for (iAxis = 0; iAxis < cJoyPosAxisMax; iAxis++) { if ((int)*pJoyValue(pjuv->ruv.jrvRanges.jpMax, iAxis) < 0) { RPF("JOYUSERVALUES: Negative jpMax not a good idea"); goto bad; } if (*pJoyValue(pjuv->ruv.jrvRanges.jpMin, iAxis) > *pJoyValue(pjuv->ruv.jrvRanges.jpMax, iAxis)) { RPF("JOYUSERVALUES: Min > Max not a good idea"); goto bad; }
if (!fInOrder(0, *pJoyValue(pjuv->ruv.jpDeadZone, iAxis), 100)) { RPF("JOYUSERVALUES: DeadZone > 100 not a good idea"); goto bad; } }
hres = S_OK;
return hres;
bad:; hres = E_INVALIDARG; return hres;
}
/*****************************************************************************
* * @doc INTERNAL * * @func HRESULT | JoyReg_GetUserValues | * * Obtain information about user settings for the joystick. * * * @parm IN OUT LPDIJOYUSERVALUES | pjuv | * * Receives information about the user joystick configuration. * The caller is assumed to have validated the * <e DIJOYUSERVALUES.dwSize> field. * * @parm DWORD | fl | * * Zero or more <c DIJU_*> flags specifying which parts * of the <t DIJOYUSERVALUES> structure contain values * which are to be retrieved. * * @returns * * Returns a COM error code. The following error codes are * intended to be illustrative and not necessarily comprehensive. * * <c DI_OK> = <c S_OK>: The operation completed successfully. * * <c DIERR_INVALIDPARAM> = <c E_INVALIDARG>: One or more * parameters was invalid. * *****************************************************************************/
STDMETHODIMP JoyReg_GetUserValues(LPDIJOYUSERVALUES pjuv, DWORD fl) { HRESULT hres; HKEY hk; LONG lRc; EnterProc(JoyReg_GetUserValues, (_ "px", pjuv, fl));
hres = S_OK; /* If nothing happens, then success */
if (fl & DIJU_USERVALUES) {
/*
* Okay, now get the user settings. * * If anything goes wrong, then just limp with the default values. */ lRc = RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGSTR_PATH_JOYCONFIG, 0, KEY_QUERY_VALUE, &hk); if (lRc == ERROR_SUCCESS) {
hres = JoyReg_GetValue(hk, REGSTR_VAL_JOYUSERVALUES, REG_BINARY, &pjuv->ruv, cbX(pjuv->ruv)); if (SUCCEEDED(hres)) { /*
* Sanity-check the values. If anything is screwy, * then fall back to the defaults. */ hres = JoyReg_IsValidUserValues(pjuv);
}
if (FAILED(hres)) { /*
* Oh well. Just use the default values, then. * * Stolen from ibmjoy\msjstick.c. */ ZeroMemory(&pjuv->ruv, cbX(pjuv->ruv));
#define DEFAULT_RANGE_MAX 65535
#define DEFAULT_TIMEOUT 5000
#define DEFAULT_DEADZONE 5
pjuv->ruv.jrvRanges.jpMax.dwX = DEFAULT_RANGE_MAX; pjuv->ruv.jrvRanges.jpMax.dwY = DEFAULT_RANGE_MAX; pjuv->ruv.jrvRanges.jpMax.dwZ = DEFAULT_RANGE_MAX; pjuv->ruv.jrvRanges.jpMax.dwR = DEFAULT_RANGE_MAX; pjuv->ruv.jrvRanges.jpMax.dwU = DEFAULT_RANGE_MAX; pjuv->ruv.jrvRanges.jpMax.dwV = DEFAULT_RANGE_MAX; pjuv->ruv.jpDeadZone.dwX = DEFAULT_DEADZONE; pjuv->ruv.jpDeadZone.dwY = DEFAULT_DEADZONE; pjuv->ruv.dwTimeOut = DEFAULT_TIMEOUT; }
RegCloseKey(hk); } }
if (fl & DIJU_INDRIVERREGISTRY) { hres = JoyReg_OpenConfigKey((UINT)-1, KEY_QUERY_VALUE, FALSE, &hk);
if (SUCCEEDED(hres)) {
if (fl & DIJU_GLOBALDRIVER) {
LONG lRc;
/*
* If it doesn't work, then return the default value * of "MSANALOG.VXD". We can't blindly use * JoyReg_GetValue, because that treats a nonexistent * value as having a default of the null string. */ lRc = RegQueryValueEx(hk, REGSTR_VAL_JOYOEMCALLOUT, 0, 0, 0, 0); if ((lRc == ERROR_SUCCESS || lRc == ERROR_MORE_DATA) && SUCCEEDED( hres = JoyReg_GetValue(hk, REGSTR_VAL_JOYOEMCALLOUT, REG_SZ, pjuv->wszGlobalDriver, cbX(pjuv->wszGlobalDriver)))) { /* Yay, it worked */ } else { CopyMemory(pjuv->wszGlobalDriver, c_wszDefPortDriver, cbX(c_wszDefPortDriver)); }
}
if (fl & DIJU_GAMEPORTEMULATOR) {
/*
* If it doesn't work, then just return a null string. */ hres = JoyReg_GetValue(hk, REGSTR_VAL_JOYGAMEPORTEMULATOR, REG_SZ, pjuv->wszGameportEmulator, cbX(pjuv->wszGameportEmulator)); if (FAILED(hres)) { pjuv->wszGameportEmulator[0] = TEXT('\0'); }
}
RegCloseKey(hk); }
}
/*
* Warning! CJoy_InitRanges() assumes this never fails. */ hres = S_OK;
ExitOleProcR(); return hres; }
/*****************************************************************************
* * @doc INTERNAL * * @func HRESULT | JoyReg_SetUserValues | * * Store information about user settings for the joystick. * * * @parm IN LPCDIJOYUSERVALUES | pjuv | * * Contains information about the user joystick configuration. * The caller is assumed to have validated the * <e DIJOYUSERVALUES.dwSize> field. * * @parm DWORD | fl | * * Zero or more <c DIJU_*> flags specifying which parts * of the <t DIJOYUSERVALUES> structure contain values * which are to be set. * * @returns * * Returns a COM error code. The following error codes are * intended to be illustrative and not necessarily comprehensive. * * <c DI_OK> = <c S_OK>: The operation completed successfully. * * <c DIERR_INVALIDPARAM> = <c E_INVALIDARG>: One or more * parameters was invalid. * *****************************************************************************/
STDMETHODIMP JoyReg_SetUserValues(LPCDIJOYUSERVALUES pjuv, DWORD fl) { HRESULT hres = E_FAIL; HKEY hk; EnterProc(JoyReg_SetUserValues, (_ "px", pjuv, fl));
if (fl & DIJU_USERVALUES) {
/*
* See if the values are sane. */ if (fl & DIJU_USERVALUES) { hres = JoyReg_IsValidUserValues(pjuv); if (FAILED(hres)) { goto done; } }
/*
* Off to the registry we go. */
hres = hresMumbleKeyEx(HKEY_LOCAL_MACHINE, REGSTR_PATH_JOYCONFIG, DI_KEY_ALL_ACCESS, REG_OPTION_NON_VOLATILE, &hk);
if (SUCCEEDED(hres)) {
hres = JoyReg_SetValue(hk, REGSTR_VAL_JOYUSERVALUES, REG_BINARY, &pjuv->ruv, cbX(pjuv->ruv)); RegCloseKey(hk);
if (FAILED(hres)) { goto done; } } else { goto done; } }
if (fl & DIJU_INDRIVERREGISTRY) {
hres = JoyReg_OpenConfigKey((UINT)-1, KEY_SET_VALUE, FALSE, &hk);
if (SUCCEEDED(hres)) {
if (fl & DIJU_GLOBALDRIVER) { /*
* This is a weird key. The default value is * "MSANALOG.VXD", so if we get a null string, we * can't use JoyReg_SetValue, because that will * delete the key. */ if (pjuv->wszGlobalDriver[0]) { hres = JoyReg_SetValue(hk, REGSTR_VAL_JOYOEMCALLOUT, REG_SZ, pjuv->wszGlobalDriver, cbX(pjuv->wszGlobalDriver)); } else { LONG lRc; lRc = RegSetValueEx(hk, REGSTR_VAL_JOYOEMCALLOUT, 0, REG_SZ, (PV)TEXT(""), cbCtch(1)); if (lRc == ERROR_SUCCESS) { hres = S_OK; } else { RPF("Unable to write %s to registry", REGSTR_VAL_JOYOEMCALLOUT); hres = E_FAIL; /* Else, something bad happened */ } } if (FAILED(hres)) { goto regdone; } }
if (fl & DIJU_GAMEPORTEMULATOR) {
hres = JoyReg_SetValue(hk, REGSTR_VAL_JOYGAMEPORTEMULATOR, REG_SZ, pjuv->wszGameportEmulator, cbX(pjuv->wszGameportEmulator)); if (FAILED(hres)) { goto regdone; } }
regdone:; RegCloseKey(hk);
} else { goto done; } }
done:; ExitOleProcR(); return hres; }
/*****************************************************************************
* * @doc INTERNAL * * @func HRESULT | JoyReg_OpenFFKey | * * Given a type key, move to its force feedback subkey. * * @parm HKEY | hkType | * * The parent type key. * * @parm REGSAM | sam | * * Access level desired. * * @parm PHKEY | phk | * * Receives created registry key. * * @returns * * Returns a COM error code. The following error codes are * intended to be illustrative and not necessarily comprehensive. * * <c DI_OK> = <c S_OK>: The operation completed successfully. * * <c DIERR_NOTFOUND>: Couldn't open the key. * *****************************************************************************/
STDMETHODIMP JoyReg_OpenFFKey(HKEY hkType, REGSAM sam, PHKEY phk) { HRESULT hres; EnterProc(JoyReg_OpenFFKey, (_ "xx", hkType, sam));
*phk = 0;
if (hkType) { if (RegOpenKeyEx(hkType, TEXT("OEMForceFeedback"), 0, sam, phk) == 0) { hres = S_OK; } else { hres = E_FAIL; } } else { hres = DIERR_NOTFOUND; }
ExitBenignOleProc(); return hres; }
/*****************************************************************************
* * @doc INTERNAL * * @func TCHAR | CJoyCfg_CharFromType | * * Convert a predefined type number to a character. * * @func UINT | CJoyCfg_TypeFromChar | * * Convert a character back to a predefined type number. * *****************************************************************************/
#define JoyCfg_CharFromType(t) ((TCHAR)(L'0' + t))
#define JoyCfg_TypeFromChar(tch) ((tch) - L'0')
/*****************************************************************************
* * @doc EXTERNAL * * @func HRESULT | JoyReg_GetPredefTypeInfo | * * Obtain information about a predefined joystick type. * * @parm LPCWSTR | pwszType | * * Points to the name of the type. It is known to begin * with a "#". The remainder has not yet been parsed. * * @parm IN OUT LPDIJOYTYPEINFO | pjti | * * Receives information about the joystick type, * already validated. * * @parm DWORD | dwFlags | * * Zero or more <c DITC_*> flags * which specify which parts of the structure pointed * to by <p pjti> are to be filled in. * * @returns * * Returns a COM error code. The following error codes are * intended to be illustrative and not necessarily comprehensive. * * <c DI_OK> = <c S_OK>: The operation completed successfully. * * <c DIERR_NOTFOUND>: The joystick type was not found. * *****************************************************************************/
HRESULT EXTERNAL JoyReg_GetPredefTypeInfo(LPCWSTR pwszType, LPDIJOYTYPEINFO pjti, DWORD fl) { HRESULT hres; UINT itype; EnterProcI(JoyReg_GetPredefTypeInfo, (_ "Wpx", pwszType, pjti, fl));
AssertF(pwszType[0] == L'#');
itype = JoyCfg_TypeFromChar(pwszType[1]);
if (fInOrder(JOY_HW_PREDEFMIN, itype, JOY_HW_PREDEFMAX) && pwszType[2] == L'\0') { /*
* No real point in checking the bits in fl, since * setting it up is so easy. */ pjti->hws = c_rghwsPredef[itype - JOY_HW_PREDEFMIN]; LoadStringW(g_hinst, IDS_PREDEFJOYTYPE + itype, pjti->wszDisplayName, cA(pjti->wszDisplayName)); pjti->wszCallout[0] = L'\0';
ZeroX(pjti->clsidConfig);
pjti->dwFlags1 = 0x0;
if ( fl & DITC_HARDWAREID ) { lstrcpyW(pjti->wszHardwareId, c_rghwIdPredef[itype-JOY_HW_PREDEFMIN] ); }
pjti->dwFlags2 = 0x0;
pjti->wszMapFile[0] = L'\0';
hres = S_OK; } else { hres = DIERR_NOTFOUND; }
ExitOleProc(); return hres; }
#if 0 //don't delete it now.
/*****************************************************************************
* * @doc INTERNAL * * @func HRESULT | JoyCfg_GetIDByOemName | * * Get the Id by OEMNAME * * @parm IN LPTSTR | szOEMNAME | * * String used to find the ID. * * @parm IN LPUNIT | lpID | * * The ID to get. * * @returns * * A COM success code unless the current configuration key could not * be opened, or could not find the OEMNAME. * *****************************************************************************/
HRESULT EXTERNAL JoyReg_GetIDByOemName( LPTSTR szOemName, PUINT pId ) { HRESULT hres = E_FAIL; LONG lRc; HKEY hkCurrCfg; UINT JoyId; TCHAR szTestName[MAX_JOYSTRING]; TCHAR szOemNameKey[MAX_JOYSTRING]; DWORD cb;
EnterProcI(JoyReg_GetIDByOemName, (_ "sp", szOemName, pId ));
hres = JoyReg_OpenConfigKey( (UINT)(-1), KEY_WRITE, REG_OPTION_NON_VOLATILE, &hkCurrCfg );
if ( SUCCEEDED( hres ) ) { for ( JoyId = 0; (JoyId < 16) || ( lRc == ERROR_SUCCESS ); JoyId++ ) { wsprintf( szOemNameKey, REGSTR_VAL_JOYNOEMNAME, JoyId+1 ); cb = sizeof( szTestName ); lRc = RegQueryValueEx( hkCurrCfg, szOemNameKey, 0, NULL, (PBYTE)szTestName, &cb ); if ( lRc == ERROR_SUCCESS ) { if ( !lstrcmpi( szOemName, szTestName ) ) { *pId = JoyId; pId ++; hres = S_OK; break; } } }
} else { SquirtSqflPtszV(sqfl | sqflError, TEXT("JoyReg_OpenConfigKey failed code 0x%08x"), hres ); }
ExitOleProc();
return hres;
} /* JoyReg_GetIDByOemName */ #endif
|