Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Ignore:
Timestamp:
Apr 28, 2011, 7:15:14 AM (13 years ago)
Author:
rgrieder
Message:

Merged kicklib2 branch back to trunk (includes former branches ois_update, mac_osx and kicklib).

Notes for updating

Linux:
You don't need an extra package for CEGUILua and Tolua, it's already shipped with CEGUI.
However you do need to make sure that the OgreRenderer is installed too with CEGUI 0.7 (may be a separate package).
Also, Orxonox now recognises if you install the CgProgramManager (a separate package available on newer Ubuntu on Debian systems).

Windows:
Download the new dependency packages versioned 6.0 and use these. If you have problems with that or if you don't like the in game console problem mentioned below, you can download the new 4.3 version of the packages (only available for Visual Studio 2005/2008).

Key new features:

  • *Support for Mac OS X*
  • Visual Studio 2010 support
  • Bullet library update to 2.77
  • OIS library update to 1.3
  • Support for CEGUI 0.7 —> Support for Arch Linux and even SuSE
  • Improved install target
  • Compiles now with GCC 4.6
  • Ogre Cg Shader plugin activated for Linux if available
  • And of course lots of bug fixes

There are also some regressions:

  • No support for CEGUI 0.5, Ogre 1.4 and boost 1.35 - 1.39 any more
  • In game console is not working in main menu for CEGUI 0.7
  • Tolua (just the C lib, not the application) and CEGUILua libraries are no longer in our repository. —> You will need to get these as well when compiling Orxonox
  • And of course lots of new bugs we don't yet know about
File:
1 edited

Legend:

Unmodified
Added
Removed
  • code/trunk/src/external/ois/win32/Win32JoyStick.cpp

    r5781 r8351  
    2121    3. This notice may not be removed or altered from any source distribution.
    2222*/
    23 #include "Win32/Win32JoyStick.h"
    24 #include "Win32/Win32InputManager.h"
    25 #include "Win32/Win32ForceFeedback.h"
     23#include "win32/Win32JoyStick.h"
     24#include "win32/Win32InputManager.h"
     25#include "win32/Win32ForceFeedback.h"
    2626#include "OISEvents.h"
    2727#include "OISException.h"
    2828
     29// (Orxonox): Required for MinGW to compile properly
     30#ifdef __MINGW32__
     31#  include <oaidl.h>
     32#  ifndef __MINGW_EXTENSION
     33#    define __MINGW_EXTENSION __extension__
     34#  endif
     35#endif
     36
    2937#include <cassert>
     38#include <wbemidl.h>
     39#include <oleauto.h>
     40//#include <wmsstd.h>
     41#ifndef SAFE_RELEASE
     42#define SAFE_RELEASE(x) \
     43   if(x != NULL)        \
     44   {                    \
     45      x->Release();     \
     46      x = NULL;         \
     47   }
     48#endif
     49
     50// (Orxonox): MinGW doesn't have swscanf_s
     51#ifdef __MINGW32__
     52#       define swscanf_s swscanf
     53#endif
     54
     55#ifdef OIS_WIN32_XINPUT_SUPPORT
     56#       pragma comment(lib, "xinput.lib")
     57#endif
    3058
    3159//DX Only defines macros for the JOYSTICK not JOYSTICK2, so fix it
     
    4068#define DIJOFS_SLIDER3(n) (FIELD_OFFSET(DIJOYSTATE2, rglFSlider)+(n) * sizeof(LONG))
    4169
     70#define XINPUT_TRANSLATED_BUTTON_COUNT 12
     71#define XINPUT_TRANSLATED_AXIS_COUNT 6
     72
    4273using namespace OIS;
    4374
    4475//--------------------------------------------------------------------------------------------------//
    45 Win32JoyStick::Win32JoyStick( InputManager* creator, IDirectInput8* pDI,
    46         bool buffered, DWORD coopSettings, const JoyStickInfo &info )
    47         : JoyStick(info.vendor, buffered, info.devId, creator)
    48 {
    49         mDirectInput = pDI;
    50         coopSetting = coopSettings;
    51         mJoyStick = 0;
    52 
    53         deviceGuid = info.deviceID;
    54 
    55         ff_device = 0;
     76Win32JoyStick::Win32JoyStick( InputManager* creator, IDirectInput8* pDI, bool buffered, DWORD coopSettings, const JoyStickInfo &info ) :
     77        JoyStick(info.vendor, buffered, info.devId, creator),
     78        mDirectInput(pDI),
     79        coopSetting(coopSettings),
     80        mJoyStick(0),
     81        mJoyInfo(info),
     82        mFfDevice(0)
     83{
    5684}
    5785
     
    5987Win32JoyStick::~Win32JoyStick()
    6088{
    61         delete ff_device;
     89        delete mFfDevice;
    6290
    6391        if(mJoyStick)
     
    6997
    7098        //Return joystick to pool
    71         JoyStickInfo js;
    72         js.deviceID = deviceGuid;
    73         js.devId = mDevID;
    74         js.vendor = mVendor;
    75         static_cast<Win32InputManager*>(mCreator)->_returnJoyStick(js);
     99        static_cast<Win32InputManager*>(mCreator)->_returnJoyStick(mJoyInfo);
    76100}
    77101
     
    79103void Win32JoyStick::_initialize()
    80104{
    81         //Clear old state
    82         mState.mAxes.clear();
    83 
    84         if (ff_device)
    85         {
    86                 delete ff_device;
    87                 ff_device = 0;
    88         }
    89 
    90         // Create direct input joystick device.
    91         if(FAILED(mDirectInput->CreateDevice(deviceGuid, &mJoyStick, NULL)))
    92                 OIS_EXCEPT( E_General, "Win32JoyStick::_initialize() >> Could not initialize joy device!");
    93 
    94         // Set DIJoystick2 data format.
    95         if(FAILED(mJoyStick->SetDataFormat(&c_dfDIJoystick2)))
    96                 OIS_EXCEPT( E_General, "Win32JoyStick::_initialize() >> data format error!");
    97 
    98         // Set cooperative level as specified when creating input manager.
    99         HWND hwin = ((Win32InputManager*)mCreator)->getWindowHandle();
    100         if(FAILED(mJoyStick->SetCooperativeLevel( hwin, coopSetting)))
    101                 OIS_EXCEPT( E_General, "Win32JoyStick::_initialize() >> failed to set cooperation level!");
    102 
    103         // Set buffer size.
    104         DIPROPDWORD dipdw;
    105         dipdw.diph.dwSize       = sizeof(DIPROPDWORD);
    106         dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
    107         dipdw.diph.dwObj        = 0;
    108         dipdw.diph.dwHow        = DIPH_DEVICE;
    109         dipdw.dwData            = JOYSTICK_DX_BUFFERSIZE;
    110 
    111         if( FAILED(mJoyStick->SetProperty(DIPROP_BUFFERSIZE, &dipdw.diph)) )
    112                 OIS_EXCEPT( E_General, "Win32JoyStick::_initialize >> Failed to set buffer size property" );
    113 
    114         // Enumerate all axes/buttons/sliders/force feedback/etc before aquiring
    115         _enumerate();
    116 
    117         mState.clear();
    118 
    119         capture();
     105    if (mJoyInfo.isXInput)
     106    {
     107        _enumerate();
     108    }
     109    else
     110    {
     111            //Clear old state
     112            mState.mAxes.clear();
     113
     114            delete mFfDevice;
     115            mFfDevice = 0;
     116
     117            DIPROPDWORD dipdw;
     118
     119            dipdw.diph.dwSize       = sizeof(DIPROPDWORD);
     120            dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
     121            dipdw.diph.dwObj        = 0;
     122            dipdw.diph.dwHow        = DIPH_DEVICE;
     123            dipdw.dwData            = JOYSTICK_DX_BUFFERSIZE;
     124
     125            if(FAILED(mDirectInput->CreateDevice(mJoyInfo.deviceID, &mJoyStick, NULL)))
     126                    OIS_EXCEPT( E_General, "Win32JoyStick::_initialize() >> Could not initialize joy device!");
     127
     128            if(FAILED(mJoyStick->SetDataFormat(&c_dfDIJoystick2)))
     129                    OIS_EXCEPT( E_General, "Win32JoyStick::_initialize() >> data format error!");
     130
     131            HWND hwin = ((Win32InputManager*)mCreator)->getWindowHandle();
     132
     133            if(FAILED(mJoyStick->SetCooperativeLevel( hwin, coopSetting)))
     134                    OIS_EXCEPT( E_General, "Win32JoyStick::_initialize() >> failed to set cooperation level!");
     135
     136            if( FAILED(mJoyStick->SetProperty(DIPROP_BUFFERSIZE, &dipdw.diph)) )
     137                    OIS_EXCEPT( E_General, "Win32Mouse::Win32Mouse >> Failed to set buffer size property" );
     138
     139            //Enumerate all axes/buttons/sliders/etc before aquiring
     140            _enumerate();
     141
     142            mState.clear();
     143
     144            capture();
     145    }
    120146}
    121147
     
    123149void Win32JoyStick::_enumerate()
    124150{
    125         // Get joystick capabilities.
    126         mDIJoyCaps.dwSize = sizeof(DIDEVCAPS);
    127         if( FAILED(mJoyStick->GetCapabilities(&mDIJoyCaps)) )
    128                 OIS_EXCEPT( E_General, "Win32JoyStick::_enumerate >> Failed to get capabilities" );
    129 
    130         // => Number of POVs
    131         mPOVs = (short)mDIJoyCaps.dwPOVs;
    132 
    133         // => Number of buttons and axes.
    134         mState.mButtons.resize(mDIJoyCaps.dwButtons);
    135         mState.mAxes.resize(mDIJoyCaps.dwAxes);
    136 
    137         // Enumerate all Force Feedback effects (if any)
    138         mJoyStick->EnumEffects(DIEnumEffectsCallback, this, DIEFT_ALL);
    139 
    140         //Reset the axis mapping enumeration value
    141         _AxisNumber = 0;
    142 
    143         // Enumerate and set axis constraints (and check FF Axes)
    144         mJoyStick->EnumObjects(DIEnumDeviceObjectsCallback, this, DIDFT_AXIS);
     151    if (mJoyInfo.isXInput)
     152    {
     153        mPOVs = 1;
     154
     155        mState.mButtons.resize(XINPUT_TRANSLATED_BUTTON_COUNT);
     156            mState.mAxes.resize(XINPUT_TRANSLATED_AXIS_COUNT);
     157    }
     158    else
     159    {
     160                // Get joystick capabilities.
     161                mDIJoyCaps.dwSize = sizeof(DIDEVCAPS);
     162                if( FAILED(mJoyStick->GetCapabilities(&mDIJoyCaps)) )
     163                        OIS_EXCEPT( E_General, "Win32JoyStick::_enumerate >> Failed to get capabilities" );
     164
     165            mPOVs = (short)mDIJoyCaps.dwPOVs;
     166
     167            mState.mButtons.resize(mDIJoyCaps.dwButtons);
     168            mState.mAxes.resize(mDIJoyCaps.dwAxes);
     169
     170            //Reset the axis mapping enumeration value
     171            _AxisNumber = 0;
     172
     173            //Enumerate Force Feedback (if any)
     174            mJoyStick->EnumEffects(DIEnumEffectsCallback, this, DIEFT_ALL);
     175
     176            //Enumerate and set axis constraints (and check FF Axes)
     177            mJoyStick->EnumObjects(DIEnumDeviceObjectsCallback, this, DIDFT_AXIS);
     178    }
    145179}
    146180
     
    191225        if((lpddoi->dwFlags & DIDOI_FFACTUATOR) != 0 )
    192226        {
    193                 if( _this->ff_device )
     227                if( _this->mFfDevice )
    194228                {
    195                         _this->ff_device->_addFFAxis();
     229                        _this->mFfDevice->_addFFAxis();
    196230                }
    197231        }
     
    200234        //as DInput has no API to query the device for these capabilities
    201235        //(the only way to know is to try them ...)
    202         if( _this->ff_device )
    203         {
    204             _this->ff_device->_setGainSupport(true);
    205             _this->ff_device->_setAutoCenterSupport(true);
     236        if( _this->mFfDevice )
     237        {
     238            _this->mFfDevice->_setGainSupport(true);
     239            _this->mFfDevice->_setAutoCenterSupport(true);
    206240        }
    207241
     
    215249
    216250        //Create the FF instance only after we know there is at least one effect type
    217         if( _this->ff_device == 0 )
    218           _this->ff_device = new Win32ForceFeedback(_this->mJoyStick, &_this->mDIJoyCaps);
    219 
    220         _this->ff_device->_addEffectSupport( pdei );
     251        if( _this->mFfDevice == 0 )
     252                _this->mFfDevice = new Win32ForceFeedback(_this->mJoyStick, &_this->mDIJoyCaps);
     253
     254        _this->mFfDevice->_addEffectSupport(pdei);
    221255
    222256        return DIENUM_CONTINUE;
     
    226260void Win32JoyStick::capture()
    227261{
     262#ifdef OIS_WIN32_XINPUT_SUPPORT
     263        //handle xbox controller differently
     264    if (mJoyInfo.isXInput)
     265        {
     266                captureXInput();
     267                return;
     268        }
     269#endif
     270
     271        //handle directinput based devices
    228272        DIDEVICEOBJECTDATA diBuff[JOYSTICK_DX_BUFFERSIZE];
    229273        DWORD entries = JOYSTICK_DX_BUFFERSIZE;
     
    241285
    242286                // Poll the device to read the current state
    243             mJoyStick->Poll();
     287                mJoyStick->Poll();
    244288                hr = mJoyStick->GetDeviceData( sizeof(DIDEVICEOBJECTDATA), diBuff, &entries, 0 );
    245289                //Perhaps the user just tabbed away
     
    353397
    354398//--------------------------------------------------------------------------------------------------//
     399void Win32JoyStick::captureXInput()
     400{
     401#ifdef OIS_WIN32_XINPUT_SUPPORT
     402    XINPUT_STATE inputState;
     403        if (XInputGetState((DWORD)mJoyInfo.xInputDev, &inputState) != ERROR_SUCCESS)
     404        memset(&inputState, 0, sizeof(inputState));
     405
     406    //Sticks and triggers
     407        int value;
     408    bool axisMoved[XINPUT_TRANSLATED_AXIS_COUNT] = {false,false,false,false,false,false};
     409
     410        //LeftY
     411        value = -(int)inputState.Gamepad.sThumbLY;
     412        mState.mAxes[0].rel = value - mState.mAxes[0].abs;
     413        mState.mAxes[0].abs = value;
     414        if(mState.mAxes[0].rel != 0)
     415        axisMoved[0] = true;
     416
     417        //LeftX
     418    mState.mAxes[1].rel = inputState.Gamepad.sThumbLX - mState.mAxes[1].abs;
     419    mState.mAxes[1].abs = inputState.Gamepad.sThumbLX;
     420
     421        if(mState.mAxes[1].rel != 0)
     422        axisMoved[1] = true;
     423
     424        //RightY
     425        value = -(int)inputState.Gamepad.sThumbRY;           
     426    mState.mAxes[2].rel = value - mState.mAxes[2].abs;
     427    mState.mAxes[2].abs = value;
     428        if(mState.mAxes[2].rel != 0)
     429        axisMoved[2] = true;
     430
     431        //RightX
     432    mState.mAxes[3].rel = inputState.Gamepad.sThumbRX - mState.mAxes[3].abs;
     433    mState.mAxes[3].abs = inputState.Gamepad.sThumbRX;
     434        if(mState.mAxes[3].rel != 0)
     435                axisMoved[3] = true;
     436
     437        //Left trigger
     438    value = inputState.Gamepad.bLeftTrigger * 129;
     439        if(value > JoyStick::MAX_AXIS)
     440                value = JoyStick::MAX_AXIS;
     441
     442    mState.mAxes[4].rel = value - mState.mAxes[4].abs;
     443    mState.mAxes[4].abs = value;
     444        if(mState.mAxes[4].rel != 0)
     445                axisMoved[4] = true;
     446
     447        //Right trigger
     448    value = (int)inputState.Gamepad.bRightTrigger * 129;
     449        if(value > JoyStick::MAX_AXIS)
     450                value = JoyStick::MAX_AXIS;
     451
     452        mState.mAxes[5].rel = value - mState.mAxes[5].abs;
     453    mState.mAxes[5].abs = value;
     454        if(mState.mAxes[5].rel != 0)
     455                axisMoved[5] = true;
     456   
     457    //POV
     458    int previousPov = mState.mPOV[0].direction;       
     459    int& pov = mState.mPOV[0].direction;
     460    pov = Pov::Centered;       
     461    if (inputState.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP)
     462        pov |= Pov::North;
     463    else if (inputState.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN)
     464        pov |= Pov::South;
     465    if (inputState.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT)
     466        pov |= Pov::West;
     467    else if (inputState.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT)
     468        pov |= Pov::East;
     469   
     470    //Buttons - The first 4 buttons don't need to be checked since they represent the dpad
     471    bool previousButtons[XINPUT_TRANSLATED_BUTTON_COUNT];
     472    std::copy(mState.mButtons.begin(), mState.mButtons.end(), previousButtons);
     473    for (size_t i = 0; i < XINPUT_TRANSLATED_BUTTON_COUNT; i++)
     474        mState.mButtons[i] = (inputState.Gamepad.wButtons & (1 << (i + 4))) != 0;
     475
     476    //Send events
     477    if (mBuffered && mListener)
     478    {
     479            JoyStickEvent joystickEvent(this, mState);
     480
     481            //Axes
     482            for (int i = 0; i < XINPUT_TRANSLATED_AXIS_COUNT; i++)
     483        {
     484                    if (axisMoved[i] && !mListener->axisMoved(joystickEvent, i))
     485                            return;
     486        }
     487
     488        //POV
     489        if (previousPov != pov && !mListener->povMoved(joystickEvent, 0))
     490            return;
     491
     492        //Buttons
     493        for (int i = 0; i < XINPUT_TRANSLATED_BUTTON_COUNT; i++)
     494        {
     495            if (!previousButtons[i] && mState.mButtons[i])
     496            {
     497                if (!mListener->buttonPressed(joystickEvent, i))
     498                    return;
     499            }
     500            else if (previousButtons[i] && !mState.mButtons[i])
     501            {
     502                if (!mListener->buttonReleased(joystickEvent, i))
     503                    return;
     504            }
     505        }
     506    }
     507#endif
     508}
     509
     510//--------------------------------------------------------------------------------------------------//
    355511bool Win32JoyStick::_doButtonClick( int button, DIDEVICEOBJECTDATA& di )
    356512{
     
    410566Interface* Win32JoyStick::queryInterface(Interface::IType type)
    411567{
    412         //Thought about using covariant return type here.. however,
    413         //some devices may allow LED light changing, or other interface stuff
    414 
    415         if( ff_device && type == Interface::ForceFeedback )
    416                 return ff_device;
     568        if( mFfDevice && type == Interface::ForceFeedback )
     569                return mFfDevice;
    417570        else
    418571                return 0;
    419572}
     573
     574//--------------------------------------------------------------------------------------------------//
     575void Win32JoyStick::CheckXInputDevices(JoyStickInfoList &joys)
     576{
     577    IWbemLocator*           pIWbemLocator  = NULL;
     578    IEnumWbemClassObject*   pEnumDevices   = NULL;
     579    IWbemClassObject*       pDevices[20]   = {0};
     580    IWbemServices*          pIWbemServices = NULL;
     581    BSTR                    bstrNamespace  = NULL;
     582    BSTR                    bstrDeviceID   = NULL;
     583    BSTR                    bstrClassName  = NULL;
     584    DWORD                   uReturned      = 0;
     585    bool                    bIsXinputDevice= false;
     586        DWORD                   iDevice        = 0;
     587        int                     xDevice        = 0;
     588    VARIANT                 var;
     589    HRESULT                 hr;
     590
     591        if(joys.size() == 0)
     592                return;
     593
     594    // CoInit if needed
     595    hr = CoInitialize(NULL);
     596    bool bCleanupCOM = SUCCEEDED(hr);
     597
     598    // Create WMI
     599    // (Orxonox): Fix for MinGW
     600#ifdef __MINGW32__
     601    hr = CoCreateInstance(CLSID_WbemLocator, NULL, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID*)&pIWbemLocator);
     602#else
     603    hr = CoCreateInstance(__uuidof(WbemLocator), NULL, CLSCTX_INPROC_SERVER, __uuidof(IWbemLocator), (LPVOID*)&pIWbemLocator);
     604#endif
     605    if( FAILED(hr) || pIWbemLocator == NULL )
     606        goto LCleanup;
     607
     608    bstrNamespace = SysAllocString( L"\\\\.\\root\\cimv2" );
     609        if( bstrNamespace == NULL )
     610                goto LCleanup;
     611
     612    bstrClassName = SysAllocString( L"Win32_PNPEntity" );
     613        if( bstrClassName == NULL )
     614                goto LCleanup;
     615
     616    bstrDeviceID  = SysAllocString( L"DeviceID" );
     617        if( bstrDeviceID == NULL )
     618                goto LCleanup;
     619   
     620    // Connect to WMI
     621    hr = pIWbemLocator->ConnectServer( bstrNamespace, NULL, NULL, 0L, 0L, NULL, NULL, &pIWbemServices );
     622    if( FAILED(hr) || pIWbemServices == NULL )
     623        goto LCleanup;
     624
     625    // Switch security level to IMPERSONATE.
     626    CoSetProxyBlanket(pIWbemServices, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE );                   
     627
     628    hr = pIWbemServices->CreateInstanceEnum( bstrClassName, 0, NULL, &pEnumDevices );
     629    if( FAILED(hr) || pEnumDevices == NULL )
     630        goto LCleanup;
     631
     632    // Loop over all devices
     633    for( ;; )
     634    {
     635        // Get 20 at a time
     636        hr = pEnumDevices->Next(5000, 20, pDevices, &uReturned);
     637        if( FAILED(hr) )
     638            goto LCleanup;
     639
     640        if( uReturned == 0 )
     641            break;
     642
     643        for(iDevice = 0; iDevice < uReturned; iDevice++)
     644        {
     645            // For each device, get its device ID
     646            hr = pDevices[iDevice]->Get(bstrDeviceID, 0L, &var, NULL, NULL);
     647            if(SUCCEEDED(hr) && var.vt == VT_BSTR && var.bstrVal != NULL)
     648            {
     649                // Check if the device ID contains "IG_".  If it does, then it's an XInput device - This information can not be found from DirectInput
     650                if(wcsstr(var.bstrVal, L"IG_"))
     651                {
     652                    // If it does, then get the VID/PID from var.bstrVal
     653                    DWORD dwPid = 0, dwVid = 0;
     654                    WCHAR* strVid = wcsstr( var.bstrVal, L"VID_" );
     655                    if(strVid && swscanf_s( strVid, L"VID_%4X", &dwVid ) != 1)
     656                                                dwVid = 0;
     657
     658                    WCHAR* strPid = wcsstr( var.bstrVal, L"PID_" );
     659                    if(strPid && swscanf_s( strPid, L"PID_%4X", &dwPid ) != 1)
     660                        dwPid = 0;
     661
     662                    // Compare the VID/PID to the DInput device
     663                    DWORD dwVidPid = MAKELONG(dwVid, dwPid);
     664                                        for(JoyStickInfoList::iterator i = joys.begin(); i != joys.end(); ++i)
     665                                        {
     666                                                if(dwVidPid == i->productGuid.Data1)
     667                                                {
     668                                                        i->isXInput = true;
     669                                                        i->xInputDev = xDevice;
     670                                                }
     671                                        }
     672
     673                                        if(joys.size() == 0)
     674                                                goto LCleanup;
     675                }
     676            }
     677
     678            SAFE_RELEASE(pDevices[iDevice]);
     679        }
     680    }
     681
     682LCleanup:
     683    if(bstrNamespace)
     684        SysFreeString(bstrNamespace);
     685
     686    if(bstrDeviceID)
     687        SysFreeString(bstrDeviceID);
     688
     689    if(bstrClassName)
     690        SysFreeString(bstrClassName);
     691
     692    for(iDevice=0; iDevice < 20; iDevice++)
     693        SAFE_RELEASE(pDevices[iDevice]);
     694
     695    SAFE_RELEASE(pEnumDevices);
     696    SAFE_RELEASE(pIWbemLocator);
     697    SAFE_RELEASE(pIWbemServices);
     698
     699    if(bCleanupCOM)
     700        CoUninitialize();
     701}
Note: See TracChangeset for help on using the changeset viewer.