void System::onRawArrival( HANDLE handle ) { UINT pathLength = 0; if ( GetRawInputDeviceInfoW( handle, RIDI_DEVICENAME, NULL, &pathLength ) ) NIL_EXCEPT_WINAPI( "GetRawInputDeviceInfoW failed" ); wideString rawPath( pathLength, '\0' ); GetRawInputDeviceInfoW( handle, RIDI_DEVICENAME, &rawPath[0], &pathLength ); rawPath.resize( rawPath.length() - 1 ); for ( auto device : mDevices ) { if ( device->getHandler() != Device::Handler_RawInput ) continue; auto rawDevice = static_cast<RawInputDevice*>( device ); if ( !_wcsicmp( rawDevice->getRawPath().c_str(), rawPath.c_str() ) ) { deviceConnect( rawDevice ); return; } } auto device = new RawInputDevice( this, getNextID(), handle, rawPath ); if ( isInitializing() ) device->setStatus( Device::Status_Connected ); else deviceConnect( device ); mDevices.push_back( device ); }
std::unique_ptr<std::wstring> rawinput_device_name(HANDLE hDevice){ UINT _data_size; UINT _result; if(0 != GetRawInputDeviceInfoW(hDevice, RIDI_DEVICENAME, 0, &_data_size)){ std::cerr << "rawinput_device_name: 0 != GetRawInputDeviceInfoW(hDevice, RIDI_DEVICENAME, 0, &data_size)" << std::endl; return std::unique_ptr<std::wstring>(nullptr); } std::unique_ptr<std::wstring> device_name (new std::wstring(_data_size, '\0')); _result = GetRawInputDeviceInfoW(hDevice, RIDI_DEVICENAME, &(*device_name)[0], &_data_size); if(-1 == _result){ std::cerr << "rawinput_device_name: -1 == GetRawInputDeviceInfoW(hDevice, RIDI_DEVICENAME, &(*device_name)[0], &data_size)" << std::endl; return std::unique_ptr<std::wstring>(nullptr); } device_name->resize(_result); return device_name; }
int _tmain(int argc, _TCHAR* argv[]) { BOOL b; UINT size = 0, i; RAWINPUTDEVICELIST *pRawInputDeviceList; b = GetRawInputDeviceList(NULL, &size, sizeof(RAWINPUTDEVICELIST)); printf("b ==> %d, size ==> %d\n", b, size); pRawInputDeviceList = (RAWINPUTDEVICELIST *)malloc(sizeof(RAWINPUTDEVICELIST)* size); b = GetRawInputDeviceList(pRawInputDeviceList, &size, sizeof(RAWINPUTDEVICELIST)); printf("b ==> %d, size ==> %d\n", b, size); for (i = 0; i < size; ++i) { WCHAR buffer[MAX_PATH + 1]; printf("device.type ==> 0x%x\n", pRawInputDeviceList[i].dwType); printf("device.handle ==> 0x%p\n", pRawInputDeviceList[i].hDevice); UINT BufferSize = ARRAYSIZE(buffer); UINT retval = GetRawInputDeviceInfoW(pRawInputDeviceList[i].hDevice, RIDI_DEVICENAME, &buffer[0], &BufferSize); printf("retval ==> %d\n", retval); printf("buffer ==> %ws\n", buffer); RID_DEVICE_INFO DeviceInfo = { 0 }; BufferSize = sizeof(DeviceInfo); retval = GetRawInputDeviceInfoW(pRawInputDeviceList[i].hDevice, RIDI_DEVICEINFO, &DeviceInfo, &BufferSize); printf("Device info.dwType ==> 0x%x\n", DeviceInfo.dwType); if (DeviceInfo.dwType == RIM_TYPEHID) { printf("usage page ==> 0x%x, usage ==> 0x%x\n", DeviceInfo.hid.usUsagePage, DeviceInfo.hid.usUsage); } } return 0; }
bool nxRawInputDevice::GetInformation(void) { HKEY hKey = NULL; try { /// Retrieve the encoded device name UINT uSize = 0; // Retrieve the number of characters needed to store the device name (including the null) // Calling the unicode version, that way we get the number of characters properly. // All the characters used, in practice, are representable in ANSI. if (GetRawInputDeviceInfoW(hDevice,RIDI_DEVICENAME,NULL,&uSize) < 0) nxThrow("Couldn't retrieve length of device name string."); // Allocate the space strDeviceName.resize(uSize-1); // Retrieve the device name. Example: "\\??\\ACPI#PNP0303#3&13c0b0c5&0#{884b96c3-56ef-11d1-bc8c-00a0c91405dd}" if (GetRawInputDeviceInfoA(hDevice,RIDI_DEVICENAME,const_cast<char*>(strDeviceName.c_str()),&uSize) < 0) nxThrow("Couldn't retrieve the encoded device name."); /// Multiply Occurring Error. Placing here so we can include the device name. const std::string strFormatError = std::string("Device name is encoded in an unsupported format. \"") + strDeviceName + std::string("\""); // Validate the device name is nonempty. if (strDeviceName.empty()) nxThrow(strFormatError); /// Split the device name into parts // Delimiter offsets std::string::size_type uCurrent, uNext; // First # position uNext = strDeviceName.find_first_of('#'); // Position of the trailing slash of the beginning "\\??\\" part. uCurrent = strDeviceName.find_last_of('\\',uNext); /// Loop through the fields std::string strField; for (UINT uField = 0;uField < 4;++uField) { // Validate field offsets if (uCurrent == std::string::npos) nxThrow(strFormatError); // Pull out the field data if (uNext != std::string::npos) strField = strDeviceName.substr(uCurrent+1,uNext-uCurrent-1); else strField = strDeviceName.substr(uCurrent+1); // Ensure some value was retrieved if (strField.empty()) nxThrow(strFormatError); /// Set the appropriate field switch (uField) { case 0: strClassCode = strField; break; case 1: strSubClassCode = strField; break; case 2: strProtocolCode = strField; break; case 3: strGUID = strField; break; default: nxThrow("Unhandled token index, notify the developer of his silly mistake."); } // Advance to the next token. uCurrent = uNext; if (uCurrent != std::string::npos) uNext = strDeviceName.find_first_of('#',uCurrent+1); else uNext = std::string::npos; } /// Retrieve the device description and class from the registry DWORD dwKeyType; DWORD dwKeySize; std::string strRegKey = std::string("SYSTEM\\CurrentControlSet\\Enum\\")+strClassCode+"\\"+strSubClassCode+"\\"+strProtocolCode; if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,strRegKey.c_str(),0,KEY_QUERY_VALUE,&hKey) != ERROR_SUCCESS) { hKey = NULL; nxThrow(std::string("Couldn't open the device's registry key - ") + strRegKey); } // Retrieve data type and size (including null) if (RegQueryValueEx(hKey,"DeviceDesc",NULL,&dwKeyType,NULL,&dwKeySize) != ERROR_SUCCESS) nxThrow(std::string("Couldn't retrieve size of \"DeviceDesc\" value for registry key - ") + strRegKey); // Size the buffer accordingly strDeviceDesc.resize(dwKeySize-1); // Added the const_cast for clarity, though it isn't necessary. if (RegQueryValueEx(hKey,"DeviceDesc",NULL,&dwKeyType,(BYTE*)const_cast<char*>(strDeviceDesc.c_str()),&dwKeySize) != ERROR_SUCCESS) nxThrow(std::string("Couldn't retrieve value of \"DeviceDesc\" for registry key - ") + strRegKey); // Retrieve data type and size (including null) if (RegQueryValueEx(hKey,"Class",NULL,&dwKeyType,NULL,&dwKeySize) != ERROR_SUCCESS) nxThrow(std::string("Couldn't retrieve size of \"Class\" value for registry key - ") + strRegKey); // Size the buffer accordingly strDeviceClass.resize(dwKeySize-1); // Added the const_cast for clarity, though it isn't necessary. if (RegQueryValueEx(hKey,"Class",NULL,&dwKeyType,(BYTE*)const_cast<char*>(strDeviceClass.c_str()),&dwKeySize) != ERROR_SUCCESS) nxThrow(std::string("Couldn't retrieve value of \"Class\" for registry key - ") + strRegKey); /// Use registry information to verify our keyboards/mice are in fact keyboards and mice. // This will also turn the terminal services "system" devices to HID if (stricmp(strClassCode.c_str(),"root")==0) dwType = RIM_TYPEHID; else if (IsKeyboard()) { if (stricmp(strDeviceClass.c_str(),"keyboard")!=0) dwType = RIM_TYPEHID; } else if (IsMouse()) { if (stricmp(strDeviceClass.c_str(),"mouse")!=0) dwType = RIM_TYPEHID; } else //HID { if (stricmp(strDeviceClass.c_str(),"keyboard")==0) dwType = RIM_TYPEKEYBOARD; else if (stricmp(strDeviceClass.c_str(),"mouse")==0) dwType = RIM_TYPEMOUSE; } // Make sure this isn't vmware's keyboard driver (rather than a physical keyboard) if (IsKeyboard()) { HKEY hKeyVM = NULL; // If this fails, then something is amiss (there should be a control key), but, it isn't really a bail-out situation if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,(strRegKey+"\\Control").c_str(),0,KEY_QUERY_VALUE,&hKeyVM) == ERROR_SUCCESS) { // Retrieve data type and size (including null) if (RegQueryValueEx(hKeyVM,"ActiveService",NULL,&dwKeyType,NULL,&dwKeySize) == ERROR_SUCCESS) { std::string strActiveService; // Size the buffer accordingly strActiveService.resize(dwKeySize-1); // Added the const_cast for clarity, though it isn't necessary. if (RegQueryValueEx(hKeyVM,"ActiveService",NULL,&dwKeyType,(BYTE*)const_cast<char*>(strActiveService.c_str()),&dwKeySize) == ERROR_SUCCESS) { if (stricmp(strActiveService.c_str(),"vmkbd") == 0) { // It's the vmware keyboard, not a physical keyboard. dwType = RIM_TYPEHID; } } } RegCloseKey(hKeyVM); } } // Clean up RegCloseKey(hKey); hKey=NULL; // Return false if it isn't a supported keyboard and mouse if (!IsMouse() && !IsKeyboard()) return false; } catch (const std::exception&e) { nxLog << e.what() << std::endl; Clear(); if (hKey) RegCloseKey(hKey); return false; } return true; }