7

I am writing a program to edit the windows registry key by C++, but when I try to pass a string value to library function RegSetValueEx(), there is a file start with TEXT() which could only be hardcode value in it.

Parts of my code:

string region;
string excelserver_type;
string keyname = region + excelserver_type;

if (RegSetValueEx(key64, TEXT("XXXXXXXXX"), 0, REG_SZ, (LPBYTE)TEXT("XXXXXXXXXX"), 100) != ERROR_SUCCESS)

{
            RegCloseKey(key);
            cout << "Unable to set registry value in HKEY_LOCAL_MACHINE\\Software" << endl;
        }

When I try to replace "XXXXXXXX" by keyname, it gives me an error. How do I pass value of keyname in RegSetValueEx()?

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
Raul Lam
  • 93
  • 1
  • 5

1 Answers1

6

You need to use the std::wstring type instead. This will give you a wide (Unicode) string, based on the wchar_t type, which is how Windows stores strings internally.

Then, you can simply use the c_str() member function to retrieve a pointer to a C-style string, and pass this directly to the RegSetValueEx function. The size() member function gives you the length of the string, which you can pass as the cbData parameter, except for two caveats:

  • cbData expects the length of the string to include the terminating NUL character, so you will need to add 1 to the length returned by size().
  • cbData expects the size of the string in bytes, not the number of characters, so for a wide string, you will need to multiply the value returned by size() by the length of a wchar_t.
bool SetStringValue(HKEY                hRegistryKey,
                    const std::wstring& valueName,
                    const std::wstring& data)
{
    assert(hRegistryKey != nullptr);

    return (RegSetValueExW(hRegistryKey,
                           valueName.c_str(),
                           0,
                           REG_SZ,
                           (LPBYTE)(data.c_str()),
                           (data.size() + 1) * sizeof(wchar_t)) == ERROR_SUCCESS);
}

If you absolutely have to use narrow (ANSI) strings (and you shouldn't, because you're interfacing directly with the operating system here, not working with user data), you can do the same thing but explicitly call the ANSI version of RegSetValueEx, which has an A suffix. Here, you still need to add 1 to the length, but the size in bytes is equivalent to the number of characters, so no scaling is necessary.

bool SetStringValue_ANSI(HKEY                hRegistryKey,
                         const std::string& valueName,
                         const std::string& data)
{
    assert(hRegistryKey != nullptr);

    return (RegSetValueExA(hRegistryKey,
                           valueName.c_str(),
                           0,
                           REG_SZ,
                           (LPBYTE)(data.c_str()),
                           data.size() + 1) == ERROR_SUCCESS);
}

Internally, RegSetValueExA will convert the string to Unicode and then perform the same task as RegSetValueExW.

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
  • 1
    Ack! One of the only APIs that requires a size in bytes. Totally blundered on that one. Thanks @David and Bo. – Cody Gray - on strike Jan 03 '17 at 08:47
  • I have completed the c++ program and i would like it to run as a .exe program in other windows 7 computer. I copied the .exe from the path C:\Users\Administrator\Documents\Visual Studio 2015\Projects\ConsoleApplication1\x64\Debug to other windows 7 computer. But when I try to open the .exe, it gives error "the program can't start because MSVCP140D.dll is missing from your computer". I don't want to install MS visual studio on other windows 7 computers, how do I solve this problem? – Raul Lam Jan 04 '17 at 03:23
  • You are trying to use the Debug build. You will need to transfer the Release build to the other computer. You will probably also need to install the VS 2015 Runtime. See [this answer](http://stackoverflow.com/questions/16083253/how-to-deploy-a-win32-api-application-as-an-executable/16096421#16096421), just change the version numbers. @raul – Cody Gray - on strike Jan 04 '17 at 11:17
  • Yes, I will choose the static linking method since my coding is simple. Thanks a lot for your suggestion. – Raul Lam Jan 05 '17 at 05:13
  • The last job is how to make the executable run as admin privilege when I double click it? How can I embedded the administrator password in coding? Because this executable is designed for normal users in domain. And normally executable is not allowed to be run by users. – Raul Lam Jan 05 '17 at 05:37
  • @raul You can include a manifest that indicates the application requires elevation, but you cannot make it automatically elevate itself when running on accounts without administrative privileges. That would be a security hole. Why does it need to run with administrative privileges? – Cody Gray - on strike Jan 05 '17 at 06:00
  • because we want to allow users to edit registry key value in a specific registry folder path only and this could save our time for supporting them. Is there any solution for users just double-click the executable which did not require asking admin privilege? It will be much more user-friendly for this approach. – Raul Lam Jan 06 '17 at 02:59
  • Users always have permission to edit registry keys that they own (e.g., in HKEY_CURRENT_USER), no elevation required. You only need elevation if you want to edit system-level keys, and if you need a non-privileged user to do this, there is a design flaw in your application. No, there's no way that non-privileged users can double-click an executable and perform administrative tasks without prompting. If you did find a way, it would be a security hole, and you would have written malware. @raul – Cody Gray - on strike Jan 06 '17 at 05:31
  • Is there any other method to call the exe to run? Such as making a separate program run as admin mode to all the executable? – Raul Lam Jan 10 '17 at 07:05
  • Yes, @raul. If you elevate the parent process, then its child processes can be elevated without prompting. But that parent process is still going to show a UAC dialog or otherwise require the user to authenticate as an administrator. – Cody Gray - on strike Jan 10 '17 at 09:42
  • I use AutoHot Key program to create an exe and embed the domain admin and password, the exe from AutoHot Key call the exe of C++ and the registry key value can be set automatically. – Raul Lam Feb 06 '17 at 10:06
  • Oh boy. A hard-coded password! That is neither secure, nor maintainable once the user changes their password. Well, whatever works for you. It isn't my system running this code, thank goodness. – Cody Gray - on strike Feb 06 '17 at 12:30
  • The password is embedded in an executable by using AutoHotKey. Is there any method to decompile or decrypt it so the password will be known by other people? – Raul Lam Feb 07 '17 at 05:20
  • Of course there is. It is trivial, in fact. Any decompiler can do it, or even a hex editor. @raul – Cody Gray - on strike Feb 07 '17 at 10:12