本来运行的挺好的Thunk,到了Vista下居然不能运行了。 跟踪了半天,终于发现了问题。 原来,new 分配的空间,已经不再是可读、可写、可执行。修改一下窗口Thunk的代码,终于搞定。 // ----------------------------- head file --------------------------- #pragma once #include <windows.h> #include <tchar.h> #ifndef HX3DWND_BULID_LIB #pragma comment( lib, "HXWindows.lib" ) #endif #pragma pack( push, 1 ) struct _WndProcThunk { DWORD m_mov; // mov dword ptr [esp+0x4], pThis (esp+0x4 is hWnd) DWORD m_this; BYTE m_jmp; // jmp WndProc DWORD m_relproc; // relative jmp }; #pragma pack( pop ) class CHXThunk { public: _WndProcThunk thunk; #pragma warning( push ) #pragma warning( disable : 4311 ) void Init( WNDPROC proc, void * pThis ) { thunk.m_mov = 0x042444C7; //C7 44 24 0C thunk.m_this = ( DWORD ) pThis; thunk.m_jmp = 0xe9; thunk.m_relproc = ( int ) proc - (( int ) this + sizeof( _WndProcThunk )); FlushInstructionCache( GetCurrentProcess(), &thunk, sizeof( thunk )); } #pragma warning( pop ) }; class CHXWindows { public: explicit CHXWindows( HINSTANCE hInstance = NULL ); virtual ~CHXWindows( void ); protected: CHXThunk * m_pThunk; HINSTANCE m_hInstance; HWND m_hWnd; protected: static LRESULT CALLBACK StaticWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); virtual LRESULT WindowProc( UINT uMsg, WPARAM wParam, LPARAM lParam ); virtual BOOL PreTranslateMessage( UINT uMsg, WPARAM wParam, LPARAM lParam ); virtual void PreCreateWindow( CREATESTRUCT& crt ); virtual void OnCreate( LPCREATESTRUCT lpCreateStruct ); virtual void OnNcDestroy(); virtual void OnDestroy(); virtual void OnPaint( HDC& dc ); virtual void OnKillFocus( HWND hWnd ); virtual void OnSetFocus( HWND hWnd ); virtual void OnCommand( UINT uCmdID ); virtual void OnMouseMove( POINT& pt, DWORD dwFlag ); virtual void OnLButtonDown( POINT& pt, DWORD dwFlag ); virtual void OnLButtonUp( POINT& pt, DWORD dwFlag ); virtual void OnRButtonDown( POINT& pt, DWORD dwFlag ); virtual void OnRButtonUp( POINT& pt, DWORD dwFlag ); virtual void OnLButtonDbClick( POINT& pt, DWORD dwFlag ); virtual void OnKeyDown( UINT nChar, UINT uFlags ); virtual void OnKeyUp( UINT nChar ); virtual void OnChar( UINT nChar, UINT uFlags ); virtual void OnIdle(); virtual void OnClose(); public: HWND Create( LPCTSTR lpWindowName, LPCTSTR lpszClassName, DWORD dwStyle, int x, int y, int cx, int cy, DWORD dwExStyle = 0, HWND hWndParant = NULL ); void MessageLoop( UINT uAccelID = 0 ); void GetWindowRect( LPRECT lpRect ); void GetClientRect( LPRECT lpRect ); void MoveWindow( int x, int y, int dx, int dy, BOOL bIsRedraw = TRUE ); void MoveWindow( LPRECT lpRect, BOOL bIsRedraw = TRUE ); BOOL IsWindowEnabled(); BOOL IsWindowVisible(); DWORD GetWindowStyle(); void SetCapture(); void SetFocus(); void Invalidate( LPRECT pRt = NULL, BOOL bRedraw = TRUE ); void GetWindowText( LPTSTR lpszText, int nBufferSize ); void ShowWindow( BOOL bShow = TRUE ); void UpdateWindow(); void ScreenToClient( LPRECT pRect ); void ClientToScreen( LPRECT pRect ); void ScreenToClient( LPPOINT pPt ); void ClientToScreen( LPPOINT pPt ); HMENU GetMenu(); public: operator HWND (); }; // ------------------------ cpp file --------------------------------- #include "StdAfx.h" #include "HXWindows.h" CHXWindows::CHXWindows( HINSTANCE hInstance ) : m_hWnd( NULL ), m_hInstance( hInstance ) { } CHXWindows::~CHXWindows(void) { if( m_pThunk != NULL ) { if ( IsProcessorFeaturePresent( 12 )) //Data execution prevention is enabled VirtualFree( m_pThunk, 0, MEM_RELEASE ); else delete m_pThunk; } } LRESULT CALLBACK CHXWindows::StaticWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { CHXWindows * pThis = NULL; #pragma warning ( push ) #pragma warning ( disable : 4311 ) if( GetWindowLong( hWnd, GWL_WNDPROC ) == ( LONG ) CHXWindows::StaticWndProc ) { if( uMsg == WM_NCCREATE ) { pThis = ( CHXWindows * ) (( LPCREATESTRUCT ) lParam )->lpCreateParams; pThis->m_hWnd = hWnd; if ( IsProcessorFeaturePresent( 12 )) //Data execution prevention is enabled { pThis->m_pThunk = reinterpret_cast< CHXThunk * > ( VirtualAlloc( NULL,sizeof( CHXThunk ), MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE )); } else pThis->m_pThunk = new CHXThunk; pThis->m_pThunk->Init( StaticWndProc, pThis ); ::SetWindowLong( hWnd, GWL_WNDPROC,( LONG ) &( pThis->m_pThunk->thunk )); return pThis->WindowProc( uMsg, wParam, lParam ); } else return ::DefWindowProc( hWnd, uMsg, wParam, lParam ); } else { pThis = ( CHXWindows * ) hWnd; return pThis->WindowProc( uMsg, wParam, lParam ); } #pragma warning ( pop ) } HWND CHXWindows::Create( LPCTSTR lpWindowName, LPCTSTR lpszClassName, DWORD dwStyle, int x, int y, int cx, int cy, DWORD dwExStyle, HWND hWndParant ) { WNDCLASSEX wcex; wcex.cbSize = sizeof( WNDCLASSEX ); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = CHXWindows::StaticWndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = m_hInstance; wcex.hIcon = NULL; wcex.hCursor = LoadCursor( NULL, IDC_ARROW ); wcex.hbrBackground = ( HBRUSH ) ( COLOR_WINDOW + 1 ); wcex.lpszMenuName = NULL; wcex.lpszClassName = lpszClassName; wcex.hIconSm = NULL; CREATESTRUCT crt; crt.lpszClass = lpszClassName; crt.lpszName = lpWindowName; crt.x = x; crt.y = y; crt.cx = cx; crt.cy = cy; crt.dwExStyle = dwExStyle; crt.hInstance = m_hInstance; crt.hMenu = NULL; crt.hwndParent = hWndParant; crt.lpCreateParams = NULL; crt.style = dwStyle; PreCreateWindow( crt ); RegisterClassEx( &wcex ); CreateWindowEx( crt.dwExStyle, crt.lpszClass, crt.lpszName, crt.style, crt.x, crt.y, crt.cx, crt.cy, crt.hwndParent, crt.hMenu, crt.hInstance, this ); return m_hWnd; } LRESULT CHXWindows::WindowProc( UINT uMsg, WPARAM wParam, LPARAM lParam ) { switch ( uMsg ) { case WM_COMMAND: { UINT wmId; wmId = LOWORD( wParam ); OnCommand( wmId ); } break; case WM_PAINT: { PAINTSTRUCT ps; HDC hdc; hdc = BeginPaint( m_hWnd, &ps); OnPaint( hdc ); EndPaint( m_hWnd, &ps); } break; case WM_DESTROY: OnDestroy(); break; case WM_NCDESTROY: OnNcDestroy(); break; case WM_MOUSEMOVE: { POINT pt; pt.x = LOWORD( lParam ); pt.y = HIWORD( lParam ); OnMouseMove( pt, ( DWORD ) wParam ); } break; case WM_LBUTTONDOWN: { POINT pt; pt.x = LOWORD( lParam ); pt.y = HIWORD( lParam ); OnLButtonDown( pt, ( DWORD ) wParam ); } break; case WM_LBUTTONUP: { POINT pt; pt.x = LOWORD( lParam ); pt.y = HIWORD( lParam ); OnLButtonUp( pt, ( DWORD ) wParam ); } break; case WM_LBUTTONDBLCLK: { POINT pt; pt.x = LOWORD( lParam ); pt.y = HIWORD( lParam ); OnLButtonDbClick( pt, ( DWORD ) wParam ); } break; case WM_RBUTTONDOWN: { POINT pt; pt.x = LOWORD( lParam ); pt.y = HIWORD( lParam ); OnRButtonDown( pt, ( DWORD ) wParam ); } break; case WM_RBUTTONUP: { POINT pt; pt.x = LOWORD( lParam ); pt.y = HIWORD( lParam ); OnRButtonUp( pt, ( DWORD ) wParam ); } break; case WM_CREATE: OnCreate(( LPCREATESTRUCT ) lParam ); break; default: return DefWindowProc( m_hWnd, uMsg, wParam, lParam); } return 0; } void CHXWindows::MessageLoop( UINT uAccelID ) { HACCEL hAccelTable = NULL; if( uAccelID != 0 ) hAccelTable = LoadAccelerators( m_hInstance, MAKEINTRESOURCE( uAccelID )); MSG msg; ::ZeroMemory( &msg, sizeof( MSG )); while( msg.message != WM_QUIT ) { if( ::PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) { if( PreTranslateMessage( msg.message, msg.wParam, msg.lParam )) continue; if(( hAccelTable == NULL ) || ( ! TranslateAccelerator( msg.hwnd, hAccelTable, &msg ))) { TranslateMessage(&msg); DispatchMessage(&msg); } } else { OnIdle(); } } } BOOL CHXWindows::PreTranslateMessage( UINT uMsg, WPARAM wParam, LPARAM lParam ) { return FALSE; } void CHXWindows::OnDestroy(){} void CHXWindows::OnCommand( UINT uCmdID ){} void CHXWindows::OnClose(){} void CHXWindows::PreCreateWindow( CREATESTRUCT& crt ){} void CHXWindows::OnCreate( LPCREATESTRUCT lpCreateStruct ){} void CHXWindows::OnNcDestroy(){} void CHXWindows::OnPaint( HDC& dc ){} void CHXWindows::OnKillFocus( HWND hWnd ){} void CHXWindows::OnSetFocus( HWND hWnd ){} void CHXWindows::OnMouseMove( POINT& pt, DWORD dwFlag ){} void CHXWindows::OnLButtonDown( POINT& pt, DWORD dwFlag ){} void CHXWindows::OnLButtonUp( POINT& pt, DWORD dwFlag ){} void CHXWindows::OnRButtonDown( POINT& pt, DWORD dwFlag ){} void CHXWindows::OnRButtonUp( POINT& pt, DWORD dwFlag ){} void CHXWindows::OnLButtonDbClick( POINT& pt, DWORD dwFlag ){} void CHXWindows::OnKeyDown( UINT nChar, UINT uFlags ){} void CHXWindows::OnKeyUp( UINT nChar ){} void CHXWindows::OnChar( UINT nChar, UINT uFlags ){} void CHXWindows::OnIdle(){} void CHXWindows::GetWindowRect( LPRECT lpRect ) { ::GetWindowRect( m_hWnd, lpRect ); } void CHXWindows::GetClientRect( LPRECT lpRect ) { ::GetClientRect( m_hWnd, lpRect ); } void CHXWindows::MoveWindow( int x, int y, int dx, int dy, BOOL bIsRedraw ) { ::MoveWindow( m_hWnd, x, y, dx, dy, bIsRedraw ); } void CHXWindows::MoveWindow( LPRECT lpRect, BOOL bIsRedraw ) { ::MoveWindow( m_hWnd, lpRect->left, lpRect->top, ( lpRect->right - lpRect->left ), ( lpRect->bottom - lpRect->top ), bIsRedraw ); } BOOL CHXWindows::IsWindowEnabled() { return ::IsWindowEnabled( m_hWnd ); } BOOL CHXWindows::IsWindowVisible() { return ::IsWindowVisible( m_hWnd ); } DWORD CHXWindows::GetWindowStyle() { return ( DWORD ) ::GetWindowLong( m_hWnd, GWL_STYLE ); } void CHXWindows::SetCapture() { ::SetCapture( m_hWnd ); } void CHXWindows::SetFocus() { ::SetFocus( m_hWnd ); } void CHXWindows::Invalidate( LPRECT pRt, BOOL bRedraw ) { ::InvalidateRect( m_hWnd, pRt, bRedraw ); } void CHXWindows::GetWindowText( LPTSTR lpszText, int nBufferSize ) { ::GetWindowText( m_hWnd, lpszText, nBufferSize ); } void CHXWindows::ShowWindow( BOOL bShow ) { ::ShowWindow( m_hWnd, bShow ? SW_SHOW : SW_HIDE ); } CHXWindows::operator HWND () { return m_hWnd; } void CHXWindows::UpdateWindow() { ::UpdateWindow( m_hWnd ); } void CHXWindows::ScreenToClient( LPRECT pRect ) { POINT pt; pt.x = pRect->left; pt.y = pRect->top; ::ScreenToClient( m_hWnd, &pt ); pRect->left = pt.x; pRect->top = pt.y; pt.x = pRect->right; pt.y = pRect->bottom; ::ScreenToClient( m_hWnd, &pt ); pRect->right = pt.x; pRect->bottom = pt.y; } void CHXWindows::ClientToScreen( LPRECT pRect ) { POINT pt; pt.x = pRect->left; pt.y = pRect->top; ::ClientToScreen( m_hWnd, &pt ); pRect->left = pt.x; pRect->top = pt.y; pt.x = pRect->right; pt.y = pRect->bottom; ::ClientToScreen( m_hWnd, &pt ); pRect->right = pt.x; pRect->bottom = pt.y; } void CHXWindows::ScreenToClient( LPPOINT pPt ) { ::ScreenToClient( m_hWnd, pPt ); } void CHXWindows::ClientToScreen( LPPOINT pPt ) { ::ClientToScreen( m_hWnd, pPt ); } HMENU CHXWindows::GetMenu() { return ::GetMenu( m_hWnd ); }