TProcessEntry32和TThreadEntry32,高分200!!(200分)

  • 主题发起人 主题发起人 engleking
  • 开始时间 开始时间
E

engleking

Unregistered / Unconfirmed
GUEST, unregistred user!
用Thread32First取出的是一个Thread的ID号;用OpenPorcess可以将TProcessEntry32中的<br>ProcessID转化为Process的Handle,可是如何将ThreadID转化为Thread的Handle呢?
 
怎么了??没人回答?
 
从 "Win32 Programmer's Referenct" -&gt; "Thread Handles and Identifiers" 的说明中<br>C&amp;P 来的一段话:<br>The Win32 API *does not* provide a way to get the thread handle from the thread <br>identifier. If the handles were made available this way, the owning process <br>could fail because another process unexpectedly performed an operation on one <br>of its threads, such as suspending it, resuming it, adjusting its priority, or <br>terminating it. Instead, you must request the handle from the thread creator or<br>&nbsp;the thread itself. <br>好象没办法了 :(
 
请问拿到个THREAD HANDLE有什么用呢?我记得用到THREAD的地方都是调用THREAD ID而已,<br>有必要调用THREAD HANDLE吗?况且,ID也好HANDLE也罢,都只是为了唯一标识一个THREAD<br>而已(虽说两者的长度不同),所以有时我也不清楚为什么MS要给PROCESS来个ID又来个HANDLE,<br>莫非是为了兼容性?不清楚
 
能够拿到每个Thread的Handle用处多多。。
 
<br>to iamfly:<br>&nbsp; &nbsp;你没有编过用我的进程控制其他进程的线程的程序,当然不知道线程句柄<br>的好处了!!!<br><br>to engleking:<br>&nbsp; &nbsp;通过知己CreateProcess可以得到主线程的Handle,但是无论如何都得不到<br>其他线程的Handle的。死心吧,我也没有办法!!!<br>
 
在别的地方看到一种办法是利用系统范围的钩子,在钩子中取得可以获得其它线程的Handle,<br>再通过消息发给自己的程序。一种是利用 OpenProcess API 的 Undocumented 的功能,却没<br>说到底怎么使用。有谁知道?
 
unit HookInst;<br><br>interface<br><br>uses<br>&nbsp; Windows;<br><br>type<br><br>&nbsp; THookCall = packed record<br>&nbsp; &nbsp; Code &nbsp; : integer;<br>&nbsp; &nbsp; WParam : WPARAM;<br>&nbsp; &nbsp; LParam : LPARAM;<br>&nbsp; &nbsp; Result : LResult<br>&nbsp; end;<br><br>&nbsp; THookMethod = procedure (var HookCall: THookCall) of object;<br><br>function &nbsp;MakeHookInstance (Method: THookMethod): pointer;<br><br>procedure FreeHookInstance (ObjectInstance: pointer);<br><br>implementation<br><br>const<br><br>&nbsp; InstanceCount = 313; &nbsp;// set so that sizeof (TInstanceBlock) &lt; PageSize<br><br>type<br><br>&nbsp; PObjectInstance = ^TObjectInstance;<br><br>&nbsp; TObjectInstance = packed record<br>&nbsp; &nbsp; Code: Byte;<br>&nbsp; &nbsp; Offset: Integer;<br>&nbsp; &nbsp; case Integer of<br>&nbsp; &nbsp; &nbsp; 0: (Next: PObjectInstance);<br>&nbsp; &nbsp; &nbsp; 1: (Method: THookMethod);<br>&nbsp; end;<br><br>type<br><br>&nbsp; PInstanceBlock = ^TInstanceBlock;<br>&nbsp; TInstanceBlock = packed record<br>&nbsp; &nbsp; Next: PInstanceBlock;<br>&nbsp; &nbsp; Code: array[1..2] of Byte;<br>&nbsp; &nbsp; WndProcPtr: Pointer;<br>&nbsp; &nbsp; Instances: array[0..InstanceCount] of TObjectInstance;<br>&nbsp; end;<br><br>var<br><br>&nbsp; InstBlockList : PInstanceBlock &nbsp;= nil;<br>&nbsp; InstFreeList &nbsp;: PObjectInstance = nil;<br><br>function StdHookProc (Code, WParam: WPARAM; LParam:<br>&nbsp; LPARAM): LResult; stdcall; assembler;<br>asm<br>&nbsp; &nbsp; &nbsp; &nbsp; XOR &nbsp; &nbsp; EAX,EAX<br>&nbsp; &nbsp; &nbsp; &nbsp; PUSH &nbsp; &nbsp;EAX<br>&nbsp; &nbsp; &nbsp; &nbsp; PUSH &nbsp; &nbsp;LParam<br>&nbsp; &nbsp; &nbsp; &nbsp; PUSH &nbsp; &nbsp;WParam<br>&nbsp; &nbsp; &nbsp; &nbsp; PUSH &nbsp; &nbsp;Code<br>&nbsp; &nbsp; &nbsp; &nbsp; MOV &nbsp; &nbsp; EDX,ESP<br>&nbsp; &nbsp; &nbsp; &nbsp; MOV &nbsp; &nbsp; EAX,[ECX].Longint[4]<br>&nbsp; &nbsp; &nbsp; &nbsp; CALL &nbsp; &nbsp;[ECX].Pointer<br>&nbsp; &nbsp; &nbsp; &nbsp; ADD &nbsp; &nbsp; ESP,12<br>&nbsp; &nbsp; &nbsp; &nbsp; POP &nbsp; &nbsp; EAX<br>end;<br><br>{ Allocate a hook method instance }<br><br>function CalcJmpOffset(Src, Dest: Pointer): Longint;<br>begin<br>&nbsp; Result := Longint(Dest) - (Longint(Src) + 5);<br>end;<br><br>function MakeHookInstance(Method: THookMethod): Pointer;<br>const<br>&nbsp; BlockCode: array [1..2] of Byte = ($59, $E9);<br>&nbsp; PageSize = 4096;<br>var<br>&nbsp; Block: PInstanceBlock;<br>&nbsp; Instance: PObjectInstance;<br>begin<br>&nbsp; if InstFreeList = nil then<br>&nbsp; begin<br>&nbsp; &nbsp; Block := VirtualAlloc (nil, PageSize, MEM_COMMIT,<br>&nbsp; &nbsp; &nbsp; PAGE_EXECUTE_READWRITE);<br>&nbsp; &nbsp; Block^.Next := InstBlockList;<br>&nbsp; &nbsp; Move(BlockCode, Block^.Code, SizeOf(BlockCode));<br>&nbsp; &nbsp; Block^.WndProcPtr :=<br>&nbsp; &nbsp; &nbsp; Pointer(CalcJmpOffset(@Block^.Code[2], @StdHookProc));<br>&nbsp; &nbsp; Instance := @Block^.Instances;<br>&nbsp; &nbsp; repeat<br>&nbsp; &nbsp; &nbsp; Instance^.Code := $E8;<br>&nbsp; &nbsp; &nbsp; Instance^.Offset := CalcJmpOffset(Instance,<br>&nbsp; &nbsp; &nbsp; &nbsp; @Block^.Code);<br>&nbsp; &nbsp; &nbsp; Instance^.Next := InstFreeList;<br>&nbsp; &nbsp; &nbsp; InstFreeList := Instance;<br>&nbsp; &nbsp; &nbsp; Inc(Longint(Instance), SizeOf(TObjectInstance));<br>&nbsp; &nbsp; until Longint(Instance) - Longint(Block) &gt;=<br>&nbsp; &nbsp; &nbsp; SizeOf(TInstanceBlock);<br>&nbsp; &nbsp; InstBlockList := Block<br>&nbsp; end;<br>&nbsp; Result := InstFreeList;<br>&nbsp; Instance := InstFreeList;<br>&nbsp; InstFreeList := Instance^.Next;<br>&nbsp; Instance^.Method := Method<br>end;<br><br>{ Free a hook method instance }<br><br>procedure FreeHookInstance (ObjectInstance: Pointer);<br>begin<br>&nbsp; if ObjectInstance &lt;&gt; nil then<br>&nbsp; begin<br>&nbsp; &nbsp; PObjectInstance(ObjectInstance)^.Next := InstFreeList;<br>&nbsp; &nbsp; InstFreeList := ObjectInstance<br>&nbsp; end<br>end;<br><br>end.<br><br>修改一个通用函数入口地址;然后找调用这个函数的线程。。可是取出来的合实际的不一样呀。
 
to engleking:<br>&nbsp; 你从 UNDU 拷一段代码干吗?全局钩子函数应放在 Dll 中,再贴:<br>In WinME/2K there is a new avaiable API called OpenThread().<br>However there are two different solutions even if you do not have WinME/2K<br>... the first idea is based upon the documentation of GetCurrentThread()<br>function:<br><br>"The function cannot be used by one thread to create a handle that can be<br>used by other threads to refer to the first thread. The handle is always<br>interpreted as referring to the thread that is using it. A thread can create<br>a "real" handle of itself that can be used by other threads, or inherited by<br>other processes, by specifying the pseudohandle as the source handle in a<br>call to the DuplicateHandle function."<br><br>The idea is the following:<br><br>1 - You install an Hook into the interested Thread (you have its Thread ID)<br>2 - From the remote process you call the DuplicateHandle passing the<br>PseudoHandle retrieved by GetCurrentThread<br>3 - You "export" the real handle<br><br>The only problem is that if the interested Thread does not have a message<br>queue the Hook will never be installed and you will not be able to call the<br>DuplicateHandle ...<br><br>Source Code:<br><br>{钩子 DLL}<br>library hThreadFromTid;<br><br>{Copyright (c) by Carlo Bertuccini -- 2001}<br><br>uses<br>&nbsp; Dialogs,<br>&nbsp; SysUtils,<br>&nbsp; ClipBrd,<br>&nbsp; Windows;<br><br>{$R *.RES}<br><br>var<br>hHook : THandle;<br>OnlyOnce : Boolean = True;<br>WM_NOTIFICA : Cardinal;<br><br><br>Function HookProc(Code:Integer; WPar : Wparam; LPar :Lparam) : Integer;<br>Stdcall;<br>var hThread, hNewThread, hRemoteProcess : THandle;<br>&nbsp; &nbsp; PID : dWord;<br>Begin<br>&nbsp; If OnlyOnce Then begin<br>&nbsp; &nbsp; &nbsp; &nbsp;OnlyOnce := False;<br>&nbsp; &nbsp; &nbsp; &nbsp;ClipBoard.Clear;<br>&nbsp; &nbsp; &nbsp; &nbsp;WM_NOTIFICA:=RegisterWindowMessage('MyMessage');<br>&nbsp; &nbsp; &nbsp; &nbsp;hThread := GetCurrentThread();<br>&nbsp; &nbsp; &nbsp; &nbsp;GetWindowThreadProcessId(FindWindow('TForm1','TheFormText'),@PID);<br>&nbsp; &nbsp; &nbsp; &nbsp;hRemoteProcess:=OpenProcess(PROCESS_DUP_HANDLE,TRUE,PID);<br>&nbsp; &nbsp; &nbsp; &nbsp;if<br>DuplicateHandle(OpenProcess(PROCESS_DUP_HANDLE,True,GetCurrentProcessId),hTh<br>read,hRemoteProcess,@(hNewThread),0,True,DUPLICATE_SAME_ACCESS) &lt;&gt; False<br>then<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ClipBoard.SetTextBuf(PChar(IntToStr(hNewThread)))<br>&nbsp; &nbsp; &nbsp; &nbsp;else<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ClipBoard.SetTextBuf('Errore');<br>&nbsp; &nbsp; &nbsp; &nbsp;PostMessage(HWND_BROADCAST,WM_NOTIFICA,0,0);<br>&nbsp; end;<br>&nbsp; Result := CallNextHookEx(hHook,Code,WPar,LPar);<br>end;<br><br><br>Procedure Load (TID : dWord); stdcall;<br>Begin<br>&nbsp; &nbsp;hHook:=SetWindowsHookEx(WH_GETMESSAGE,@HookProc,hInstance,TID);<br>end;<br><br><br>Procedure Remove; stdcall;<br>Begin<br>&nbsp; &nbsp;UnHookWindowsHookEx(hHook);<br>end;<br><br>Exports<br>Load,Remove;<br><br><br>end.<br><br>Executable (set the Form caption to "TheFormText" ... is important)<br>{exe 主文件}<br>unit Unit1;<br><br>interface<br><br>uses<br>&nbsp; Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,<br>&nbsp; StdCtrls, ClipBrd;<br><br>type<br>&nbsp; TForm1 = class(TForm)<br>&nbsp; &nbsp; Button1: TButton;<br>&nbsp; &nbsp; Button2: TButton;<br>&nbsp; &nbsp; Edit1: TEdit;<br>&nbsp; &nbsp; procedure Button1Click(Sender: TObject);<br>&nbsp; &nbsp; procedure Button2Click(Sender: TObject);<br>&nbsp; &nbsp; procedure FormCreate(Sender: TObject);<br>&nbsp; private<br>&nbsp; &nbsp; { Private declarations }<br>&nbsp; public<br>&nbsp; &nbsp; &nbsp;Procedure MessageHandler (var MSG : TMSG; var Handled : boolean);<br>&nbsp; &nbsp; { Public declarations }<br>&nbsp; end;<br><br>Procedure Load (TID : dWord); stdcall; External 'hThreadFromTid.DLL';<br>Procedure Remove; stdcall; External 'hThreadFromTid.DLL';<br><br><br>var<br>&nbsp; Form1: TForm1;<br>&nbsp; WM_NOTIFICA : Cardinal;<br><br>implementation<br><br>{$R *.DFM}<br><br>Procedure TForm1.MessageHandler(var MSG : TMSG; var Handled : boolean);<br>Begin<br>&nbsp; if (Msg.message = WM_NOTIFICA) then begin<br>&nbsp; &nbsp; &nbsp;Edit1.Clear;<br>&nbsp; &nbsp; &nbsp;Edit1.text := 'Handle Reale: ' + ClipBoard.AsText;<br>&nbsp; end;<br>end;<br><br>procedure TForm1.Button1Click(Sender: TObject);<br>Var TID : dWord;<br>&nbsp; &nbsp; hExplorer : THandle;<br>begin<br>&nbsp; hExplorer:=FindWindow('Progman','Program Manager');<br>&nbsp; If hExplorer&lt;&gt;0 Then Begin<br>&nbsp; &nbsp; &nbsp;TID := GetWindowThreadProcessId(hExplorer,nil);<br>&nbsp; &nbsp; &nbsp;Load(TID);<br>&nbsp; &nbsp; &nbsp;PostMessage(hExplorer,WM_MOUSEMOVE,0,0);<br>&nbsp; end;<br>end;<br><br>procedure TForm1.Button2Click(Sender: TObject);<br>begin<br>&nbsp; Remove;<br>end;<br><br>procedure TForm1.FormCreate(Sender: TObject);<br>begin<br>&nbsp; WM_NOTIFICA:=RegisterWindowMessage('MyMessage');<br>&nbsp; Application.OnMessage := MessageHandler;<br>end;<br><br>end.<br><br>If this solution fails I have an undocumented solution: the OpenProcess()<br>API can become an "OpenThread()" ...
 
老兄:俺要的不是这个;你用FindWindow给俺一个特定的东东干吗?<br>
 
关键在于这里:<br>&nbsp; ...<br>&nbsp; TID := GetWindowThreadProcessId(hExplorer,nil);<br>&nbsp; //TID 是 hExplorer 窗口所属线程的 ID<br>&nbsp; Load(TID); //设置钩子,传入 TID <br>&nbsp; ...<br>在 &nbsp;MessageHandler 中就得到了 ID 为 TID 的线程的 Handle。<br>请注意,FindWindow 并不是关键的部分,只是获得 ThreadID 的一种方法,你完全可以通过<br>其它的途径获得 ThreadID。 &nbsp; &nbsp;
 
当然不行;继续朝下贴呀,下面的俺想看,怎么个变成OpenThread??
 
To:bbkxjy:<br>&nbsp; 如果要是要控制的主线程为 csrss,system Idle等;我想要HOOK回的消息应该为什么?如果是一般的,那样的消息会很多。思路好巧呀,俺被TMsg给迷惑了好久,没有走这条路。。
 
to:bbkxjy:<br>&nbsp; &nbsp; 要得到ToolAPI里所有的现成的句柄,俺还有路要走,望指教。。谢谢!
 
下面没啦!洋鬼子就说了这么多,我只是 Copy 过来罢了。第二种办法我也很想知道啊。
 
用发消息然后再用钩子广播回来的方法,只对于窗口类有效;别的好像就被window屏蔽掉了,<br>例如给systemIDle发一条消息,有如泥牛入海。。
 
<br>又学到一招了,谢谢bbkxjy大虾!!!<br>
 
难道没有人知道么??
 
&nbsp;lppe.dwSize := Sizeof(TProcessEntry32);<br>&nbsp; GetProcess := Process32First(hSnapShot, lppe);<br>&nbsp; while GetProcess do<br>&nbsp; begin<br>&nbsp; &nbsp; if WideString(Uppercase(lppe.szExeFile)) = (ExtractFileName(UpperCase(fileName))) then<br>&nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; hCurrentWindow := GetWindow(Handle, GW_HWNDFIRST);<br>&nbsp; &nbsp; &nbsp; while hCurrentWindow &lt;&gt; 0 do<br>&nbsp; &nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; &nbsp; GetWindowThreadProcessId(hCurrentWindow, Processid);<br>&nbsp; &nbsp; &nbsp; &nbsp; if processid = lppe.th32ProcessID then<br>&nbsp; &nbsp; &nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 做你想做的事就行了<br>&nbsp; &nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; &nbsp; &nbsp; hCurrentWindow := GetWindow(hCurrentWindow, GW_HWNDNEXT);<br>&nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; end;<br>&nbsp; &nbsp; GetProcess := process32Next(hSnapShot, lppe);<br>&nbsp; end;<br>我的这段是用来找一个指定的EXE 名称的HANDLE 并关闭它,或许你可以从中得到启发!<br>
 
接受答案了.
 

Similar threads

S
回复
0
查看
1K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
897
SUNSTONE的Delphi笔记
S
后退
顶部