xref: /reactos/boot/freeldr/fdebug/fdebug.c (revision 23373acb)
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 }
504