I've installed vscode extension (ms-vscode.cpptools) from Microsoft to enable intellisense. But, when i typed MessageBox, the parameters have no labels.
It should be
MessageBoxW(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType)
My Question: Why MingW distribute the header files without labels?
It should be
MessageBoxW(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType)
That is not so.
The tooltip is showing you the declaration of the function, as declared
in MingGW's header winuser.h. That declaration specifies the function's
prototype, consisting of:
The return type of the function, then
The name of the function, then
The types of the parameters in the parameter-list, within brackets, in the right order.
as the tooltip does:
int MessageBoxW (HWND, LPCSTR, LPCSTR, UINT)
What you call "labels" are parameter-names. They are optional, and redundant,
in a function declaration, since the compiler does not need them to understand
how the declared function will be called, and what it returns. MessageBoxW
is to be called with arguments that are a HWND, a LPCSTR, another LPCSTR,
and a UINT, in that order; and it returns and int.
The compiler requires parameters to be named in a function definition:
add.c
// definition
int add(int x, int y)
{
return x + y;
}
main.c
#include <stdio.h>
extern int add(int,int); // Declaration
int main()
{
printf("%d\n",add(3,4));
return 0;
}
Compile with maximum strictness, link and run:
$ gcc -Wall -Wextra -pedantic -o prog main.c add.c
$ ./prog
7
See also Function Declaration in C
Parameter-names are useful to human readers in a function-declaration when the declaration
is accompanied by documentation of the function, since the documentation
can then refer to the parameter-names to explain the function's behaviour:
/*
Return the sum of `x` and `y`
*/
int add(int x, int y);
But they are unnecessary to the compiler.
Like the MinGW windows headers, Micorosoft's own headers do not contain comments
to document the APIs, but they do contain parameter-names, and also SAL Annotations
of the parameter names. E.g. in Microsoft's WinUser.h (SDK 2017) the declaration of MessageBoxW is:
int
WINAPI
MessageBoxW(
_In_opt_ HWND hWnd,
_In_opt_ LPCWSTR lpText,
_In_opt_ LPCWSTR lpCaption,
_In_ UINT uType);
The SAL annotations, (_In_opt_, _In_ and similar) are a non-standard Microsoft
language extension that supports static analysis of the correctness of code
implementing or invoking the APIs and they are used for that purpose by Microsoft's
compilers.
Such SAL-based static analysis needs names for the annotated parameters in order to provide
meaningful diagnostics; hence the parameters have names in the annotated declarations
in Microsoft's headers.
GCC, including MinGW ports, does not support SAL; so parameter names remain
redundant in function declarations.
Related
I am trying to use -Wl, -wrap=sendto -Wl, -wrap, sendto in my final g++ link command that links my app to replace the standard sendto function with my own.
I compile the following source code with:
gcc -c -o wrap.o wrap.c
and include the wrap.o in the final g++ command that links the app (the rest of the app is C++ hence the use of g++):
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
ssize_t __real_sendto(int, const void *, size_t, int, const struct sockaddr *, socklen_t);
ssize_t __wrap_sendto
(
int sockfd,
const void *buf,
size_t len,
int flags,
const struct sockaddr *dest_addr,
socklen_t addrlen
)
{
printf("my wrap sendto ...\n");
return __real_sendto(sockfd, buf, len, flags, dest_addr, addrlen);
}
When I use sendto in my own source code, the wrapper is in fact used ok but all 3rd party shared objects i linked against in my final g++ command that use sendto still use the system sendto i.e. not my wrapper. How can I get my sendto wrapper used throughout?
I have also tried an LD_PRELOAD approach with a sendto and dlsym(RTLD_NEXT) inside but that did not work either.
How can I figure out why the 3rd party library keeps on using the libc sendto directly?
When I use ldd to find all shared object dependencies of my compiled app and then objdump -T on each one of them grepping for sendto, I get UND (undefined) for all the 3rd party shared objects. The shared objects that do define it however is:
/lib64/libpthread.so.0
000000000000ed80 w DF .text 0000000000000064 GLIBC_2.2.5 sendto
/lib64/libc.so.6
00000000000e98d0 w DF .text 0000000000000064 GLIBC_2.2.5 sendto
I see in glibc sendto.c on git the following:
weak_alias (__libc_sendto, sendto)
weak_alias (__libc_sendto, __sendto)
The --wrap sendto option does not define the sendto symbol in your binary. Instead, it replaces references to this symbols with __wrap_sendto and leaves sendto undefined.
In other words, your executable does not provide sendto, so the run-time symbol resolution picks the one from glibc.
To fix this you need to define sendto in your executable. Try dlsym once again, but this time without LD_PRELOAD/shim library:
ssize_t sendto
(
int sockfd,
const void *buf,
size_t len,
int flags,
const struct sockaddr *dest_addr,
socklen_t addrlen
)
{
ssize_t (*libc_sendto)(int, const void *, size_t, int, const struct sockaddr *, socklen_t)
= dlsym(RTLD_NEXT, "sendto");
printf("my wrap sendto ...\n");
return libc_sendto(sockfd, buf, len, flags, dest_addr, addrlen);
}
If third-party libraries keep finding wrong sendto after this, then I see only one (not particularly likely) possibility. Shared libraries are linked with -Bsymbolic/-Bsymbolic-functions and provide their own sendto.
Also, since you've tagged this question as g++, make sure that your symbol names don't get mangled - use extern "C".
I have eventually managed to figure out what was going on here. Even though the strace states sendto is being called:
[pid 17956] sendto(4, "abc"..., 2052, 0, NULL, 0) = 2052
what was in fact happening was send(...) was being called (probably possible because 0, null, 0 last three parameters). The moment I made an interceptor for send(...) it worked.
I am fresh off from learning C++ and to learn winapi, I am doing the Forgers Win32 API tutorial.
Here is my code:
//MyControl.h
#pragma once
#include <windows.h>
#include "resource.h"
BOOL CALLBACK DlgProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam);
BOOL BrushExists(HBRUSH hBrush);
-------------------------------------------------------
//MyControl.cpp
#include "MyControl.h"
HBRUSH g_hbrBackground = NULL;
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
return (int)DialogBox(hInstance, MAKEINTRESOURCE(IDD_MAIN), NULL, (DLGPROC)DlgProc);
}
BOOL BrushExists(HBRUSH hBrush) // I added this to better understand what is happening
{
if (hBrush)
return TRUE;
else
return FALSE;
}
BOOL CALLBACK DlgProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
{
switch (Message)
{
case WM_INITDIALOG:
{
g_hbrBackground = CreateSolidBrush(RGB(0, 0, 0));
//... Other code skipped copy pasting ...
}
break;
case WM_COMMAND:
//... Other code skipped copy pasting ...
break;
case WM_CTLCOLORDLG:
return (LONG_PTR)g_hbrBackground; // Where casting happens
// return BrushExists(g_hbrBackground); // Tried this to understand things
break;
case WM_CTLCOLORSTATIC:
{
HDC hdcStatic = (HDC)wParam;
SetTextColor(hdcStatic, RGB(255, 255, 255));
SetBkMode(hdcStatic, TRANSPARENT);
return (LONG_PTR)g_hbrBackground; // Where casting happens
// return BrushExists(g_hbrBackground); // Tried this to understand things
}
break;
//... Other code skipped copy pasting ...
}
The code compiles and gives the warning: C4244: 'return': conversion from 'LONG_PTR' to 'BOOL', possible loss of data
The casting works and the dialog box is colored right as expected:
Black colored dialog.
My question: What happens in the background when HBRUSH is returned as a LONG_PTR from a function (DLGPROC) that returns BOOL? My assumption from reading C++ was that if the LONG_PTR is non-zero then the BOOL returned is TRUE and if LONG_PTR is zero then the BOOL returned is FALSE. To check this I created the function BOOL BrushExists(HBRUSH hBrush);// See code. Using this function to check for the HBRUSH and return TRUE, compiles without warnings and runs without error. But the coloring of the Dialog box does not happen:
Black color missing.
So my assumption is wrong. The LONG_PTR seems to be evaluated by the win32 API as a number instead of as a BOOL. Can someone explain to me how this is happening?
Note that it's BOOL and not bool. With the Windows SDK, BOOL is a typedef for int, which can store a 32-bit value - it's not a simple boolean that can only store true or false.
This is a kludge in the API basically. In 32 bit Windows, a brush handle fits in a 32 bit value, and even though it's ugly and potentially confusing, it's "safe" to return a brush handle cast as a BOOL (and you had to cast it, since that's what DialogProc was defined as returning).
Once Windows gained 64 bit support this situation obviously wasn't acceptable - in this example, brush handles (which are pointers) are 64 bits in size - casting them to a 32-bit type isn't safe.
Therefore, the definition of DialogProc was changed to return INT_PTR rather than BOOL. This is typedefed to 32-bits in x86 and 64-bits in x64. The example code you've used obviously pre-dates this change, but all new code should use the correct definition of DialogProc as returning INT_PTR.
BOOL is nothing but int typedef'd.
LONG_PTR may be either long int or __int64 - depending on platform chosen.
From header:
#ifdef _WIN64
typedef __int64 LONG_PTR;
#else
typedef long LONG_PTR;
#endif
You seem to be building the project as x64 compiler, and hence BOOL to LONG_PTR (essentially int to int64) is giving you warning.
Note that int and long are essentially same on Visual C++/Windows.
I'm trying to make a win32 dll that are able to handle ansi and unicode depending what specify in the character set on properties. Unicode or Not Set. ANSI when building in Visual Studio.
The dll has the definition
extern "C" int __stdcall calc(TCHAR *foo)
The definition file is as follow
typedef int (CALLBACK* LPFNDLLCALC)( TCHAR *foo)
Inside the MFC Calling app i load the dll as this
HINSTANCE DllFoo = LoadLibrary(L"foo.dll");
LPFNDLLCALC lpfnDllcalc = (LPFNDLLCALC)GetProcAddress(DllFoo ,"calc");
CString C_SerialNumber;
mvSerialNumber.GetWindowText(C_SerialNumber);
TCHAR* SerialNumber = C_SerialNumber.GetBuffer(0);
LPFNDLLCALC(SerialNumber);
I understand that i make something wrong in the C_SerialNumber.GetBuffer(0) to the TCHAR* pointer. Because in the debugger in the dll only show the first char is passed to the dll. Not the complete string.
How do i get CString to pointer that work in both ansi and unicode.
If change all my code to wchar_t or char in stead of TCHAR i get it to work. Put not with this nativ TCHAR macro.
As I see it you have two options:
Write the code entirely using TCHAR. Then compile the code into two separate DLLs, one narrow and one wide.
Have a single DLL that exports two variants of each function that operates on text. This is how the Windows API is implemented.
If you choose the second option, you don't need to implement each function twice. The primary function is the wide variant. For the narrow variant you convert the input from narrow to wide and then call the wide version. Vice versa for output text. In other words, you use the adapter pattern.
I suppose that you are imagining a third option where you have a single function that can operate on either form of text. Don't go this way. This way abandons type safety and will give you no end of pain. It will also be counter to user's expectations.
As David said, you need to export two separate functions, one for Ansi and one for Unicode, just like the Win32 API does, eg:
#ifdef __cplusplus
extern "C" {
#endif
int WINAPI calcA(LPCSTR foo);
int WINAPI calcW(LPCWSTR foo);
#ifdef __cplusplus
}
#endif
typedef int (WINAPI *LPFNDLLCALC)(LPCTSTR foo);
Then you can do the following:
int WINAPI calcA(LPCSTR foo)
{
return calcW(CStringW(foo));
}
int WINAPI calcW(LPCWSTR foo)
{
//...
}
HINSTANCE DllFoo = LoadLibrary(L"foo.dll");
LPFNDLLCALC lpfnDllcalc = (LPFNDLLCALC) GetProcAddress(DllFoo,
#ifdef UNICODE
"calcW"
#else
"calcA"
#endif
);
CString C_SerialNumber;
mvSerialNumber.GetWindowText(C_SerialNumber);
lpfnDllcalc(C_SerialNumber);
I am trying to hide the WinMain function inside a DLL in order to avoid typing again much of the code over and over again.
I exported wWinMain from the DLL by declaring it as
extern "C" int WINAPI wWinMain( ... )
{
// repetitive code here
}
and used the linker option /EXPORT:wWinMain, but when I try to use the import library in another project I get the error
LIBCMTD.lib(wincrt0.obj) : error LNK2019: unresolved external symbol _WinMain#16 referenced in function __tmainCRTStartup
Remark I do want to use the GUI interface and I know this is common error when you define a main instead of a WinMain function. Also, I enabled the UNICODE support in both projects. What should I do?
This is not possible as-is, the linker can only set the entrypoint for an EXE to a function that's inside the EXE. Rename the wWinMain() in the DLL to something else. Write a wWinMain() in a source code file that gets linked into your EXE, simply call the DLL's exported function.
// ...somewhere in a .cpp file within my .dll's sources...
#define WinMain WinMainOld // ...to suppress Win32 declaration of WinMain
#include <windows.h>
#undef WinMain // ...so that WinMain below is not replaced
. . .
#pragma comment(linker, "/export:_WinMain#16") // ...to export it from .dll
extern "C" // ...to suppress C++ name decoration
int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR pCmdLine, int nCmdShow)
{
. . .
}
Should you be using WinMain in a DLL? Should it not be DllMain?
If you want to call the WinMain of the dll, you need to replace the CRTWinMainStartup function(_tmainCRTStartup in your liked CRT lib), and make it call your exported WinMain, this stops the linker looking for a local WinMain and still keeps correct flow of the program(the source for the CRT startups should be in the crt source of any compiler)
I find one way to put WinMain inside DLL.
You need to use WinMain instead of wWinMain (I don't know why)
Append a def file into your project and,
append EXPORTS WinMain in def file.
Like this
EXPORTS
WinMain
From the observation, all need exported functions generated, not only WinMain.
After test, the way of __declspec(dllexport) is invalid for WinMain.
Link your program to the DLL library
use #pragma comment(lib, "testDll.lib")
or modify setting in the project.
EXPORT int WINAPI _WinMain_(int (*_main_)(int argc, char **argv), HINSTANCE hInst, HINSTANCE hPrevInstance, LPSTR commandLine, int nCmdShow);
int _XMain( int argc, char **argv );
#define XMain WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInstance, LPSTR commandLine, int nCmdShow)\
{return _WinMain_( _XMain, hInst, hPrevInstance, commandLine, nCmdShow );} \
int _XMain
Then _WinMain_() calls or schedules _XMain().
Over in your application source:
int XMain( int argc, char **argv )
{
}
I have created a DLL in VC++ as Win32 project
DLLMAIN function is
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
return TRUE;
}
Now I need HINSTANCE of the DLL , that need to be passed to Win32 functions.
Are HMODULE and HINSTANCE same?
How can I get HINSTANCE?
An excerpt from the book Windows Via C/C++ [1]
Note As it turns out, HMODULEs and HINSTANCEs are exactly the same thing. If the documentation for a function indicates that an HMODULE is required, you can pass an HINSTANCE and vice versa. There are two data types because in 16-bit Windows HMODULEs and HINSTANCEs identified different things
[1] Richter, Jeffery and Nasarre, Christophe, Windows Via C/C++, 5th ed, Redmond: Microsoft Press 2008, pp. 74
Microsoft linker specific
#include "windows.h"
EXTERN_C IMAGE_DOS_HEADER __ImageBase;
#pragma warning(disable: 4047)
HINSTANCE hInstance = (HINSTANCE)&__ImageBase;
#pragma warning(default: 4047)
I think that these are the same. If you want HINSTANCE of the running process (exe), you should use
GetModuleHandle(NULL);
Calling GetModuleHandle(NULL) from a dll will return the Hinstanc of the EXE that started the DLL; to get the Hinstance for the curently running dll try this tip:
http://www.dotnet247.com/247reference/msgs/13/65259.aspx
DllMain function as it's described in MSDN:
BOOL WINAPI DllMain(
__in HINSTANCE hinstDLL,
__in DWORD fdwReason,
__in LPVOID lpvReserved
);
http://msdn.microsoft.com/en-us/library/ms682583%28v=vs.85%29.aspx
Each DLL has at least a header file, say MyDll.h and a corresponding implementation file MyDll.cpp. Open the header file and add
extern HMODULE hDllModule;//or whatever name you like
Now open the MyDll.cpp file. There is a function DLLMAIN. Add before it HMODULE hDllModule; and insert hDllModuleDll = hModule; before return true;. Your code will look like this:
HMODULE hDllModuleDll;
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
hDllModuleDll = hModule;
return TRUE;
}
In functions like ::GetModuleFileNameW(hModule, PathFile, MAX_PATH); that require a HMODULE of the DLL you can pass the global variable hDllModule.
To complement the other answers, for the sake of completness.
The actual signature of DllMain has an HINSTANCE parameter, instead of a HMODULE parameter. The Visual Studio DLL template generates the signature with HMODULE since at least Visual Studio 2008 however, but I believe this to be a minor bug more than anything. VC6 generated the code with HANDLE (even though both HINSTANCE and HMODULE exist). The reason that doesn't cause problems is because HINSTANCE and HMODULE are now exactly the same thing. Unfortunately I was unable to find an ancient enough version of the MSDN documetnation that could have confirmed this.
So the answer is: You get your HINSTANCE as an argument to your DllMain.
Personally I sort of like the distinction between HMODULE and HINSTANCE because it appeals to me as being good code hygiene. It's a bit like using const. But then, a new question arises: Given your HINSTANCE, how do you get your HMODULE in the "hygienic" way?
The windowsx.h header defines GetInstanceModule, which is now a macro that just casts the HINSTANCE to HMODULE. It only exists for code compatibility, along with a bunch of very similar macros.