I'm trying to build a windows dll using mingw-64 that once loaded starts printing "Hello World" indefinetly.
Here's my dll.c
#include <stdio.h>
#include <windows.h>
#include "dll.h"
#include "main.h"
HINSTANCE hThisModule;
DWORD mainThread() {
while(1) {
printf("Hello world!");
}
}
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {
static HANDLE hThread;
hThisModule = hinstDLL;
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
hThread = CreateThread(0, 0, mainThread, 0, 0, 0);
break;
case DLL_PROCESS_DETACH:
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
}
return TRUE;
}
void dummy() {
Hello();
}
and here's my dll.h:
#ifndef DLL_H_
#define DLL_H_
#ifdef BUILD_DLL
/* DLL export */
#define EXPORT __declspec(dllexport)
#else
/* EXE import */
#define EXPORT __declspec(dllimport)
#endif
#endif /* DLL_H_ */
so I've built a simple program that loads my DLL to see if it's working correctly, here it is: hello.cpp
#include <windows.h>
#include <iostream>
typedef int (__stdcall *f_funci)();
int main()
{
HINSTANCE hGetProcIDDLL = LoadLibrary("./wow.dll");
if (!hGetProcIDDLL) {
std::cout << "could not load the dynamic library" << std::endl;
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
Now, when I compile hello.cpp into hello.exe and dll.c into wow.dll, I get nothing on my console. What's wrong?
As has been already mentioned, your mainThread function has wrong signature. Try something like this:
DWORD WINAPI mainThread(LPVOID lpParam)
{
UNREFERENCED_PARAMETER(lpParam);
while (1)
{
printf("Hello world!\n");
Sleep(1000);
}
return 0;
}
This works just fine for me. I modified your .exe so that you could drag and drop .dll onto it to test:
#include <windows.h>
#include <iostream>
int main(int argc, char *argv[])
{
if (argc < 2)
{
std::cout << "drag drop dll over exe" << std::endl;
std::cin.get();
return EXIT_FAILURE;
}
HINSTANCE hGetProcIDDLL = LoadLibraryA(argv[1]);
if (!hGetProcIDDLL)
{
std::cout << "could not load the dynamic library" << std::endl;
std::cin.get();
return EXIT_FAILURE;
}
std::cin.get();
return EXIT_SUCCESS;
}
First, I'd like to mention that it is not advisable to implement such a busy loop in your thread.
As for the issue you are experiencing, there are several potential issues here:
printf is a CRT function, however you are calling CreateThread() instead of beginthread(ex), so the CRT is not initialized properly.
Dll entry point is a notoriously problematic place. You can hardly call any kernel32 function from there, let alone CRT ones (see DllMain entry point and Dynamic Link Library Best Practices).
In most cases, it is advisable to implement separate Init and Exit functions that the client will need to call when using your library.
Related
I have a simple project running under Windows. It consists of two DLLs and one EXE.
The EXE loads the two DLLs. Each will create a shared memory object in a class instatiated by a std::unique_ptr globaly. The crash happens during FreeLibrary and only if I use the /MTd switch (Multi-threaded Debug) instead of /MDd (Multi-threaded Debug DLL).
I built boost libs using:
b2.exe -a -j %NUMBER_OF_PROCESSORS% --prefix=%BOOST% --libdir=%BOOST%/lib/x86 --reconfigure --build-type=complete --toolset=msvc-14.2 link=static address-model=32 runtime-link=static runtime-link=shared threading=multi define=BOOST_USE_WINDOWS_H define=NOMINMAX install
where %BOOST% points to my BOOST installation folder.
I hope someone can help me,
Christian.
The example code:
APOLLOSHM\dllmain.cpp
#include <memory>
#include "../shared/SHMBASE.h"
std::unique_ptr<SHM> shm;
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call, LPVOID )
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
shm = std::make_unique<SHM>("a_shm");
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
PHONYXSHM\dllmain.cpp
#include <memory>
#include "../shared/SHMBASE.h"
std::unique_ptr<SHM> shm;
BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID )
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
shm = std::make_unique<SHM>("p_shm");
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
shared\SHMBASE.h
#ifndef SHAREDMEM_H
#define SHAREDMEM_H
#include <boost/interprocess/shared_memory_object.hpp>
#include <boost/interprocess/mapped_region.hpp>
class SHMBASE
{
boost::interprocess::shared_memory_object shm;
boost::interprocess::mapped_region region;
protected:
void* addr{ nullptr };
public:
SHMBASE(const char* n)
{
try {
boost::interprocess::shared_memory_object::remove(n);
shm = boost::interprocess::shared_memory_object(
boost::interprocess::open_or_create,
n, boost::interprocess::read_write);
}
catch (boost::interprocess::interprocess_exception & ex) {
throw std::runtime_error(ex.what());
}
}
void create_shm(size_t size)
{
shm.truncate(size);
region = boost::interprocess::mapped_region(shm,
boost::interprocess::read_write);
addr = region.get_address();
}
};
struct shared_memory_info
{
char x[20];
int y;
};
class SHM : public SHMBASE
{
public:
SHM(const char* n) :
SHMBASE(n)
{
create_shm(sizeof(shared_memory_info));
shm = static_cast<shared_memory_info*>(addr);
}
shared_memory_info* shm;
};
#endif
SharedMemTest\SharedMemTest.cpp
#include <iostream>
#include <utility>
#include <vector>
#include <string>
#include <Windows.h>
struct LIBOBJ
{
HMODULE libhandle{ nullptr };
LIBOBJ(std::string libname){
libhandle = LoadLibraryA(libname.c_str());
if (!libhandle) {
throw std::runtime_error("Cannot open library");
}
}
~LIBOBJ() {
if (libhandle){
FreeLibrary(libhandle);
}
}
};
int main(){
std::vector<std::string> dlls = {"ApolloSHM.dll", "PhonyxSHM.dll"};
std::vector<std::unique_ptr<LIBOBJ> > objs;
try{
for (auto& n : dlls){
objs.emplace_back(std::make_unique<LIBOBJ>(n));
}
// if freelibrary in reverse order no crash
// for (auto it = objs.rbegin(); it != objs.rend(); ++it)
// if in order of loading it crashes, but only with /MTd
// for (auto it = objs.begin(); it != objs.end(); ++it)
for (auto it = objs.begin(); it != objs.end(); ++it){
it->reset();
}
}
catch (std::exception & e){
std::cout << "Exception: " << e.what() << std::endl;
}
return 0;
}
I think I solved the issue (maybe just for me). The problem isn't the /MTd switch of the compiler.
I think the problem is related to the singleton implementation inside boost::interprocess::shared_memory_object. My project structure is as follows:
An EXE file loads a DLL (a driver wrapper) which can load several device driver DLLs in parallel. Two of the driver DLLs are using their own shared_memory_object's as described in the doc and it work in both cases. Until I call FreeLibrary for the driver DLLs. In that case always the second FreeLibrary crashes (but not with /MDd I didn't understand this seconds fact, sorry).
I solved the issue by creating a boost::interprocess::shared_memory_object inside the driver wrapper DLL. I just instantiate such an object and in the next line I remove it. If I do this my DLLs does not crash any more.
I hope this helps the developer of boost::interprocess.
Kind regards,
Christian
I'm have a dll file that exports a function where i will load inside another dll file.
My problem is that not is possible find function on second dll, tried do equals this tutorial, but nothing of success until now .
Any suggestion will welcome.
Code:
below is dll that loads a function that is exported by another dll:
Code:
below is dll that loads a function that is exported by another dll:
// dllmain.cpp : Defines the entry point for the DLL application.
#include "stdafx.h"
#include <windows.h>
#include <fstream>
#include <string>
#include <iostream>
using namespace std;
typedef BOOL (WINAPI *TERMINATEPROCESS_PROC)(HANDLE, UINT);
TERMINATEPROCESS_PROC HookFunction(char *UserDll,TERMINATEPROCESS_PROC pfn,TERMINATEPROCESS_PROC HookFunc)
{
DWORD dwSizeofExportTable=0;
DWORD dwRelativeVirtualAddress=0;
HMODULE hm=GetModuleHandle(NULL);
PIMAGE_DOS_HEADER pim=(PIMAGE_DOS_HEADER)hm;
PIMAGE_NT_HEADERS pimnt=(PIMAGE_NT_HEADERS)((DWORD)pim +
(DWORD)pim->e_lfanew);
PIMAGE_DATA_DIRECTORY
pimdata=(PIMAGE_DATA_DIRECTORY)&(pimnt->OptionalHeader.DataDirectory);
PIMAGE_OPTIONAL_HEADER pot=&(pimnt->OptionalHeader);
PIMAGE_DATA_DIRECTORY
pim2=(PIMAGE_DATA_DIRECTORY)((DWORD)pot+(DWORD)104);
dwSizeofExportTable=pim2->Size;
dwRelativeVirtualAddress=pim2->VirtualAddress;
char *ascstr;
PIMAGE_IMPORT_DESCRIPTOR
pimexp=(PIMAGE_IMPORT_DESCRIPTOR)(pim2->VirtualAddress + (DWORD)pim);
while(pimexp->Name)
{
ascstr=(char *)((DWORD)pim + (DWORD)pimexp->Name);
if(_strcmpi(ascstr,UserDll) == 0)
{
break;
}
pimexp++;
}
PIMAGE_THUNK_DATA
pname=(PIMAGE_THUNK_DATA)((DWORD)pim+(DWORD)pimexp->FirstThunk);
LPDWORD lpdw=&(pname->u1.Function);
DWORD dwError=0;
DWORD OldProtect=0;
while(pname->u1.Function)
{
if((DWORD)pname->u1.Function == (DWORD)pfn)
{
lpdw=&(pname->u1.Function);
VirtualProtect((LPVOID)lpdw,sizeof(DWORD),PAGE_READWRITE,&OldProtect);
pname->u1.Function=(DWORD)HookFunc;
VirtualProtect((LPVOID)lpdw,sizeof(DWORD),PAGE_READONLY,&OldProtect);
return pfn;
}
pname++;
}
return (TERMINATEPROCESS_PROC)0;
}
TERMINATEPROCESS_PROC CallHook(void)
{
DWORD dwAddOfTerminateProcess;
HMODULE hm=GetModuleHandle(TEXT("Kernel32.dll"));
TERMINATEPROCESS_PROC fp=(TERMINATEPROCESS_PROC)GetProcAddress(hm,"TerminateProcess");
HMODULE hm2=GetModuleHandle(TEXT("Math.dll"));
TERMINATEPROCESS_PROC fpHook=(TERMINATEPROCESS_PROC)GetProcAddress(hm2,"MyTerminateProcess");
dwAddOfTerminateProcess=(DWORD)HookFunction("Kernel32.dll",fp,fpHook);
if(dwAddOfTerminateProcess == 0)
{
MessageBox(NULL,TEXT("Unable TO Hook Function."),TEXT("Parth"),MB_OK);
}
else
{
MessageBox(NULL,TEXT("Success Hooked."),TEXT("Parth"),MB_OK);
}
return 0;
}
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
CallHook();
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
here is dll that contains function to be exported:
// dllmain.cpp : Defines the entry point for the DLL application.
#include "stdafx.h"
#include "Mathlib.h"
// a sample exported function
BOOL DLL_EXPORT MyTerminateProcess(HANDLE hProcess,UINT uExitCode)
{
SetLastError(5);
return FALSE;
}
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;
}
header.h file:
#ifndef __MAIN_H__
#define __MAIN_H__
#include <windows.h>
/* To use this exported function of dll, include this header
* in your project.
*/
#define DLL_EXPORT __declspec(dllexport)
#ifdef __cplusplus
extern "C"
{
#endif
BOOL DLL_EXPORT MyTerminateProcess(HANDLE hProcess,UINT uExitCode);
#ifdef __cplusplus
}
#endif
#endif // __MAIN_H__
I'm trying to export a function called CreateGameClient and when I do dumpbin /exports I get this instead ?CreateGameClient##YAXXZ and the program I'm injecting the DLL into needs CreateGameClient and not ?CreateGameClient##YAXXZ
And I'm using Visual Studio 2012 if that helps
This is my code ExpFunc.h
#ifndef INDLL_H
#define INDLL_H
#ifdef EXPORTING_DLL
__declspec(dllexport) void CreateGameClient() ;
#else
__declspec(dllimport) void CreateGameClient() ;
#endif
#endif
Main.cpp
#include "stdafx.h"
#include <Windows.h>
#include <string.h>
#include <sstream>
#include <stdio.h>
#include <fstream>
#define EXPORTING_DLL
#include "ExpFunc.h"
void WriteLogFile(const char*);
void CreateGameClient2(int);
char* logStr;
char* CGCNStr;
char buf[250];
DWORD pid = GetCurrentProcessId();
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:
logStr = "Attached To: %d";
sprintf(buf, logStr, pid);
WriteLogFile(buf);
break;
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
logStr = "Detached To: %d";
sprintf(buf, logStr, pid);
WriteLogFile(buf);
break;
}
return TRUE;
}
void CreateGameClient()
{
CreateGameClient2(2);
}
void CreateGameClient2(int num)
{
std::stringstream temp_str;
temp_str << (num);
std::string str = temp_str.str();
const char* cstr2 = str.c_str();
sprintf(buf, cstr2, pid);
WriteLogFile(buf);
}
void WriteLogFile(const char* szString)
{
FILE* pFile = fopen("logFile.txt", "a");
fprintf(pFile, "%s\n",szString);
fclose(pFile);
}
I have tried C++ DLL Export: Decorated/Mangled names
but still didn't work
You must decorate both declaration and definition of a function with extern "C" __declspec(...) otherwise you should be getting a warning about non consistent linking definition and erratic behaviour.
I'm building a password filter as demonstrated with by the following link: http://msdn.microsoft.com/en-us/library/windows/desktop/ms721882(v=vs.85).aspx
I attempted to build a dll and load it on a test machine following the instructions provided by MS and discovered something was obviously wrong as the dll was not getting loaded. So I then decided to run a unit test program on the dll and that doesn't seem to work either. Rather, it works if I use mangled functions without use of the extern "C" directive or an .def file. As soon as I do use extern "C" or the def file, the code doesn't work.
The Code below produces the error code 127: The specified procedure could not be found. Despite me using extern "C" and using Dependency Walker to get the name of the function, I'm told by the code that the function could not be found.
Here is the unit test app:
#include "stdafx.h"
#include <Windows.h>
#include <NTSecAPI.h>
#include <strsafe.h>
typedef NTSTATUS (__stdcall *MYPROC)(PUNICODE_STRING, ULONG, PUNICODE_STRING);
int _tmain(int argc, _TCHAR* argv[])
{
MYPROC ProcAdd;
HMODULE MyDllHnd = LoadLibrary(TEXT("C:\\Users\\mmatovic\\Documents\\Visual Studio 2012\\Projects\\PasswordFilterUnitTest\\Debug\\PasswordFilter.dll"));
if (NULL == MyDllHnd)
{
DWORD dwError = GetLastError();
cout << "Error: " << dwError << endl;
}
ProcAdd = (MYPROC)GetProcAddress(
MyDllHnd,
"PasswordChangeNotify");
ULONG rid = 0;
if (NULL != ProcAdd)
{
(ProcAdd)((PUNICODE_STRING)"test",(ULONG)0,(PUNICODE_STRING)"test");
} else {
DWORD dwProcError = GetLastError();
cout << "Error: " << dwProcError << endl;
}
return 0;
}
Here is the code for the actual DLL:
#include "stdafx.h"
#define LOGFILE "c:\\PasswordFilter.txt"
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;
}
void WriteToLog (PUNICODE_STRING str)
{
#ifdef LOGFILE
FILE* log = fopen(LOGFILE, "a");
if(NULL == log)
{
return;
}
fprintf(log, "%s\r\n", str);
fclose(log);
#endif
return;
}
BOOLEAN __stdcall InitializeChangeNotify(void)
{
return TRUE;
}
NTSTATUS __stdcall PasswordChangeNotify(
PUNICODE_STRING UserName,
ULONG RelativeId,
PUNICODE_STRING NewPassword
)
{
WriteToLog(UserName);
WriteToLog(NewPassword);
return 0;
}
BOOLEAN __stdcall PasswordFilter(
PUNICODE_STRING AccountName,
PUNICODE_STRING FullName,
PUNICODE_STRING Password,
BOOLEAN SetOperation
)
{
return TRUE;
}
And lastly the contents of the .def file
LIBRARY PasswordFilter
EXPORTS
InitializeChangeNotify
PasswordChangeNotify
PasswordFilter
Also the stdafx.h file generated in VS for the DLL code:
#pragma once
#include "targetver.h"
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
// Windows Header Files:
#include <stdio.h>
#include <windows.h>
#include <winnt.h>
#include <NTSecAPI.h>
I'm in the process of writing a dll-injected global keyboard hook but have run into a problem which I can't seem to get past. So far I have one program which is in charge of loading the dll and calling the SetWindowsHookEx, and ofcourse the dll to be injected.
The DLL looks like this:
#include "stdafx.h"
#include <stdio.h>
#include <windows.h>
#include <string>
using namespace std;
INT APIENTRY DllMain(HMODULE hDLL, DWORD Reason, LPVOID Reserved) {
switch(Reason) {
case DLL_PROCESS_ATTACH:
//fprintf(file, "DLL attach function called.\n");
break;
case DLL_PROCESS_DETACH:
//fprintf(file, "DLL detach function called.\n");
break;
case DLL_THREAD_ATTACH:
//fprintf(file, "DLL thread attach function called.\n");
break;
case DLL_THREAD_DETACH:
//fprintf(file, "DLL thread detach function called.\n");
break;
}
return TRUE;
}
extern "C" __declspec(dllexport) int meconnect(int code, WPARAM wParam, LPARAM lParam) {
if (code == HC_ACTION)
{
FILE *file;
string c;
c += (char)wParam;
fopen_s(&file, "c:\\temp2.txt", "a+");
fprintf(file, c.c_str());
fclose(file);
}
return(CallNextHookEx(NULL, code, wParam, lParam));
}
The main program looks like this:
#include <Windows.h>
#include <iostream>
#include <SDKDDKVer.h>
using namespace std;
void CheckForExit(HHOOK handle);
int main()
{
/*
* Load library in which we'll be hooking our functions.
*/
HMODULE dll = LoadLibrary(L"dllinject.dll");
if (dll == NULL) {
printf("The DLL could not be found.n");
//getchar();
return -1;
}
/*
* Get the address of the function inside the DLL.
*/
HOOKPROC addr = (HOOKPROC)GetProcAddress(dll, "meconnect");
if (addr == NULL) {
printf("The function was not found.n");
//getchar();
return -1;
}
DWORD id = GetCurrentThreadId();
HHOOK handle = SetWindowsHookEx(WH_KEYBOARD, addr, dll, 0);
if (handle == NULL) {
printf("The KEYBOARD could not be hooked.n");
}
/*
* Unhook the function.
*/
system("pause");
UnhookWindowsHookEx(handle);
return 0;
}