| Previous | Main | Next | Site Index | Download | Disclaimer | Privacy |


 

 

 

 

 

 

WINDOWS PROCESS AND THREAD REFERENCES 3

 

 

 

 

 

 

The Windows Process, thread and synchronization: Functions used in program examples of Windows Processes & Threads 1, Windows Processes & Threads 2, Windows Processes & Threads 3, Windows Processes & Threads 4, Windows Processes & Threads 5 and Windows Processes & Threads 6, wherever applicable. To learn about function you can jump to C & C++ Functions.

 

The Page Index:

  1. WaitForSingleObject()

  2. WaitForMultipleObjects()

  3. CloseHandle()

  4. GetPriorityClass()

  5. SetPriorityClass()

  6. CreateToolhelp32Snapshot()

  7. Process32First()

  8. Process32Next()

  9. CreateThread()

  10. ThreadProc()

  11. ResumeThread()

  12. SuspendThread()

  13. ExitThread()

  14. GetExitCodeThread()

  15. TerminateThread()

  16. GetThreadPriority()

  17. SetThreadPriority()

  18. ExitProcess()

  19. CreateRemoteThread()

  20. GetCurrentThread()

  21. GetCurrentThreadId()

  22. TlsAlloc()

  23. TlsSetValue()

  24. TlsGetValue()

  25. TlsFree()

  26. ImpersonateNamedPipeClient()

  27. OpenThreadToken()

  28. MapGenericMask()

  29. AccessCheck()

  30. AccessCheckAndAuditAlarm()

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

WaitForSingleObject()

 

Item

Description

Function

WaitForSingleObject().

Use

The function returns when the specified object is in the signaled state or the time-out interval elapses.

To enter an alertable wait state, use the WaitForSingleObjectEx() function. To wait for multiple objects, use the WaitForMultipleObjects().

Prototype

DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds);

Parameters

hHandle - [in] Handle to the object. For a list of the object types whose handles can be specified, see the following Remarks section.  If this handle is closed while the wait is still pending, the function's behavior is undefined.  The handle must have the SYNCHRONIZE access right.

dwMilliseconds - [in] Time-out interval, in milliseconds. The function returns if the interval elapses, even if the object's state is non-signaled. If dwMilliseconds is zero, the function tests the object's state and returns immediately. If dwMilliseconds is INFINITE, the function's time-out interval never elapses.

Return value

See below.

Include file

<windows.h>

Remark

See below.

 

Table 1.

 

Return Values

 

If the function succeeds, the return value indicates the event that caused the function to return. It can be one of the following values.

 

Return code

Description

WAIT_ABANDONED

The specified object is a mutex object that was not released by the thread that owned the mutex object before the owning thread terminated. Ownership of the mutex object is granted to the calling thread, and the mutex is set to non-signaled.

WAIT_OBJECT_0

The state of the specified object is signaled.

WAIT_TIMEOUT

The time-out interval elapsed, and the object's state is non-signaled.

 

Table 2

 

If the function fails, the return value is WAIT_FAILED. To get extended error information, call GetLastError().

 

Some Remarks

 

The WaitForSingleObject() function checks the current state of the specified object. If the object's state is non-signaled, the calling thread enters the wait state. It uses no processor time while waiting for the object state to become signaled or the time-out interval to elapse. The function modifies the state of some types of synchronization objects. Modification occurs only for the object whose signaled state caused the function to return. For example, the count of a semaphore object is decreased by one.  The WaitForSingleObject() function can wait for the following objects:

  1. Change notification.

  2. Console input.

  3. Event.

  4. Job.

  5. Memory resource notification.

  6. Mutex.

  7. Process.

  8. Semaphore.

  9. Thread.

  10. Waitable timer.

 

Use caution when calling the wait functions and code that directly or indirectly creates windows. If a thread creates any windows, it must process messages. Message broadcasts are sent to all windows in the system. A thread that uses a wait function with no time-out interval may cause the system to become deadlocked. Two examples of code that indirectly creates windows are DDE and the CoInitialize() function. Therefore, if you have a thread that creates windows, use MsgWaitForMultipleObjects() or MsgWaitForMultipleObjectsEx(), rather than WaitForSingleObject().

 

WaitForMultipleObjects()

 

Item

Description

Function

WaitForMultipleObjects().

Use

Returns when any one or all of the specified objects are in the signaled state or the time-out interval elapses.  To enter an alertable wait state, use the WaitForMultipleObjectsEx() function.

Prototype

DWORD WaitForMultipleObjects( DWORD nCount, const HANDLE* lpHandles, BOOL bWaitAll, DWORD dwMilliseconds);

Parameters

See below.

Return value

See below.

Include file

<windows.h>

Remark

See below.

 

Table 3.

 

Parameters

 

nCount - [in] Number of object handles in the array pointed to by lpHandles. The maximum number of object handles is MAXIMUM_WAIT_OBJECTS.

lpHandles - [in] Pointer to an array of object handles. For a list of the object types whose handles can be specified, see the following Remarks section. The array can contain handles to objects of different types. It may not contain the multiple copies of the same handle. If one of these handles is closed while the wait is still pending, the function's behavior is undefined. The handles must have the SYNCHRONIZE access right.  For Windows Me/98/95:  No handle may be a duplicate of another handle created using DuplicateHandle().

bWaitAll - [in] If this parameter is TRUE, the function returns when the state of all objects in the lpHandles array is signaled. If FALSE, the function returns when the state of any one of the objects is set to signaled. In the latter case, the return value indicates the object whose state caused the function to return.

dwMilliseconds - [in] Time-out interval, in milliseconds. The function returns if the interval elapses, even if the conditions specified by the bWaitAll parameter are not met. If dwMilliseconds is zero, the function tests the states of the specified objects and returns immediately. If dwMilliseconds is INFINITE, the function's time-out interval never elapses.

 

Return Values

 

If the function succeeds, the return value indicates the event that caused the function to return. It can be one of the following values.

 

Return code

Description

WAIT_OBJECT_0 to (WAIT_OBJECT_0 + nCount 1)

If bWaitAll is TRUE, the return value indicates that the state of all specified objects is signaled. If bWaitAll is FALSE, the return value minus WAIT_OBJECT_0 indicates the lpHandles array index of the object that satisfied the wait. If more than one object became signaled during the call, this is the array index of the signaled object with the smallest index value of all the signaled objects.

WAIT_ABANDONED_0 to (WAIT_ABANDONED_0 + nCount 1)

If bWaitAll is TRUE, the return value indicates that the state of all specified objects is signaled and at least one of the objects is an abandoned mutex object. If bWaitAll is FALSE, the return value minus WAIT_ABANDONED_0 indicates the lpHandles array index of an abandoned mutex object that satisfied the wait.

WAIT_TIMEOUT

The time-out interval elapsed and the conditions specified by the bWaitAll parameter are not satisfied.

 

Table 4

 

If the function fails, the return value is WAIT_FAILED. To get extended error information, call GetLastError().

 

Some Remarks

 

The WaitForMultipleObjects function determines whether the wait criteria have been met. If the criteria have not been met, the calling thread enters the wait state. It uses no processor time while waiting for the criteria to be met. When bWaitAll is TRUE, the function's wait operation is completed only when the states of all objects have been set to signaled. The function does not modify the states of the specified objects until the states of all objects have been set to signaled. For example, a mutex can be signaled, but the thread does not get ownership until the states of the other objects are also set to signaled. In the meantime, some other thread may get ownership of the mutex, thereby setting its state to non-signaled. The function modifies the state of some types of synchronization objects. Modification occurs only for the object or objects whose signaled state caused the function to return. For example, the count of a semaphore object is decreased by one. When bWaitAll is FALSE, and multiple objects are in the signaled state, the function chooses one of the objects to satisfy the wait; the states of the objects not selected are unaffected. The WaitForMultipleObjects() function can specify handles of any of the following object types in the lpHandles array:

  1. Change notification

  2. Console input

  3. Event

  4. Job

  5. Memory resource notification

  6. Mutex.

  7. Process.

  8. Semaphore.

  9. Thread.

  10. Waitable timer.

 

Use caution when calling the wait functions and code that directly or indirectly creates windows. If a thread creates any windows, it must process messages. Message broadcasts are sent to all windows in the system. A thread that uses a wait function with no time-out interval may cause the system to become deadlocked. Two examples of code that indirectly creates windows are DDE and the CoInitialize() function. Therefore, if you have a thread that creates windows, use MsgWaitForMultipleObjects() or MsgWaitForMultipleObjectsEx(), rather than WaitForMultipleObjects().

 

CloseHandle()

 

Item

Description

Function

CloseHandle().

Use

To close an open object handle.

Prototype

BOOL CloseHandle(HANDLE hObject);

Parameters

hObject - [in, out] Handle to an open object.

Return value

See below.

Include file

<windows.h>

Remark

See below.

 

Table 5.

 

Return Values

 

If the function succeeds, the return value is nonzero.  If the function fails, the return value is zero. To get extended error information, call GetLastError().

Because pseudo-handle values are accepted as valid by GetCurrentHandle(), they (or -1) can be specified as the value of hObject.  This function will throw an exception if either a handle value that is not valid (or 0) or pseudo-handle value is specified as the value of hObject and the application is running under a debugger. This includes closing a handle twice, and using CloseHandle() on a handle returned by the FindFirstFile() function. Note that this function will not throw an exception when a handle value that is not valid or pseudo-handle value is specified and the application is not running under a debugger.

 

Some Remarks

 

The CloseHandle() function closes handles to the following objects:

  1. Access token.

  2. Communications device.

  3. Console input.

  4. Console screen buffer.

  5. Event.

  6. File.

  7. File mapping.

  8. Job.

  9. Mailslot.

  10. Mutex.

  11. Named pipe.

  12. Process.

  13. Semaphore.

  14. Socket.

  15. Thread.

 

CloseHandle() invalidates the specified object handle, decrements the object's handle count, and performs object retention checks. After the last handle to an object is closed, the object is removed from the system. Closing a thread handle does not terminate the associated thread. To remove a thread object, you must terminate the thread, then close all handles to the thread. Use CloseHandle() to close handles returned by calls to the CreateFile() function. Use FindClose() to close handles returned by calls to FindFirstFile(). To use operating system resources efficiently, an application should close files when they are no longer needed by using the CloseHandle() function. If a file is open when an application terminates, the system closes it automatically.  Note that closing a file does not delete the file from disk.

 

GetPriorityClass()

 

Item

Description

Function

GetPriorityClass().

Use

Retrieves the priority class for the specified process. This value, together with the priority value of each thread of the process, determines each thread's base priority level.

Prototype

DWORD GetPriorityClass(HANDLE hProcess);

Parameters

hProcess - [in] Handle to the process. The handle must have the PROCESS_QUERY_INFORMATION access right.

Return value

See below.

Include file

<windows.h>

Remark

See below.

 

Table 6.

 

Return Values

 

If the function succeeds, the return value is the priority class of the specified process.  If the function fails, the return value is zero. To get extended error information, call GetLastError().  The process's priority class is one of the following values.

 

Return code

Description

ABOVE_NORMAL_PRIORITY_CLASS

Process that has priority above NORMAL_PRIORITY_CLASS but below HIGH_PRIORITY_CLASS. Windows NT and Windows Me/98/95:  This value is not supported.

BELOW_NORMAL_PRIORITY_CLASS

Process that has priority above IDLE_PRIORITY_CLASS but below NORMAL_PRIORITY_CLASS. For Windows NT and Windows Me/98/95:  This value is not supported.

HIGH_PRIORITY_CLASS

Process that performs time-critical tasks that must be executed immediately for it to run correctly. The threads of a high-priority class process preempt the threads of normal or idle priority class processes. An example is the Task List, which must respond quickly when called by the user, regardless of the load on the operating system. Use extreme care when using the high-priority class, because a high-priority class CPU-bound application can use nearly all available cycles.

IDLE_PRIORITY_CLASS

Process whose threads run only when the system is idle and are preempted by the threads of any process running in a higher priority class. An example is a screen saver. The idle priority class is inherited by child processes.

NORMAL_PRIORITY_CLASS

Process with no special scheduling needs.

REALTIME_PRIORITY_CLASS

Process that has the highest possible priority. The threads of a real-time priority class process preempt the threads of all other processes, including operating system processes performing important tasks. For example, a real-time process that executes for more than a very brief interval can cause disk caches not to flush or cause the mouse to be unresponsive.

 

Table 7

 

Some Remarks

 

Every thread has a base priority level determined by the thread's priority value and the priority class of its process. The operating system uses the base priority level of all executable threads to determine which thread gets the next slice of CPU time. Threads are scheduled in a round-robin fashion at each priority level, and only when there are no executable threads at a higher level will scheduling of threads at a lower level take place. Priority class is maintained by the executive, so all processes have a priority class that can be queried. For Windows NT:  Priority class is maintained by the Windows subsystem (csrss), so only Windows-based application have a priority class that can be queried.

 

SetPriorityClass()

 

Item

Description

Function

SetPriorityClass().

Use

Sets the priority class for the specified process. This value together with the priority value of each thread of the process determines each thread's base priority level.

Prototype

BOOL SetPriorityClass(HANDLE hProcess, DWORD dwPriorityClass);

Parameters

See below.

Return value

If the function succeeds, the return value is nonzero.  If the function fails, the return value is zero. To get extended error information, call GetLastError().

Include file

<windows.h>

Remark

See below.

 

Table 8.

 

Parameters

 

hProcess - [in] Handle to the process. The handle must have the PROCESS_SET_INFORMATION access right.

dwPriorityClass - [in] Priority class for the process. This parameter can be one of the following values.

 

Priority

Meaning

ABOVE_NORMAL_PRIORITY_CLASS

Process that has priority above NORMAL_PRIORITY_CLASS but below HIGH_PRIORITY_CLASS.

Windows NT and Windows Me/98/95:  This value is not supported.

BELOW_NORMAL_PRIORITY_CLASS

Process that has priority above IDLE_PRIORITY_CLASS but below NORMAL_PRIORITY_CLASS.

Windows NT and Windows Me/98/95:  This value is not supported.

HIGH_PRIORITY_CLASS

Process that performs time-critical tasks that must be executed immediately. The threads of the process preempt the threads of normal or idle priority class processes. An example is the Task List, which must respond quickly when called by the user, regardless of the load on the operating system. Use extreme care when using the high-priority class, because a high-priority class application can use nearly all available CPU time.

IDLE_PRIORITY_CLASS

Process whose threads run only when the system is idle. The threads of the process are preempted by the threads of any process running in a higher priority class. An example is a screen saver. The idle-priority class is inherited by child processes.

NORMAL_PRIORITY_CLASS

Process with no special scheduling needs.

REALTIME_PRIORITY_CLASS

Process that has the highest possible priority. The threads of the process preempt the threads of all other processes, including operating system processes performing important tasks. For example, a real-time process that executes for more than a very brief interval can cause disk caches not to flush or cause the mouse to be unresponsive.

 

Table 9

 

Some Remarks

 

Every thread has a base priority level determined by the thread's priority value and the priority class of its process. The system uses the base priority level of all executable threads to determine which thread gets the next slice of CPU time. The SetThreadPriority() function enables setting the base priority level of a thread relative to the priority class of its process.

 

CreateToolhelp32Snapshot()

 

Item

Description

Function

CreateToolhelp32Snapshot().

Use

To take a snapshot of the specified processes in the system, as well as the heaps, modules, and threads used by these processes.

Prototype

HANDLE WINAPI CreateToolhelp32Snapshot(DWORD dwFlags, DWORD th32ProcessID);

Parameters

See below.

Return value

If the function succeeds, it returns an open handle to the specified snapshot.  If the function fails, it returns INVALID_HANDLE_VALUE. To get extended error information, call GetLastError().

Include file

<tlhelp32.h>

Remark

See below.

 

Table.

 

Parameters

 

dwFlags - [in] Portions of the system to include in the snapshot. This parameter can be one of the following values.

 

Value

Meaning

TH32CS_INHERIT

Indicates that the snapshot handle is to be inheritable.

TH32CS_SNAPALL

Includes all processes and threads in the system, plus the heaps and modules of the process specified in th32ProcessID. Equivalent to specifying the TH32CS_SNAPHEAPLIST, TH32CS_SNAPMODULE, TH32CS_SNAPPROCESS, and TH32CS_SNAPTHREAD values.

TH32CS_SNAPHEAPLIST

Includes all heaps of the process specified in th32ProcessID in the snapshot. To enumerate the heaps, see Heap32ListFirst().

TH32CS_SNAPMODULE

Includes all modules of the process specified in th32ProcessID in the snapshot. To enumerate the modules, see Module32First().

TH32CS_SNAPPROCESS

Includes all processes in the system in the snapshot. To enumerate the processes, see Process32First().

TH32CS_SNAPTHREAD

Includes all threads in the system in the snapshot. To enumerate the threads, see Thread32First().

To identify the threads that belong to a specific process, compare its process identifier to the th32OwnerProcessID member of the THREADENTRY32 structure when enumerating the threads.

 

Table 10

 

th32ProcessID - [in] Process identifier of the process to be included in the snapshot. This parameter can be zero to indicate the current process. This parameter is used when the TH32CS_SNAPHEAPLIST, TH32CS_SNAPMODULE, or TH32CS_SNAPALL value is specified. Otherwise, it is ignored and all processes are included in the snapshot.

 

Some Remarks

 

The snapshot taken by this function is examined by the other tool help functions to provide their results. Access to the snapshot is read only. The snapshot handle acts as an object handle and is subject to the same rules regarding which processes and threads it is valid in.  To enumerate the heap or module states for all processes, specify TH32CS_SNAPALL and set th32ProcessID to zero. Then, for each additional process in the snapshot, call CreateToolhelp32Snapshot() again, specifying its process identifier and the TH32CS_SNAPHEAPLIST or TH32_SNAPMODULE value.

To destroy the snapshot, use the CloseHandle() function.

 

Process32First()

 

Item

Description

Function

Process32First().

Use

To retrieve information about the first process encountered in a system snapshot.

Prototype

BOOL WINAPI Process32First(HANDLE hSnapshot, LPPROCESSENTRY32 lppe);

Parameters

hSnapshot - [in] Handle to the snapshot returned from a previous call to the CreateToolhelp32Snapshot() function.

lppe - [in, out] Pointer to a PROCESSENTRY32 structure. It contains process information such as the name of the executable file, the process identifier, and the process identifier of the parent process.

Return value

Returns TRUE if the first entry of the process list has been copied to the buffer or FALSE otherwise. The ERROR_NO_MORE_FILES error value is returned by the GetLastError() function if no processes exist or the snapshot does not contain process information.

Include file

<tlhelp32.h>

Remark

The calling application must set the dwSize member of PROCESSENTRY32 to the size, in bytes, of the structure.  To retrieve information about other processes recorded in the same snapshot, use the Process32Next() function.

 

Table 11.

 

Process32Next()

 

Item

Description

Function

Process32Next().

Use

To retrieve information about the next process recorded in a system snapshot.

Prototype

BOOL WINAPI Process32Next(HANDLE hSnapshot, LPPROCESSENTRY32 lppe);

Parameters

hSnapshot - [in] Handle to the snapshot returned from a previous call to the CreateToolhelp32Snapshot() function.

lppe - [out] Pointer to a PROCESSENTRY32 structure.

Return value

Returns TRUE if the next entry of the process list has been copied to the buffer or FALSE otherwise. The ERROR_NO_MORE_FILES error value is returned by the GetLastError() function if no processes exist or the snapshot does not contain process information.

Include file

<tlhelp32.h>

Remark

To retrieve information about the first process recorded in a snapshot, use the Process32First() function.

 

Table 12.

 

CreateThread()

 

Item

Description

Function

CreateThread().

Use

To create a thread to execute within the virtual address space of the calling process.  To create a thread that runs in the virtual address space of another process, use the CreateRemoteThread() function.

Prototype

HANDLE CreateThread( LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId);

Parameters

See below.

Return value

If the function succeeds, the return value is a handle to the new thread.  If the function fails, the return value is NULL. To get extended error information, call GetLastError().

Note that CreateThread() may succeed even if lpStartAddress points to data, code, or is not accessible. If the start address is invalid when the thread runs, an exception occurs, and the thread terminates. Thread termination due to a invalid start address is handled as an error exit for the thread's process. This behavior is similar to the asynchronous nature of CreateProcess(), where the process is created even if it refers to invalid or missing dynamic-link libraries (DLLs).  For Windows Me/98/95:  CreateThread() succeeds only when it is called in the context of a 32-bit program. A 32-bit DLL cannot create an additional thread when that DLL is being called by a 16-bit program.

Include file

<windows.h>

Remark

See below.

 

Table 13.

 

Parameters

 

lpThreadAttributes - [in] Pointer to a SECURITY_ATTRIBUTES structure that determines whether the returned handle can be inherited by child processes. If lpThreadAttributes is NULL, the handle cannot be inherited. The lpSecurityDescriptor member of the structure specifies a security descriptor for the new thread. If lpThreadAttributes is NULL, the thread gets a default security descriptor. The ACLs in the default security descriptor for a thread come from the primary or impersonation token of the creator.

dwStackSize - [in] Initial size of the stack, in bytes. The system rounds this value to the nearest page. If this parameter is zero, the new thread uses the default size for the executable.

lpStartAddress - [in] Pointer to the application-defined function to be executed by the thread and represents the starting address of the thread.

lpParameter - [in] Pointer to a variable to be passed to the thread.

dwCreationFlags - [in] Flags that control the creation of the thread. If the CREATE_SUSPENDED flag is specified, the thread is created in a suspended state, and will not run until the ResumeThread() function is called. If this value is zero, the thread runs immediately after creation. If the STACK_SIZE_PARAM_IS_A_RESERVATION flag is specified, the dwStackSize parameter specifies the initial reserve size of the stack. Otherwise, dwStackSize specifies the commit size.  For Windows 2000/NT and Windows Me/98/95:  The STACK_SIZE_PARAM_IS_A_RESERVATION flag is not supported.

lpThreadId - [out] Pointer to a variable that receives the thread identifier. If this parameter is NULL, the thread identifier is not returned.  For Windows Me/98/95:  This parameter may not be NULL.

 

Some Remarks

 

The number of threads a process can create is limited by the available virtual memory. By default, every thread has one megabyte of stack space. Therefore, you can create at most 2028 threads. If you reduce the default stack size, you can create more threads. However, your application will have better performance if you create one thread per processor and build queues of requests for which the application maintains the context information. A thread would process all requests in a queue before processing requests in the next queue. The new thread handle is created with the THREAD_ALL_ACCESS access right. If a security descriptor is not provided, the handle can be used in any function that requires a thread object handle. When a security descriptor is provided, an access check is performed on all subsequent uses of the handle before access is granted. If the access check denies access, the requesting process cannot use the handle to gain access to the thread. If the thread impersonates a client, then calls CreateThread() with a NULL security descriptor, the thread object created has a default security descriptor which allows access only to the impersonation token's TokenDefaultDacl owner or members.

The thread execution begins at the function specified by the lpStartAddress parameter. If this function returns, the DWORD return value is used to terminate the thread in an implicit call to the ExitThread() function. Use the GetExitCodeThread() function to get the thread's return value. The thread is created with a thread priority of THREAD_PRIORITY_NORMAL. Use the GetThreadPriority() and SetThreadPriority() functions to get and set the priority value of a thread. When a thread terminates, the thread object attains a signaled state, satisfying any threads that were waiting on the object. The thread object remains in the system until the thread has terminated and all handles to it have been closed through a call to CloseHandle(). The ExitProcess(), ExitThread(), CreateThread(), CreateRemoteThread() functions, and a process that is starting (as the result of a call by CreateProcess()) are serialized between each other within a process. Only one of these events can happen in an address space at a time. This means that the following restrictions hold:

Do not create a thread while impersonating another user. The call will succeed, however the newly created thread will have reduced access rights to itself when calling GetCurrentThread(). The access rights granted are derived from the access rights that the impersonated user has to the process. Some access rights including THREAD_SET_THREAD_TOKEN and THREAD_GET_CONTEXT may not be present, leading to unexpected failures.

  1. During process startup and DLL initialization routines, new threads can be created, but they do not begin execution until DLL initialization is done for the process.

  2. Only one thread in a process can be in a DLL initialization or detach routine at a time.

  3. ExitProcess() does not return until no threads are in their DLL initialization or detach routines.

A thread in an executable that is linked to the static C run-time library (CRT) should use _beginthread() and _endthread() for thread management rather than CreateThread() and ExitThread(). Failure to do so results in small memory leaks when the thread calls ExitThread(). Another work around is to link the executable to the CRT in a DLL instead of the static CRT. Note that this memory leak only occurs from a DLL if the DLL is linked to the static CRT and a thread calls the DisableThreadLibraryCalls() function. Otherwise, it is safe to call CreateThread() and ExitThread() from a thread in a DLL that links to the static CRT.

 

ThreadProc()

 

Item

Description

Function

ThreadProc().

Use

An application-defined function that serves as the starting address for a thread. Specify this address when calling the CreateThread() or CreateRemoteThread() function. The LPTHREAD_START_ROUTINE type defines a pointer to this callback function. ThreadProc() is a placeholder for the application-defined function name.

Prototype

DWORD WINAPI ThreadProc(LPVOID lpParameter);

Parameters

lpParameter - [in] Thread data passed to the function using the lpParameter parameter of the CreateThread() or CreateRemoteThread() function.

Return value

The function should return a value that indicates its success or failure.

Include file

<windows.h>

Remark

A process can obtain the return value of the ThreadProc() of a thread it created with CreateThread() by calling the GetExitCodeThread() function. A process cannot obtain the return value from the ThreadProc() of a thread it created with CreateRemoteThread().

 

Table 14.

 

ResumeThread()

 

Item

Description

Function

ResumeThread().

Use

Decrements a thread's suspend count. When the suspend count is decremented to zero, the execution of the thread is resumed.

Prototype

DWORD ResumeThread(HANDLE hThread);

Parameters

hThread - [in] Handle to the thread to be restarted.  The handle must have the THREAD_SUSPEND_RESUME access right.

Return value

If the function succeeds, the return value is the thread's previous suspend count.  If the function fails, the return value is (DWORD) -1. To get extended error information, call GetLastError().

Include file

<windows.h>

Remark

See below.

 

Table 15.

 

Some Remarks

 

The ResumeThread() function checks the suspend count of the subject thread. If the suspend count is zero, the thread is not currently suspended. Otherwise, the subject thread's suspend count is decremented. If the resulting value is zero, then the execution of the subject thread is resumed. If the return value is zero, the specified thread was not suspended. If the return value is 1, the specified thread was suspended but was restarted. If the return value is greater than 1, the specified thread is still suspended. Note that while reporting debug events, all threads within the reporting process are frozen. Debuggers are expected to use the SuspendThread() and ResumeThread() functions to limit the set of threads that can execute within a process. By suspending all threads in a process except for the one reporting a debug event, it is possible to "single step" a single thread. The other threads are not released by a continue operation if they are suspended.

 

SuspendThread()

 

Item

Description

Function

SuspendThread().

Use

Suspends the specified thread.

Prototype

DWORD SuspendThread(HANDLE hThread);

Parameters

hThread - [in] Handle to the thread that is to be suspended. The handle must have the THREAD_SUSPEND_RESUME access right.

Return value

If the function succeeds, the return value is the thread's previous suspend count; otherwise, it is (DWORD) -1. To get extended error information, use the GetLastError() function.

Include file

<windows.h>

Remark

See below.

 

Table 16.

 

Some Remarks

 

If the function succeeds, execution of the specified thread is suspended and the thread's suspend count is incremented. Suspending a thread causes the thread to stop executing user-mode (application) code. This function is primarily designed for use by debuggers. It is not intended to be used for thread synchronization. Calling SuspendThread() on a thread that owns a synchronization object, such as a mutex or critical section, can lead to a deadlock if the calling thread tries to obtain a synchronization object owned by a suspended thread. To avoid this situation, a thread within an application that is not a debugger should signal the other thread to suspend itself. The target thread must be designed to watch for this signal and respond appropriately. Each thread has a suspend count (with a maximum value of MAXIMUM_SUSPEND_COUNT). If the suspend count is greater than zero, the thread is suspended; otherwise, the thread is not suspended and is eligible for execution. Calling SuspendThread() causes the target thread's suspend count to be incremented. Attempting to increment past the maximum suspend count causes an error without incrementing the count. The ResumeThread() function decrements the suspend count of a suspended thread.

 

ExitThread()

 

Item

Description

Function

ExitThread().

Use

Ends a thread.

Prototype

VOID ExitThread(DWORD dwExitCode);

Parameters

dwExitCode - [in] Exit code for the calling thread. Use the GetExitCodeThread() function to retrieve a thread's exit code.

Return value

This function does not return a value.

Include file

<windows.h>

Remark

See below.

 

Table 17.

 

Some Remarks

 

ExitThread() is the preferred method of exiting a thread. When this function is called (either explicitly or by returning from a thread procedure), the current thread's stack is de-allocated, all pending I/O initiated by the thread is cancelled, and the thread terminates. The entry-point function of all attached dynamic-link libraries (DLLs) is invoked with a value indicating that the thread is detaching from the DLL. If the thread is the last thread in the process when this function is called, the thread's process is also terminated. The state of the thread object becomes signaled, releasing any other threads that had been waiting for the thread to terminate. The thread's termination status changes from STILL_ACTIVE to the value of the dwExitCode parameter.  Terminating a thread does not necessarily remove the thread object from the operating system. A thread object is deleted when the last handle to the thread is closed.  The ExitProcess(), ExitThread(), CreateThread(), CreateRemoteThread() functions, and a process that is starting (as the result of a CreateProcess() call) are serialized between each other within a process. Only one of these events can happen in an address space at a time. This means the following restrictions hold:

  1. During process startup and DLL initialization routines, new threads can be created, but they do not begin execution until DLL initialization is done for the process.

  2. Only one thread in a process can be in a DLL initialization or detach routine at a time.

  3. ExitProcess() does not return until no threads are in their DLL initialization or detach routines.

 

A thread in an executable that is linked to the static C run-time library (CRT) should use _beginthread() and _endthread() for thread management rather than CreateThread() and ExitThread(). Failure to do so results in small memory leaks when the thread calls ExitThread(). Another work around is to link the executable to the CRT in a DLL instead of the static CRT. Note that this memory leak only occurs from a DLL if the DLL is linked to the static CRT and a thread calls the DisableThreadLibraryCalls() function. Otherwise, it is safe to call CreateThread() and ExitThread() from a thread in a DLL that links to the static CRT.

 

GetExitCodeThread()

 

Item

Description

Function

GetExitCodeThread().

Use

Retrieves the termination status of the specified thread.

Prototype

BOOL GetExitCodeThread(HANDLE hThread, LPDWORD lpExitCode);

Parameters

hThread - [in] Handle to the thread. The handle must have the THREAD_QUERY_INFORMATION access right.

lpExitCode - [out] Pointer to a variable to receive the thread termination status.

Return value

If the function succeeds, the return value is nonzero.  If the function fails, the return value is zero. To get extended error information, call GetLastError().

Include file

<windows.h>

Remark

If the specified thread has not terminated, the termination status returned is STILL_ACTIVE. If the thread has terminated, the termination status returned may be one of the following:

  1. he exit value specified in the ExitThread() or TerminateThread() function.

  2. The return value from the thread function.

  3. The exit value of the thread's process.

 

Warning:  If a thread happens to return STILL_ACTIVE (259) as an error code, applications that test for this value could end up in an infinite loop.

 

Table 18.

 

TerminateThread()

 

Item

Description

Function

TerminateThread().

Use

Terminates a thread.

Prototype

BOOL TerminateThread(HANDLE hThread, DWORD dwExitCode);

Parameters

hThread -- [in, out] Handle to the thread to terminate. The handle must have the THREAD_TERMINATE access right.

dwExitCode - [in] Exit code for the thread. Use the GetExitCodeThread() function to retrieve a thread's exit value.

Return value

If the function succeeds, the return value is nonzero.  If the function fails, the return value is zero. To get extended error information, call GetLastError().

Include file

<windows.h>

Remark

See below.

 

Table 19.

 

Some Remarks

 

TerminateThread() is used to cause a thread to exit. When this occurs, the target thread has no chance to execute any user-mode code and its initial stack is not de-allocated. DLLs attached to the thread are not notified that the thread is terminating. TerminateThread() is a dangerous function that should only be used in the most extreme cases. You should call TerminateThread() only if you know exactly what the target thread is doing, and you control all of the code that the target thread could possibly be running at the time of the termination. For example, TerminateThread() can result in the following problems:

  1. If the target thread owns a critical section, the critical section will not be released.

  2. If the target thread is allocating memory from the heap, the heap lock will not be released.

  3. If the target thread is executing certain kernel32 calls when it is terminated, the kernel32 state for the thread's process could be inconsistent.

  4. If the target thread is manipulating the global state of a shared DLL, the state of the DLL could be destroyed, affecting other users of the DLL.

 

A thread cannot protect itself against TerminateThread(), other than by controlling access to its handles. The thread handle returned by the CreateThread() and CreateProcess() functions has THREAD_TERMINATE access, so any caller holding one of these handles can terminate your thread. If the target thread is the last thread of a process when this function is called, the thread's process is also terminated. The state of the thread object becomes signaled, releasing any other threads that had been waiting for the thread to terminate. The thread's termination status changes from STILL_ACTIVE to the value of the dwExitCode parameter. Terminating a thread does not necessarily remove the thread object from the system. A thread object is deleted when the last thread handle is closed.

 

GetThreadPriority()

 

Item

Description

Function

GetThreadPriority().

Use

To retrieve the priority value for the specified thread. This value, together with the priority class of the thread's process, determines the thread's base-priority level.

Prototype

int GetThreadPriority(HANDLE hThread);

Parameters

hThread - [in] Handle to the thread. The handle must have THREAD_QUERY_INFORMATION access.

Return value

See below.

Include file

<windows.h>

Remark

Every thread has a base-priority level determined by the thread's priority value and the priority class of its process. The operating system uses the base-priority level of all executable threads to determine which thread gets the next slice of CPU time. Threads are scheduled in a round-robin fashion at each priority level, and only when there are no executable threads at a higher level will scheduling of threads at a lower level take place. For a table that shows the base-priority levels for each combination of priority class and thread priority value, refer to the SetPriorityClass() function.

 

Table 20.

 

Return Values

 

If the function succeeds, the return value is the thread's priority level.  If the function fails, the return value is THREAD_PRIORITY_ERROR_RETURN. To get extended error information, call GetLastError().  The thread's priority level is one of the following values.

 

Return code

Description

THREAD_PRIORITY_ABOVE_NORMAL

Priority 1 point above the priority class.

THREAD_PRIORITY_BELOW_NORMAL

Priority 1 point below the priority class.

THREAD_PRIORITY_HIGHEST

Priority 2 points above the priority class.

THREAD_PRIORITY_IDLE

Base priority of 1 for IDLE_PRIORITY_CLASS, BELOW_NORMAL_PRIORITY_CLASS, NORMAL_PRIORITY_CLASS, ABOVE_NORMAL_PRIORITY_CLASS, or HIGH_PRIORITY_CLASS processes, and a base priority of 16 for REALTIME_PRIORITY_CLASS processes.

THREAD_PRIORITY_LOWEST

Priority 2 points below the priority class.

THREAD_PRIORITY_NORMAL

Normal priority for the priority class.

THREAD_PRIORITY_TIME_CRITICAL

Base-priority level of 15 for IDLE_PRIORITY_CLASS, BELOW_NORMAL_PRIORITY_CLASS, NORMAL_PRIORITY_CLASS, ABOVE_NORMAL_PRIORITY_CLASS, or HIGH_PRIORITY_CLASS processes, and a base-priority level of 31 for REALTIME_PRIORITY_CLASS processes.

 

Table 21

 

SetThreadPriority()

 

Item

Description

Function

SetThreadPriority().

Use

To set the priority value for the specified thread. This value, together with the priority class of the thread's process, determines the thread's base priority level.

Prototype

BOOL SetThreadPriority(HANDLE hThread, int nPriority);

Parameters

See below.

Return value

If the function succeeds, the return value is nonzero.  If the function fails, the return value is zero. To get extended error information, call GetLastError().

Include file

<windows.h>

Remark

See below.

 

Table 22.

 

Parameters

 

hThread - [in] Handle to the thread whose priority value is to be set.  The handle must have the THREAD_SET_INFORMATION access right.

nPriority - [in] Priority value for the thread.  This parameter can be one of the following values.

 

Priority

Meaning

THREAD_PRIORITY_ABOVE_NORMAL

Priority 1 point above the priority class.

THREAD_PRIORITY_BELOW_NORMAL

Priority 1 point below the priority class.

THREAD_PRIORITY_HIGHEST

Priority 2 points above the priority class.

THREAD_PRIORITY_IDLE

Base priority of 1 for IDLE_PRIORITY_CLASS, BELOW_NORMAL_PRIORITY_CLASS, NORMAL_PRIORITY_CLASS, ABOVE_NORMAL_PRIORITY_CLASS, or HIGH_PRIORITY_CLASS processes, and a base priority of 16 for REALTIME_PRIORITY_CLASS processes.

THREAD_PRIORITY_LOWEST

Priority 2 points below the priority class.

THREAD_PRIORITY_NORMAL

Normal priority for the priority class.

THREAD_PRIORITY_TIME_CRITICAL

Base priority of 15 for IDLE_PRIORITY_CLASS, BELOW_NORMAL_PRIORITY_CLASS, NORMAL_PRIORITY_CLASS, ABOVE_NORMAL_PRIORITY_CLASS, or HIGH_PRIORITY_CLASS processes, and a base priority of 31 for REALTIME_PRIORITY_CLASS processes.

 

Table 23

 

This parameter can also be -7, -6, -5, -4, -3, 3, 4, 5, or 6.

 

Some Remarks

 

Every thread has a base priority level determined by the thread's priority value and the priority class of its process. The system uses the base priority level of all executable threads to determine which thread gets the next slice of CPU time. Threads are scheduled in a round-robin fashion at each priority level, and only when there are no executable threads at a higher level does scheduling of threads at a lower level take place. The SetThreadPriority() function enables setting the base priority level of a thread relative to the priority class of its process. For example, specifying THREAD_PRIORITY_HIGHEST in a call to SetThreadPriority() for a thread of an IDLE_PRIORITY_CLASS process sets the thread's base priority level to 6. For IDLE_PRIORITY_CLASS, BELOW_NORMAL_PRIORITY_CLASS, NORMAL_PRIORITY_CLASS, ABOVE_NORMAL_PRIORITY_CLASS, and HIGH_PRIORITY_CLASS processes, the system dynamically boosts a thread's base priority level when events occur that are important to the thread. REALTIME_PRIORITY_CLASS processes do not receive dynamic boosts. All threads initially start at THREAD_PRIORITY_NORMAL. Use the GetPriorityClass() and SetPriorityClass() functions to get and set the priority class of a process. Use the GetThreadPriority() function to get the priority value of a thread. Use the priority class of a process to differentiate between applications that are time critical and those that have normal or below normal scheduling requirements. Use thread priority values to differentiate the relative priorities of the tasks of a process. For example, a thread that handles input for a window could have a higher priority level than a thread that performs intensive calculations for the CPU. When manipulating priorities, be very careful to ensure that a high-priority thread does not consume all of the available CPU time. A thread with a base priority level above 11 interferes with the normal operation of the operating system. Using REALTIME_PRIORITY_CLASS may cause disk caches to not flush, hang the mouse, and so on.

 

ExitProcess()

 

Item

Description

Function

ExitProcess().

Use

To end a process and all its threads.

Prototype

VOID ExitProcess(UINT uExitCode);

Parameters

uExitCode - [in] Exit code for the process and all threads terminated as a result of this call. Use the GetExitCodeProcess() function to retrieve the process's exit value. Use the GetExitCodeThread() function to retrieve a thread's exit value.

Return value

This function does not return a value.

Include file

<windows.h>

Remark

See below.

 

Table 24.

 

Some Remarks

 

ExitProcess() is the preferred method of ending a process. This function provides a clean process shutdown. This includes calling the entry-point function of all attached dynamic-link libraries (DLLs) with a value indicating that the process is detaching from the DLL. If a process terminates by calling TerminateProcess(), the DLLs that the process is attached to are not notified of the process termination.  After all attached DLLs have executed any process termination value; this function terminates the current process.  Terminating a process causes the following:

The state of the process object becomes signaled, satisfying any threads that had been waiting for the process to terminate. The states of all threads of the process become signaled, satisfying any threads that had been waiting for the threads to terminate. The termination status of the process changes from STILL_ACTIVE to the exit value of the process. Terminating a process does not cause child processes to be terminated. Terminating a process does not necessarily remove the process object from the operating system. A process object is deleted when the last handle to the process is closed. Warning    Calling ExitProcess() in a DLL can lead to unexpected application or system errors. Be sure to call ExitProcess() from a DLL only if you know which applications or system components will load the DLL and that it is safe to call ExitProcess() in this context. The ExitProcess(), ExitThread(), CreateThread(), CreateRemoteThread() functions, and a process that is starting (as the result of a call by CreateProcess()) are serialized between each other within a process. Only one of these events can happen in an address space at a time. This means the following restrictions hold:

CreateRemoteThread()

 

Item

Description

Function

CreateRemoteThread().

Use

To create a thread that runs in the virtual address space of another process.

Prototype

HANDLE CreateRemoteThread( HANDLE hProcess, LPSECURITY_ATTRIBUTES lpThreadAttributes,   SIZE_T dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId);

Parameters

See below.

Return value

If the function succeeds, the return value is a handle to the new thread.  If the function fails, the return value is NULL. To get extended error information, call GetLastError(). Note that CreateRemoteThread() may succeed even if lpStartAddress points to data, code, or is not accessible. If the start address is invalid when the thread runs, an exception occurs, and the thread terminates. Thread termination due to an invalid start address is handled as an error exit for the thread's process. This behavior is similar to the asynchronous nature of CreateProcess(), where the process is created even if it refers to invalid or missing dynamic-link libraries (DLLs).

Include file

<windows.h>

Remark

See below.

 

Table 25.

 

Parameters

 

hProcess - [in] Handle to the process in which the thread is to be created. The handle must have the PROCESS_CREATE_THREAD, PROCESS_QUERY_INFORMATION, PROCESS_VM_OPERATION, PROCESS_VM_WRITE, and PROCESS_VM_READ access rights.

lpThreadAttributes - [in] Pointer to a SECURITY_ATTRIBUTES structure that specifies a security descriptor for the new thread and determines whether child processes can inherit the returned handle. If lpThreadAttributes is NULL, the thread gets a default security descriptor and the handle cannot be inherited. The ACLs in the default security descriptor for a thread come from the primary or impersonation token of the creator.

dwStackSize - [in] Initial size of the stack, in bytes. The system rounds this value to the nearest page. If this parameter is zero, the new thread uses the default size for the executable.

lpStartAddress - [in] Pointer to the application-defined function of type LPTHREAD_START_ROUTINE to be executed by the thread and represents the starting address of the thread in the remote process. The function must exist in the remote process.

lpParameter - [in] Pointer to a variable to be passed to the thread function.

dwCreationFlags - [in] Flags that control the creation of the thread. If the CREATE_SUSPENDED flag is specified, the thread is created in a suspended state and will not run until the ResumeThread() function is called. If this value is zero, the thread runs immediately after creation.

If the STACK_SIZE_PARAM_IS_A_RESERVATION flag is specified, the dwStackSize parameter specifies the initial reserve size of the stack. Otherwise, dwStackSize specifies the commit size.  For Windows 2000/NT:  The STACK_SIZE_PARAM_IS_A_RESERVATION flag is not supported.

lpThreadId - [out] Pointer to a variable that receives the thread identifier. If this parameter is NULL, the thread identifier is not returned.

 

Some Remarks

 

The CreateRemoteThread() function causes a new thread of execution to begin in the address space of the specified process. The thread has access to all objects opened by the process. The new thread handle is created with full access to the new thread. If a security descriptor is not provided, the handle may be used in any function that requires a thread object handle. When a security descriptor is provided, an access check is performed on all subsequent uses of the handle before access is granted. If the access check denies access, the requesting process cannot use the handle to gain access to the thread. The thread is created with a thread priority of THREAD_PRIORITY_NORMAL. Use the GetThreadPriority() and SetThreadPriority() functions to get and set the priority value of a thread. When a thread terminates, the thread object attains a signaled state, satisfying any threads that were waiting for the object. The thread object remains in the system until the thread has terminated and all handles to it have been closed through a call to CloseHandle(). The ExitProcess(), ExitThread(), CreateThread(), CreateRemoteThread() functions, and a process that is starting (as the result of a CreateProcess() call) are serialized between each other within a process. Only one of these events can happen in an address space at a time. This means the following restrictions hold:

Terminal Services:  Terminal Services isolates each terminal session by design. Therefore, CreateRemoteThread() fails if the target process is in a different session than the calling process.

 

GetCurrentThread()

 

Item

Description

Function

GetCurrentThread().

Use

To retrieve a pseudo handle for the current thread.

Prototype

HANDLE GetCurrentThread(void);

Parameters

This function has no parameters.

Return value

The return value is a pseudo handle for the current thread.

Include file

<windows.h>

Remark

See below.

 

Table 26.

 

Some Remarks

 

A pseudo handle is a special constant that is interpreted as the current thread handle. The calling thread can use this handle to specify itself whenever a thread handle is required. Pseudo handles are not inherited by child processes. This handle has the maximum possible access to the thread object. For systems that support security descriptors, this is the maximum access allowed by the security descriptor for the calling process. For systems that do not support security descriptors, this is THREAD_ALL_ACCESS. The function cannot be used by one thread to create a handle that can be used by other threads to refer to the first thread. The handle is always interpreted as referring to the thread that is using it. A thread can create a "real" handle to itself that can be used by other threads, or inherited by other processes, by specifying the pseudo handle as the source handle in a call to the DuplicateHandle() function. The pseudo handle need not be closed when it is no longer needed. Calling the CloseHandle() function with this handle has no effect. If the pseudo handle is duplicated by DuplicateHandle(), the duplicate handle must be closed. Do not create a thread while impersonating a security context. The call will succeed, however the newly created thread will have reduced access rights to itself when calling this function. The access rights granted this thread will be derived from the access rights the impersonated user has to the process. Some access rights including THREAD_SET_THREAD_TOKEN and THREAD_GET_CONTEXT may not be present, leading to unexpected failures.

 

GetCurrentThreadId()

 

Item

Description

Function

GetCurrentThreadId().

Use

To retrieve the thread identifier of the calling thread.

Prototype

DWORD GetCurrentThreadId(void);

Parameters

This function has no parameters.

Return value

The return value is the thread identifier of the calling thread.

Include file

<windows.h>

Remark

Until the thread terminates, the thread identifier uniquely identifies the thread throughout the system.

 

Table 27.

 

TlsAlloc()

 

Item

Description

Function

TlsAlloc().

Use

Allocates a thread local storage (TLS) index. Any thread of the process can subsequently use this index to store and retrieve values that are local to the thread, because each thread receives its own slot for the index.

Prototype

DWORD TlsAlloc(void);

Parameters

This function has no parameters.

Return value

If the function succeeds, the return value is a TLS index. The slots for the index are initialized to zero. If the function fails, the return value is TLS_OUT_OF_INDEXES. To get extended error information, call GetLastError().

Include file

<windows.h>

Remark

The threads of the process can use the TLS index in subsequent calls to the TlsFree(), TlsSetValue(), or TlsGetValue() functions. TLS indexes are typically allocated during process or dynamic-link library (DLL) initialization. After a TLS index has been allocated, each thread of the process can use it to access its own TLS storage slot. To store a value in its TLS slot, a thread specifies the index in a call to TlsSetValue(). The thread specifies the same index in a subsequent call to TlsGetValue(), to retrieve the stored value.  TLS indexes are not valid across process boundaries. A DLL cannot assume that an index assigned in one process is valid in another process.

 

Table 28.

 

TlsSetValue()

 

Item

Description

Function

TlsSetValue().

Use

To store a value in the calling thread's thread local storage (TLS) slot for the specified TLS index. Each thread of a process has its own slot for each TLS index.

Prototype

BOOL TlsSetValue(DWORD dwTlsIndex, LPVOID lpTlsValue);

Parameters

dwTlsIndex - [in] TLS index that was allocated by the TlsAlloc() function.

lpTlsValue - [in] Value to be stored in the calling thread's TLS slot for the index.

Return value

If the function succeeds, the return value is nonzero.  If the function fails, the return value is zero. To get extended error information, call GetLastError().

Include file

<windows.h>

Remark

TLS indexes are typically allocated by the TlsAlloc() function during process or DLL initialization. After a TLS index is allocated, each thread of the process can use it to access its own TLS slot for that index. A thread specifies a TLS index in a call to TlsSetValue(), to store a value in its slot. The thread specifies the same index in a subsequent call to TlsGetValue(), to retrieve the stored value.  TlsSetValue() was implemented with speed as the primary goal. The function performs minimal parameter validation and error checking. In particular, it succeeds if dwTlsIndex is in the range 0 through (TLS_MINIMUM_AVAILABLE – 1). It is up to the programmer to ensure that the index is valid and that the thread calls TlsSetValue() before calling TlsGetValue().

 

Table.

 

TlsGetValue()

 

Item

Description

Function

TlsGetValue().

Use

To retrieve the value in the calling thread's thread local storage (TLS) slot for the specified TLS index. Each thread of a process has its own slot for each TLS index.

Prototype

LPVOID TlsGetValue(DWORD dwTlsIndex);

Parameters

dwTlsIndex - [in] TLS index that was allocated by the TlsAlloc() function.

Return value

See below.

Include file

<windows.h>

Remark

See below.

 

Table 29.

 

Return Values

 

If the function succeeds, the return value is the value stored in the calling thread's TLS slot associated with the specified index.  If the function fails, the return value is zero. To get extended error information, call GetLastError(). The data stored in a TLS slot can have a value of zero (either because the thread has not called TlsSetValue() or because the thread called TlsSetValue() with 0). In this case, the return value is zero and GetLastError() returns ERROR_SUCCESS. Functions that return indications of failure call SetLastError() when they fail. They generally do not call SetLastError() when they succeed. The TlsGetValue() function is an exception to this general rule. The TlsGetValue() function calls SetLastError() to clear a thread's last error when it succeeds. That allows checking for the error-free retrieval of zero values.

 

Some Remarks

 

TLS indexes are typically allocated by the TlsAlloc() function during process or DLL initialization. After a TLS index is allocated, each thread of the process can use it to access its own TLS slot for that index. A thread specifies a TLS index in a call to TlsSetValue() to store a value in its slot. The thread specifies the same index in a subsequent call to TlsGetValue() to retrieve the stored value. TlsGetValue() was implemented with speed as the primary goal. The function performs minimal parameter validation and error checking. In particular, it succeeds if dwTlsIndex is in the range 0 through (TLS_MINIMUM_AVAILABLE – 1). It is up to the programmer to ensure that the index is valid and that the thread calls TlsSetValue() before calling TlsGetValue().

 

TlsFree()

 

Item

Description

Function

TlsFree().

Use

To release a thread local storage (TLS) index, making it available for reuse.

Prototype

BOOL TlsFree(DWORD dwTlsIndex);

Parameters

dwTlsIndex - [in] TLS index that was allocated by the TlsAlloc() function.

Return value

If the function succeeds, the return value is nonzero.  If the function fails, the return value is zero. To get extended error information, call GetLastError().

Include file

<windows.h>

Remark

If the threads of the process have allocated memory and stored a pointer to the memory in a TLS slot, they should free the memory before calling TlsFree(). The TlsFree() function does not free memory blocks whose addresses have been stored in the TLS slots associated with the TLS index. It is expected that DLLs call this function (if at all) only during DLL_PROCESS_DETACH.

 

Table 30.

 

ImpersonateNamedPipeClient()

 

Item

Description

Function

ImpersonateNamedPipeClient().

Use

Impersonates a named-pipe client application.

Prototype

BOOL ImpersonateNamedPipeClient(HANDLE hNamedPipe);

Parameters

hNamedPipe - [in] Handle to a named pipe.

Return value

If the function succeeds, the return value is nonzero.  If the function fails, the return value is zero. To get extended error information, call GetLastError().

Include file

<windows.h>

Remark

See below.

 

Table 31.

 

Some Remarks

 

The ImpersonateNamedPipeClient() function allows the server end of a named pipe to impersonate the client end. When this function is called, the named-pipe file system changes the thread of the calling process to start impersonating the security context of the last message read from the pipe. Only the server end of the pipe can call this function. The server can call the RevertToSelf() function when the impersonation is complete. Important:  If the ImpersonateNamedPipeClient() function fails, the client is not impersonated, and all subsequent client requests are made in the security context of the process that called the function. If the calling process is running as a privileged account, it can perform actions that the client would not be allowed to perform. To avoid security risks, the calling process should always check the return value. If the return value indicates that the function call failed, no client requests should be executed. All impersonate functions, including ImpersonateNamedPipeClient(), check to determine if the caller has the SeImpersonatePrivilege() privilege. If the caller has the SeImpersonatePrivilege() privilege, or if the authenticated identity is the same as the caller, then the requested impersonation is allowed. Otherwise, the impersonation succeeds at Identify level only. For Windows XP, Windows 2000 SP3 and earlier, and Windows NT:  The SeImpersonatePrivilege() privilege is not supported.

 

OpenThreadToken()

 

Item

Description

Function

OpenThreadToken().

Use

To open the access token associated with a thread.

Prototype

BOOL OpenThreadToken( HANDLE ThreadHandle, DWORD DesiredAccess, BOOL OpenAsSelf, PHANDLE TokenHandle);

Parameters

See below.

Return value

If the function succeeds, the return value is nonzero.  If the function fails, the return value is zero. To get extended error information, call GetLastError(). If the token has the anonymous impersonation level, the token will not be opened and OpenThreadToken() sets ERROR_CANT_OPEN_ANONYMOUS as the error.

Include file

<windows.h>

Remark

The OpenAsSelf() parameter allows the caller of the API to open the access token of a specified thread when the caller is impersonating a token at SecurityIdentification level. Without this parameter, the calling thread cannot open the access token on the specified thread because it is impossible to open executive-level objects using the SecurityIdentification impersonation level.  Tokens with the anonymous impersonation level cannot be opened.  Close the access token handle returned through the TokenHandle parameter by calling CloseHandle().

 

Table 32.

 

Parameters

 

ThreadHandle - [in] Handle to the thread whose access token is opened.

DesiredAccess - [in] Specifies an access mask that specifies the requested types of access to the access token. These requested access types are reconciled against the token's discretionary access control list (DACL) to determine which accesses are granted or denied.

OpenAsSelf - [in] Indicates whether the access check is to be made against the security context of the thread calling the OpenThreadToken() function or against the security context of the process for the calling thread. If this parameter is FALSE, the access check is performed using the security context for the calling thread. If the thread is impersonating a client, this security context can be that of a client process. If this parameter is TRUE, the access check is made using the security context of the process for the calling thread.

TokenHandle - [out] Pointer to a variable that receives the handle to the newly opened access token.

 

MapGenericMask()

 

Item

Description

Function

MapGenericMask().

Use

Maps the generic access rights in an access mask to specific and standard access rights. The function applies a mapping supplied in a GENERIC_MAPPING structure.

Prototype

VOID MapGenericMask(PDWORD AccessMask, PGENERIC_MAPPING GenericMapping);

Parameters

AccessMask - [out] Pointer to an access mask receiving the specific and standard rights mapped from generic access rights.

GenericMapping - [in] Pointer to a GENERIC_MAPPING structure specifying a mapping of generic access types to specific and standard access types.

Return value

This function does not return a value.

Include file

<windows.h>

Remark

After calling the MapGenericMask() function, the access mask pointed to by the AccessMask parameter has none of its generic bits (GenericRead, GenericWrite, GenericExecute, or GenericAll) or undefined bits set, although it can have other bits set. If bits other than the generic bits are provided on input, this function does not clear them.

 

Table 33.

 

AccessCheck()

 

Item

Description

Function

AccessCheck().

Use

To determine whether a security descriptor grants a specified set of access rights to the client identified by an access token. Typically, server applications use this function to check access to a private object.

Prototype

BOOL AccessCheck( PSECURITY_DESCRIPTOR pSecurityDescriptor, HANDLE ClientToken, DWORD DesiredAccess, PGENERIC_MAPPING GenericMapping, PPRIVILEGE_SET PrivilegeSet, LPDWORD PrivilegeSetLength, LPDWORD GrantedAccess, LPBOOL AccessStatus);

Parameters

See below.

Return value

If the function succeeds, the return value is nonzero.  If the function fails, the return value is zero. To get extended error information, call GetLastError().

Include file

<windows.h>

Remark

See below.

 

Table 34.

 

Parameters

 

pSecurityDescriptor - [in] Pointer to a SECURITY_DESCRIPTOR structure against which access is checked.

ClientToken - [in] Handle to an impersonation token that represents the client that is attempting to gain access. The handle must have TOKEN_QUERY access to the token; otherwise, the function fails with ERROR_ACCESS_DENIED.

DesiredAccess - [in] Access mask that specifies the access rights to check. This mask must have been mapped by the MapGenericMask() function to contain no generic access rights. If this parameter is MAXIMUM_ALLOWED, the function sets the GrantedAccess access mask to indicate the maximum access rights the security descriptor allows the client.

GenericMapping - [in] Pointer to the GENERIC_MAPPING structure associated with the object for which access is being checked.

PrivilegeSet - [out] Pointer to a PRIVILEGE_SET structure that receives the privileges used to perform the access validation. If no privileges were used, the function sets the PrivilegeCount member to zero.

PrivilegeSetLength - [in] Specifies the size, in bytes, of the buffer pointed to by the PrivilegeSet parameter.

GrantedAccess - [out] Pointer to an access mask that receives the granted access rights. If AccessStatus is set to FALSE, the function sets the access mask to zero. If the function fails, it does not set the access mask.

AccessStatus - [out] Pointer to a variable that receives the results of the access check. If the security descriptor allows the requested access rights to the client identified by the access token, AccessStatus is set to TRUE. Otherwise, AccessStatus is set to FALSE, and you can call GetLastError() to get extended error information.

 

Some Remarks

 

The AccessCheck() function compares the specified security descriptor with the specified access token and indicates, in the AccessStatus parameter, whether access is granted or denied. If access is granted, the requested access mask becomes the object's granted access mask. If the security descriptor's DACL is NULL, the AccessStatus parameter returns TRUE, which indicates that the client has the requested access. The AccessCheck() function fails with ERROR_INVALID_SECURITY_DESCR if the security descriptor does not contain owner and group SIDs. The AccessCheck() function does not generate an audit. If your application requires audits for access checks, use functions such as AccessCheckAndAuditAlarm(), AccessCheckByTypeAndAuditAlarm(), AccessCheckByTypeResultListAndAuditAlarm(), or AccessCheckByTypeResultListAndAuditAlarmByHandle(), instead of AccessCheck().

 

AccessCheckAndAuditAlarm()

 

Item

Description

Function

AccessCheckAndAuditAlarm().

Use

Determines whether a security descriptor grants a specified set of access rights to the client being impersonated by the calling thread. If the security descriptor has a SACL with ACEs that apply to the client, the function generates any necessary audit messages in the security event log.  Alarms are not currently supported.

Prototype

BOOL AccessCheckAndAuditAlarm( LPCTSTR SubsystemName, LPVOID HandleId, LPTSTR ObjectTypeName, LPTSTR ObjectName, PSECURITY_DESCRIPTOR SecurityDescriptor, DWORD DesiredAccess, PGENERIC_MAPPING GenericMapping, BOOL ObjectCreation, LPDWORD GrantedAccess, LPBOOL AccessStatus, LPBOOL pfGenerateOnClose);

Parameters

 See below.

Return value

If the function succeeds, the return value is nonzero.  If the function fails, the return value is zero. To get extended error information, call GetLastError().

Include file

<windows.h>

Remark

Implemented as Unicode and ANSI versions.  The AccessCheckAndAuditAlarm() function requires the calling process to have the SE_AUDIT_NAME privilege enabled. The test for this privilege is performed against the primary token of the calling process, not the impersonation token of the thread. The AccessCheckAndAuditAlarm() function fails if the calling thread is not impersonating a client.

 

Table 35.

 

Parameters

 

SubsystemName - [in] Pointer to a null-terminated string specifying the name of the subsystem calling the function. This string appears in any audit message that the function generates.

HandleId - [in] Pointer to a unique value representing the client's handle to the object. If the access is denied, the system ignores this value.

ObjectTypeName - [in] Pointer to a null-terminated string specifying the type of object being created or accessed. This string appears in any audit message that the function generates.

ObjectName - [in] Pointer to a null-terminated string specifying the name of the object being created or accessed. This string appears in any audit message that the function generates.

SecurityDescriptor - [in] Pointer to the SECURITY_DESCRIPTOR structure against which access is checked.

DesiredAccess - [in] Access mask that specifies the access rights to check. This mask must have been mapped by the MapGenericMask() function to contain no generic access rights. If this parameter is MAXIMUM_ALLOWED, the function sets the GrantedAccess access mask to indicate the maximum access rights the security descriptor allows the client.

GenericMapping - [in] Pointer to the GENERIC_MAPPING structure associated with the object for which access is being checked.

ObjectCreation - [in] Specifies a flag that determines whether the calling application will create a new object when access is granted. A value of TRUE indicates the application will create a new object. A value of FALSE indicates the application will open an existing object.

GrantedAccess - [out] Pointer to an access mask that receives the granted access rights. If AccessStatus is set to FALSE, the function sets the access mask to zero. If the function fails, it does not set the access mask.

AccessStatus - [out] Pointer to a variable that receives the results of the access check. If the security descriptor allows the requested access rights to the client, AccessStatus is set to TRUE. Otherwise, AccessStatus is set to FALSE.

pfGenerateOnClose - [out] Pointer to a flag set by the audit-generation routine when the function returns. Pass this flag to the ObjectCloseAuditAlarm() function when the object handle is closed.

 

 

-------------------------------------------Part 2/5-----------------------------------------

 

 

 

 

 

 

 

 

 

 

 

 

Further reading and digging:

 

  1. Microsoft Visual C++, online MSDN.

  2. Structure, enum, union and typedef story can be found in C struct, typedef, enum etc..

  3. For Multibytes, Unicode characters and Localization please refer to Multibyte & Unicode 1 (Story) and Multibyte & Unicode 2 (Implementation).

  4. Check the best selling C / C++ and Windows books at Amazon.com.

 

 

 

 

 

 

| Previous | Main | Next | Site Index | Download | Disclaimer | Privacy |