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

#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);

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;
}

My winreg function is not being recognized

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) {

Conversion from C to C++ avoiding <strsafe.h>

Recently I read a post here in S.O. which claimed to have the solution for removing a file after its execution, providing some code to do so.
Then I figured out that it was written in C and used a library called strsafe.h, which I have read in some other forums that is a Visual library and it doesn't work on C++.
Is there a working solution for using this code in C++? Any help will be appreciated.
#include <Windows.h>
#include <strsafe.h>
#define SELF_REMOVE_STRING TEXT("cmd.exe /C ping 1.1.1.1 -n 1 -w 3000 > Nul & Del \"%s\"")
void DelMe()
{
TCHAR szModuleName[MAX_PATH];
TCHAR szCmd[2 * MAX_PATH];
STARTUPINFO si = {0};
PROCESS_INFORMATION pi = {0};
GetModuleFileName(NULL, szModuleName, MAX_PATH);
StringCbPrintf(szCmd, 2 * MAX_PATH, SELF_REMOVE_STRING, szModuleName);
CreateProcess(NULL, szCmd, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi);
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
}
void main()
{
/* Do what you need */
/* Call this function at the very end of your program to delete itself */
DelMe();
}
The only function from <strsafe.h> here is StringCbPrintf which you can replace with wsprintf
//StringCbPrintf(szCmd, 2 * MAX_PATH, SELF_REMOVE_STRING, szModuleName);
wsprintf(szCmd, SELF_REMOVE_STRING, szModuleName);
However, you won't be able to port it to other platforms so easily, because of Windows native functions used.

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

Converting a string to LPCWSTR for CreateFile() to address a serial port

I seem to be having a bit of a TEXT / UNICODE problem when using the windows CreateFile function for addressing a serial port. Can someone please help point out my error?
I'm writing a Win32 console application in VC++ using VS 2008.
I can create a handle to address the serial port like this:
#include <iostream>
#include <windows.h>
#include <string>
int main()
{
HANDLE hSerial;
hSerial = CreateFile( L"\\\\.\\COM20",
GENERIC_READ | GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
0);`
return 0;
}
That works just fine (the \\\\.\\ bit is required for comports greater than COM9 and works for those up to COM9 also). The problem is that my comport will not always be COM20, so I'd like to have the user specify what it is.
Here are some things I've tried:
#include <iostream>
#include <windows.h>
#include <string>
int main()
{
std::string comNum;
std::cout << "\n\nEnter the port (ex: COM20): ";
std::cin >> comNum;
std::string comPrefix = "\\\\.\\";
std::string comID = comPrefix+comNum;
HANDLE hSerial;
hSerial = CreateFile( comID,
GENERIC_READ | GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
0);`
return 0;
}
This does not compile and returns the error: error C2664: 'CreateFileW' : cannot convert parameter 1 from 'std::string' to 'LPCWSTR'
I thought maybe specifying CreateFileA would work then, but that gave basically the same error.
I also tried :
/*
everything else the same
*/
hSerial = CreateFile( TEXT(comID),
GENERIC_READ | GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
0);`
which also does not compile and returns: error C2065: 'LcomID' : undeclared identifier
I am not much of an expert but I have been working on this for a while now. Can someone tell me how to replace L"\\\\.\\COM20" in such a way that the user can specify the comport and so that CreateFile will still work? Thanks!
You can either use std::wstring and std::wcin, std::wcout to perform input directly in "unicode strings", or you can look into Microsoft's conversion functions.
If you go for the 1st option (recommended), you still need to use the c_str() function to gain access to a LPCWSTR value (pointer to const wchar_t).
Sample solution (also not use of CreateFileW syntax, to prevent issues with UNICODE macro):
#include <iostream>
#include <windows.h>
#include <string>
int main()
{
std::wstring comNum;
std::wcout << L"\n\nEnter the port (ex: COM20): ";
std::wcin >> comNum;
std::wstring comPrefix = L"\\\\.\\";
std::wstring comID = comPrefix+comNum;
HANDLE hSerial;
hSerial = CreateFileW( comID.c_str(),
GENERIC_READ | GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
0);`
return 0;
}
If you want to continue using std::string, then use its c_str() method when calling CreateFileA(), eg:
hSerial = CreateFileA( comID.c_str(), ...);
As an additional reference, have a look at the ATL conversions macros (eg: CA2CW, etc.). These (if used properly) can handle pretty much all simple conversion cases inline, with little fuss.
In your example, you can use std::string, then use:
CreateFile( CA2CT( comID.c_str() ), ... );
If (for some reason) you decide to keep working with ANSI strings, then take a look at the MultiByteToWideChar function. But ANSI strings are pretty much obsolete.
I ran into this recently. I simply disabled Unicode, as Unicode was wholly out of scope for this application.
General info on string conversions here: http://www.codeproject.com/KB/string/cppstringguide2.aspx