Arguments from commandline to MessageBox in pure winapi (C++ without standard libraries) - c++

I was trying to make a pure WinApi program that simply takes arguments and puts the first one into MessageBoxW. However, there is a problem, as the arguments passed are put into LPWSTR array, but MessageBoxW takes in LPCWSTR. This givesme an error, and I tried everything, using reinterpret_cast, const_cast, standard C conversion, but nothing works.
Here's the code:
#include <Windows.h>
int main()
{
LPWSTR *argv;
int argc;
argv = CommandLineToArgvW(GetCommandLineW(), &argc);
LPWSTR lol = argv[1];
MessageBoxW(NULL, lol, "Test", 0);
ExitProcess(0);
}
The result is:
main.cpp(11): error C2664: 'int MessageBoxW(HWND,LPCWSTR,LPCWSTR,UINT)': cannot convert argument 3 from 'const char [5]' to 'LPCWSTR'
main.cpp(11): note: Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
Program compiled in Visual Studio 2015 using commandline:
cl /Os /GS- /Oi- primetest.cpp /link /fixed /nodefaultlib /safeseh:no /filealign:512 /entry:main /subsystem:console /MERGE:.rdata=.text kernel32.lib shell32.lib user32.lib
Those parameters allow for a small output file of 2kb, but this has nothing to do with the type conversion.
Also, the program compiles without any errors or warnings, and works, if a string literal is placed instead of "lol" variable in MessageBoxW.

#include <Windows.h>
int main()
{
LPCWSTR *argv;
int argc;
argv = CommandLineToArgvW(GetCommandLineW(),
&argc);
LPCWSTR lol = argv[1];
MessageBoxW(NULL, lol, L"Test", NULL);
ExitProcess(0);
return 0;
}

Related

How to cause SAL compiler warnings in my own code using Visual C++ without running static code analysis

If I create a new console project in VS 2019 and add my own annotated implementation of printf and call both real printf and my version:
// SALTest.cpp : This file contains the 'main' function. Program execution begins and ends there.
//
#include <iostream>
#include <cstdarg>
int my_printf(_In_z_ _Printf_format_string_ char const* const format, ...)
{
va_list arglist;
va_start(arglist, format);
int result = _vfprintf_l(stdout, format, nullptr, arglist);
va_end(arglist);
return result;
}
int main()
{
printf("Hello World!\n");
printf("printf good: %s\n", "narrow string");
printf("printf bad: %s\n", L"wide string");
my_printf("my_printf good: %s\n", "narrow string");
my_printf("my_printf bad: %s\n", L"wide string");
}
When I compile the file I see a compiler warning for the misuse of printf but not for the misuse of my_printf:
1>------ Build started: Project: SALTest, Configuration: Debug Win32 ------
1>SALTest.cpp
1>C:\Code\SALTest\SALTest.cpp(21,12): warning C4477: 'printf' : format string '%s' requires an argument of type 'char *', but variadic argument 1 has type 'const wchar_t *'
Now it is true that I can "Run Code Analysis on File (Ctrl+Shift+Alt+F7)" and that will give me code analysis warnings for both printf and my_printf in addition to the original compiler warning for printf:
1>------ Build started: Project: SALTest, Configuration: Debug Win32 ------
1>SALTest.cpp
1>C:\Code\SALTest\SALTest.cpp(21,12): warning C4477: 'printf' : format string '%s' requires an argument of type 'char *', but variadic argument 1 has type 'const wchar_t *'
...
C:\Code\SALTest\SALTest.cpp(21): warning C6303: Format string mismatch: wide character string passed as _Param_(2) when character string is required in call to 'printf' Actual type: 'const wchar_t [12]'.
C:\Code\SALTest\SALTest.cpp(23): warning C6303: Format string mismatch: wide character string passed as _Param_(2) when character string is required in call to 'my_printf' Actual type: 'const wchar_t [12]'.
But my question is this: is it possible to get the same compiler warning for my_printf that I get for printf without resorting to running a code-analysis?
Turning on code-analysis for the huge project I'm on is not an option.
SAL annotations have no effect whatsoever during the compiling stage, as they are implemented as empty preprocessor macros. They only have an effect on static analysis tools.
In the case of printf() (and other similar standard functions, like scanf()), modern compilers have built-in knowledge of the requirements of their parameters, and can thus validate user-provided parameter values at compile-time. But that a compiler extension, not defined by the C/C++ standards.
For instance, gcc and clang offer compile-time validation of a printf-style user function by decorating it with __attribute__((format(...))), but MSVC does not support that feature at this time, it only supports SAL annotations.

how to "use unicode character set" in g++?

i'm working on a program in c++ where i'm trying to use the WriteProcessMemory() function in windows. for that i need a function that gets the target process id. i'm able to do that using the following function:
#pragma once
#include <Windows.h>
#include <TlHelp32.h>
#include <iostream>
//get process id from executable name using tlhelp32snapshot
DWORD GetProcID(wchar_t *exeName){
PROCESSENTRY32 procEntry = {0};
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (!hSnapshot) {
return 0;
}
procEntry.dwSize = sizeof(procEntry);
if (!Process32First(hSnapshot, &procEntry)) {
return 0;
}
do {
if (!wcscmp(procEntry.szExeFile, exeName)) {
CloseHandle(hSnapshot);
return procEntry.th32ProcessID;
}
} while (Process32Next(hSnapshot, &procEntry));
CloseHandle(hSnapshot);
return 0;
}
//main function
int main() {
using namespace std;
cout << "some output" << endl;
return 0;
}
i'm able to compile using visual studio if i set the character set to unicode but when i try using g++ i get a conversion error:
g++ -std=c++17 write.cpp
write.cpp:1:9: warning: #pragma once in main file
#pragma once
^
write.cpp: In function 'DWORD GetProcID(wchar_t*)':
write.cpp:21:43: error: cannot convert 'CHAR* {aka char*}' to 'const wchar_t*' for argument '1' to 'int wcscmp(const wchar_t*, const wchar_t*)'
if (!wcscmp(procEntry.szExeFile, exeName)) {
^
write.cpp: In function 'MODULEENTRY32 GetModule(DWORD, wchar_t*)':
write.cpp:40:46: error: cannot convert 'char*' to 'const wchar_t*' for argument '1' to 'int wcscmp(const wchar_t*, const wchar_t*)'
if (!wcscmp(modEntry.szModule, moduleName)) {
^
i'm able to compile with cl using the arguments:
cl /EHsc /D UNICODE write.cpp
here /D UNICODE is the same as going in visual studio > rmb on project > properties and seting Character Set to Use Unicode Character Set.
is there an option to force unicode in g++ like in cl?
cl (Microsoft C/C++ Compiler) and g++ (Gnu C++ Compiler) have a very close arguments syntax on certain parameter. The delta is more of the usual difference Dos / Shell (slash vs dash).
The equivalent of /DMY_IDENTIFIER (cl) is on g++:
-DMY_IDENTIFER
Which means in your case: -DUNICODE
The complete compilation command line would have to look like:
g++ -DUNICODE -std=c++17 write.cpp
The correct answer here is to use the compiler switch -municode which defines everything you need, and links to the correct CRT files as to provide you with the proper definition of _wmain.
This is not available on ye olde MinGW, so you'll need a MinGW-w64 toolchain for that. Chances are you are already using that anyway. If that is not the case, you can download the installer from here.

argument of type "const char *" is incompatible with parameter of type "LPCWSTR"

I have a very big problem... I' ve started today morning programming in Windows.h but I can't figure out why it gave me this problem as I litteraly copy the thing in the tut. (https://youtu.be/8GCvZs55mEM?t=5m20s) (I put the link to start the video when occurs my error)
The only thing I noticed is that in the tut it uses a LPCSTR variable for test, but my editor (Visual Studio Code) signal a LPCWSTR variable.
Sorry for the bad English.
#include <windows.h>
using namespace std;
int WINAPI WinMain (HINSTANCE hInts, HINSTANCE hPrevInst, LPSTR args, int ncmdshow)
{
MessageBox(NULL, "Ciao!", "La prima GUI", MB_OK, );
return 0;
}
How can I solve?
In the comment:
Now the error don't show up, thanks a lot. But there is a problem... The editor don' t built the application. The Console give:
Executing task: g++ -g main.cpp -o Program <
main.cpp: In function 'int WinMain(void *, void *, char *, int)':
main.coo:8: pasing '__wchar_t *' as argument 2 of 'MessageBox(void *, const char *, const char *, UINT)'
Obviously not a good tutorial. Do it like like this
MessageBox(NULL, L"Ciao!", L"La prima GUI", MB_OK);
Using L changes the string literal so that it uses wide characters. A wide character string literal can be converted to the type LPCWSTR, a normal string literal cannot.

error C2664: cannot convert from 'LPTSTR []' to 'LPCTSTR *'

I use Visual Studio 2013 and I get the following error:
error C2664: 'DWORD Options(int,LPCTSTR *,LPCTSTR,...)' : cannot convert argument 2 from 'LPTSTR []' to 'LPCTSTR *' 54 1 ConsoleApplication3
This is the code:
DWORD Options(int argc, LPCTSTR argv[], LPCTSTR OptStr, ...){
// Code
}
int _tmain(int argc, LPTSTR argv[]){
iFirstFile = Options(argc, argv, _T("s"), &dashS, NULL);
// Code
}
Does anyone know how to fix it?
And explain why this error does occur?
"And explain why this error does occur?"
The reason behind this error can be found here:
an implicit conversion "... would let you silently and accidentally modify a const object without a cast..."
"Does anyone know how to fix it?"
LPCTSTR argv[] is not a constant object, but an array of constant strings. The array itself may be modified (argv[0] = 0;).
Since the advice in the link above is to avoid casting ("...please do not pointer-cast your way around that compile-time error message..."), the simplest solution is to change the signature of Options (notice the added const):
DWORD Options(int argc, const LPCTSTR argv[], LPCTSTR OptStr, ...)

Cannot convert char* to WCHAR* [qt/c++]

im developin QT application, and i need to include pure C code. When i compile this code in code::blocks it was successful, maybe one warning, but when i try to compile it in QT creator, i get these 4 errors.
cannot convert 'char*' to 'WCHAR*' for argument '1' to 'UINT GetSystemDirectoryW(WCHAR*, UINT)'
cannot convert 'char*' to 'const WCHAR*' for argument '1' to 'HINSTANCE__* LoadLibraryW(const WCHAR*)'
cannot convert 'char*' to 'WCHAR*' for argument '1' to 'BOOL
cannot convert 'const char*' to 'const WCHAR*' for argument '2' to 'LONG RegQueryValueExW(HKEY__*, const WCHAR*, DWORD*, DWORD*, BYTE*, DWORD*)'
and the code is here>
char systemDirectory[MAX_PATH];
GetSystemDirectory(systemDirectory, MAX_PATH); //first error
char kbdLayoutFilePath[MAX_PATH];
kbdLibrary = LoadLibrary(kbdLayoutFilePath); //second error
char kbdName[KL_NAMELENGTH];
GetKeyboardLayoutName(kbdName); //third error
if(RegQueryValueEx(hKey, "Layout File", NULL, &varType, layoutFile, &bufferSize) != ERROR_SUCCESS) //fourth error
i also use snprintf function, so i cant just change the type from char to WCHAR, because then it wont compile the snprintf
snprintf(kbdKeyPath, 51 + KL_NAMELENGTH,
"SYSTEM\\CurrentControlSet\\Control\\Keyboard Layouts\\%s", kbdName);
So do you have any ideas how to fix it ? first i tried change type from char to WCHAR, but then the snprintf didnt work, so i tried to use swprinf, but with no success, since strangely it didnt find this function
int swprintf(wchar_t *wcs, size_t maxlen,
const wchar_t *format, ...);
but just this
int swprintf(wchar_t *wcs,
const wchar_t *format, ...);
so what are my option ? How to compile pure C code in c++ environment without any errors... or how to make the right type conversion.
You are compiling in Unicode mode. You could set your compile to multi-byte strings. The problem that is happening is those windows API functions are macros that check whether you are building Unicode or not and then call either the W or A version of the function (in your code there, the GetSystemDirectory is actually calling GetSystemDirectoryW. So, you can either change your compile to multi-byte strings....or you could explicitly change your api calls to call the A version (i.e. GetSystemDirectoryA)
You are compiling your project with the UNICODE or _UNICODE define. Check your project settings and remove the define if necessary. To remove the define, you might need to disable unicode support for the whole project.
Change over from char to WCHAR and then to solve your swprintf problem just do this
#define swprintf _snwprintf
On Windows, the prototype of swprintf is
int swprintf( wchar_t *buffer,const wchar_t *format [,argument] ... );
But the ISO C Standard requires the following prototype for swprintf
int swprintf (wchar_t *, size_t, const wchar_t *, ...);
For this very reason, on Windows, _snwprintf is provided.
Read this for more details
http://msdn.microsoft.com/en-us/library/ybk95axf(v=vs.71).aspx