WM_PAINT

closed account (LTXN8vqX)
Here is what is confusing me. I am simply making a program to load a .dll into my program, using the LoadLibrary() function. If the file was loaded I want it to print on the window that "File was Loaded", if it didn't load then i want it to print on the window "Error loading file". Now, I wrote a console program doing this but it would be better practice for me to do it in winapi. My problem is, that if i want to print "File loaded", I will have to use SendMessage() function to send a message to the WM_PAINT label to print it, but I already have all my information that i want laid out on the screen in there, and it will print "File Loaded, and "file not loaded". Is there a solution for this. here is my code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#include <windows.h>
#define done_button 3
 char filename;
 char* filenameptr;
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
HINSTANCE hInst;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    PSTR szCmdLine, int iCmdShow)
{
     static TCHAR szAppName[] = TEXT ("HelloWin") ;
     HWND         hwnd ;
     MSG          msg ;
     WNDCLASS     wndclass ;
	 hInst = hInstance;
     wndclass.style         = CS_HREDRAW | CS_VREDRAW ;
     wndclass.lpfnWndProc   = WndProc ;
     wndclass.cbClsExtra    = 0 ;
     wndclass.cbWndExtra    = 0 ;
     wndclass.hInstance     = hInstance ;
     wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ;
     wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
     wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
     wndclass.lpszMenuName  = NULL ;
     wndclass.lpszClassName = szAppName ;

     if (!RegisterClass (&wndclass))
     {
          MessageBox (NULL, TEXT ("This program requires Windows NT!"), 
                      szAppName, MB_ICONERROR) ;
          return 0 ;
     }
     hwnd = CreateWindow (szAppName,                  // window class name
                          TEXT ("The Hello Program"), // window caption
                          WS_OVERLAPPEDWINDOW,        // window style
                          CW_USEDEFAULT,              // initial x position
                          CW_USEDEFAULT,              // initial y position
                          CW_USEDEFAULT,              // initial x size
                          CW_USEDEFAULT,              // initial y size
                          NULL,                       // parent window handle
                          NULL,                       // window menu handle
                          hInstance,                  // program instance handle
                          NULL) ;                     // creation parameters
     
     ShowWindow (hwnd, iCmdShow) ;
     UpdateWindow (hwnd) ;
     
     while (GetMessage (&msg, NULL, 0, 0))
     {
          TranslateMessage (&msg) ;
          DispatchMessage (&msg) ;
     }
     return msg.wParam ;
}

LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
     HDC         hdc ;
     PAINTSTRUCT ps ;
     RECT        rect ;
	 static HWND filenamebox, donebutton ;
      HANDLE handle;
     switch (message)
     {

	 case WM_CREATE:
		 filenamebox = CreateWindow(TEXT("edit"), NULL, WS_CHILD | WS_VISIBLE | WS_BORDER, 400, 50, 100, 40, hwnd, 0, hInst, NULL);
         donebutton = CreateWindow(TEXT("button"), TEXT("Load .dll"), WS_CHILD | WS_VISIBLE, 550, 50, 100, 60, hwnd , NULL, hInst ,NULL);
		 return 0;
	 case WM_COMMAND:
		 switch(wParam)
		 {
		 case done_button:
			 GetWindowTextA(filenamebox, filenameptr, 60);
			 handle = LoadLibraryA(filenameptr);
			 GetClientRect(hwnd, &rect);
			 if (handle == 0)
			 {
				SendMessage(hwnd, WM_PAINT, NULL, NULL);	
				 
			 }
			 else
			 {
				SendMessage(hwnd, WM_PAINT, NULL, NULL);
			 }
		 default:
			 return 0;
		 }
			 return 0;
		

     case WM_PAINT:
          hdc = BeginPaint (hwnd, &ps) ;
          GetClientRect(hwnd, &rect);
		  DrawText(hdc, TEXT("Put File name here: "), -1, &rect, DT_TOP | DT_CENTER );
		    DrawTextA(hdc, "File Not Loaded", 60, &rect, DT_SINGLELINE | DT_VCENTER);  
			TextOutA(hdc, 50, 300, "File Successfully Loaded", 60);
		  EndPaint (hwnd, &ps);
          
          return 0 ;
     case WM_DESTROY:
          PostQuitMessage (0) ;
          return 0 ;
     }
     return DefWindowProc (hwnd, message, wParam, lParam) ;
}



closed account (LTXN8vqX)
Anyone?
I'm not sure what you are asking. The correct way to draw something on the screen is to persist the message in a buffer somewhere, then when you want to display it, send a WM_PAINT message (or InvalidateRect()) to cause the paint handler to draw your text. I can see if you are just coming from a console mode background this might seem a bit odd, but you'll get used to it.
Here is how I'd handle it. First, I don't use global variables at all, so defining a global char string buffer is out of the question for me. What I'd do is in my WM_CREATE handler, I'd allocate a buffer for however many TCHARs I needed. For a message like you want 64 would probably suffice. I'd use HeapAlloc() or GlobalAlloc() to allocate the buffer. Then I'd store the pointer to the buffer in my .cbWndExtra bytes (you'd need to allocate four extra).

After the user clicked the button to load the library I'd naturally test for success/failure. If successful, I'd retrieve the pointer to the buffer and write a success message to the buffer. Otherwise, a failure message. Then I'd do an InvalidateRect() call to force a WM_PAINT message. In the WM_PAINT handler the pointer to my buffer associated with the window would be retrieved, and the correct message displayed.

In my WM_CLOSE handler I'd release the allocated buffer.
Last edited on
closed account (LTXN8vqX)
ok freddie1, that was confusing, if you could write a little code snippet or something explaining your geniousness if I make call it, I would appreciate it, thanks.
ok, just give me a little bit.
closed account (LTXN8vqX)
kk, thanks a bunch, take your time.



ok, not that much time, lol.
Last edited on
Here is my version of your program GeoMike. First I created a dll that just outputs to a console window a character string (the main GUI host creates the console window from the GUI process). Here is the dll code. I named the project dllLoadTest…

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//Main.cpp
//#define  UNICODE
//#define  _UNICODE
#include <windows.h>
#include <tchar.h>
#include <string.h>

extern "C" void __declspec(dllexport) Print(const TCHAR* pStr)
{
 DWORD dwCharsWritten;
 HANDLE hStdOutput;

 hStdOutput=GetStdHandle(STD_OUTPUT_HANDLE);
 WriteConsole(hStdOutput,pStr,_tcslen(pStr),&dwCharsWritten,NULL);
}


I used CodeBlocks and mingw, but you can use whatever suitable you want. The following program attempts to use LoadLibrary() to load dllLoadTest.dll from whatever directory the program is running from, and it does that in response to a button click, which I believe is what you had in mind. The program then stores the handle to the loaded dll within the program’s Window Class structure. The SetWindowLong() Api function does this and stores the hDll at offset zero in the twelve allocated bytes.

The Windows Api is completely object oriented, although I do believe its manner of working is rather mysterious to most aspiring C++ coders because it is C based – not C++ based. In C there are no classes in the C++ sense; there are structures. In the same manner though that you would store object properties within a class, you store Window (Windows are objects in every sense) properties within the WNDCLASSEX struct. First though in filling out the members of the WNDCLASSEX struct (which is a C based class) you must allocate a sufficient number of bytes for the information you want to store. You do this using the .cbWndExtra member. In this program I wanted to persist/store the handle to the loaded Dll, and two text strings. I wanted one string for displaying on the window when the button was pressed to load the dll, and the other string for when I used GetProcAddress() to obtain the runtime address of the single exported ‘Print’ function from within the dll. These are essentially all pointers, and since I only know/use 32 bit Windows (I haven’t purchased a 64 bit OS yet), the three will require 12 .cbWndExtra bytes.

Note the program has no global variables unless you count a FILE* if MYDEBUG is defined for debug output purposes. In that case the program will open a log output file in the program’s directory. The issue with global variables is significant, I believe. In my opinion, there are a lot of coders who don’t realize the poor habits they engender.

Here is what the program does. In its WM_CREATE handler it creates two buttons; a button whose clicking will attempt to load the dllLoadTest.dll; the second button will attempt to obtain the address of ‘Print’ exported from the dll. Note that when the 1st button is clicked it stores the hDll in the .cbWndExtra bytes – not in a tempory/global. Also, when you click either of the buttons a character string message is copied to buffers that were also allocated in the WM_CREATE handler. GlobalAlloc() was used and the pointers were stored at offsets 4 and 8 in the .cbWndExtra bytes. You’ll note quite a lot of use of Get/SetWindowLong(). These are very important Windows Api functions, to be sure! After storing the text strings in the allocated memory the button click procedures end by calling InvalidateRect() which call forces a WM_PAINT message. Of course, the WM_PAINT handler must also retrieve various info from the storage accessed by the .cbWndExtra bytes.

Anyway, here is the code. Note there is a .h file and a main .cpp file. Please don’t be put off too much by my message cracker scheme. It looks complicated (I guess it sort of is, in a sense ) but all it really does is route Windows messages to the correct procedure for handling each respective message. You see, I work on programs which contain many tens of thousands of lines, and in such cases the typical WndProc with its massive switch is simply unworkable. However, for this small program, if you are ‘put off’ by it, it wouldn’t be hard to coelesse it back into a switch....

continued...
Last edited on
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
//WinTypes.h
#ifndef WINTYPES_H
#define WINTYPES_H
#define dim(x) (sizeof(x) / sizeof(x[0]))

typedef struct           WindowsEventArguments
{
 HWND                    hWnd;
 WPARAM                  wParam;
 LPARAM                  lParam;
 HINSTANCE               hIns;
}WndEventArgs,           *lpWndEventArgs;

long fnWndProc_OnCreate  (lpWndEventArgs Wea);
long fnWndProc_OnCommand (lpWndEventArgs Wea);
long fnWndProc_OnPaint   (lpWndEventArgs Wea);
long fnWndProc_OnClose   (lpWndEventArgs Wea);

struct EVENTHANDLER
{
 unsigned int            Code;
 long                    (*fnPtr)(lpWndEventArgs);
};

const EVENTHANDLER EventHandler[]=
{
 {WM_CREATE,             fnWndProc_OnCreate},
 {WM_COMMAND,            fnWndProc_OnCommand},
 {WM_PAINT,              fnWndProc_OnPaint},
 {WM_CLOSE,              fnWndProc_OnClose}
};
#endif 



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
//Main.cpp
//#define       UNICODE
//#define       _UNICODE
#include      <windows.h>
#include      <tchar.h>
#include      <stdio.h>
#include      <string.h>
#include      "WinTypes.h"
//#define       MY_DEBUG             1
#define       IDC_LOAD_LIBRARY     1500
#define       IDC_GET_PROC_ADDRESS 1505
#if defined(MY_DEBUG)
FILE*         fp;
#endif

long fnWndProc_OnCreate(lpWndEventArgs Wea)
{
 TCHAR* lpBuffer=NULL;
 HWND hButton=0;

 #if defined(MY_DEBUG)
 fp=_tfopen(_T("Output.txt"),_T("w"));
 _ftprintf(fp,_T("Entering fnWndProc_OnCreate()\n"));
 _ftprintf(fp,_T("  Output.txt Opened in fnWndProc_OnCreate()\n"));
 #endif
 Wea->hIns=((LPCREATESTRUCT)Wea->lParam)->hInstance;
 hButton=CreateWindow(_T("button"),_T("Load Library"),WS_CHILD|WS_VISIBLE,20,15,150,25,Wea->hWnd,(HMENU)IDC_LOAD_LIBRARY,Wea->hIns,0);
 hButton=CreateWindow(_T("button"),_T("Get Proc Address"),WS_CHILD|WS_VISIBLE,20,65,150,25,Wea->hWnd,(HMENU)IDC_GET_PROC_ADDRESS,Wea->hIns,0);
 lpBuffer=(TCHAR*)GlobalAlloc(GPTR,64*sizeof(TCHAR));
 if(lpBuffer)
    SetWindowLong(Wea->hWnd,4,(long)lpBuffer);
 #if defined(MY_DEBUG)
 _ftprintf(fp,_T("  lpBuffer = %u\n"),(unsigned)lpBuffer);
 #endif
 lpBuffer=(TCHAR*)GlobalAlloc(GPTR,64*sizeof(TCHAR));
 if(lpBuffer)
    SetWindowLong(Wea->hWnd,8,(long)lpBuffer);
 #if defined(MY_DEBUG)
 _ftprintf(fp,_T("Leaving fnWndProc_OnCreate()\n"));
 #endif

 return 0;
}


long fnWndProc_OnCommand(lpWndEventArgs Wea)
{
 switch(LOWORD(Wea->wParam))
 {
   case IDC_LOAD_LIBRARY:
   {
      TCHAR* pBuffer=NULL;
      HINSTANCE hDll=0;
      #if defined(MY_DEBUG)
      _ftprintf(fp,_T("\nEntering fnWndProc_OnCommand() -- IDC_LOAD_LIBRARY\n"));
      #endif
      hDll=LoadLibrary(_T("dllLoadTest.dll"));
      pBuffer=(TCHAR*)GetWindowLong(Wea->hWnd,4);
      #if defined(MY_DEBUG)
      _ftprintf(fp,_T("  hDll   = %u\n"),(unsigned)hDll);
      #endif
      if(hDll)
      {
         SetWindowLong(Wea->hWnd,0,(long)hDll);
         if(pBuffer)
         {
            _tcscpy(pBuffer,_T("Successfully Loaded Dll!"));
            InvalidateRect(Wea->hWnd,NULL,TRUE);
         }
      }
      #if defined(MY_DEBUG)
      _ftprintf(fp,_T("Leaving fnWndProc_OnCommand() -- IDC_LOAD_LIBRARY\n"));
      #endif
      break;
   }
   case IDC_GET_PROC_ADDRESS:
   {
      void (*pPrint)(TCHAR*);
      TCHAR* pBuffer=NULL;
      HINSTANCE hDll=0;
      #if defined(MY_DEBUG)
      _ftprintf(fp,_T("\nEntering fnWndProc_OnCommand() -- IDC_GET_PROC_ADDRESS\n"));
      #endif
      hDll=(HINSTANCE)GetWindowLong(Wea->hWnd,0);
      #if defined(MY_DEBUG)
      _ftprintf(fp,_T("  hDll   = %u\n"),(unsigned)hDll);
      #endif
      if(hDll)
      {  AllocConsole();
         //HWND hConsole=GetConsoleWindow();
         //HMENU hSysMenu=GetSystemMenu(hConsole,0);
         //DeleteMenu(hSysMenu,6,MF_BYPOSITION);
         pPrint=(void (*)(TCHAR*))GetProcAddress(hDll,"Print");
         if(pPrint)
         {
            pPrint((TCHAR*)_T("Here Is A Line Of Text!\n"));
            pPrint((TCHAR*)_T("Please Don't Use The [x] Button To Close This Console Window!!!!\n"));
            pPrint((TCHAR*)_T("The reason Is It Will Shut Down The Whole Process!!!\n"));
            pBuffer=(TCHAR*)GetWindowLong(Wea->hWnd,8);
            _tcscpy(pBuffer,_T("Successfully Obtained Proc Address!"));
            InvalidateRect(Wea->hWnd,NULL,TRUE);
         }
         #if defined(MY_DEBUG)
         _ftprintf(fp, _T("  pPrint = %u\n"),(unsigned)pPrint);
         #endif
      }
      #if defined(MY_DEBUG)
      _ftprintf(fp,_T("Leaving fnWndProc_OnCommand() -- IDC_GET_PROC_ADDRESS\n"));
      #endif
      break;
   }
 }

 return 0;
}


long fnWndProc_OnPaint(lpWndEventArgs Wea)
{
 TCHAR* pBuffer=NULL;
 PAINTSTRUCT ps;
 HDC hDC;

 hDC=BeginPaint(Wea->hWnd,&ps);
 SetBkMode(hDC,TRANSPARENT);
 pBuffer=(TCHAR*)GetWindowLong(Wea->hWnd,4);
 if(pBuffer)
    TextOut(hDC,200,15,pBuffer,_tcslen(pBuffer));
 pBuffer=(TCHAR*)GetWindowLong(Wea->hWnd,8);
 if(pBuffer)
    TextOut(hDC,200,65,pBuffer,_tcslen(pBuffer));
 EndPaint(Wea->hWnd,&ps);

 return 0;
}


long fnWndProc_OnClose(lpWndEventArgs Wea)
{
 TCHAR* lpBuffer=NULL;
 HINSTANCE hDll=0;

 #if defined(MY_DEBUG)
 _ftprintf(fp,_T("\nEntering fnWndProc_OnClose()\n"));
 #endif
 hDll=(HINSTANCE)GetWindowLong(Wea->hWnd,0);
 #if defined(MY_DEBUG)
 _ftprintf(fp,_T("  hDll = %u\n"),(unsigned)hDll);
 #endif
 if(hDll)
    FreeLibrary(hDll);
 lpBuffer=(TCHAR*)GetWindowLong(Wea->hWnd,4);
 #if defined(MY_DEBUG)
 _ftprintf(fp,_T("  lpBuffer = %u\n"),(unsigned)lpBuffer);
 #endif
 if(lpBuffer)
    GlobalFree(lpBuffer);
 lpBuffer=(TCHAR*)GetWindowLong(Wea->hWnd,8);
 #if defined(MY_DEBUG)
 _ftprintf(fp,_T("  lpBuffer = %u\n"),(unsigned)lpBuffer);
 #endif
 if(lpBuffer)
    GlobalFree(lpBuffer);
 DestroyWindow(Wea->hWnd);
 #if defined(MY_DEBUG)
 _ftprintf(fp,_T("Leaving fnWndProc_OnClose()\n"));
 fclose(fp);
 #endif
 PostQuitMessage(0);

 return 0;
}


LRESULT CALLBACK fnWndProc(HWND hwnd, unsigned int msg, WPARAM wParam, LPARAM lParam)
{
 WndEventArgs Wea;

 for(unsigned int i=0; i<dim(EventHandler); i++)
 {
     if(EventHandler[i].Code==msg)
     {
        Wea.hWnd=hwnd, Wea.lParam=lParam, Wea.wParam=wParam;
        return (*EventHandler[i].fnPtr)(&Wea);
     }
 }

 return (DefWindowProc(hwnd,msg,wParam,lParam));
}


int WINAPI WinMain(HINSTANCE hIns,HINSTANCE hPrevIns,LPSTR lpszArgument,int iShow)
{
 TCHAR szClassName[]=_T("LoadLibrary");
 WNDCLASSEX wc;
 MSG messages;
 HWND hWnd;

 wc.lpszClassName=szClassName;                          wc.lpfnWndProc=fnWndProc;
 wc.cbSize=sizeof (WNDCLASSEX);                         wc.style=0;
 wc.hIcon=LoadIcon(NULL,IDI_APPLICATION);               wc.hInstance=hIns;
 wc.hIconSm=LoadIcon(NULL, IDI_APPLICATION);            wc.hCursor=LoadCursor(NULL,IDC_ARROW);
 wc.hbrBackground=(HBRUSH)COLOR_BTNSHADOW;              wc.cbWndExtra=12;
 wc.lpszMenuName=NULL;                                  wc.cbClsExtra=0;
 RegisterClassEx(&wc);
 hWnd=CreateWindow(szClassName,szClassName,WS_OVERLAPPEDWINDOW,700,400,500,150,HWND_DESKTOP,0,hIns,0);
 ShowWindow(hWnd,iShow);
 UpdateWindow(hWnd);
 while(GetMessage(&messages,NULL,0,0))
 {
       TranslateMessage(&messages);
       DispatchMessage(&messages);
 }

 return messages.wParam;
}
Finally, note that by uncommenting out the UNICODE / _UNICODE defines you can control whether the program is running ansi or wide character. All the Api and C/C++ Runtime functions have a version for each scenerio defined in the headers, so its usually not necessary to use the 'A' or 'W' versions. If you do uncomment out the unicode stuff though, you need to do it in the dll too and recompile.

If you compile and run both programs with the MY_DEBUG defined in the host, you should end up with an "Output.txt" file in the program's directory. In that you can see what the program is doing. Here's mine after a run...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Entering fnWndProc_OnCreate()
  Output.txt Opened in fnWndProc_OnCreate()
  lpBuffer = 2378056
Leaving fnWndProc_OnCreate()

Entering fnWndProc_OnCommand() -- IDC_LOAD_LIBRARY
  hDll     = 1675886592
Leaving fnWndProc_OnCommand() -- IDC_LOAD_LIBRARY

Entering fnWndProc_OnCommand() -- IDC_GET_PROC_ADDRESS
  hDll     = 1675886592
  pPrint   = 1675891160
Leaving fnWndProc_OnCommand() -- IDC_GET_PROC_ADDRESS

Entering fnWndProc_OnClose()
  hDll     = 1675886592
  lpBuffer = 2378056
  lpBuffer = 2385680
Leaving fnWndProc_OnClose()


On my box the main program compiled to 9 K and the dll to 7K. I consider that suitably small. I'm very much against code bloat.

Let me know if it works for you!

Last edited on
closed account (LTXN8vqX)
WOw, this is really some advanced stuff. I will for sure be saving this code and studying it, thanks a bunch man.
Hadn't really thought of it as advanced, although I guess maybe it is a bit. The message cracker scheme I learned from Douglas Boling who writes books for Windows CE. He credits it to another writer named Ray Duncan. I have tutorials on it here...

http://www.jose.it-berater.org/smfforum/index.php?topic=3391.0

You'll note the program struggles a bit with the console window it creates. I made some comments about that. I had used CodeBlocks and mingw in developing the program, and found out to my dismay that the headers they used didn't declare the Api function GetConsoleWindow(). You can see three commented out lines in the program about that. The point of those three lines was to disable the [x] button in the AllocConsole() created console, so a user couldn't prematurely kill the whole process - console, GUI, and all. I just created a VC9 project out of the code, and in those headers it allowed GetConsoleWindow(). Here is that code (I also made some other slight mods)...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
//Main.cpp

//#define       UNICODE

//#define       _UNICODE
//For VC9, etc - CRT_SECURE_NO_WARNINGS

#include      <windows.h>

#include      <tchar.h>

#include      <stdio.h>

#include      <string.h>

#include      "WinTypes.h"

//#define       MY_DEBUG             1

#define       IDC_LOAD_LIBRARY     1500

#define       IDC_GET_PROC_ADDRESS 1505

#if defined(MY_DEBUG)

FILE*         fp;

#endif





long fnWndProc_OnCreate(lpWndEventArgs Wea)

{

 TCHAR* lpBuffer=NULL;

 HWND hButton=0;



 #if defined(MY_DEBUG)

 fp=_tfopen(_T("Output.txt"),_T("w"));

 _ftprintf(fp,_T("Entering fnWndProc_OnCreate()\n"));

 _ftprintf(fp,_T("  Output.txt Opened in fnWndProc_OnCreate()\n"));

 #endif

 Wea->hIns=((LPCREATESTRUCT)Wea->lParam)->hInstance;

 hButton=CreateWindow(_T("button"),_T("Load Library"),WS_CHILD|WS_VISIBLE,20,15,150,25,Wea->hWnd,(HMENU)IDC_LOAD_LIBRARY,Wea->hIns,0);

 hButton=CreateWindow(_T("button"),_T("Get Proc Address"),WS_CHILD|WS_VISIBLE,20,55,150,25,Wea->hWnd,(HMENU)IDC_GET_PROC_ADDRESS,Wea->hIns,0);

 lpBuffer=(TCHAR*)GlobalAlloc(GPTR,64*sizeof(TCHAR));

 if(lpBuffer)

    SetWindowLong(Wea->hWnd,4,(long)lpBuffer);

 #if defined(MY_DEBUG)

 _ftprintf(fp,_T("  lpBuffer = %u\n"),(unsigned)lpBuffer);

 #endif

 lpBuffer=(TCHAR*)GlobalAlloc(GPTR,64*sizeof(TCHAR));

 if(lpBuffer)

    SetWindowLong(Wea->hWnd,8,(long)lpBuffer);

 #if defined(MY_DEBUG)

 _ftprintf(fp,_T("Leaving fnWndProc_OnCreate()\n"));

 #endif



 return 0;

}





void LoadLibrary_OnClick(lpWndEventArgs Wea)

{

 TCHAR* pBuffer=NULL;

 HINSTANCE hDll=0;



 #if defined(MY_DEBUG)

 _ftprintf(fp,_T("\nEntering LoadLibrary_OnClick()\n"));

 #endif

 hDll=LoadLibrary(_T("dllLoadTest.dll"));

 pBuffer=(TCHAR*)GetWindowLong(Wea->hWnd,4);

 #if defined(MY_DEBUG)

 _ftprintf(fp,_T("  hDll   = %u\n"),(unsigned)hDll);

 #endif

 if(hDll)

 {

    SetWindowLong(Wea->hWnd,0,(long)hDll);

    if(pBuffer)

    {

       _tcscpy(pBuffer,_T("Successfully Loaded Dll!"));

       InvalidateRect(Wea->hWnd,NULL,TRUE);

    }

 }

 #if defined(MY_DEBUG)

 _ftprintf(fp,_T("Leaving LoadLibrary_OnClick\n"));

 #endif

}





void GetProcAddress_OnClick(lpWndEventArgs Wea)

{

 void (*pPrint)(TCHAR*);

 TCHAR* pBuffer=NULL;

 HINSTANCE hDll=0;



 #if defined(MY_DEBUG)

 _ftprintf(fp,_T("\nEntering GetProcAddress_OnClick()\n"));

 #endif

 hDll=(HINSTANCE)GetWindowLong(Wea->hWnd,0);

 #if defined(MY_DEBUG)

 _ftprintf(fp,_T("  hDll   = %u\n"),(unsigned)hDll);

 #endif

 if(hDll)

 {

    AllocConsole();

    HWND hConsole=GetConsoleWindow();

    HMENU hSysMenu=GetSystemMenu(hConsole,0);

    DeleteMenu(hSysMenu,6,MF_BYPOSITION);

    pPrint=(void (*)(TCHAR*))GetProcAddress(hDll,"Print");

    if(pPrint)

    {

       pPrint((TCHAR*)_T("Here Is A Line Of Text!\n"));

       pPrint((TCHAR*)_T("Please Don't Use The [x] Button To Close This Console Window!!!!\n"));

       pPrint((TCHAR*)_T("The reason Is It Will Shut Down The Whole Process!!!\n"));

       pBuffer=(TCHAR*)GetWindowLong(Wea->hWnd,8);

       _tcscpy(pBuffer,_T("Successfully Obtained Proc Address!"));

       InvalidateRect(Wea->hWnd,NULL,TRUE);

    }

    #if defined(MY_DEBUG)

    _ftprintf(fp, _T("  pPrint = %u\n"),(unsigned)pPrint);

    #endif

 }

 #if defined(MY_DEBUG)

 _ftprintf(fp,_T("Leaving GetProcAddress_OnClick()\n"));

 #endif

}





long fnWndProc_OnCommand(lpWndEventArgs Wea)

{

 switch(LOWORD(Wea->wParam))

 {

   case IDC_LOAD_LIBRARY:

   {

      LoadLibrary_OnClick(Wea);

      break;

   }

   case IDC_GET_PROC_ADDRESS:

   {

      GetProcAddress_OnClick(Wea);

      break;

   }

 }



 return 0;

}





long fnWndProc_OnPaint(lpWndEventArgs Wea)

{

 TCHAR* pBuffer=NULL;

 PAINTSTRUCT ps;

 HDC hDC;



 hDC=BeginPaint(Wea->hWnd,&ps);

 SetBkMode(hDC,TRANSPARENT);

 pBuffer=(TCHAR*)GetWindowLong(Wea->hWnd,4);

 if(pBuffer)

    TextOut(hDC,200,15,pBuffer,_tcslen(pBuffer));

 pBuffer=(TCHAR*)GetWindowLong(Wea->hWnd,8);

 if(pBuffer)

    TextOut(hDC,200,55,pBuffer,_tcslen(pBuffer));

 EndPaint(Wea->hWnd,&ps);



 return 0;

}





long fnWndProc_OnClose(lpWndEventArgs Wea)

{

 TCHAR* lpBuffer=NULL;

 HINSTANCE hDll=0;



 #if defined(MY_DEBUG)

 _ftprintf(fp,_T("\nEntering fnWndProc_OnClose()\n"));

 #endif

 hDll=(HINSTANCE)GetWindowLong(Wea->hWnd,0);

 #if defined(MY_DEBUG)

 _ftprintf(fp,_T("  hDll = %u\n"),(unsigned)hDll);

 #endif

 if(hDll)

    FreeLibrary(hDll);

 lpBuffer=(TCHAR*)GetWindowLong(Wea->hWnd,4);

 #if defined(MY_DEBUG)

 _ftprintf(fp,_T("  lpBuffer = %u\n"),(unsigned)lpBuffer);

 #endif

 if(lpBuffer)

    GlobalFree(lpBuffer);

 lpBuffer=(TCHAR*)GetWindowLong(Wea->hWnd,8);

 #if defined(MY_DEBUG)

 _ftprintf(fp,_T("  lpBuffer = %u\n"),(unsigned)lpBuffer);

 #endif

 if(lpBuffer)

    GlobalFree(lpBuffer);

 DestroyWindow(Wea->hWnd);

 #if defined(MY_DEBUG)

 _ftprintf(fp,_T("Leaving fnWndProc_OnClose()\n"));

 fclose(fp);

 #endif

 PostQuitMessage(0);



 return 0;

}





LRESULT CALLBACK fnWndProc(HWND hwnd, unsigned int msg, WPARAM wParam, LPARAM lParam)

{

 WndEventArgs Wea;



 for(unsigned int i=0; i<dim(EventHandler); i++)

 {

     if(EventHandler[i].Code==msg)

     {

        Wea.hWnd=hwnd, Wea.lParam=lParam, Wea.wParam=wParam;

        return (*EventHandler[i].fnPtr)(&Wea);

     }

 }



 return (DefWindowProc(hwnd,msg,wParam,lParam));

}





int WINAPI WinMain(HINSTANCE hIns,HINSTANCE hPrevIns,LPSTR lpszArgument,int iShow)

{

 TCHAR szClassName[]=_T("LoadLibrary");

 WNDCLASSEX wc;

 MSG messages;

 HWND hWnd;



 wc.lpszClassName=szClassName;                          wc.lpfnWndProc=fnWndProc;

 wc.cbSize=sizeof (WNDCLASSEX);                         wc.style=0;

 wc.hIcon=LoadIcon(NULL,IDI_APPLICATION);               wc.hInstance=hIns;

 wc.hIconSm=LoadIcon(NULL, IDI_APPLICATION);            wc.hCursor=LoadCursor(NULL,IDC_ARROW);

 wc.hbrBackground=(HBRUSH)COLOR_BTNSHADOW;              wc.cbWndExtra=12;

 wc.lpszMenuName=NULL;                                  wc.cbClsExtra=0;

 RegisterClassEx(&wc);

 hWnd=CreateWindow(szClassName,szClassName,WS_OVERLAPPEDWINDOW,700,400,480,135,HWND_DESKTOP,0,hIns,0);

 ShowWindow(hWnd,iShow);

 UpdateWindow(hWnd);

 while(GetMessage(&messages,NULL,0,0))

 {

       TranslateMessage(&messages);

       DispatchMessage(&messages);

 }



 return messages.wParam;

}
Topic archived. No new replies allowed.