QuakeGod
2022-05-10 65f7136c6dfebde14a07c89c4366fb8bed2fe37f
提交 | 用户 | age
0ed438 1 
Q 2 // MTerm1.cpp: 定义应用程序的类行为。
3 //
4
5 #include "pch.h"
6 #include "framework.h"
7 #include "afxwinappex.h"
8 #include "afxdialogex.h"
9 #include "MTerm1.h"
10 #include "MainFrm.h"
11
12 #include "ChildFrm.h"
13 #include "MTerm1Doc.h"
14 #include "MTerm1View.h"
15
16 #ifdef _DEBUG
17 #define new DEBUG_NEW
18 #endif
19
20 #include <devguid.h>
21 #include <SetupAPI.h>
22
23 #include <eh.h>
24 #include <dbghelp.h>
25 #pragma comment(lib,"dbghelp.lib")
26
27 #pragma comment(lib,"gdiplus.lib")
28 #pragma comment(lib,"SetupAPI.lib")
29
30 MHash MyCfg1;
31 Logger MyLogger1;
32
33 //KLinkProtocol MyKLProtocol1;
34 // CSerialCom MySerialCom1;
35 //HvSerialPort MyHvSerialPort1;
36
37 // CMTerm1App
38
39 BEGIN_MESSAGE_MAP(CMTerm1App, CWinAppEx)
40     ON_COMMAND(ID_APP_ABOUT, &CMTerm1App::OnAppAbout)
41     // 基于文件的标准文档命令
42 //    ON_COMMAND(ID_FILE_NEW, &CWinAppEx::OnFileNew)
43     ON_COMMAND(ID_FILE_NEW, &OnFileNew)
44     ON_COMMAND(ID_FILE_OPEN, &CWinAppEx::OnFileOpen)
45     // 标准打印设置命令
46     ON_COMMAND(ID_FILE_PRINT_SETUP, &CWinAppEx::OnFilePrintSetup)
47 END_MESSAGE_MAP()
48
49
50 // CMTerm1App 构造
51
52 CMTerm1App::CMTerm1App() noexcept
53 {
54     m_bHiColorIcons = TRUE;
55
56     // 支持重新启动管理器
57     m_dwRestartManagerSupportFlags = AFX_RESTART_MANAGER_SUPPORT_ALL_ASPECTS;
58 #ifdef _MANAGED
59     // 如果应用程序是利用公共语言运行时支持(/clr)构建的,则: 
60     //     1) 必须有此附加设置,“重新启动管理器”支持才能正常工作。
61     //     2) 在您的项目中,您必须按照生成顺序向 System.Windows.Forms 添加引用。
62     System::Windows::Forms::Application::SetUnhandledExceptionMode(System::Windows::Forms::UnhandledExceptionMode::ThrowException);
63 #endif
64
65     // TODO: 将以下应用程序 ID 字符串替换为唯一的 ID 字符串;建议的字符串格式
66     //为 CompanyName.ProductName.SubProduct.VersionInformation
67     SetAppID(_T("MTerm1.AppID.NoVersion"));
68
69     // TODO: 在此处添加构造代码,
70     // 将所有重要的初始化放置在 InitInstance 中
71 }
72
73 // 唯一的 CMTerm1App 对象
74
75 CMTerm1App theApp;
76
77
78 // CMTerm1App 初始化
79
80 BOOL CMTerm1App::InitInstance()
81 {
82     // 如果一个运行在 Windows XP 上的应用程序清单指定要
83     // 使用 ComCtl32.dll 版本 6 或更高版本来启用可视化方式,
84     //则需要 InitCommonControlsEx()。  否则,将无法创建窗口。
85     INITCOMMONCONTROLSEX InitCtrls;
86     InitCtrls.dwSize = sizeof(InitCtrls);
87     // 将它设置为包括所有要在应用程序中使用的
88     // 公共控件类。
89     InitCtrls.dwICC = ICC_WIN95_CLASSES;
90     InitCommonControlsEx(&InitCtrls);
91
92     CWinAppEx::InitInstance();
93
94
95     // 初始化 OLE 库
96     if (!AfxOleInit())
97     {
98         AfxMessageBox(IDP_OLE_INIT_FAILED);
99         return FALSE;
100     }
101
102     Gdiplus::GdiplusStartupInput gdiplusStartupInput;
103     Gdiplus::GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL);
104
105     AfxEnableControlContainer();
106
107     EnableTaskbarInteraction();
108
109     // 使用 RichEdit 控件需要 AfxInitRichEdit2()
110     // AfxInitRichEdit2();
111
112     // 标准初始化
113     // 如果未使用这些功能并希望减小
114     // 最终可执行文件的大小,则应移除下列
115     // 不需要的特定初始化例程
116     // 更改用于存储设置的注册表项
117     // TODO: 应适当修改该字符串,
118     // 例如修改为公司或组织名
119     SetRegistryKey(_T("应用程序向导生成的本地应用程序"));
120     LoadStdProfileSettings(4);  // 加载标准 INI 文件选项(包括 MRU)
121
122
123     InitContextMenuManager();
124
125     InitKeyboardManager();
126
127     InitTooltipManager();
128     CMFCToolTipInfo ttParams;
129     ttParams.m_bVislManagerTheme = TRUE;
130     theApp.GetTooltipManager()->SetTooltipParams(AFX_TOOLTIP_TYPE_ALL,
131         RUNTIME_CLASS(CMFCToolTipCtrl), &ttParams);
132
133     // 注册应用程序的文档模板。  文档模板
134     // 将用作文档、框架窗口和视图之间的连接
135     CMultiDocTemplate* pDocTemplate;
136     pDocTemplate = new CMultiDocTemplate(IDR_MTerm1TYPE,
137         RUNTIME_CLASS(CMTerm1Doc),
138         RUNTIME_CLASS(CChildFrame), // 自定义 MDI 子框架
139         RUNTIME_CLASS(CMTerm1View));
140     if (!pDocTemplate)
141         return FALSE;
142     AddDocTemplate(pDocTemplate);
143
144     // 创建主 MDI 框架窗口
145     CMainFrame* pMainFrame = new CMainFrame;
146     if (!pMainFrame || !pMainFrame->LoadFrame(IDR_MAINFRAME))
147     {
148         delete pMainFrame;
149         return FALSE;
150     }
151     m_pMainWnd = pMainFrame;
152
153
154     // 分析标准 shell 命令、DDE、打开文件操作的命令行
155     CCommandLineInfo cmdInfo;
156     ParseCommandLine(cmdInfo);
157
158
159
160     // 调度在命令行中指定的命令。  如果
161     // 用 /RegServer、/Register、/Unregserver 或 /Unregister 启动应用程序,则返回 FALSE。
162     if (!ProcessShellCommand(cmdInfo))
163         return FALSE;
164     // 主窗口已初始化,因此显示它并对其进行更新
165     pMainFrame->ShowWindow(m_nCmdShow);
166     pMainFrame->UpdateWindow();
167
168     return TRUE;
169 }
170
171 int CMTerm1App::ExitInstance()
172 {
173     //TODO: 处理可能已添加的附加资源
174     Gdiplus::GdiplusShutdown(m_gdiplusToken);
175 //    CoUninitialize();
176     SaveMyConfig();
177
178     AfxOleTerm(FALSE);
179
180     return CWinAppEx::ExitInstance();
181 }
182
183 // CMTerm1App 消息处理程序
184
185
186 // 用于应用程序“关于”菜单项的 CAboutDlg 对话框
187
188 class CAboutDlg : public CDialogEx
189 {
190 public:
191     CAboutDlg() noexcept;
192
193 // 对话框数据
194 #ifdef AFX_DESIGN_TIME
195     enum { IDD = IDD_ABOUTBOX };
196 #endif
197
198 protected:
199     virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持
200
201 // 实现
202 protected:
203     DECLARE_MESSAGE_MAP()
204 };
205
206 CAboutDlg::CAboutDlg() noexcept : CDialogEx(IDD_ABOUTBOX)
207 {
208 }
209
210 void CAboutDlg::DoDataExchange(CDataExchange* pDX)
211 {
212     CDialogEx::DoDataExchange(pDX);
213 }
214
215 BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
216 END_MESSAGE_MAP()
217
218 // 用于运行对话框的应用程序命令
219 void CMTerm1App::OnAppAbout()
220 {
221     CAboutDlg aboutDlg;
222     aboutDlg.DoModal();
223 }
224
225 // CMTerm1App 自定义加载/保存方法
226
227 void CMTerm1App::PreLoadState()
228 {
229     BOOL bNameValid;
230     CString strName;
231     bNameValid = strName.LoadString(IDS_EDIT_MENU);
232     ASSERT(bNameValid);
233     GetContextMenuManager()->AddMenu(strName, IDR_POPUP_EDIT);
234     bNameValid = strName.LoadString(IDS_EXPLORER);
235     ASSERT(bNameValid);
236     GetContextMenuManager()->AddMenu(strName, IDR_POPUP_EXPLORER);
237 }
238
239 void CMTerm1App::LoadCustomState()
240 {
241 }
242
243 void CMTerm1App::SaveCustomState()
244 {
245 }
246
247 // CMTerm1App 消息处理程序
248
249
250 int SysLog(CString s, int channel)
251 {
252     MyLogger1.LogTxt(s, channel);
253     return 1;
254 }
255
256 int PopupMessage(CString Msg, int channel)
257 {
258     Msg.Trim(_T("\r\n"));
259     SysLog(_T("报警信息: ") + Msg + _T("\r\n"), channel);
260     return 0;
261 }
262
263 void DoEvents()
264 {
265     MSG msg;
266     while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
267     {
268         DispatchMessage(&msg);
269         TranslateMessage(&msg);
270     }
271 }
272
273 void dump_callstack(PCONTEXT pcontext, CString & infostr)
274 {
275 #ifdef _WIN64
276
277     STACKFRAME64 sf;
278     memset(&sf, 0, sizeof(STACKFRAME64));
279
280     sf.AddrPC.Offset = pcontext->Rip;
281     //context->
282     sf.AddrPC.Mode = AddrModeFlat;
283     sf.AddrStack.Offset = pcontext->Rsp;
284     sf.AddrStack.Mode = AddrModeFlat;
285     sf.AddrFrame.Offset = pcontext->Rbp;
286     sf.AddrFrame.Mode = AddrModeFlat;
287
288     DWORD machineType = //IMAGE_FILE_MACHINE_I386;
289         IMAGE_FILE_MACHINE_AMD64;
290 #elif defined _WIN32
291     STACKFRAME sf;
292     memset(&sf, 0, sizeof(STACKFRAME));
293
294     sf.AddrPC.Offset = pcontext->Eip;
295     //context->
296     sf.AddrPC.Mode = AddrModeFlat;
297     sf.AddrStack.Offset = pcontext->Esp;
298     sf.AddrStack.Mode = AddrModeFlat;
299     sf.AddrFrame.Offset = pcontext->Ebp;
300     sf.AddrFrame.Mode = AddrModeFlat;
301
302     DWORD machineType = //IMAGE_FILE_MACHINE_I386;
303         IMAGE_FILE_MACHINE_AMD64;
304 #endif
305     HANDLE hProcess = GetCurrentProcess();
306     HANDLE hThread = GetCurrentThread();
307
308     for (;;)
309     {
310         if (!StackWalk(machineType, hProcess, hThread, &sf, pcontext, 0, SymFunctionTableAccess, SymGetModuleBase, 0))
311         {
312             break;
313         }
314
315         if (sf.AddrFrame.Offset == 0)
316         {
317             break;
318         }
319         BYTE symbolBuffer[sizeof(SYMBOL_INFO) + 1024];
320         PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)symbolBuffer;
321
322         pSymbol->SizeOfStruct = sizeof(symbolBuffer);
323         pSymbol->MaxNameLen = 1024;
324
325         DWORD64 symDisplacement = 0;
326         if (SymFromAddr(hProcess, sf.AddrPC.Offset, 0, pSymbol))
327         {
328             printf("Function : %s\n", pSymbol->Name);
329             infostr.AppendFormat(_T("Function : %S \r\n"), pSymbol->Name);
330         }
331         else
332         {
333             printf("SymFromAdd failed!\n");
334             //    infostr.AppendFormat(_T("SymFromAdd failed \r\n"),pSymbol->Name);
335         }
336
337         DWORD dwLineDisplacement;
338 #ifdef _WIN64
339         IMAGEHLP_LINEW64 lineInfoW = { sizeof(IMAGEHLP_LINEW64) };
340         if (SymGetLineFromAddrW(hProcess, sf.AddrPC.Offset, &dwLineDisplacement, &lineInfoW))
341         {
342             //        printf( "[Source File : %s]\n", lineInfo.FileName ); 
343             //        printf( "[Source Line : %u]\n", lineInfo.LineNumber ); 
344             CString s1(lineInfoW.FileName);
345             infostr.AppendFormat(_T("File %s Line %d\r\n"), s1.Mid(s1.ReverseFind(_T('\\')) + 1, 99), lineInfoW.LineNumber);
346         }
347         else
348         {
349             printf("SymGetLineFromAddr failed!\n");
350             //    infostr.Append(_T("SymGetLineFromAddr failed!\r\n"));
351         }
352 #elif defined _WIN32
353         IMAGEHLP_LINE lineInfo = { sizeof(IMAGEHLP_LINE) };
354         if (SymGetLineFromAddr(hProcess, sf.AddrPC.Offset, &dwLineDisplacement, &lineInfo))
355         {
356             //        printf( "[Source File : %s]\n", lineInfo.FileName ); 
357             //        printf( "[Source Line : %u]\n", lineInfo.LineNumber ); 
358             CString s1(lineInfo.FileName);
359             infostr.AppendFormat(_T("File %s Line %d\r\n"), s1.Mid(s1.ReverseFind(_T('\\')) + 1, 99), lineInfo.LineNumber);
360         }
361         else
362         {
363             printf("SymGetLineFromAddr failed!\n");
364             //    infostr.Append(_T("SymGetLineFromAddr failed!\r\n"));
365         }
366 #endif
367
368     }
369 }
370 DWORD excep_filter(LPEXCEPTION_POINTERS lpEP)
371 {
372     /**//// init dbghelp.dll
373     CString s1;
374     if (SymInitialize(GetCurrentProcess(), NULL, TRUE))
375     {
376         printf("Init dbghelp ok.\n");
377     }
378
379     dump_callstack(lpEP->ContextRecord, s1);
380
381     if (SymCleanup(GetCurrentProcess()))
382     {
383         printf("Cleanup dbghelp ok.\n");
384     }
385
386     return EXCEPTION_EXECUTE_HANDLER;
387 }
388
389 void Trans_Tunc(unsigned int n, EXCEPTION_POINTERS* pExp)
390 {
391     //    pExp->ExceptionRecord.
392     //    throw SE_Exception(n);
393     CString s1;
394     if (SymInitialize(GetCurrentProcess(), NULL, TRUE))
395     {
396         printf("Init dbghelp ok.\n");
397         //        s1=_T("Init dbghelp ok.\r\n");
398     }
399
400     dump_callstack(pExp->ContextRecord, s1);
401
402     if (SymCleanup(GetCurrentProcess()))
403     {
404         printf("Cleanup dbghelp ok.\n");
405         //        s1.Append(_T("Cleanup dbghelp ok.\n"));
406     }
407     throw SE_Exception(n, pExp->ExceptionRecord->ExceptionAddress, s1);
408 }
409
410 int DisplayException(CString File, int Line, CString Func, CString Sentence, SE_Exception &e)
411 {
412     CString Serror;
413     CString s1;
414     s1.Format(_T("程序发生SE异常 代码 %08X 地址 %p \r\nFile: %s \r\nLine: %d \r\nFunc %s \r\n语句 %s \r\n 信息\r\n %s \r\n"), e.getSeNumber(), e.getAddress(), File, Line, Func, Sentence, e.getInfoStr());;
415     PopupMessage(s1);
416     return 0;
417 }
418 int DisplayException(CString File, int Line, CString Func, CString Sentence, CException *e)
419 {
420     CString Serror;
421     CString s1;
422     e->GetErrorMessage(Serror.GetBuffer(256), 256);
423     Serror.ReleaseBuffer();
424     s1.Format(_T("程序发生C++异常 %s 在File: %s Line: %d Func %s Sentence %s \r\n"), Serror, File, Line, Func, Sentence);
425     PopupMessage(s1);
426     return 0;
427 }
428 int DisplayException(CString File, int Line, CString Func, CString Sentence)
429 {
430     CString s1;
431     s1.Format(_T("程序发生未知错误 File: %s Line: %d Func %s Sentence %s \r\n"), File, Line, Func, Sentence);
432     PopupMessage(s1);
433     return 0;
434 }
435
436
437 int LoadMyConfig()
438 {
439     CString ConfigFilePathName;
440     ConfigFilePathName = _T("./Settings.ini");
441     int j = MyCfg1.LoadFromFile(ConfigFilePathName);
442     return j;
443 }
444
445 int SaveMyConfig()
446 {
447     CString ConfigFilePathName;
448     ConfigFilePathName = _T("./Settings.ini");
449     int j = MyCfg1.SaveToFile(ConfigFilePathName);
450     return j;
451 }
452
453
454 //得到COMx的名字
455 //namebuf:用于存放名字的缓冲区
456 //bufsize:缓冲区大小
457 //comx:要查找的COM编号.例如:COM1,COM2,COM3....
458 //返回值:0,成功找到了.
459 //       1,失败.
460 int get_com_name(CString comx, CString &namebuf)
461 {
462     HDEVINFO hdinfo;
463     int res = 0;
464     SP_DEVINFO_DATA   hddevinfo = { sizeof(SP_DEVINFO_DATA) };
465     hdinfo = SetupDiGetClassDevs(&GUID_DEVCLASS_PORTS, 0, 0, DIGCF_PRESENT);//获取PORTS类别的已安装设备信息
466     if (hdinfo != INVALID_HANDLE_VALUE)//获取成功
467     {
468         for (int i = 0; SetupDiEnumDeviceInfo(hdinfo, i, &hddevinfo); i++)//轮询所有已安装设备
469         {
470             SetupDiGetDeviceRegistryProperty(hdinfo, &hddevinfo, SPDRP_FRIENDLYNAME, 0, (PBYTE)(namebuf.GetBuffer(2048)), 2048, 0);//获得单个装置的详细资料
471             namebuf.ReleaseBuffer();
472             if (namebuf.Find(comx) != -1) {
473                 res = 1; break;
474             }
475             //char *t;
476             //t = strstr(namebuf, comx);
477             //if (t)
478             //{
479             //    t--;
480             //    *t = '\0';//添加结束符,作用就是把"(COMX)"这段字符去掉
481             //    res = 0;
482             //    break;//成功找到了COMx的名字
483             //}
484         }
485     }
486     return res;
487 }
488
489 CString & intToString(int num)
490 {
491     static CString Str1;
492     Str1.Format(_T("%d"), num);
493     int k = Str1.GetLength();
494     int j = (k - 1) / 3;    //逗号个数
495     int l = k - j * 3; //起始位置
496     for (int i = l; i < k + j; i += 4)
497     {
498         Str1.Insert(i, _T(","));
499     }
500
501     return Str1;
502 }
503
504 CString & intToBinString(int num, int digits)
505 {
506     static CString Str1;
507     Str1.Empty();
508     int mask = 1 << (digits - 1);
509
510     for (int i = 0; i < digits; i++)
511     {
512         if (num&mask) Str1.Append(_T("*"));
513         else Str1.Append(_T("."));
514         mask >>= 1;
515     }
516     return Str1;
517 }
518