Creating windows from a DLL? - 09/01/11 11:53 PM
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).
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?
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?