|
|
/*****************************************************************************
* * DIWdm.c * * Copyright (c) 1996 Microsoft Corporation. All Rights Reserved. * * Abstract: * * WINNT specific functions. * * Contents: * * hResIdJoyInstanceGUID * DIWdm_SetLegacyConfig * DIWdm_InitJoyId * *****************************************************************************/
#include "dinputpr.h"
/*****************************************************************************
* * The sqiffle for this file. * *****************************************************************************/
#define sqfl sqflWDM
/*****************************************************************************
* * @doc INTERNAL * * @func HRESULT | DIWdm_SetJoyId | * Given a guid for a HID device and a Joystick ID. * This function will swap the old joystick ID for the device * specified by the guid ( pcguid ) for the new ID specified in * idJoy * * @parm IN UINT | idJoy | * * The Joyid the the HID device specified by pcguid should have. * * @parm OUT LPGUID | pcguid | * * GUID that specifies a HID device. * * @returns * HRESULT * *****************************************************************************/ HRESULT EXTERNAL DIWdm_SetJoyId ( IN PCGUID pcguid, IN int idJoy ) { PHIDDEVICEINFO phdi; HRESULT hres; BOOL fConfigChanged = FALSE;
EnterProcI(DIWdm_SetJoyId, (_"Gu", pcguid, idJoy));
//PostDx7 patch:
// No point setting the joystick entries in the registry
// if the ID of the joystick is -1.
if( idJoy == -1 ) { return E_FAIL; }
DllEnterCrit();
hres = S_OK;
/* Get pointer to HIDDEVICEINFO from the GUID */ phdi = phdiFindHIDInstanceGUID(pcguid); if(phdi != NULL ) { PHIDDEVICEINFO phdiSwap = NULL; GUID guidInstanceOld; LONG lRc; int idJoySwap;
/* Swap the ID's */ idJoySwap = phdi->idJoy; phdi->idJoy = idJoy;
phdiSwap = NULL; /* Get the GUID for the old ID */ if( SUCCEEDED( hres = hResIdJoypInstanceGUID_WDM(idJoySwap, &guidInstanceOld)) ) { /* Get pointer to HIDDEVICEINFO for old ID */ phdiSwap = phdiFindHIDInstanceGUID(&guidInstanceOld); if( phdiSwap ) { phdiSwap->idJoy = idJoySwap; } else { // Old device disappeared !
}
} else { DIJOYCONFIG c_djcReset = { cbX(c_djcReset), /* dwSize */ { 0}, /* guidInstance */ { 0}, /* hwc */ DI_FFNOMINALMAX, /* dwGain */ { 0}, /* wszType */ { 0}, /* wszCallout */ };
hres = JoyReg_SetConfig(idJoySwap, &c_djcReset.hwc,&c_djcReset, DIJC_SETVALID) ; if( FAILED(hres) ) { SquirtSqflPtszV(sqfl | sqflError, TEXT("%S: JoyReg_SetConfig to NULL FAILED "), s_szProc ); }
}
/* Set the new ID and LegacyConfig */ if( phdi ) { if( lRc = RegSetValueEx(phdi->hk, TEXT("Joystick Id"), 0, REG_BINARY, (PV)&idJoy, cbX(idJoy)) == ERROR_SUCCESS ) { /*
* This extra RegSetValueEx on "Joystick Id" is to keep the * compatibility with Win2k Gold. * See Windows bug 395416 for detail. */ RegSetValueEx(phdi->hkOld, TEXT("Joystick Id"), 0, REG_BINARY, (PV)&idJoy, cbX(idJoy));
if( SUCCEEDED( hres = DIWdm_SetLegacyConfig(idJoy)) ) { fConfigChanged = TRUE; } } }
/* Set old ID and legacy Config */ if( (phdiSwap != NULL) && (phdiSwap != phdi) ) { if( lRc = RegSetValueEx(phdiSwap->hk, TEXT("Joystick Id"), 0, REG_BINARY, (PV)&idJoySwap, cbX(idJoySwap)) == ERROR_SUCCESS ) { /*
* This extra RegSetValueEx on "Joystick Id" is to keep the * compatibility with Win2k Gold. * See Windows bug 395416 for detail. */ RegSetValueEx(phdiSwap->hkOld, TEXT("Joystick Id"), 0, REG_BINARY, (PV)&idJoySwap, cbX(idJoySwap));
if( SUCCEEDED( hres = DIWdm_SetLegacyConfig(idJoySwap) ) ) { fConfigChanged = TRUE; } } } else if( phdiSwap == NULL ) { // Old Device disappeared !
if( SUCCEEDED( hres = DIWdm_SetLegacyConfig(idJoySwap) ) ) { fConfigChanged = TRUE; } } } else { hres = E_FAIL; RPF("ERROR %s: invalid guid.", s_szProc); }
#ifndef WINNT
if( SUCCEEDED(hres) ) { /*
* Make sure the new Ids do not cause any collisions */ DIWdm_InitJoyId(); } #endif
if( fConfigChanged ) { #ifdef WINNT
Excl_SetConfigChangedTime( GetTickCount() ); PostMessage(HWND_BROADCAST, g_wmJoyChanged, 0, 0L); #else
joyConfigChanged(0); #endif
}
DllLeaveCrit();
ExitOleProc();
return hres; }
/*****************************************************************************
* * @doc EXTERNAL * * @func HRESULT | hResIdJoyInstanceGUID_WDM | * * Maps a HID JoyStick ID to a DeviceInstance GUID * * The parameters have already been validated. * * * @parm IN UINT | idJoy | * * The Joyid of the HID device to be located. * * @parm OUT LPGUID | lpguid | * * The Device Instance GUID corresponding to the JoystickID * If a mapping is not found GUID_NULL is passed back in lpguid * * @returns * HRESULT * *****************************************************************************/ HRESULT EXTERNAL hResIdJoypInstanceGUID_WDM ( IN UINT idJoy, OUT LPGUID lpguid ) { HRESULT hres = DIERR_NOTFOUND; EnterProc( hResIdJoypInstanceGUID_WDM, ( _ "ux", idJoy, lpguid) );
/* Zap the guid for failure case */ ZeroBuf(lpguid, cbX(*lpguid) );
if( idJoy > cJoyMax ) { hres = DIERR_NOMOREITEMS; } else { DllEnterCrit();
/* Build the HID list if it is too old */ DIHid_BuildHidList(FALSE);
/* Make sure there is some HID device */ if(g_phdl) { int ihdi; PHIDDEVICEINFO phdi;
/* Search over all HID devices */ for(ihdi = 0, phdi = g_phdl->rghdi; ihdi < g_phdl->chdi; ihdi++, phdi++) { /* Check for matching ID */ if(idJoy == (UINT)phdi->idJoy) { hres = S_OK; /* Copy the GUID */ *lpguid = phdi->guid; break; } } } DllLeaveCrit(); }
ExitBenignOleProc(); return hres; }
/*****************************************************************************
* * @doc INTERNAL * * @func PHIDDEVICEINFO | phdiFindJoyId | * * Locates information given a joystick ID for a HID device. * * The parameters have already been validated. * * The DLL critical must be held across the call; once the * critical section is released, the returned pointer becomes * invalid. * * @parm IN int | idJoy | * * The Id of the joystick to be located. * * @returns * * Pointer to the <t HIDDEVICEINFO> that describes * the device. * *****************************************************************************/
PHIDDEVICEINFO EXTERNAL phdiFindJoyId(int idJoy ) { PHIDDEVICEINFO phdi;
EnterProcI(phdiFindJoyId, (_"u", idJoy));
/* We should have atleast one HID device */ if(g_phdl) { int ihdi;
/* Loop over all HID devices */ for(ihdi = 0, phdi = g_phdl->rghdi; ihdi < g_phdl->chdi; ihdi++, phdi++) { /* Match */ if(idJoy == phdi->idJoy) { goto done; } } } phdi = 0;
done:;
ExitProcX((UINT_PTR)phdi); return phdi; }
/*****************************************************************************
* * @doc INTERNAL * * @func HRESULT | DIWdm_SetLegacyConfig | * * Sets up the registry keys so that a joystick HID device * can be "seen" by legacy APIs and the Control Panel. * Primarily, this routine sets up the structs that are passed * to JoyReg_SetConfig routine. * * @parm IN int | idJoy | * * Joystick ID. * * @returns HRESULT * *****************************************************************************/ //ISSUE-2001/03/29-timgill Fix unicode madness
HRESULT INTERNAL DIWdm_SetLegacyConfig ( IN int idJoy ) { HRESULT hres; DIJOYCONFIG cfg; BOOL fNeedType; BOOL fNeedConfig; BOOL fNeedNone; HKEY hk; DIJOYTYPEINFO dijti; PHIDDEVICEINFO phdi; WCHAR wszType[cA(VID_PID_TEMPLATE)]; #ifndef UNICODE
char szType[cbX(VID_PID_TEMPLATE)]; #endif
EnterProcI(DIWdm_SetLegacyConfig, (_ "u", idJoy));
if( idJoy == -1 ) { // Dx7Gold Patch:
// ID == -1 implies this device is not joystick.
// Do not write any entries to the registry
return E_FAIL; }
ZeroX(dijti); dijti.dwSize = cbX(dijti);
fNeedType = fNeedConfig = TRUE; fNeedNone = FALSE;
/*
* 1. Find out what the WinMM registry data is saying now */ CAssertF( JOY_HW_NONE == 0 ); hres = JoyReg_OpenConfigKey(idJoy, KEY_QUERY_VALUE, 0x0, &hk); if( SUCCEEDED(hres) ) { /* Get the type name from the registry */ JoyReg_GetConfigValue( hk, REGSTR_VAL_JOYNOEMNAME, idJoy, REG_SZ, &cfg.wszType, cbX(cfg.wszType) ); hres = JoyReg_GetConfigValue( hk, REGSTR_VAL_JOYNCONFIG, idJoy, REG_BINARY, &cfg.hwc, cbX(cfg.hwc) ); RegCloseKey(hk); } else { cfg.wszType[0] = '\0'; } if( FAILED( hres ) ) { cfg.hwc.dwType = JOY_HW_NONE; }
/*
* 2. If the config info is in sync with WDM then don't rewrite */ phdi = phdiFindJoyId(idJoy); if( phdi ) { /*
* The type key for HID devices is "VID_xxxx&PID_yyyy", * mirroring the format used by plug and play. */
if( ( LOWORD(phdi->guidProduct.Data1) == MSFT_SYSTEM_VID ) &&( ( HIWORD(phdi->guidProduct.Data1) >= MSFT_SYSTEM_PID + JOY_HW_PREDEFMIN ) &&( HIWORD(phdi->guidProduct.Data1) < MSFT_SYSTEM_PID + JOY_HW_PREDEFMAX ) ) ) { /* Predefined type definitions don't go into the registry */ fNeedType = FALSE;
/*
* Predefined types are determined by the dwType value so fix * only it if that is wrong. */ if( cfg.hwc.dwType + MSFT_SYSTEM_PID == HIWORD(phdi->guidProduct.Data1) ) { fNeedConfig = FALSE; } else { /*
* Get type info so that JOY_HWS_* flags start with correct values. */ wszType[0] = L'#'; wszType[1] = L'0' + HIWORD(phdi->guidProduct.Data1) - MSFT_SYSTEM_PID; wszType[2] = L'\0'; JoyReg_GetPredefTypeInfo(wszType, &dijti, DITC_INREGISTRY | DITC_DISPLAYNAME); } } else { /*
* This should work, but it doesn't in Win98. * * ctch = wsprintfW(wszType, L"VID_%04X&PID_%04X", * LOWORD(phdi->guidProduct.Data1), HIWORD(phdi->guidProduct.Data1)); */
#ifdef UNICODE
wsprintfW(wszType, VID_PID_TEMPLATE, LOWORD(phdi->guidProduct.Data1), HIWORD(phdi->guidProduct.Data1)); CharUpperW(wszType); #else
wsprintf(szType, VID_PID_TEMPLATE, LOWORD(phdi->guidProduct.Data1), HIWORD(phdi->guidProduct.Data1)); CharUpper( szType ); AToU( wszType, cA(wszType), szType ); #endif
} } else { /*
* There is no WDM device so flag for deletion if the WinMM data is wrong */ if( ( cfg.hwc.dwType != JOY_HW_NONE ) || ( cfg.wszType[0] != L'\0' ) ) { fNeedNone = TRUE; fNeedType = fNeedConfig = FALSE; } }
if( fNeedType ) /* Not already decided against (predefined type) */ { /* Does the registry have the correct device ? */
/*
* lstrcmpW doesn't work in Win9x, bad. We have to use our own DiChauUpperW, * then memcmp. Also, the wsprintf template has to use 'X' not 'x'. */ DiCharUpperW(cfg.wszType); if( (memcmp(cfg.wszType, wszType, cbX(wszType)) == 0x0) && (cfg.hwc.dwType >= JOY_HW_PREDEFMAX) ) { fNeedConfig = FALSE; }
/* Check the type key */ hres = JoyReg_GetTypeInfo(wszType, &dijti, DITC_INREGISTRY); if( SUCCEEDED(hres) ) { fNeedType = FALSE; } }
/*
* No failures up to this point should be returned */ hres = S_OK;
/*
* 3. If something is missing, find the data from WDM and set it straight */ if( fNeedType || fNeedConfig ) { if( fNeedConfig ) { ZeroX(cfg); cfg.dwSize = cbX(cfg);
hres = DIWdm_JoyHidMapping(idJoy, NULL, &cfg, &dijti ); } else {
hres = DIWdm_JoyHidMapping(idJoy, NULL, NULL, &dijti ); }
if( SUCCEEDED(hres) ) { if( fNeedType == TRUE) { hres = hresMumbleKeyEx(HKEY_LOCAL_MACHINE, REGSTR_PATH_JOYOEM, DI_KEY_ALL_ACCESS, REG_OPTION_NON_VOLATILE, &hk);
if( SUCCEEDED(hres) ) { hres = JoyReg_SetTypeInfo(hk, cfg.wszType, &dijti, DITC_REGHWSETTINGS | DITC_DISPLAYNAME | DITC_HARDWAREID ); if( SUCCEEDED(hres ) ) { } else // SetTypeinfo FAILED
SquirtSqflPtszV(sqfl | sqflError, TEXT("%S: JoyReg_SetTypeInfo FAILED "), s_szProc );
RegCloseKey(hk); } else // SetTypeinfo FAILED
SquirtSqflPtszV(sqfl | sqflError, TEXT("%S: JoyReg_OpenTypeKey FAILED "), s_szProc ); }
if( fNeedConfig ) { hres = JoyReg_SetConfig(idJoy, &cfg.hwc, &cfg, DIJC_INREGISTRY);
if( SUCCEEDED(hres) ) { #ifdef WINNT
Excl_SetConfigChangedTime( GetTickCount() ); PostMessage (HWND_BROADCAST, g_wmJoyChanged, idJoy+1, 0L); #else
joyConfigChanged(0); #endif
} else { SquirtSqflPtszV(sqfl | sqflError, TEXT(",JoyReg_SetConfig FAILED hres=%d"), hres); } } } else // DIWdm_GetJoyHidMapping FAILED
{ fNeedNone = TRUE; } }
/*
* 4. If WinMM has data for a device that WDM does not, delete it */ if( fNeedNone ) { ZeroX( cfg ); cfg.dwSize = cbX( cfg ); cfg.dwGain = DI_FFNOMINALMAX;
if(SUCCEEDED(hres = JoyReg_SetConfig(idJoy, &cfg.hwc, &cfg, DIJC_SETVALID)) && SUCCEEDED(hres = JoyReg_OpenConfigKey(idJoy, MAXIMUM_ALLOWED, REG_OPTION_VOLATILE, &hk))) { TCHAR tsz[MAX_JOYSTRING];
wsprintf(tsz, TEXT("%u"), idJoy + 1); #ifdef WINNT
DIWinnt_RegDeleteKey(hk, tsz); #else
RegDeleteKey(hk, tsz); #endif
RegCloseKey(hk);
hres = S_OK; } }
ExitProcX(hres);
return hres; }
/*****************************************************************************
* * @doc INTERNAL * * @func void | DIWdm_InitJoyId | * * Initializes Joystick IDs for JoyConfig and legacy APIs * Store the joystick IDs the registry under the %%DirectX/JOYID key. * *****************************************************************************/
BOOL EXTERNAL DIWdm_InitJoyId( void ) { BOOL fRc; LONG lRc; int ihdi; int idJoy; BOOL fNeedId; BOOL rfJoyId[cJoyMax]; /* Bool Array for to determine which IDs are in use */ PHIDDEVICEINFO phdi; HRESULT hres = E_FAIL;
EnterProcI(DIWdm_InitJoyId, (_ ""));
DllEnterCrit();
fRc = TRUE; ZeroX(rfJoyId ); fNeedId = FALSE;
/* Iterate over all HID devices to find used IDs */ for( ihdi = 0, phdi = g_phdl->rghdi ; (g_phdl != NULL) && (phdi != NULL) && (phdi->fAttached) && (ihdi < g_phdl->chdi) ; ihdi++, phdi++ ) { /* We need joyIDs only for HID game controller devices */ if( ( GET_DIDEVICE_TYPE( phdi->osd.dwDevType ) >= DI8DEVTYPE_GAMEMIN ) && ( phdi->osd.dwDevType & DIDEVTYPE_HID ) ) { idJoy = phdi->idJoy ;
/* Validate the ID. */ if( idJoy < cJoyMax && rfJoyId[idJoy] != TRUE ) { rfJoyId[idJoy] = TRUE; hres = DIWdm_SetLegacyConfig(idJoy); if( FAILED ( hres ) ) { fRc = FALSE; SquirtSqflPtszV(sqfl | sqflError, TEXT("%S: DIWdm_SetLegacyConfig() FAILED ") TEXT("idJoy=%d FAILED hres = %d"), s_szProc, idJoy, hres ); } } else { /* ID either over the limit OR is already used */ phdi->idJoy = JOY_BOGUSID; fNeedId = TRUE; } } }
/* Are there devices that need an ID */ if( fNeedId ) { /*
* We have Examined all Joystick Ids found used IDs * and determined some device needs an Id */ /* Iterate to assign unused Id's */ for( ihdi = 0, phdi = g_phdl->rghdi; ihdi < g_phdl->chdi ; ihdi++, phdi++ ) { /* We need joyIDs only for HID game controller devices */ if( ( GET_DIDEVICE_TYPE( phdi->osd.dwDevType ) >= DI8DEVTYPE_GAMEMIN ) && ( phdi->osd.dwDevType & DIDEVTYPE_HID ) ) { idJoy = phdi->idJoy; if( idJoy == JOY_BOGUSID ) { /* Get an Unused ID */ for(idJoy = 0x0; idJoy < cJoyMax; idJoy++ ) { if( rfJoyId[idJoy] == FALSE ) break; }
if( idJoy < cJoyMax ) { rfJoyId[idJoy] = TRUE; phdi->idJoy = idJoy; if( lRc = RegSetValueEx(phdi->hk, TEXT("Joystick Id"), 0, REG_BINARY, (PV)&idJoy, cbX(idJoy)) == ERROR_SUCCESS ) { /*
* This extra RegSetValueEx on "Joystick Id" is to keep the * compatibility with Win2k Gold. * See Windows bug 395416 for detail. */ RegSetValueEx(phdi->hkOld, TEXT("Joystick Id"), 0, REG_BINARY, (PV)&idJoy, cbX(idJoy));
/* Setup Registry data for legacy API's */ hres = DIWdm_SetLegacyConfig(idJoy);
if( FAILED ( hres ) ) { fRc = FALSE; SquirtSqflPtszV(sqfl | sqflError, TEXT("%S: DIWdm_SetLegacyConfig() FAILED") TEXT(" idJoy=%d hres = %d"), s_szProc, idJoy, hres ); } } else { SquirtSqflPtszV(sqfl | sqflError, TEXT("%S: RegSetValueEx(JOYID) FAILED ") TEXT("Error = %d"), s_szProc, lRc); fRc = FALSE; } } } } } }
DllLeaveCrit();
ExitBenignProcF(fRc);
return fRc; }
/*****************************************************************************
* * @doc EXTERNAL * * @func HRESULT | DIWdm_SetConfig | * * Sets config for analog joysticks. This function is an * extention of the JoyCfg_SetConfig function for NT. * It associates a gameport/serialport bus with a legacy (HID) device and * sends an IOCTL to the gameport/serialport bus to attach the device. * The IOCLT takes the hardware ID[] which is got from * the Joystick OEM types entry * (HKLM\CurrentControlSet\Control\Media\PrivateProperties\Joystick\OEM) * Some time later PnP realizes that a new device has been added, and hunts for * an inf file that matches the HardwareId. * * When the new HID device finally shows up, we look for the gameport/serialport that * the HID device is associated with and try to give it the requested idJoy. * * * @parm IN UINT | idJoy | * * ID of Joystick * * @parm IN LPJOYREGHWCONFIG | pjwc | * * Address of JOYREGHWCONFIG structure that contains config info for the joystick * * @parm IN LPCDIJOYCONFIG | pcfg | * * Address of DIJOYCONFIG structure that contains config info for the joystick * * @parm IN DWORD | fl | * * Flags * * @returns * * DIERR_INVALIDPARAM This function needs DX6.1a functionality. * DIERR_UNSUPPORTED Autoload devices cannot be added through this API. * DIERR_NOTFOUND TypeInfo not found in the registry. * E_ACCESSDENIED Gameport is configured to use another device. * E_FAIL CreateFile on Gameport device failed. * Could not send IOCTL to gameport device. * *****************************************************************************/
HRESULT EXTERNAL DIWdm_SetConfig ( IN UINT idJoy, IN LPJOYREGHWCONFIG pjwc, IN LPCDIJOYCONFIG pcfg, IN DWORD fl ) { HRESULT hres; EnterProc(DIWdm_SetConfig, (_"uppu", idJoy, pjwc, pcfg, fl));
DllEnterCrit();
hres = E_FAIL;
if( pcfg->dwSize < cbX(DIJOYCONFIG_DX6 )) { /* This function needs DX5B2 functionality */ hres = DIERR_INVALIDPARAM; } else if( pjwc->hws.dwFlags & JOY_HWS_AUTOLOAD ) { /* Device cannot be autoload */ hres = DIERR_UNSUPPORTED; } else { DIJOYTYPEINFO dijti; BUS_REGDATA RegData;
ZeroX(dijti); dijti.dwSize = cbX(dijti);
ZeroX(RegData); RegData.dwSize = cbX(RegData); RegData.nJoysticks = 1;
/* Is this a predefined joystick type ? */ if(pcfg->wszType[0] == TEXT('#')) { #define JoyCfg_TypeFromChar(tch) ((tch) - L'0')
hres = JoyReg_GetPredefTypeInfo(pcfg->wszType, &dijti, DITC_INREGISTRY | DITC_HARDWAREID);
RegData.uVID = MSFT_SYSTEM_VID; RegData.uPID = MSFT_SYSTEM_PID + JoyCfg_TypeFromChar(pcfg->wszType[1]);
if(JoyCfg_TypeFromChar(pcfg->wszType[1]) == JOY_HW_TWO_2A_2B_WITH_Y ) { RegData.nJoysticks = 2; pjwc->hws.dwFlags = 0x0; } #undef JoyCfg_TypeFromChar
} else { hres = JoyReg_GetTypeInfo(pcfg->wszType, &dijti, DITC_INREGISTRY | DITC_HARDWAREID | DITC_DISPLAYNAME );
if( SUCCEEDED(hres) ) { USHORT uVID, uPID; PWCHAR pCurrChar; PWCHAR pLastSlash = NULL;
/* Find the last slash in the hardwareId, any VID/PID should follow directly */ for( pCurrChar = dijti.wszHardwareId; *pCurrChar != L'\0'; pCurrChar++ ) { if( *pCurrChar == L'\\' ) { pLastSlash = pCurrChar; } }
/*
* If the hardware ID has no separator, treat the device as * though JOY_HWS_AUTOLOAD were set because we cannot expose * a non-PnP device without a hardware ID. */ if( pLastSlash++ ) { /*
* If the hardwareId does contain a VIDPID, try the type * name. Some auto-detect types require this. * * Prefix gets messed up in ParseVIDPID (mb:34573) and warns * that uVID is uninitialized when ParseVIDPID returns TRUE. */ if( ParseVIDPID( &uVID, &uPID, pLastSlash ) || ParseVIDPID( &uVID, &uPID, pcfg->wszType ) ) { RegData.uVID = uVID; RegData.uPID = uPID; } else { SquirtSqflPtszV(sqfl | sqflBenign, TEXT("%hs: cannot find VID and PID for non-PnP type %ls"), s_szProc, pcfg->wszType); } } else { SquirtSqflPtszV(sqfl | sqflError, TEXT("%hs: invalid hardware ID for non-PnP type %ls"), s_szProc, pcfg->wszType); hres = DIERR_UNSUPPORTED; }
} }
if( SUCCEEDED(hres) ) { PBUSDEVICEINFO pbdi; PBUSDEVICELIST pbdl;
/* Copy over the hardwareID */ lstrcpyW(RegData.wszHardwareId, dijti.wszHardwareId); RegData.hws = pjwc->hws; RegData.dwFlags1 = dijti.dwFlags1;
pbdi = pbdiFromGUID(&pcfg->guidGameport);
// Attach device to the gameport
if( pbdi ) { // Set the Joystick ID for the gameport/serialport
pbdi->idJoy = idJoy;
// We know which instance of the gameport.
hres = DIBusDevice_Expose(pbdi, &RegData); } else if( NULL != ( pbdl = pbdlFromGUID(&pcfg->guidGameport ) ) ) { // We don't kwow which instance of the gameport
// only which bus.
// We will expose the device on all instances of the
// gameport and later delete devices when we find they
// are not connected.
hres = DIBusDevice_ExposeEx(pbdl, &RegData); } else { hres = DIERR_DEVICENOTREG; }
if( SUCCEEDED(hres) ) { /* Device is not present */ pjwc->dwUsageSettings &= ~JOY_US_PRESENT;
/* Definately volatile */ pjwc->dwUsageSettings |= JOY_US_VOLATILE;
} } }
ExitOleProc(); DllLeaveCrit();
return hres; } /* DIWdm_SetConfig */
/*****************************************************************************
* * @doc EXTERNAL * * @func HRESULT | DIWdm_DeleteConfig | * * WDM extension for JoyCfd::DeleteConfig. On WDM a legacy(HID) device will * keep reappearing as long as the gameport bus is aware of it. So when a * legacy(HID) device is deleted, we need to find out he associated gameport bus * and tell him to stop attaching the device. * * @parm IN UINT | idJoy | * * ID of Joystick * * @returns * * HRESULT code * DIERR_DEVICENOTREG: Device is not a WDM device * DIERR_UNSUPPORTED: Device is WDM but not gameport * S_OK: Device Persistance removed. * *****************************************************************************/
HRESULT EXTERNAL DIWdm_DeleteConfig( int idJoy ) { HRESULT hres = S_OK; PBUSDEVICEINFO pbdi = NULL; PHIDDEVICEINFO phdi = NULL;
EnterProcI(DIWdm_DeleteConfig, (_"u", idJoy)); DllEnterCrit();
DIHid_BuildHidList(FALSE);
/*
* pbdi (BUSDEVICEINFO) must be obtained before we remove the device */ phdi = phdiFindJoyId(idJoy); if(phdi != NULL ) { pbdi = pbdiFromphdi(phdi); } else { hres = DIERR_DEVICENOTREG; goto _done; }
if( SUCCEEDED(hres) && phdi != NULL && pbdi != NULL ) { lstrcpy( g_tszIdLastRemoved, pbdi->ptszId ); g_tmLastRemoved = GetTickCount();
// If the device is a bus device ( Non USB )
// it needs some help in removal.
hres = DIBusDevice_Remove(pbdi);
//If the device has been successfully removed,
//then we need remember it in phdi list in case
//the PnP doesn't function well.
if( pbdi->fAttached == FALSE ) { phdi->fAttached = FALSE; }
} else { //HDEVINFO hdev;
// Device is USB, we do not support removing
// USB devices from the CPL. User is encouraged to
// Yank out the device or go to the device manager to
// remove it.
// This is true in Win2K. But in Win9X, since VJOYD also works with USB,
// when we swap id, we need delete it first.
hres = DIERR_UNSUPPORTED; #if 0
// In case we wanted to support removing USB devices from
// the game cpl. Here is the code ...
/*
* Talk to SetupApi to delete the device. * This should not be necessary, but I have * to do this to work around a PnP bug whereby * the device is not removed after I send a remove * IOCTL to gameenum. */ hdev = SetupDiCreateDeviceInfoList(NULL, NULL); if( phdi && hdev != INVALID_HANDLE_VALUE) { SP_DEVINFO_DATA dinf;
dinf.cbSize = cbX(SP_DEVINFO_DATA);
/* Get SP_DEVINFO_DATA for the HID device */ if(SetupDiOpenDeviceInfo(hdev, phdi->ptszId, NULL, 0, &dinf)) { /* Delete the device */ if( SetupDiCallClassInstaller(DIF_REMOVE, hdev, &dinf) ) { // SUCCESS
} else { hres = E_FAIL; SquirtSqflPtszV(sqfl | sqflError, TEXT("%S: SetupDiClassInstalled(DIF_REMOVE) FAILED "), s_szProc ); } } SetupDiDestroyDeviceInfoList(hdev); } #endif
}
_done:
/*
* Force a remake of the HID list * Some devices may have disappered * It helps to sleep for some time to give * PnP and its worker threads to spin. */ Sleep(10);
DIHid_BuildHidList(TRUE); DllLeaveCrit();
ExitOleProc();
return hres; }
|