void SMNetworkAdapterSettings::_FingSetupInfo(HDEVINFO* devInfo, SP_DEVINFO_DATA* devInfoData) const
{
	SM_ASSERT( !_hardwareId.IsEmpty() );

	SMString hwID(_hardwareId);
	hwID.MakeUpper();

	*devInfo = ::SetupDiGetClassDevs(NULL, NULL, NULL, DIGCF_ALLCLASSES | DIGCF_PRESENT);
	if( INVALID_HANDLE_VALUE == *devInfo )
		throw SMRuntimeException(::GetLastError());

	::ZeroMemory(devInfoData, sizeof(SP_DEVINFO_DATA));
	devInfoData->cbSize = sizeof(SP_DEVINFO_DATA);

	PTSTR buf = NULL;
	DWORD bufSize = 0;
	DWORD reqSize = 0;

	for(int i=0; SetupDiEnumDeviceInfo(*devInfo,i, devInfoData); i++)
	{
		if ( !SetupDiGetDeviceInstanceId(*devInfo, devInfoData, buf, bufSize, &reqSize) )
		{
			if ( bufSize < reqSize )
			{
				if ( NULL != buf )
				{
					delete[] buf;
					buf = NULL;
					bufSize = 0;
				}
				buf = new TCHAR[reqSize];
				if ( NULL == buf )
				{
					SM_LOG(1, E_FAIL, SMString("Insufficient memory : ") + _com_error(GetLastError()).ErrorMessage());
					break;
				}
				bufSize = reqSize;
				if ( !SetupDiGetDeviceInstanceId(*devInfo, devInfoData, buf, bufSize, &reqSize) )
					throw SMRuntimeException(::GetLastError());
			}
			else
			{
				SM_LOG(1, E_FAIL, SMString("SetupDiGetDeviceInstanceId(): ") + _com_error(GetLastError()).ErrorMessage());
				break;
			}
		}

		SMString szBuf = buf;
		szBuf.MakeUpper();

		if ( szBuf.Find(hwID.DataW()) != -1 )
			return;
	}
}
void FillDeviceInstanceId(HDEVINFO hDevHandle, SP_DEVINFO_DATA deviceInfoData, WCHAR *wAdapter)
{
	DWORD i;

	for (i = 0; SetupDiEnumDeviceInfo(hDevHandle, i, &deviceInfoData); i++)
	{
		BYTE buffer[BUFFER_SIZE];
		WCHAR deviceInfo[BUFFER_SIZE];
		DWORD dwProperty = 0; 

		memset(buffer, 0, BUFFER_SIZE);

		if (SetupDiGetDeviceRegistryProperty(hDevHandle, &deviceInfoData,
			SPDRP_DEVICEDESC , &dwProperty, buffer, BUFFER_SIZE, NULL) == TRUE)
		{
			wcscpy_s(deviceInfo, BUFFER_SIZE, (LPWSTR)buffer);

			if (wcscmp(wAdapter, deviceInfo) == 0)
			{
				RtlZeroMemory(wDeviceInstanceId, MAX_PATH);

				SetupDiGetDeviceInstanceId(hDevHandle, &deviceInfoData, wDeviceInstanceId, MAX_PATH, 0);
			}
		}
	}
} 
bool QextSerialEnumerator::matchAndDispatchChangedDevice(const QString & deviceID, const GUID & guid, WPARAM wParam)
{
    bool rv = false;
    DWORD dwFlag = (DBT_DEVICEARRIVAL == wParam) ? DIGCF_PRESENT : DIGCF_ALLCLASSES;
    HDEVINFO devInfo;
    if( (devInfo = SetupDiGetClassDevs(&guid,NULL,NULL,dwFlag)) != INVALID_HANDLE_VALUE )
    {
        SP_DEVINFO_DATA spDevInfoData;
        spDevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
        for(int i=0; SetupDiEnumDeviceInfo(devInfo, i, &spDevInfoData); i++)
        {
            DWORD nSize=0 ;
            TCHAR buf[MAX_PATH];
            if ( SetupDiGetDeviceInstanceId(devInfo, &spDevInfoData, buf, MAX_PATH, &nSize) &&
                    deviceID.contains(TCHARToQString(buf))) // we found a match
            {
                rv = true;
                QextPortInfo info;
                info.productID = info.vendorID = 0;
                getDeviceDetailsWin( &info, devInfo, &spDevInfoData, wParam );
                if( wParam == DBT_DEVICEARRIVAL )
                    emit deviceDiscovered(info);
                else if( wParam == DBT_DEVICEREMOVECOMPLETE )
                    emit deviceRemoved(info);
                break;
            }
        }
        SetupDiDestroyDeviceInfoList(devInfo);
    }
    return rv;
}
Esempio n. 4
0
static BOOL
DeviceIdMatch(IN HDEVINFO DeviceInfoSet,
              IN PSP_DEVINFO_DATA DeviceInfoData,
              IN LPCWSTR lpDeviceId)
{
    DWORD DevIdLen;
    LPWSTR lpQueriedDeviceId;
    BOOL Ret = FALSE;

    if (!SetupDiGetDeviceInstanceId(DeviceInfoSet,
                                    DeviceInfoData,
                                    NULL,
                                    0,
                                    &DevIdLen) &&
        GetLastError() == ERROR_INSUFFICIENT_BUFFER)
    {
        if (DevIdLen == wcslen(lpDeviceId) + 1)
        {
            lpQueriedDeviceId = HeapAlloc(GetProcessHeap(),
                                          0,
                                          DevIdLen * sizeof(WCHAR));
            if (lpQueriedDeviceId != NULL)
            {
                if (SetupDiGetDeviceInstanceId(DeviceInfoSet,
                                               DeviceInfoData,
                                               lpQueriedDeviceId,
                                               DevIdLen,
                                               NULL))
                {
                    Ret = (wcscmp(lpDeviceId,
                                  lpQueriedDeviceId) == 0);
                }

                HeapFree(GetProcessHeap(),
                         0,
                         lpQueriedDeviceId);
            }
        }
    }

    return Ret;
}
Esempio n. 5
0
bool GetSizeForDevID(wxString &TargetDevID, int *WidthMm, int *HeightMm)
{
    HDEVINFO devInfo = SetupDiGetClassDevsEx(
        &GUID_CLASS_MONITOR, //class GUID
        NULL, //enumerator
        NULL, //HWND
        DIGCF_PRESENT, // Flags //DIGCF_ALLCLASSES|
        NULL, // device info, create a new one.
        NULL, // machine name, local machine
        NULL);// reserved
    
    if (NULL == devInfo)
        return false;
    
    bool bRes = false;
    
    for (ULONG i=0; ERROR_NO_MORE_ITEMS != GetLastError(); ++i)
    {
        SP_DEVINFO_DATA devInfoData;
        memset(&devInfoData,0,sizeof(devInfoData));
        devInfoData.cbSize = sizeof(devInfoData);
        
        if (SetupDiEnumDeviceInfo(devInfo,i,&devInfoData))
        {
            wchar_t    Instance[80];
            SetupDiGetDeviceInstanceId(devInfo, &devInfoData, Instance, MAX_PATH, NULL);
            wxString instance(Instance);
            if(instance.Upper().Find( TargetDevID.Upper() ) == wxNOT_FOUND )
                continue;
            
            HKEY hDevRegKey = SetupDiOpenDevRegKey(devInfo,&devInfoData,
                                                   DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_READ);
            
            if(!hDevRegKey || (hDevRegKey == INVALID_HANDLE_VALUE))
                continue;
            
            bRes = GetMonitorSizeFromEDID(hDevRegKey, WidthMm, HeightMm);
            
            RegCloseKey(hDevRegKey);
        }
    }
    SetupDiDestroyDeviceInfoList(devInfo);
    return bRes;
}
    LRESULT QextSerialEnumerator::onDeviceChangeWin( WPARAM wParam, LPARAM lParam )
    {
        if ( DBT_DEVICEARRIVAL == wParam || DBT_DEVICEREMOVECOMPLETE == wParam )
        {
            PDEV_BROADCAST_HDR pHdr = (PDEV_BROADCAST_HDR)lParam;
            if( pHdr->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE )
            {
                PDEV_BROADCAST_DEVICEINTERFACE pDevInf = (PDEV_BROADCAST_DEVICEINTERFACE)pHdr;
                QString devId = TCHARToQString(pDevInf->dbcc_name);
                // devId: \\?\USB#Vid_04e8&Pid_503b#0002F9A9828E0F06#{a5dcbf10-6530-11d2-901f-00c04fb951ed}
                devId.remove("\\\\?\\"); // USB#Vid_04e8&Pid_503b#0002F9A9828E0F06#{a5dcbf10-6530-11d2-901f-00c04fb951ed}
                devId.remove(QRegExp("#\\{(.+)\\}")); // USB#Vid_04e8&Pid_503b#0002F9A9828E0F06
                devId.replace("#", "\\"); // USB\Vid_04e8&Pid_503b\0002F9A9828E0F06
                devId = devId.toUpper();
                //qDebug() << "devname:" << devId;

                DWORD dwFlag = DBT_DEVICEARRIVAL == wParam ? (DIGCF_ALLCLASSES | DIGCF_PRESENT) : DIGCF_ALLCLASSES;
                HDEVINFO hDevInfo = SetupDiGetClassDevs(&GUID_DEVCLASS_PORTS,NULL,NULL,dwFlag);
                SP_DEVINFO_DATA spDevInfoData;
                spDevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);

                for(int i=0; SetupDiEnumDeviceInfo(hDevInfo, i, &spDevInfoData); i++)
                {
                    DWORD nSize=0 ;
                    TCHAR buf[MAX_PATH];
                    if ( !SetupDiGetDeviceInstanceId(hDevInfo, &spDevInfoData, buf, sizeof(buf), &nSize) )
                        qDebug() << "SetupDiGetDeviceInstanceId():" << GetLastError();
                    if( devId == TCHARToQString(buf) ) // we found a match
                    {
                        QextPortInfo info;
                        getDeviceDetailsWin( &info, hDevInfo, &spDevInfoData, wParam );
                        if( wParam == DBT_DEVICEARRIVAL )
                            emit deviceDiscovered(info);
                        else if( wParam == DBT_DEVICEREMOVECOMPLETE )
                            emit deviceRemoved(info);
                        break;
                    }
                }
                SetupDiDestroyDeviceInfoList(hDevInfo);
            }
        }
        return 0;
    }
int iKX::init(int device,int ignore_winmm)
{
    int i=0;
    char string[1024];
    int ret=-1;

    if(device_num!=-1) // double init
    {
     strcpy(error_name,"interface already initialized");
     debug("iKX init(): already initialized\n");
     return -7;
    }

    strcpy(error_name,"no error");

    // asio init
    asio_inited=0;
    last_asio_voice=-1;

    asio_method=0;

     asio_iks_property=NULL;
     asio_secondary_buffer=NULL;
     asio_prim_buffer=NULL;
     asio_ds=NULL;

     pRenderEnumerator=0;
     pRenderFilter=0;
     pRenderPin=0;

    memset(asio_mem_table,0,sizeof(asio_mem_table));

    memset(&guid_,0,sizeof(guid_));

    device_num=device;
    
    HDEVINFO hInfo=SetupDiGetClassDevs((GUID *)&KSCATEGORY_AUDIO,NULL,NULL,DIGCF_DEVICEINTERFACE |DIGCF_PRESENT);
    
    if(hInfo==INVALID_HANDLE_VALUE)
    { 
     debug("iKX init(): setupdigetclassdevs failed [%x]\n",GetLastError());
     strcpy(error_name,"error enumerating devices");
     return ret; 
    }
    
    SP_DEVINFO_DATA devinfo;
    devinfo.cbSize=sizeof(devinfo);

    while(SetupDiEnumDeviceInfo(hInfo,i,&devinfo))
    {
        i++;
        if(SetupDiGetDeviceInstanceId(hInfo,&devinfo,string,sizeof(string),NULL))
        {
            if(
               (strstr(string,"VEN_1102&DEV_0002")==NULL) &&
               (strstr(string,"VEN_1102&DEV_0004")==NULL) &&
               (strstr(string,"VEN_1102&DEV_0008")==NULL) 
              ) // FIXME: bad test, actually :(
            { 
              continue; 
            }
        }
        else
        {
         continue;
         }

        SP_DEVICE_INTERFACE_DATA data;
        data.cbSize=sizeof(data);
        int j=0;
        while(SetupDiEnumDeviceInterfaces(hInfo,&devinfo,(GUID *)&KSCATEGORY_AUDIO,j++,&data)==TRUE)
        {
            DWORD ReqLen=0;
            SetupDiGetInterfaceDeviceDetail (
                hInfo,
                &data,
                NULL,
                0,
                &ReqLen,
            NULL
            );

                PSP_INTERFACE_DEVICE_DETAIL_DATA m_Detail = PSP_INTERFACE_DEVICE_DETAIL_DATA(new char[ReqLen]);

                if ( m_Detail )
                {
                        m_Detail->cbSize = sizeof SP_INTERFACE_DEVICE_DETAIL_DATA;

                        if(SetupDiGetInterfaceDeviceDetail (
                            hInfo,
                            &data,
                            m_Detail,
                            ReqLen,
                            &ReqLen,
                            NULL
                            )==TRUE)
                        {
                            if(strstr(m_Detail->DevicePath,"kx_topo1")!=NULL)
                            {
                             HKEY key=SetupDiOpenDeviceInterfaceRegKey(hInfo,&data,0,KEY_ALL_ACCESS);
                             if(key!=INVALID_HANDLE_VALUE)
                             {
                                      DWORD type; type=REG_SZ;
                                      char tmp_str[256];
                                      DWORD len; len=(DWORD)sizeof(tmp_str);
                                      if(RegQueryValueEx(key,"FriendlyName",NULL,&type,(unsigned char *)tmp_str,&len)==ERROR_SUCCESS)
                                      {
                                        strncpy(mixer_name,tmp_str,sizeof(mixer_name));
                                      }
                                      RegCloseKey(key);
                             }
                             strncpy(topo_path,m_Detail->DevicePath,sizeof(topo_path));
                            } else
                            if(strstr(m_Detail->DevicePath,"kx_wave0")!=NULL)
                            {
                             HKEY key=SetupDiOpenDeviceInterfaceRegKey(hInfo,&data,0,KEY_ALL_ACCESS);
                             if(key!=INVALID_HANDLE_VALUE)
                             {
                                      DWORD type; type=REG_SZ;
                                      char tmp_str[256];
                                      DWORD len; len=(DWORD)sizeof(tmp_str);
                                      if(RegQueryValueEx(key,"FriendlyName",NULL,&type,(unsigned char *)tmp_str,&len)==ERROR_SUCCESS)
                                      {
                                        strncpy(wave_name,tmp_str,sizeof(wave_name));

                                        strncpy(wave23_name,tmp_str,sizeof(wave_name));
                                        char *p=strstr(wave23_name," 0/1");
                                        if(p)
                                        {
                                         *p=0;
                                         strcpy(wave45_name,wave23_name);
                                         strcpy(wave67_name,wave23_name);
                                         strcpy(waveHQ_name,wave23_name);

                                         strcat(wave23_name," 2/3");
                                         strcat(wave45_name," 4/5");
                                         strcat(wave67_name," 6/7");
                                         strcat(waveHQ_name," HQ");
                                        }
                                        else
                                        {
                                         wave23_name[0]=0;
                                         debug("ikX API: not all the 4 wave devices were found... strange\n");
                                        }
                                      }
                                      RegCloseKey(key);
                             }
                             strncpy(wave_path,m_Detail->DevicePath,sizeof(wave_path));
                            } else
                            if(strstr(m_Detail->DevicePath,"kx_uart2")!=NULL)
                            {
                             //strncpy(uart2_path,m_Detail->DevicePath,sizeof(uart2_path));
                             HKEY key=SetupDiOpenDeviceInterfaceRegKey(hInfo,&data,0,KEY_ALL_ACCESS);
                             if(key!=INVALID_HANDLE_VALUE)
                             {
                                      DWORD type; type=REG_SZ;
                                      char tmp_str[256];
                                      DWORD len; len=(DWORD)sizeof(tmp_str);
                                      if(RegQueryValueEx(key,"FriendlyName",NULL,&type,(unsigned char *)tmp_str,&len)==ERROR_SUCCESS)
                                      {
                                        strncpy(uart2_name,tmp_str,sizeof(uart2_name));
                                      }
                                      RegCloseKey(key);
                             }
                            } else
                            if(strstr(m_Detail->DevicePath,"kx_uart1")!=NULL)
                            {
                             //strncpy(uart_path,m_Detail->DevicePath,sizeof(uart_path));
                             HKEY key=SetupDiOpenDeviceInterfaceRegKey(hInfo,&data,0,KEY_ALL_ACCESS);
                             if(key!=INVALID_HANDLE_VALUE)
                             {
                                      DWORD type; type=REG_SZ;
                                      char tmp_str[256];
                                      DWORD len; len=(DWORD)sizeof(tmp_str);
                                      if(RegQueryValueEx(key,"FriendlyName",NULL,&type,(unsigned char *)tmp_str,&len)==ERROR_SUCCESS)
                                      {
                                        strncpy(uart_name,tmp_str,sizeof(uart_name));
                                      }
                                      RegCloseKey(key);
                             }
                            } else
                            if(strstr(m_Detail->DevicePath,"kx_ctrl")!=NULL)
                            {
                             //strncpy(ctrl_path,m_Detail->DevicePath,sizeof(ctrl_path));
                             HKEY key=SetupDiOpenDeviceInterfaceRegKey(hInfo,&data,0,KEY_ALL_ACCESS);
                             if(key!=INVALID_HANDLE_VALUE)
                             {
                                      DWORD type; type=REG_SZ;
                                      char tmp_str[256];
                                      DWORD len; len=(DWORD)sizeof(tmp_str);
                                      if(RegQueryValueEx(key,"FriendlyName",NULL,&type,(unsigned char *)tmp_str,&len)==ERROR_SUCCESS)
                                      {
                                        strncpy(ctrl_name,tmp_str,sizeof(ctrl_name));
                                      }
                                      RegCloseKey(key);
                             }
                            } else
                            if(strstr(m_Detail->DevicePath,"kx_synth2")!=NULL)
                            {
                             //strncpy(synth2_path,m_Detail->DevicePath,sizeof(synth2_path));
                             HKEY key=SetupDiOpenDeviceInterfaceRegKey(hInfo,&data,0,KEY_ALL_ACCESS);
                             if(key!=INVALID_HANDLE_VALUE)
                             {
                                      DWORD type; type=REG_SZ;
                                      char tmp_str[256];
                                      DWORD len; len=(DWORD)sizeof(tmp_str);
                                      if(RegQueryValueEx(key,"FriendlyName",NULL,&type,(unsigned char *)tmp_str,&len)==ERROR_SUCCESS)
                                      {
                                        strncpy(synth2_name,tmp_str,sizeof(synth2_name));
                                      }
                                      RegCloseKey(key);
                             }
                            } else
                            if(strstr(m_Detail->DevicePath,"kx_synth1")!=NULL)
                            {
                             //strncpy(synth_path,m_Detail->DevicePath,sizeof(synth_path));
                             HKEY key=SetupDiOpenDeviceInterfaceRegKey(hInfo,&data,0,KEY_ALL_ACCESS);
                             if(key!=INVALID_HANDLE_VALUE)
                             {
                                      DWORD type; type=REG_SZ;
                                      char tmp_str[256];
                                      DWORD len; len=(DWORD)sizeof(tmp_str);
                                      if(RegQueryValueEx(key,"FriendlyName",NULL,&type,(unsigned char *)tmp_str,&len)==ERROR_SUCCESS)
                                      {
                                        strncpy(synth_name,tmp_str,sizeof(synth_name));
                                      }
                                      RegCloseKey(key);
                             }
                            }
                        } // if(SetupDiGetInterfaceDeviceDetail)
                        delete m_Detail;
                } // if detail -- SetupDiGetInterfaceDeviceDetail
       } // while enum interfaces

       if(wave_path[0] && topo_path[0]) // have necessary interfaces:
       {
           if(device!=0)
           { 
             device--; 
             // clean-up:
             mixer_name[0]=0; topo_path[0]=0;
             wave_name[0]=0;
             wave23_name[0]=0;
             wave45_name[0]=0;
             wave67_name[0]=0;
             waveHQ_name[0]=0;  wave_path[0]=0;
             synth_name[0]=0;
             synth2_name[0]=0;
             uart_name[0]=0;
             uart2_name[0]=0;
             ctrl_name[0]=0;

             continue; 
           }
           // right device with correct # found:
           break;
       }
    } // enum dev info
    SetupDiDestroyDeviceInfoList(hInfo);

    if(wave_path[0])
    {
        hWave = (void *)CreateFile(
        wave_path,
        GENERIC_READ,
        FILE_SHARE_READ | FILE_SHARE_WRITE,
        NULL,
        OPEN_EXISTING,
        0,
        NULL
        );
        if((HANDLE)hWave == INVALID_HANDLE_VALUE)
        {
                debug("iKX init(): error opening wave device [%x]\n",GetLastError());
                strcpy(error_name,"error opening wave device");
        return GetLastError();
        }   
    } 

    if(topo_path[0])
    {
        hTopo = (void *)CreateFile(
        topo_path,
        GENERIC_READ,
        FILE_SHARE_READ | FILE_SHARE_WRITE,
        NULL,
        OPEN_EXISTING,
        0,
        NULL
        );
        if((HANDLE)hTopo == INVALID_HANDLE_VALUE)
        {
            debug("iKX init() error opening topology device [%x]\n",GetLastError());
            strcpy(error_name,"error opening topology device");
        return GetLastError();
        }   
    } 

    if(hTopo && hWave)
    {
                char card_name[KX_MAX_STRING];
                get_string(KX_STR_CARD_NAME,card_name);

                if(!mixer_name[0])
                 sprintf(mixer_name,"kX Mixer %s 0/1",card_name);
                if(!wave_name[0])
                  sprintf(wave_name,"kX Wave %s 0/1",card_name);
                if(!wave23_name[0])
                  sprintf(wave23_name,"kX Wave %s 2/3",card_name);
                if(!wave45_name[0])
                  sprintf(wave45_name,"kX Wave %s 4/5",card_name);
                if(!wave67_name[0])
                  sprintf(wave67_name,"kX Wave %s 6/7",card_name);
                if(!waveHQ_name[0])
                  sprintf(waveHQ_name,"kX Wave %s HQ",card_name);
                if(!uart2_name[0])
                  sprintf(uart2_name,"kX Uart2 %s",card_name);
                if(!uart_name[0])
                  sprintf(uart_name,"kX Uart %s",card_name);
                if(!synth_name[0])
                  sprintf(synth_name,"kX Synth %s",card_name);
                if(!synth2_name[0])
                  sprintf(synth2_name,"kX Synth2 %s",card_name);
                if(!ctrl_name[0])
                  sprintf(ctrl_name,"kX Control %s",card_name);

        ret=init_winmm();
        if(!ignore_winmm)
        {
         if(ret)
         {
          debug("iKX init() error initializing WinMM subsystem [%x]\n",GetLastError());
          strcpy(error_name,"error initializing WinMM subsystem");
         }
        }
        else
        {
         debug("iKX init(): ignore_winmm=1; btw, result was: %d [mixer_num=%d %d %d %d]\n",ret,mixer_handler[0],mixer_handler[1],mixer_handler[2],mixer_handler[3]);
//       if(mixer_handler[0]==-1)
//        mixer_num[0]=0;
        }
    }
    else
    {
     strcpy(error_name,"kX device not found");
    }

    if(ret==0)
    {
        // set emulation
        is_10k2=0;
    if(get_dword(KX_DWORD_IS_10K2,(dword *)&is_10k2))
    {
     debug("iKX init(): incorrect driver version\n");
     strcpy(error_name,"incorrect driver version");
     ret=-100;
    }

        // set device name
        if(get_string(KX_STR_CARD_NAME,device_name))
         ret=-200;
    }

    return ret;
}
Esempio n. 8
0
BOOL getDeviceInterfaceDetail(const GUID* category, CMIDEV* pDev)
{
	DWORD                     dataSize = 0;
	BOOL                      result;
	PTSTR                     pnpStr = NULL;
	HDEVINFO                  hDevInfoWithInterface;
	SP_DEVICE_INTERFACE_DATA  DeviceInterfaceData;

	// get the PnP string
	SetupDiGetDeviceInstanceId(pDev->Info, &(pDev->InfoData), NULL, 0, &dataSize);
	if ((GetLastError() != ERROR_INSUFFICIENT_BUFFER) || (!dataSize)) {
		PrintLastError("SetupDiGetDeviceInstanceId()");
		return FALSE;
	}
	pnpStr = (PTSTR)LocalAlloc(LPTR, dataSize * sizeof(TCHAR));
	if (!pnpStr) {
		PrintLastError("LocalAlloc()");
		return FALSE;
	}
	result = SetupDiGetDeviceInstanceId(pDev->Info, &(pDev->InfoData), pnpStr, dataSize, NULL);
	if (!result) {
		PrintLastError("SetupDiGetDeviceInstanceId()");
		LocalFree(pnpStr);
		return FALSE;
	}
	hDevInfoWithInterface = SetupDiGetClassDevs(&KSCATEGORY_TOPOLOGY, pnpStr, NULL, DIGCF_DEVICEINTERFACE);
	LocalFree(pnpStr);
	if (hDevInfoWithInterface == INVALID_HANDLE_VALUE) {
		PrintLastError("SetupDiGetClassDevs()");
		return FALSE;
	}

	// get the device interface data
	DeviceInterfaceData.cbSize = sizeof(DeviceInterfaceData);
	result = SetupDiEnumDeviceInterfaces(hDevInfoWithInterface, NULL, &KSCATEGORY_TOPOLOGY, 0, &DeviceInterfaceData);
	if (!result)	{
		PrintLastError("SetupDiEnumDeviceInterfaces()");
		SetupDiDestroyDeviceInfoList(hDevInfoWithInterface);
		return FALSE;
	}

	// get the device interface detail data
	dataSize = 0;
	SetupDiGetDeviceInterfaceDetail(hDevInfoWithInterface, &DeviceInterfaceData, NULL, 0, &dataSize, NULL);
	if ((GetLastError() != ERROR_INSUFFICIENT_BUFFER) || (!dataSize)) {
		PrintLastError("SetupDiGetDeviceInterfaceDetail()");
		SetupDiDestroyDeviceInfoList(hDevInfoWithInterface);
		return FALSE;
	}
	pDev->InterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)LocalAlloc(LPTR, dataSize);
	if (!pDev->InterfaceDetailData) {
		PrintLastError("LocalAlloc()");
		SetupDiDestroyDeviceInfoList(hDevInfoWithInterface);
		return FALSE;
	}
	pDev->InterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
	result = SetupDiGetDeviceInterfaceDetail(hDevInfoWithInterface, &DeviceInterfaceData, pDev->InterfaceDetailData, dataSize, NULL, NULL);
	SetupDiDestroyDeviceInfoList(hDevInfoWithInterface);
	if (!result) {
		PrintLastError("SetupDiGetDeviceInterfaceDetail()");
		LocalFree(pDev->InterfaceDetailData);
		pDev->InterfaceDetailData = NULL;
		return FALSE;
	}

	return TRUE;

}
Esempio n. 9
0
/*static*/ std::string SuperCardProWin32::GetDevicePath ()
{
	std::string path;

	HDEVINFO hDevInfo = SetupDiGetClassDevs(&GUID_DEVCLASS_PORTS, nullptr, nullptr, DIGCF_PRESENT);
	if (hDevInfo != INVALID_HANDLE_VALUE)
	{
		for (int i = 0; ; ++i)
		{
			char szInstanceId[256];
			SP_DEVINFO_DATA DevInfoData = { sizeof(DevInfoData) };

			if (SetupDiEnumDeviceInfo(hDevInfo, i, &DevInfoData) &&
				SetupDiGetDeviceInstanceId(hDevInfo, &DevInfoData, szInstanceId, sizeof(szInstanceId), nullptr))
			{
				if (!strstr(szInstanceId, "SCP-JIM"))
					continue;

				HKEY hkey = SetupDiOpenDevRegKey(hDevInfo, &DevInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_READ);
				if (hkey != INVALID_HANDLE_VALUE)
				{
					char szPort[256];
					DWORD dwType = REG_SZ, dwSize = sizeof(szPort) / 2;
					if (SUCCEEDED(RegQueryValueEx(hkey, "PortName", nullptr, &dwType, (PBYTE)szPort, &dwSize)))
						path = std::string(R"(\\.\)") + szPort;
					RegCloseKey(hkey);
					break;
				}
			}
			else if (GetLastError() == ERROR_NO_MORE_ITEMS)
				break;
		}

		SetupDiDestroyDeviceInfoList(hDevInfo);
	}
	return path;
}

/*static*/ std::unique_ptr<SuperCardPro> SuperCardProWin32::Open ()
{
	std::string path = GetDevicePath();
	if (!path.empty())
	{
		HANDLE h = CreateFile(path.c_str(), GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, 0, nullptr);
		if (h != INVALID_HANDLE_VALUE)
		{
			DCB dcb = { sizeof(dcb) };
			if (BuildCommDCB("baud=9600 parity=N data=8 stop=1", &dcb) && SetCommState(h, &dcb))
				return std::unique_ptr<SuperCardPro>(new SuperCardProWin32(h));
		}
	}
	return std::unique_ptr<SuperCardPro>();
}

SuperCardProWin32::SuperCardProWin32 (HANDLE hdev)
	: m_hdev(hdev), m_dwError(ERROR_SUCCESS)
{
}

SuperCardProWin32::~SuperCardProWin32 ()
{
	CloseHandle(m_hdev);
}

bool SuperCardProWin32::Read (void *p, int len, int *bytes_read)
{
	DWORD dwBytesRead = 0;
	if (!ReadFile(m_hdev, p, static_cast<DWORD>(len), &dwBytesRead, nullptr))
	{
		m_dwError = GetLastError();
		return false;
	}

	*bytes_read = static_cast<int>(dwBytesRead);
	return true;
}
Esempio n. 10
0
CDeviceMgr::CDeviceMgr()
{
	TCHAR sEnumerator[] = _T("USB");
	HDEVINFO hDev;
	DWORD dwIndex;
	SP_DEVINFO_DATA devInfo;

	BYTE Buffer[300];
	DWORD BufferSize = 0;
	DWORD DataType;

	m_hDev = SetupDiGetClassDevs(NULL, sEnumerator, NULL, DIGCF_ALLCLASSES);
	if (m_hDev != INVALID_HANDLE_VALUE)
	{
		dwIndex = 0;

		memset(&devInfo, 0, sizeof(devInfo));
		devInfo.cbSize = sizeof(devInfo);

		while (SetupDiEnumDeviceInfo(m_hDev, dwIndex ++, &devInfo))
		{
			CDevice device(m_hDev, devInfo);

			if (SetupDiGetDeviceRegistryProperty(m_hDev,&devInfo,SPDRP_DEVICEDESC,
				&DataType,Buffer,sizeof(Buffer),&BufferSize))
			{
				device.SetDeviceDesc((char *) Buffer);
			}
			if (SetupDiGetDeviceRegistryProperty(m_hDev,&devInfo,SPDRP_FRIENDLYNAME,
				&DataType,Buffer,sizeof(Buffer),&BufferSize))
			{
				device.SetFriendlyName((char *) Buffer);
			}
			if (SetupDiGetDeviceRegistryProperty(m_hDev,&devInfo,SPDRP_HARDWAREID,
				&DataType,Buffer,sizeof(Buffer),&BufferSize))
			{
				device.SetHardwareID((char *) Buffer);
			}
			if (SetupDiGetDeviceInstanceId(m_hDev,&devInfo,
				(PSTR )Buffer,sizeof(Buffer),&BufferSize))
			{
				device.SetInstanceID((char *) Buffer);
			}
			if (SetupDiGetDeviceRegistryProperty(m_hDev,&devInfo,SPDRP_MFG,
				&DataType,Buffer,sizeof(Buffer),&BufferSize))
			{
				device.SetMfg((char *) Buffer);
			}
			if (SetupDiGetDeviceRegistryProperty(m_hDev,&devInfo,SPDRP_DRIVER,
				&DataType,Buffer,sizeof(Buffer),&BufferSize))
			{
				device.SetDriver((char *) Buffer);
			}
			deviceList.AddTail(device);
		}
	}

	hDev = SetupDiGetClassDevs(NULL, sEnumerator, NULL, DIGCF_ALLCLASSES | DIGCF_PRESENT);
	if (hDev != INVALID_HANDLE_VALUE)
	{
		dwIndex = 0;

		memset(&devInfo, 0, sizeof(devInfo));
		devInfo.cbSize = sizeof(devInfo);

		while (SetupDiEnumDeviceInfo(hDev, dwIndex ++, &devInfo))
		{
			if (SetupDiGetDeviceInstanceId(hDev,&devInfo,
				(PSTR )Buffer,sizeof(Buffer),&BufferSize))
			{
                CString instanceID;
				POSITION pos;

				instanceID = ((const char * )Buffer);
				pos = FindDeviceByInstanceId(instanceID);
				if (pos)
					GetFoundDevice(pos).SetPresent(TRUE);
			}
		}
	}
	SetupDiDestroyDeviceInfoList(hDev);

}
Esempio n. 11
0
HDEVINFO
GetNonPresentDevices(
    _In_  LPCWSTR   Enumerator OPTIONAL,
    _In_  LPCWSTR   HardwareID
    )
    
/*++

Routine Description:

    This routine retrieves any non-present devices matching the specified 
    criteria, and returns them in a device information set.

Arguments:

    Enumerator - Optionally, supplies the name of the Enumerator under which 
        this device may be found.  If the device may show up under more than 
        one enumerator, the routine can be called with Enumerator specified as
        NULL, in which case all device instances in the registry are examined.
        
    HardwareID - Supplies the hardware ID to be searched for.  This will be
        compared against each of the hardware IDs for all device instances in
        the system (potentially filtered based on Enumerator), present or not.

Return Value:

    If any non-present devices are discovered, this routine returns a device
    information set containing those devices.  This set must be freed via
    SetupDiDestroyDeviceInfoList by the caller.
    
    If no such devices are encountered (or if an error occurs), the return
    value is INVALID_HANDLE_VALUE.  GetLastError will indicate the cause of
    failure.

--*/

{
    HDEVINFO AllDevs, ExistingNonPresentDevices;
    DWORD i, Err;
    SP_DEVINFO_DATA DeviceInfoData;
    LPWSTR HwIdBuffer, CurId;
    DWORD HwIdBufferLen, RegDataType, RequiredSize;
    BOOL bRet;
    ULONG Status, Problem;
    TCHAR DeviceInstanceId[MAX_DEVNODE_ID_LEN];

    ExistingNonPresentDevices = INVALID_HANDLE_VALUE;
    
    AllDevs = SetupDiGetClassDevs(NULL,
                                  Enumerator,
                                  NULL,
                                  DIGCF_ALLCLASSES
                                 );
                                 
    if(AllDevs == INVALID_HANDLE_VALUE) {
        //
        // last error has already been set during the above call.
        //
        return INVALID_HANDLE_VALUE;
    }
                                  
    //
    // Iterate through each device we found, comparing its hardware ID(s)
    // against the one we were passed in.
    //
    DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
    
    HwIdBuffer = NULL;
    HwIdBufferLen = 0;
    Err = NO_ERROR;
    bRet = FALSE;
    
    i = 0;
        
    while(SetupDiEnumDeviceInfo(AllDevs, i, &DeviceInfoData)) {
        //
        // Retrieve the HardwareID property for this device info element
        //
        if(!SetupDiGetDeviceRegistryProperty(AllDevs,
                                             &DeviceInfoData,
                                             SPDRP_HARDWAREID,
                                             &RegDataType,
                                             (PBYTE)HwIdBuffer,
                                             HwIdBufferLen,
                                             &RequiredSize)) {
            //
            // If the failure was due to buffer-too-small, we can resize and
            // try again.
            //
            if(GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
            
                if(HwIdBuffer) {
                    GlobalFree(HwIdBuffer);
                }
                
                HwIdBuffer = GlobalAlloc(0, RequiredSize);
                if(HwIdBuffer) {
                    HwIdBufferLen = RequiredSize;
                    //
                    // try again
                    //
                    continue;
                } else {
                    //
                    // We failed to allocate the buffer we needed.  This is
                    // considered a critical failure that should cause us to
                    // bail.
                    //
                    Err = ERROR_NOT_ENOUGH_MEMORY;
                    break;
                }
                
            } else {
                //
                // We failed to retrieve the property for some other reason.
                // Skip this device and move on to the next.
                //
                i++;
                continue;
            }
        }

        if((RegDataType != REG_MULTI_SZ) || (RequiredSize < sizeof(TCHAR))) {
            //
            // Data is invalid--this should never happen, but we'll skip the
            // device in this case...
            //
            i++;
            continue;
        }
        
        //
        // If we get to here, then we successfully retrieved the multi-sz
        // hardware id list for this device.  Compare each of those IDs with
        // the caller-supplied one.
        //
        for(CurId = HwIdBuffer; CurId && *CurId; CurId += (lstrlen(CurId) + 1)) {
        
            if(!lstrcmpi(CurId, HardwareID)) {
                //
                // We found a match!
                //
                bRet = TRUE;
                
                //
                // If the device isn't currently present (as indicated by
                // failure to retrieve its status), then add it to the list of
                // such devices to be returned to the caller.
                //
                if(CR_SUCCESS != CM_Get_DevNode_Status(&Status,
                                                       &Problem,
                                                       (DEVNODE)DeviceInfoData.DevInst,
                                                       0))
                {
                    if(ExistingNonPresentDevices == INVALID_HANDLE_VALUE) {
                        //
                        // This is the first non-present device we've 
                        // encountered--we need to create the HDEVINFO set.
                        //
                        ExistingNonPresentDevices = 
                            SetupDiCreateDeviceInfoList(NULL, NULL);
                        
                        if(ExistingNonPresentDevices == INVALID_HANDLE_VALUE) {
                            //
                            // Failure to create this set is a critical error!
                            //
                            Err = GetLastError();
                            bRet = FALSE;
                            break;
                        }
                    }
                        
                    //
                    // We need to get the device instance's name so we can
                    // open it up into our "non-present devices" list
                    //
                    if(!SetupDiGetDeviceInstanceId(AllDevs,
                                                   &DeviceInfoData,
                                                   DeviceInstanceId,
                                                   sizeof(DeviceInstanceId) / sizeof(TCHAR),
                                                   NULL)) {
                        //
                        // Should never fail, but considered critical if it
                        // does...
                        //
                        Err = GetLastError();
                        bRet = FALSE;
                        break;
                    }

                    //
                    // Now open up the non-present device into our list.
                    //
                    if(!SetupDiOpenDeviceInfo(ExistingNonPresentDevices,
                                              DeviceInstanceId,
                                              NULL,
                                              0,
                                              NULL)) {
                        //
                        // This failure is also considered critical!
                        //                          
                        Err = GetLastError();
                        bRet = FALSE;
                    }

                    break;
                }
            }
        }

        if(Err != NO_ERROR) {
            //
            // Critical error encountered--bail!
            //
            break;
        }

        //
        // Move onto the next device instance
        //
        i++;
    }
    
    if(HwIdBuffer) {
        GlobalFree(HwIdBuffer);
    }

    //
    // We can now destroy our temporary list of all devices under consideration
    //
    SetupDiDestroyDeviceInfoList(AllDevs);

    if((Err != NO_ERROR) && 
       (ExistingNonPresentDevices != INVALID_HANDLE_VALUE)) {
        //
        // We encountered a critical error, so we need to destroy the (partial)
        // list of non-present devices we'd built.
        //
        SetupDiDestroyDeviceInfoList(ExistingNonPresentDevices);
        ExistingNonPresentDevices = INVALID_HANDLE_VALUE;
    }

    SetLastError(Err);

    return ExistingNonPresentDevices;
}
/*
 * Finds information about USB HID devices using setup class API.
 *
 * The sequence of entries in array must match with what java layer expect. If a particular USB
 * attribute is not set in descriptor or can not be obtained "---" is placed in its place.
 *
 * The array returned will be in following sequence; transport, device node, vendor ID,
 * product ID, serial, product, manufacturer, USB bus number, USB device number, location.
 *
 * For an HID interface in a USB device, Windows create a device instance for the USB interface
 * (GUID_DEVINTERFACE_HID_DEVICE) and another device instance for the HID collection (GUID_DEVINTERFACE_HID).
 * This function relate HID collection device instance to its USB interface (physical USB device) through
 * HardwareID. A hardware ID is a vendor-defined identification string that Windows uses to match a
 * device to an INF file. In most cases, a device has associated with it a list of hardware IDs.
 * (However, there are exceptions − see Identifiers for 1394 Devices). When an enumerator reports a
 * list of hardware IDs for a device, the hardware IDs should be listed in order of decreasing suitability.
 *
 * This key contains symbolic links to HID device instances :
 * HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\DeviceClasses\{4d1e55b2-f16f-11cf-88cb-001111000030}
 * 
 * This function basically collect information from USB and HID subsystems and relate them to identify a device
 * and then create a unified information to be sent to java application.
 */
jobjectArray enumerate_usb_hid_devices(JNIEnv *env, jint vendor_to_match) {

	int q = 0;
	int i = 0;
	int x = 0;
	BOOL ret = FALSE;
	LONG status = 0;
	DWORD error_code = 0;
	DWORD errorVal = 0;
	DWORD size = 0;
	DWORD charbuffer_size = 0;
	DWORD driver_name_size = 0;
	ULONG buffer_size = 0;
	ULONG devprop_buffer_size = 0;
	DEVPROPTYPE proptype;
	DWORD regproptype;

	CONFIGRET cmret = 0;
	DEVINST firstchild = 0;
	DEVINST next_sibling = 0;
	DEVINST current_sibling = 0;

	struct hiddev_inst_cont_id *instidinfo;
	struct hiddev_instance_list hiddevinst_list = { 0 };
	struct jstrarray_list list = { 0 };

	DWORD hid_member_index = 0;
	HDEVINFO hid_dev_info_set;
	SP_DEVINFO_DATA hid_dev_instance;

	DWORD usb_member_index = 0;
	HDEVINFO usb_dev_info_set;
	SP_DEVINFO_DATA usb_dev_instance;

	/* size of these buffers is hardcoded in functions using them */
	TCHAR buffer[1024];
	TCHAR devprop_buffer[1024];
	TCHAR keybuf[1024];
	TCHAR charbuffer[512];
	TCHAR tmpbuf[128];
	char cmerror[256];

	jstring usb_dev_info;
	jclass strClass = NULL;
	jobjectArray usbHidDevicesFound = NULL;

	/* allocate memory to hold information used during processing and returning information
	   to caller. */
	x = init_hiddev_instance_list(&hiddevinst_list, 25);
	if (x < 0) {
		return clean_throw_exp_usbenumeration(env, 0, 1, 0, E_CALLOCSTR, NULL, NULL, NULL, NULL);
	}

	/* ~~~~~~~~~~~~~ ENUMERATE ALL HID DEVICES ~~~~~~~~~~~~~ */

	/* get information set for all HID devices matching the GUID. It an array of 
	   structures containing information about all attached and enumerated HID devices.	*/
	hid_dev_info_set = SetupDiGetClassDevs(&GUID_DEVINTERFACE_HID, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
	if (hid_dev_info_set == INVALID_HANDLE_VALUE) {
		return clean_throw_exp_usbenumeration(env, 1, 2, HRESULT_FROM_SETUPAPI(GetLastError()), NULL, NULL, &hiddevinst_list, NULL, &hid_dev_info_set);
	}

	/* enumerate all devices in this information set starting from 0th index */
	hid_member_index = 0;
	while (1) {
		ZeroMemory(&hid_dev_instance, sizeof(hid_dev_instance));
		hid_dev_instance.cbSize = sizeof(hid_dev_instance);

		/* from information set, get device by index */
		ret = SetupDiEnumDeviceInfo(hid_dev_info_set, hid_member_index, &hid_dev_instance);
		if (ret == FALSE) {
			error_code = GetLastError();
			if (error_code == ERROR_NO_MORE_ITEMS) {
				break;
			}else {
				return clean_throw_exp_usbenumeration(env, 1, 2, HRESULT_FROM_SETUPAPI(GetLastError()), NULL, NULL, &hiddevinst_list, NULL, &hid_dev_info_set);
			}
		}

		/* for this device find its instance ID, for example; HID\VID_04D8&PID_00DF&MI_02\7&33842C3F&0&0000
		 * this is variable 'Device Instance Path' in device manager. */
		memset(buffer, '\0', 1024);
		ret = SetupDiGetDeviceInstanceId(hid_dev_info_set, &hid_dev_instance, buffer, 1024, &size);
		if (ret == FALSE) {
			return clean_throw_exp_usbenumeration(env, 1, 2, HRESULT_FROM_SETUPAPI(GetLastError()), NULL, NULL, &hiddevinst_list, NULL, &hid_dev_info_set);
		}

		/* get HardwareID of this device;
		   HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\HID\VID_04D8&PID_00DF&MI_02\7&33842C3F&0&0000\HardwareID */
		memset(keybuf, '\0', 1024);
		_stprintf_s(keybuf, 1024, TEXT("SYSTEM\\CurrentControlSet\\Enum\\%s"), buffer);

		charbuffer_size = sizeof(charbuffer);
		memset(charbuffer, '\0', 512);

		status = RegGetValue(HKEY_LOCAL_MACHINE, keybuf, TEXT("HardwareID"), RRF_RT_REG_MULTI_SZ, NULL, (PVOID)charbuffer, &charbuffer_size);
		if (status != ERROR_SUCCESS) {
			return clean_throw_exp_usbenumeration(env, 1, 2, GetLastError(), NULL, NULL, &hiddevinst_list, NULL, &hid_dev_info_set);
		}

		/* save device instance and hardware id (including terminating null character) in the
		   list for later comparision */
		instidinfo = NULL;
		instidinfo = (struct hiddev_inst_cont_id *) malloc(sizeof(struct hiddev_inst_cont_id));
		if (instidinfo == NULL) {
			return clean_throw_exp_usbenumeration(env, 1, 1, 0, E_MALLOCSTR, NULL, &hiddevinst_list, NULL, &hid_dev_info_set);
		}
		_tcscpy_s(instidinfo->instance, 512, buffer);
		_tcscpy_s(instidinfo->hwid, 512, charbuffer);

		insert_hiddev_instance_list(&hiddevinst_list, instidinfo);

		/* increment to get the next HID device instance */
		hid_member_index++;
	}

	/* release HID info set as it is no longer needed */
	SetupDiDestroyDeviceInfoList(hid_dev_info_set);

	/* allocate memory to hold information used during processing and returning information
	to caller. */
	x = init_jstrarraylist(&list, 100);
	if (x < 0) {
		return clean_throw_exp_usbenumeration(env, 2, 1, 0, E_CALLOCSTR, NULL, &hiddevinst_list, NULL, NULL);
	}

	/* From here onwards, enumerate over all USB interfaces looking for HID interface and try to
	   associate with its device instance and then create information that will be passed to
	   application. */

	/* ~~~~~~~~~~~~~ ENUMERATE ALL USB DEVICES ~~~~~~~~~~~~~ */

	/* get information set for all usb devices matching the GUID */
	usb_dev_info_set = SetupDiGetClassDevs(&GUID_DEVINTERFACE_USB_DEVICE, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
	if (usb_dev_info_set == INVALID_HANDLE_VALUE) {
		return clean_throw_exp_usbenumeration(env, 3, 2, HRESULT_FROM_SETUPAPI(GetLastError()), NULL, &list, &hiddevinst_list, &usb_dev_info_set, NULL);
	}

	/* enumerate all devices in this information set */
	usb_member_index = 0;
	while (1) {
		ZeroMemory(&usb_dev_instance, sizeof(usb_dev_instance));
		usb_dev_instance.cbSize = sizeof(usb_dev_instance);

		/* from information set, get device by index */
		ret = SetupDiEnumDeviceInfo(usb_dev_info_set, usb_member_index, &usb_dev_instance);
		if (ret == FALSE) {
			error_code = GetLastError();
			if (error_code == ERROR_NO_MORE_ITEMS) {
				break;
			}else {
				return clean_throw_exp_usbenumeration(env, 3, 2, HRESULT_FROM_SETUPAPI(GetLastError()), NULL, &list, &hiddevinst_list, &usb_dev_info_set, NULL);
			}
		}

		/* for this device find its instance ID (USB\VID_04D8&PID_00DF\000098037)
		 * this is the variable 'Device Instance Path' in device manager. */
		memset(buffer, '\0', sizeof(buffer));
		ret = SetupDiGetDeviceInstanceId(usb_dev_info_set, &usb_dev_instance, buffer, 1024, &size);
		if (ret == FALSE) {
			return clean_throw_exp_usbenumeration(env, 3, 2, HRESULT_FROM_SETUPAPI(GetLastError()), NULL, &list, &hiddevinst_list, &usb_dev_info_set, NULL);
		}

		/* fetch and examine USB interface */
		cmret = CM_Get_Child(&firstchild, usb_dev_instance.DevInst, 0);
		if (cmret != CR_SUCCESS) {
			if (cmret == CR_NO_SUCH_DEVNODE) {
				/* this device does not have any child, so check if this is a HID class device or not */
				memset(devprop_buffer, '\0', 1024);
				ret = SetupDiGetDeviceRegistryProperty(usb_dev_info_set, &usb_dev_instance, SPDRP_CLASSGUID, &regproptype, (BYTE *)devprop_buffer, sizeof(devprop_buffer), &size);
				if (ret == FALSE) {
					return clean_throw_exp_usbenumeration(env, 3, 2, HRESULT_FROM_SETUPAPI(GetLastError()), NULL, &list, &hiddevinst_list, &usb_dev_info_set, NULL);
				}

				/* check if this is a HID device interface, if it is not than loop back to examine next USB device */
				ret = _tcsicmp(devprop_buffer, TEXT("{745A17A0-74D3-11D0-B6FE-00A0C90F57DA}"));
				if (ret != 0) {
					usb_member_index++;
					continue;
				}

				/* reaching here means that the device is a HID device, so create all the information
				that will be passed to java layer. */

				/* get the HardwareID of this USB HID interface. HardwareID is multi-sz, however
				   we use only 1st string from multi-string HardwareID for our matching.
				   HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\USB\VID_04D8&PID_00DF&MI_02\7&33842C3F&0&0000\HardwareID 
				   The buffer contains device instance path of USB device */
				memset(keybuf, '\0', 1024);
				_stprintf_s(keybuf, 1024, TEXT("SYSTEM\\CurrentControlSet\\Enum\\%s"), buffer);

				charbuffer_size = sizeof(charbuffer);
				memset(charbuffer, '\0', 512);

				/* USB\VID_04D8&PID_00DF&REV_0101 and USB\VID_04D8&PID_00DF and so on */
				status = RegGetValue(HKEY_LOCAL_MACHINE, keybuf, TEXT("HardwareID"), RRF_RT_REG_MULTI_SZ, NULL, (PVOID)charbuffer, &charbuffer_size);
				if (status != ERROR_SUCCESS) {
					return clean_throw_exp_usbenumeration(env, 3, 2, GetLastError(), NULL, &list, &hiddevinst_list, &usb_dev_info_set, NULL);
				}

				/* charbuffer now contains hardwareID, cook it a little bit to enable suitable matching */
				if ((charbuffer[0] == 'U') && (charbuffer[1] == 'S') && (charbuffer[2] == 'B')) {
					charbuffer[0] = 'H';
					charbuffer[1] = 'I';
					charbuffer[2] = 'D';
				}

				for (q = 0; q < hiddevinst_list.index; q++) {

					/* check association between HID collection device instance and USB device instance */
					ret = _tcsicmp(charbuffer, hiddevinst_list.base[q]->hwid);
					if (ret != 0) {
						continue;
					}

					/* reaching here means this HID collection belongs to this USB HID device, so glean information
					   to be passed to java layer. */

					/* TRANSPORT */
					usb_dev_info = (*env)->NewStringUTF(env, "USB");
					if ((usb_dev_info == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) {
						return clean_throw_exp_usbenumeration(env, 3, 1, 0, E_NEWSTRUTFSTR, &list, &hiddevinst_list, &usb_dev_info_set, NULL);
					}
					insert_jstrarraylist(&list, usb_dev_info);

					/* DEVICE NODE */
					usb_dev_info = (*env)->NewString(env, hiddevinst_list.base[q]->instance, (jsize)_tcslen(hiddevinst_list.base[q]->instance));
					if ((usb_dev_info == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) {
						return clean_throw_exp_usbenumeration(env, 3, 1, 0, E_NEWSTRUTFSTR, &list, &hiddevinst_list, &usb_dev_info_set, NULL);
					}
					insert_jstrarraylist(&list, usb_dev_info);

					/* USB-IF VENDOR ID
					   (extracted from USB device instance for example: USB\VID_04D8&PID_00DF\000098037) */
					x = 0;
					while (buffer[x] != '\0') {
						if ((buffer[x] == 'V') && (buffer[x + 1] == 'I') && (buffer[x + 2] == 'D') && (buffer[x + 3] == '_')) {
							break;
						}
						x++;
					}
					x = x + 4;
					i = 0;
					while (buffer[x] != '&') {
						tmpbuf[i] = buffer[x];
						i++;
						x++;
					}
					tmpbuf[i] = '\0'; /* indicate end of string */
					usb_dev_info = (*env)->NewString(env, tmpbuf, (jsize)_tcslen(tmpbuf));
					if ((usb_dev_info == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) {
						return clean_throw_exp_usbenumeration(env, 3, 1, 0, E_NEWSTRUTFSTR, &list, &hiddevinst_list, &usb_dev_info_set, NULL);
					}
					insert_jstrarraylist(&list, usb_dev_info);

					/* USB product ID
					   (extracted from USB device instance for example: USB\VID_04D8&PID_00DF\000098037) */
					x = 6;
					while (buffer[x] != '\0') {
						if ((buffer[x] == 'P') && (buffer[x + 1] == 'I') && (buffer[x + 2] == 'D') && (buffer[x + 3] == '_')) {
							break;
						}
						x++;
					}
					x = x + 4;
					i = 0;
					while (buffer[x] != '\\') {
						tmpbuf[i] = buffer[x];
						i++;
						x++;
					}
					tmpbuf[i] = '\0'; /* indicate end of string */
					usb_dev_info = (*env)->NewString(env, tmpbuf, (jsize)_tcslen(tmpbuf));
					if ((usb_dev_info == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) {
						return clean_throw_exp_usbenumeration(env, 3, 1, 0, E_NEWSTRUTFSTR, &list, &hiddevinst_list, &usb_dev_info_set, NULL);
					}
					insert_jstrarraylist(&list, usb_dev_info);

					/* SERIAL NUMBER */
					x++;
					i = 0;
					while (buffer[x] != '\0') {
						tmpbuf[i] = buffer[x];
						i++;
						x++;
					}
					tmpbuf[i] = '\0';
					usb_dev_info = (*env)->NewString(env, tmpbuf, (jsize)_tcslen(tmpbuf));
					if ((usb_dev_info == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) {
						return clean_throw_exp_usbenumeration(env, 3, 1, 0, E_NEWSTRUTFSTR, &list, &hiddevinst_list, &usb_dev_info_set, NULL);
					}
					insert_jstrarraylist(&list, usb_dev_info);

					/* PRODUCT
					   (iProduct field of USB device descriptor) */
					memset(devprop_buffer, '\0', sizeof(devprop_buffer));
					ret = SetupDiGetDeviceProperty(usb_dev_info_set, &usb_dev_instance, &DEVPKEY_Device_BusReportedDeviceDesc, &proptype, (BYTE *)devprop_buffer, sizeof(devprop_buffer), &size, 0);
					if (ret == FALSE) {
						/* fallback to SPDRP_DEVICEDESC if DEVPKEY_Device_BusReportedDeviceDesc fails */
						ret = SetupDiGetDeviceRegistryProperty(usb_dev_info_set, &usb_dev_instance, SPDRP_DEVICEDESC, &regproptype, (BYTE *)devprop_buffer, sizeof(devprop_buffer), &size);
						if (ret == FALSE) {
							/* if second attempt fails, throw error, we need to investigate drivers/firmware etc */
							return clean_throw_exp_usbenumeration(env, 3, 2, HRESULT_FROM_SETUPAPI(GetLastError()), NULL, &list, &hiddevinst_list, &usb_dev_info_set, NULL);
						}
					}
					usb_dev_info = (*env)->NewString(env, devprop_buffer, (jsize)_tcslen(devprop_buffer));
					insert_jstrarraylist(&list, usb_dev_info);

					/* MANUFACTURER */
					memset(devprop_buffer, '\0', sizeof(devprop_buffer));
					ret = SetupDiGetDeviceProperty(usb_dev_info_set, &usb_dev_instance, &DEVPKEY_Device_Manufacturer, &proptype, (BYTE *)devprop_buffer, sizeof(devprop_buffer), &size, 0);
					if (ret == FALSE) {
						return clean_throw_exp_usbenumeration(env, 3, 2, HRESULT_FROM_SETUPAPI(GetLastError()), NULL, &list, &hiddevinst_list, &usb_dev_info_set, NULL);
					}
					usb_dev_info = (*env)->NewString(env, devprop_buffer, (jsize)_tcslen(devprop_buffer));
					insert_jstrarraylist(&list, usb_dev_info);

					/* LOCATION
					   (Location paths + Location info, get separately and then create a single string) */

					// PCIROOT(0)#PCI(1400)#USBROOT(0)#USB(3)
					memset(devprop_buffer, '\0', sizeof(devprop_buffer));
					ret = SetupDiGetDeviceRegistryProperty(usb_dev_info_set, &usb_dev_instance, SPDRP_LOCATION_PATHS, &regproptype, (BYTE *)devprop_buffer, sizeof(devprop_buffer), &size);
					if (ret == FALSE) {
						return clean_throw_exp_usbenumeration(env, 3, 2, HRESULT_FROM_SETUPAPI(GetLastError()), NULL, &list, &hiddevinst_list, &usb_dev_info_set, NULL);
					}
					// Port_#0003.Hub_#0001
					memset(charbuffer, '\0', sizeof(charbuffer));
					ret = SetupDiGetDeviceRegistryProperty(usb_dev_info_set, &usb_dev_instance, SPDRP_LOCATION_INFORMATION, &regproptype, (BYTE *)charbuffer, sizeof(charbuffer), &size);
					if (ret == FALSE) {
						return clean_throw_exp_usbenumeration(env, 3, 2, HRESULT_FROM_SETUPAPI(GetLastError()), NULL, &list, &hiddevinst_list, &usb_dev_info_set, NULL);
					}

					i = 0;
					x = (int)_tcslen(devprop_buffer);
					devprop_buffer[x] = '-';
					x++;
					for (i = 0; i < (int)_tcslen(charbuffer); i++) {
						devprop_buffer[x] = charbuffer[i];
						x++;
					}
					devprop_buffer[x] = '\0';

					usb_dev_info = (*env)->NewString(env, devprop_buffer, (jsize)_tcslen(devprop_buffer));
					insert_jstrarraylist(&list, usb_dev_info);
				}

				/* loop back to get next USB device */
				usb_member_index++;
				continue;
			}else {
				/* error happend when getting child of USB device */
				_snprintf_s(cmerror, 256, 256, "CM_Get_Child failed with CR_xxxx error code : 0x%X\0", cmret);
				return clean_throw_exp_usbenumeration(env, 3, 1, 0, cmerror, &list, &hiddevinst_list, &usb_dev_info_set, NULL);
			}
		}

		/* reaching here means that this USB device has at-least one child device node, examine first child now */
		devprop_buffer_size = sizeof(devprop_buffer);
		memset(devprop_buffer, '\0', 1024);

		cmret = CM_Get_DevNode_Registry_Property(firstchild, CM_DRP_CLASSGUID, &proptype, (PVOID)devprop_buffer, &devprop_buffer_size, 0);
		if (cmret != CR_SUCCESS) {
			_snprintf_s(cmerror, 256, 256, "CM_Get_DevNode_Registry_Property failed with CR_xxxx error code : 0x%X\0", cmret);
			return clean_throw_exp_usbenumeration(env, 3, 1, 0, cmerror, &list, &hiddevinst_list, &usb_dev_info_set, NULL);
		}

		/* check if first child is a HID device interface */
		ret = _tcsicmp(devprop_buffer, TEXT("{745A17A0-74D3-11D0-B6FE-00A0C90F57DA}"));
		if (ret == 0) {
			/* reaching here means that this sibling (interface) is a HID type, get its device instance path */
			memset(devprop_buffer, '\0', 1024);
			cmret = CM_Get_Device_ID(firstchild, devprop_buffer, 1024, 0);
			if (cmret != CR_SUCCESS) {
				_snprintf_s(cmerror, 256, 256, "CM_Get_Device_ID failed with CR_xxxx error code : 0x%X\0", cmret);
				return clean_throw_exp_usbenumeration(env, 3, 1, 0, cmerror, &list, &hiddevinst_list, &usb_dev_info_set, NULL);
			}

			/* get the HardwareID of this USB HID interface. HardwareID is multi-sz, however
			   we use only 1st string from multi-string HardwareID for our matching.
			   HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\USB\VID_04D8&PID_00DF&MI_02\7&33842C3F&0&0000\HardwareID */
			memset(charbuffer, '\0', 512);
			buffer_size = sizeof(charbuffer);
			cmret = CM_Get_DevNode_Registry_Property(firstchild, CM_DRP_HARDWAREID, NULL, (PVOID)charbuffer, &buffer_size, 0);
			if (cmret != CR_SUCCESS) {
				_snprintf_s(cmerror, 256, 256, "CM_Get_Device_ID failed with CR_xxxx error code : 0x%X\0", cmret);
				return clean_throw_exp_usbenumeration(env, 3, 1, 0, cmerror, &list, &hiddevinst_list, &usb_dev_info_set, NULL);
			}

			if ((charbuffer[0] == 'U') && (charbuffer[1] == 'S') && (charbuffer[2] == 'B')) {
				charbuffer[0] = 'H';
				charbuffer[1] = 'I';
				charbuffer[2] = 'D';
			}

			for (q = 0; q < hiddevinst_list.index; q++) {

				/* check association between HID collection device instance and USB interface device instance */
				ret = _tcsncicmp(charbuffer, hiddevinst_list.base[q]->hwid, 512);
				if (ret != 0) {
					continue;
				}

				/* reaching here means this HID collection belongs to this USB HID interface, so glean information
				   to be passed to java layer. */

				/* TRANSPORT */
				usb_dev_info = (*env)->NewStringUTF(env, "USB");
				if ((usb_dev_info == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) {
					return clean_throw_exp_usbenumeration(env, 3, 1, 0, E_NEWSTRUTFSTR, &list, &hiddevinst_list, &usb_dev_info_set, NULL);
				}
				insert_jstrarraylist(&list, usb_dev_info);

				/* DEVICE NODE */
				usb_dev_info = (*env)->NewString(env, hiddevinst_list.base[q]->instance, (jsize)_tcslen(hiddevinst_list.base[q]->instance));
				if ((usb_dev_info == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) {
					return clean_throw_exp_usbenumeration(env, 3, 1, 0, E_NEWSTRUTFSTR, &list, &hiddevinst_list, &usb_dev_info_set, NULL);
				}
				insert_jstrarraylist(&list, usb_dev_info);

				/* USB-IF VENDOR ID
				   (extracted from USB device instance for example: USB\VID_04D8&PID_00DF\000098037) */
				x = 0;
				while (buffer[x] != '\0') {
					if ((buffer[x] == 'V') && (buffer[x + 1] == 'I') && (buffer[x + 2] == 'D') && (buffer[x + 3] == '_')) {
						break;
					}
					x++;
				}
				x = x + 4;
				i = 0;
				while (buffer[x] != '&') {
					tmpbuf[i] = buffer[x];
					i++;
					x++;
				}
				tmpbuf[i] = '\0'; /* indicate end of string */
				usb_dev_info = (*env)->NewString(env, tmpbuf, (jsize)_tcslen(tmpbuf));
				if ((usb_dev_info == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) {
					return clean_throw_exp_usbenumeration(env, 3, 1, 0, E_NEWSTRUTFSTR, &list, &hiddevinst_list, &usb_dev_info_set, NULL);
				}
				insert_jstrarraylist(&list, usb_dev_info);

				/* USB product ID
				   (extracted from USB device instance for example: USB\VID_04D8&PID_00DF\000098037) */
				x = 6;
				while (buffer[x] != '\0') {
					if ((buffer[x] == 'P') && (buffer[x + 1] == 'I') && (buffer[x + 2] == 'D') && (buffer[x + 3] == '_')) {
						break;
					}
					x++;
				}
				x = x + 4;
				i = 0;
				while (buffer[x] != '\\') {
					tmpbuf[i] = buffer[x];
					i++;
					x++;
				}
				tmpbuf[i] = '\0'; /* indicate end of string */
				usb_dev_info = (*env)->NewString(env, tmpbuf, (jsize)_tcslen(tmpbuf));
				if ((usb_dev_info == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) {
					return clean_throw_exp_usbenumeration(env, 3, 1, 0, E_NEWSTRUTFSTR, &list, &hiddevinst_list, &usb_dev_info_set, NULL);
				}
				insert_jstrarraylist(&list, usb_dev_info);

				/* SERIAL NUMBER */
				x++;
				i = 0;
				while (buffer[x] != '\0') {
					tmpbuf[i] = buffer[x];
					i++;
					x++;
				}
				tmpbuf[i] = '\0';
				usb_dev_info = (*env)->NewString(env, tmpbuf, (jsize)_tcslen(tmpbuf));
				if ((usb_dev_info == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) {
					return clean_throw_exp_usbenumeration(env, 3, 1, 0, E_NEWSTRUTFSTR, &list, &hiddevinst_list, &usb_dev_info_set, NULL);
				}
				insert_jstrarraylist(&list, usb_dev_info);

				/* PRODUCT
				   (iProduct field of USB device descriptor) */
				memset(devprop_buffer, '\0', sizeof(devprop_buffer));
				ret = SetupDiGetDeviceProperty(usb_dev_info_set, &usb_dev_instance, &DEVPKEY_Device_BusReportedDeviceDesc, &proptype, (BYTE *)devprop_buffer, sizeof(devprop_buffer), &size, 0);
				if (ret == FALSE) {
					/* fallback to SPDRP_DEVICEDESC if DEVPKEY_Device_BusReportedDeviceDesc fails */
					ret = SetupDiGetDeviceRegistryProperty(usb_dev_info_set, &usb_dev_instance, SPDRP_DEVICEDESC, &regproptype, (BYTE *)devprop_buffer, sizeof(devprop_buffer), &size);
					if (ret == FALSE) {
						/* if second attempt fails, throw error, we need to investigate drivers/firmware etc */
						return clean_throw_exp_usbenumeration(env, 3, 2, HRESULT_FROM_SETUPAPI(GetLastError()), NULL, &list, &hiddevinst_list, &usb_dev_info_set, NULL);
					}
				}
				usb_dev_info = (*env)->NewString(env, devprop_buffer, (jsize)_tcslen(devprop_buffer));
				insert_jstrarraylist(&list, usb_dev_info);

				/* MANUFACTURER */
				memset(devprop_buffer, '\0', sizeof(devprop_buffer));
				ret = SetupDiGetDeviceProperty(usb_dev_info_set, &usb_dev_instance, &DEVPKEY_Device_Manufacturer, &proptype, (BYTE *)devprop_buffer, sizeof(devprop_buffer), &size, 0);
				if (ret == FALSE) {
					return clean_throw_exp_usbenumeration(env, 3, 2, HRESULT_FROM_SETUPAPI(GetLastError()), NULL, &list, &hiddevinst_list, &usb_dev_info_set, NULL);
				}
				usb_dev_info = (*env)->NewString(env, devprop_buffer, (jsize)_tcslen(devprop_buffer));
				insert_jstrarraylist(&list, usb_dev_info);

				/* LOCATION
				  (Location paths + Location info, get separately and then create a single string) */

				// PCIROOT(0)#PCI(1400)#USBROOT(0)#USB(3)
				memset(devprop_buffer, '\0', sizeof(devprop_buffer));
				ret = SetupDiGetDeviceRegistryProperty(usb_dev_info_set, &usb_dev_instance, SPDRP_LOCATION_PATHS, &regproptype, (BYTE *)devprop_buffer, sizeof(devprop_buffer), &size);
				if (ret == FALSE) {
					return clean_throw_exp_usbenumeration(env, 3, 2, HRESULT_FROM_SETUPAPI(GetLastError()), NULL, &list, &hiddevinst_list, &usb_dev_info_set, NULL);
				}
				// Port_#0003.Hub_#0001
				memset(charbuffer, '\0', sizeof(charbuffer));
				ret = SetupDiGetDeviceRegistryProperty(usb_dev_info_set, &usb_dev_instance, SPDRP_LOCATION_INFORMATION, &regproptype, (BYTE *)charbuffer, sizeof(charbuffer), &size);
				if (ret == FALSE) {
					return clean_throw_exp_usbenumeration(env, 3, 2, HRESULT_FROM_SETUPAPI(GetLastError()), NULL, &list, &hiddevinst_list, &usb_dev_info_set, NULL);
				}

				i = 0;
				x = (int)_tcslen(devprop_buffer);
				devprop_buffer[x] = '-';
				x++;
				for (i = 0; i < (int)_tcslen(charbuffer); i++) {
					devprop_buffer[x] = charbuffer[i];
					x++;
				}
				devprop_buffer[x] = '\0';

				usb_dev_info = (*env)->NewString(env, devprop_buffer, (jsize)_tcslen(devprop_buffer));
				insert_jstrarraylist(&list, usb_dev_info);
			}
		}

		/* check if this usb device has more than one interface. if it has enumerate over each
		   one by one and collecting information for every HID interface found and sending it to 
		   java layer. */
		current_sibling = firstchild;
		while (1) {
			cmret = CM_Get_Sibling(&next_sibling, current_sibling, 0);
			if (cmret != CR_SUCCESS) {
				if (cmret == CR_NO_SUCH_DEVNODE) {
					/* done iterating over all interfaces, move to next examine next USB device */
					break;
				}else {
					_snprintf_s(cmerror, 256, 256, "CM_Get_Sibling failed with CR_xxxx error code : 0x%X\0", cmret);
					return clean_throw_exp_usbenumeration(env, 3, 1, 0, cmerror, &list, &hiddevinst_list, &usb_dev_info_set, NULL);
				}
			}

			/* reaching here means USB device has more than 1 interfaces, get class of this interface (sibling) */
			devprop_buffer_size = sizeof(devprop_buffer);
			memset(devprop_buffer, '\0', sizeof(devprop_buffer));
			cmret = CM_Get_DevNode_Registry_Property(next_sibling, CM_DRP_CLASSGUID, &proptype, (VOID *)devprop_buffer, &devprop_buffer_size, 0);
			if (cmret != CR_SUCCESS) {
				_snprintf_s(cmerror, 256, 256, "CM_Get_DevNode_Registry_Property failed with CR_xxxx error code : 0x%X\0", cmret);
				return clean_throw_exp_usbenumeration(env, 3, 1, 0, cmerror, &list, &hiddevinst_list, &usb_dev_info_set, NULL);
			}

			/* check if this is a HID device interface */
			ret = _tcsicmp(devprop_buffer, TEXT("{745A17A0-74D3-11D0-B6FE-00A0C90F57DA}"));
			if (ret != 0) {
				/* this is not HID interface, move to check next interface */
				current_sibling = next_sibling;
				continue;
			}

			/* reaching here means that this sibling (interface) is a HID type, get its device instance path */
			memset(devprop_buffer, '\0', 1024);
			cmret = CM_Get_Device_ID(next_sibling, devprop_buffer, 1024, 0);
			if (cmret != CR_SUCCESS) {
				_snprintf_s(cmerror, 256, 256, "CM_Get_Device_ID failed with CR_xxxx error code : 0x%X\0", cmret);
				return clean_throw_exp_usbenumeration(env, 3, 1, 0, cmerror, &list, &hiddevinst_list, &usb_dev_info_set, NULL);
			}

			/* get the HardwareID of this USB HID interface. HardwareID is multi-sz, however
			   we use only 1st string from multi-string HardwareID for our matching.
			   HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\USB\VID_04D8&PID_00DF&MI_02\7&33842C3F&0&0000\HardwareID */
			memset(charbuffer, '\0', 512);
			buffer_size = sizeof(charbuffer);

			cmret = CM_Get_DevNode_Registry_Property(next_sibling, CM_DRP_HARDWAREID, NULL, (PVOID)charbuffer, &buffer_size, 0);
			if (cmret != CR_SUCCESS) {
				_snprintf_s(cmerror, 256, 256, "CM_Get_Device_ID failed with CR_xxxx error code : 0x%X\0", cmret);
				return clean_throw_exp_usbenumeration(env, 3, 1, 0, cmerror, &list, &hiddevinst_list, &usb_dev_info_set, NULL);
			}

			if ((charbuffer[0] == 'U') && (charbuffer[1] == 'S') && (charbuffer[2] == 'B')) {
				charbuffer[0] = 'H';
				charbuffer[1] = 'I';
				charbuffer[2] = 'D';
			}

			for (q = 0; q < hiddevinst_list.index; q++) {

				/* check association between HID collection device instance and USB interface device instance */
				ret = _tcsncicmp(charbuffer, hiddevinst_list.base[q]->hwid, 512);
				if (ret != 0) {
					continue;
				}

				/* reaching here means this HID collection belongs to this USB HID interface, so glean information
				   to be passed to java layer. */

				/* TRANSPORT */
				usb_dev_info = (*env)->NewStringUTF(env, "USB");
				if ((usb_dev_info == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) {
					return clean_throw_exp_usbenumeration(env, 3, 1, 0, E_NEWSTRUTFSTR, &list, &hiddevinst_list, &usb_dev_info_set, NULL);
				}
				insert_jstrarraylist(&list, usb_dev_info);

				/* DEVICE NODE */
				usb_dev_info = (*env)->NewString(env, hiddevinst_list.base[q]->instance, (jsize)_tcslen(hiddevinst_list.base[q]->instance));
				if ((usb_dev_info == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) {
					return clean_throw_exp_usbenumeration(env, 3, 1, 0, E_NEWSTRUTFSTR, &list, &hiddevinst_list, &usb_dev_info_set, NULL);
				}
				insert_jstrarraylist(&list, usb_dev_info);

				/* USB-IF VENDOR ID
				   (extracted from USB device instance for example: USB\VID_04D8&PID_00DF\000098037) */
				x = 0;
				while (buffer[x] != '\0') {
					if ((buffer[x] == 'V') && (buffer[x + 1] == 'I') && (buffer[x + 2] == 'D') && (buffer[x + 3] == '_')) {
						break;
					}
					x++;
				}
				x = x + 4;
				i = 0;
				while (buffer[x] != '&') {
					tmpbuf[i] = buffer[x];
					i++;
					x++;
				}
				tmpbuf[i] = '\0'; /* indicate end of string */
				usb_dev_info = (*env)->NewString(env, tmpbuf, (jsize)_tcslen(tmpbuf));
				if ((usb_dev_info == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) {
					return clean_throw_exp_usbenumeration(env, 3, 1, 0, E_NEWSTRUTFSTR, &list, &hiddevinst_list, &usb_dev_info_set, NULL);
				}
				insert_jstrarraylist(&list, usb_dev_info);

				/* USB product ID
				   (extracted from USB device instance for example: USB\VID_04D8&PID_00DF\000098037) */
				x = 6;
				while (buffer[x] != '\0') {
					if ((buffer[x] == 'P') && (buffer[x + 1] == 'I') && (buffer[x + 2] == 'D') && (buffer[x + 3] == '_')) {
						break;
					}
					x++;
				}
				x = x + 4;
				i = 0;
				while (buffer[x] != '\\') {
					tmpbuf[i] = buffer[x];
					i++;
					x++;
				}
				tmpbuf[i] = '\0'; /* indicate end of string */
				usb_dev_info = (*env)->NewString(env, tmpbuf, (jsize)_tcslen(tmpbuf));
				if ((usb_dev_info == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) {
					return clean_throw_exp_usbenumeration(env, 3, 1, 0, E_NEWSTRUTFSTR, &list, &hiddevinst_list, &usb_dev_info_set, NULL);
				}
				insert_jstrarraylist(&list, usb_dev_info);

				/* SERIAL NUMBER */
				x++;
				i = 0;
				while (buffer[x] != '\0') {
					tmpbuf[i] = buffer[x];
					i++;
					x++;
				}
				tmpbuf[i] = '\0';
				usb_dev_info = (*env)->NewString(env, tmpbuf, (jsize)_tcslen(tmpbuf));
				if ((usb_dev_info == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) {
					return clean_throw_exp_usbenumeration(env, 3, 1, 0, E_NEWSTRUTFSTR, &list, &hiddevinst_list, &usb_dev_info_set, NULL);
				}
				insert_jstrarraylist(&list, usb_dev_info);

				/* PRODUCT
				   (iProduct field of USB device descriptor) */
				memset(devprop_buffer, '\0', sizeof(devprop_buffer));
				ret = SetupDiGetDeviceProperty(usb_dev_info_set, &usb_dev_instance, &DEVPKEY_Device_BusReportedDeviceDesc, &proptype, (BYTE *)devprop_buffer, sizeof(devprop_buffer), &size, 0);
				if (ret == FALSE) {
					/* fallback to SPDRP_DEVICEDESC if DEVPKEY_Device_BusReportedDeviceDesc fails */
					ret = SetupDiGetDeviceRegistryProperty(usb_dev_info_set, &usb_dev_instance, SPDRP_DEVICEDESC, &regproptype, (BYTE *)devprop_buffer, sizeof(devprop_buffer), &size);
					if (ret == FALSE) {
						/* if second attempt fails, throw error, we need to investigate drivers/firmware etc */
						return clean_throw_exp_usbenumeration(env, 3, 2, HRESULT_FROM_SETUPAPI(GetLastError()), NULL, &list, &hiddevinst_list, &usb_dev_info_set, NULL);
					}
					usb_dev_info = (*env)->NewString(env, devprop_buffer, (jsize)_tcslen(devprop_buffer));
					insert_jstrarraylist(&list, usb_dev_info);
				}else {
					usb_dev_info = (*env)->NewString(env, devprop_buffer, (jsize)_tcslen(devprop_buffer));
					insert_jstrarraylist(&list, usb_dev_info);
				}

				/* MANUFACTURER */
				memset(devprop_buffer, '\0', sizeof(devprop_buffer));
				ret = SetupDiGetDeviceProperty(usb_dev_info_set, &usb_dev_instance, &DEVPKEY_Device_Manufacturer, &proptype, (BYTE *)devprop_buffer, sizeof(devprop_buffer), &size, 0);
				if (ret == FALSE) {
					return clean_throw_exp_usbenumeration(env, 3, 2, HRESULT_FROM_SETUPAPI(GetLastError()), NULL, &list, &hiddevinst_list, &usb_dev_info_set, NULL);
				}
				usb_dev_info = (*env)->NewString(env, devprop_buffer, (jsize)_tcslen(devprop_buffer));
				insert_jstrarraylist(&list, usb_dev_info);

				/* LOCATION
				   (Location paths + Location info, get separately and then create a single string) */

				// PCIROOT(0)#PCI(1400)#USBROOT(0)#USB(3)
				memset(devprop_buffer, '\0', sizeof(devprop_buffer));
				ret = SetupDiGetDeviceRegistryProperty(usb_dev_info_set, &usb_dev_instance, SPDRP_LOCATION_PATHS, &regproptype, (BYTE *)devprop_buffer, sizeof(devprop_buffer), &size);
				if (ret == FALSE) {
					return clean_throw_exp_usbenumeration(env, 3, 2, HRESULT_FROM_SETUPAPI(GetLastError()), NULL, &list, &hiddevinst_list, &usb_dev_info_set, NULL);
				}
				// Port_#0003.Hub_#0001
				memset(charbuffer, '\0', sizeof(charbuffer));
				ret = SetupDiGetDeviceRegistryProperty(usb_dev_info_set, &usb_dev_instance, SPDRP_LOCATION_INFORMATION, &regproptype, (BYTE *)charbuffer, sizeof(charbuffer), &size);
				if (ret == FALSE) {
					return clean_throw_exp_usbenumeration(env, 3, 2, HRESULT_FROM_SETUPAPI(GetLastError()), NULL, &list, &hiddevinst_list, &usb_dev_info_set, NULL);
				}

				i = 0;
				x = (int)_tcslen(devprop_buffer);
				devprop_buffer[x] = '-';
				x++;
				for (i = 0; i < (int)_tcslen(charbuffer); i++) {
					devprop_buffer[x] = charbuffer[i];
					x++;
				}
				devprop_buffer[x] = '\0';

				usb_dev_info = (*env)->NewString(env, devprop_buffer, (jsize)_tcslen(devprop_buffer));
				insert_jstrarraylist(&list, usb_dev_info);
			}

			/* set this sibling as base sibling for fetching next sibling, loop over to get and check next
			   interface (sibling) */
			current_sibling = next_sibling;
		}

		/* increment to get and examine the next usb device for HID class */
		usb_member_index++;
	}

	strClass = (*env)->FindClass(env, JAVALSTRING);
	if ((strClass == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) {
		return clean_throw_exp_usbenumeration(env, 3, 1, 0, E_FINDCLASSSSTRINGSTR, &list, &hiddevinst_list, &usb_dev_info_set, NULL);
	}

	usbHidDevicesFound = (*env)->NewObjectArray(env, (jsize)list.index, strClass, NULL);
	if ((usbHidDevicesFound == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) {
		return clean_throw_exp_usbenumeration(env, 3, 1, 0, E_NEWOBJECTARRAYSTR, &list, &hiddevinst_list, &usb_dev_info_set, NULL);
	}

	for (x = 0; x < list.index; x++) {
		(*env)->SetObjectArrayElement(env, usbHidDevicesFound, x, list.base[x]);
		if ((*env)->ExceptionOccurred(env)) {
			return clean_throw_exp_usbenumeration(env, 3, 1, 0, E_SETOBJECTARRAYSTR, &list, &hiddevinst_list, &usb_dev_info_set, NULL);
		}
	}

	/* clean up and return result to java layer application */
	free_jstrarraylist(&list);
	free_hiddev_instance_list(&hiddevinst_list);
	SetupDiDestroyDeviceInfoList(usb_dev_info_set);
	return usbHidDevicesFound;
}
Esempio n. 13
0
PPH_STRING FindDiskDeviceInstance(
    _In_ PPH_STRING DevicePath
    )
{
    PPH_STRING deviceIdString = NULL;
    HDEVINFO deviceInfoHandle;
    SP_DEVICE_INTERFACE_DATA deviceInterfaceData = { sizeof(SP_DEVICE_INTERFACE_DATA) };
    SP_DEVINFO_DATA deviceInfoData = { sizeof(SP_DEVINFO_DATA) };
    PSP_DEVICE_INTERFACE_DETAIL_DATA deviceInterfaceDetail;
    ULONG deviceInfoLength = 0;

    if ((deviceInfoHandle = SetupDiGetClassDevs(
        &GUID_DEVINTERFACE_DISK,
        NULL,
        NULL,
        DIGCF_DEVICEINTERFACE
        )) == INVALID_HANDLE_VALUE)
    {
        return NULL;
    }

    for (ULONG i = 0; SetupDiEnumDeviceInterfaces(deviceInfoHandle, NULL, &GUID_DEVINTERFACE_DISK, i, &deviceInterfaceData); i++)
    {
        if (SetupDiGetDeviceInterfaceDetail(
            deviceInfoHandle,
            &deviceInterfaceData,
            0,
            0,
            &deviceInfoLength,
            &deviceInfoData
            ) || GetLastError() != ERROR_INSUFFICIENT_BUFFER)
        {
            continue;
        }

        deviceInterfaceDetail = PhAllocate(deviceInfoLength);
        deviceInterfaceDetail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);

        if (SetupDiGetDeviceInterfaceDetail(
            deviceInfoHandle,
            &deviceInterfaceData,
            deviceInterfaceDetail,
            deviceInfoLength,
            &deviceInfoLength,
            &deviceInfoData
            ))
        {
            if (PhEqualStringZ(deviceInterfaceDetail->DevicePath, DevicePath->Buffer, TRUE))
            {
                deviceIdString = PhCreateStringEx(NULL, 0x100);

                SetupDiGetDeviceInstanceId(
                    deviceInfoHandle,
                    &deviceInfoData,
                    deviceIdString->Buffer,
                    (ULONG)deviceIdString->Length,
                    NULL
                    );

                PhTrimToNullTerminatorString(deviceIdString);
            }
        }

        PhFree(deviceInterfaceDetail);
    }

    SetupDiDestroyDeviceInfoList(deviceInfoHandle);

    return deviceIdString;
}
Esempio n. 14
0
//------------------------------------------------------------------------------
// DWORD WINAPI EnumComPorts(DWORD dwIndex, LPTSTR lptszName,
//      DWORD dwNumOfElements)
//
// User-mode code fragment to identify attached VCP COMnn port[s] with a
// specific device instance ID based on USB VID and PID and returns the COMnn
// port that the OS embeds into the device instance ID. When called with
// dwIndex = 0, the function will enumerate all COMPORT class devices and
// return the name of the first one that was found. Subsequent calls using an
// incremented dwIndex parameter can be performed until ERROR_NO_MORE_ITEMS
// is returned.
//
// IN:  dwIndex               COMPORT class device # 0, 1, 2, ... to check
//      dwNumOfElements       The size of the lptszName buffer
// OUT: lptszName             COMnn name of given device #
//      return()              ERROR_SUCCESS - lpszName is valid
//                            ERROR_NO_MORE_ITEMS - End of device list reached
//------------------------------------------------------------------------------
DWORD WINAPI EnumComPorts(DWORD dwIndex, LPTSTR lptszName, DWORD dwNumOfElements)
{
    HDEVINFO hDevInfo;
    SP_DEVINFO_DATA DeviceInfoData;
    DWORD i;
    TCHAR *pcParse;

    // Create a HDEVINFO with all present devices
    hDevInfo = SetupDiGetClassDevs(
                    NULL,
                    0, // Enumerator
                    0,
                    DIGCF_PRESENT | DIGCF_ALLCLASSES);
    
    if (INVALID_HANDLE_VALUE == hDevInfo)
    {
        return GetLastError();
    }
    
    // Enumerate through all devices in set
    DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);

    for (i = 0; SetupDiEnumDeviceInfo(hDevInfo, i, &DeviceInfoData); i++)
    {
        LPTSTR buffer     = NULL;
        DWORD  buffersize = 0;

        // Get the device instance ID that is associated with the device information element
        while (!SetupDiGetDeviceInstanceId(
                    hDevInfo, 
                    &DeviceInfoData, 
                    buffer, 
                    buffersize, 
                    &buffersize))
        {
            if (buffer)
            {
               LocalFree(buffer);
            }
                
            if (ERROR_INSUFFICIENT_BUFFER == GetLastError())
            {
                // Change the buffer size. Double the size to avoid problems on
                // W2K MBCS systems per KB 888609.
                buffer = (LPTSTR)LocalAlloc(LPTR, buffersize * 2);
            }
            else
            {
                // Error: could not get device instance ID
                // Cleanup and return error code
                SetupDiDestroyDeviceInfoList(hDevInfo);
                return GetLastError();
            }
        }

        if (buffer)
        {
            // Look for the "Application UART" of common MSP430 EVMs. The application UART
            // has an USB VID of 0x0451 (Texas Instruments) and an PID of 0xF432.
			const TCHAR testval[] = _T("USB\\VID_0451&PID_F432&MI_00");

			if (NULL != _tcsstr(buffer, testval))
            {
				TCHAR szFriendlyName[MAX_PATH];
			    
				if (SetupDiGetDeviceRegistryProperty(
					hDevInfo,
					&DeviceInfoData,
					SPDRP_FRIENDLYNAME,
					NULL,
					(PBYTE)szFriendlyName,
					sizeof(szFriendlyName) - 1,
					NULL))
				{
                    // Check if we have reached the dwIndex-th element, if not keep looking
                    if (dwIndex == 0)
                    {
                        // Find pointer to "COM" substring (secure)
                        szFriendlyName[sizeof(szFriendlyName) - 1] = 0x00;
                        pcParse = _tcsstr(szFriendlyName, _T("COM"));

                        if (pcParse != NULL)
                        {
                            // Zero-terminate COM port string after last digit
                            if (!isdigit(pcParse[4])) {
                                pcParse[4] = 0;
                            }
                            else if (!isdigit(pcParse[5])) {
                                pcParse[5] = 0;
                            }
                            else {
                                pcParse[6] = 0;
                            }

                            // Pass string to the return parameter
                            _tcscpy_s(lptszName, dwNumOfElements, pcParse);

                            // Cleanup
                            SetupDiDestroyDeviceInfoList(hDevInfo);

                            return ERROR_SUCCESS;
                        }
                    }
                    else
                    {
                        dwIndex--;
                    }
				}
			}
		}
    }
   
    //  Cleanup
    SetupDiDestroyDeviceInfoList(hDevInfo);
    
    return ERROR_NO_MORE_ITEMS;
}
/*
 * Get the current latency timer value for ftdi devices.
 * return value read on success or -1 if any error occurs.
 */
jint get_latency_timer_value(JNIEnv *env, jstring comPortName) {

	const jchar* port_name = NULL;
	int x = 0;
	BOOL ret = FALSE;
	LONG status = 0;
	DWORD error_code = 0;
	DWORD size = 0;
	DWORD regproptype;
	DWORD charbuffer_size = 0;
	DWORD driver_name_size = 0;
	ULONG buffer_size = 0;
	DWORD usb_member_index = 0;
	HDEVINFO usb_dev_info_set;
	SP_DEVINFO_DATA usb_dev_instance;
	ULONG devprop_buffer_size = 0;
	DEVPROPTYPE proptype;
	CONFIGRET cmret = 0;
	DEVINST firstchild = 0;
	DEVINST next_sibling = 0;
	DEVINST current_sibling = 0;
	DWORD timer_value;
	DWORD timervalue_size;

	/* size of these buffers is hardcoded in functions using them */
	TCHAR buffer[1024];
	TCHAR devprop_buffer[1024];
	TCHAR keybuf[1024];
	TCHAR charbuffer[128];
	char cmerror[256];

	/* extract com port name to match (as an array of Unicode characters) */
	port_name = (*env)->GetStringChars(env, comPortName, JNI_FALSE);
	if ((port_name == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) {
		throw_serialcom_exception(env, 3, 0, E_GETSTRUTFCHARSTR);
		return -1;
	}

	/* get information set for all usb devices matching the GUID */
	usb_dev_info_set = SetupDiGetClassDevs(&GUID_DEVINTERFACE_USB_DEVICE, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
	if (usb_dev_info_set == INVALID_HANDLE_VALUE) {
		SetupDiDestroyDeviceInfoList(usb_dev_info_set);
		(*env)->ReleaseStringChars(env, comPortName, port_name);
		throw_serialcom_exception(env, 4, HRESULT_FROM_SETUPAPI(GetLastError()), NULL);
		return -1;
	}

	/* enumerate all devices in this information set */
	usb_member_index = 0;

	while (1) {
		ZeroMemory(&usb_dev_instance, sizeof(usb_dev_instance));
		usb_dev_instance.cbSize = sizeof(usb_dev_instance);

		/* from information set, get device by index */
		ret = SetupDiEnumDeviceInfo(usb_dev_info_set, usb_member_index, &usb_dev_instance);
		if (ret == FALSE) {
			error_code = GetLastError();
			if (error_code == ERROR_NO_MORE_ITEMS) {
				break;
			}
			else {
				SetupDiDestroyDeviceInfoList(usb_dev_info_set);
				(*env)->ReleaseStringChars(env, comPortName, port_name);
				throw_serialcom_exception(env, 4, HRESULT_FROM_SETUPAPI(error_code), NULL);
				return -1;
			}
		}

		/* for this device find its instance ID (USB\VID_04D8&PID_00DF\000098037)
		 * this is variable 'Device Instance Path' in device manager. */
		memset(buffer, '\0', 1024);
		ret = SetupDiGetDeviceInstanceId(usb_dev_info_set, &usb_dev_instance, buffer, 1024, &size);
		if (ret == FALSE) {
			SetupDiDestroyDeviceInfoList(usb_dev_info_set);
			(*env)->ReleaseStringChars(env, comPortName, port_name);
			throw_serialcom_exception(env, 4, HRESULT_FROM_SETUPAPI(GetLastError()), NULL);
			return -1;
		}

		cmret = CM_Get_Child(&firstchild, usb_dev_instance.DevInst, 0);
		if (cmret != CR_SUCCESS) {
			if (cmret == CR_NO_SUCH_DEVNODE) {
				/* this device does not have any child, so check if this device itself is a "Ports" class device or not */
				memset(devprop_buffer, '\0', 1024);
				ret = SetupDiGetDeviceRegistryProperty(usb_dev_info_set, &usb_dev_instance, SPDRP_CLASSGUID, &regproptype, (BYTE *)devprop_buffer, sizeof(devprop_buffer), &size);
				if (ret == FALSE) {
					SetupDiDestroyDeviceInfoList(usb_dev_info_set);
					(*env)->ReleaseStringChars(env, comPortName, port_name);
					throw_serialcom_exception(env, 4, HRESULT_FROM_SETUPAPI(GetLastError()), NULL);
					return -1;
				}

				/* match GUID */
				ret = _tcsicmp(devprop_buffer, TEXT("{4D36E978-E325-11CE-BFC1-08002BE10318}"));
				if (ret != 0) {
					usb_member_index++;
					continue;
				}

				/* reaching here means that the device is COM port device (CDC/ACM), get its COM port name/number
				 * HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\FTDIBUS\VID_VID+PID_PID+Serial_Number\0000\DeviceParameters\PortName
				 * HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\USB\VID_VID+PID_PID\Serial_Number\DeviceParameters\PortName */
				memset(keybuf, '\0', 1024);
				_stprintf_s(keybuf, 1024, TEXT("SYSTEM\\CurrentControlSet\\Enum\\%s\\Device Parameters"), buffer);

				charbuffer_size = sizeof(charbuffer);
				memset(charbuffer, '\0', 128);
				status = RegGetValue(HKEY_LOCAL_MACHINE, keybuf, TEXT("PortName"), RRF_RT_REG_SZ, NULL, (PVOID)charbuffer, &charbuffer_size);
				if (status != ERROR_SUCCESS) {
					SetupDiDestroyDeviceInfoList(usb_dev_info_set);
					(*env)->ReleaseStringChars(env, comPortName, port_name);
					throw_serialcom_exception(env, 4, GetLastError(), NULL);
					return -1;
				}

				/* match port name */
				ret = _tcsicmp(charbuffer, port_name);
				if (ret != 0) {
					usb_member_index++;
					continue;
				}

				/* HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\FTDIBUS\VID_VID+PID_PID+Serial_Number\0000\DeviceParameters\LatencyTimer */
				status = RegGetValue(HKEY_LOCAL_MACHINE, keybuf, TEXT("LatencyTimer"), RRF_RT_REG_DWORD, NULL, &timer_value, &timervalue_size);
				if (status != ERROR_SUCCESS) {
					SetupDiDestroyDeviceInfoList(usb_dev_info_set);
					(*env)->ReleaseStringChars(env, comPortName, port_name);
					throw_serialcom_exception(env, 4, status, NULL);
					return -1;
				}

				SetupDiDestroyDeviceInfoList(usb_dev_info_set);
				(*env)->ReleaseStringChars(env, comPortName, port_name);
				return (jint)timer_value;
			}else {
				SetupDiDestroyDeviceInfoList(usb_dev_info_set);
				(*env)->ReleaseStringChars(env, comPortName, port_name);
				_snprintf_s(cmerror, 256, 256, "CM_Get_DevNode_Registry_Property CR_xxxx error code : 0x%X\0", cmret);
				throw_serialcom_exception(env, 3, 0, cmerror);
				return -1;
			}
		}

		/* reaching here means that this USB device has at-least one child device node, examine child now */

		devprop_buffer_size = sizeof(devprop_buffer);
		memset(devprop_buffer, '\0', sizeof(devprop_buffer));
		cmret = CM_Get_DevNode_Registry_Property(firstchild, CM_DRP_CLASSGUID, &proptype, (PVOID)devprop_buffer, &devprop_buffer_size, 0);
		if (cmret != CR_SUCCESS) {
			SetupDiDestroyDeviceInfoList(usb_dev_info_set);
			(*env)->ReleaseStringChars(env, comPortName, port_name);
			_snprintf_s(cmerror, 256, 256, "CM_Get_DevNode_Registry_Property CR_xxxx error code : 0x%X\0", cmret);
			throw_serialcom_exception(env, 3, 0, cmerror);
			return -1;
		}

		/* match GUID */
		ret = _tcsicmp(devprop_buffer, TEXT("{4D36E978-E325-11CE-BFC1-08002BE10318}"));
		if (ret == 0) {
			/* reaching here means that the child device is COM port device (CDC/ACM), get its COM port name/number */
			memset(buffer, '\0', 1024);
			cmret = CM_Get_Device_ID(firstchild, buffer, 1024, 0);
			if (cmret != CR_SUCCESS) {
				SetupDiDestroyDeviceInfoList(usb_dev_info_set);
				(*env)->ReleaseStringChars(env, comPortName, port_name);
				_snprintf_s(cmerror, 256, 256, "CM_Get_Device_ID CR_xxxx error code : 0x%X\0", cmret);
				throw_serialcom_exception(env, 3, 0, cmerror);
				return -1;
			}

			memset(keybuf, '\0', 1024);
			_stprintf_s(keybuf, 1024, TEXT("SYSTEM\\CurrentControlSet\\Enum\\%s\\Device Parameters"), buffer);

			charbuffer_size = sizeof(charbuffer);
			memset(charbuffer, '\0', 128);

			status = RegGetValue(HKEY_LOCAL_MACHINE, keybuf, TEXT("PortName"), RRF_RT_REG_SZ, NULL, (PVOID)charbuffer, &charbuffer_size);
			if (status != ERROR_SUCCESS) {
				SetupDiDestroyDeviceInfoList(usb_dev_info_set);
				(*env)->ReleaseStringChars(env, comPortName, port_name);
				throw_serialcom_exception(env, 4, GetLastError(), NULL);
				return -1;
			}

			/* match port name */
			ret = _tcsicmp(charbuffer, port_name);
			if (ret == 0) {
				status = RegGetValue(HKEY_LOCAL_MACHINE, keybuf, TEXT("LatencyTimer"), RRF_RT_REG_DWORD, NULL, &timer_value, &timervalue_size);
				if (status != ERROR_SUCCESS) {
					SetupDiDestroyDeviceInfoList(usb_dev_info_set);
					(*env)->ReleaseStringChars(env, comPortName, port_name);
					throw_serialcom_exception(env, 4, GetLastError(), NULL);
					return -1;
				}

				/* clean up and return timer value found */
				SetupDiDestroyDeviceInfoList(usb_dev_info_set);
				(*env)->ReleaseStringChars(env, comPortName, port_name);
				return (jint)timer_value;
			}
		}

		/* reaching here means first child of this USB device was not CDC/ACM interface, need to
		   iterate over all the interfaces (siblings) this device has examining them for matching our criteria */
		current_sibling = firstchild;
		while (1) {
			cmret = CM_Get_Sibling(&next_sibling, current_sibling, 0);
			if (cmret != CR_SUCCESS) {
				if (cmret == CR_NO_SUCH_DEVNODE) {
					/* done iterating over all interfaces, move to next examine next USB device */
					break;
				}
				else {
					SetupDiDestroyDeviceInfoList(usb_dev_info_set);
					_snprintf_s(cmerror, 256, 256, "CM_Get_Sibling failed with CR_xxxx error code : 0x%X\0", cmret);
					(*env)->ReleaseStringChars(env, comPortName, port_name);
					throw_serialcom_exception(env, 3, 0, cmerror);
					return -1;
				}

			}

			/* reaching here means USB device has more than 1 interfaces, get class of this interface (sibling) */
			devprop_buffer_size = sizeof(devprop_buffer);
			memset(devprop_buffer, '\0', sizeof(devprop_buffer));
			cmret = CM_Get_DevNode_Registry_Property(next_sibling, CM_DRP_CLASSGUID, &proptype, (VOID *)devprop_buffer, &devprop_buffer_size, 0);
			if (cmret != CR_SUCCESS) {
				SetupDiDestroyDeviceInfoList(usb_dev_info_set);
				_snprintf_s(cmerror, 256, 256, "CM_Get_DevNode_Registry_Property failed with CR_xxxx error code : 0x%X\0", cmret);
				(*env)->ReleaseStringChars(env, comPortName, port_name);
				throw_serialcom_exception(env, 3, 0, cmerror);
				return -1;
			}

			/* match GUID for this sibling */
			ret = _tcsicmp(devprop_buffer, TEXT("{4D36E978-E325-11CE-BFC1-08002BE10318}"));
			if (ret != 0) {
				/* this interface is not CDC/ACM, loop over to next interface */
				current_sibling = next_sibling;
				continue;
			}

			/* reaching here means that this sibling (interface) is a CDC/ACM type, get its COM port name/number */
			buffer_size = (ULONG)_tcslen(buffer);
			memset(buffer, '\0', 1024);
			cmret = CM_Get_Device_ID(next_sibling, buffer, 1024, 0);
			if (cmret != CR_SUCCESS) {
				SetupDiDestroyDeviceInfoList(usb_dev_info_set);
				_snprintf_s(cmerror, 256, 256, "CM_Get_Device_ID failed with CR_xxxx error code : 0x%X\0", cmret);
				(*env)->ReleaseStringChars(env, comPortName, port_name);
				throw_serialcom_exception(env, 3, 0, cmerror);
				return -1;
			}

			memset(keybuf, '\0', 1024);
			_stprintf_s(keybuf, 1024, TEXT("SYSTEM\\CurrentControlSet\\Enum\\%s\\Device Parameters"), buffer);

			charbuffer_size = sizeof(charbuffer);
			memset(charbuffer, '\0', 128);
			status = RegGetValue(HKEY_LOCAL_MACHINE, keybuf, TEXT("PortName"), RRF_RT_REG_SZ, NULL, (PVOID)charbuffer, &charbuffer_size);
			if (status != ERROR_SUCCESS) {
				SetupDiDestroyDeviceInfoList(usb_dev_info_set);
				(*env)->ReleaseStringChars(env, comPortName, port_name);
				throw_serialcom_exception(env, 4, GetLastError(), NULL);
				return -1;
			}

			/* match port name */
			ret = _tcsicmp(charbuffer, port_name);
			if (ret == 0) {
				status = RegGetValue(HKEY_LOCAL_MACHINE, keybuf, TEXT("LatencyTimer"), RRF_RT_REG_DWORD, NULL, &timer_value, &timervalue_size);
				if (status != ERROR_SUCCESS) {
					SetupDiDestroyDeviceInfoList(usb_dev_info_set);
					(*env)->ReleaseStringChars(env, comPortName, port_name);
					throw_serialcom_exception(env, 4, GetLastError(), NULL);
					return -1;
				}

				/* clean up and return timer value found */
				SetupDiDestroyDeviceInfoList(usb_dev_info_set);
				(*env)->ReleaseStringChars(env, comPortName, port_name);
				return (jint)timer_value;
			}

			/* set this sibling as base sibling for fetching next sibling, loop over to get and check next
			interface (sibling) */
			current_sibling = next_sibling;
		}

		/* increment to get and examine the next usb device for COM ports class */
		usb_member_index++;
	}

	/* reaching here means that probably given com port does not represent ftdi device or does not exist at all */
	SetupDiDestroyDeviceInfoList(usb_dev_info_set);
	(*env)->ReleaseStringChars(env, comPortName, port_name);
	throw_serialcom_exception(env, 3, 0, E_NOTFTDIPORT);
	return -1;
}
// CDeviceSelect message handlers
BOOL CDeviceSelect::OnInitDialog()
{
    CDialogEx::OnInitDialog();

    HDEVINFO                            hardwareDeviceInfo;
    PSP_DEVICE_INTERFACE_DETAIL_DATA    deviceInterfaceDetailData = NULL;
    ULONG                               predictedLength = 0;
    ULONG                               requiredLength = 0, bytes=0;
	WCHAR								szBda[13] = {0};
	HANDLE								hDevice = INVALID_HANDLE_VALUE;

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon

    m_numDevices = 0;

    if ((hardwareDeviceInfo = SetupDiGetClassDevs (NULL, NULL, NULL, DIGCF_ALLCLASSES | DIGCF_PRESENT)) != INVALID_HANDLE_VALUE)
    {
        SP_DEVINFO_DATA DeviceInfoData;

        memset(&DeviceInfoData, 0, sizeof(DeviceInfoData));
        DeviceInfoData.cbSize = sizeof(DeviceInfoData);

        WCHAR szService[80];
        GUID guid;
        if (m_bWin8)
            guid = GUID_LONG_CHAR_SERVICE;
        else
        {
            guid.Data1 = (GUID_LONG_CHAR_SERVICE.Data4[4]     ) + (GUID_LONG_CHAR_SERVICE.Data4[5] << 8) + (GUID_LONG_CHAR_SERVICE.Data4[6] << 16) + (GUID_LONG_CHAR_SERVICE.Data4[7] << 24);
            guid.Data2 = (GUID_LONG_CHAR_SERVICE.Data4[2]     ) + (GUID_LONG_CHAR_SERVICE.Data4[3] << 8);
            guid.Data3 = (GUID_LONG_CHAR_SERVICE.Data4[0]     ) + (GUID_LONG_CHAR_SERVICE.Data4[1] << 8);
            guid.Data4[0] = (GUID_LONG_CHAR_SERVICE.Data3      ) & 0xff;
            guid.Data4[1] = (GUID_LONG_CHAR_SERVICE.Data3 >> 8 ) & 0xff;
            guid.Data4[2] = (GUID_LONG_CHAR_SERVICE.Data2      ) & 0xff;
            guid.Data4[3] = (GUID_LONG_CHAR_SERVICE.Data2 >> 8 ) & 0xff;
            guid.Data4[4] = (GUID_LONG_CHAR_SERVICE.Data1      ) & 0xff;
            guid.Data4[5] = (GUID_LONG_CHAR_SERVICE.Data1 >> 8 ) & 0xff;
            guid.Data4[6] = (GUID_LONG_CHAR_SERVICE.Data1 >> 16) & 0xff;
            guid.Data4[7] = (GUID_LONG_CHAR_SERVICE.Data1 >> 24) & 0xff;
        }
        UuidToString(szService, 80, &guid);
        ods ("%S\n", szService);
        for (DWORD n = 0; SetupDiEnumDeviceInfo(hardwareDeviceInfo, n, &DeviceInfoData); n++)
        {
            DWORD dwBytes = 0;

            SetupDiGetDeviceInstanceId(hardwareDeviceInfo, &DeviceInfoData, NULL, 0, &dwBytes);

            PWSTR szInstanceId = new WCHAR [dwBytes];
            if (szInstanceId)
            {
                if (SetupDiGetDeviceInstanceId(hardwareDeviceInfo, &DeviceInfoData, szInstanceId, dwBytes, &dwBytes))
                {
                    _wcsupr_s (szInstanceId, dwBytes);
//                    if (wcsstr(szInstanceId, L"BTHENUM"))
//                    {
//                        OutputDebugStringW(szInstanceId);
//                        OutputDebugStringW(L"\n");
                    if (wcsstr(szInstanceId, szService))
                    {
                        OutputDebugStringW(szInstanceId);
                        WCHAR buf[13];
                        wchar_t* pStart;
                        wchar_t* pEnd;
                        if (m_bWin8)
                        {
                            pStart = wcsrchr(szInstanceId, '_');
                            pEnd = wcsrchr(szInstanceId, '\\');
                        }
                        else
                        {
                            pStart = wcsrchr(szInstanceId, '&');
                            pEnd = wcsrchr(szInstanceId, '_');
                        }
                        if (pStart && pEnd)
                        {
                            *pEnd = 0;
                            wcscpy_s(buf, pStart + 1);
                            m_lbDevices.AddString(buf);
                            m_numDevices++;
                        }
//                    }
                    }
                }
                delete[] szInstanceId;
            }
        }
        SetupDiDestroyDeviceInfoList(hardwareDeviceInfo);
    }
Esempio n. 17
0
static
void
SetDeviceDetails(HWND hwndDlg, LPCGUID classGUID, LPCWSTR lpcstrDescription)
{
    HDEVINFO hInfo;
    DWORD dwIndex = 0;
    SP_DEVINFO_DATA InfoData;
    WCHAR szText[30];
    HWND hDlgCtrls[3];
    WAVEOUTCAPSW waveOut;
    UINT numDev;
    MMRESULT errCode;


    /*  enumerate waveout devices */
    numDev = waveOutGetNumDevs();
    if (numDev)
    {
        do
        {
                ZeroMemory(&waveOut, sizeof(waveOut));
                errCode = waveOutGetDevCapsW(dwIndex++, &waveOut, sizeof(waveOut));
                if (!wcsncmp(lpcstrDescription, waveOut.szPname, min(MAXPNAMELEN, wcslen(waveOut.szPname))))
                {
                    /* set the product id */
                    SetDlgItemInt(hwndDlg, IDC_STATIC_DSOUND_PRODUCTID, waveOut.wPid, FALSE);
                    /* set the vendor id */
                    SetDlgItemInt(hwndDlg, IDC_STATIC_DSOUND_VENDORID, waveOut.wMid, FALSE);
                    /* check if its a wdm audio driver */
                    if (waveOut.wPid == MM_MSFT_WDMAUDIO_WAVEOUT)
                        SendDlgItemMessageW(hwndDlg, IDC_STATIC_DSOUND_TYPE, WM_SETTEXT, 0, (LPARAM)L"WDM");

                    /* check if device is default device */
                    szText[0] = L'\0';
                    if (dwIndex - 1 == 0) /* FIXME assume default playback device is device 0 */
                        LoadStringW(hInst, IDS_OPTION_YES, szText, sizeof(szText)/sizeof(WCHAR));
                    else
                        LoadStringW(hInst, IDS_OPTION_NO, szText, sizeof(szText)/sizeof(WCHAR));

                    szText[(sizeof(szText)/sizeof(WCHAR))-1] = L'\0';
                    /* set default device info */
                    SendDlgItemMessageW(hwndDlg, IDC_STATIC_DSOUND_STANDARD, WM_SETTEXT, 0, (LPARAM)szText);
                    break;
                }
                }while(errCode == MMSYSERR_NOERROR && dwIndex < numDev);
    }

    dwIndex = 0;
    /* create the setup list */
    hInfo = SetupDiGetClassDevsW(classGUID, NULL, NULL, DIGCF_PRESENT|DIGCF_PROFILE);
    if (hInfo == INVALID_HANDLE_VALUE)
        return;

    do
    {
        ZeroMemory(&InfoData, sizeof(InfoData));
        InfoData.cbSize = sizeof(InfoData);

        if (SetupDiEnumDeviceInfo(hInfo, dwIndex, &InfoData))
        {
            /* set device name */
            if (SetupDiGetDeviceInstanceId(hInfo, &InfoData, szText, sizeof(szText)/sizeof(WCHAR), NULL))
                SendDlgItemMessageW(hwndDlg, IDC_STATIC_DSOUND_DEVICEID, WM_SETTEXT, 0, (LPARAM)szText);

            /* set the manufacturer name */
            if (SetupDiGetDeviceRegistryPropertyW(hInfo, &InfoData, SPDRP_MFG, NULL, (PBYTE)szText, sizeof(szText), NULL))
                SendDlgItemMessageW(hwndDlg, IDC_STATIC_ADAPTER_PROVIDER, WM_SETTEXT, 0, (LPARAM)szText);

            /* FIXME
             * we currently enumerate only the first adapter 
             */
            hDlgCtrls[0] = GetDlgItem(hwndDlg, IDC_STATIC_DSOUND_DRIVER);
            hDlgCtrls[1] = GetDlgItem(hwndDlg, IDC_STATIC_DSOUND_VERSION);
            hDlgCtrls[2] = GetDlgItem(hwndDlg, IDC_STATIC_DSOUND_DATE);
            EnumerateDrivers(hDlgCtrls, hInfo, &InfoData);
            break;
        }

        if (GetLastError() == ERROR_NO_MORE_ITEMS)
            break;

        dwIndex++;
    }while(TRUE);

    /* destroy the setup list */
    SetupDiDestroyDeviceInfoList(hInfo);
}
Esempio n. 18
0
static
VOID
EnumDevices(
    HWND hTreeView,
    PDEVCLASS_ENTRY pClassArray,
    ULONG ulClassCount,
    BOOL bShowHidden)
{
    HDEVINFO hDevInfo =  INVALID_HANDLE_VALUE;
    SP_DEVINFO_DATA DeviceInfoData;
    ULONG Status, Problem;
    DWORD DevIdSize;
    TCHAR DeviceName[MAX_DEV_LEN];
    DWORD DevIndex;
    LPTSTR InstanceId;
    PDEVCLASS_ENTRY pClass;
    UINT OverlayImage;
    CONFIGRET cr;


    /* Get device info for all devices of a particular class */
    hDevInfo = SetupDiGetClassDevs(NULL,
                                   NULL,
                                   NULL,
                                   DIGCF_PRESENT | DIGCF_ALLCLASSES);
    if (hDevInfo == INVALID_HANDLE_VALUE)
        return;

    for (DevIndex = 0; ; DevIndex++)
    {
        ZeroMemory(&DeviceInfoData, sizeof(SP_DEVINFO_DATA));
        DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);

        InstanceId = NULL;
        DeviceName[0] = _T('\0');
        OverlayImage = 0;

        if (!SetupDiEnumDeviceInfo(hDevInfo,
                                   DevIndex,
                                   &DeviceInfoData))
            break;

        if (bShowHidden == FALSE &&
            (IsEqualGUID(&DeviceInfoData.ClassGuid, &GUID_DEVCLASS_LEGACYDRIVER) ||
             IsEqualGUID(&DeviceInfoData.ClassGuid, &GUID_DEVCLASS_VOLUME)))
            continue;

        pClass = GetClassFromClassGuid(pClassArray,
                                       ulClassCount,
                                       &DeviceInfoData.ClassGuid);

        /* get the device ID */
        if (!SetupDiGetDeviceInstanceId(hDevInfo,
                                        &DeviceInfoData,
                                        NULL,
                                        0,
                                        &DevIdSize))
        {
            if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
            {
                InstanceId = (LPTSTR)HeapAlloc(GetProcessHeap(),
                                             0,
                                             DevIdSize * sizeof(TCHAR));
                if (InstanceId != NULL)
                {
                    if (!SetupDiGetDeviceInstanceId(hDevInfo,
                                                    &DeviceInfoData,
                                                    InstanceId,
                                                    DevIdSize,
                                                    NULL))
                    {
                        HeapFree(GetProcessHeap(),
                                 0,
                                 InstanceId);
                        InstanceId = NULL;
                    }
                }
            }
        }

        /* Skip the root device */
        if (InstanceId != NULL &&
            _tcscmp(InstanceId, _T("HTREE\\ROOT\\0")) == 0)
        {
            HeapFree(GetProcessHeap(),
                     0,
                     InstanceId);
            InstanceId = NULL;
            continue;
        }

        /* Get the device's friendly name */
        if (!SetupDiGetDeviceRegistryProperty(hDevInfo,
                                              &DeviceInfoData,
                                              SPDRP_FRIENDLYNAME,
                                              0,
                                              (BYTE*)DeviceName,
                                              MAX_DEV_LEN,
                                              NULL))
        {
            /* If the friendly name fails, try the description instead */
            SetupDiGetDeviceRegistryProperty(hDevInfo,
                                             &DeviceInfoData,
                                             SPDRP_DEVICEDESC,
                                             0,
                                             (BYTE*)DeviceName,
                                             MAX_DEV_LEN,
                                             NULL);
        }

        cr = CM_Get_DevNode_Status_Ex(&Status,
                                      &Problem,
                                      DeviceInfoData.DevInst,
                                      0,
                                      NULL);
        if ((cr == CR_SUCCESS) &&
            (Status & DN_HAS_PROBLEM))
        {
            if (Problem == CM_PROB_DISABLED ||
                Problem == CM_PROB_HARDWARE_DISABLED)
                OverlayImage = 2;
            else
                OverlayImage = 1;
        }

        InsertIntoTreeView(hTreeView,
                           pClass->hItem,
                           DeviceName,
                           InstanceId,
                           pClass->ClassImage,
                           OverlayImage);

        if (OverlayImage != 0)
        {
             /* Expand the class if the device has a problem */
             (void)TreeView_Expand(hTreeView,
                                   pClass->hItem,
                                   TVE_EXPAND);
        }

        pClass->bUsed = TRUE;
    }

    if (hDevInfo !=  INVALID_HANDLE_VALUE)
        SetupDiDestroyDeviceInfoList(hDevInfo);
}
Esempio n. 19
0
// Returns physical drive number that represents private.img.
BOOL GetPrivateImgDriveNumber(IN ULONG xenVbdId, OUT ULONG *driveNumber)
{
    HDEVINFO deviceInfoSet = INVALID_HANDLE_VALUE;
    SP_DEVINFO_DATA deviceInfoData;
    DEVPROPTYPE devPropType;
    GUID diskClassGuid = { 0 };
    DWORD returnedSize;
    WCHAR deviceId[MAX_DEVICE_ID_LEN];
    WCHAR deviceName[1024];
    WCHAR locationString[1024];
    WCHAR *s;
    DWORD index;

    // Enumerate disk class devices.
    UuidFromString((RPC_WSTR) DISK_CLASS_GUID, &diskClassGuid);
    deviceInfoSet = SetupDiGetClassDevs(&diskClassGuid, NULL, NULL, DIGCF_PRESENT); // only connected devices

    if (deviceInfoSet == INVALID_HANDLE_VALUE)
    {
        perror("SetupDiGetClassDevs");
        return FALSE;
    }

    deviceInfoData.cbSize = sizeof(deviceInfoData);
    for (index = 0;
        SetupDiEnumDeviceInfo(deviceInfoSet, index, &deviceInfoData);
        index++)
    {
        if (!SetupDiGetDeviceInstanceId(deviceInfoSet, &deviceInfoData, deviceId, RTL_NUMBER_OF(deviceId), &returnedSize))
        {
            perror("SetupDiGetDeviceInstanceId");
            continue;
        }

        LogDebug("DEVID: %s", deviceId);

        // Get device's location info.
        ZeroMemory(locationString, sizeof(locationString));
        if (!SetupDiGetDeviceProperty(deviceInfoSet, &deviceInfoData, &DEVPKEY_Device_LocationInfo, &devPropType,
            (BYTE *)locationString, sizeof(locationString), &returnedSize, 0))
        {
            perror("SetupDiGetDeviceProperty(location)");
            continue;
        }

        // Check if it's the disk we want.
        if (!IsPrivateDisk(locationString, xenVbdId))
            continue;

        LogDebug("backend ID match");

        // Get the user mode device name.
        StringCchPrintf(deviceName, RTL_NUMBER_OF(deviceName), L"\\\\?\\%s\\" DISK_INTERFACE_GUID, deviceId);
        // Replace all backslashes with #.
        for (s = deviceName + 4; *s; s++)
            if (*s == L'\\')
                *s = '#';
        LogDebug("Device name: %s", deviceName);

        // Get physical drive number.
        return GetPhysicalDriveNumber(deviceName, driveNumber);
    }

    // No matching drive found.
    return FALSE;
}
/*
 * Find the name of the most specific driver which is currently associated with the 
 * given HID device instance.
 *
 * A HID device can be on USB, I2C, BLUETOOTH or pseudo.
 */
jstring find_driver_for_given_hiddevice(JNIEnv *env, jstring hidDevNode) {

	int x = 0;
	BOOL ret = FALSE;
	LONG status = 0;
	DWORD error_code = 0;
	DWORD errorVal = 0;
	DWORD size = 0;
	DWORD charbuffer_size = 0;
	DWORD driver_name_size = 0;
	ULONG buffer_size = 0;
	DWORD hid_member_index = 0;
	HDEVINFO hid_dev_info_set;
	SP_DEVINFO_DATA hid_dev_instance;
	ULONG devprop_buffer_size = 0;
	const jchar* device_node = NULL;
	jstring driver_name = NULL;

	/* size of these buffers is hardcoded in functions using them */
	TCHAR buffer[1024];
	TCHAR keybuf[1024];
	TCHAR charbuffer[128];

	/* extract HID device name to match (as an array of Unicode characters) */
	device_node = (*env)->GetStringChars(env, hidDevNode, JNI_FALSE);
	if ((device_node == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) {
		throw_serialcom_exception(env, 3, 0, E_GETSTRCHARSTR);
		return NULL;
	}

	/* get information set for all usb devices matching the GUID */
	hid_dev_info_set = SetupDiGetClassDevs(&GUID_DEVINTERFACE_HID, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
	if (hid_dev_info_set == INVALID_HANDLE_VALUE) {
		SetupDiDestroyDeviceInfoList(hid_dev_info_set);
		(*env)->ReleaseStringChars(env, hidDevNode, device_node);
		throw_serialcom_exception(env, 4, HRESULT_FROM_SETUPAPI(GetLastError()), NULL);
		return NULL;
	}

	/* enumerate all devices in this information set */
	hid_member_index = 0;
	while (1) {
		ZeroMemory(&hid_dev_instance, sizeof(hid_dev_instance));
		hid_dev_instance.cbSize = sizeof(hid_dev_instance);

		/* from information set, get device by index */
		ret = SetupDiEnumDeviceInfo(hid_dev_info_set, hid_member_index, &hid_dev_instance);
		if (ret == FALSE) {
			error_code = GetLastError();
			if (error_code == ERROR_NO_MORE_ITEMS) {
				break;
			}else {
				SetupDiDestroyDeviceInfoList(hid_dev_info_set);
				(*env)->ReleaseStringChars(env, hidDevNode, device_node);
				throw_serialcom_exception(env, 4, HRESULT_FROM_SETUPAPI(error_code), NULL);
				return NULL;
			}
		}

		/* for this device find its instance ID, for example; HID\VID_04D8&PID_00DF&MI_02\7&33842C3F&0&0000
		 * this is variable 'Device Instance Path' in device manager. */
		memset(buffer, '\0', 1024);
		ret = SetupDiGetDeviceInstanceId(hid_dev_info_set, &hid_dev_instance, buffer, 1024, &size);
		if (ret == FALSE) {
			SetupDiDestroyDeviceInfoList(hid_dev_info_set);
			(*env)->ReleaseStringChars(env, hidDevNode, device_node);
			throw_serialcom_exception(env, 4, HRESULT_FROM_SETUPAPI(GetLastError()), NULL);
			return NULL;
		}

		/* match device path */
		ret = _tcsicmp(device_node, buffer);
		if (ret != 0) {
			hid_member_index++;
			continue;
		}

		/* reaching here means this is the device for which driver is to be found. 
		   HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\HID\VID_VID+PID_PID\Serial_Number */
		memset(keybuf, '\0', 1024);
		_stprintf_s(keybuf, 1024, TEXT("SYSTEM\\CurrentControlSet\\Enum\\%s"), buffer);

		/* HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\HID\VID_VID+PID_PID\Serial_Number\Service */
		charbuffer_size = sizeof(charbuffer);
		memset(charbuffer, '\0', 128);
		status = RegGetValue(HKEY_LOCAL_MACHINE, keybuf, TEXT("Service"), RRF_RT_REG_SZ, NULL, (PVOID)charbuffer, &charbuffer_size);
		if (status != ERROR_SUCCESS) {
			errorVal = GetLastError();
			if (errorVal == 0x00) {
				/* this indicates Service registery entry does not exist, we assume windows provided 
				   default HidClass driver is driving this device */
				driver_name = (*env)->NewStringUTF(env, "HidClass");
				if ((driver_name == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) {
					(*env)->ExceptionClear(env);
					SetupDiDestroyDeviceInfoList(hid_dev_info_set);
					(*env)->ReleaseStringChars(env, hidDevNode, device_node);
					throw_serialcom_exception(env, 3, 0, E_NEWSTRUTFSTR);
					return NULL;
				}
				return driver_name;
			}else {
				SetupDiDestroyDeviceInfoList(hid_dev_info_set);
				(*env)->ReleaseStringChars(env, hidDevNode, device_node);
				throw_serialcom_exception(env, 4, errorVal, NULL);
				return NULL;
			}
		}

		/* return the driver name found as indicated by Service registry entry */
		driver_name = (*env)->NewString(env, charbuffer, (jsize)_tcslen(charbuffer));
		if ((driver_name == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) {
			(*env)->ExceptionClear(env);
			SetupDiDestroyDeviceInfoList(hid_dev_info_set);
			(*env)->ReleaseStringChars(env, hidDevNode, device_node);
			throw_serialcom_exception(env, 3, 0, E_NEWSTRUTFSTR);
			return NULL;
		}

		SetupDiDestroyDeviceInfoList(hid_dev_info_set);
		(*env)->ReleaseStringChars(env, hidDevNode, device_node);
		return driver_name;
	}

	/* reaching here means that the no driver was found for given device path, 
	   return empty string */
	driver_name = (*env)->NewStringUTF(env, "");
	if ((driver_name == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) {
		(*env)->ExceptionClear(env);
		throw_serialcom_exception(env, 3, 0, E_NEWSTRUTFSTR);
		return NULL;
	}
	return driver_name;
}
/*
 * The sequence of entries in array must match with what java layer expect (6 informations
 * per USB device). If a particular USB attribute is not set in descriptor or can not be
 * obtained "---" is placed in its place.
 *
 * Returns array of USB device's information found, empty array if no USB device is found,
 * NULL if an error occurs (additionally throws exception).
 */
jobjectArray list_usb_devices(JNIEnv *env, jint vendor_to_match) {

	int x = 0;
	int i = 0;
	int vid = 0;
	BOOL ret = FALSE;
	DWORD error_code = 0;
	DWORD size = 0;
	TCHAR *ptrend;
	DWORD usb_member_index = 0;
	HDEVINFO usb_dev_info_set;
	SP_DEVINFO_DATA usb_dev_instance;
	DEVPROPTYPE proptype;
	DWORD regproptype;
	TCHAR buffer[1024];
	TCHAR charbuffer[1024];

	struct jstrarray_list list = { 0 };
	jstring usb_dev_info;
	jclass strClass = NULL;
	jobjectArray usbDevicesFound = NULL;

	init_jstrarraylist(&list, 50);

	/* get information set for all usb devices matching the GUID */
	usb_dev_info_set = SetupDiGetClassDevs(&GUID_DEVINTERFACE_USB_DEVICE, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
	if (usb_dev_info_set == INVALID_HANDLE_VALUE) {
		SetupDiDestroyDeviceInfoList(usb_dev_info_set);
		free_jstrarraylist(&list);
		throw_serialcom_exception(env, 4, HRESULT_FROM_SETUPAPI(GetLastError()), NULL);
		return NULL;
	}

	/* enumerate all devices in this information set */
	usb_member_index = 0;
	while (1) {
		ZeroMemory(&usb_dev_instance, sizeof(usb_dev_instance));
		usb_dev_instance.cbSize = sizeof(usb_dev_instance);

		/* from information set, get device by index */
		ret = SetupDiEnumDeviceInfo(usb_dev_info_set, usb_member_index, &usb_dev_instance);
		if (ret == FALSE) {
			error_code = GetLastError();
			if (error_code == ERROR_NO_MORE_ITEMS) {
				break;
			}
			else {
				SetupDiDestroyDeviceInfoList(usb_dev_info_set);
				free_jstrarraylist(&list);
				throw_serialcom_exception(env, 4, HRESULT_FROM_SETUPAPI(error_code), NULL);
				return NULL;
			}
		}

		/* for this device find its instance ID (USB\VID_04D8&PID_00DF\000098037)
		 * this is the variable 'Device Instance Path' in device manager. */
		memset(buffer, '\0', sizeof(buffer));
		ret = SetupDiGetDeviceInstanceId(usb_dev_info_set, &usb_dev_instance, buffer, sizeof(buffer), &size);
		if (ret == FALSE) {
			SetupDiDestroyDeviceInfoList(usb_dev_info_set);
			free_jstrarraylist(&list);
			throw_serialcom_exception(env, 4, HRESULT_FROM_SETUPAPI(GetLastError()), NULL);
			return NULL;
		}

		/* USB-IF vendor ID, extract and match, if matched continue further otherwise loop back */
		x = 0;
		while (buffer[x] != '\0') {
			if((buffer[x] == 'V') && (buffer[x + 1] == 'I') && (buffer[x + 2] == 'D') && (buffer[x + 3] == '_')) {
				break;
			}
			x++;
		}
		x = x + 4;
		i = 0;
		while (buffer[x] != '&') {
			charbuffer[i] = buffer[x];
			i++;
			x++;
		}
		charbuffer[i] = '\0'; /* indicate end of string */

		vid = (int)_tcstol(charbuffer, &ptrend, 16);

		if(vendor_to_match != 0) {
			/* we need to apply filter for identify specific vendor */
			if(vid != vendor_to_match) {
				usb_member_index++;
				continue;
			}
		}

		usb_dev_info = (*env)->NewString(env, charbuffer, (jsize) _tcslen(charbuffer));
		if((usb_dev_info == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) {
			(*env)->ExceptionClear(env);
			SetupDiDestroyDeviceInfoList(usb_dev_info_set);
			free_jstrarraylist(&list);
			throw_serialcom_exception(env, 3, 0, E_NEWSTRSTR);
			return NULL;
		}
		insert_jstrarraylist(&list, usb_dev_info);

		/* USB product ID */
		x = 6;
		while (buffer[x] != '\0') {
			if ((buffer[x] == 'P') && (buffer[x + 1] == 'I') && (buffer[x + 2] == 'D') && (buffer[x + 3] == '_')) {
				break;
			}
			x++;
		}
		x = x + 4;
		i = 0;
		while (buffer[x] != '\\') {
			charbuffer[i] = buffer[x];
			i++;
			x++;
		}
		charbuffer[i] = '\0';

		usb_dev_info = (*env)->NewString(env, charbuffer, (jsize) _tcslen(charbuffer));
		if ((usb_dev_info == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) {
			(*env)->ExceptionClear(env);
			SetupDiDestroyDeviceInfoList(usb_dev_info_set);
			free_jstrarraylist(&list);
			throw_serialcom_exception(env, 3, 0, E_NEWSTRSTR);
			return NULL;
		}
		insert_jstrarraylist(&list, usb_dev_info);

		/* SERIAL NUMBER */
		x++;
		i = 0;
		while (buffer[x] != '\0') {
			charbuffer[i] = buffer[x];
			i++;
			x++;
		}
		charbuffer[i] = '\0';

		usb_dev_info = (*env)->NewString(env, charbuffer, (jsize) _tcslen(charbuffer));
		if ((usb_dev_info == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) {
			(*env)->ExceptionClear(env);
			SetupDiDestroyDeviceInfoList(usb_dev_info_set);
			free_jstrarraylist(&list);
			throw_serialcom_exception(env, 3, 0, E_NEWSTRSTR);
			return NULL;
		}
		insert_jstrarraylist(&list, usb_dev_info);

		/* PRODUCT (idProduct field of USB device descriptor) */
		memset(buffer, '\0', sizeof(buffer));
		ret = SetupDiGetDeviceProperty(usb_dev_info_set, &usb_dev_instance, &DEVPKEY_Device_BusReportedDeviceDesc, &proptype, (BYTE *)buffer, sizeof(buffer), &size, 0);
		if (ret == FALSE) {
			SetupDiDestroyDeviceInfoList(usb_dev_info_set);
			free_jstrarraylist(&list);
			throw_serialcom_exception(env, 4, HRESULT_FROM_SETUPAPI(GetLastError()), NULL);
			return NULL;
		}
		usb_dev_info = (*env)->NewString(env, buffer, (jsize) _tcslen(buffer));
		insert_jstrarraylist(&list, usb_dev_info);

		/* MANUFACTURER */
		memset(buffer, '\0', sizeof(buffer));
		ret = SetupDiGetDeviceProperty(usb_dev_info_set, &usb_dev_instance, &DEVPKEY_Device_Manufacturer, &proptype, (BYTE *)buffer, sizeof(buffer), &size, 0);
		if (ret == FALSE) {
			SetupDiDestroyDeviceInfoList(usb_dev_info_set);
			free_jstrarraylist(&list);
			throw_serialcom_exception(env, 4, HRESULT_FROM_SETUPAPI(GetLastError()), NULL);
			return NULL;
		}
		usb_dev_info = (*env)->NewString(env, buffer, (jsize) _tcslen(buffer));
		insert_jstrarraylist(&list, usb_dev_info);

		/* LOCATION (Location paths + Location info, get separately and then create a single string) */
		memset(buffer, '\0', sizeof(buffer));
		ret = SetupDiGetDeviceRegistryProperty(usb_dev_info_set, &usb_dev_instance, SPDRP_LOCATION_PATHS, &regproptype, (BYTE *)buffer, sizeof(buffer), &size);
		if (ret == FALSE) {
			SetupDiDestroyDeviceInfoList(usb_dev_info_set);
			free_jstrarraylist(&list);
			throw_serialcom_exception(env, 4, HRESULT_FROM_SETUPAPI(GetLastError()), NULL);
			return NULL;
		}

		memset(charbuffer, '\0', sizeof(charbuffer));
		ret = SetupDiGetDeviceRegistryProperty(usb_dev_info_set, &usb_dev_instance, SPDRP_LOCATION_INFORMATION, &regproptype, (BYTE *)charbuffer, sizeof(charbuffer), &size);
		if (ret == FALSE) {
			SetupDiDestroyDeviceInfoList(usb_dev_info_set);
			free_jstrarraylist(&list);
			throw_serialcom_exception(env, 4, HRESULT_FROM_SETUPAPI(GetLastError()), NULL);
			return NULL;
		}

		i = 0;
		x = (int)_tcslen(buffer);
		buffer[x] = '-';
		x++;
		for (i = 0; i < (int)_tcslen(charbuffer); i++) {
			buffer[x] = charbuffer[i];
			x++;
		}
		buffer[x] = '\0';

		usb_dev_info = (*env)->NewString(env, buffer, (jsize)_tcslen(buffer));
		insert_jstrarraylist(&list, usb_dev_info);

		/* loop to get next USB device */
		usb_member_index++;
	}

	SetupDiDestroyDeviceInfoList(usb_dev_info_set);

	strClass = (*env)->FindClass(env, JAVALSTRING);
	if((strClass == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) {
		(*env)->ExceptionClear(env);
		free_jstrarraylist(&list);
		throw_serialcom_exception(env, 3, 0, E_FINDCLASSSSTRINGSTR);
		return NULL;
	}

	usbDevicesFound = (*env)->NewObjectArray(env, (jsize)list.index, strClass, NULL);
	if((usbDevicesFound == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) {
		(*env)->ExceptionClear(env);
		free_jstrarraylist(&list);
		throw_serialcom_exception(env, 3, 0, E_NEWOBJECTARRAYSTR);
		return NULL;
	}

	for (x = 0; x < list.index; x++) {
		(*env)->SetObjectArrayElement(env, usbDevicesFound, x, list.base[x]);
		if ((*env)->ExceptionOccurred(env)) {
			(*env)->ExceptionClear(env);
			free_jstrarraylist(&list);
			throw_serialcom_exception(env, 3, 0, E_SETOBJECTARRAYSTR);
			return NULL;
		}
	}

	free_jstrarraylist(&list);
	return usbDevicesFound;
}
Esempio n. 22
0
//功能:	枚举机器上的所有的物理网卡(不包括虚拟网卡)
//参数:	NIC结构体的列表,调用成功包含所有的物理网卡的相关系统
//返回值:	调用成功返回TRUE,否则返回FALSE
//调用成功后必须调用FreeNicListBuffer释放内存
 BOOL  NetworkInterfaces(NICLIST **Niclist)
{
	if (NULL==Niclist)
	{
		return FALSE;
	}
	else
	{
		*Niclist=NULL;
	}

	HDEVINFO hDevInfo=INVALID_HANDLE_VALUE;

	//if (INVALID_HANDLE_VALUE == (hDevInfo =SetupDiGetClassDevs(&GUID_NDIS_LAN_CLASS/*NULL*/,NULL,NULL,	DIGCF_DEVICEINTERFACE/*DIGCF_PRESENT |DIGCF_ALLCLASSES*/))) 
	if (INVALID_HANDLE_VALUE == (hDevInfo =SetupDiGetClassDevs(&GUID_NDIS_LAN_CLASS, NULL, NULL, DIGCF_DEVICEINTERFACE))) 
	{ 
		return FALSE; 
	} 

	Garbage DevListGC(hDevInfo);

	DWORD	i		=0, 
		Status	=0,
		Problem	=0;
	NIC		CurNic;

	SP_DEVINFO_DATA DeviceInfoData	={sizeof(SP_DEVINFO_DATA)}; 

	TCHAR			Buffer[MY_BUFFER_SIZE]	={0};
	DWORD			Length			=sizeof(Buffer);

	std::list<NIC> nics_list;

	for (i=0;SetupDiEnumDeviceInfo(hDevInfo,i,&DeviceInfoData);i++) 
	{ 
		if (CM_Get_DevNode_Status(&Status, &Problem, DeviceInfoData.DevInst,0) == CR_SUCCESS)
		{
			if ( ((Status & DN_NO_SHOW_IN_DM)==0)&&(!IsClassHidden(&DeviceInfoData.ClassGuid)) )
			//if ( ((Status & DN_NO_SHOW_IN_DM)==0) )
			{
				CurNic.m_dwId=i;

				if (SetupDiGetDeviceRegistryProperty(hDevInfo,   
					&DeviceInfoData, SPDRP_DEVICEDESC, NULL,(PBYTE)Buffer, Length, &Length))   
				{   
					Buffer[Length]=TEXT('\0');
					//CurNic.m_strDevDesc=Buffer;
					_tcscpy(CurNic.m_chDevDesc,Buffer);
					Length=sizeof(Buffer);
				}
				else
				{
					//CurNic.m_strDevDesc=TEXT("Nic without description");
					_tcscpy(CurNic.m_chDevDesc,TEXT("Nic without description"));
				}

				CurNic.m_bDisabled=(Status & DN_HAS_PROBLEM) && (CM_PROB_DISABLED == Problem);
				CurNic.m_dwNicType=0;
				//CurNic.m_strDevGuid.clear();
				CurNic.m_chDevGuid[0]=TEXT('\0');

				DWORD dwSizeRequired = 0;
				TCHAR szPnpInstanceId[MY_BUFFER_SIZE+1];

				if (SetupDiGetDeviceInstanceId(hDevInfo, &DeviceInfoData, 
					szPnpInstanceId, MY_BUFFER_SIZE, &dwSizeRequired))
				{
					std::list<TString>	GuidList;
					int					iMedia		=0;
					if (GetNicGuid(szPnpInstanceId,GuidList)&&(!GuidList.empty()))
					{
						//CurNic.m_strDevGuid=GuidList.front();
						_tcscpy(CurNic.m_chDevGuid,GuidList.front().c_str());

						if ((iMedia=GetNicMediaType(GuidList.front()))>0)
						{
							CurNic.m_dwNicType=iMedia;
						}
					}

				}

				if (IsPhysicalNic(/*CurNic.m_strDevGuid.c_str()*/CurNic.m_chDevGuid))
				{
					//TString strDevGuid=CurNic.m_chDevGuid;
					//_tcscpy(CurNic.m_chDevGuid,strDevGuid.substr(1,36).c_str());//去掉GUID的大括号

					nics_list.push_back(CurNic);
				}

			}//if
		}//if
	} //for


	if (nics_list.size()!=0)
	{
		*Niclist=new NICLIST;
		NICLIST *lpTemp=*Niclist;
		lpTemp->dwCount	=nics_list.size();
		lpTemp->lpNics		=new NIC[lpTemp->dwCount];
		int k=0;
		for (std::list<NIC>::iterator i=nics_list.begin();i!=nics_list.end();++i,++k)
		{
			lpTemp->lpNics[k].m_bDisabled	=i->m_bDisabled;
			lpTemp->lpNics[k].m_dwId		=i->m_dwId;
			lpTemp->lpNics[k].m_dwNicType	=i->m_dwNicType;
			_tcscpy(lpTemp->lpNics[k].m_chDevDesc,i->m_chDevDesc);
			_tcscpy(lpTemp->lpNics[k].m_chDevGuid,i->m_chDevGuid);
		}
		return TRUE;
	}
	else
	{
		*Niclist=NULL;
		return FALSE;
	}
}
Esempio n. 23
0
//+---------------------------------------------------------------------------
//
// Function:  HrShowNetAdapters
//
// Purpose:   Display all installed net class devices using Setup API
//
// Arguments: None
//
// Returns:   S_OK on success, otherwise an error code
//
// Notes:
//
HRESULT HrShowNetAdapters()
{
#define MAX_COMP_INSTID 4096
#define MAX_COMP_DESC   4096

    HRESULT hr=S_OK;
    HDEVINFO hdi;
    DWORD dwIndex=0;
    SP_DEVINFO_DATA deid;
    BOOL fSuccess=FALSE;
    DWORD   cchRequiredSize;
    TCHAR szCompInstanceId[MAX_COMP_INSTID];
    TCHAR szCompDescription[MAX_COMP_DESC];
    DWORD dwRegType;
    BOOL fFound=FALSE;

    // get a list of all devices of class 'GUID_DEVCLASS_NET'
    hdi = SetupDiGetClassDevs(&GUID_DEVCLASS_NET, NULL, NULL, DIGCF_PRESENT);

    if (INVALID_HANDLE_VALUE != hdi)
    {
        // enumerate over each device
        while (deid.cbSize = sizeof(SP_DEVINFO_DATA),
               SetupDiEnumDeviceInfo(hdi, dwIndex, &deid))
        {
            dwIndex++;

            // the right thing to do here would be to call this function
            // to get the size required to hold the instance ID and then
            // to call it second time with a buffer large enough for that size.
            // However, that would tend to obscure the control flow in
            // the sample code. Lets keep things simple by keeping the
            // buffer large enough.

            // get the device instance ID
            fSuccess = SetupDiGetDeviceInstanceId(hdi, &deid,
                                                  szCompInstanceId,
                                                  MAX_COMP_INSTID, NULL);
            if (fSuccess)
            {
                // get the description for this instance
                fSuccess =
                    SetupDiGetDeviceRegistryProperty(hdi, &deid,
                                                     SPDRP_DEVICEDESC,
                                                     &dwRegType,
                                                     (BYTE*) szCompDescription,
                                                     MAX_COMP_DESC,
                                                     NULL);
                if (fSuccess)
                {
                    if (!fFound)
                    {
                        fFound = TRUE;
                        LogPrintf(_T("Instance ID\tDescription\n"));
                        LogPrintf(_T("-----------\t-----------\n"));
                    }
                   LogPrintf(_T("%s\t%s\n"),
                            szCompInstanceId, szCompDescription);
                }
            }
        }

        // release the device info list
        SetupDiDestroyDeviceInfoList(hdi);
    }

    if (!fSuccess)
    {
        DWORD dwError = GetLastError();
        hr = HRESULT_FROM_WIN32(dwError);
    }

    return hr;
}
Esempio n. 24
0
static PTCHAR
GetDeviceInstance(
    IN  HDEVINFO            DeviceInfoSet,
    IN  PSP_DEVINFO_DATA    DeviceInfoData
    )
{
    DWORD                   DeviceInstanceLength;
    PTCHAR                  DeviceInstance;
    DWORD                   Index;
    HRESULT                 Error;

    if (!SetupDiGetDeviceInstanceId(DeviceInfoSet,
                                    DeviceInfoData,
                                    NULL,
                                    0,
                                    &DeviceInstanceLength)) {
        if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
            goto fail1;
    }

    DeviceInstanceLength += sizeof (TCHAR);

    DeviceInstance = malloc(DeviceInstanceLength);
    if (DeviceInstance == NULL)
        goto fail2;

    memset(DeviceInstance, 0, DeviceInstanceLength);

    if (!SetupDiGetDeviceInstanceId(DeviceInfoSet,
                                    DeviceInfoData,
                                    DeviceInstance,
                                    DeviceInstanceLength,
                                    NULL))
        goto fail3;

    for (Index = 0; Index < strlen(DeviceInstance); Index++)
        DeviceInstance[Index] = (CHAR)toupper(DeviceInstance[Index]);

    Log("%s", DeviceInstance);

    return DeviceInstance;

fail3:
    Log("fail3");

    free(DeviceInstance);

fail2:
    Log("fail2");

fail1:
    Error = GetLastError();

    {
        PTCHAR  Message;

        Message = GetErrorMessage(Error);
        Log("fail1 (%s)", Message);
        LocalFree(Message);
    }

    return NULL;
}