Example #1
0
BOOL CEnumerateSerial::UsingSetupAPI2(CSimpleArray<UINT>& ports, CSimpleArray<CString>& friendlyNames)
#endif
{
  //Make sure we clear out any elements which may already be in the array(s)
#if defined CENUMERATESERIAL_USE_STL
  ports.clear();
  friendlyNames.clear();
#else
  ports.RemoveAll();
  friendlyNames.RemoveAll();
#endif  

  //Get the function pointers to "SetupDiGetClassDevs", "SetupDiGetClassDevs", "SetupDiEnumDeviceInfo", "SetupDiOpenDevRegKey" 
  //and "SetupDiDestroyDeviceInfoList" in setupapi.dll
  CAutoHModule setupAPI(LoadLibraryFromSystem32(_T("SETUPAPI.DLL")));
  if (setupAPI == NULL)
    return FALSE;

  SETUPDIOPENDEVREGKEY* lpfnLPSETUPDIOPENDEVREGKEY = reinterpret_cast<SETUPDIOPENDEVREGKEY*>(GetProcAddress(setupAPI, "SetupDiOpenDevRegKey"));
#if defined _UNICODE
  SETUPDICLASSGUIDSFROMNAME* lpfnSETUPDICLASSGUIDSFROMNAME = reinterpret_cast<SETUPDICLASSGUIDSFROMNAME*>(GetProcAddress(setupAPI, "SetupDiClassGuidsFromNameW"));
  SETUPDIGETCLASSDEVS* lpfnSETUPDIGETCLASSDEVS = reinterpret_cast<SETUPDIGETCLASSDEVS*>(GetProcAddress(setupAPI, "SetupDiGetClassDevsW"));
  SETUPDIGETDEVICEREGISTRYPROPERTY* lpfnSETUPDIGETDEVICEREGISTRYPROPERTY = reinterpret_cast<SETUPDIGETDEVICEREGISTRYPROPERTY*>(GetProcAddress(setupAPI, "SetupDiGetDeviceRegistryPropertyW"));
#else
  SETUPDICLASSGUIDSFROMNAME* lpfnSETUPDICLASSGUIDSFROMNAME = reinterpret_cast<SETUPDICLASSGUIDSFROMNAME*>(GetProcAddress(setupAPI, "SetupDiClassGuidsFromNameA"));
  SETUPDIGETCLASSDEVS* lpfnSETUPDIGETCLASSDEVS = reinterpret_cast<SETUPDIGETCLASSDEVS*>(GetProcAddress(setupAPI, "SetupDiGetClassDevsA"));
  SETUPDIGETDEVICEREGISTRYPROPERTY* lpfnSETUPDIGETDEVICEREGISTRYPROPERTY = reinterpret_cast<SETUPDIGETDEVICEREGISTRYPROPERTY*>(GetProcAddress(setupAPI, "SetupDiGetDeviceRegistryPropertyA"));
#endif
  SETUPDIDESTROYDEVICEINFOLIST* lpfnSETUPDIDESTROYDEVICEINFOLIST = reinterpret_cast<SETUPDIDESTROYDEVICEINFOLIST*>(GetProcAddress(setupAPI, "SetupDiDestroyDeviceInfoList"));
  SETUPDIENUMDEVICEINFO* lpfnSETUPDIENUMDEVICEINFO = reinterpret_cast<SETUPDIENUMDEVICEINFO*>(GetProcAddress(setupAPI, "SetupDiEnumDeviceInfo"));

  if ((lpfnLPSETUPDIOPENDEVREGKEY == NULL) || (lpfnSETUPDICLASSGUIDSFROMNAME == NULL) || (lpfnSETUPDIDESTROYDEVICEINFOLIST == NULL) ||
      (lpfnSETUPDIENUMDEVICEINFO == NULL) || (lpfnSETUPDIGETCLASSDEVS == NULL) || (lpfnSETUPDIGETDEVICEREGISTRYPROPERTY == NULL))
  {
    //Set the error to report
    setupAPI.m_dwError = ERROR_CALL_NOT_IMPLEMENTED;

    return FALSE;
  }
  
  //First need to convert the name "Ports" to a GUID using SetupDiClassGuidsFromName
  DWORD dwGuids = 0;
  lpfnSETUPDICLASSGUIDSFROMNAME(_T("Ports"), NULL, 0, &dwGuids);
  if (dwGuids == 0)
  {
    //Set the error to report
    setupAPI.m_dwError = GetLastError();

    return FALSE;
  }

  //Allocate the needed memory
  ATL::CHeapPtr<GUID> pGuids;
  if (!pGuids.Allocate(dwGuids))
  {
    //Set the error to report
    setupAPI.m_dwError = ERROR_OUTOFMEMORY;

    return FALSE;
  }

  //Call the function again
  if (!lpfnSETUPDICLASSGUIDSFROMNAME(_T("Ports"), pGuids, dwGuids, &dwGuids))
  {
    //Set the error to report
    setupAPI.m_dwError = GetLastError();

    return FALSE;
  }

  //Now create a "device information set" which is required to enumerate all the ports
  HDEVINFO hDevInfoSet = lpfnSETUPDIGETCLASSDEVS(pGuids, NULL, NULL, DIGCF_PRESENT);
  if (hDevInfoSet == INVALID_HANDLE_VALUE)
  {
    //Set the error to report
    setupAPI.m_dwError = GetLastError();

    return FALSE;
  }

  //Finally do the enumeration
  BOOL bMoreItems = TRUE;
  int nIndex = 0;
  SP_DEVINFO_DATA devInfo;
  while (bMoreItems)
  {
    //Enumerate the current device
    devInfo.cbSize = sizeof(SP_DEVINFO_DATA);
    bMoreItems = lpfnSETUPDIENUMDEVICEINFO(hDevInfoSet, nIndex, &devInfo);
    if (bMoreItems)
    {
      //Did we find a serial port for this device
      BOOL bAdded = FALSE;

      //Get the registry key which stores the ports settings
      HKEY hDeviceKey = lpfnLPSETUPDIOPENDEVREGKEY(hDevInfoSet, &devInfo, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_QUERY_VALUE);
      if (hDeviceKey)
      {
        int nPort = 0;
        if (QueryRegistryPortName(hDeviceKey, nPort))
        {
        #if defined CENUMERATESERIAL_USE_STL
          ports.push_back(nPort);
        #else
          ports.Add(nPort);
        #endif  
          bAdded = TRUE;
        }

        //Close the key now that we are finished with it
        RegCloseKey(hDeviceKey);
      }

      //If the port was a serial port, then also try to get its friendly name
      if (bAdded)
      {
        TCHAR szFriendlyName[1024];
        szFriendlyName[0] = _T('\0');
        DWORD dwSize = sizeof(szFriendlyName);
        DWORD dwType = 0;
        if (lpfnSETUPDIGETDEVICEREGISTRYPROPERTY(hDevInfoSet, &devInfo, SPDRP_DEVICEDESC, &dwType, reinterpret_cast<PBYTE>(szFriendlyName), dwSize, &dwSize) && (dwType == REG_SZ))
        {
        #if defined CENUMERATESERIAL_USE_STL
          friendlyNames.push_back(szFriendlyName);
        #else
          friendlyNames.Add(szFriendlyName);
        #endif  
        }
        else
        {
        #if defined CENUMERATESERIAL_USE_STL
          friendlyNames.push_back(_T(""));
        #else
          friendlyNames.Add(_T(""));
        #endif  
        }
      }
    }

    ++nIndex;
  }

  //Free up the "device information set" now that we are finished with it
  lpfnSETUPDIDESTROYDEVICEINFOLIST(hDevInfoSet);

  //Return the success indicator
  return TRUE;
}
Example #2
0
BOOL CEnumerateSerial::EnumeratePorts()
{
  int SPDRPlist[] = {
    SPDRP_DEVICEDESC, SPDRP_FRIENDLYNAME, SPDRP_MFG, 
    SPDRP_LOCATION_INFORMATION, SPDRP_PHYSICAL_DEVICE_OBJECT_NAME, 
    -1};

  // Clear anything from previous enumerate...
  ResetPortList();

  // Dynamically get pointers to device installation library (setupapi.dll)
  // in case it isn't installed...
  //   SetupDiOpenDevRegKey
  //   SetupDiEnumDeviceInfo
  //   SetupDiDestroyDeviceInfoList
  //   SetupDiGetClassDevs
  //   SetupDiClassGuidsFromName
  //   SetupDiGetDeviceRegistryProperty 
  CLoadLib setupAPI(_T("SETUPAPI.DLL"));
  if (setupAPI == NULL) return FALSE;

#define SETUPPROC(x,y) x* lpfn##x = reinterpret_cast<x*>(GetProcAddress(setupAPI,y))
  SETUPPROC(SETUPDIOPENDEVREGKEY,"SetupDiOpenDevRegKey");
  SETUPPROC(SETUPDIENUMDEVICEINFO, "SetupDiEnumDeviceInfo");
  SETUPPROC(SETUPDIDESTROYDEVICEINFOLIST, "SetupDiDestroyDeviceInfoList");
#if defined _UNICODE
  SETUPPROC(SETUPDIGETCLASSDEVS, "SetupDiGetClassDevsW");
  SETUPPROC(SETUPDICLASSGUIDSFROMNAME, "SetupDiClassGuidsFromNameW");
  SETUPPROC(SETUPDIGETDEVICEREGISTRYPROPERTY, "SetupDiGetDeviceRegistryPropertyW");
#else
  SETUPPROC(SETUPDIGETCLASSDEVS, "SetupDiGetClassDevsA");
  SETUPPROC(SETUPDICLASSGUIDSFROMNAME, "SetupDiClassGuidsFromNameA");
  SETUPPROC(SETUPDIGETDEVICEREGISTRYPROPERTY, "SetupDiGetDeviceRegistryPropertyA");
#endif  
                       
  if ((lpfnSETUPDIOPENDEVREGKEY == NULL) || 
      (lpfnSETUPDIENUMDEVICEINFO == NULL) || 
      (lpfnSETUPDIGETDEVICEREGISTRYPROPERTY == NULL) ||
      (lpfnSETUPDIGETCLASSDEVS == NULL) || 
      (lpfnSETUPDICLASSGUIDSFROMNAME == NULL) || 
      (lpfnSETUPDIDESTROYDEVICEINFOLIST == NULL))
  {
    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
    return FALSE;
  }
  
  // First need to convert the name "Ports" to a GUID using SetupDiClassGuidsFromName...
  DWORD dwGuids = 0;
  lpfnSETUPDICLASSGUIDSFROMNAME(_T("Ports"), NULL, 0, &dwGuids);
  if (dwGuids == 0) return FALSE;

  // Allocate the needed memory...
  CHeapPtr<GUID> GuidArray;
  GUID *pGuids = (GUID*)GuidArray.Allocate(sizeof(GUID) * dwGuids);
  if (pGuids==NULL) {
    SetLastError(ERROR_OUTOFMEMORY);
    return FALSE;
  }

  // Call the function again...
  if (!lpfnSETUPDICLASSGUIDSFROMNAME(_T("Ports"), pGuids, dwGuids, &dwGuids))
    return FALSE;

  // Now create a "device information set" which is required to enumerate all the ports...
  HDEVINFO hDevInfoSet = lpfnSETUPDIGETCLASSDEVS(pGuids, NULL, NULL, DIGCF_PRESENT);
  if (hDevInfoSet == INVALID_HANDLE_VALUE)
    return FALSE;

  // Finally do the enumeration...
  int nIndex = 0;
  SP_DEVINFO_DATA devInfo;
  CHeapPtr<TCHAR> tempstr(256);
  CSerialPortInfo *portinfo = NULL;

  // Enumerate the current device...
  devInfo.cbSize = sizeof(SP_DEVINFO_DATA);
  while (lpfnSETUPDIENUMDEVICEINFO(hDevInfoSet, nIndex, &devInfo))
  {
    portinfo = NULL;

    // Get the registry key which stores the ports settings...
    HKEY hDeviceKey = lpfnSETUPDIOPENDEVREGKEY(hDevInfoSet, &devInfo, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_QUERY_VALUE);
    if (hDeviceKey) {
      tempstr.FillZero();
      DWORD dwSize = tempstr.SizeOf(); 
      DWORD dwType = 0;

      // Read name of port.  If formatted as "COMxx" then allocate a port slot...
  	  if ((RegQueryValueEx(hDeviceKey, _T("PortName"), NULL, &dwType, reinterpret_cast<LPBYTE>((TCHAR*)tempstr), &dwSize) == ERROR_SUCCESS) && (dwType == REG_SZ))
        if (_tcslen(tempstr) > 3)
          if ((_tcsnicmp(tempstr, _T("COM"), 3) == 0) && IsNumber(&(tempstr[3])))
            portinfo = AddPort(_ttoi(&(tempstr[3])));

      // Close the key now that we are finished with it...
      RegCloseKey(hDeviceKey);
    }

    // If a serial port, then try getting additional useful descriptive info...
    if (portinfo) {
      for (int i=0; SPDRPlist[i]>=0; i++) {
        tempstr.FillZero(); 
        DWORD dwSize = tempstr.SizeOf(); 
        DWORD dwType = 0;
        if (lpfnSETUPDIGETDEVICEREGISTRYPROPERTY(hDevInfoSet, &devInfo, SPDRPlist[i], &dwType, reinterpret_cast<PBYTE>((TCHAR*)tempstr), dwSize, &dwSize) && (dwType == REG_SZ))
          switch (SPDRPlist[i]) {
            case SPDRP_MFG : portinfo->SetManufacturer(tempstr); break;
            case SPDRP_DEVICEDESC : portinfo->SetDeviceDesc(tempstr); break;
            case SPDRP_FRIENDLYNAME : portinfo->SetFriendlyName(tempstr); break;
            case SPDRP_LOCATION_INFORMATION : portinfo->SetLocationInfo(tempstr); break;
            case SPDRP_PHYSICAL_DEVICE_OBJECT_NAME : portinfo->SetPhysLocation(tempstr); break;
          }
      }

      // Get COM port properties...
      HANDLE hPort = ::CreateFile(portinfo->GetPortDeviceName(), GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
      if (hPort != INVALID_HANDLE_VALUE) {
        COMMPROP cp;
        GetCommProperties(hPort, &cp);
        portinfo->SetCommProp(cp);
        TRACE ("Port %d:  CommProp: maxbaud=%08x  settablebaud=%08x\n",portinfo->GetPortNum(),cp.dwMaxBaud,cp.dwSettableBaud);
        CloseHandle(hPort);
      }
    }
    
    ++nIndex;
  }

  // Free up the "device information set" now that we are finished with it
  lpfnSETUPDIDESTROYDEVICEINFOLIST(hDevInfoSet);


  // Return the success indicator
  return TRUE;
}