Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/mac_osx/src/external/ois/win32/Win32JoyStick.cpp @ 8069

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

MinGW quick fix for OIS (doesn't yet work though).

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