Skip to content

Commit

Permalink
Refactoring of EIO_List for Windows: …
Browse files Browse the repository at this point in the history
1. use single API -- SetupAPI directly without COM-object
2. supply ResultItem with vendorId, productId and locationId (issue serialport#877)
3. solve problem with pnpId not beeing returned on some systems
  • Loading branch information
Zensey committed Nov 20, 2016
1 parent fdad005 commit 2768653
Show file tree
Hide file tree
Showing 11 changed files with 94 additions and 8,079 deletions.
4 changes: 1 addition & 3 deletions binding.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,7 @@
['OS=="win"',
{
'sources': [
'src/serialport_win.cpp',
'src/win/disphelper.c',
'src/win/enumser.cpp',
'src/serialport_win.cpp'
],
'msvs_settings': {
'VCCLCompilerTool': {
Expand Down
167 changes: 93 additions & 74 deletions src/serialport_win.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@
#include <list>
#include <vector>
#include "./serialport.h"
#include "win/disphelper.h"
#include "win/stdafx.h"
#include "win/enumser.h"
#include <string.h>
#include <windows.h>
#include <Setupapi.h>
#include <devguid.h>
#pragma comment (lib, "setupapi.lib")

#ifdef WIN32

Expand Down Expand Up @@ -454,88 +456,105 @@ void EIO_Close(uv_work_t* req) {
}
}

/*
* listComPorts.c -- list COM ports
*
* http://github.com/todbot/usbSearch/
*
* 2012, Tod E. Kurt, http://todbot.com/blog/
*
*
* Uses DispHealper : http://disphelper.sourceforge.net/
*
* Notable VIDs & PIDs combos:
* VID 0403 - FTDI
*
* VID 0403 / PID 6001 - Arduino Diecimila
*
*/
char *copySubstring(char *someString, int n)
{
char *new_ = (char*)malloc(sizeof(char)*n + 1);
strncpy_s(new_, n + 1, someString, n);
new_[n] = '\0';
return new_;
}

void EIO_List(uv_work_t* req) {
ListBaton* data = static_cast<ListBaton*>(req->data);

{
DISPATCH_OBJ(wmiSvc);
DISPATCH_OBJ(colDevices);

dhInitialize(TRUE);
dhToggleExceptions(FALSE);

dhGetObject(L"winmgmts:{impersonationLevel=impersonate}!\\\\.\\root\\cimv2", NULL, &wmiSvc);
dhGetValue(L"%o", &colDevices, wmiSvc, L".ExecQuery(%S)", L"Select * from Win32_PnPEntity");

int port_count = 0;
FOR_EACH(objDevice, colDevices, NULL) {
char* name = NULL;
char* pnpid = NULL;
char* manu = NULL;
char* match;

dhGetValue(L"%s", &name, objDevice, L".Name");
dhGetValue(L"%s", &pnpid, objDevice, L".PnPDeviceID");

if (name != NULL && ((match = strstr(name, "(COM")) != NULL)) { // look for "(COM23)"
// 'Manufacturuer' can be null, so only get it if we need it
dhGetValue(L"%s", &manu, objDevice, L".Manufacturer");
port_count++;
char* comname = strtok(match, "()");
ListResultItem* resultItem = new ListResultItem();
resultItem->comName = comname;
resultItem->manufacturer = manu;
resultItem->pnpId = pnpid;
data->results.push_back(resultItem);
dhFreeString(manu);
GUID *guidDev = (GUID*)& GUID_DEVCLASS_PORTS;
HDEVINFO hDevInfo = SetupDiGetClassDevs(guidDev, NULL, NULL, DIGCF_PRESENT | DIGCF_PROFILE);
SP_DEVINFO_DATA deviceInfoData;

int memberIndex = 0;
DWORD dwSize, dwPropertyRegDataType;
char szBuffer[400];
char *pnpId;
char *vendorId;
char *productId;
char *name;
char *manufacturer;
char *locationId;
bool isCom;
while (true) {
pnpId = NULL;
vendorId = NULL;
productId = NULL;
name = NULL;
manufacturer = NULL;
locationId = NULL;

ZeroMemory(&deviceInfoData, sizeof(SP_DEVINFO_DATA));
deviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);

if (SetupDiEnumDeviceInfo(hDevInfo, memberIndex, &deviceInfoData) == FALSE) {
if (GetLastError() == ERROR_NO_MORE_ITEMS) {
break;
}
}

dhFreeString(name);
dhFreeString(pnpid);
} NEXT(objDevice);
dwSize = sizeof(szBuffer);
SetupDiGetDeviceInstanceId(hDevInfo, &deviceInfoData, szBuffer, dwSize, &dwSize);
szBuffer[dwSize] = '\0';
pnpId = strdup(szBuffer);

SAFE_RELEASE(colDevices);
SAFE_RELEASE(wmiSvc);
vendorId = strstr(szBuffer, "VID_");
if (vendorId) {
vendorId += 4;
vendorId = copySubstring(vendorId, 4);
}
productId = strstr(szBuffer, "PID_");
if (productId) {
productId += 4;
productId = copySubstring(productId, 4);
}

dhUninitialize(TRUE);
}
if (SetupDiGetDeviceRegistryProperty(hDevInfo, &deviceInfoData, SPDRP_LOCATION_INFORMATION, &dwPropertyRegDataType, (BYTE*)szBuffer, sizeof(szBuffer), &dwSize)) {
locationId = strdup(szBuffer);
}
if (SetupDiGetDeviceRegistryProperty(hDevInfo, &deviceInfoData, SPDRP_MFG, &dwPropertyRegDataType, (BYTE*)szBuffer, sizeof(szBuffer), &dwSize)) {
manufacturer = strdup(szBuffer);
}

std::vector<UINT> ports;
if (CEnumerateSerial::UsingQueryDosDevice(ports)) {
for (size_t i = 0; i < ports.size(); i++) {
char comname[64] = { 0 };
_snprintf_s(comname, sizeof(comname), _TRUNCATE, "COM%u", ports[i]);
bool bFound = false;
for (std::list<ListResultItem*>::iterator ri = data->results.begin(); ri != data->results.end(); ++ri) {
if (stricmp((*ri)->comName.c_str(), comname) == 0) {
bFound = true;
break;
}
HKEY hkey = SetupDiOpenDevRegKey(hDevInfo, &deviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_READ);
if (hkey != INVALID_HANDLE_VALUE) {
dwSize = sizeof(szBuffer);
if (RegQueryValueEx(hkey, "PortName", NULL, NULL, (LPBYTE)&szBuffer, &dwSize) == ERROR_SUCCESS) {
szBuffer[dwSize] = '\0';
name = strdup(szBuffer);
isCom = strstr(szBuffer, "COM") != NULL;
}
if (!bFound) {
ListResultItem* resultItem = new ListResultItem();
resultItem->comName = comname;
resultItem->manufacturer = "";
resultItem->pnpId = "";
data->results.push_back(resultItem);
}
if (isCom) {
ListResultItem* resultItem = new ListResultItem();
resultItem->comName = name;
resultItem->manufacturer = manufacturer;
resultItem->pnpId = pnpId;
if (vendorId) {
resultItem->vendorId = vendorId;
}
if (productId) {
resultItem->productId = productId;
}
data->results.push_back(resultItem);
}
free(pnpId);
free(vendorId);
free(productId);
free(locationId);
free(manufacturer);
free(name);

RegCloseKey(hkey);
memberIndex++;
}
if (hDevInfo) {
SetupDiDestroyDeviceInfoList(hDevInfo);
}
}

Expand Down
72 changes: 0 additions & 72 deletions src/win/AutoHModule.h

This file was deleted.

62 changes: 0 additions & 62 deletions src/win/AutoHandle.h

This file was deleted.

Loading

0 comments on commit 2768653

Please sign in to comment.