|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166 |
- #if defined(OS_WINDOWS)
-
- struct SSerInfo {
- CString strDevPath; // Device path for use with CreateFile()
- CString strPortName; // Simple name (i.e. COM1)
- CString strFriendlyName; // Full name to be displayed to a user
- CString strPortDesc; // friendly name without the COMx
- };
-
-
- void EnumSerialPorts(CArray<SSerInfo,SSerInfo&> &asi, BOOL bIgnoreBusyPorts)
- {
- // Clear the output array
- asi.RemoveAll();
- EnumPortsWdm(asi);
-
- for (int ii=0; ii<asi.GetSize(); ii++)
- {
- SSerInfo& rsi = asi[ii];
- if (bIgnoreBusyPorts) {
- // Only display ports that can be opened for read/write
- HANDLE hCom = CreateFile(rsi.strDevPath,
- GENERIC_READ | GENERIC_WRITE,
- 0, /* comm devices must be opened w/exclusive-access */
- NULL, /* no security attrs */
- OPEN_EXISTING, /* comm devices must use OPEN_EXISTING */
- 0, /* not overlapped I/O */
- NULL /* hTemplate must be NULL for comm devices */
- );
- if (hCom == INVALID_HANDLE_VALUE) {
- // It can't be opened; remove it.
- asi.RemoveAt(ii);
- ii--;
- continue;
- }
- else {
- // It can be opened! Close it and add it to the list
- ::CloseHandle(hCom);
- }
- }
-
- if (rsi.strFriendlyName.IsEmpty())
- {
- asi.RemoveAt(ii);
- ii--;
- continue;
- }
-
- CString fName = rsi.strFriendlyName;
- TCHAR *pt, *pt1;
- pt = fName.GetBuffer() + fName.GetLength() - 1;
- while (*pt != _T('('))
- {
- pt --;
- }
- if (_tcsncmp(pt, _T("(COM"), 4))
- {
- asi.RemoveAt(ii);
- ii--;
- continue;
- }
- rsi.strPortName.Empty();
- rsi.strPortName = _T("COM");
- pt1 = pt + 4;
- while ((*pt1>=_T('0')) && (*pt1<=_T('9')))
- {
- rsi.strPortName += *pt1++;
- }
-
- pt -= 2;
- pt1 = fName.GetBuffer();
- rsi.strPortDesc.Empty();
- while (pt1 <= pt)
- {
- rsi.strPortDesc += *pt1++;
- }
- }
- }
-
- void EnumPortsWdm(CArray<SSerInfo,SSerInfo&> &asi)
- {
- CString strErr;
- // Create a device information set that will be the container for
- // the device interfaces.
- GUID *guidDev = (GUID*) &GUID_CLASS_COMPORT;
-
- HDEVINFO hDevInfo = INVALID_HANDLE_VALUE;
- SP_DEVICE_INTERFACE_DETAIL_DATA *pDetData = NULL;
-
- try {
- hDevInfo = SetupDiGetClassDevs( guidDev,
- NULL,
- NULL,
- DIGCF_PRESENT | DIGCF_DEVICEINTERFACE
- );
-
- if(hDevInfo == INVALID_HANDLE_VALUE)
- {
- strErr.Format(_T("SetupDiGetClassDevs failed. (err=%lx)"),
- GetLastError());
- throw strErr;
- }
-
- // Enumerate the serial ports
- BOOL bOk = TRUE;
- SP_DEVICE_INTERFACE_DATA ifcData;
- DWORD dwDetDataSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA) + 256;
- pDetData = (SP_DEVICE_INTERFACE_DETAIL_DATA*) new char[dwDetDataSize];
- // This is required, according to the documentation. Yes,
- // it's weird.
- ifcData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
- pDetData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
- for (DWORD ii=0; bOk; ii++) {
- bOk = SetupDiEnumDeviceInterfaces(hDevInfo,
- NULL, guidDev, ii, &ifcData);
- if (bOk) {
- // Got a device. Get the details.
- SP_DEVINFO_DATA devdata = {sizeof(SP_DEVINFO_DATA)};
- bOk = SetupDiGetDeviceInterfaceDetail(hDevInfo,
- &ifcData, pDetData, dwDetDataSize, NULL, &devdata);
- if (bOk) {
- CString strDevPath(pDetData->DevicePath);
- // Got a path to the device. Try to get some more info.
- TCHAR fname[256];
- BOOL bSuccess = SetupDiGetDeviceRegistryProperty(
- hDevInfo, &devdata, SPDRP_FRIENDLYNAME, NULL,
- (PBYTE)fname, sizeof(fname), NULL);
- if (bSuccess) {
- // Add an entry to the array
- SSerInfo si;
- si.strDevPath = strDevPath;
- si.strFriendlyName = fname;
- asi.Add(si);
- }
-
- }
- else {
- strErr.Format(_T("SetupDiGetDeviceInterfaceDetail failed. (err=%lx)"),
- GetLastError());
- throw strErr;
- }
- }
- else {
- DWORD err = GetLastError();
- if (err != ERROR_NO_MORE_ITEMS) {
- strErr.Format(_T("SetupDiEnumDeviceInterfaces failed. (err=%lx)"), err);
- throw strErr;
- }
- }
- }
- }
- catch (CString strCatchErr) {
- strErr = strCatchErr;
- }
-
- if (pDetData != NULL)
- delete [] (char*)pDetData;
-
- if (hDevInfo != INVALID_HANDLE_VALUE)
- SetupDiDestroyDeviceInfoList(hDevInfo);
-
- if (!strErr.IsEmpty())
- throw strErr;
- }
- #endif /* OS_WINDOWS */
-
|