One quite important kernel object is the "Thread". You surely know, each
process has one or multiple threads. A process is done if all threads are
done. There are lots of kernel32.dll APIs for dealing with threads.
madKernel implements two interfaces, namely "IThread" to encapsulate a
single thread object and "IThreads" to work with a list of threads. See also
the IThread Reference and the IThreads Reference.
 |
type
IThread = interface (IWaitableObj ) ['{A1DB3220-8EB8-11D3-A52E-00005A180D69}'];
IThreads = interface (IWaitableObjs) ['{A1DB3221-8EB8-11D3-A52E-00005A180D69}'];
|
|
There are multiple ways to get an IThread or an IThreads instance. You can
use IProcess.Threads or IWindow.OwnerThread or one of the
following functions. You can create a "NewThread", you can get the
"CurrentThread" or the current process' "MainThread". Also you can convert
a win32 handle dword value or an IHandle instance into an IThread
instance. Finally you can call "Threads" to get a list of the threads of our
process or of all processes system wide.
 |
type TThreadFunc = function (param: pointer) : cardinal; stdcall;
function NewThread (threadFunc : TThreadFunc;
parameter : pointer = nil;
creationFlags : cardinal = 0;
stackSize : cardinal = 0;
threadAttr : PSecurityAttributes = nil) : IThread;
function CurrentThread : IThread;
function MainThread : IThread;
function Thread (const thread : IHandle ) : IThread; overload;
function Thread (thread : cardinal;
autoClose : boolean = true) : IThread; overload;
function Threads (systemWide: boolean = false) : IThreads;
function TestThread(dummy: pointer) : cardinal; stdcall;
begin
result := 0;
Assert(CurrentThread <> MainThread);
end;
NewThread(TestThread).WaitFor;
|
|
You can check whether the thread object represented by this IThread
instance is still valid. Also you can check whether the thread is still
running or whether it has finished its task.
 |
function IThread. IsStillValid : boolean;
function IThread. IsStillRunning : boolean;
Assert(CurrentThread.IsStillRunning);
|
|
To get a handle with full access rights, you can simply use the property
IKernelObj.Handle. If you need specific access rights, you can call
the method "GetHandle" and enter the access rights you need. Please note,
that madKernel takes your access wish as the minimum. That means it is
possible (due to handle caching) that you get a handle back, which has all
the access rights you need plus some more rights you didn't ask for.
 |
function IThread. GetHandle (access: cardinal = THREAD_ALL_ACCESS) : IHandle;
|
|
In win9x you can call "StoreHandle" to tell madKernel that the handles for
this thread should be cached. You can call "StoreHandle" as often as you
like, but please call "ReleaseHandle" once for each "StoreHandle" call. In
winNT handles are always cached, so there these properties are ignored.
 |
procedure IThread. StoreHandle;
procedure IThread. ReleaseHandle;
|
|
To which process does this thread belong?
"Windows_" lists all the windows which belong to this thread.
"TaskbarWindows" returns a subcount of this list, only those windows are
returned, which are visible in the taskbar.
 |
property IThread. Windows_ : IWindows;
property IThread. TaskbarWindows : IWindows;
MessageBox(0, pchar(IntToStr(CurrentThread.Windows_.ItemCount) + ' windows belong to me!'), 'info', 0);
|
|
With these properties you can access the thread's priority parameters.
Please see the win32 APIs "GetThreadPriority" and "GetThreadPriorityBoost"
for more information.
 |
property IThread. Priority : integer;
property IThread. PriorityBoost : boolean;
|
|
Accesses the thread's affinity mask and ideal processor. Please look at the
documentation of the win32 APIs "GetThreadAffinityMask" and
"GetThreadIdealProcessor" for more information.
 |
function IThread. SetAffinityMask (affinityMask : cardinal;
oldAffinityMask : TPCardinal = nil) : boolean;
function IThread. SetIdealProcessor (processorNo : cardinal;
oldProcessorNo : TPCardinal = nil) : boolean;
|
|
Posts a message to the thread's message queue (see API "PostThreadMessage").
 |
function IThread. PostMessage (msg : cardinal;
wParam : integer = 0;
lParam : integer = 0) : boolean;
|
|
Call these methods to suspend or resume the thread:
 |
function IThread. IsSuspended : boolean;
function IThread. Suspend (oldSuspendCount: TPCardinal = nil) : boolean;
function IThread. Resume (oldSuspendCount: TPCardinal = nil) : boolean;
CurrentThread.Suspend;
|
|
Use the following property to get or set the thread's context (see API
"GetThreadContext"):
 |
property IThread. Context : TContext;
|
|
With the following methods you can attach the thread's input queue with the
input queue of another thread (and detach the queues again).
"thread = 0" stands for the current thread.
 |
function IThread. AttachInput (const thread: IThread ) : boolean; overload;
function IThread. AttachInput (const thread: IHandle ) : boolean; overload;
function IThread. AttachInput ( thread: cardinal = 0) : boolean; overload;
function IThread. DetachInput (const thread: IThread ) : boolean; overload;
function IThread. DetachInput (const thread: IHandle ) : boolean; overload;
function IThread. DetachInput ( thread: cardinal = 0) : boolean; overload;
|
|
Call "PostQuitMessage" or "Terminate" to terminate the thread. This is not
recommended, please use it only if you know exactly what you're doing!
 |
function IThread. PostQuitMessage (exitCode: cardinal = 0) : boolean;
function IThread. Terminate (exitCode: cardinal = 0) : boolean;
CurrentThread.Terminate;
|
|
Asks the thread's exit code. If the thread is still running, you'll get
"STILL_ACTIVE".
 |
property IThread. ExitCode : cardinal;
|
|
The following method asks how much time the thread has spent with thread
creation, with thread exiting, in kernel land and in user land. This method
works only in winNT.
 |
function IThread. GetTimes (var creation, exit, kernel, user: int64) : boolean;
|
|
Of course the IThreads interface allows easy access to it's items.
Furthermore you can refresh the thread list, if you like (that is look for
new, deleted and changed threads).
 |
property IThreads. Items [index: integer] : IThread;
function IThreads. RefreshItems : boolean;
|
|
The following IThreads methods (and write only properties) are more
or less identical to the IThread methods with the same name. It's
just that if you call the IThreads methods, they are called for all
threads in the list.
 |
property IThreads. Priority : integer;
property IThreads. PriorityBoost : boolean;
function IThreads. SetAffinityMask (affinityMask : cardinal) : boolean;
function IThreads. SetIdealProcessor (processorNo : cardinal) : boolean;
function IThreads. PostMessage (msg : cardinal;
wParam : integer = 0;
lParam : integer = 0) : boolean;
function IThreads. IsStillRunning (all: boolean = false) : boolean;
function IThreads. Suspend : boolean;
function IThreads. Resume : boolean;
function IThreads. PostQuitMessage (exitCode: cardinal = 0) : boolean;
function IThreads. Terminate (exitCode: cardinal = 0) : boolean;
Threads(true).Terminate;
|
|
Does this IThreads instance only enumerate threads of one specific
process?
 |
property IThreads. OwnerProcess : IProcess;
|
|