消息循环
概述
ATL
消息循环
h
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 |
#ifndef WIN_TOOLS_MESSAGE_LOOP_H #define WIN_TOOLS_MESSAGE_LOOP_H #include <atlbase.h> #include <atlwin.h> #include <atlapp.h> #include <atlcrack.h> #include <thread> #include <mutex> #include <list> typedef bool (WINAPI* MSG_TASKBAR)(LPCSTR name); class MessageLoop : public CWindowImpl<MessageLoop> { enum CustomMessage { WM_SWITCH_TO_UI_THREAD = WM_USER + 100, WM_ASYNC_TO_UI_THREAD, WM_SWITCH_TO_UI_THREAD2 }; BEGIN_MSG_MAP_EX(MessageLoop) MESSAGE_HANDLER(msg_taskbar_restart_, OnTaskbarCreated) //REGISTERED_MESSAGE_HANDLER_EX(msg_taskbar_restart_, OnTaskbarCreated) END_MSG_MAP() public: bool MsgLoopInit(bool use_current_thread, MSG_TASKBAR cb); bool MsgLoopUnInit(); private: /*template <typename T> void PostTask(T task) { std::function<void()> task_wrp = [task]() { task(); }; PostTask(task_wrp); } template <> void PostTask<std::function<void()>>(std::function<void()> task) { AddTask(task); this->PostMessage(CustomMessage::WM_ASYNC_TO_UI_THREAD, 0, 0); }*/ private: LRESULT OnAsyncToUIThreadMessage(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/); LRESULT OnTaskbarCreated(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/); void AddTask(std::function<void()> task); void DispatchTask(); private: UINT msg_taskbar_restart_; DWORD thread_id_ = 0; std::thread message_loop_thread_; std::mutex mutex_; //std::list<std::function<void()>> tasks_; std::mutex tasks_mutex_; MSG_TASKBAR cb_; }; #endif // WIN_TOOLS_MESSAGE_LOOP_H |
cpp
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 |
#include "message_loop.h" #include <LdsUtils/smart_ptr.hpp> //extern std::atomic<bool> flag; bool MessageLoop::MsgLoopInit(bool use_current_thread, MSG_TASKBAR cb) { std::unique_lock<std::mutex>locker(mutex_); cb_ = cb; msg_taskbar_restart_ = RegisterWindowMessage(TEXT("TaskbarCreated")); if (thread_id_) { return true; } smart_ptr::handle create_event = CreateEvent(NULL, FALSE, FALSE, FALSE); //HANDLE create_event = CreateEvent(NULL, FALSE, FALSE, FALSE); message_loop_thread_ = std::thread([&]() { thread_id_ = GetCurrentThreadId(); Create(NULL, NULL, NULL, WS_POPUP); SetEvent(create_event); CMessageLoop theLoop; theLoop.Run(); }); return true; } bool MessageLoop::MsgLoopUnInit() { if (IsWindow()) { DestroyWindow(); m_hWnd = NULL; } if (message_loop_thread_.joinable()) { ::PostThreadMessage(thread_id_, WM_QUIT, 0, 0); message_loop_thread_.join(); } //tasks_.clear(); return true; } LRESULT MessageLoop::OnAsyncToUIThreadMessage(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/) { DispatchTask(); return 0; } LRESULT MessageLoop::OnTaskbarCreated(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/) { /*if (cb_) { cb_("taskbar"); }*/ /*if (!flag.load()) { flag.store(true); }*/ //::MessageBox(NULL, L"OnTaskbarCreated", L"OnTaskbarCreated", MB_OK); return 0; } void MessageLoop::AddTask(std::function<void()> task) { //std::unique_lock<std::mutex>locker(tasks_mutex_); //tasks_.push_back(task); } void MessageLoop::DispatchTask() { /*std::function<void()> task; { std::unique_lock<std::mutex>locker(tasks_mutex_); task = tasks_.front(); tasks_.pop_front(); } task();*/ } |
其他:Visual studio
相关
符合模式permissive
- 概述
/permissive-
是Visual Studio
(从VS 2017
版本开始引入)中的一个重要编译器选项,旨在让编译器遵循最新的C++
语言标准(C++11
、C++14
、C++17
、C++20
及更高)更严格,并禁用许多历史悠久的Microsoft
特有的语言扩展- 目标是提高代码的可移植性和符合标准
- 作用
- 在
/permissive-
模式下,编译器对代码的标准符合性要求显著提高 - 它会拒绝编译许多依赖于非标准、
Microsoft
传统行为的代码,这些行为在默认的/permissive
(VS 2019 Update 3 (16.3)
起,默认为/permissive-
)或更早版本的MSVC
编译器宽松模式下会被接受
- 在
其他
强制内存访问+编译指令 防优化
- 概述
- 看一段
dump
收集相关的实现,发现了这个手法
- 看一段
1 2 3 4 5 6 7 8 9 10 |
HRESULT CDbgHelper::SetFilter(void) { // 设置新的Filter,保存原来的Filter SetUnhandledExceptionFilter( _MiniDumpHanlder ); // 破坏SetUnhandledExceptionFilter,避免我们的Filter被覆盖 bool bRet = EnforceFilter(true); return bRet ? S_OK : E_FAIL; } |
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 |
bool CDbgHelper::EnforceFilter( bool bEnforce ) { DWORD ErrCode = 0; // Obtain the address of SetUnhandledExceptionFilter HMODULE hLib = GetModuleHandle( _T("kernel32.dll") ); if( hLib == NULL ) { ErrCode = GetLastError(); _ASSERTE( !_T("GetModuleHandle(kernel32.dll) failed.") ); return false; } BYTE* pTarget = (BYTE*)GetProcAddress( hLib, "SetUnhandledExceptionFilter" ); if( pTarget == 0 ) { ErrCode = GetLastError(); _ASSERTE( !_T("GetProcAddress(SetUnhandledExceptionFilter) failed.") ); return false; } if( IsBadReadPtr( pTarget, sizeof(OriginalBytes) ) ) { _ASSERTE( !_T("Target is unreadable.") ); return false; } if( bEnforce ) { // Save the original contents of SetUnhandledExceptionFilter memcpy( OriginalBytes, pTarget, sizeof(OriginalBytes) ); // Patch SetUnhandledExceptionFilter if( !WriteMemory( pTarget, c_PatchBytes, sizeof(c_PatchBytes) ) ) return false; } else { // Restore the original behavior of SetUnhandledExceptionFilter if( !WriteMemory( pTarget, OriginalBytes, sizeof(OriginalBytes) ) ) return false; } // Success return true; } |
- 代码
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 |
LONG WINAPI CDbgHelper::_MiniDumpHanlder( PEXCEPTION_POINTERS pep ) { // 记录常规信息到minidump中 DWORD last_error = GetLastError(); debug::Ref(&last_error); bool is_user32_and_gdi32_available = gdi_collector::IsUser32AndGdi32Available(); DWORD num_user_handles = GetGuiResources(GetCurrentProcess(), GR_USEROBJECTS); DWORD num_gdi_handles = GetGuiResources(GetCurrentProcess(), GR_GDIOBJECTS); debug::Ref(&is_user32_and_gdi32_available); debug::Ref(&num_user_handles); debug::Ref(&num_gdi_handles); gdi_collector::GdiHandleCounts gdi_handle_counts = gdi_collector::CollectGdiHandles(GetCurrentProcessId()); debug::Ref(&gdi_handle_counts); // 获取当前进程的句柄数; DWORD handle_count = 0; if (GetProcessHandleCount(GetCurrentProcess(), &handle_count) == FALSE) { handle_count = 0; } debug::Ref(&handle_count); // 获取当前系统的架构是32位还是64位; SYSTEM_INFO system_info = {}; GetSystemInfo(&system_info); debug::Ref(&system_info); // 获取当前进程的内存信息; MEMORYSTATUSEX memory_status = {}; memory_status.dwLength = sizeof(memory_status); GlobalMemoryStatusEx(&memory_status); debug::Ref(&memory_status); PROCESS_MEMORY_COUNTERS_EX pmc; GetProcessMemoryInfo(::GetCurrentProcess(), (PROCESS_MEMORY_COUNTERS*)&pmc, sizeof(pmc)); debug::Ref(&pmc); WCHAR szDumper[MAX_PATH] = {}; GetModuleFileName(NULL, szDumper, MAX_PATH); PathRemoveFileSpec(szDumper); CString strBase(szDumper); CString strDumpUper = strBase + L"\\DumpUper.exe"; if(_waccess(strDumpUper, 4) != 0) { strDumpUper = strBase + L"\\Utils\\DumpUper.exe"; //加一层,从上一层目录查找 if(_waccess(strDumpUper, 4) != 0) { strDumpUper = strBase + L"\\..\\DumpUper.exe"; if(_waccess(strDumpUper, 4) != 0) { strDumpUper = strBase + L"\\..\\..\\DumpUper.exe"; } } } CString szParam; szParam.Format(L"--pep=%llu --pid=%d --tid=%d --src=%s --ver=%s", (UINT64)pep, (UINT)GetCurrentProcessId(), (UINT)GetCurrentThreadId(), (LPCTSTR)m_szSrc, (LPCTSTR)m_szVersion); SHELLEXECUTEINFO si; ZeroMemory(&si, sizeof(si)); si.cbSize = sizeof(si); si.lpFile = strDumpUper; si.lpParameters = szParam; si.nShow = SW_HIDE; si.fMask = SEE_MASK_FLAG_NO_UI | SEE_MASK_NOCLOSEPROCESS; BOOL bRet = ::ShellExecuteExW(&si); if(bRet) { //break,等待dump生成完了会杀掉 WaitForSingleObject(si.hProcess, INFINITE); CloseHandle(si.hProcess); } return EXCEPTION_EXECUTE_HANDLER; } |
- 问题
- 发现很多重要信息之后都调用了这个
debug::Ref
- 发现很多重要信息之后都调用了这个
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
#pragma optimize("", off) void __declspec(noinline) debug::Ref(const void* ref) { if (ref == nullptr) return; // 内联汇编强制读取内存 #ifndef _WIN64 __asm { mov eax, ref // 将指针地址存入eax mov eax, [eax] // 解引用读取内存值 } #else #error "Not implemented" #endif } #pragma optimize("", on) |
- 解析
#pragma optimize("", off)
强制编译器不对该函数进行优化(如删除“无副作用”代码),确保汇编指令被保留__declspec(noinline)
阻止编译器将函数内联展开,避免其逻辑被合并到调用处后被优化掉- 内联汇编(
32
位环境)
mov eax, ref
:将指针ref
(指向last_error
)的地址加载到寄存器eax
mov eax, [eax]
:解引用操作,读取eax
指向的内存值(即last_error
的实际内容)
此操作通过显式内存访问“欺骗”编译器,使其认为last_error
被使用,从而保留该变量
- 总结
- 通过
debug::Ref
的“虚假”内存访问,迫使编译器保留last_error
及其值
- 通过
一种Windows
的延迟删除机制
- 通过
CreateFileW
的特定参数组合实现了一种延迟删除机制:- 文件不会立即被删除,而是在所有句柄关闭后由系统自动删除
- 关键在于
FILE_FLAG_DELETE_ON_CLOSE
标志,其作用如下:- 当该句柄(或文件的其他所有句柄)被关闭时,系统自动删除文件
- 删除操作由文件系统驱动(如
NTFS
、FAT32
)在关闭时执行,而非应用程序主动调用DeleteFile
- 调用者需具备文件的删除权限(
DELETE
)或父目录的子项删除权限(DELETE_CHILD
)
- 实现
DELETE
:请求删除访问权限,允许后续通过句柄标记文件为“待删除”FILE_SHARE_DELETE
:允许其他进程以DELETE
权限打开同一文件(例如重命名操作)OPEN_EXISTING
:仅打开已存在的文件。若文件不存在,返回INVALID_HANDLE_VALUE
(错误码ERROR_FILE_NOT_FOUND
)FILE_FLAG_RANDOM_ACCESS
:提示系统优化缓存策略(针对随机访问模式),提升性能但非必需
1 2 3 4 5 6 7 8 9 10 11 12 |
HANDLE hDelFile = CreateFileW( tmp_path.c_str(), DELETE, FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE | FILE_FLAG_RANDOM_ACCESS, NULL); if (hDelFile != INVALID_HANDLE_VALUE) { FILE_DISPOSITION_INFO dispInfo = {TRUE}; SetFileInformationByHandle(hDelFile, FileDispositionInfo, &dispInfo, sizeof(dispInfo)); CloseHandle(hDelFile); } else { DeleteFileW(tmp_path.c_str()); } |
声明:本文为原创文章,版权归Aet所有,欢迎分享本文,转载请保留出处!
你可能也喜欢
- ♥ Windows 核心编程 _ 内核对象:同步异步设备IO08/24
- ♥ Visual Studio:远程部署调试相关06/30
- ♥ Windows 核心编程 _ 内核对象:线程同步一07/29
- ♥ Windows 核心编程 _ 内核对象一06/04
- ♥ Windows 核心编程 _ 作业07/01
- ♥ Windows线程同步相关03/10