打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
Win32help翻译

Win32help翻译(Hooks)

hook提供一种机制,使得程序可以在消息的传递过程中加入自己的处理方法。由于hook增加了消息传递过程中的处理,所以会影响系统性能,应该仅在必须的时候使用hook

Windows提供多种不同的hook,每一种访问不同的消息处理,例如,程序可以使用WH_MOUSE来监视鼠标消息。对每种hook,Windows都提供了单独的hook chain。A hook chain is a listof pointers to special, application-defined callback functions calledhookprocedures。当消息产生时挂接到特定的钩子上,Windows将消息逐个传递给消息链上定义的钩子函数。钩子函数可以截取的消息取决于钩子的定义,有些钩子函数可以只能监视消息,有些则可以修改或取消消息。

为了处理hook,必须声明钩子函数并使用SetWindowsHookEx来安装到hook chain的最前端。
hook procedure的格式如下:
LRESULT CALLBACK HookProc(int nCode, WPARAM wParam, LPARAM lParam)
nCode的值取决于hook类型,每种hook都有不同的nCode值域。wParam和lParam取决于nCode
hook procedure可以通过CallNextHookEx将消息传递到下一个hook procedure。

hookprocedure如果为global,则监视系统中所有线程的消息;如果特定于线程,则只监视特定线程的消息。全局钩子函数必须在DLL中实现;如果钩子函数监视自身创建的线程,则可以在程序内实现钩子函数;如果监视的是不同进程的消息,则必须在DLL中实现。

钩子类型:
==================================================
◎ WH_CALLWNDPROC and WH_CALLWNDPROCRET Hooks
==================================================

WH_CALLWNDPROC钩子监视SendMessage消息的传递,WM_CALLWNDPROCRET在消息被处理、函数返回后被调用(看名称多了一个ret),它们都只能监视消息而不能修改。WH_CALLWNDPROC需要用到的结构:

LRESULT CALLBACK CallWndProc(int nCode, WPARAM wParam, LPARAM lParam)
nCode:如果nCode为HC_ACTION则proc必须处理消息,如果小于0,则必须不作处理的传递给CallNextHookEx并且result:=CallNextHookEx
wParam:如果消息是当前进程发送的,则值为非零,否则为零。
这两个参数都不知道效果,感觉第三个比较有用
lParam:指向CWPSTRUCT结构的指针

typedef struct tagCWPSTUCT{LPARAM lParam; WPARAM wParam; UINT message; HWND hwnd;} CWPSTRUCT
hwnd标识将要接收消息的窗体,其他的都是SendMessage的参数

HHOOK SetWindowsHookEx(int idHook, HOOKPROC lpfn, HINSTANCE hMod, DWORD dwThreadId);
idHook:type of hook
lpfn:hook procedure,如果是监视其他进程的hook,hook proc必须在dll中实现
hMod:标识包含hook procedure的DLL。如果是程序内的hook procedure则必须为NULL
dwThreadId:标识hook procedure要处理的thread,如果为0,则处理所有线程。
返回值:如果成功返回hook procedure的handle,如果失败返回NULL

应用方法:点击按钮时改变窗体caption,当加载hook后,会弹出对话框显示修改后的标题
procedure TForm1.FormCreate(Sender: TObject);
begin
FMsg := RegisterWindowMessage('ANUSERMSG'); //注册自定义消息
Application.OnMessage := OnCustomMessage; //消息发生时进行处理
EnableCWPHook; //启用hook,函数在DLL中实现
end;

procedure TForm1.OnCustomMessage(var msg: TMsg; var handled: Boolean);
begin
if (msg.message = FMsg) and (not handled) then
begin
    handled := True; //有什么作用?
    ShowMessage(PChar(msg.lParam)); //自定义消息的参数在lParam中传递
end;
end;

按钮点击事件:SendMessage(Handle, WM_SETTEXT, 0, Integer(PChar('abc'))); //发送消息,hook proc中捕捉WM_SETTEXT消息并发送自定义消息
窗体释放的时候取消hook:DisableCWPHook;

DLL中的实现

procedure EnableCWPHook;
begin
user_msg := RegisterWindowMessage('ANUSERMSG'); //注册自定义消息,必须在DLL和EXE中都进行注册
hHookProc := SetWindowsHookEx(WH_CALLWNDPROC, CallWNDProc, HInstance, 0); //调用函数注册钩子
end;

function CallWNDProc(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
var dw: DWORD;
begin
   if PCWPSTRUCT(lParam).message = WM_SETTEXT then //lParam见上面的结构说明
begin
    dw := BSM_ALLCOMPONENTS;
    //广播消息,以便APP可以接收
     BroadcastSystemMessage(BSF_POSTMESSAGE, @dw, user_msg, 0, PCWPSTRUCT(lParam).lParam);
end;
Result := 0; // the return value of CallWNDProc should always be zero.
end;

==================================================
◎WH_KEYBOARD Hook
==================================================
WH_KEYBOARD钩子可以监视键盘消息,当程序调用GetMessage或PeekMessage时,会得到WM_KEYDOWN和WM_KEYUP消息,此种hook截获这个消息供程序处理

LRESULT CALLBACK KeyboardProc(int code, WPARAM wParam, LPARAM lParam);
code:表示如何处理消息。HC_ACTION、HC_NOREMOVE,如果code<0,必须调用CallNextHookEx来处理并返回处理结果
wParam:键盘的virtual-key code
lParam:32位数值,详细含义可以查阅
Keystroke Message Flags
返回值:如果返回值为0,则消息在hook chain上传递,若返回值不为0,则消息不再继续传递(按键失效)

示例,监视按键(仅字母),在edit中显示按键

HKeyHook := SetWindowsHookEx(WH_KEYBOARD, @KeyBoardProc, 0, GetCurrentThreadId);

function KeyBoardProc(iCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall; //注意调用方式
var c: char; iCaps: Integer; pc: PChar;
begin
Result := 0; //允许消息的继续传递
if iCode < 0 then //iCode<0必须不作处理并返回处理结果
begin
    Result := CallNextHookEx(HKeyHook, iCode, wParam, lParam);
    Exit;
end;
GetMem(pc, 20);
GetKeyNameText(lParam, pc, 20); //获得按键名称,如:Caps Lock, Shift, Right Alt
if wParam in [$41..$5A] then //只处理字母
begin
    iCaps := (GetKeyState(VK_SHIFT) shr 31) xor (GetKeyState(VK_CAPITAL) and 1); //检查shift和caps状态确定大小写
    c := Char(wParam + (1 - iCaps) * $20); //小写字母要加20h
    Form1.edt2.Text := c + ' 0x' + IntToHex(Ord(c), 2) + ' lParam:0x' + IntToHex(lParam, 8);
end;
Form1.edt3.Text := pc;
FreeMem(pc);
end;

==================================================
◎WH_MOUSE Hook
==================================================
WM_MOUSE钩子可以用来监视鼠标消息

LRESULT CALLBACK MouseProc(int nCode, WPARAM wParam, LPARAM lParam);
nCode:同KeyboardHookProc,nCode<0只能传递处理
wParam:鼠标消息的标识,鼠标单击、双击右击等
lParam:MOUSEHOOKSTRUCT结构的指针
返回值:0继续传递,1不传递

typedef stuct tagMOUSEHOOKSTRUCT{POINT pt; HWND hwnd; UINT wHitTestCode; DWORD dwExtraInfo;} MOUSEHOOKSTRUCT;
pt:光标位置
hwnd:将要接受鼠标消息的窗口handle
wHitTestCode:标识鼠标所在位置 HTxx常量
dwExtraInfo:额外信息

示例,光标移动时在窗体caption显示光标位置信息。当光标不在当前窗口时,是无法收到光标消息的,因此使用全局hook

function MouseHookProc(iCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
var hookStruct: PMOUSEHOOKSTRUCT; sText: PChar; i: Integer;
begin
Result := 0;
if iCode < 0 then
begin
    Result := CallNextHookEx(hHookProc, iCode, wParam, lParam);
    Exit;
end;
hookStruct := PMOUSEHOOKSTRUCT(lParam);
i := (hookStruct.wHitTestCode); //具体值查询WM_NCHITTEST
sText := PChar(Format('X:%.4d Y:%.3d %d %d', [hookStruct.pt.X, hookStruct.pt.Y, i, wParam]));
SendMessage(hWindow, WM_SETTEXT, 0, Integer(sText));
end;

hWindow := FindWindow('TForm1', nil);

==================================================
◎WH_SHELL Hook
==================================================
shell程序使用WH_SHELL钩子获得重要的信息。windows在shell程序将要被激活或顶级窗口被创建和删除是调用WH_SHELL

LRESULT CALLBACK ShelProc( int nCode, WPARAM wParam, LPARAM lParam);
nCode:NT可用的只有以下三个
HSHELL_ACTIVATESHELLWINDOW:shell应当激活主窗体。wParam=0
HSHELL_WINDOWCREATED:顶级无主窗体被创建,当调用时窗体已存在。wParam为窗体的handle
HSHELL_DESTROYED:顶级无主窗体将要被销毁,调用时窗体仍存在。lParam为窗体handle
返回值:0

不知道何所谓shell程序,仅提供窗体实现当双击文件夹时修改窗体caption,显示计数

function shellProc(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
begin
Result := 0;
if nCode < 0 then
begin
Result := CallNextHookEx(hHookProc2, nCode, wParam, lParam);
    Exit;
end;
if nCode = HSHELL_WINDOWCREATED then
begin
    Inc(i); // i 为全局变量,计数用
    SendMessage(hWindow, WM_SETTEXT, 0, Integer(PChar('create ' + IntToStr(i))));
    
//SendMessage(wParam, WM_CLOSE, 0, 0); 这句执行的话,那可就……^_^
end;
end;

==================================================
◎WH_CBT Hook
==================================================
当系统发生以下事件时,调用WH_CBT hook函数:before activating,creating, destroying, minimizing, maximizing, moving, or sizing awindow; before completing a system command; before removing a mouse orkeyboard event from the system message queue; before setting the inputfocus; or before synchronizing with the system message queue. CBThook主要应用于computer-based traing程序

LRESULT CALLBACK CBTProc(int nCode, WPARAM wParam, LPARAM lParam);
nCode:见win32help CBTProc 一节
wParam, lParam:含义依赖于nCode

示例作一个比shell hook中更过分的,禁止所有窗口的创建

if nCode = HCBT_CREATEWND then Result := 1 //返回 1 表示不允许创建
else Result := 0;

程序中的调用也换换口味

procedure TForm1.FormCreate(Sender: TObject);
var
hInstDll: HINST;
hookProc: Pointer;
begin
hInstDll := LoadLibrary('CBTHook.dll');
hookProc := GetProcAddress(hInstDll, 'CBTHookProc');
hookProcResult := SetWindowsHookEx(WH_CBT, hookProc, 0, GetCurrentThreadId);
end;

==================================================
◎WH_DEBUG Hook
==================================================

==================================================
◎WH_FOREGROUNDIDLE Hook
==================================================

==================================================
◎WH_GETMESSAGE Hook
==================================================

==================================================
◎WH_JOURNALPLAYBACK Hook
==================================================

==================================================
◎WH_JOURNALRECORD Hook
==================================================

==================================================
◎WH_MSGFILTER and WH_SYSMSGFILTER Hooks
==================================================

由于些原因,到此

2006/9/12

无聊时的无聊

不记得谁说过,无聊的时候就编游戏好了。于是,我无聊了……

mapUtils.pas //类

unit mapUtils;

interface

uses
SysUtils, Classes, ExtCtrls, Controls, Contnrs, jpeg, Graphics, Dialogs;

type
PLight = ^TLight;
TLight = class(TImage)
private
FPicLightOn: TPicture;
FPicLightOff: TPicture;
FIsLightOn: Boolean;
protected
procedure SetPicLightOn(value: TPicture);
procedure SetPicLightOff(value: TPicture);
procedure ClickLight(Sender: TObject);
procedure SetIsLightOn(value: Boolean);
public
property IsLightOn: Boolean read FIsLightOn write SetIsLightOn;
constructor Create(AOwner: TComponent); override;
procedure changeStatus;
property picLightOn: TPicture read FPicLightOn write SetPicLightOn;
property picLightOff: TPicture read FPicLightOff write SetPicLightOff;
end;

TLightMang = class(TWinControl)
private
FList: TComponentList;
FRowCount, FColCount: Integer;
FPicLightOn: TPicture;
FPicLightOff: TPicture;
FGameOver: Boolean;
protected
procedure ClearLights;
procedure SetPicLightOn(value: string);
procedure SetPicLightOff(value: string);
public
property picLightOn: string write SetPicLightOn;
property picLightOff: string write SetPicLightOff;
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure CreateLights(iRow, iCol: Integer);
procedure LightOnClick(Sender: TObject);
function checkWin: Boolean;

procedure NewGame;
end;

implementation

{ TLight }

procedure TLight.changeStatus;
begin
IsLightOn := not IsLightOn;
end;

constructor TLight.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
Self.OnClick := ClickLight;
end;

procedure TLight.ClickLight(Sender: TObject);
begin
changeStatus;
end;

procedure TLight.SetPicLightOff(value: TPicture);
begin
FPicLightOff := value;
end;

procedure TLight.SetPicLightOn(value: TPicture);
begin
FPicLightOn := value;
end;

procedure TLight.SetIsLightOn(value: Boolean);
begin
if value then
begin
FIsLightOn := True;
Picture := FPicLightOn;
end
else
begin
FIsLightOn := False;
Picture := FPicLightOff;
end;
end;

{ TLightMang }

constructor TLightMang.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FList := TComponentList.Create(True);
end;

destructor TLightMang.Destroy;
begin
FList.Free;
if FPicLightOn <> nil then FreeAndNil(FPicLightOn);
if FPicLightOff <> nil then FreeAndNil(FPicLightOff);
inherited;
end;

procedure TLightMang.CreateLights(iRow, iCol: Integer);
var
i, j: Integer;
light: TLight;
begin
if FPicLightOn = nil then
raise Exception.Create('未指定灯亮图片');
if FPicLightOff = nil then
raise Exception.Create('未指定灯暗图片');
if FList <> nil then
ClearLights;
for i := 0 to iRow - 1 do
for j := 0 to iCol - 1 do
begin
light := TLight.Create(Self);
light.Parent := Self.Parent;
light.picLightOn := FPicLightOn;
light.picLightOff := FPicLightOff;
light.IsLightOn := False;
light.AutoSize := True;
light.Left := j * light.Width;
light.Top := i * light.Height;
light.Cursor := crHandPoint;
light.OnClick := LightOnClick;
FList.Add(light);
end;
FRowCount := iRow;
FColCount := iCol;
end;

procedure TLightMang.ClearLights;
var
i: Integer;
begin
for i := FList.Count - 1 downto 0 do
FList.Delete(i);

FRowCount := 0;
FColCount := 0;
end;

procedure TLightMang.SetPicLightOn(value: string);
begin
if FPicLightOn = nil then FPicLightOn := TPicture.Create;
FPicLightOn.LoadFromFile(value);
end;

procedure TLightMang.SetPicLightOff(value: string);
begin
if FPicLightOff = nil then FPicLightOff := TPicture.Create;
FPicLightOff.LoadFromFile(value);
end;

procedure TLightMang.LightOnClick(Sender: TObject);
var
light: TLight;
i, iRow, iCol: Integer;
begin
if FGameOver then Exit;
light := (sender as TLight);
if not Assigned(light) then exit;
i := FList.IndexOf(light);
iRow := Trunc(i / FColCount);
iCol := i mod FColCount;
light.changeStatus;
if iRow > 0 then TLight(FList[i - FColCount]).changeStatus;
if iRow < FRowCount - 1 then TLight(FList[i + FColCount]).changeStatus;
if iCol > 0 then TLight(FList[i - 1]).changeStatus;
if iCol < FColCount - 1 then TLight(FList[i + 1]).changeStatus;
if checkWin then ShowMessage('done');
end;

function TLightMang.checkWin: Boolean;
var
i: Integer;
begin
Result := False;
for i := 0 to FList.Count - 1 do
if not TLight(FList[i]).IsLightOn then Exit;
Result := True;
FGameOver := True;
end;

procedure TLightMang.NewGame;
var
i: Integer;
begin
Randomize;
for i := 0 to FList.Count - 1 do
TLight(FList[i]).IsLightOn := Odd(Random(2));
end;

end.

窗体

type
TfrmMain = class(TForm)
btn1: TButton;
btn2: TButton;
procedure btn1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure btn2Click(Sender: TObject);
private
{ Private declarations }
FLightMang: TLightMang;
FAppPath: string;
public
{ Public declarations }
end;

procedure TfrmMain.btn1Click(Sender: TObject);
begin
if FLightMang <> nil then FLightMang.Free;
FLightMang := TLightMang.Create(Self);
FLightMang.Parent := Self;
FLightMang.picLightOn := FAppPath + '1.jpg';
FLightMang.picLightOff := FAppPath + '0.jpg';
FLightMang.CreateLights(9, 9);
end;

procedure TfrmMain.FormCreate(Sender: TObject);
begin
FAppPath := ExtractFilePath(Application.ExeName);
end;

procedure TfrmMain.btn2Click(Sender: TObject);
begin
FLightMang.NewGame;
end;

PS.好像拼错了,management缩写好像习惯是mgmt

2006/8/31

win32help翻译(Atoms)

windows系统中,atomtable是系统定义的表,其中保存了strings和corresponding identifiers。程序将一个string放入atomtable,并返回一个atom(16位的integer),这个atom可以用来操作string。被放入atomtable的string称为atom name

DDE程序间使用atom table来共享item-name和topic-name,DDE程序间通过传递atoms而不是直接使用strings来传递strings

global atom table可以包含37个entries,对所有应用程序都是可以用的。当应用程序放置string在global atomtalbe中,系统就会创建一个atom,任何获得这个atom的程序都可以通过便利global atom table来获得string


应用程序可以定义自身的local atom table,其只能在程序内部使用。应用程序通过定义local atomtable来减少内存使用。例如:程序可以将一个string放置在local atomtable中,在其他地方使用atom访问,string在内存中只出现了一次,但却可以在多个地方来使用。
另外,程序可以通过使用local atom table来减少检索时间。程序通过将string放在atom table中获得atom,使用atom于相应的结构做比较。通常,atom的比较比string之间的比较来的更快。
默认状态下,local atom table包含37个元素,可以使用InitAtomTable重新分配空间,但需要在其他atom function调用之前分配。

程序中可以使用两种类型的atom,string atoms和integer atoms

string atoms:
string atom值范围在0xC000~0xFFFF
大小写不敏感,只能匹配字符串中的所有字符,不能进行子串匹配
长度限制为255。所有的atom function都具有此限制
每一个atom name都具有reference count(跟delphi字符串的引用计数一样),引用为零时删除。

integer atoms:
integer atoms值范围在0x0001~0xBFFF
代表integer atom的string表示格式为#dddd,前导零被忽略
不具有引用计数
一些Windows function的参数既接受string atom也接受integer atom,当传递integer atom时,必须使用MAKEINTATOM来创建。

应用程序通过使用AddAtom来创建local atom,使用GlobalAddAtom创建global atom
当程序不在使用atom的时候应该使用DeleteAtom来删除,对全局atom应使用GlobalDeleteAtom
string型全局atom只有在reference count为零时才会被删除,局部atom当应用程序退出后即被删除

可以通过FindAtom和GlobalFindAtom来检测string是否在table中,若在,返回atom
也可以使用GetAtomName和GlobalGetAtomName来返回atom-name string

应用FindAtom查询integer atom时,参数形式为#dddd

有关atom的应用示例,见dynamic data exchange

atoms应用的函数

AddAtom
DeleteAtom
FindAtom
GetAtomName
GlobalAddAtom
GlobalDeleteAtom
GlobalFindAtom
GlobalGetAtomName
InitAtomTable

win32help翻译(Handles and Objects)

不喜欢全中文的翻译,有些词到写代码的时候对不上号,保留了部分英文

object是系统内部定义的一种结构,它用来定义系统资源(如:文件,线程,图像等)。application不能直接操作object,必须通过handle来访问和修改系统资源。在Win32 API中,handle经常(但不总是)用直接指针来实现。

Windows使用object和handle主要有两个原因。第一,objcet保证开发人员不会编写代码对底层进行操作。这使得微软可以替换系统函数的实现,当新版本的Windows发布时,应用程序可以使用新的实现而只需做很少(或不需要)修改。
第二,使用object可以让开发人员使用Win32的安全机制。每一个object都有其自身的access-control list(ACL),每次程序试图创建object的handle时,系统都将检验object的ACL。有关更多信息,请参见
Security。

对大多数的object而言,Win32 API都提供了create the object,create the object handle, close the object handle, destroy theobject,但有些是重复和多余的。例如:程序可以创建一个eventobject,其他程序可以打开这个事件对象并且每一个都可以获得一个引用相同对象的唯一handle。程序不再使用对象时释放handle,当所有的打开的handle都被释放,操作系统会从内存中删除object。
相反,程序可以获得已存在于系统中的window-object handle。这种情况下,当应用程序不再使用window object时,应用程序需要负责释放object。
process结束时,系统自动关闭所有程序创建的handle并删除object。但是,thread结束时,系统并不关闭handle或释放object。例外情况是:window, hook, window position, dynamic data exchange(DDE)conversation objects,当创建他们的thread结束时,这些对象被释放。
handle和object会占用内存,因此,当不再使用时应关闭handle和释放object以释放内存。
Windows提供三种对象:user, graphics deviceinterface(GDI)和kernel。系统使用user对象以支持window管理,GDI对象支持图形图像,kernel对象支持内存管理、执行进程和interprocess communications(IPC)。

user object: Caret, Cursor, Dynamic data exchange conversation, Desktop, Hook, Icon, Menu, Window, Window position, Window station
GDI object: Bitmap, brush, font, palette,pen, extended pen, region, device context, memory device context,metafile, metafile device context, enhanced metafile, enhanced-metafiledevice context
Kernel object: process, thread, file, filemapping, event, semaphore, mutex, pipe, mailslot, communications device,heap, module, update resource, find file, event log, changenotification, token, service objcet, LZ file

一些对象(user和GDI对象),每时刻仅支持一个handle,当对象被创建时系统提供handle并在对象被销毁时释放。另外一些对象(例如一些kernel对象),支持多个handle,当所有的handle都被关闭时,object被释放。

user和GDI对象仅支持单一handle,process不能inherit或duplicate对user和GDI的handle

user objects的handle对所有进程来说是public的,所有的process都可以使用用户对象句柄。
GDI objects的handle对进程来说是private,只有创建GDI对象的进程可以使用对象句柄。

creator and destructor function list见Win32help

kernel对象句柄是独立于进程的,这意味着,必须在进程中创建内核对象或打开已有的内核对象以获得一个句柄。任何process都可以创建到已有kernel对象的句柄。

进程只可以创建或继承以下内核对象句柄:processes, threads, files, events, semaphores, mutexes, pipes, mailslots, communications devices

creator and destructor function list见Win32help

2006/8/29

内存访问学习笔记

HWND FindWindowA(LPCTSTR lpClassName, LPCTSTR lpWindowName);
function FindWindow(lpClassName: PAnsiChar; lpWindowName: PAnsiChar): HWND;
函数返回顶级窗口的handle,查询时不包含子窗体。失败返回NULL
lpClassName:指向NULL结尾字符串,为类名或atom,atom需要使用GlobalAddAtom添加,长度为16位,低位为指向lpClassName,高位为零。
atom不会用
lpWindowName:指向NULL结尾字符串,为窗体caption

ApplicationInfo = record //图方便声明个结构
hWindow: HWND;
processId: Cardinal;
threadId: Cardinal;
hProcess: Cardinal;
end;

procedure TForm1.btn1Click(Sender: TObject);
var
appInfo: ApplicationInfo;
begin
appInfo.hWindow := 0;
if rb1.Checked then appInfo.hWindow := FindWindow(PChar(edt1.Text), nil)
else if rb2.Checked then appInfo.hWindow := FindWindow(nil, PChar(edt1.Text));
if appInfo.hWindow = 0 then
begin
ShowMessage('not find');
Exit;
end;
SendMessage(appInfo.hWindow, WM_SETTEXT, 0, Integer(PChar('text')));
end;

获得hWnd之后,可以获得processId&threadId

DWORD GetWindowThreadProcessId(HWND hWnd, LPDWORD lpdwProcessId);
function GetWindowThreadProcessId(hWnd: HWND; lpdwProcessId: Pointer=nil): Cardinal;
函数返回创建窗口的threadId,这个东西怎么用?
hWnd:前面得到的hWindow
lpdwProcessId:函数返回创建窗口的processId,这里为保存processId变量的地址

appInfo.threadId := GetWindowThreadProcessId(appInfo.hWindow, @appInfo.processId);
if appInfo.threadId <> 0 then ShowMessage('got threadId && processId');

这里得到的processId即是Windows任务管理器中看到的PID,是系统用来标识不同进程的,不能用来对进程进行操作。要操作进程、向进程空间的地址读写,需要获得一个句柄(handle)。获得程序自身的PID可以用 DWORD GetCurrentProcessId(VOID)

HANDLE OpenProcess(DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwProcessId);
function OpenProcess(dwDesiredAccess: Cardinal; bInheritHandle: LongBool; dwProcessId: Cardinal): Cardinal;
函数返回进程对象的handle,失败返回NULL
dwDesiredAccess:访问权限,怕麻烦就用 PROCESS_ALL_ACCESS
bInheritHandle:如果为True,则当前进程所创建的进程也可以使用这个handle。有什么用?如何使用?
dwProcessId:要打开的processId
注意:使用完毕要用CloseHandle关闭

获得process的handle之后,就可以读写内存干坏事了
BOOL ReadProcessMemory(HANDLE hProcess, LPCVOID lpBaseAddress, LPVOID lpBuffer, DWORD nSize, LPDWORD lpNumberOfBytesRead);
BOOL WriteProcessMemory(HANDLE hProcess, LPVOID lpBaseAddress, LPVOID lpBuffer, DWORD nSize, LPDWORD lpNumberOfbytesWritten);
function
ReadProcessMemory(hProcess:Cardinal; lpBaseAddress: Pointer; lpBuffer: Pointer; nSize: Cardinal;lpNumberOfBytesRead: Cardinal): LoogBool;
function WriteProcessMemory(hProcess: Cardinal; lpBaseAddress: Pointer;lpBuffer: Pointer; nSize: Cardinal; lpNumberOfbytesWritten: Cardinal):LoogBool;
hProcess:没什么好说的,handle一个
lpBaseAddress:读写目标的起始地址
lpBuffer:读写用的缓存地址,读取时保存读出的数据,写入时保存将写入的数据
nSize:读写的字节数(byte)
lpNumberOfBytesRead|Written:实际读写的字节数
读取操作需要有PROCESS_VM_READ权限,写入操作需要具有PROCESS_VM_WRITE 和 PROCESS_VM_OPERATION 权限

var buffer: PByteArray;

appInfo.hProcess := OpenProcess(PROCESS_ALL_ACCESS, False, appInfo.processId);
GetMem(buffer, SizeOf(buffer));
ReadProcessMemory(appInfo.hProcess, Pointer($00D52270), buffer, 4, iCount); //关键是要知道数据的地址
buffer[0] := buffer[0] + 10;
WriteProcessMemory(appInfo.hProcess, Pointer($00D52270), buffer, 4, iCount);
CloseHandle(appInfo.hProcess);
FreeMem(buffer);

内存数据表往往只需要const array[...] of 类型 定义死就可以了

==============================

以上方法需要目标程序先运行,程序也可以主动运行目标程序,然后再读写数据

Bool CreateProcess(...)
函数的参数比较多而且大多可以使用默认值,只给出个常用结构,具体在Win32.hlp中查询
CreateProcess(appName, nil, nil, nil, False, NORMAL_PRIORITY_CLASS, nil, nil, sInfo, pInfo);
appName为要执行的程序名称(exe为例)
sInfo是一个STARTUPINFO类型的变量,用来初始化app,但其使用前也需要初始化,基本上也使用默认值,只需要设置其大小即可
ZeroMemory(@sInfo, SizeOf(sInfo));
sInfo.cb := SizeOf(sInfo);
pInfo是一个PROCESS_INFORMATION类型变量,执行后向其中填写数据
_PROCESS_INFORMATION = record
hProcess: THandle;
hThread: THandle;
dwProcessId: DWORD;
dwThreadId: DWORD;
end;
需要的东西里面就都有了

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
钩子函数
使用钩子函数[1]
Delphi中Hook技术全接触
用HOOK禁用鼠标与键盘点击
DLL
扫盲之Api Hook 细析
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服