mirror of
https://github.com/mirror/processhacker
synced 2026-06-08 16:03:24 +00:00
* fixed APC delegate
* more progress on native.html git-svn-id: svn://svn.code.sf.net/p/processhacker/code@1608 21ef857c-d57f-4fe0-8362-d861dc6d29cd
This commit is contained in:
@@ -1885,7 +1885,7 @@ namespace ProcessHacker.Native.Api
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
public static extern bool QueueUserAPC(
|
||||
[MarshalAs(UnmanagedType.FunctionPtr)]
|
||||
[In] Action<IntPtr> APC,
|
||||
[In] ApcRoutine APC,
|
||||
[In] IntPtr ThreadHandle,
|
||||
[In] IntPtr Data
|
||||
);
|
||||
|
||||
@@ -26,6 +26,7 @@ using System.Runtime.InteropServices;
|
||||
namespace ProcessHacker.Native.Api
|
||||
{
|
||||
public delegate void ApcCallbackDelegate(NtStatus ioStatus, IntPtr apcContext, IntPtr context);
|
||||
public delegate void ApcRoutine(IntPtr parameter);
|
||||
public delegate void TimerApcRoutine(IntPtr context, int lowValue, int highValue);
|
||||
public delegate void WaitOrTimerCallbackDelegate(IntPtr context, bool timeout);
|
||||
public delegate void WorkerCallbackDelegate(IntPtr context);
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
/*
|
||||
* Process Hacker -
|
||||
* heap memory allocation wrapper
|
||||
*
|
||||
* Copyright (C) 2008 wj32
|
||||
*
|
||||
* This file is part of Process Hacker.
|
||||
*
|
||||
* Process Hacker is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Process Hacker is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using ProcessHacker.Native.Api;
|
||||
|
||||
namespace ProcessHacker.Native
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a heap memory allocation.
|
||||
/// </summary>
|
||||
public sealed class HeapMemoryAlloc : MemoryAlloc
|
||||
{
|
||||
public HeapMemoryAlloc(int size)
|
||||
{
|
||||
this.Memory = Win32.HeapAlloc(Win32.GetProcessHeap(), 0, size);
|
||||
|
||||
if (this.Memory == IntPtr.Zero)
|
||||
throw new OutOfMemoryException();
|
||||
|
||||
base.Size = size;
|
||||
}
|
||||
|
||||
protected override void Free()
|
||||
{
|
||||
Win32.HeapFree(Win32.GetProcessHeap(), 0, this);
|
||||
}
|
||||
|
||||
public override void Resize(int newSize)
|
||||
{
|
||||
IntPtr newMemory;
|
||||
|
||||
newMemory = Win32.HeapReAlloc(Win32.GetProcessHeap(), 0, this, newSize);
|
||||
|
||||
if (newMemory == IntPtr.Zero)
|
||||
throw new OutOfMemoryException();
|
||||
|
||||
this.Memory = newMemory;
|
||||
base.Size = newSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -713,7 +713,7 @@ namespace ProcessHacker.Native.Objects
|
||||
Win32.ThrowLastError();
|
||||
}
|
||||
|
||||
public void QueueApc(Action<IntPtr> action, IntPtr parameter)
|
||||
public void QueueApc(ApcRoutine action, IntPtr parameter)
|
||||
{
|
||||
if (!Win32.QueueUserAPC(action, this, parameter))
|
||||
Win32.ThrowLastError();
|
||||
|
||||
+404
-8
@@ -26,11 +26,15 @@ p {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
h1 {
|
||||
border-top: solid 3px #000;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 20pt;
|
||||
margin-top: 1.3em;
|
||||
margin-bottom: 0.3em;
|
||||
border-top: dotted 3px #333;
|
||||
border-top: dashed 1px #333;
|
||||
}
|
||||
|
||||
h3 {
|
||||
@@ -45,10 +49,280 @@ h4 {
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1 style="font-size: 30pt;">The Definitive Native API Guide</h1>
|
||||
<h1 style="font-size: 30pt; border: none;">The Definitive Native API Guide</h1>
|
||||
<p>Written by wj32.</p>
|
||||
|
||||
<h1>Native API</h1>
|
||||
<h1>NT Concepts</h1>
|
||||
|
||||
<h3>ALPC Port</h3>
|
||||
<p>Local Inter-process Communication (LPC) ports are an interprocess communication (IPC) method.
|
||||
A server process creates a port object and waits for a client to connect to the port. Once
|
||||
the connection is established, both the client and server receive a handle to a communication
|
||||
port, a special instance of a port object which can be used to send and receive messages. From
|
||||
Windows Vista onward, LPC ports have been replaced with ALPC ports (<code>NtAlpc*</code>
|
||||
system calls). Existing port-related system calls now redirect to the new ALPC port functions.</p>
|
||||
<p>Related functions:
|
||||
<code>NtCreatePort</code> (server),
|
||||
<code>NtCreateWaitablePort</code> (server),
|
||||
<code>NtConnectPort</code> (client),
|
||||
<code>NtListenPort</code> (server),
|
||||
<code>NtAcceptConnectPort</code> (server),
|
||||
<code>NtRequestWaitReplyPort</code> (client),
|
||||
<code>NtReplyWaitReceivePort</code> (server),
|
||||
<code>NtReplyWaitReplyPort</code>,
|
||||
<code>NtReplyPort</code>.
|
||||
</p>
|
||||
<p>Related types:
|
||||
<code>PORT_MESSAGE</code>,
|
||||
<code>PORT_VIEW</code>,
|
||||
<code>REMOTE_PORT_VIEW</code>,
|
||||
<code>LPCP_PORT_OBJECT</code>.
|
||||
</p>
|
||||
|
||||
<h3>Asynchronous Procedure Calls (APCs)</h3>
|
||||
<p>Asynchronous procedure calls are functions which execute in the context of a specific thread.
|
||||
There are two types of APCs, user-mode and kernel-mode. Each thread has two APC queues, one for
|
||||
each type.</p>
|
||||
<p>User-mode APCs are queued using <code>NtQueueApcThread</code>. They will not be called
|
||||
unless an <em>alertable</em> wait is being performed or <code>NtTestAlert</code> is called in the
|
||||
target thread. In those cases, a flag will be set in the target thread's APC state indicating that
|
||||
one or more user-mode APCs are pending and the wait operation will be interrupted. When the system
|
||||
call returns to user-mode, any pending user-mode APCs will be called.</p>
|
||||
<p>A special use of user-mode APCs is thread termination, where a thread termination APC
|
||||
(<code>PspExitNormalApc</code>) is inserted into the target thread. <code>KiInsertQueueApc</code>
|
||||
contains a special case for thread termination and inserts the APC at the beginning of the
|
||||
user-mode APC queue so that any wait operations in the target thread are interrupted and
|
||||
the thread is terminated upon exiting the currently executing system service.</p>
|
||||
<p>Kernel-mode APCs always preempt user-mode code, including user-mode APCs. There are two types of
|
||||
kernel-mode APCs, normal and special. Normal APCs can be temporarily disabled by using
|
||||
<code>KeEnterCriticalRegion</code> and both types of APCs can be temporarily disabled by using
|
||||
<code>KeEnterGuardedRegion</code> or raising the IRQL to <code>APC_LEVEL</code> or higher.</p>
|
||||
<ul>
|
||||
<li>Normal kernel-mode APCs run at IRQL = <code>PASSIVE_LEVEL</code> and are inserted at the end
|
||||
of the kernel-mode APC queue.</li>
|
||||
<li>Special kernel-mode APCs run at IRQL = <code>APC_LEVEL</code> and are inserted after all existing
|
||||
special APCs in the kernel-mode APC queue.</li>
|
||||
</ul>
|
||||
<p>When a kernel-mode APC is inserted:</p>
|
||||
<ul>
|
||||
<li>If the target thread is running, a software interrupt is issued to call any queued kernel-mode
|
||||
APCs in the thread.</li>
|
||||
<li>If the target thread is waiting at IRQL = <code>PASSIVE_LEVEL</code> and special kernel-mode APCs
|
||||
are not disabled, the wait will be interrupted with <code>STATUS_KERNEL_APC</code>. Note that normal
|
||||
kernel-mode APCs cannot interrupt currently executing kernel-mode APCs which are waiting. Kernel-mode
|
||||
APCs do not cause wait operations to return; rather, the wait function will be interrupted,
|
||||
execute any queued kernel-mode APCs, and continue waiting.</li>
|
||||
</ul>
|
||||
<p>Normal kernel-mode APCs are used to implement thread suspension.</p>
|
||||
|
||||
<h3>Dispatcher Object</h3>
|
||||
<p>A dispatcher object is one which has two states: <em>signaled</em> and <em>non-signaled</em>.
|
||||
These objects can be used with standard wait functions such as <code>NtWaitForSingleObject</code> or
|
||||
<code>NtWaitForMultipleObjects</code>. These functions wait until one or more objects are set to
|
||||
a signaled state. The dispatcher objects are:</p>
|
||||
<ul>
|
||||
<li>Events</li>
|
||||
<li>Gates (kernel-mode only)</li>
|
||||
<li>Mutants</li>
|
||||
<li>Processes</li>
|
||||
<li>Queues (kernel-mode only)</li>
|
||||
<li>Semaphores</li>
|
||||
<li>Threads</li>
|
||||
<li>Timers</li>
|
||||
</ul>
|
||||
<p>Events and gates are the most basic dispatcher objects, consisting of only a dispatcher header.</p>
|
||||
<p>Note that the dispatcher header of a dispatcher object uses a signed integer field to represent
|
||||
its signal state. Signal state values greater than 0 are considered to be signaled, while 0 is
|
||||
considered to be non-signaled. This is useful for objects such as mutants and semaphores which can be
|
||||
acquired and released multiple times.</p>
|
||||
<p>Related types:
|
||||
<code>DISPATCHER_HEADER</code>.
|
||||
</p>
|
||||
|
||||
<h3>Event</h3>
|
||||
<p>An event is a synchronization object that can be explicitly set to the signaled state. There are two
|
||||
types of events:</p>
|
||||
<ul>
|
||||
<li><strong>Notification event.</strong> When a notification event is set, all waiting threads are
|
||||
released. The event remains signaled until it is explicitly reset.</li>
|
||||
<li><strong>Synchronization event.</strong> When a synchronization event is set, a single waiting
|
||||
thread is released and the event is reset to a non-signaled state. When multiple threads wait
|
||||
on a synchronization event, there is no guarantee of first-in first-out (FIFO) ordering.</li>
|
||||
</ul>
|
||||
<p>Related functions:
|
||||
<code>NtCreateEvent</code>,
|
||||
<code>NtOpenEvent</code>,
|
||||
<code>NtClearEvent</code>,
|
||||
<code>NtPulseEvent</code>,
|
||||
<code>NtQueryEvent</code>,
|
||||
<code>NtResetEvent</code>,
|
||||
<code>NtSetEvent</code>,
|
||||
<code>NtSetEventBoostPriority</code>.
|
||||
</p>
|
||||
<p>Related types:
|
||||
<code>EVENT_INFORMATION_CLASS</code>,
|
||||
<code>EVENT_BASIC_INFORMATION</code>,
|
||||
<code>KEVENT</code>.
|
||||
</p>
|
||||
|
||||
<h3>Event Pair</h3>
|
||||
<p>An event pair is a synchronization object containing two events, <em>high</em> and <em>low</em>. The
|
||||
system provides set, wait, and atomic signal-and-wait functions for event pairs. Note that an event pair
|
||||
object is not a dispatcher object and cannot be used with the standard wait functions.</p>
|
||||
<p>Related functions:
|
||||
<code>NtCreateEventPair</code>,
|
||||
<code>NtOpenEventPair</code>,
|
||||
<code>NtSetHighEventPair</code>,
|
||||
<code>NtSetHighWaitLowEventPair</code>,
|
||||
<code>NtSetLowEventPair</code>,
|
||||
<code>NtSetLowWaitHighEventPair</code>,
|
||||
<code>NtWaitHighEvenPair</code>,
|
||||
<code>NtWaitLowEventPair</code>.
|
||||
</p>
|
||||
<p>Related types:
|
||||
<code>EEVENT_PAIR</code>.
|
||||
</p>
|
||||
|
||||
<h3>Keyed Event</h3>
|
||||
<p>A keyed event is a dictionary of events. Each key must be even (the lowest bit must be clear). Internally,
|
||||
the keyed event object is implemented using a linked list of pointers to threads. Every thread object has
|
||||
two fields, <code>KeyedWaitValue</code> and <code>KeyedWaitSemaphore</code>. The <code>KeyedWaitValue</code>
|
||||
contains the key being waited for by the thread. When a thread attempts to release a key which is not being
|
||||
waited for, its <code>KeyedWaitValue</code> will be set to the key OR'ed with 1, to indicate that the thread
|
||||
is attempting to release the key, and the thread will wait until another thread waits for the key.</p>
|
||||
<p>Related functions:
|
||||
<code>NtCreateKeyedEvent</code>,
|
||||
<code>NtOpenKeyedEvent</code>,
|
||||
<code>NtReleaseKeyedEvent</code>,
|
||||
<code>NtWaitForKeyedEvent</code>.
|
||||
</p>
|
||||
<p>Related types:
|
||||
<code>KEYED_EVENT_OBJECT</code>.
|
||||
</p>
|
||||
|
||||
<h3>Mutant</h3>
|
||||
<p>A "mutant" is a standard mutex. When a thread successfully waits for a mutant, it will acquire the mutant
|
||||
and become the owner of the mutant; the mutant will be set to a non-signaled state. When the owning thread
|
||||
releases the mutant the same number of times it has acquired it, the mutant will be set to a signaled state
|
||||
and the mutant will no longer be owned, allowing other threads to acquire the mutant. Note that the mutant
|
||||
can be acquired recursively, i.e. the owning thread can acquire the mutant more than once without causing a
|
||||
deadlock.</p>
|
||||
<p>Related functions:
|
||||
<code>NtCreateMutant</code>,
|
||||
<code>NtOpenMutant</code>,
|
||||
<code>NtQueryMutant</code>,
|
||||
<code>NtReleaseMutant</code>
|
||||
</p>
|
||||
<p>Related types:
|
||||
<code>MUTANT_INFORMATION_CLASS</code>,
|
||||
<code>MUTANT_BASIC_INFORMATION</code>,
|
||||
<code>KMUTANT</code>.
|
||||
</p>
|
||||
|
||||
<h3>Port</h3>
|
||||
<p>See <strong>ALPC Port</strong>.</p>
|
||||
|
||||
<h3>Profile</h3>
|
||||
<p>A profile object can be used for performance monitoring. When certain profiling events are triggered,
|
||||
a corresponding counter in a user-allocated buffer is incremented.</p>
|
||||
<p>Related functions:
|
||||
<code>NtCreateProfile</code>,
|
||||
<code>NtQueryIntervalProfile</code>,
|
||||
<code>NtSetIntervalProfile</code>,
|
||||
<code>NtStartProfile</code>,
|
||||
<code>NtStopProfile</code>.
|
||||
</p>
|
||||
|
||||
<h3>Section</h3>
|
||||
<p>Sections are objects describing a region of memory "backed" by a file. There are two types of section
|
||||
objects:</p>
|
||||
<ul>
|
||||
<li><strong>File-backed section.</strong> File-backed sections are memory-mapped files, where mapped
|
||||
view contents are the same as in the file. Writing to mapped views will also change the contents of the
|
||||
the file, unless the section is mapped copy-on-write, where any changes are discarded after the last
|
||||
view is unmapped and the last reference to the section is closed.</li>
|
||||
<li><strong>Pagefile-backed section.</strong> Page-file-backed sections are a form of shared memory;
|
||||
any changes will be discarded after the section is freed. The section is not backed by any
|
||||
user-specified file.</li>
|
||||
</ul>
|
||||
<p>Multiple views of the section can be mapped, and changes will be reflected across processes.</p>
|
||||
<p>Related functions:
|
||||
<code>NtCreateSection</code>,
|
||||
<code>NtOpenSection</code>,
|
||||
<code>NtAreMappedFilesTheSame</code>,
|
||||
<code>NtExtendSection</code>,
|
||||
<code>NtMapViewOfSection</code>,
|
||||
<code>NtQuerySection</code>,
|
||||
<code>NtUnmapViewOfSection</code>.
|
||||
</p>
|
||||
|
||||
<h3>Semaphore</h3>
|
||||
<p>A semaphore is a synchronization object with a signal state that represents how many times it has been
|
||||
acquired. Each time a semaphore is acquired, its signal state is decremented. Each time a semaphore is
|
||||
released, its signal state is incremented (but cannot be greater than the limit). If a semaphore's
|
||||
signal state is 0 (non-signaled), threads must wait until another thread releases the semaphore before they
|
||||
can acquire the semaphore.</p>
|
||||
<p>Related functions:
|
||||
<code>NtCreateSemaphore</code>,
|
||||
<code>NtOpenSemaphore</code>,
|
||||
<code>NtQuerySemaphore</code>,
|
||||
<code>NtReleaseSemaphore</code>.
|
||||
</p>
|
||||
<p>Related types:
|
||||
<code>SEMAPHORE_INFORMATION_CLASS</code>,
|
||||
<code>SEMAPHORE_BASIC_INFORMATION</code>,
|
||||
<code>KSEMAPHORE</code>.
|
||||
</p>
|
||||
|
||||
<h3>Timer</h3>
|
||||
<p>A timer is executive object and a wrapper around the kernel timer object. There are two types of timers:</p>
|
||||
<ul>
|
||||
<li><strong>Notification timer.</strong> When a notification timer is signaled, all waiting threads are
|
||||
released. The timer remains signaled until explicitly reset.</li>
|
||||
<li><strong>Synchronization timer.</strong> When a synchronization timer is signaled, one waiting thread is
|
||||
released and the timer is set to a non-signaled state.</li>
|
||||
</ul>
|
||||
<p>A timer can be configured to be signaled periodically or to insert an APC into the thread that set the
|
||||
timer when the timer is signaled.</p>
|
||||
<p>Related functions:
|
||||
<code>NtCreateTimer</code>,
|
||||
<code>NtOpenTimer</code>,
|
||||
<code>NtCancelTimer</code>,
|
||||
<code>NtQueryTimer</code>,
|
||||
<code>NtSetTimer</code>.
|
||||
</p>
|
||||
<p>Related types:
|
||||
<code>TIMER_INFORMATION_CLASS</code>,
|
||||
<code>TIMER_BASIC_INFORMATION</code>,
|
||||
<code>ETIMER</code>,
|
||||
<code>KTIMER</code>,
|
||||
<code>PTIMER_APC_ROUTINE</code>.
|
||||
</p>
|
||||
|
||||
<h3>Wait</h3>
|
||||
<p>A thread can wait for one or more objects; the standard system calls are <code>NtWaitForSingleObject</code>,
|
||||
<code>NtWaitForMultipleObjects</code>, <code>NtSignalAndWaitForSingleObject</code>, and a few type-specific
|
||||
wait functions. The pointer-based kernel-mode functions are <code>KeWaitForSingleObject</code> and
|
||||
<code>KeWaitForMultipleObjects</code>. These functions will block until a certain condition is met. For
|
||||
example, <code>*WaitForSingleObject</code> will return when the specified object is signaled.
|
||||
<code>*WaitForMultipleObjects</code> will return when all/any specified objects are signaled.</p>
|
||||
<p>When a wait function is called, it initializes a wait block for each object to be waited for. The storage
|
||||
for the wait blocks is supplied in the thread object by default, but the caller can allocate storage if
|
||||
they wish. The wait function then checks if the wait can be satisfied immediately. If it could not, the
|
||||
wait function inserts the wait block(s) into the dispatch header(s) of the object(s), sets the thread's state
|
||||
to Waiting and will no longer be considered for execution. It then switches to another ready thread.</p>
|
||||
<p>When an object is set to a signaled state (such as when an event is set or a mutant is released),
|
||||
the function performs a <em>wait test</em> (<code>KiWaitTest</code>) which enumerates the wait blocks in the
|
||||
object's dispatcher header and unwaits each waiting thread. Each waiting thread will now be ready to run.</p>
|
||||
<p>A waiting thread regains control due to either a wait test or a kernel-mode APC. It proceeds to
|
||||
call any queued kernel-mode APCs and check if the wait operation has been satisfied (for multiple-object
|
||||
waits, this is when any/all objects have been signaled). If it has not, the wait function continues to repeat
|
||||
the wait process until the wait operation has been satisfied.</p>
|
||||
<p>For some object types, object state must be modified when a thread is finished waiting for the object.
|
||||
For example, a semaphore's signal state must be decremented. These operations are called <em>side-effects</em>,
|
||||
and are performed when a wait is satisfied.</p>
|
||||
|
||||
<h1>NT Enumerations</h1>
|
||||
|
||||
<h2>Debug Object Access</h2>
|
||||
<pre>
|
||||
@@ -56,8 +330,8 @@ h4 {
|
||||
#define DEBUG_PROCESS_ASSIGN 0x0002
|
||||
#define DEBUG_SET_INFORMATION 0x0004
|
||||
#define DEBUG_QUERY_INFORMATION 0x0008
|
||||
#define DEBUG_ALL_ACCESS STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | DEBUG_READ_EVENT |
|
||||
DEBUG_PROCESS_ASSIGN | DEBUG_SET_INFORMATION | DEBUG_QUERY_INFORMATION</pre>
|
||||
#define DEBUG_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | DEBUG_READ_EVENT | \
|
||||
DEBUG_PROCESS_ASSIGN | DEBUG_SET_INFORMATION | DEBUG_QUERY_INFORMATION)</pre>
|
||||
|
||||
<h2>Directory Object Access</h2>
|
||||
<pre>
|
||||
@@ -68,6 +342,99 @@ h4 {
|
||||
|
||||
#define DIRECTORY_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | 0xf)</pre>
|
||||
|
||||
<h2>Event Access</h2>
|
||||
<pre>
|
||||
#define EVENT_QUERY_STATE 0x0001
|
||||
#define EVENT_MODIFY_STATE 0x0002
|
||||
#define EVENT_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x3)</pre>
|
||||
|
||||
<h2>Event Pair Access</h2>
|
||||
<pre>
|
||||
#define EVENT_PAIR_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE)</pre>
|
||||
|
||||
<h2>Keyed Event Access</h2>
|
||||
<pre>
|
||||
#define KEYEDEVENT_WAIT 0x0001
|
||||
#define KEYEDEVENT_WAKE 0x0002
|
||||
#define KEYEDEVENT_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | KEYEDEVENT_WAIT | KEYEDEVENT_WAKE)</pre>
|
||||
|
||||
<h2>Mutant Access</h2>
|
||||
<pre>
|
||||
#define MUTANT_QUERY_STATE 0x0001
|
||||
|
||||
#define MUTANT_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE| MUTANT_QUERY_STATE)</pre>
|
||||
|
||||
<h2>Object Flags</h2>
|
||||
<pre>
|
||||
#define OBJ_INHERIT 0x00000002L
|
||||
#define OBJ_PERMANENT 0x00000010L
|
||||
#define OBJ_EXCLUSIVE 0x00000020L
|
||||
#define OBJ_CASE_INSENSITIVE 0x00000040L
|
||||
#define OBJ_OPENIF 0x00000080L
|
||||
#define OBJ_OPENLINK 0x00000100L
|
||||
#define OBJ_KERNEL_HANDLE 0x00000200L
|
||||
#define OBJ_FORCE_ACCESS_CHECK 0x00000400L
|
||||
#define OBJ_VALID_ATTRIBUTES 0x000007f2L</pre>
|
||||
<h3>Members</h3>
|
||||
<h4>OBJ_INHERIT</h4>
|
||||
<p>Specifies that the handle (in the appropriate context) should be inherited by child processes.</p>
|
||||
<h4>OBJ_PERMANENT</h4>
|
||||
<p>Specifies that the object is permanent and should not be freed when all references to it have been
|
||||
closed. If this flag is not specified, the object is temporary and will be freed when all references
|
||||
have been closed. User-mode callers must have <code>SeCreatePermanentPrivilege</code> in order to
|
||||
create permanent objects.</p>
|
||||
<h4>OBJ_EXCLUSIVE</h4>
|
||||
<p>Specifies that the object should be opened for exclusive access; the object cannot be opened
|
||||
again until the handle is closed.</p>
|
||||
<h4>OBJ_CASE_INSENSITIVE</h4>
|
||||
<p>Specifies that name comparisons should be made case insensitively.</p>
|
||||
<h4>OBJ_OPENIF</h4>
|
||||
<p>Specifies that if an object with the specified name already exists, the creation routine should
|
||||
open the existing object. If this flag is not specified and the name already exists, the creation
|
||||
routine will return <code>STATUS_OBJECT_NAME_COLLISION</code>.</p>
|
||||
<h4>OBJ_OPENLINK</h4>
|
||||
<p>Not used.</p>
|
||||
<h4>OBJ_KERNEL_HANDLE</h4>
|
||||
<p>Specifies that the handle should be opened in the context of the System process, i.e. a kernel
|
||||
handle.</p>
|
||||
<h4>OBJ_FORCE_ACCESS_CHECK</h4>
|
||||
<p>Specifies that an access check should be performed, even if the caller is from kernel-mode.</p>
|
||||
|
||||
<h2>Profile Access</h2>
|
||||
<pre>
|
||||
#define PROFILE_CONTROL 0x0001
|
||||
#define PROFILE_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | PROFILE_CONTROL)</pre>
|
||||
|
||||
<h2>Section Access</h2>
|
||||
<pre>
|
||||
#define SECTION_QUERY 0x0001
|
||||
#define SECTION_MAP_WRITE 0x0002
|
||||
#define SECTION_MAP_READ 0x0004
|
||||
#define SECTION_MAP_EXECUTE 0x0008
|
||||
#define SECTION_EXTEND_SIZE 0x0010
|
||||
#define SECTION_MAP_EXECUTE_EXPLICIT 0x0020
|
||||
|
||||
#define SECTION_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | \
|
||||
SECTION_MAP_WRITE | SECTION_MAP_READ | SECTION_MAP_EXECUTE | \
|
||||
SECTION_EXTEND_SIZE)</pre>
|
||||
|
||||
<h2>Semaphore Access</h2>
|
||||
<pre>
|
||||
#define SEMAPHORE_QUERY_STATE 0x0001
|
||||
#define SEMAPHORE_MODIFY_STATE 0x0002
|
||||
|
||||
#define SEMAPHORE_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x3)</pre>
|
||||
|
||||
<h2>Timer Access</h2>
|
||||
<pre>
|
||||
#define TIMER_QUERY_STATE 0x0001
|
||||
#define TIMER_MODIFY_STATE 0x0002
|
||||
|
||||
#define TIMER_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | \
|
||||
TIMER_QUERY_STATE | TIMER_MODIFY_STATE)</pre>
|
||||
|
||||
<h1>NT Structures</h1>
|
||||
|
||||
<h2>CLIENT_ID</h2>
|
||||
<p>A structure identifying a process or thread.</p>
|
||||
<pre>
|
||||
@@ -128,6 +495,33 @@ typedef struct _INITIAL_TEB
|
||||
<a href="http://www.reactos.org/serendipity/index.php?/archives/15-They-lied-to-you-about-INITIAL_TEB!.html">this blog post</a>
|
||||
for more details.</p>
|
||||
|
||||
<h2>OBJECT_ATTRIBUTES</h2>
|
||||
<p>A structure describing object properties such as its name, location and security attributes.</p>
|
||||
<pre>
|
||||
typedef struct _OBJECT_ATTRIBUTES
|
||||
{
|
||||
ULONG Length;
|
||||
HANDLE RootDirectory;
|
||||
PUNICODE_STRING ObjectName;
|
||||
ULONG Attributes;
|
||||
PVOID SecurityDescriptor; // PSECURITY_DESCRIPTOR
|
||||
PVOID SecurityQualityOfService; // PSECURITY_QUALITY_OF_SERVICE
|
||||
} OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES;</pre>
|
||||
<h3>Fields</h3>
|
||||
<h4>Length</h4>
|
||||
<p>The length of the <code>OBJECT_ATTRIBUTES</code> structure; 24 on 32-bit systems and 40 on 64-bit systems.</p>
|
||||
<h4>RootDirectory</h4>
|
||||
<p>A handle to a directory object from which to begin searching for the object. If this value is <code>NULL</code>,
|
||||
the object manager will use the default root directory.</p>
|
||||
<h4>ObjectName</h4>
|
||||
<p>The name of the object, optional when creating most types of objects.</p>
|
||||
<h4>Attributes</h4>
|
||||
<p>See <strong>Object Flags</strong>.</p>
|
||||
<h4>SecurityDescriptor</h4>
|
||||
<p>A pointer to a <code>SECURITY_DESCRIPTOR</code> structure for the object.</p>
|
||||
<h4>SecurityQualityOfService</h4>
|
||||
<p>A pointer to a <code>SECURITY_QUALITY_OF_SERVICE</code> structure for the object.</p>
|
||||
|
||||
<h2>RTL_DRIVE_LETTER_CURDIR</h2>
|
||||
<p>Unknown.</p>
|
||||
<pre>
|
||||
@@ -228,6 +622,8 @@ typedef struct _UNICODE_STRING
|
||||
<h4>Buffer</h4>
|
||||
<p>A buffer containing the string.</p>
|
||||
|
||||
<h1>NT System Calls</h1>
|
||||
|
||||
<h2>NtAlertThread</h2>
|
||||
<p>Alerts the specified thread, causing it to resume execution if it is in an alertable Wait state.
|
||||
Otherwise, the thread is set to an alerted state.</p>
|
||||
@@ -503,7 +899,7 @@ NtCreateThreadEx(
|
||||
__in_opt ULONG Reserved,
|
||||
__in_opt ULONG StackCommit,
|
||||
__in_opt ULONG StackReserve,
|
||||
__in_opt PVOID Unknown
|
||||
__in_opt PVOID ProcessContext
|
||||
);</pre>
|
||||
<h3>Arguments</h3>
|
||||
<h4>ThreadHandle</h4>
|
||||
@@ -529,7 +925,7 @@ NtCreateThreadEx(
|
||||
<p>The number of bytes to commit in the thread stack.</p>
|
||||
<h4>StackReserve</h4>
|
||||
<p>The number of bytes to reserve for the thread stack.</p>
|
||||
<h4>Unknown</h4>
|
||||
<h4>ProcessContext</h4>
|
||||
<p>An optional structure which is passed to <code>PspBuildCreateProcessContext</code>.</p>
|
||||
<h3>Code paths</h4>
|
||||
<p><code>NtCreateThreadEx</code> ... <code>PspCreateThread</code> ... <code>PspAllocateThread</code> ...
|
||||
@@ -572,7 +968,7 @@ NtOpenProcess(
|
||||
|
||||
<h2>NtQueueApcThread</h2>
|
||||
<p>Queues a user-mode APC to the specified thread. The APC will execute when the thread performs an alertable wait or
|
||||
calls <code>NtTestAlert</code>.</p>
|
||||
calls <code>NtTestAlert</code>. Any wait operations will return with <code>STATUS_USER_APC</code>.</p>
|
||||
<pre>
|
||||
NTSYSCALLAPI
|
||||
NTSTATUS
|
||||
|
||||
Reference in New Issue
Block a user