Hi,

I'm fairly new to win32 programming. I've been trying to create a window from within my DLL (don't ask) and I've had limited success so far. I've followed several tutorials and read many discussion forums but no matter what I do, my code seems to always cause mIRC to crash. The window creation code below is something I found in one of the tutorials I've read with very little modifications by me (variable names etc).

Code:
#include <windows.h>

#define MYMENU_EXIT         (WM_APP + 101)
#define MYMENU_MESSAGEBOX   (WM_APP + 102) 

// WndProc for the new window
LRESULT CALLBACK DLLWindowProc (HWND, UINT, WPARAM, LPARAM);

HINSTANCE dllInstance;
HWND mIRC_window;

typedef struct {
	DWORD  mVersion;
	HWND   mHwnd;
	BOOL   mKeep;
	BOOL   mUnicode;
} LOADINFO;

void __stdcall LoadDll(LOADINFO*);
int __stdcall UnloadDll(int);

int __stdcall UnloadDll(int mTimeout) {
	return 0; // keep the dll loaded
}

void __stdcall LoadDLL(LOADINFO *load) {
	load->mKeep = TRUE;
}

// Register our window's Class
BOOL RegisterDLLWindowClass(wchar_t szClassName[])
{
    WNDCLASSEX wc;
    wc.hInstance =  dllInstance;
	wc.lpszClassName = (LPCWSTR)L"DLLWindowClass";
    wc.lpszClassName = (LPCWSTR)szClassName;
    wc.lpfnWndProc = DLLWindowProc;
    wc.style = CS_DBLCLKS;
    wc.cbSize = sizeof (WNDCLASSEX);
    wc.hIcon = LoadIcon (NULL, IDI_APPLICATION);
    wc.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
    wc.hCursor = LoadCursor (NULL, IDC_ARROW);
    wc.lpszMenuName = NULL;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hbrBackground = (HBRUSH) COLOR_BACKGROUND;
    if (!RegisterClassEx (&wc))
		return 0;
}
// Creating our window's Menu
HMENU CreateDLLWindowMenu()
{
	HMENU hMenu;
	hMenu = CreateMenu();
	HMENU hMenuPopup;
    if(hMenu==NULL)
        return FALSE;
    hMenuPopup = CreatePopupMenu();
	AppendMenu (hMenuPopup, MF_STRING, MYMENU_EXIT, TEXT("Exit"));
    AppendMenu (hMenu, MF_POPUP, (UINT_PTR) hMenuPopup, TEXT("File")); 

	hMenuPopup = CreatePopupMenu();
    AppendMenu (hMenuPopup, MF_STRING,MYMENU_MESSAGEBOX, TEXT("MessageBox")); 
    AppendMenu (hMenu, MF_POPUP, (UINT_PTR) hMenuPopup, TEXT("Test")); 
	return hMenu;
}

// The new thread
DWORD WINAPI ThreadProc( LPVOID lpParam )
{
    MSG messages;
	wchar_t *pString = reinterpret_cast<wchar_t * > (lpParam);
	HMENU hMenu = CreateDLLWindowMenu();
	RegisterDLLWindowClass(L"DLLWindowClass");
	HWND hwnd = CreateWindowEx (0, L"DLLWindowClass", pString, WS_EX_PALETTEWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 400, 300, mIRC_window, hMenu, dllInstance, NULL );
	ShowWindow (hwnd, SW_SHOWNORMAL);
    while (GetMessage (&messages, NULL, 0, 0))
    {
		TranslateMessage(&messages);
        DispatchMessage(&messages);
    }
    return 1;
}
// Our new window's proc
LRESULT CALLBACK DLLWindowProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
		case WM_COMMAND:
               switch(wParam)
               {
                    case MYMENU_EXIT:
						SendMessage(hwnd, WM_CLOSE, 0, 0);
                        break;
                    case MYMENU_MESSAGEBOX:
						MessageBox(hwnd, L"Test", L"MessageBox",MB_OK);
                        break;
               }
               break;
		case WM_DESTROY:
			PostQuitMessage (0);
			break;
		default:
			return DefWindowProc (hwnd, message, wParam, lParam);
    }
    return 0;
}



BOOL APIENTRY DllMain( HINSTANCE hModule, 
                       DWORD  ul_reason_for_call, 
                       LPVOID lpReserved
					 )
{
	dllInstance = hModule;
    return TRUE;
}

int __stdcall dllname(HWND mWnd, HWND aWnd, char *data, char *parms, BOOL show, BOOL nopause) {
	wchar_t szFileName[MAX_PATH];
	GetModuleFileName((HMODULE)dllInstance, szFileName, MAX_PATH);
	MessageBox(aWnd, szFileName, L"This DLL is:", MB_OK | MB_ICONINFORMATION);
	lstrcpyA(data, "yay");
	return 3;
}

int __stdcall window(HWND mWnd, HWND aWnd, char *data, char *parms, BOOL show, BOOL nopause) {
	mIRC_window = mWnd;
	HANDLE hThread = CreateThread(0, NULL, ThreadProc, (LPVOID)L"Window Title", NULL, NULL);
	if (hThread) {
		lstrcpyA(data, "Thread (and window) created!");
	}
	else {
		lstrcpyA(data, "Thread creation failed!");
	}
	return 3;
}


As you can see, the code above creates a new thread for the window, which I'm assuming is the saner way of doing this. I tried creating my window without using a new thread and the result wasn't really different (mIRC crashed).

Most of my attempts = no window appears + mIRC crashes
If I'm lucky = window appears, but mIRC crashes shortly after that (the window appears because I would have changed something in the code, but mIRC still crashes).

//echo -a $dll(test.dll,dllname,1) works fine (pops up a message box, and as soon as I click OK, "yay" is echoed)

//echo -a $dll(test.dll,window,1) immediately echoes "Thread (and window) created!" and mIRC crashes (mIRC window remains until I close the Visual Studio JIT debugger dialog)

Has anyone successfully created a window/dialog from within their DLLs? If so, could you please share how and/or see what I'm doing wrong here?