Hiding a winform & bringing it back from a DLL - c++

In my DDL, I have the following function defined:
extern "C" __declspec(dllexport) void hideme(HWND h) {
//ShowWindow(h, SW_HIDE);
SendMessage(h, WM_SHOWWINDOW, FALSE, 0);
}
As you can see, I've tried multiple things to get this working...
I have it declared in my winform as followed:
typedef void (*HideMe)(HWND);
In my System::Windows::Forms::Form Load event, I have the following code:
...
HINSTANCE hinst = LoadLibrary(_T("My.dll"));
if (hinst == NULL)
System::Diagnostics::Debug::WriteLine("null hinst");
else
hideme = (HideMe) GetProcAddress(hinst, "hideme");
...
In my System::Windows::Forms::Form Shown event, I have the following code:
...
hideme((HWND)this->Handle.ToPointer());
...
I think the problem must lie in the way I send over the HWND, but I've been searching all day, and can't find an alternative.
I've also tried setting this->Visible = false; but then I can't figure out how to trigger it back to visible from the DLL (abuse sendmessage?).
I'm not a C++ programmer, I normally only program in managed languages, so any help (and patience is appreciated.
Thanks,
Nick.
N.B.
One weird thing I can't explain is that I can't call ShowWindow from the WinForm itself. It will throw up this gem:
Error 2 error LNK2028: unresolved token (0A00001E) "extern "C" int __stdcall ShowWindow(struct HWND__ *,int)" (?ShowWindow##$$J18YGHPAUHWND__##H#Z) referenced in function "private: void __clrcall CheckMSNCpp::frmMain::frmMain_Shown(class System::Object ^,class System::EventArgs ^)" (?frmMain_Shown#frmMain#CheckMSNCpp##$$FA$AAMXP$AAVObject#System##P$AAVEventArgs#4##Z)
Error 3 error LNK2019: unresolved external symbol "extern "C" int __stdcall ShowWindow(struct HWND__ *,int)" (?ShowWindow##$$J18YGHPAUHWND__##H#Z) referenced in function "private: void __clrcall CheckMSNCpp::frmMain::frmMain_Shown(class System::Object ^,class System::EventArgs ^)" (?frmMain_Shown#frmMain#CheckMSNCpp##$$FA$AAMXP$AAVObject#System##P$AAVEventArgs#4##Z)
Error 4 error LNK1120: 2 unresolved externals
[EDIT1]
Hans Passant said:
The linker error message you got on
the ShowWindow() attempt is also a
strong hint why your current code is
not working. You forgot to add error
checking code, GetProcAddress() can
fail and will return a NULL pointer.
It will, the function isn't exported
by the "hideme" name. In a 32-bit
build, it will be exported as
"_hideme", note the underscore. Which
was added to indicate that the
function uses the __cdecl calling
convention. The linker error on
ShowWindow demonstrates C++ name
decoration, you forgot to #include
windows.h and made up your own,
incorrect, declaration for ShowWindow.
This is not the right way to do it,
you should just set the Visible
property to false. Like you tried. Why
you cannot set it back to true is
quite unguessable.
What you said makes no sense to me at all for a few reasons.
1)
The imports for the winform:
#include "stdafx.h"
#include <windows.h>
#include <iostream>
#include <stdio.h>
As you can tell, windows.h is in there.
2) the ShowWindor error is not in the DLL, there I can call it fine, it's in the WinForm code.
3) I never exported ShowWindow, just my own functions.
[/EDIT1]
[EDIT2]
Uwe Keim said:
Why do you need an extra DLL that is
merely just a wrapper to another DLL
function?
I would do it like in e.g. C# by using
PInvoke from your managed C++
application. The signature for
SendMessage would be (in C#):
The PInvoke stuff just doesn't make any sense, like commenters said.
As for the DLL, it needs to be a DLL because i require a global hook to respond to my hotkeys & WH_CBT. In this case, I want the program to start hidden & just show a setting screen when pressing a key combo.
Everything in the program works as expected, the hotkey works like a charm, the only thin I can't get right, is showing the application, triggered from the DLL.
[/EDIT2]
[EDIT3]
Example code at: http://www.nickkusters.com/CPP_PROBLEM_Demo-NOBIN.zip
[/EDIT3]

The linker error message you got on the ShowWindow() attempt is also a strong hint why your current code is not working. You forgot to add error checking code, GetProcAddress() can fail and will return a NULL pointer. It will, the function isn't exported by the "hideme" name. In a 32-bit build, it will be exported as "_hideme", note the underscore. Which was added to indicate that the function uses the __cdecl calling convention. The linker error on ShowWindow demonstrates C++ name decoration, you forgot to #include windows.h and made up your own, incorrect, declaration for ShowWindow.
This is not the right way to do it, you should just set the Visible property to false. Like you tried. Why you cannot set it back to true is quite unguessable.

Why do you need an extra DLL that is merely just a wrapper to another DLL function?
I would do it like in e.g. C# by using PInvoke from your managed C++ application. The signature for SendMessage would be (in C#):
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern IntPtr SendMessage(
IntPtr hWnd,
UInt32 Msg,
IntPtr wParam,
IntPtr lParam);

Related

SetCursorPos in wxWidgets

I code with visual c++, and i use wxwidget 3.x., Windows 10
I would like to use SetCursorPos (to move my camera, and let the mouse cursor stay in middle of screen), but i got some error message:
canvas.obj : error LNK2019: unresolved external symbol __imp__SetCursorPos#8 referenced in function "public: void __thiscall CanvasFrame::setCursorPos(int,int)" (?setCursorPos#CanvasFrame##QAEXHH#Z)
I m not sure i can use SetCursorPos via wwxwidget, i think wxwidget manage this, but cant find it on google …
Some idea?
My bad …
this->WarpPointer(renderer->GetWidth() / 2, renderer->GetHeight() / 2);
works..
Thanks anyway :)

DirectXTK no member in "Mouse" for "SetWindow(HWND hwnd)"

I was trying to implement mouse and keyboard support in my game engine using DirectXTK. It was quite simple for keyboard, but I have got a problem with implementing proper mouse support. I was following THIS for implementing mouse into my engine. This article from Microsoft wiki says that I have call SetWindow, before I will be able to change mouse mode from absolute to relative. It sounds easy, but when I try to do this like this:
auto mouse = std::make_unique<DirectX::Mouse>();
mouse->SetWindow(hwnd);
mouse->SetMode(DirectX::Mouse::Mode::MODE_RELATIVE);
I get an error:
E0135 class "DirectX::Mouse" has no member "SetWindow"
It looks like this method doesn't exist in Mouse class. It is weird, becuse if I remove this line with setting window it will compile, but I will fail in runtime due to this assertion in Mouse class:
assert(mWindow != nullptr);
So it is required to set window, but how can I do this, when this function doesn't exist? What's worse the article from wiki is not old, it's from 18 Apr 2019. Have anyone encountered this problem? How can I fix this?
A quick look at the header file and you'll see this
#if (!defined(WINAPI_FAMILY) || (WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP)) && defined(WM_USER)
void __cdecl SetWindow(HWND window);
static void __cdecl ProcessMessage(UINT message, WPARAM wParam, LPARAM lParam);
#endif
So it seems likely that you don't have WINAPI_FAMILY and/or WM_USER defined in a suitable way to enable the declaration of that method in the header file.
I believe WM_USER will be defined by #include <windows.h> so maybe all you need to do is place that include before #include <mouse.h>

Running C++ DLL with rundll32 - Missing entry

So I'm trying to use rundll to test and run my C++ written DLL , and i've followed the guidelines here and on other sites and the entry point looks like this:
__declspec(dllexport) void CALLBACK entry(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow)
{
//do stuff
}
But the rundll process prompts me with an error message box saying "Error in C:\path\to\DLL Missing entry: entry"
Attempted execution command: "rundll32 C:\path\to\DLL, entry".
You can double-check by running Dumpbin.exe /exports on your DLL to see the actual exported name. Which right now is not entry, as the error message tells you.
You need to prefix extern "C" to the declaration to disable C++ name mangling.
Good enough for a 64-bit executable, but that turns it into _entry#16 if this is a 32-bit DLL, still not quite good enough to keep rundll32 happy. Use Project + Add New Item, Code node, pick the "Module-Definition File (.def)" item template. And make it look like this:
EXPORTS
entry = entry

Unresolved External Symbols in complex library dependent project using WINAPI

Having searched for days now i decided to post a question here and hope that somebody has the ultimate idea or advice.
I wrote a WINAPI wrapping mechanism consisting of a WindowManager and a WINAPIWindow class. The latter uses the famous "First WINAPI Window" functionality known from most tutorials in a more structured manner, mainly HWND and HINSTANCE.
Remarks: the macro "_ WINDOWS _" (without spaces but this tool makes it bold otherwise ) is a macro defined in one of my headers to determine, wether the compilation environment supports WIN32 and the WINAPI.
#if defined(_ _WINDOWS_ _)
LRESULT CALLBACK gDefaultWndProcFwd(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
#pragma region WINAPIWindow
class WINAPIWindow : public WindowBase
{
friend class WindowManager;
public:
virtual ~WINAPIWindow();
RESULT show();
inline HWND handle() const;
LRESULT CALLBACK wndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
private:
WINAPIWindow(__in const HINSTANCE hInstance, __in const Rect& bounds, __in const String& title = "", __in const int flags = WDF_DEFAULT);
HRESULT createWindowClass(__in const HINSTANCE hInstance, __in const String& clsName);
tInt16 _wndState;
HWND _hWnd;
};
typedef WINAPIWindow Window;
#pragma endregion
#elif
The mechanism is located in a static library called "ShirabePlatformFeatureLayer.lib".
This static library uses classes and code from another custom static lib called "ShiCore.lib" which does not use any platform dependent code.
My actual application project (x64!) now imports both as additional depenencies using the WindowManager.
Although both library projects compile fine and without errors, compiling the Application Project leads to the following error messages.
Error 43 error LNK2019: unresolved external symbol "public: struct HWND__ * __cdecl ShirabePlatformFeatureLayer::WINAPIWindow::handle(void)const " (?handle#WINAPIWindow#ShirabePlatformFeatureLayer##QEBAPEAUHWND__##XZ) referenced in function wWinMain C:\Users\Dev.Dev-PC\Documents\Workspaces\ShirabeEngine\ShirabeDevelopment\Win32TestProject\main.obj Win32TestProject
Error 45 error LNK2019: unresolved external symbol "__int64 __cdecl ShirabePlatformFeatureLayer::gDefaultWndProcFwd(struct HWND__ *,unsigned int,unsigned __int64,__int64)" (?gDefaultWndProcFwd#ShirabePlatformFeatureLayer##YA_JPEAUHWND__##I_K_J#Z) referenced in function "private: long __cdecl ShirabePlatformFeatureLayer::WINAPIWindow::createWindowClass(struct HINSTANCE__ * const,class ShirabeCORE::String const &)" (?createWindowClass#WINAPIWindow#ShirabePlatformFeatureLayer##AEAAJQEAUHINSTANCE__##AEBVString#ShirabeCORE###Z) C:\Users\Dev.Dev-PC\Documents\Workspaces\ShirabeEngine\ShirabeDevelopment\Win32TestProject\ShirabePlatformFeatureLayer.lib(Window.obj) Win32TestProject
Error 44 error LNK2001: unresolved external symbol "public: struct HWND__ * __cdecl ShirabePlatformFeatureLayer::WINAPIWindow::handle(void)const " (?handle#WINAPIWindow#ShirabePlatformFeatureLayer##QEBAPEAUHWND__##XZ) C:\Users\Dev.Dev-PC\Documents\Workspaces\ShirabeEngine\ShirabeDevelopment\Win32TestProject\ShirabePlatformFeatureLayer.lib(WindowManager.obj) Win32TestProject
Error 46 error LNK1120: 2 unresolved externals C:\Users\Dev.Dev-PC\Documents\Workspaces\ShirabeEngine\ShirabeDevelopment\Debug\Win32TestProject.exe Win32TestProject
I checked, whether the methods are declared and defined properly. I also included and imported the libs.
#if defined(_ _WINDOWS_ _)
#pragma comment(lib, "user32.lib")
#pragma comment(lib, "kernel32.lib")
#pragma comment(lib, "gdi32.lib")
#include <Windows.h>
#endif
In addition i registered the 3 libs above as additional dependencies and the lib-directories are $(VC_LibraryPath_x64) and $(WindowsSDK_LibraryPath_x64).
My first thoughts after having analyzed this a bit is, that all methods or functions that use WINAPI classes and structs are not linked into the import library "ShirabePlatformFeatureLayer.lib". Having registered them above 3 libs as additional dependencies with equal library paths as above and the /VERBOSE:LIB shows me that the libraries are appended but not with "x64\gdi32.lib" as the message but "GDI32.DLL". Likewise for the other two.
Doing /VERBOSE:LIB in the application project shows me the actual relative paths to the "~.lib" and not "~.DLL".
What can cause the methods to not being linked/included/important when they use WINAPI functionality?
Is the general build design with so many .libs the problem?
Does anybody else have an idea?
Here the entire affected code ( imho ): http://pastebin.com/f7MaBBwM
If any further information is required, please tell me.
EDIT: I've continued searching and came up with the "project to project" dependencies in the new MSBuild system. Although this appeared to be the same problem, it isn't since obviously the dependency of "ShirabePlatformFeatureLayer.lib" to the import libs kernel32, gdi32 and user32 causes problem, when effectively being consumed by the Win32TestProject using the ShirabePlatformFeatureLayer.lib code.
Unfortunately i wasn't able to solve the problem yet with the various advice given est. 10 different articles on the topic. :/
Edit: Consulting Rodrigo s remarks i was able to get rid of the handle() unresolved symbol. However the second with gDefaultWndProcFwd seems to be a logic/design error.
Once i managed to get 10 Reputation I'll attach an image of the relation between WindowManager, WINAPIWindow and gDefaultWndProcFwd!
That said here a textual description:
1) Creating the window implies creating the WindowClassEx structure that refers to gDefaultWndProcFwd using a forward declaration in Window.h.
2) When the window is created and shown the method should be called, which consults WIndowManager::get(key : HWND) : WindowBase*;
3) If found, the function invokes wndProc on the window pointer and leaves handling to the specified implementation of the wndproc.
The gDefaultWndProcFwd is declared and defined in WindowManager.h/.cpp.
The design flaw becomes more and more obvious, as I'm thinking about a solution!
See the pastebin link for the actual code!
Thank you very much for your help in advance.
Sincerely, Marc
You have 2 unresolved external symbols:
HWND ShirabePlatformFeatureLayer::WINAPIWindow::handle(void) const
LRESULT ShirabePlatformFeatureLayer::gDefaultWndProcFwd(HWND,UINT,WPARAM,LPARAM)
The first one is probably due to handle() being inline. You probably defined it in the CPP file (or you forgot it?) , but since it is inline, the definition is not exported. Instead it is expected to be available to every compilation unit that needs it. In other words, inline functions should be defined in the same header file as the declaration.
The second one is trickier without seeing all your code. But I'd bet that you simply forgot to write the defintion of gDefaultWndProcFwd(). Or maybe you wrote it in a different namespace, or with different parameters.
Note that static libraries are not linked, so unresolved symbol errors such as yours, will never happen when building the library, even when the defect is in the library itself. Linker errors will always happen when linking the final executable.
UPDATE: Ok, I said it was tricky... Re-reading your code I noticed that the offending function is declared twice, and defined once. That itself is not a problem, but look at the two declarations together:
LRESULT CALLBACK gDefaultWndProcFwd(HWND hWnd, UINT msg, LPARAM lParam, WPARAM wParam);
LRESULT CALLBACK gDefaultWndProcFwd(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
And the definition is:
LRESULT CALLBACK gDefaultWndProcFwd(HWND hWnd, UINT msg, LPARAM lParam, WPARAM wParam)
Do you see the difference? WPARAM and LPARAM are swapped!!!

How to get function address from loader DLL?

I have got 2 DLLs. DLL1 will be presented as MyDLL.dll and DLL2 is just a DLL containing extensions to MyDLL.
So to get these extensions from DLL2 to MyDLL, I need to load DLL2 inside MyDLL using LoadLibrary(). But here comes the problem. MyDLL contains one function, which will be very important in DLL2. And I need to reach that function. How do I do it?
#include <Windows.h>
#include <stdio.h>
#include "DLL1API.h"
typedef DLL1API* (*PGetDLL1API)();
DLL1API *g_API;
void Init();
BOOL WINAPI DllMain(HINSTANCE hMod, DWORD dwReason, LPVOID reserve){
switch(dwReason){
case DLL_PROCESS_ATTACH:
Init();
break;
}
}
void Init(){
PGetDLL1API GetDLL1API;
HMODULE mainDllMod=GetModuleHandleA("MyDLL.dll"); //how do I reach module of DLL1?
GetDLL1API=(PGetDLL1API)GetProcAddress(mainDllMod,"GetDLL1API");
if(GetDLL1API){
g_API=GetDLL1API();
printf("DLL1API: %p",g_API);
} else { //always gets to this result :(
printf("Error, failed to get GetDLL1API()!\n");
}
}
Other thing is, that I am scared to use LoadLibrary("MyDLL.dll") inside DLL2, because I think it would cause one big infinite loadLibrary loop (MyDll => DLL2 => MyDLL ...)
Calling LoadLibrary from inside DllMain is not recommended. Fix that, and your circular loading concerns will go away as well.
BTW DLL2 doesn't need to load DLL1. It can use GetModuleHandle to find the already-loaded DLL to pass to GetProcAddress, use a static import, or DLL1 can call a function exported from DLL2 passing a function pointer.
More suggested reading, with specific notes on LoadLibrary: http://blog.barthe.ph/2009/07/30/no-stdlib-in-dllmai/
You are right to not want to use LoadLibrary in DllMain. Using LoadLibrary in DllMain is expressly forbidden according to this Microsoft page. Also, GetModuleHandle only works if the DLL has already been loaded by the current process.
Are you really sure you need to load the DLL from your DllMain? You could just call GetModuleHandle from your exported functions, assuming of course that the module has been loaded by the program already.