Can't call function from .dll created in C++ - c++

I'm able to call function from DLL created in C (.c file), but i can't do it from DLL created in C++ (.cpp file). I want to find out why it doesn't work in .cpp file.
I'm trying to call function printword() from a simple DLL, created with Visual Studio 2022:
// FILE: dllmain.cpp
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
__declspec(dllexport) void printword() {
std::cout << "word" << std::endl; //with printf() doesn't work too
}
And when i call function the way like this:
int main() {
HMODULE dll;
if ((dll = LoadLibrary(L"D:\\Visual Studio projects\\Dll1\\x64\\Debug\\Dll1.dll")) == NULL) {
return GetLastError();
}
FARPROC func;
if ((func = GetProcAddress(dll, "printword")) == NULL) {
return GetLastError();
}
func();
return 0;
}
GetProcAddress throws error ERROR_PROC_NOT_FOUND
But if i create DLL in file with .c suffix printword() function calls correctly (with same code above):
// FILE: dllmain.c
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
__declspec(dllexport) void printword() {
printf("word\n");
}

The exported function's name will get mangled when the DLL is compiled. You must use the mangled name in GetProcAddress() in order for it to work. For example, the mangled name
in MSVC is:
GetProcAddress(dll, "?printword##YAXXZ");
Or, you could add this to the function's body to tell the compiler not to mangle it:
__declspec(dllexport) void printword() {
#pragma comment(linker, "/EXPORT:" __FUNCTION__"=" __FUNCDNAME__)
printf("word\n");
}
Alternatively, adding extern "C" will also solve the problem.

Review and try the recommendations from this article:
https://learn.microsoft.com/sr-cyrl-rs/cpp/build/exporting-cpp-functions-for-use-in-c-language-executables?view=msvc-170
Example
// MyCFuncs.h
extern "C" __declspec( dllexport ) int MyFunc(long parm1);
Key part being extern "C"
[I accidentally posted the link for importing instead of exporting earlier - corrected for the export article]

Related

Connection lost between C++ and Matlab Engine

I have a mission to call Matlab functions from C++ poject. I know there are several ways to do that, I prefer to use it through Matlab Engine.
I have several m-files work perfect in Matlab enviroment.
mymat.m
function myfig()
figure;
end
I made a dll-wrapper in C++ to connect the m-files with C++.
dllwrap.h
#pragma once
#include <Engine.h>
#pragma comment ( lib,"libmx.lib" )
#pragma comment ( lib,"libmat.lib" )
#pragma comment ( lib,"libeng.lib" )
#pragma comment ( lib,"libmex.lib" )
#ifdef DLLWRAP_EXPORTS
#define DLLWRAP_API __declspec(dllexport)
#else
#define DLLWRAP_API __declspec(dllimport)
#endif
DLLWRAP_API bool TestDll();
DLLWRAP_API void MyFigure();
dllwrap.cpp
#include "stdafx.h"
#include "dllwrap.h"
Engine* pEng = NULL;
void StartVirtualEngineMatlab()
{
if ((pEng = engOpen(NULL)) == NULL)
{
MessageBoxA(NULL, (LPSTR)"Can't start MATLAB engine!", (LPSTR) "MatLab Engine: ERROR!", MB_OK | MB_ICONSTOP);
return;
};
return;
}
void StopedVirtualEngineMatlab()
{
engClose(pEng);
return;
}
DLLWRAP_API bool TestDll()
{
if (pEng == NULL) return false;
return true;
}
DLLWRAP_API void MyFigure()
{
engEvalString(pEng, "myfig();");
}
dllmain.cpp
#include "stdafx.h"
#include "dllwrap.h"
extern Engine* pEng;
extern void StartVirtualEngineMatlab();
extern void StopedVirtualEngineMatlab();
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
StartVirtualEngineMatlab();
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
StopedVirtualEngineMatlab();
break;
}
return TRUE;
}
Now I am in focus on a Test project (C# Console Application) to call a m-files through dll-wraper.
Test.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
namespace Test
{
class Program
{
[DllImport("dllwrap.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern bool TestDll();
[DllImport("dllwrap.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void MyFigure();
static void Main(string[] args)
{
bool res = TestDll();
if (res == false)
return;
MyFigure();
}
}
}
The Test project is running and doing the job, but there is a problem. A Matlab Engine crashes in unexpected time. It may crash at the begining or after a while. I even tried to stop on breaking point right after the engOpen(NULL) function, but the crashing is seems not depending on my break.
I use Visual Studio 2013, Matlab 2015a 32bit.
Please help in advise.
Thanks.
Ok, I found the problem.
I just removed the line:
StopedVirtualEngineMatlab();
from dllmain.cpp
case DLL_PROCESS_DETACH:
StopedVirtualEngineMatlab();
break;
}
and put it as external funtion to call it from the end of the code of Test.cs.
Now it works perfect.
But still I don't understand why the DLL_PROCESS_DETACH case is invoked...?

Return double* from c++ dll to delphi program

Im trying to return the array of double (declared as double*) to delphi program. In c++ dll project I have
#define DllExport __declspec( dllexport )
extern double* array;
extern "C"
{
DllExport double* SomeMethod(double);
}
and array got deleted when Dll is unloaded
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch( ul_reason_for_call )
{
...
case DLL_PROCESS_DETACH:
delete [] array;
break;
}
return TRUE; // Successful DLL_PROCESS_ATTACH.
}
While I was testing my dll in c++ console application I got the right result after using SomeMethod from dll. Next i tried to test my dll in Delphi but the content of array returned by method is wrong. I used the following code.
TSomeMethod = function(level : Double): PDouble; cdecl;
...
var
SomeMethod: TSomeMethod;
arr: PDouble;
...
if Assigned(SomeMethod) then
begin
arr:= SomeMethod(15);
writeln(arr^:2:0);
inc(arr);
writeln(arr^:2:0);
end
...
What is a proper way to return a double* from c++ dll to use in delphi?
P.S. Other methods work in th right way. For example dll returns char* and in delphi I got it using PAnsiChar
UPDATE
Here is some C++ code from file where SomeMethod is written.
double* array; // yea it's an array that declared as external in other file;
...
double* SomeMethod(double level)
{
...
deque<double> arrayToReturn;
... // some actions with deque
array= new double[arrayToReturn.size()];
for (unsigned int i = 0; i<arrayToReturn.size(); i++)
array[i] = arrayToReturn[i];
return array;
}
The code in your question works fine. Which means that the problem lies elsewhere. Here's the proof:
C++
#include <Windows.h>
BOOL APIENTRY DllMain(HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
extern "C" {
__declspec(dllexport) double* SomeMethod(double)
{
double* array = new double[2];
array[0] = 42;
array[1] = 666;
return array;
}
}
Delphi
{$APPTYPE CONSOLE}
uses
Windows, SysUtils;
type
TSomeMethod = function(level : Double): PDouble; cdecl;
var
SomeMethod: TSomeMethod;
arr: PDouble;
lib: HMODULE;
begin
lib := LoadLibrary('MyDll.dll');
Win32Check(lib<>0);
SomeMethod := GetProcAddress(lib, 'SomeMethod');
Win32Check(Assigned(SomeMethod));
arr:= SomeMethod(15);
Writeln(arr^:3:0);
inc(arr);
Writeln(arr^:3:0);
Readln;
end.
Output
42
666

Application Crashes when hooked with MS Detours and Injected with Withdll.exe

I am hooking FindNextFile() using MS Detours. I have configured the Detours library successfully and wrote a dll named "Detuors.dll" and an application named "FNFSend.exe". The following is the code:
DLL:
#include <cstdio>
#include <stdio.h>
#include <windows.h>
#include "detours.h"
#pragma comment (lib,"detours.lib")
//Prototypes
extern "C" __declspec(dllexport) BOOL (WINAPI *pFNF)(HANDLE hFindFile, LPWIN32_FIND_DATA lpFindFileData) = FindNextFile;
extern "C" __declspec(dllexport) BOOL WINAPI MyFNF(HANDLE hFindFile, LPWIN32_FIND_DATA lpFindFileData);
//Log File
FILE* pFNFLogFile;
int counter = 0;
INT APIENTRY DllMain(HMODULE hDLL, DWORD Reason, LPVOID Reserved)
{
switch(Reason)
{
case DLL_PROCESS_ATTACH:
DisableThreadLibraryCalls(hDLL);
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(PVOID&)pFNF, MyFNF);
if(DetourTransactionCommit() == NO_ERROR)
OutputDebugString("FNF() detoured successfully");
else
OutputDebugString("FNF() not detoured");
break;
case DLL_PROCESS_DETACH:
DetourTransactionBegin(); //Detach
DetourUpdateThread(GetCurrentThread());
DetourDetach(&(PVOID&)pFNF, MyFNF);
DetourTransactionCommit();
break;
case DLL_THREAD_ATTACH:
DisableThreadLibraryCalls(hDLL);
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(PVOID&)pFNF, MyFNF);
if(DetourTransactionCommit() == NO_ERROR)
OutputDebugString("FNF() detoured successfully");
else
OutputDebugString("FNF() not detoured");
break;
case DLL_THREAD_DETACH:
break;
}
return TRUE;
}
//Open file, write contents, close it
extern "C" __declspec(dllexport) int WINAPI MyFNF(HANDLE hFindFile, LPWIN32_FIND_DATA lpFindFileData)
{
counter ++;
fopen_s(&pFNFLogFile, "C:\\FNFLog.txt", "a+");
fprintf(pFNFLogFile, "%s\n", counter);
fclose(pFNFLogFile);
return pFNF(hFindFile, lpFindFileData);
}
Both the codes compiled successfully with no errors. The application calls FindNextFile() recursively and the dll hooks it and write the counter to a file.
I then used the tool named "withdll.exe" that is provided by detours library itself to create a process with a dll injected in it. So I injected my dll into the application using command:
withdll /d:Detuors.dll "C:\FNFSend.exe"
After injection, the function is hooked successfully, i.e. the file is made in the dirctory but suddenly the application crashes. After debugging in visual studio, I saw the exception in "output.c" as follows:
Unhandled exception at 0x6265984f (msvcr90d.dll) in FNFSend.exe: 0xC0000005:
Access violation reading location 0x00000001.
Kindly help in rectifying the problem.
%s is not a valid format string for printing out a number. Use %d instead.
By specifying %s you're telling fprintf to read the memory at address counter as a string. The first value you try calling fprintf with is 1 which is why there is an access violation at address 0x00000001.

Cannot implement password filter

I try to implement password filter, so I write a simple password filter.
I followed the document in the MSDN, and make sure that the functions are declared correctly.
I compile in VS 2010.
.def file:
LIBRARY myFilt
EXPORTS
InitializeChangeNotify
PasswordFilter
PasswordChangeNotify
.cpp file:
#include <windows.h>
#include <stdio.h>
#include <ntsecapi.h>
void writeToLog(const char* szString)
{
FILE* pFile = fopen("c:\\work\\logFile.txt", "a+");
if (NULL == pFile)
{
return;
}
fprintf(pFile, "%s\r\n", szString);
fclose(pFile);
return;
}
// Default DllMain implementation
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
OutputDebugString(L"DllMain");
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
BOOLEAN __stdcall InitializeChangeNotify(void)
{
OutputDebugString(L"InitializeChangeNotify");
writeToLog("InitializeChangeNotify()");
return TRUE;
}
BOOLEAN __stdcall PasswordFilter(
PUNICODE_STRING AccountName,
PUNICODE_STRING FullName,
PUNICODE_STRING Password,
BOOLEAN SetOperation
)
{
OutputDebugString(L"PasswordFilter");
return TRUE;
}
NTSTATUS __stdcall PasswordChangeNotify(
PUNICODE_STRING UserName,
ULONG RelativeId,
PUNICODE_STRING NewPassword
)
{
OutputDebugString(L"PasswordChangeNotify");
writeToLog("PasswordChangeNotify()");
return 0;
}
I put myFilt.dll in %windir%\system32, add "myFilt" to "Notification Packages" in the registry, restart the computer, change the password, and nothing happens.
I opened depends.exe and saw that the functions are correctly:
InitializeChangeNotify
PasswordChangeNotify
PasswordFilter
Where is the mistake??
Thanks.
I found the problem! I changed the runtime library from Multi-threaded Debug DLL (/MDd) to Multi-threaded Debug (/MTd) and it works perfect! :)
– user1375970 May 5 at 10:38
Notification Packages
Specifies the dynamic-link libraries (DLLs) that are loaded or called when passwords are set or changed. To specify more than one file, list the file names one above the other by pressing ENTER between each file name.
above the other!

MS Detours 2.1 - Popping out of stack

I wont to detour PlaySoundW function inside Minesweeper.
Game is crashing as soon as it calls PlaySoundW function.
If I uncomment Beep inside my code, game beeps and than crashes.
Now code is calling original function from hooked function so it should't do anything. But it is crashing anyway.
Can you tell me what is wrong?
After debugging app in Olly I found that when detour is active not all rubbish is popped out of stack.
How to fix it?
This is my code:
#include <Windows.h>
#include <tchar.h>
#include <detours.h>
namespace Hooks
{
BOOL(__stdcall *OrgPlaySoundW)(LPCTSTR pszSound, HMODULE hmod, DWORD fdwSound) = &PlaySoundW;
BOOL HookPlaySoundW(LPCTSTR pszSound, HMODULE hmod, DWORD fdwSound)
{
//Beep(1000, 250);
//return TRUE;
return OrgPlaySoundW(pszSound, hmod, fdwSound);
}
void DetourPlaySoundW(BOOL disable)
{
if(!disable)
{
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(PVOID&)OrgPlaySoundW, &HookPlaySoundW);
DetourTransactionCommit();
} else
{
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourDetach(&(PVOID&)OrgPlaySoundW, &HookPlaySoundW);
DetourTransactionCommit();
}
}
}
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
switch(fdwReason)
{
case DLL_PROCESS_ATTACH:
Hooks::DetourPlaySoundW(FALSE);
break;
case DLL_PROCESS_DETACH:
Hooks::DetourPlaySoundW(TRUE);
break;
}
return TRUE;
}
Try setting the calling convention of HookPlaySoundW to __stdcall (because the CC of PlaySoundW is also __stdcall (from Windows.h): WINMMAPI BOOL WINAPI PlaySoundW( __in_opt LPCWSTR pszSound, __in_opt HMODULE hmod, __in DWORD fdwSound);).
I have worked with detours before and after a casual glance everything looks correct except what I mentioned above. If this doesn't resolve your problem I'd be glad to do some further investigation.
The default setting for Visual C++ is __cdecl in which the call*er* cleans up the stack, but in __stdcall the call*ee* cleans up the stack. This is probably (i.e. might possibly be) the reason for all the "rubbish being popped off the stack".