搜了些thunk原理,其中有一句话实在不理解,有人用过thunk吗? 以下是几个头文件和main.cpp,应该直接能编译运行,异常出现位置见下面代码中注释部分,请教这咋整,谢谢。AJ_Thunk.h
#pragma pack(push,1)
struct AJ_Thunk {
DWORD _mov;
DWORD _this;
BYTE _jmp;
DWORD _relProc; void init(DWORD proc, void* pThis) { _mov = 0x042444C7;
_this = PtrToLong(pThis); _jmp = 0xE9;
_relProc = DWORD((INT_PTR)proc - ((INT_PTR)this + sizeof(AJ_Thunk))); FlushInstructionCache(GetCurrentProcess(), this, sizeof(AJ_Thunk));
}
};
#pragma pack(pop)AJ_Window.h
//#include "AJ_Component.h"
#include <string>
using namespace std;#define AJ_UI_CLASS_NAME "xxxx"
#include "Thunk/AJ_Thunk.h"LRESULT CALLBACK AJ_WndInitProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);LRESULT CALLBACK AJ_WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
class AJ_Window {
private:
int a;
public:
HWND hWnd; AJ_Thunk* thunk; ATOM registerClass() { WNDCLASS wndclass; wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = AJ_WndInitProc;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = NULL ;
wndclass.hIcon = LoadIcon( NULL, IDI_APPLICATION ) ;
wndclass.hCursor = LoadCursor( NULL, IDC_ARROW ) ;
wndclass.hbrBackground = ( HBRUSH ) GetStockObject( WHITE_BRUSH ) ;
wndclass.lpszMenuName = "" ;
wndclass.lpszClassName = AJ_UI_CLASS_NAME;
wndclass.hbrBackground = HBRUSH(COLOR_WINDOW ) ; return RegisterClass(&wndclass);
}
AJ_Thunk* createThunk() {
thunk = new AJ_Thunk;
thunk->init((DWORD)AJ_WndInitProc, this); return thunk;
}
void showError() {
}
MSG msg;
void wait() {
while(GetMessage( &msg, NULL, 0, 0 )){
TranslateMessage( &msg ) ;
DispatchMessage( &msg ) ;
}
}
AJ_Window() : hWnd(NULL), a(9) {
this->registerClass(); string title = "aj window";
CreateWindow(
AJ_UI_CLASS_NAME,
title.c_str(),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT ,
CW_USEDEFAULT ,
//width ? width : 480,
//height ? height :260,
300,200,
NULL,
NULL,
NULL,
this ) ;
if(hWnd == NULL) {
this->showError();
} }
WNDPROC getThunk() {
return (WNDPROC)thunk;
}
~AJ_Window() {
delete thunk;
} void show() {
ShowWindow(hWnd, true);
}
void hide() {
ShowWindow(hWnd, false);
} void updateWindow() {
::UpdateWindow(hWnd);
}
void onPaint() {
PAINTSTRUCT ps;
HDC hdc;
hdc = BeginPaint(hWnd, &ps);
TextOut(hdc, 10, 10, "tttt", 4);
EndPaint(hWnd, &ps);
}
void onDestory() {
PostQuitMessage(0);
}
};
LRESULT CALLBACK AJ_WndInitProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
if(msg == WM_NCCREATE) {
AJ_Window* win = (AJ_Window*)((LPCREATESTRUCT)lParam)->lpCreateParams;
win->hWnd = hWnd;
SetWindowLong(hWnd, GWL_WNDPROC, (LONG)win->createThunk());
WNDPROC thunk = win->getThunk();
return (*thunk)(hWnd, msg, wParam, lParam); // 就这个地方异常
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}LRESULT CALLBACK AJ_WndProc(HWND hWnd, UINT msg, UINT wParam, UINT lParam) {
AJ_Window* pWindow = (AJ_Window*)hWnd;
switch(msg){
case WM_PAINT:
pWindow->onPaint();
break;
case WM_DESTROY:
pWindow->onDestory();
break;
default:
return DefWindowProc( hWnd, msg, wParam, lParam ) ;
}
return 0;
}
main.cpp
#include <Windows.h>#include "AJ_Window.h"
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) { AJ_Window* win = new AJ_Window(); win->show(); win->wait();
return 0;
}
#pragma pack(push,1)
struct AJ_Thunk {
DWORD _mov;
DWORD _this;
BYTE _jmp;
DWORD _relProc; void init(DWORD proc, void* pThis) { _mov = 0x042444C7;
_this = PtrToLong(pThis); _jmp = 0xE9;
_relProc = DWORD((INT_PTR)proc - ((INT_PTR)this + sizeof(AJ_Thunk))); FlushInstructionCache(GetCurrentProcess(), this, sizeof(AJ_Thunk));
}
};
#pragma pack(pop)AJ_Window.h
//#include "AJ_Component.h"
#include <string>
using namespace std;#define AJ_UI_CLASS_NAME "xxxx"
#include "Thunk/AJ_Thunk.h"LRESULT CALLBACK AJ_WndInitProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);LRESULT CALLBACK AJ_WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
class AJ_Window {
private:
int a;
public:
HWND hWnd; AJ_Thunk* thunk; ATOM registerClass() { WNDCLASS wndclass; wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = AJ_WndInitProc;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = NULL ;
wndclass.hIcon = LoadIcon( NULL, IDI_APPLICATION ) ;
wndclass.hCursor = LoadCursor( NULL, IDC_ARROW ) ;
wndclass.hbrBackground = ( HBRUSH ) GetStockObject( WHITE_BRUSH ) ;
wndclass.lpszMenuName = "" ;
wndclass.lpszClassName = AJ_UI_CLASS_NAME;
wndclass.hbrBackground = HBRUSH(COLOR_WINDOW ) ; return RegisterClass(&wndclass);
}
AJ_Thunk* createThunk() {
thunk = new AJ_Thunk;
thunk->init((DWORD)AJ_WndInitProc, this); return thunk;
}
void showError() {
}
MSG msg;
void wait() {
while(GetMessage( &msg, NULL, 0, 0 )){
TranslateMessage( &msg ) ;
DispatchMessage( &msg ) ;
}
}
AJ_Window() : hWnd(NULL), a(9) {
this->registerClass(); string title = "aj window";
CreateWindow(
AJ_UI_CLASS_NAME,
title.c_str(),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT ,
CW_USEDEFAULT ,
//width ? width : 480,
//height ? height :260,
300,200,
NULL,
NULL,
NULL,
this ) ;
if(hWnd == NULL) {
this->showError();
} }
WNDPROC getThunk() {
return (WNDPROC)thunk;
}
~AJ_Window() {
delete thunk;
} void show() {
ShowWindow(hWnd, true);
}
void hide() {
ShowWindow(hWnd, false);
} void updateWindow() {
::UpdateWindow(hWnd);
}
void onPaint() {
PAINTSTRUCT ps;
HDC hdc;
hdc = BeginPaint(hWnd, &ps);
TextOut(hdc, 10, 10, "tttt", 4);
EndPaint(hWnd, &ps);
}
void onDestory() {
PostQuitMessage(0);
}
};
LRESULT CALLBACK AJ_WndInitProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
if(msg == WM_NCCREATE) {
AJ_Window* win = (AJ_Window*)((LPCREATESTRUCT)lParam)->lpCreateParams;
win->hWnd = hWnd;
SetWindowLong(hWnd, GWL_WNDPROC, (LONG)win->createThunk());
WNDPROC thunk = win->getThunk();
return (*thunk)(hWnd, msg, wParam, lParam); // 就这个地方异常
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}LRESULT CALLBACK AJ_WndProc(HWND hWnd, UINT msg, UINT wParam, UINT lParam) {
AJ_Window* pWindow = (AJ_Window*)hWnd;
switch(msg){
case WM_PAINT:
pWindow->onPaint();
break;
case WM_DESTROY:
pWindow->onDestory();
break;
default:
return DefWindowProc( hWnd, msg, wParam, lParam ) ;
}
return 0;
}
main.cpp
#include <Windows.h>#include "AJ_Window.h"
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) { AJ_Window* win = new AJ_Window(); win->show(); win->wait();
return 0;
}
请参考这个 http://blog.csdn.net/lqk1985/archive/2009/11/10/4791304.aspx
不明白你这里也拿来用了,既然都是windows,封装现有的问题不大吧,可移植性应该好点。
Unhandled exception at 0x006c4a58 in UI.exe: 0xC0000005: Access violation.
AJ_Window.cpp
//#include "AJ_Component.h"
#include <string>
using namespace std;#define AJ_UI_CLASS_NAME "xxxx"
#include "Thunk/AJ_Thunk.h"LRESULT CALLBACK AJ_WndInitProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);LRESULT CALLBACK AJ_WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); bool debug = false;
void showError() {
if(!debug) return;
LPVOID buff;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &buff,
0,
NULL
); MessageBox(NULL, (const char*)buff, "", NULL);}
class AJ_Window {
private:
int a;
public:
HWND hWnd; AJ_Thunk* thunk; ATOM registerClass() { WNDCLASS wndclass; wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = AJ_WndInitProc;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = NULL ;
wndclass.hIcon = LoadIcon( NULL, IDI_APPLICATION ) ;
wndclass.hCursor = LoadCursor( NULL, IDC_ARROW ) ;
wndclass.hbrBackground = ( HBRUSH ) GetStockObject( WHITE_BRUSH ) ;
wndclass.lpszMenuName = "" ;
wndclass.lpszClassName = AJ_UI_CLASS_NAME;
wndclass.hbrBackground = HBRUSH(COLOR_WINDOW ) ; return RegisterClass(&wndclass);
} AJ_Thunk* getThunk() {
if(!thunk) {
thunk = new AJ_Thunk;
thunk->init((DWORD)AJ_WndProc, this);
}
return thunk;
}
void wait() {
MSG msg;
while(GetMessage( &msg, NULL, 0, 0 )){
TranslateMessage( &msg ) ;
DispatchMessage( &msg ) ;
}
}
AJ_Window() : hWnd(NULL), thunk(NULL), a(9) {
showError();
this->registerClass();
showError(); string title = "aj window";
CreateWindow(
AJ_UI_CLASS_NAME,
title.c_str(),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT ,
CW_USEDEFAULT ,
//width ? width : 480,
//height ? height :260,
300,200,
NULL,
NULL,
NULL,
this ) ; showError(); } ~AJ_Window() {
delete thunk;
} void show() {
showError();
int succ = ShowWindow(hWnd, SW_SHOWNORMAL);
showError();
UpdateWindow(hWnd); }
void hide() {
ShowWindow(hWnd, false);
} void updateWindow() {
::UpdateWindow(hWnd);
}
void onPaint() {
PAINTSTRUCT ps;
HDC hdc;
hdc = BeginPaint(hWnd, &ps);
TextOut(hdc, 10, 10, "tttt", 4);
EndPaint(hWnd, &ps);
}
void onDestory() {
PostQuitMessage(0);
}
};
LRESULT CALLBACK AJ_WndInitProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
showError();
if(msg == WM_NCCREATE) {
AJ_Window* win = (AJ_Window*)((LPCREATESTRUCT)lParam)->lpCreateParams;
win->hWnd = hWnd;
showError();
SetWindowLong(hWnd, GWL_WNDPROC, (LONG)win->getThunk());
showError();
WNDPROC thunk = (WNDPROC)win->getThunk();
return (thunk)((HWND)win, msg, wParam, lParam);
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}LRESULT CALLBACK AJ_WndProc(HWND pWin, UINT msg, WPARAM wParam, LPARAM lParam) {
AJ_Window* pWindow = (AJ_Window*)pWin;
switch(msg){
case WM_PAINT:
pWindow->onPaint();
break;
case WM_DESTROY:
pWindow->onDestory();
break;
default:
return DefWindowProc( pWindow->hWnd, msg, wParam, lParam ) ;
}
return 0;
}
AJ_Thunk* getThunk() {
if(!thunk) {
thunk = new AJ_Thunk;
thunk->init((DWORD)AJ_WndProc, this);
}
return thunk;
}
估计是new的问题
试试使用VirtualAlloc之类的API分配内存
VC6和VC2008出现差异没碰到过,倒是因为WIN2003的数据执行保护会导致非法操作。
关于thunk更详细的说明请看这里:http://blog.csdn.net/ringphone/archive/2004/09/28/118883.aspx
不过这篇文章里的代码不能在WIN2003下运行,可运行的版本请到我博客下载RingSDK看里面的代码。
AJ_Thunk* getThunk() {
if(!thunk) {
thunk = (AJ_Thunk*)::VirtualAlloc(NULL, sizeof( AJ_Thunk ), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
thunk->init((DWORD)AJ_WndProc, this);
}
return thunk;
}