Home > other >  C: Windows not finding HARDWARE\DEVICEMAP\SERIALCOMM even though it can be found using regedit
C: Windows not finding HARDWARE\DEVICEMAP\SERIALCOMM even though it can be found using regedit

Time:03-08

I want to list the COM ports (like one can see in 'Device Manager'), but at runtime.

I shamelessly copied the code from this site (code shown at end of post), and I think I understand it. However, the program fails at line 36, giving me the error:

Failed to open key 'HARDWARE\DEVICEMAP\SERIALCOMM' 
Windows reports error: (0x00000002): The system cannot find the file specified.

If I open the registry editor I clearly see the folder, and when I click it, I see the device I have connected to my computer.

I've compiled the code using MinGW and the command gcc filename.c

Any ideas on how to fix this? Might it be a permission issue? Is there some compiler flag that gcc needs for me to be able to use it?


The code I am running is this:

#define WIN32_LEAN_AND_MEAN  // excludes stuff frokm windows.h that we won't need here.
#include <Windows.h>
#include <string.h>
#include <tchar.h>
#include <malloc.h>

void ShowErrorFromLStatus(LSTATUS lResult)
{
    LPTSTR psz;
    FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
        NULL,
        lResult,
        0,
        (LPTSTR)&psz,
        1024,
        NULL);

    _tprintf(_T("Windows reports error: (0xX): %s\n"), lResult, (psz) ? psz : _T("(null)"));
    if (psz)
    {
        LocalFree(psz);
    }
}

int main()
{
    DWORD nValues, nMaxValueNameLen, nMaxValueLen;
    HKEY hKey = NULL;
    LPTSTR szDeviceName = NULL;
    LPTSTR szFriendlyName = NULL;
    DWORD dwType = 0;
    DWORD nValueNameLen = 0;
    DWORD nValueLen = 0;
    DWORD dwIndex = 0;

    LSTATUS lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"HARDWARE\\DEVICEMAP\\SERIALCOMM", 0, KEY_READ, &hKey);
    if (ERROR_SUCCESS != lResult)
    {
        printf("Failed to open key \'HARDWARE\\DEVICEMAP\\SERIALCOMM\' \n");
        ShowErrorFromLStatus(lResult);
        return 1;
    }

    lResult = RegQueryInfoKey(hKey, NULL, NULL, NULL, NULL, NULL, NULL,
        &nValues, &nMaxValueNameLen, &nMaxValueLen, NULL, NULL);

    if (ERROR_SUCCESS != lResult)
    {
        _tprintf(_T("Failed to RegQueryInfoKey()\n"));
        ShowErrorFromLStatus(lResult);
        RegCloseKey(hKey);
        return 2;
    }

    szDeviceName = (LPTSTR)malloc(nMaxValueNameLen   sizeof(TCHAR));
    if (!szDeviceName)
    {
        _tprintf(_T("malloc() fail\n"));
        RegCloseKey(hKey);
        return 3;
    }

    szFriendlyName = (LPTSTR)malloc(nMaxValueLen   sizeof(TCHAR));
    if (!szFriendlyName)
    {
        free(szDeviceName);
        _tprintf(_T("malloc() fail\n"));
        RegCloseKey(hKey);
        return 3;
    }

    _tprintf(_T("Found %d serial device(s) registered with PnP and active or available at the moment.\n"), nValues);

    for (DWORD dwIndex = 0; dwIndex < nValues;   dwIndex)
    {
        dwType = 0;
        nValueNameLen = nMaxValueNameLen   sizeof(TCHAR);
        nValueLen = nMaxValueLen   sizeof(TCHAR);

        lResult = RegEnumValueW(hKey, dwIndex, 
            szDeviceName, &nValueNameLen,
            NULL, &dwType, 
            (LPBYTE)szFriendlyName, &nValueLen);

        if (ERROR_SUCCESS != lResult || REG_SZ != dwType)
        {
            _tprintf(_T("SerialPortEnumerator::Init() : can't process registry value, index: %d\n"), dwIndex);
            ShowErrorFromLStatus(lResult);
            continue;
        }
        _tprintf(_T("Found port \'%s\': Device name for CreateFile(): \'\\.%s\'\n"), szFriendlyName, szDeviceName);
    }

    free(szDeviceName);
    free(szFriendlyName);
    RegCloseKey(hKey);
    return 0;
}

EDIT

I'm now calling RegOpenKeyEx with _T("HARDWARE\\DEVICEMAP\\SERIALCOMM"), and in the call to RegEnumValueW on line 81, I casted szDeviceName to a LPWSTR. gcc no longer gives any errors or warnings. However, when running the program, all that comes out is

Found 1 serial device(s) registered with PnP and active or available at the moment.
Found port 'C': Device name for CreateFile(): '\.\'

And the port I have connected (COM3) does not show up.

Any other advice?

CodePudding user response:

Thank you to Simon Mourier and Ian Abbott!

As stated in the edit, calling RegOpenKeyEx with _T("HARDWARE\\DEVICEMAP\\SERIALCOMM") and casting szDeviceName to a LPWSTR fixed all errors.

Further, using the identifier %ls in the call to _tprintf() on line 92 made the names print correctly.


The final, working code looks like this:

#define WIN32_LEAN_AND_MEAN  // excludes stuff frokm windows.h that we won't need here.
#include <Windows.h>
#include <string.h>
#include <tchar.h>
#include <malloc.h>
#include <stdio.h>

void ShowErrorFromLStatus(LSTATUS lResult)
{
    LPTSTR psz;
    FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
        NULL,
        lResult,
        0,
        (LPTSTR)&psz,
        1024,
        NULL);

    _tprintf(_T("Windows reports error: (0xX): %s\n"), lResult, (psz) ? psz : _T("(null)"));
    if (psz)
    {
        LocalFree(psz);
    }
}

int main()
{
    DWORD nValues, nMaxValueNameLen, nMaxValueLen;
    HKEY hKey = NULL;
    LPTSTR szDeviceName = NULL;
    LPTSTR szFriendlyName = NULL;
    DWORD dwType = 0;
    DWORD nValueNameLen = 0;
    DWORD nValueLen = 0;
    DWORD dwIndex = 0;

    LSTATUS lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("HARDWARE\\DEVICEMAP\\SERIALCOMM"), 0, KEY_READ, &hKey);
    if (ERROR_SUCCESS != lResult)
    {
        printf("Failed to open key \'HARDWARE\\DEVICEMAP\\SERIALCOMM\' \n");
        ShowErrorFromLStatus(lResult);
        return 1;
    }

    lResult = RegQueryInfoKey(hKey, NULL, NULL, NULL, NULL, NULL, NULL,
        &nValues, &nMaxValueNameLen, &nMaxValueLen, NULL, NULL);

    if (ERROR_SUCCESS != lResult)
    {
        _tprintf(_T("Failed to RegQueryInfoKey()\n"));
        ShowErrorFromLStatus(lResult);
        RegCloseKey(hKey);
        return 2;
    }

    szDeviceName = (LPTSTR)malloc(nMaxValueNameLen   sizeof(TCHAR));
    if (!szDeviceName)
    {
        _tprintf(_T("malloc() fail\n"));
        RegCloseKey(hKey);
        return 3;
    }

    szFriendlyName = (LPTSTR)malloc(nMaxValueLen   sizeof(TCHAR));
    if (!szFriendlyName)
    {
        free(szDeviceName);
        _tprintf(_T("malloc() fail\n"));
        RegCloseKey(hKey);
        return 3;
    }

    _tprintf(_T("Found %d serial device(s) registered with PnP and active or available at the moment.\n"), nValues);

    for (DWORD dwIndex = 0; dwIndex < nValues;   dwIndex)
    {
        dwType = 0;
        nValueNameLen = nMaxValueNameLen   sizeof(TCHAR);
        nValueLen = nMaxValueLen   sizeof(TCHAR);

        lResult = RegEnumValueW(hKey, dwIndex, 
            (LPWSTR)szDeviceName, &nValueNameLen,
            NULL, &dwType, 
            (LPBYTE)szFriendlyName, &nValueLen);

        if (ERROR_SUCCESS != lResult || REG_SZ != dwType)
        {
            _tprintf(_T("SerialPortEnumerator::Init() : can't process registry value, index: %d\n"), dwIndex);
            ShowErrorFromLStatus(lResult);
            continue;
        }
        _tprintf(_T("Found port \'%ls\': Device name for CreateFile(): \'\\.%ls\'\n"), szFriendlyName, szDeviceName);
    }

    free(szDeviceName);
    free(szFriendlyName);
    RegCloseKey(hKey);
    return 0;
}
  • Related