Jake Niledon
Jake Niledon

Reputation: 13

Issue with converting a filesystem path to a const BYTE*

What I'm trying to achieve is getting my program executed on Windows startup using the Registry. When I try to put the file location, the compiler complains it cannot convert from filesystem::path to const BYTE*. I have no idea how to fix this, since I'm a beginner when it comes to C++. I have provided the code below:

HKEY newValue;
RegOpenKey(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Run", &newValue);
RegSetValueEx(newValue, "myprogram", 0, REG_SZ, fs::temp_directory_path().append(filename), sizeof("tes3t")); // This line is the issue. fs::temp_directory_path().append(filename)
RegCloseKey(newValue);
return 0;

EXCEPTION: No suitable conversion function from "std:filesystem::path" to "const BYTE *" exists

Upvotes: 1

Views: 249

Answers (2)

Remy Lebeau
Remy Lebeau

Reputation: 597156

Per the RegSetValueExA() documentation, the function does not accept a std::filesystem::path object. That is what the error message is complaining about.

LSTATUS RegSetValueExA(
  HKEY       hKey,
  LPCSTR     lpValueName,
  DWORD      Reserved,
  DWORD      dwType,
  const BYTE *lpData, // <-- here
  DWORD      cbData
);

The 5th parameter takes a const BYTE* pointer to a null-terminated C-style string. The 6th parameter takes the number of characters in the string, including the null terminator:

lpData

The data to be stored.

For string-based types, such as REG_SZ, the string must be null-terminated. With the REG_MULTI_SZ data type, the string must be terminated with two null characters.

Note lpData indicating a null value is valid, however, if this is the case, cbData must be set to '0'.

cbData

The size of the information pointed to by the lpData parameter, in bytes. If the data is of type REG_SZ, REG_EXPAND_SZ, or REG_MULTI_SZ, cbData must include the size of the terminating null character or characters.

std::filesystem::path does not have an implicit conversion to const BYTE*, hence the compiler error. You need to explicitly convert the path to a std::string or std::wstring first (prefer the latter, since the Registry stores strings as Unicode internally), before you can then save that string value to the Registry, eg:

// using std::string...

HKEY newValue;

// don't use RegOpenKey()! It is provided only for backwards compatibility with 16bit apps...
if (RegOpenKeyExA(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Run", 0, KEY_SET_VALUE, &newValue) == 0)
{
    // this may lose data for non-ASCII characters!
    std::string s = fs::temp_directory_path().append(filename).string();

    // this will convert the ANSI string to Unicode for you...
    RegSetValueExA(newValue, "myprogram", 0, REG_SZ, reinterpret_cast<LPCBYTE>(s.c_str()), s.size()+1);

    RegCloseKey(newValue);
}

return 0;
// using std::wstring...

HKEY newValue;

// don't use RegOpenKey()! It is provided only for backwards compatibility with 16bit apps...
if (RegOpenKeyExW(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\Run", 0, KEY_SET_VALUE, &newValue) == 0)
{
    // no data loss here!
    std::wstring s = fs::temp_directory_path().append(filename).wstring();

    // no ANSI->Unicode conversion is performed here...
    RegSetValueExW(newValue, L"myprogram", 0, REG_SZ, reinterpret_cast<LPCBYTE>(s.c_str()), (s.size()+1) * sizeof(WCHAR));

    RegCloseKey(newValue);
}

return 0;

Upvotes: 2

Ted Lyngmo
Ted Lyngmo

Reputation: 117563

The WinAPI functions do not take arguments of std::filesystem::path type so you need to convert it to a const BYTE* somehow.

This is one example:

std::string fullpath = (fs::temp_directory_path() / filename).string();

RegSetValueEx(
    newValue,
    "myprogram",
    0,
    REG_SZ,
    reinterpret_cast<LPCBYTE>(fullpath.c_str()), // returns a "const char*" then cast
    fullpath.size() + 1  // + 1 for null terminator
);

Upvotes: 2

Related Questions