My winreg function is not being recognized - c++

The error:
error: no matching function for call to 'RegCreateKeyExW'
What I am including:
#include <iostream>
#include <Windows.h>
#include <stdio.h>
#include <string>
#include <winreg.h>
My code:
HKEY hKey;
LONG result = 0;
char *path = "SYSTEM\\CurrentControlSet\\Control\\IDConfigDB\\Hardware Profiles\\0001";
if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, path, 0, NULL,
REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, NULL) == ERROR_SUCCESS) {
printf("2. success \n");
} else {
printf("fail\n");
}
I have tried everything but this error won't vanish, I would aprecciate if someone could help me!

You are calling the TCHAR version of RegCreateKeyEx(). It is clear from the error message that RegCreateKeyEx() is resolving to the Unicode version, RegCreateKeyExW() (because UNICODE is defined in your build config). That version takes in a wide wchar_t string as input, but you are passing in a narrow char string instead.
You can either:
use a TCHAR string, to match the TCHAR function your code is calling:
const TCHAR* path = TEXT("SYSTEM\\CurrentControlSet\\Control\\IDConfigDB\\Hardware Profiles\\0001");
use a Unicode string, to match the Unicode function actually being called at runtime:
const wchar_t *path = L"SYSTEM\\CurrentControlSet\\Control\\IDConfigDB\\Hardware Profiles\\0001";
use the ANSI version of the function, RegCreateKeyExA(), to match your original string:
if (RegCreateKeyExA(...) == ERROR_SUCCESS) {

Related

Error writing to Windows 10 registry with WindowsAPI/C (strange situation)

I am trying to write to my Windows 10 registry, to include a program in Startup.
At the moment I have written the following code, which is not wroking:
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <winnt.h>
#include <winreg.h>
int main()
{
const TCHAR* path = TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run");
LPDWORD holdResult;
PHKEY hKey;
int lResult;
//lResult = RegOpenKeyEx(HKEY_CURRENT_USER, path, 0, KEY_READ, &hKey);
lResult = RegCreateKeyExA(HKEY_CURRENT_USER, "myprogram", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, &holdResult);
if (lResult != ERROR_SUCCESS)
{
if (lResult == ERROR_FILE_NOT_FOUND) {
printf("Key not found.\n");
return TRUE;
}
else {
printf("Error opening key.\n");
return FALSE;
}
}
printf("Key already existed or not: %p\n", holdResult);
char* szPath = "C:\\Users\\Myname\\Documents\\coolprogram.exe";
lResult = RegSetValueExA(hKey, "program", 0, REG_SZ,(LPBYTE)szPath, sizeof(wchar_t)*(wcslen(szPath)+1));
printf("Key successfully set or not: %d\n", lResult);
RegCloseKey(hKey);
return 0;
}
The strange thing is, although the code does not write anything to the registry, I get no error message, and the program executes as successful!
This is what gets printed to the terminal when I run the code:
Key already existed or not: 0000000000000002
Key successfully set or not: 0
So, the key had already been previously created, and was succesfully set, which did not happen, there is nothing in my registry.
I believe this is a permissions problem, because for some reason I cannot alter my registry permissions manually, even after setting myself as owner, it is impossible for me to allow "Full Control" to myself.
But I expected some sort of error, such as "ACCESS DENIED: INSUFFICIENT PERMISSIONS", but I am getting a success. Strange.
You are passing the wrong key path to RegCreateKeyEx(). You are trying to write your program value to HKCU\myprogram rather than to HKCU\SOFTWARE\Microsoft\...\Run.
You are also passing invalid pointers to RegCreateKeyEx(). Its last 2 parameters expect pointers to HKEY and DWORD variables, but you are passing in pointers to HKEY* and DWORD* variables instead.
You are also passing an incorrect parameter to RegSetValueExA(), too. You are giving it an ANSI string (OK, since it is an ANSI function), but are passing in a Unicode string length that is 2x the byte size of the actual ANSI string (bad).
In fact, your code shouldn't even compile as shown.
Try this instead:
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <winnt.h>
#include <winreg.h>
int main()
{
const char* szKey = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run";
const char* szPath = "C:\\Users\\Myname\\Documents\\coolprogram.exe";
DWORD dwDisposition;
HKEY hKey;
LSTATUS lResult;
//lResult = RegOpenKeyExA(HKEY_CURRENT_USER, szKey, 0, KEY_QUERY_VALUE, &hKey);
lResult = RegCreateKeyExA(HKEY_CURRENT_USER, szKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &hKey, &dwDisposition);
if (lResult != ERROR_SUCCESS)
{
printf("Error creating key: %ld\n", lResult);
return 0;
}
printf("Key already existed or not: %lu\n", dwDisposition);
lResult = RegSetValueExA(hKey, "program", 0, REG_SZ, (LPBYTE)szPath, sizeof(TCHAR)*(strlen(szPath)+1));
printf("Key successfully set or not: %ld\n", lResult);
RegCloseKey(hKey);
return 0;
}

argument of type "WCHAR *" is incompatible with parameter of type "LPCSTR" in c++

I know that there are lots of questions like this as it is a common error, I also know it is happening because I am using unicode. However, after reading through SO/microsoft docs and fixing the code, it still does not seem to work and I am stumped.
The code is as follows:
#include <Windows.h>
#include <Tlhelp32.h>
#include <string>
DWORD find_pid(const char* procname) {
// Dynamically resolve some functions
HMODULE kernel32 = GetModuleHandleA("Kernel32.dll");
using CreateToolhelp32SnapshotPrototype = HANDLE(WINAPI *)(DWORD, DWORD);
CreateToolhelp32SnapshotPrototype CreateToolhelp32Snapshot = (CreateToolhelp32SnapshotPrototype)GetProcAddress(kernel32, "CreateToolhelp32Snapshot");
using Process32FirstPrototype = BOOL(WINAPI *)(HANDLE, LPPROCESSENTRY32);
Process32FirstPrototype Process32First = (Process32FirstPrototype)GetProcAddress(kernel32, "Process32First");
using Process32NextPrototype = BOOL(WINAPI *)(HANDLE, LPPROCESSENTRY32);
Process32NextPrototype Process32Next = (Process32NextPrototype)GetProcAddress(kernel32, "Process32Next");
// Init some important local variables
HANDLE hProcSnap;
PROCESSENTRY32 pe32;
DWORD pid = 0;
pe32.dwSize = sizeof(PROCESSENTRY32);
// Find the PID now by enumerating a snapshot of all the running processes
hProcSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (INVALID_HANDLE_VALUE == hProcSnap)
return 0;
if (!Process32First(hProcSnap, &pe32)) {
CloseHandle(hProcSnap);
return 0;
}
while (Process32Next(hProcSnap, &pe32)) {
//--->here is offending code...
if (lstrcmpiA(procname, pe32.szExeFile) == 0) {
pid = pe32.th32ProcessID;
break;
}
}
// Cleanup
CloseHandle(hProcSnap);
return pid;
}
I changed the code to this:
if (strcmp(procname, pe32.szExeFile) == 0) {
pid = pe32.th32ProcessID;
break;
}
but still get the same error. Any ideas?
PROCESSENTRY32 uses wchars when you define UNICODE. The doc's are probably misleading.
Tlhelp32.h defines this:
#ifdef UNICODE
#define Process32First Process32FirstW
#define Process32Next Process32NextW
#define PROCESSENTRY32 PROCESSENTRY32W
#define PPROCESSENTRY32 PPROCESSENTRY32W
#define LPPROCESSENTRY32 LPPROCESSENTRY32W
#endif // !UNICODE
As you can see, PROCESSENTRY32 maps to PROCESSENTRY32W if UNICODE is defined.
pe32.szExeFile is a WCHAR szExeFile[MAX_PATH]; // Path
That is the reason why strcmp fails with the error you get. strcmp expects a char* but you pass pe32.szExeFile, which in your case is a WCHAR*.
Take real care to get the correct pointers to the helper functions. Are you getting the ANSI or UNICODE pointers? You are using a lot of C-style casts in the GetProcAddress calls. You can easily end up casting the return value to an ANSI style function, but using the UNICODE style pointer type.

C++ RegSetValueEx is giving problems

I'm using RegSetValueEx to set a Registry key. The problem is that it only writes the first 2 characters. I can get the RegSetValueExA (ANSI version) to work, but my Project is set to Unicode in properties so I would like to use either RegSetValueEx or RegSetValueExW.
#include <iostream>
#include <Windows.h>
HKEY hKey;
int main()
{
RegCreateKeyEx(HKEY_CURRENT_USER, L"SOFTWARE\\stuff", 0, NULL, NULL, KEY_ALL_ACCESS, NULL, &hKey, NULL);
RegSetValueEx(hKey, L"Test", 0, REG_SZ, (const BYTE*)L"test", strlen("test"));
system("PAUSE");
return 0;
}
Output in registry is "te" instead of "test".
The final parameter to RegSetValueEx has to be the size in bytes of the value, including the terminating null. You're giving the length in characters (and each character needs two bytes) and not including the null.
sizeof(L"test") would work, I think, or you could use (strlen("test")+1) * sizeof(wchar_t)
See https://msdn.microsoft.com/en-us/library/windows/desktop/ms724923(v=vs.85).aspx

error when i tried opening a website with windows.h library

#include<iostream>
#include <windows.h>
#include<string>
using namespace std;
int main()
{
cout << "Opening Google...";
ShellExecute(NULL, L"open", L"https://www.google.com",NULL, NULL, SW_SHOWNORMAL);
return 0;
}
I get this error: Cannot convert 'const wchart_t*' to 'LPCSTR{aka const char*}\ for argument '2' to 'HINSTANCE_*SHellExecuteA(HWND,LPCSTR,LPCSTR, LPCSTR, LPCSTR, INT)'
You have 2 capabilities:
As #chris noted, you can compile you program with UNICODE defined
You can use special macros for string literals for more flexibility
ShellExecute(NULL,
TEXT("open"),
TEXT("https://www.google.com"),
NULL,
NULL,
SW_SHOWNORMAL);

C++: convert LPTSTR to char array [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Convert lptstr to char*
I need to convert an LPTSTR p to CHAR ch[]. I am new to C++.
#include "stdafx.h"
#define _WIN32_IE 0x500
#include <shlobj.h>
#include <atlstr.h>
#include <iostream>
#include <Strsafe.h>
using namespace std;
int main(){
int a;
string res;
CString path;
char ch[MAX_PATH];
LPTSTR p = path.GetBuffer(MAX_PATH);
HRESULT hr = SHGetFolderPath(NULL,CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, p);
/* some operation with P and CH */
if(SUCCEEDED(hr))
{ /* succeeded */
cout << ch;
} /* succeeded */
else
{ /* failed */
cout << "error";
} /* failed */
cin >> a;
return 0;
}
Thanks in advance.
LPTSTR is a (non-const) TCHAR string. Depends if it is Unicode or not it appears. LPTSTR is char* if not Unicode, or w_char* if so.
If you are using non-Unicode strings LPTSTR is just a char*, otherwise do:
size_t size = wcstombs(NULL, p, 0);
char* CharStr = new char[size + 1];
wcstombs( CharStr, p, size + 1 );
Also, this link can help:
Convert lptstr to char*
LPTSTR means TCHAR* (expanding those Win32 acronyms typedefs can make it easier to understand them). TCHAR expands to char in ANSI/MBCS builds, and to wchar_t in Unicode builds (which should be the default in these days for better internationalization support).
This table summarizes the TCHAR expansions in ANSI/MBCS and Unicode builds:
| ANSI/MBCS | Unicode
--------+----------------+-----------------
TCHAR | char | wchar_t
LPTSTR | char* | wchar_t*
LPCTSTR | const char* | const wchar_t*
So, in ANSI/MBCS builds, LPTSTR expands to char*; in Unicode builds it expands to wchar_t*.
char ch[MAX_PATH] is an array of char's in both ANSI and Unicode builds.
If you want to convert from a TCHAR string (LPTSTR) to an ANSI/MBCS string (char-based), you can use ATL string conversion helpers, e.g.:
LPTSTR psz; // TCHAR* pointing to something valid
CT2A ch(psz); // convert from TCHAR string to char string
(Note also that in your original code you should call CString::ReleaseBuffer() which is the symmetric of CString::GetBuffer().)
Sample code follows:
// Include ATL headers to use string conversion helpers
#include <atlbase.h>
#include <atlconv.h>
...
LPTSTR psz = path.GetBuffer(MAX_PATH);
HRESULT hr = SHGetFolderPath(NULL,CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, psz);
path.ReleaseBuffer();
if (FAILED(hr))
{
// handle error
...
}
// Convert from TCHAR string (CString path) to char string.
CT2A ch(path);
// Use ch...
cout << static_cast<const char*>(ch) << endl;
Note also that the conversion from Unicode to ANSI can be lossy.
First, you defined char* ch[MAX_PATH] instead of char ch[MAX_PATH].
Regarding your question, LPTSTR (Long Pointer to TCHAR String) is equivalent to LPWSTR (which is w_char*) if it's unicode, or just LPSTR (char*) if it is not. You can use this link for reference about conversion in each case.
EDIT: To cut to the chase, here's some code:
if (sizeof(TCHAR) == sizeof(char)) // String is non-unicode
strcpy(ch, (char*)(p));
else // String is unicode
wcstombs(ch, p, MAX_PATH);
EDIT 2: In windows I would recommend using TCHAR instead of char. It will save you some headache.
EDIT 3: As a side note, if you want to prevent Visual Studio from flooding you with warnings about unsafe functions, you can add something like the following to the very beginning of your code:
#ifdef _MSC_VER
#define _CRT_SECURE_NO_WARNINGS
#endif