Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/ois_update/src/external/ois/win32/Win32JoyStick.cpp @ 7506

Last change on this file since 7506 was 7506, checked in by rgrieder, 14 years ago

Updated OIS source files to its current SVN trunk (r26).

  • Property svn:eol-style set to native
File size: 20.9 KB
Line 
1/*
2The zlib/libpng License
3
4Copyright (c) 2005-2007 Phillip Castaneda (pjcast -- www.wreckedgames.com)
5
6This software is provided 'as-is', without any express or implied warranty. In no event will
7the authors be held liable for any damages arising from the use of this software.
8
9Permission is granted to anyone to use this software for any purpose, including commercial
10applications, and to alter it and redistribute it freely, subject to the following
11restrictions:
12
13    1. The origin of this software must not be misrepresented; you must not claim that
14                you wrote the original software. If you use this software in a product,
15                an acknowledgment in the product documentation would be appreciated but is
16                not required.
17
18    2. Altered source versions must be plainly marked as such, and must not be
19                misrepresented as being the original software.
20
21    3. This notice may not be removed or altered from any source distribution.
22*/
23#include "win32/Win32JoyStick.h"
24#include "win32/Win32InputManager.h"
25#include "win32/Win32ForceFeedback.h"
26#include "OISEvents.h"
27#include "OISException.h"
28
29#include <cassert>
30#include <wbemidl.h>
31#include <oleauto.h>
32//#include <wmsstd.h>
33#ifndef SAFE_RELEASE
34#define SAFE_RELEASE(x) \
35   if(x != NULL)        \
36   {                    \
37      x->Release();     \
38      x = NULL;         \
39   }
40#endif
41
42#ifdef OIS_WIN32_XINPUT_SUPPORT
43#       pragma comment(lib, "xinput.lib")
44#endif
45
46//DX Only defines macros for the JOYSTICK not JOYSTICK2, so fix it
47#undef DIJOFS_BUTTON
48#undef DIJOFS_POV
49
50#define DIJOFS_BUTTON(n)  (FIELD_OFFSET(DIJOYSTATE2, rgbButtons) + (n))
51#define DIJOFS_POV(n)     (FIELD_OFFSET(DIJOYSTATE2, rgdwPOV)+(n)*sizeof(DWORD))
52#define DIJOFS_SLIDER0(n) (FIELD_OFFSET(DIJOYSTATE2, rglSlider)+(n) * sizeof(LONG))
53#define DIJOFS_SLIDER1(n) (FIELD_OFFSET(DIJOYSTATE2, rglVSlider)+(n) * sizeof(LONG))
54#define DIJOFS_SLIDER2(n) (FIELD_OFFSET(DIJOYSTATE2, rglASlider)+(n) * sizeof(LONG))
55#define DIJOFS_SLIDER3(n) (FIELD_OFFSET(DIJOYSTATE2, rglFSlider)+(n) * sizeof(LONG))
56
57#define XINPUT_TRANSLATED_BUTTON_COUNT 12
58#define XINPUT_TRANSLATED_AXIS_COUNT 6
59
60using namespace OIS;
61
62//--------------------------------------------------------------------------------------------------//
63Win32JoyStick::Win32JoyStick( InputManager* creator, IDirectInput8* pDI, bool buffered, DWORD coopSettings, const JoyStickInfo &info ) :
64        JoyStick(info.vendor, buffered, info.devId, creator),
65        mDirectInput(pDI),
66        coopSetting(coopSettings),
67        mJoyStick(0),
68        mJoyInfo(info),
69        mFfDevice(0)
70{
71}
72
73//--------------------------------------------------------------------------------------------------//
74Win32JoyStick::~Win32JoyStick()
75{
76        delete mFfDevice;
77
78        if(mJoyStick)
79        {
80                mJoyStick->Unacquire();
81                mJoyStick->Release();
82                mJoyStick = 0;
83        }
84
85        //Return joystick to pool
86        static_cast<Win32InputManager*>(mCreator)->_returnJoyStick(mJoyInfo);
87}
88
89//--------------------------------------------------------------------------------------------------//
90void Win32JoyStick::_initialize()
91{
92    if (mJoyInfo.isXInput)
93    {
94        _enumerate();
95    }
96    else
97    {
98            //Clear old state
99            mState.mAxes.clear();
100
101            delete mFfDevice;
102            mFfDevice = 0;
103
104            DIPROPDWORD dipdw;
105
106            dipdw.diph.dwSize       = sizeof(DIPROPDWORD);
107            dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
108            dipdw.diph.dwObj        = 0;
109            dipdw.diph.dwHow        = DIPH_DEVICE;
110            dipdw.dwData            = JOYSTICK_DX_BUFFERSIZE;
111
112            if(FAILED(mDirectInput->CreateDevice(mJoyInfo.deviceID, &mJoyStick, NULL)))
113                    OIS_EXCEPT( E_General, "Win32JoyStick::_initialize() >> Could not initialize joy device!");
114
115            if(FAILED(mJoyStick->SetDataFormat(&c_dfDIJoystick2)))
116                    OIS_EXCEPT( E_General, "Win32JoyStick::_initialize() >> data format error!");
117
118            HWND hwin = ((Win32InputManager*)mCreator)->getWindowHandle();
119
120            if(FAILED(mJoyStick->SetCooperativeLevel( hwin, coopSetting)))
121                    OIS_EXCEPT( E_General, "Win32JoyStick::_initialize() >> failed to set cooperation level!");
122
123            if( FAILED(mJoyStick->SetProperty(DIPROP_BUFFERSIZE, &dipdw.diph)) )
124                    OIS_EXCEPT( E_General, "Win32Mouse::Win32Mouse >> Failed to set buffer size property" );
125
126            //Enumerate all axes/buttons/sliders/etc before aquiring
127            _enumerate();
128
129            mState.clear();
130
131            capture();
132    }
133}
134
135//--------------------------------------------------------------------------------------------------//
136void Win32JoyStick::_enumerate()
137{
138    if (mJoyInfo.isXInput)
139    {
140        mPOVs = 1;
141
142        mState.mButtons.resize(XINPUT_TRANSLATED_BUTTON_COUNT);
143            mState.mAxes.resize(XINPUT_TRANSLATED_AXIS_COUNT);
144    }
145    else
146    {
147                // Get joystick capabilities.
148                mDIJoyCaps.dwSize = sizeof(DIDEVCAPS);
149                if( FAILED(mJoyStick->GetCapabilities(&mDIJoyCaps)) )
150                        OIS_EXCEPT( E_General, "Win32JoyStick::_enumerate >> Failed to get capabilities" );
151
152            mPOVs = (short)mDIJoyCaps.dwPOVs;
153
154            mState.mButtons.resize(mDIJoyCaps.dwButtons);
155            mState.mAxes.resize(mDIJoyCaps.dwAxes);
156
157            //Reset the axis mapping enumeration value
158            _AxisNumber = 0;
159
160            //Enumerate Force Feedback (if any)
161            mJoyStick->EnumEffects(DIEnumEffectsCallback, this, DIEFT_ALL);
162
163            //Enumerate and set axis constraints (and check FF Axes)
164            mJoyStick->EnumObjects(DIEnumDeviceObjectsCallback, this, DIDFT_AXIS);
165    }
166}
167
168//--------------------------------------------------------------------------------------------------//
169BOOL CALLBACK Win32JoyStick::DIEnumDeviceObjectsCallback(LPCDIDEVICEOBJECTINSTANCE lpddoi, LPVOID pvRef)
170{
171        Win32JoyStick* _this = (Win32JoyStick*)pvRef;
172
173        //Setup mappings
174        DIPROPPOINTER diptr;
175        diptr.diph.dwSize       = sizeof(DIPROPPOINTER);
176        diptr.diph.dwHeaderSize = sizeof(DIPROPHEADER);
177        diptr.diph.dwHow        = DIPH_BYID;
178        diptr.diph.dwObj        = lpddoi->dwType;
179        //Add a magic number to recognise we set seomthing
180        diptr.uData             = 0x13130000 | _this->_AxisNumber;
181
182        //Check if axis is slider, if so, do not treat as regular axis
183        if(GUID_Slider == lpddoi->guidType)
184        {
185                ++_this->mSliders;
186
187                //Decrease Axes, since this slider shows up in a different place
188                _this->mState.mAxes.pop_back();
189        }
190        else if (FAILED(_this->mJoyStick->SetProperty(DIPROP_APPDATA, &diptr.diph)))
191        {       //If for some reason we could not set needed user data, just ignore this axis
192                return DIENUM_CONTINUE;
193        }
194
195        //Increase for next time through
196        if(GUID_Slider != lpddoi->guidType)
197                _this->_AxisNumber += 1;
198
199        //Set range
200        DIPROPRANGE diprg;
201        diprg.diph.dwSize       = sizeof(DIPROPRANGE);
202        diprg.diph.dwHeaderSize = sizeof(DIPROPHEADER);
203        diprg.diph.dwHow        = DIPH_BYID;
204        diprg.diph.dwObj        = lpddoi->dwType;
205        diprg.lMin              = MIN_AXIS;
206        diprg.lMax              = MAX_AXIS;
207
208        if (FAILED(_this->mJoyStick->SetProperty(DIPROP_RANGE, &diprg.diph)))
209                OIS_EXCEPT( E_General, "Win32JoyStick::_DIEnumDeviceObjectsCallback >> Failed to set min/max range property" );
210
211        //Check if FF Axes, and if so, increment counter
212        if((lpddoi->dwFlags & DIDOI_FFACTUATOR) != 0 )
213        {
214                if( _this->mFfDevice )
215                {
216                        _this->mFfDevice->_addFFAxis();
217                }
218        }
219
220        //Force the flags for gain and auto-center support to true,
221        //as DInput has no API to query the device for these capabilities
222        //(the only way to know is to try them ...)
223        if( _this->mFfDevice )
224        {
225            _this->mFfDevice->_setGainSupport(true);
226            _this->mFfDevice->_setAutoCenterSupport(true);
227        }
228
229        return DIENUM_CONTINUE;
230}
231
232//--------------------------------------------------------------------------------------------------//
233BOOL CALLBACK Win32JoyStick::DIEnumEffectsCallback(LPCDIEFFECTINFO pdei, LPVOID pvRef)
234{
235        Win32JoyStick* _this = (Win32JoyStick*)pvRef;
236
237        //Create the FF instance only after we know there is at least one effect type
238        if( _this->mFfDevice == 0 )
239                _this->mFfDevice = new Win32ForceFeedback(_this->mJoyStick, &_this->mDIJoyCaps);
240
241        _this->mFfDevice->_addEffectSupport(pdei);
242
243        return DIENUM_CONTINUE;
244}
245
246//--------------------------------------------------------------------------------------------------//
247void Win32JoyStick::capture()
248{
249#ifdef OIS_WIN32_XINPUT_SUPPORT
250        //handle xbox controller differently
251    if (mJoyInfo.isXInput)
252        {
253                captureXInput();
254                return;
255        }
256#endif
257
258        //handle directinput based devices
259        DIDEVICEOBJECTDATA diBuff[JOYSTICK_DX_BUFFERSIZE];
260        DWORD entries = JOYSTICK_DX_BUFFERSIZE;
261
262        // Poll the device to read the current state
263        HRESULT hr = mJoyStick->Poll();
264        if( hr == DI_OK )
265                hr = mJoyStick->GetDeviceData( sizeof(DIDEVICEOBJECTDATA), diBuff, &entries, 0 );
266
267        if( hr != DI_OK )
268        {
269                hr = mJoyStick->Acquire();
270                while( hr == DIERR_INPUTLOST )
271                        hr = mJoyStick->Acquire();
272
273                // Poll the device to read the current state
274                mJoyStick->Poll();
275                hr = mJoyStick->GetDeviceData( sizeof(DIDEVICEOBJECTDATA), diBuff, &entries, 0 );
276                //Perhaps the user just tabbed away
277                if( FAILED(hr) )
278                        return;
279        }
280
281        bool axisMoved[24] = {false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,
282                                                  false,false,false,false,false,false,false,false};
283        bool sliderMoved[4] = {false,false,false,false};
284
285        //Loop through all the events
286        for(unsigned int i = 0; i < entries; ++i)
287        {
288                //This may seem outof order, but is in order of the way these variables
289                //are declared in the JoyStick State 2 structure.
290                switch(diBuff[i].dwOfs)
291                {
292                //------ slider -//
293                case DIJOFS_SLIDER0(0):
294                        sliderMoved[0] = true;
295                        mState.mSliders[0].abX = diBuff[i].dwData;
296                        break;
297                case DIJOFS_SLIDER0(1):
298                        sliderMoved[0] = true;
299                        mState.mSliders[0].abY = diBuff[i].dwData;
300                        break;
301                //----- Max 4 POVs Next ---------------//
302                case DIJOFS_POV(0):
303                        if(!_changePOV(0,diBuff[i]))
304                                return;
305                        break;
306                case DIJOFS_POV(1):
307                        if(!_changePOV(1,diBuff[i]))
308                                return;
309                        break;
310                case DIJOFS_POV(2):
311                        if(!_changePOV(2,diBuff[i]))
312                                return;
313                        break;
314                case DIJOFS_POV(3):
315                        if(!_changePOV(3,diBuff[i]))
316                                return;
317                        break;
318                case DIJOFS_SLIDER1(0):
319                        sliderMoved[1] = true;
320                        mState.mSliders[1].abX = diBuff[i].dwData;
321                        break;
322                case DIJOFS_SLIDER1(1):
323                        sliderMoved[1] = true;
324                        mState.mSliders[1].abY = diBuff[i].dwData;
325                        break;
326                case DIJOFS_SLIDER2(0):
327                        sliderMoved[2] = true;
328                        mState.mSliders[2].abX = diBuff[i].dwData;
329                        break;
330                case DIJOFS_SLIDER2(1):
331                        sliderMoved[2] = true;
332                        mState.mSliders[2].abY = diBuff[i].dwData;
333                        break;
334                case DIJOFS_SLIDER3(0):
335                        sliderMoved[3] = true;
336                        mState.mSliders[3].abX = diBuff[i].dwData;
337                        break;
338                case DIJOFS_SLIDER3(1):
339                        sliderMoved[3] = true;
340                        mState.mSliders[3].abY = diBuff[i].dwData;
341                        break;
342                //-----------------------------------------//
343                default:
344                        //Handle Button Events Easily using the DX Offset Macros
345                        if( diBuff[i].dwOfs >= DIJOFS_BUTTON(0) && diBuff[i].dwOfs < DIJOFS_BUTTON(128) )
346                        {
347                                if(!_doButtonClick((diBuff[i].dwOfs - DIJOFS_BUTTON(0)), diBuff[i]))
348                                        return;
349                        }
350                        else if((short)(diBuff[i].uAppData >> 16) == 0x1313)
351                        {       //If it was nothing else, might be axis enumerated earlier (determined by magic number)
352                                int axis = (int)(0x0000FFFF & diBuff[i].uAppData); //Mask out the high bit
353                                assert( axis >= 0 && axis < (int)mState.mAxes.size() && "Axis out of range!");
354
355                                if(axis >= 0 && axis < (int)mState.mAxes.size())
356                                {
357                                        mState.mAxes[axis].abs = diBuff[i].dwData;
358                                        axisMoved[axis] = true;
359                                }
360                        }
361
362                        break;
363                } //end case
364        } //end for
365
366        //Check to see if any of the axes values have changed.. if so send events
367        if( mBuffered && mListener && entries > 0 )
368        {
369                JoyStickEvent temp(this, mState);
370
371                //Update axes
372                for( int i = 0; i < 24; ++i )
373                        if( axisMoved[i] )
374                                if( mListener->axisMoved( temp, i ) == false )
375                                        return;
376
377                //Now update sliders
378                for( int i = 0; i < 4; ++i )
379                        if( sliderMoved[i] )
380                                if( mListener->sliderMoved( temp, i ) == false )
381                                        return;
382        }
383}
384
385//--------------------------------------------------------------------------------------------------//
386void Win32JoyStick::captureXInput()
387{
388#ifdef OIS_WIN32_XINPUT_SUPPORT
389    XINPUT_STATE inputState;
390        if (XInputGetState((DWORD)mJoyInfo.xInputDev, &inputState) != ERROR_SUCCESS)
391        memset(&inputState, 0, sizeof(inputState));
392
393    //Sticks and triggers
394        int value;
395    bool axisMoved[XINPUT_TRANSLATED_AXIS_COUNT] = {false,false,false,false,false,false};
396
397        //LeftY
398        value = -(int)inputState.Gamepad.sThumbLY;
399        mState.mAxes[0].rel = value - mState.mAxes[0].abs;
400        mState.mAxes[0].abs = value;
401        if(mState.mAxes[0].rel != 0)
402        axisMoved[0] = true;
403
404        //LeftX
405    mState.mAxes[1].rel = inputState.Gamepad.sThumbLX - mState.mAxes[1].abs;
406    mState.mAxes[1].abs = inputState.Gamepad.sThumbLX;
407
408        if(mState.mAxes[1].rel != 0)
409        axisMoved[1] = true;
410
411        //RightY
412        value = -(int)inputState.Gamepad.sThumbRY;           
413    mState.mAxes[2].rel = value - mState.mAxes[2].abs;
414    mState.mAxes[2].abs = value;
415        if(mState.mAxes[2].rel != 0)
416        axisMoved[2] = true;
417
418        //RightX
419    mState.mAxes[3].rel = inputState.Gamepad.sThumbRX - mState.mAxes[3].abs;
420    mState.mAxes[3].abs = inputState.Gamepad.sThumbRX;
421        if(mState.mAxes[3].rel != 0)
422                axisMoved[3] = true;
423
424        //Left trigger
425    value = inputState.Gamepad.bLeftTrigger * 129;
426        if(value > JoyStick::MAX_AXIS)
427                value = JoyStick::MAX_AXIS;
428
429    mState.mAxes[4].rel = value - mState.mAxes[4].abs;
430    mState.mAxes[4].abs = value;
431        if(mState.mAxes[4].rel != 0)
432                axisMoved[4] = true;
433
434        //Right trigger
435    value = (int)inputState.Gamepad.bRightTrigger * 129;
436        if(value > JoyStick::MAX_AXIS)
437                value = JoyStick::MAX_AXIS;
438
439        mState.mAxes[5].rel = value - mState.mAxes[5].abs;
440    mState.mAxes[5].abs = value;
441        if(mState.mAxes[5].rel != 0)
442                axisMoved[5] = true;
443   
444    //POV
445    int previousPov = mState.mPOV[0].direction;       
446    int& pov = mState.mPOV[0].direction;
447    pov = Pov::Centered;       
448    if (inputState.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP)
449        pov |= Pov::North;
450    else if (inputState.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN)
451        pov |= Pov::South;
452    if (inputState.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT)
453        pov |= Pov::West;
454    else if (inputState.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT)
455        pov |= Pov::East;
456   
457    //Buttons - The first 4 buttons don't need to be checked since they represent the dpad
458    bool previousButtons[XINPUT_TRANSLATED_BUTTON_COUNT];
459    std::copy(mState.mButtons.begin(), mState.mButtons.end(), previousButtons);
460    for (size_t i = 0; i < XINPUT_TRANSLATED_BUTTON_COUNT; i++)
461        mState.mButtons[i] = (inputState.Gamepad.wButtons & (1 << (i + 4))) != 0;
462
463    //Send events
464    if (mBuffered && mListener)
465    {
466            JoyStickEvent joystickEvent(this, mState);
467
468            //Axes
469            for (int i = 0; i < XINPUT_TRANSLATED_AXIS_COUNT; i++)
470        {
471                    if (axisMoved[i] && !mListener->axisMoved(joystickEvent, i))
472                            return;
473        }
474
475        //POV
476        if (previousPov != pov && !mListener->povMoved(joystickEvent, 0))
477            return;
478
479        //Buttons
480        for (int i = 0; i < XINPUT_TRANSLATED_BUTTON_COUNT; i++)
481        {
482            if (!previousButtons[i] && mState.mButtons[i])
483            {
484                if (!mListener->buttonPressed(joystickEvent, i))
485                    return;
486            }
487            else if (previousButtons[i] && !mState.mButtons[i])
488            {
489                if (!mListener->buttonReleased(joystickEvent, i))
490                    return;
491            }
492        }
493    }
494#endif
495}
496
497//--------------------------------------------------------------------------------------------------//
498bool Win32JoyStick::_doButtonClick( int button, DIDEVICEOBJECTDATA& di )
499{
500        if( di.dwData & 0x80 )
501        {
502                mState.mButtons[button] = true;
503                if( mBuffered && mListener )
504                        return mListener->buttonPressed( JoyStickEvent( this, mState ), button );
505        }
506        else
507        {
508                mState.mButtons[button] = false;
509                if( mBuffered && mListener )
510                        return mListener->buttonReleased( JoyStickEvent( this, mState ), button );
511        }
512
513        return true;
514}
515
516//--------------------------------------------------------------------------------------------------//
517bool Win32JoyStick::_changePOV( int pov, DIDEVICEOBJECTDATA& di )
518{
519        //Some drivers report a value of 65,535, instead of —1,
520        //for the center position
521        if(LOWORD(di.dwData) == 0xFFFF)
522        {
523                mState.mPOV[pov].direction = Pov::Centered;
524        }
525        else
526        {
527                switch(di.dwData)
528                {
529                        case 0: mState.mPOV[pov].direction = Pov::North; break;
530                        case 4500: mState.mPOV[pov].direction = Pov::NorthEast; break;
531                        case 9000: mState.mPOV[pov].direction = Pov::East; break;
532                        case 13500: mState.mPOV[pov].direction = Pov::SouthEast; break;
533                        case 18000: mState.mPOV[pov].direction = Pov::South; break;
534                        case 22500: mState.mPOV[pov].direction = Pov::SouthWest; break;
535                        case 27000: mState.mPOV[pov].direction = Pov::West; break;
536                        case 31500: mState.mPOV[pov].direction = Pov::NorthWest; break;
537                }
538        }
539
540        if( mBuffered && mListener )
541                return mListener->povMoved( JoyStickEvent( this, mState ), pov );
542
543        return true;
544}
545
546//--------------------------------------------------------------------------------------------------//
547void Win32JoyStick::setBuffered(bool buffered)
548{
549        mBuffered = buffered;
550}
551
552//--------------------------------------------------------------------------------------------------//
553Interface* Win32JoyStick::queryInterface(Interface::IType type)
554{
555        if( mFfDevice && type == Interface::ForceFeedback )
556                return mFfDevice;
557        else
558                return 0;
559}
560
561//--------------------------------------------------------------------------------------------------//
562void Win32JoyStick::CheckXInputDevices(JoyStickInfoList &joys)
563{
564    IWbemLocator*           pIWbemLocator  = NULL;
565    IEnumWbemClassObject*   pEnumDevices   = NULL;
566    IWbemClassObject*       pDevices[20]   = {0};
567    IWbemServices*          pIWbemServices = NULL;
568    BSTR                    bstrNamespace  = NULL;
569    BSTR                    bstrDeviceID   = NULL;
570    BSTR                    bstrClassName  = NULL;
571    DWORD                   uReturned      = 0;
572    bool                    bIsXinputDevice= false;
573        DWORD                   iDevice        = 0;
574        int                     xDevice        = 0;
575    VARIANT                 var;
576    HRESULT                 hr;
577
578        if(joys.size() == 0)
579                return;
580
581    // CoInit if needed
582    hr = CoInitialize(NULL);
583    bool bCleanupCOM = SUCCEEDED(hr);
584
585    // Create WMI
586    hr = CoCreateInstance(__uuidof(WbemLocator), NULL, CLSCTX_INPROC_SERVER, __uuidof(IWbemLocator), (LPVOID*)&pIWbemLocator);
587    if( FAILED(hr) || pIWbemLocator == NULL )
588        goto LCleanup;
589
590    bstrNamespace = SysAllocString( L"\\\\.\\root\\cimv2" );
591        if( bstrNamespace == NULL )
592                goto LCleanup;
593
594    bstrClassName = SysAllocString( L"Win32_PNPEntity" );
595        if( bstrClassName == NULL )
596                goto LCleanup;
597
598    bstrDeviceID  = SysAllocString( L"DeviceID" );
599        if( bstrDeviceID == NULL )
600                goto LCleanup;
601   
602    // Connect to WMI
603    hr = pIWbemLocator->ConnectServer( bstrNamespace, NULL, NULL, 0L, 0L, NULL, NULL, &pIWbemServices );
604    if( FAILED(hr) || pIWbemServices == NULL )
605        goto LCleanup;
606
607    // Switch security level to IMPERSONATE.
608    CoSetProxyBlanket(pIWbemServices, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE );                   
609
610    hr = pIWbemServices->CreateInstanceEnum( bstrClassName, 0, NULL, &pEnumDevices ); 
611    if( FAILED(hr) || pEnumDevices == NULL )
612        goto LCleanup;
613
614    // Loop over all devices
615    for( ;; )
616    {
617        // Get 20 at a time
618        hr = pEnumDevices->Next(5000, 20, pDevices, &uReturned);
619        if( FAILED(hr) )
620            goto LCleanup;
621
622        if( uReturned == 0 )
623            break;
624
625        for(iDevice = 0; iDevice < uReturned; iDevice++)
626        {
627            // For each device, get its device ID
628            hr = pDevices[iDevice]->Get(bstrDeviceID, 0L, &var, NULL, NULL);
629            if(SUCCEEDED(hr) && var.vt == VT_BSTR && var.bstrVal != NULL)
630            {
631                // Check if the device ID contains "IG_".  If it does, then it's an XInput device - This information can not be found from DirectInput
632                if(wcsstr(var.bstrVal, L"IG_"))
633                {
634                    // If it does, then get the VID/PID from var.bstrVal
635                    DWORD dwPid = 0, dwVid = 0;
636                    WCHAR* strVid = wcsstr( var.bstrVal, L"VID_" );
637                    if(strVid && swscanf_s( strVid, L"VID_%4X", &dwVid ) != 1)
638                                                dwVid = 0;
639
640                    WCHAR* strPid = wcsstr( var.bstrVal, L"PID_" );
641                    if(strPid && swscanf_s( strPid, L"PID_%4X", &dwPid ) != 1)
642                        dwPid = 0;
643
644                    // Compare the VID/PID to the DInput device
645                    DWORD dwVidPid = MAKELONG(dwVid, dwPid);
646                                        for(JoyStickInfoList::iterator i = joys.begin(); i != joys.end(); ++i)
647                                        {
648                                                if(dwVidPid == i->productGuid.Data1)
649                                                {
650                                                        i->isXInput = true;
651                                                        i->xInputDev = xDevice;
652                                                }
653                                        }
654
655                                        if(joys.size() == 0)
656                                                goto LCleanup;
657                }
658            }
659
660            SAFE_RELEASE(pDevices[iDevice]);
661        }
662    }
663
664LCleanup:
665    if(bstrNamespace)
666        SysFreeString(bstrNamespace);
667
668    if(bstrDeviceID)
669        SysFreeString(bstrDeviceID);
670
671    if(bstrClassName)
672        SysFreeString(bstrClassName);
673
674    for(iDevice=0; iDevice < 20; iDevice++)
675        SAFE_RELEASE(pDevices[iDevice]);
676
677    SAFE_RELEASE(pEnumDevices);
678    SAFE_RELEASE(pIWbemLocator);
679    SAFE_RELEASE(pIWbemServices);
680
681    if(bCleanupCOM)
682        CoUninitialize();
683}
Note: See TracBrowser for help on using the repository browser.