
EnumSerialPorts v1.24 A set of
functions to enumerate serial ports
One of the posts that keeps reappearing in the programming
newsgroups is how to enumerate all the serial ports installed.
The code uses a number of different
methods to enumerate the ports.
Features
- Simple C++ class interface.
- The code provides methods which support both Windows 9x and the Windows NT
kernel versions of Windows.
- The code is fully Unicode compliant and
includes Unicode built options in the solution file.
- Internally the code provides 9 different ways (yes you read that right:
Nine) of enumerating serial ports: Using CreateFile, QueryDosDevice,
GetDefaultCommConfig, two ways using the Setup API, EnumPorts, WMI, Com Database
& enumerating the values under the registry key HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\SERIALCOMM.
The enclosed zip file contains the EnumSerialPorts source code and a simple console based
application which exercises the functions.
Copyright
- You are allowed to include the source code in
any product (commercial, shareware, freeware or otherwise) when your product
is released in binary form.
- You are allowed to modify the source code in
any way you want except you cannot modify the copyright details at the top
of each module.
- If you want to distribute source code with
your application, then you are only allowed to distribute versions released
by the author. This is to maintain a single distribution point for the
source code.
Updates
v1.0 (3 November 1998)
v1.01 (23 February 1999)
- Code now uses QueryDosDevice if running on
NT to determine which serial ports are available. This avoids having to open the ports at
all. It should operate a lot faster in addition
v1.02 (12 December
1999)
- Fixed a problem in the Win9x code path when trying to
detect deactivated IRDA-ports. When trying to open those, you will get the
error-code ERROR_GEN_FAILURE.
v1.03 (17 May 2000)
- Code now uses GetDefaultCommConfig in all cases to
detect the ports.
v1.04 (29 March 2001)
- Reverted code to use CreateFile or QueryDosDevice as it
is much faster than using the GetDefaultCommConfig method.
- Updated copyright message.
v1.05 (25 June 2001)
-
Guess what, You now have the choice of
using the GetDefaultCommConfig thro the use of three versions of the
function. You take your pick.
-
Fixed problem where port fails to be
reported thro the CreateFile mechanism when the error code is
ERROR_SHARING_VIOLATION i.e. someone has the port already open.
v1.06 (11 August 2001)
v1.07 (13 August 2001)
v1.08 (22 May 2003)
v1.09 (20 September 2003)
v1.10 (12 December 2003)
- Updated the sample app to VC 6.
- Addition of a "EnumerateSerialPorts6" (See
Note 4 below) which uses WMI.
- You can now optionally exclude each function
using preprocessor defines of the form "NO_ENUMSERIAL_USING_XYX".
- Made the functions members of a C++ class and renamed
them to using more meaningful names
v1.11 (13 May 2004)
- Extended CEnumerateSerial::UsingSetupAPI to now also
return the friendly name of the port. Thanks to Jay C. Howard for prompting
this update.
v1.12 (9 July 2006)
- Updated copyright details.
- Addition of a CENUMERATESERIAL_EXT_CLASS macro to allow the code to be easily
added to an extension dll.
- Code now uses newer C++ style casts instead of C style casts.
- Updated the code to clean compile on VC 2005.
- Updated the documentation to use the same style as the web site.
v1.13 (8 November 2006)
- Extended CEnumerateSerial::UsingWMI to now also return the friendly name
of the port. Thanks to Giovanni Bajo for providing this update.
- Fixed a bug where CEnumerateSerial::UsingSetupAPI forget to empty out
the Friendly name array on start.
- VariantInit is now called for the 2 VARIANT structs used in the UsingWMI
method code.
v1.14 (29 January 2007)
- Updated copyright details.
- UsingSetupAPI code now uses the GUID_DEVINTERFACE_COMPORT guid to
enumerate COM ports. Thanks to David McMinn for reporting this nice
addition.
- Detection code which uses CreateFile call, now treats the error code of
ERROR_SEM_TIMEOUT as indication that a port is present.
v1.15 (9 June 2007)
- Following feedback from John Miles, it looks like my previous change of
the 29 January 2007 to use GUID_DEVINTERFACE_COMPORT in the UsingSetupAPI
method had the unintended consequence of causing this method not to work on
any versions of Windows prior to Windows 2000. What I have now done is
reinstate the old mechanism using the name UsingSetupAPI2 so that you can
continue to use this approach if you need to support NT 4 and Windows 9x.
The new approach of using GUID_DEVINTERFACE_COMPORT has been renamed to
UsingSetupAPI1.
v1.16 (5 July 2007)
- Updated the code to work if the code does not include MFC. In this case,
CUIntArray parameters becomes the ATL class CSimpleArray<UINT> and
CStringArray parameters become the ATL class CSimpleArray<CString>. Please
note that this support requires a recentish copy of Visual Studio and will
not support Visual C++ 6.0 as the code makes use of the ATL CString class.
Thanks to Michael Venus for prompting this update.
- CEnumerateSerial::UsingWMI method now uses ATL smart pointers to improve
robustness of the code.
v1.17 (20 March 2008)
- Updated copyright details
- Updates to preprocessor logic to correctly include UsingSetupAPI1 and
UsingSetupAPI2 functionality
- Updated sample app to clean compile on VC 2008
v1.18 (23 November 2008)
- Updated code to compile correctly using _ATL_CSTRING_EXPLICIT_CONSTRUCTORS
define
- The code now only supports VC 2005 or later.
- Code now compiles cleanly using Code Analysis (/analyze)
- Yes, Addition of a another method called "UsingComDB" to enumerate
serial ports!. This function uses the so called "COM Database" functions
which are part of the Windows DDK which device drivers can use to support
claiming an unused port number when the device driver is being installed.
Please note that the list returning from this function will only report used
port numbers. The device may or may not be actually present, just that the
associated port number is currently "claimed". Thanks to Dmitry Nikitin for
prompting this very nice addition. The code now supports a total of 8
different ways to enumerate serial ports!
v1.19 (29 November 2008)
- Addition of a ninth and hopefully final method to enumerate serial
ports. The function is called "UsingRegistry" and enumerates the ports by
examining the registry location at HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\SERIALCOMM.
Thanks to Martin Oberhuber for prompting this update.
- Fixed a bug where the last error value was not being preserved in
CEnumerateSerial::UsingComDB.
v1.20 (30 April 2009)
- Updated copyright details.
- Updated the sample app's project settings to more modern default values.
- Updated the sample app to log the time taken for the various methods.
v1.21 (27 March 2010)
- Updated copyright details.
- Code can now optionally use STL instead of MFC or ATL in the API. To use
STL containers instead of MFC or ATL versions, please define
CENUMERATESERIAL_USE_STL before you include enumser in your project. Please
note that the code still internally uses ATL in the UsingWMI method, but the
other functions do not. This means that the class should now be partly
compilable on VC Express (2005, 2008 or 2010) as none of these have support
for ATL or MFC. I do not personally have VC Express installed so people's
feedback on this would be appreciated. Thanks to Bill Adair for providing
this update.
v1.22 (28 March 2011)
- Updated copyright details.
- Updated the UsingComDB method to fix an off by one issue. This resulting
in the list of ports this function reported being incorrect. Thanks to "Jar,
Min, Jeong" for reporting this issue.
- Updated sample app to compile cleanly on VC 2010
v1.23 (15 October 2012)
- Updated copyright details.
- Code no longer uses LoadLibrary without an absolute path when loading
SETUPAPI and MSPORTS dlls. This avoids DLL planting security issues.
- Added a new internal CAutoHandle and CAutoHModule classes which makes
the implementation for CEnumerateSerial simpler
- Code now uses an internal RegQueryValueString method to ensure
that data returned from raw Win32 API call RegQueryValueEx is null
terminated before it is treated as such in the code. Thanks to Jeffrey
Walton for reporting this security issue.
- Updated the code to clean compile on VC 2012
v1.24 (10 January 2013)
- Updated copyright details
- Spun off CAutoHModule class into its own header file
- Spun off CAutoHandle class into its own header file
- Addition of a new CAutoHeapAlloc class which encapsulates HeapAlloc /
HeapFree calls in a C++ class.
- Removed ATL usage completely from UsingQueryDevice, UsingSetupAPI2 and
UsingEnumPorts. This should allow these methods to support compilers which
do not have support for ATL such as VC Express SKUs.