www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Can't find windows' CreateThread function / concurrency.spawn crashes

reply alkololl <analgleit3r byom.de> writes:
Hey there and a happy new year,

I wrote a C++ Dll which gets injecrted into another process. Now 
I want to port that Dll to D. In my C++ Dll I used a while loop 
which captures all keystrokes via GetAsyncKeyState and waited for 
F7 to be pressed and lastly unloads the dll via 
FreeLibraryAndExitThread.
This while loop needs to be run out of an dedicated thread.
I've found that std.c.windows.windows doesn't include a 
definition for Windows API's CreateThread method and the usage of 
concurrency.spawn crashes my host application (in which the Dll 
gets injected to).

How am I supposed to create a thread in the host application? Or 
are there other ways to capture the F7 keystroke?
Jan 01 2016
next sibling parent alkololl <meltor trash-mail.com> writes:
Here is my code:

// File dllmain.d
module dllmain;

import core.runtime;
import std.c.stdlib;
import std.string;
import std.c.windows.windows;

import honmod;


private HINSTANCE g_hInst;


extern (Windows) BOOL DllMain(HINSTANCE hInstance, ULONG 
ulReason, LPVOID pvReserved)
{
	g_hInst = hInstance;
	
	switch (ulReason) {
		case DLL_PROCESS_ATTACH:
			Runtime.initialize();
			break;
			
		case DLL_PROCESS_DETACH:
			Runtime.terminate();
			break;
			
		default:
	}
	
	return true;
}


static this()
{
	honmod.initialize(g_hInst);
	MessageBoxA(null, "Dll Injection successful", "", MB_OK);
}


static ~this()
{
	MessageBoxA(null, "Dll ejected", "", MB_OK);
}




// File honmod
module honmod;

import std.concurrency;
import std.c.windows.windows;
import core.thread;


private HINSTANCE _hModule;



// The quit thread waits until F7 gets pressed and then frees the 
module
private void quitThread()
{
	while (true) {
		// KeyDown
		if (GetAsyncKeyState(VK_F7) & 0x0001) {
			break;
		}
		
		Sleep(1);
	}
	
	FreeLibraryAndExitThread(_hModule, 0);
}


void initialize(HINSTANCE hModule)
{
	_hModule = hModule;
	
	// Spawn the quit thread
	new Thread(&quitThread).start();
}
Jan 01 2016
prev sibling parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Friday, 1 January 2016 at 22:02:46 UTC, alkololl wrote:
 I've found that std.c.windows.windows doesn't include a
std.c.windows is basically useless. The new version should have it in core.sys.windows.windows though I'm not sure if it has actually been released yet. If it isn't in there on your version, you can also just define teh function yourself somewhere and use it. Add to your module: extern(Windows) HANDLE CreateThread( LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId ); and then call it. If a type isn't defined you can replace it with void* usually.
Jan 01 2016
parent reply alkololl <meltor trash-mail.com> writes:
On Friday, 1 January 2016 at 22:45:20 UTC, Adam D. Ruppe wrote:
 On Friday, 1 January 2016 at 22:02:46 UTC, alkololl wrote:
 I've found that std.c.windows.windows doesn't include a
std.c.windows is basically useless. The new version should have it in core.sys.windows.windows though I'm not sure if it has actually been released yet. If it isn't in there on your version, you can also just define teh function yourself somewhere and use it. Add to your module: extern(Windows) HANDLE CreateThread( LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId ); and then call it. If a type isn't defined you can replace it with void* usually.
Thanks, I replaced LPSECURITY_ATTRIBUTES and LPTHREAD_START_ROUTINE with void* and it works now. Anyhow the method FreeLibraryAndExitThread, which worked perfectly in the C++ Dll, doesn't unload the D Dll properly (the call has no effect at all). Why is that?
Jan 01 2016
parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Saturday, 2 January 2016 at 00:32:20 UTC, alkololl wrote:
  Why is that?
I'm not sure, but in the switch you posted, you didn't handle the DLL_THREAD_ATTACH and DLL_THREAD_DETACH cases, the runtime might be incrementing the refcount there. Check this out: http://wiki.dlang.org/Win32_DLLs_in_D
Jan 01 2016
parent reply alkololl <meltor trash-mail.com> writes:
On Saturday, 2 January 2016 at 01:44:46 UTC, Adam D. Ruppe wrote:
 On Saturday, 2 January 2016 at 00:32:20 UTC, alkololl wrote:
  Why is that?
I'm not sure, but in the switch you posted, you didn't handle the DLL_THREAD_ATTACH and DLL_THREAD_DETACH cases, the runtime might be incrementing the refcount there. Check this out: http://wiki.dlang.org/Win32_DLLs_in_D
Thanks for your reply. I replaced my switch statement with the one behind the link you left but the result (no result) stays the same. The Dll doesn't get unloaded. Not until I close the host application.
Jan 02 2016
parent reply Rainer Schuetze <r.sagitario gmx.de> writes:
On 02.01.2016 16:34, alkololl wrote:
 On Saturday, 2 January 2016 at 01:44:46 UTC, Adam D. Ruppe wrote:
 On Saturday, 2 January 2016 at 00:32:20 UTC, alkololl wrote:
  Why is that?
I'm not sure, but in the switch you posted, you didn't handle the DLL_THREAD_ATTACH and DLL_THREAD_DETACH cases, the runtime might be incrementing the refcount there. Check this out: http://wiki.dlang.org/Win32_DLLs_in_D
Thanks for your reply. I replaced my switch statement with the one behind the link you left but the result (no result) stays the same. The Dll doesn't get unloaded. Not until I close the host application.
D needs "implicite thread local storage" to implement thread local variables, but Windows XP and earlier versions do not support this for DLLs dynamically loaded through LoadLibrary. The D runtime implements the part necessary for loading, but does not support unloading. As a consequence it sets the DLL to never unload. If you are actually running XP, you can check https://github.com/denis-sh/hooking. IIRC Denis Shelomovskij implemented the missing parts.
Jan 02 2016
parent reply alkololl <meltor trash-mail.com> writes:
On Saturday, 2 January 2016 at 16:42:46 UTC, Rainer Schuetze 
wrote:

 On 02.01.2016 16:34, alkololl wrote:
 On Saturday, 2 January 2016 at 01:44:46 UTC, Adam D. Ruppe 
 wrote:
 [...]
Thanks for your reply. I replaced my switch statement with the one behind the link you left but the result (no result) stays the same. The Dll doesn't get unloaded. Not until I close the host application.
D needs "implicite thread local storage" to implement thread local variables, but Windows XP and earlier versions do not support this for DLLs dynamically loaded through LoadLibrary. The D runtime implements the part necessary for loading, but does not support unloading. As a consequence it sets the DLL to never unload. If you are actually running XP, you can check https://github.com/denis-sh/hooking. IIRC Denis Shelomovskij implemented the missing parts.
What? I'm actually running Windows 7. For me it's inevitable to not unload the D Dll dynamically. Isn't there some kind of workaround or a sneaky hack to solve this?
Jan 02 2016
parent Rainer Schuetze <r.sagitario gmx.de> writes:
On 02.01.2016 18:41, alkololl wrote:
 On Saturday, 2 January 2016 at 16:42:46 UTC, Rainer Schuetze wrote:

 On 02.01.2016 16:34, alkololl wrote:
 On Saturday, 2 January 2016 at 01:44:46 UTC, Adam D. Ruppe wrote:
 [...]
Thanks for your reply. I replaced my switch statement with the one behind the link you left but the result (no result) stays the same. The Dll doesn't get unloaded. Not until I close the host application.
D needs "implicite thread local storage" to implement thread local variables, but Windows XP and earlier versions do not support this for DLLs dynamically loaded through LoadLibrary. The D runtime implements the part necessary for loading, but does not support unloading. As a consequence it sets the DLL to never unload. If you are actually running XP, you can check https://github.com/denis-sh/hooking. IIRC Denis Shelomovskij implemented the missing parts.
What? I'm actually running Windows 7. For me it's inevitable to not unload the D Dll dynamically. Isn't there some kind of workaround or a sneaky hack to solve this?
If you run Windows 7, I guess the runtime patch is not the issue here. Have you tried to load the DLL explicitely (without injecting it)? Does it unload correctly in this case? If not, it should ease debugging the problem.
Jan 04 2016