[FREELDR] Diverse enhancements.
[reactos.git] / boot / freeldr / fdebug / fdebug.c
1 /* fdebug.c : Defines the entry point for the application. */
2
3 #include <tchar.h>
4
5 #include <windef.h>
6 #include <winbase.h>
7 #include <wingdi.h>
8 #include <winuser.h>
9 #include <commdlg.h>
10 #include <process.h>
11
12 #include "resource.h"
13 #include "rs232.h"
14
15 #define MAX_LOADSTRING 100
16
17 // Global Variables:
18 HINSTANCE hInst; // current instance
19 TCHAR szTitle[MAX_LOADSTRING]; // The title bar text
20 TCHAR szWindowClass[MAX_LOADSTRING]; // The title bar text
21 HWND hMainWnd; // The main window handle
22 HWND hDisplayWnd; // The window to display the incoming data
23 HWND hEditWnd; // The edit window to get input from the user
24 TCHAR strComPort[MAX_PATH] = TEXT("COM1"); // The COM port to use
25 TCHAR strBaudRate[MAX_PATH] = TEXT("115200"); // The baud rate to use
26 TCHAR strCaptureFileName[MAX_PATH] = TEXT(""); // The file name to capture to
27 BOOL bConnected = FALSE; // Tells us if we are currently connected
28 BOOL bCapturing = FALSE; // Tells us if we are currently capturing data
29 BOOL bLocalEcho = FALSE; // Tells us if local echo is currently enabled
30 HANDLE hCaptureFile; // Handle to the capture file
31 DWORD dwThreadId = 0; // Thread id of RS232 communication thread
32
33 // Forward declarations of functions included in this code module:
34 ATOM MyRegisterClass(HINSTANCE hInstance);
35 BOOL InitInstance(HINSTANCE, int);
36 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
37 INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
38 INT_PTR CALLBACK ConnectionDialogProc(HWND, UINT, WPARAM, LPARAM);
39 INT_PTR CALLBACK CaptureDialogProc(HWND, UINT, WPARAM, LPARAM);
40 VOID EnableFileMenuItemByID(UINT Id, BOOL Enable);
41 VOID CheckLocalEchoMenuItem(BOOL Checked);
42 VOID __cdecl Rs232Thread(VOID* Parameter);
43
44 int APIENTRY _tWinMain(HINSTANCE hInstance,
45 HINSTANCE hPrevInstance,
46 LPTSTR lpCmdLine,
47 int nCmdShow)
48 {
49 // TODO: Place code here.
50 MSG msg;
51 HACCEL hAccelTable;
52
53 UNREFERENCED_PARAMETER(lpCmdLine);
54 UNREFERENCED_PARAMETER(hPrevInstance);
55
56 // Initialize global strings
57 LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
58 LoadString(hInstance, IDC_FDEBUG, szWindowClass, MAX_LOADSTRING);
59 MyRegisterClass(hInstance);
60
61 // Perform application initialization:
62 if (!InitInstance (hInstance, nCmdShow))
63 {
64 return FALSE;
65 }
66
67 hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_FDEBUG);
68
69 // Main message loop:
70 while (GetMessage(&msg, NULL, 0, 0))
71 {
72 if (!TranslateAccelerator(hMainWnd, hAccelTable, &msg))
73 {
74 TranslateMessage(&msg);
75 DispatchMessage(&msg);
76 }
77 }
78
79 return (int)msg.wParam;
80 }
81
82
83
84 //
85 // FUNCTION: MyRegisterClass()
86 //
87 // PURPOSE: Registers the window class.
88 //
89 // COMMENTS:
90 //
91 // This function and its usage is only necessary if you want this code
92 // to be compatible with Win32 systems prior to the 'RegisterClassEx'
93 // function that was added to Windows 95. It is important to call this function
94 // so that the application will get 'well formed' small icons associated
95 // with it.
96 //
97 ATOM MyRegisterClass(HINSTANCE hInstance)
98 {
99 WNDCLASSEX wcex;
100
101 wcex.cbSize = sizeof(WNDCLASSEX);
102
103 wcex.style = CS_HREDRAW | CS_VREDRAW;
104 wcex.lpfnWndProc = WndProc;
105 wcex.cbClsExtra = 0;
106 wcex.cbWndExtra = 0;
107 wcex.hInstance = hInstance;
108 wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_FDEBUG));
109 wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
110 wcex.hbrBackground = NULL;//(HBRUSH)(COLOR_WINDOW+1);
111 wcex.lpszMenuName = MAKEINTRESOURCE(IDC_FDEBUG);
112 wcex.lpszClassName = szWindowClass;
113 wcex.hIconSm = (HICON)LoadImage(hInstance,
114 MAKEINTRESOURCE(IDI_FDEBUG),
115 IMAGE_ICON,
116 16,
117 16,
118 LR_SHARED);
119
120 return RegisterClassEx(&wcex);
121 }
122
123 //
124 // FUNCTION: InitInstance(HANDLE, int)
125 //
126 // PURPOSE: Saves instance handle and creates main window
127 //
128 // COMMENTS:
129 //
130 // In this function, we save the instance handle in a global variable and
131 // create and display the main program window.
132 //
133 BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
134 {
135 HWND hWnd;
136
137 hInst = hInstance; // Store instance handle in our global variable
138
139 hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
140 CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
141
142 if (!hWnd)
143 {
144 return FALSE;
145 }
146
147 hMainWnd = hWnd;
148
149 ShowWindow(hWnd, nCmdShow);
150 UpdateWindow(hWnd);
151
152 return TRUE;
153 }
154
155 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
156 {
157 int wmId, wmEvent;
158 PAINTSTRUCT ps;
159 HDC hdc;
160 RECT rc;
161 TCHAR WndText[MAX_PATH];
162 DWORD Index;
163 NONCLIENTMETRICS ncm;
164 HFONT hFont;
165
166 switch (message)
167 {
168 case WM_CREATE:
169
170 hEditWnd = CreateWindowEx(WS_EX_CLIENTEDGE, TEXT("EDIT"), TEXT(""), WS_CHILD|WS_VISIBLE|WS_VSCROLL|ES_AUTOHSCROLL|ES_LEFT|ES_MULTILINE, 0, 0, 0, 0, hWnd, NULL, hInst, NULL);
171 hDisplayWnd = CreateWindowEx(WS_EX_CLIENTEDGE, TEXT("EDIT"), TEXT(""), WS_CHILD|WS_VISIBLE|WS_HSCROLL|WS_VSCROLL|ES_MULTILINE, 0, 0, 0, 0, hWnd, NULL, hInst, NULL);
172
173 memset(&ncm, 0, sizeof(NONCLIENTMETRICS));
174 ncm.cbSize = sizeof(NONCLIENTMETRICS);
175 SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0);
176
177 hFont = CreateFontIndirect(&ncm.lfMessageFont);
178
179 SendMessage(hEditWnd, WM_SETFONT, (WPARAM)hFont, TRUE);
180 SendMessage(hDisplayWnd, WM_SETFONT, (WPARAM)hFont, TRUE);
181
182 break;
183 case WM_COMMAND:
184 wmId = LOWORD(wParam);
185 wmEvent = HIWORD(wParam);
186
187 if (lParam == (LPARAM)hEditWnd && wmEvent == EN_CHANGE)
188 {
189 GetWindowText(hEditWnd, WndText, MAX_PATH);
190
191 if (_tcslen(WndText) > 0)
192 {
193 SetWindowText(hEditWnd, TEXT(""));
194
195 if (!bConnected)
196 {
197 MessageBox(hWnd, TEXT("You are not currently connected!"), TEXT("Error"), MB_OK|MB_ICONSTOP);
198 break;
199 }
200
201 for (Index=0; Index<_tcslen(WndText); Index++)
202 {
203 if (dwThreadId != 0)
204 {
205 PostThreadMessage(dwThreadId, WM_CHAR, (WPARAM)WndText[Index], (LPARAM)0);
206 }
207 }
208 }
209 }
210
211 // Parse the menu selections:
212 switch (wmId)
213 {
214 case IDM_ABOUT:
215 DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, About);
216 break;
217 case IDM_EXIT:
218 DestroyWindow(hWnd);
219 break;
220 case IDM_FILE_CLEARDISPLAY:
221 SetWindowText(hDisplayWnd, TEXT(""));
222 break;
223 case IDM_FILE_CONNECT:
224 if (bConnected)
225 {
226 MessageBox(hWnd, TEXT("You are already connected!"), TEXT("Error"), MB_OK|MB_ICONSTOP);
227 }
228 else
229 {
230 if (DialogBox(hInst, (LPCTSTR)IDD_CONNECTION, hWnd, ConnectionDialogProc) == IDOK)
231 {
232 bConnected = TRUE;
233 EnableFileMenuItemByID(IDM_FILE_DISCONNECT, TRUE);
234 EnableFileMenuItemByID(IDM_FILE_CONNECT, FALSE);
235 _beginthread(Rs232Thread, 0, NULL);
236 }
237 }
238 break;
239 case IDM_FILE_DISCONNECT:
240 if (bConnected)
241 {
242 bConnected = FALSE;
243 EnableFileMenuItemByID(IDM_FILE_DISCONNECT, FALSE);
244 EnableFileMenuItemByID(IDM_FILE_CONNECT, TRUE);
245 }
246 else
247 {
248 MessageBox(hWnd, TEXT("You are not currently connected!"), TEXT("Error"), MB_OK|MB_ICONSTOP);
249 }
250 break;
251 case IDM_FILE_STARTCAPTURE:
252 if (DialogBox(hInst, (LPCTSTR)IDD_CAPTURE, hWnd, CaptureDialogProc) == IDOK)
253 {
254 bCapturing = TRUE;
255 EnableFileMenuItemByID(IDM_FILE_STOPCAPTURE, TRUE);
256 EnableFileMenuItemByID(IDM_FILE_STARTCAPTURE, FALSE);
257 hCaptureFile = CreateFile(strCaptureFileName, FILE_APPEND_DATA, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
258 }
259 break;
260 case IDM_FILE_STOPCAPTURE:
261 if (bCapturing)
262 {
263 bCapturing = FALSE;
264 EnableFileMenuItemByID(IDM_FILE_STOPCAPTURE, FALSE);
265 EnableFileMenuItemByID(IDM_FILE_STARTCAPTURE, TRUE);
266 CloseHandle(hCaptureFile);
267 hCaptureFile = NULL;
268 }
269 break;
270 case IDM_FILE_LOCALECHO:
271 if (bLocalEcho)
272 {
273 bLocalEcho = FALSE;
274 CheckLocalEchoMenuItem(bLocalEcho);
275 }
276 else
277 {
278 bLocalEcho = TRUE;
279 CheckLocalEchoMenuItem(bLocalEcho);
280 }
281 break;
282 default:
283 return DefWindowProc(hWnd, message, wParam, lParam);
284 }
285 break;
286 case WM_PAINT:
287 hdc = BeginPaint(hWnd, &ps);
288 (void)hdc; // FIXME
289 EndPaint(hWnd, &ps);
290 break;
291 case WM_SIZE:
292
293 GetClientRect(hWnd, &rc);
294
295 MoveWindow(hDisplayWnd, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top - 20, TRUE);
296 MoveWindow(hEditWnd, rc.left, rc.bottom - 20, rc.right - rc.left, 20, TRUE);
297
298 break;
299 case WM_DESTROY:
300 PostQuitMessage(0);
301 break;
302 default:
303 return DefWindowProc(hWnd, message, wParam, lParam);
304 }
305 return 0;
306 }
307
308 INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
309 {
310 HWND hLicenseEditWnd;
311 TCHAR strLicense[0x1000];
312
313 UNREFERENCED_PARAMETER(lParam);
314
315 switch (message)
316 {
317 case WM_INITDIALOG:
318
319 hLicenseEditWnd = GetDlgItem(hDlg, IDC_LICENSE_EDIT);
320
321 LoadString(hInst, IDS_LICENSE, strLicense, 0x1000);
322
323 SetWindowText(hLicenseEditWnd, strLicense);
324
325 return TRUE;
326
327 case WM_COMMAND:
328 if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
329 {
330 EndDialog(hDlg, LOWORD(wParam));
331 return TRUE;
332 }
333 break;
334 }
335 return FALSE;
336 }
337
338 INT_PTR CALLBACK ConnectionDialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
339 {
340 UNREFERENCED_PARAMETER(lParam);
341
342 switch (message)
343 {
344 case WM_INITDIALOG:
345
346 SetWindowText(GetDlgItem(hDlg, IDC_COMPORT), strComPort);
347 SetWindowText(GetDlgItem(hDlg, IDC_BAUTRATE), strBaudRate);
348
349 return TRUE;
350
351 case WM_COMMAND:
352 if (LOWORD(wParam) == IDOK)
353 {
354 GetWindowText(GetDlgItem(hDlg, IDC_COMPORT), strComPort, MAX_PATH);
355 GetWindowText(GetDlgItem(hDlg, IDC_BAUTRATE), strBaudRate, MAX_PATH);
356 }
357
358 if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
359 {
360 EndDialog(hDlg, LOWORD(wParam));
361 return TRUE;
362 }
363 break;
364 }
365 return FALSE;
366 }
367
368 INT_PTR CALLBACK CaptureDialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
369 {
370 OPENFILENAME ofn;
371
372 UNREFERENCED_PARAMETER(lParam);
373
374 switch (message)
375 {
376 case WM_INITDIALOG:
377
378 SetWindowText(GetDlgItem(hDlg, IDC_CAPTUREFILENAME), strCaptureFileName);
379
380 return TRUE;
381
382 case WM_COMMAND:
383 if (LOWORD(wParam) == IDC_BROWSE)
384 {
385 memset(&ofn, 0, sizeof(OPENFILENAME));
386 ofn.lStructSize = sizeof(OPENFILENAME);
387 ofn.hwndOwner = hDlg;
388 ofn.hInstance = hInst;
389 ofn.lpstrFilter = NULL;
390 ofn.lpstrCustomFilter = NULL;
391 ofn.nMaxCustFilter = 0;
392 ofn.nFilterIndex = 0;
393 ofn.lpstrFile = strCaptureFileName;
394 ofn.nMaxFile = MAX_PATH;
395 ofn.lpstrFileTitle = NULL;
396 ofn.nMaxFileTitle = 0;
397 ofn.lpstrInitialDir = NULL;
398 ofn.lpstrTitle = NULL;
399 ofn.Flags = OFN_HIDEREADONLY|OFN_NOREADONLYRETURN;
400
401 if (GetOpenFileName(&ofn))
402 {
403 SetWindowText(GetDlgItem(hDlg, IDC_CAPTUREFILENAME), strCaptureFileName);
404 }
405 }
406
407 if (LOWORD(wParam) == IDOK)
408 {
409 GetWindowText(GetDlgItem(hDlg, IDC_CAPTUREFILENAME), strCaptureFileName, MAX_PATH);
410 }
411
412 if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
413 {
414 EndDialog(hDlg, LOWORD(wParam));
415 return TRUE;
416 }
417 break;
418 }
419 return FALSE;
420 }
421
422 VOID EnableFileMenuItemByID(UINT Id, BOOL Enable)
423 {
424 HMENU hMenuBar;
425 HMENU hFileMenu;
426
427 hMenuBar = GetMenu(hMainWnd);
428 hFileMenu = GetSubMenu(hMenuBar, 0);
429 EnableMenuItem(hFileMenu, Id, MF_BYCOMMAND|(Enable ? MF_ENABLED : MF_GRAYED));
430 }
431
432 VOID CheckLocalEchoMenuItem(BOOL Checked)
433 {
434 HMENU hMenuBar;
435 HMENU hFileMenu;
436
437 hMenuBar = GetMenu(hMainWnd);
438 hFileMenu = GetSubMenu(hMenuBar, 0);
439 CheckMenuItem(hFileMenu, IDM_FILE_LOCALECHO, MF_BYCOMMAND|(Checked ? MF_CHECKED : MF_UNCHECKED));
440 }
441
442 VOID __cdecl Rs232Thread(VOID* Parameter)
443 {
444 BYTE Byte;
445 TCHAR String[MAX_PATH];
446 MSG msg;
447 DWORD dwNumberOfBytesWritten;
448
449 UNREFERENCED_PARAMETER(Parameter);
450
451 dwThreadId = GetCurrentThreadId();
452
453 if (!Rs232OpenPortWin32(strComPort))
454 {
455 MessageBox(hMainWnd, TEXT("Error opening port!"), TEXT("Error"), MB_OK|MB_ICONSTOP);
456 bConnected = FALSE;
457 return;
458 }
459
460 _stprintf(String, TEXT("%s,n,8,1"), strBaudRate);
461 if (!Rs232ConfigurePortWin32(String))
462 {
463 MessageBox(hMainWnd, TEXT("Error configuring port!"), TEXT("Error"), MB_OK|MB_ICONSTOP);
464 bConnected = FALSE;
465 return;
466 }
467
468 while (bConnected)
469 {
470 if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
471 {
472 if (msg.message == WM_CHAR)
473 {
474 Rs232WriteByteWin32((BYTE)msg.wParam);
475
476 if (bLocalEcho && msg.wParam != (WPARAM)TEXT('\r'))
477 {
478 PostMessage(hDisplayWnd, WM_CHAR, (WPARAM)msg.wParam, (LPARAM)0);
479
480 if (hCaptureFile)
481 {
482 WriteFile(hCaptureFile, &msg.wParam, sizeof(TCHAR), &dwNumberOfBytesWritten, NULL);
483 }
484 }
485 }
486 }
487
488 if (Rs232ReadByteWin32(&Byte))
489 {
490 _stprintf(String, TEXT("%c"), Byte);
491
492 PostMessage(hDisplayWnd, WM_CHAR, (WPARAM)String[0], (LPARAM)0);
493
494 if (hCaptureFile)
495 {
496 WriteFile(hCaptureFile, &String[0], sizeof(TCHAR), &dwNumberOfBytesWritten, NULL);
497 }
498 }
499 }
500
501 dwThreadId = 0;
502 Rs232ClosePortWin32();
503 }