Why does the RegQueryValueEx() function return ERROR_FILE_NOT_FOUND while trying to read from a registry key?

killdaclick picture killdaclick · Dec 21, 2011 · Viewed 36.8k times · Source

System: Windows 7 32bit
Language: C++

I have tried to access register HKEY_LOCAL_MACHINE\\HARDWARE\\DEVICEMAP\\Scsi\\Scsi Port 0, key Driver (type REG_SZ) -- no problem.

The same for reading from HKEY_LOCAL_MACHINE\\HARDWARE\\DEVICEMAP\\SERIALCOMM, all keys (types REG_SZ) got slashes, for example \Device\Serial0.

While reading such keys it always returns 2 (no such file) with following example code:

HKEY hKey = 0;
DWORD dwType = REG_SZ;
char buf[255] = {0};
DWORD dwBufSize = sizeof(buf);

if( RegOpenKeyEx( HKEY_LOCAL_MACHINE, TEXT("HARDWARE\\DEVICEMAP\\SERIALCOMM"), 0, KEY_QUERY_VALUE, &hKey ) == ERROR_SUCCESS ) 
{
  auto ret = RegQueryValueEx( hKey, TEXT("\Device\Serial0"), 0, &dwType, (LPBYTE)buf, &dwBufSize );
  // ret always == 2 for key with slashes
--- CUT ---

What is the proper way to read key values with slashes in name?


Above has been properly answered by Cody Gray.
Below another issue.


Im getting the same problem when Im using variable instead of a text string.
Iv considered both approaches with single and double slashes:

HKEY hKey = 0;
DWORD keyType = REG_SZ;
TCHAR buf[255] = {0};
DWORD bufSize = sizeof(buf);

QSettings winReg("HKEY_LOCAL_MACHINE\\HARDWARE\\DEVICEMAP\\SERIALCOMM", QSettings::NativeFormat);
auto comsKey = winReg.allKeys();

FOREACH( auto com, comsKey )
{
  // FOREACH - boost macro
  // comsKey = QList<QString> (list of key names) [from Qt framework]
  // com = QString (single key name) [from Qt framework]
  if( RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("HARDWARE\\DEVICEMAP\\SERIALCOMM"), 0, KEY_QUERY_VALUE, &hKey ) == ERROR_SUCCESS )
  {
    wchar_t* keyw = new wchar_t();
    //com.replace("/", "\\\\"); <- checked both variants commented and not commented; com == /Device/Serial0 so im converting to \\Device\\Serial0
    int size = com.size();
    mbstowcs( keyw, com.toStdString().data(), size );
    //auto ret = RegQueryValueEx( hKey, TEXT("\\Device\\Serial0"), 0, &keyType, (LPBYTE)buf, &bufSize ); // <- this works!
    auto ret = RegQueryValueExW( hKey, (LPCWSTR)&keyw, 0, &keyType, (LPBYTE)buf, &bufSize ); // <- this one not works!

I have tried all variants with "\Device..", "/Device", "\Device", etc.

Answer

Cody Gray picture Cody Gray · Dec 21, 2011

You have to escape the slashes, just like you did in the first line...

if( RegOpenKeyEx( HKEY_LOCAL_MACHINE, TEXT("HARDWARE\\DEVICEMAP\\SERIALCOMM"), 0, KEY_QUERY_VALUE, &hKey ) == ERROR_SUCCESS ) 
{
  auto ret = RegQueryValueEx( hKey, TEXT("\\Device\\Serial0"), 0, &dwType, (LPBYTE)buf, &dwBufSize );
  // ret always == 2 for key with slashes

If you don't, the RegQueryValueEx function can't find the specified key, and it returns ERROR_FILE_NOT_FOUND (== 2).


But there's another problem. You should be declaring the buffer array as type wchar_t (or TCHAR), rather than char:

TCHAR buf[255] = {0};

Otherwise, the RegQueryValueEx function is going to attempt to fill the array with a Unicode string read from the specified registry key, and you're going to get something unreadable.