I have the following code:
#include <windows.h>
class systemfunctions
{
public:
void (*sleep) (DWORD ms);
systemfunctions ()
{
sleep = reinterpret_cast<void>(Sleep);
}
} sys;
When I call sys.sleep(), the application crashes. Why does the program crash, and what can I do to resolve the problem?
Windows.h declares Sleep() like WINBASEAPI VOID WINAPI Sleep(__in DWORD dwMilliseconds);, try telling the compiler it needs to use the proper calling convention when it uses that pointer:
typedef VOID (WINAPI * SleepFunction)(DWORD ms);
SleepFunction sleep;
sleep = Sleep;
The only time you should cast a function pointer is when using the return value from GetProcAddress.
Get rid of the cast, and then the compiler will tell you what is wrong.
Related
I am using VS2019
Trying to call a thread in DLL. to run two executables simultaneously with detach
following threads worked when I Run a normal c++ program
I get error
Error C3867 'myClass::runexeone': non-standard syntax; use '&' to create a pointer to member myGateway C:\Users\user\Downloads\Demo\myGateway\myplugin.cpp 21
plugin header
#include <windows.h>
#include <iostream>
#include <thread>
#define MYPLUGIN_EXPORT __declspec(dllexport)
extern "C"
{
MYPLUGIN_EXPORT void WINAPI OnStart();
}
pluging.cpp
#include "plugin.h"
using namespace std;
class myClass
{
public:
myClass()
{
}
~myClass()
{
}
void onStart()
{
std::thread(runexeone).detach();
std::thread(runexetwo).detach();
}
void runexeone()
{
int exerunpne = system("cmd /C \"%MY_ROOT%\\bin\\Mytest.exe\" -ORBEndpoint iiop://localhost:12345 -d");
}
void runexetwo()
{
int exeruntwo = system("cmd /C \"%MY_ROOT%\\bin\\Mytest_2.exe\" -ORBEndpoint iiop://localhost:12345 -d");
}
};
myClass& getmyclass()
{
static myClass myclass;
return myclass;
}
MYPLUGIN_EXPORT void WINAPI OnStart()
{
getmyClass().onStart();
}
The problem is that runexeone is an unqualified name of a member function, and std::thread needs something executable. runexeone isn't. VC++ tries to guess from context what you mean, but the suggestion isn't enough. Even if you had written &myClass::runexeone, it still wouldn't have worked, because myClass::runexeone also needs a this pointer. You can fix the latter problem by making it static.
Compiler suggestions work best when there's just one problem.
As MSalters already mentioned, you provided the wrong data type for the functor for std::thread. If you cannot make the method static (which you can actually at least for the current state of your code, but to let this not be unstated here), you can do this
void onStart()
{
std::thread(std::bind(&myClass::runexeone, this)).detach();
}
But be careful about the lifetime/existence of your object/this!
I just want to call the function from the API. WhozCraig just now told me that mine is just a type and not a function. But I still don't know how to solve this. How should i declare this instead of just typedef? Sorry, I'm a noob. Thanks for your help guys!
#include <Windows.h>
#include <stdlib.h>
#include <conio.h>
#include <stdio.h>
#include "ftrScanAPI.h"
typedef FTR_API_PREFIX FTRHANDLE (FTR_API *MyftrScanOpenDevice)();
MyftrScanOpenDevice NowftrScanOpenDevice;
void main()
{
FTRHANDLE hDevice=NULL;
PVOID pBuffer;
FTRSCAN_IMAGE_SIZE ImageSize;
hDevice=LoadLibrary("ftrScanAPI.dll");
if(hDevice==NULL)
{ printf("Failed to detect ScanAPI.dll");
getch();
exit(EXIT_FAILURE);
}
hDevice = NowftrScanOpenDevice();
}
Here's a snippet from the API:
FTR_API_PREFIX FTRHANDLE FTR_API ftrScanOpenDevice();
The variable NowftrScanOpenDevice is a pointer to a function, and as it's a global variable it's zero-initialized. By calling it, you are in effect dereferencing a NULL pointer, which is undefined behavior and leads to the crash.
You need to use GetProcAddress to get the actual address of the function, and assign it to NowftrScanOpenDevice:
...
HMODULE hLibrary = LoadLibrary(...);
NowftrScanOpenDevice = (MyftrScanOpenDevice) GetProcAddress(hLibrary,
"ftrScanOpenDevice");
hDevice = NowftrScanOpenDevice();
...
Note: I added a new variable hLibrary for the handle returned by LoadLibrary. You need it to later call FreeLibrary.
I created a DLL file (helloWorld.dll):
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#define DLL_FUNC extern "C" __declspec(dllexport)
DLL_FUNC int __stdcall Hello() {
MessageBox(HWND_DESKTOP, "Hello, world", "MEssage", MB_OK);
return 0;
}
After that I created a cpp where I would like to call (useDLL.cpp)
#include <windows.h>
#include <stdio.h>
int main () {
typedef void (*pfunc)();
HINSTANCE hdll = LoadLibrary("HelloWorld.dll");
pfunc Hello;
Hello = (pfunc)GetProcAddress(hdll, "hello");
Hello();
return 0;
}
How can I call the Hello() function?
The code in the question contains a number of errors:
LoadLibrary returns HMODULE and not HINSTANCE
The function pointer has the wrong return value and an incorrect calling convention.
Function names are case sensitive and you must account for name decoration.
You did no error checking at all. Your code probably fails on the call to GetProcAddress, returns NULL and then bombs when you try to call the function at NULL.
So you need something like this:
typedef int (__stdcall *HelloProc)();
....
HMODULE hdll = LoadLibrary("HelloWorld.dll");
if (hdll == NULL)
// handle error
HelloProc Hello = (HelloProc)GetProcAddress(hdll, "_Hello#0");
if (Hello == NULL)
// handle error
int retval = Hello();
The function name is decorated because you used __stdcall. If you had used __cdecl, or a .def file, then there would have been no decoration. I'm assuming MSVC decoration. It seems that decoration differs with your compiler, mingw, and the function is named "Hello#0".
Frankly it's much easier to do it with a .lib file instead of calling LoadLibrary and GetProcAddress. If you can, I'd switch to that way now.
You need to specifically search and find specific functions you are lookins for, check out this link:
Calling functions in a DLL from C++
This feels like a noob question, so if it's a dupe, please point me to the right location :)
I tried including a DLL written in C into a C++ program. It didn't work; gcc said
test.cpp: xxx: error: too many arguments to function.
Here's a minimal working example:
Wrapper for DLL functions:
/* myWrapper.h */
#ifndef _MYWRAPPER_H
#define _MYWRAPPER_H
#include <windows.h>
#ifdef __cplusplus
extern "C" {
#endif
extern FARPROC EXPORTED_functionNameP;
int GetDLLpointers();
#ifdef __cplusplus
}
#endif
#endif
Implementation thereof:
/* myWrapper.c */
#include <windows.h>
#include "myHeader.h"
#ifdef __cplusplus
extern "C" {
#endif
HINSTANCE drvsHANDLE;
extern FARPROC EXPORTED_functionNameP;
int GetDLLpointers()
{
static int result;
drvsHANDLE = LoadLibrary("myLibrary.dll");
if (drvsHANDLE == NULL) return (result=0);
EXPORTED_functionNameP = GetProcAddress(
drvsHANDLE, "originalFunctionName");
if (EXPORTED_functionNameP == NULL) return (result = 0);
return (result = 1);
}
#ifdef __cplusplus
}
#endif
Naturally, I haven't written these nor the library myself, and preferably, they should all stay untouched. I did however add the extern "C" lines.
Then, my main file:
// my Main
#include <windows.h>
#include "myHeader.h"
int main(int argc, char **argv)
{
int arg = 1;
EXPORTED_functionNameP(arg);
return 0;
}
Build commands:
gcc -I. -c -o myHeader.o myHeader.c -L. -lmyLibrary
g++ -I. -o main.exe myMain.cpp myHeader.o -L. -lmyLibrary
It works fine if I rewrite my main.cpp into valid C and compile with gcc instead of g++.
I tried changing extern "C" into extern "C++" to no avail, I tried all permutations or gcc and g++ for the two build commands, nothing.
I know it's something to do with name mangling, but I thought gcc would take care of that when you include the extern "C" lines...Can someone please explain what I'm missing here?
In case it matters --
Windows XP Pro (will be Win7 later on)
(MinGW) gcc 4.6.2
I know this is a very old question, but I am having exactly the same issues but in relation to writing a generic wrapper template for wrapping calls to LoadLibrary() and GetProcAddress()
Taking https://blog.benoitblanchon.fr/getprocaddress-like-a-boss/ as inspiration, it looks like he is taking FARPROC as a kind of "void* for Windows functions" and then casting it to the correct type subsequently.
I needed to tweak that code a little to work for me, and reproduce it here:
class ProcPtr
{
public:
explicit ProcPtr(FARPROC ptr) : m_ptr(ptr) {}
template <typename T>
operator T* () const { return reinterpret_cast<T*>(m_ptr); }
private:
FARPROC m_ptr;
};
class DllHelper
{
public:
explicit DllHelper(LPCTSTR filename) : m_module(LoadLibrary(filename)) {}
~DllHelper() { FreeLibrary(m_module); }
ProcPtr operator[](LPCSTR proc_name) const
{
return ProcPtr(::GetProcAddress(m_module, proc_name));
}
private:
HMODULE m_module;
};
So, with that helper code now available we can use it to write a wrapper class that encapsulates several functions in the Advapi32 library:
class Advapi32
{
public:
Advapi32() : m_dll(TEXT("Advapi32"))
{
getUserName = m_dll["GetUserNameA"];
openSCManager = m_dll["OpenSCManagerA"];
bogusFunction = m_dll["BogusFunctionThatDoesNotExist"];
}
decltype(GetUserNameA)* getUserName;
decltype(OpenSCManagerA)* openSCManager;
decltype(GetWindowsDirectoryA)* bogusFunction;
private:
DllHelper m_dll;
};
bogusFunction is a function with the same signature as GetWindowsDirectoryA but which doesn't exist in Advapi32. This is what I was trying to achieve - graceful fallback on an older OS which might not have a certain function.
So, finally a test app...
int main()
{
Advapi32 advapi32;
auto func1 = advapi32.getUserName;
if (func1)
{
TCHAR infoBuf[256];
DWORD bufCharCount = sizeof(infoBuf);
if (func1(infoBuf, &bufCharCount))
{
std::cout << "Username: " << infoBuf << std::endl;
}
}
auto func2 = advapi32.openSCManager;
if (func2)
{
SC_HANDLE handle = func2(NULL, NULL, SC_MANAGER_CONNECT);
if (handle)
{
std::cout << "opened SC Manager" << std::endl;
}
}
auto func3 = advapi32.bogusFunction;
if (func3)
{
std::cerr << "This should not happen!" << std::endl;
}
else
{
std::cout << "Function not supported" << std::endl;
}
}
Output:
Username: TestAccount
opened SC Manager
Function not supported
Note: This was compiled as a Windows 32-bit console application with MBCS rather than Unicode, under VS2019 with the VS2015_XP toolset, since that is what I am needing to target (don't ask).
The FARPROC type is a function pointer for a function that takes no parameters. You should declare EXPORTED_functionNameP like so (replacing void with whatever the function really returns):
extern void (*EXPORTED_functionNameP)(int);
And initialize it like so (the returned value from GetProcAddress() pretty much always needs to be cast to the correct type):
EXPORTED_functionNameP = (void (*)(int)) GetProcAddress(drvsHANDLE, "originalFunctionName");
A typedef for the funciton type might make things a bit more readable.
There is a difference between C and C++.
int (FAR WINAPI * FARPROC) ()
In C, the FARPROC declaration indicates a callback function that has an unspecified parameter list. In C++, however, the empty parameter list in the declaration indicates that a function has no parameters.
The MSDN page on CallWindowProc explains a bit more.
After a quick Google search, it seems that FARPROC is defined as this:
typedef int (FAR WINAPI *FARPROC)();
That is, FARPROC is a function that returns an int and takes no arguments. So you can't use it for any other case.
Instead declare EXPORTED_functionNameP like this:
extern void (*EXPORTED_functionNameP)(int);
Now EXPORTED_functionNameP is a pointer to a function that takes an int argument and returns no value.
It is because of FARPROC is defined as:
int (FAR WINAPI * FARPROC) ()
So you can not pass any parameters to such function in C++. For fix it you should define EXPORTED_functionNameP as pointer to function with equal semantics as defined in DLL-library. For example:
typedef (void* EXPORTED_functionNameP)(int value);
EXPORTED_functionNameP ExportedFns;
...
ExportedFns = GetProcAddress(drvsHANDLE, "originalFunctionName");
FARPROC is defined as
typedef int (FAR WINAPI *FARPROC)();
When you pass an additional argument although the argument list of the prototype is empty you get the error.
You need a proper prototype definition for PORTED_functionNameP and cas the result from GetProcAddress to that type in your GetDLLPopinters functions.
code:
#include <cstdlib>
#include <iostream>
#include <windows.h>
using namespace std;
void calldll();
int main(int argc, char *argv[])
{
calldll();
system("PAUSE");
return EXIT_SUCCESS;
}
void calldll()
{
HINSTANCE LoadMe;
LoadMe = LoadLibrary("Trans_ATL.dll");
if(LoadMe!=0)
cout<<"loaded successfully\n";
else
cout<<"loading error\n";
/* get pointer to the functions in the dll*/
FARPROC function01 = GetProcAddress(LoadMe,"EnableLastCharTashkeel");
FARPROC function02 = GetProcAddress(LoadMe,"EnableEmphaticLAM_RAA");
FARPROC function03 = GetProcAddress(LoadMe,"SetText");
FARPROC function04 = GetProcAddress(LoadMe,"GetResult");
typedef void (__stdcall * pICFUNC01)(bool);
typedef void (__stdcall * pICFUNC02)(bool);
typedef bool (__stdcall * pICFUNC03)(string);
typedef string (__stdcall * pICFUNC04)(string);
pICFUNC01 EnableLastCharTashkeel_function;
EnableLastCharTashkeel_function = pICFUNC01(function01);
pICFUNC02 EnableEmphaticLAM_RAA_function;
EnableEmphaticLAM_RAA_function = pICFUNC02(function02);
pICFUNC03 SetText_function;
SetText_function = pICFUNC03(function03);
pICFUNC04 GetResult_function;
GetResult_function = pICFUNC04(function04);
EnableLastCharTashkeel_function(true);
EnableEmphaticLAM_RAA_function(true);
FreeLibrary(LoadMe);
}
in this code i call a dll it load successfully but when i try to use any function it compile without any errors but at the line
EnableLastCharTashkeel_function(true); (first call for a function)
it froozes and give me the following
Unhandled exception at 0x00000000 in test_trans_new.exe: 0xC0000005: Access violation reading location 0x00000000.
i guess that this becuse the function pointer point to NULL but i don't know how to fix it
i use visual c++ 2010
thanks in advance
thank you for all your replies which are realy helpfull but the problem still ocurrs but i approximately know the reason if i correct the problem is that the functions i try to access are of type COM so any idea about using this type
thanks in advance
FARPROC function01 = GetProcAddress(LoadMe,"EnableLastCharTashkeel");
That's a guaranteed NULL. Calling it does go kaboom, you didn't check if the function succeeded. The exported function is not named "EnableLastCharTashkeel". A more likely string is "?EnableLastCharTashkeel##YAX_N#Z". That's the name of the function after the C++ compiler mangled it, a trick to support overloaded functions.
You can declare the function extern "C", that suppresses name mangling and makes the function name "_EnableLastCharTashkeel". Note the leading underscore, used by the 32-bit compiler to mark that the function uses the __cdecl calling convention. To be sure, run Dumpbin.exe /exports on your DLL from the Visual Studio Command Prompt, it shows the exported names.
It's most likely 0 because the symbol you were trying to find in the DLL wasn't found, which would suggest that (a) it's either not there or (b) there might be a typo in the function name or (c) the function name might be mangled because it's being exported as a decorated name. This happens quite a lot in C++...
Unless the library exporting those four functions is under your control, use dumpbin /EXPORTS and have a look at the correct spelling of the symbols.