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