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


 

 

 

 

 

 

WINDOWS THREAD SYNCHRONIZATION REFERENCES 1

 

 

 

 

 

 

 

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

 

The Page Index:

  1. EnterCriticalSection()

  2. InitializeCriticalSectionAndSpinCount()

  3. LeaveCriticalSection()

  4. DeleteCriticalSection()

  5. Module32First()

  6. Module32Next()

  7. MsgWaitForMultipleObjects()

  8. CreateEvent()

  9. ResetEvent()

  10. SetEvent()

  11. EnumProcesses()

  12. OpenProcess()

  13. EnumProcessModules()

  14. GetModuleBaseName()

  15. GetModuleFileNameEx()

  16. CommandLineToArgvW()

  17. CreateMutex()

  18. ReleaseMutex()

  19. CreateSemaphore()

  20. ReleaseSemaphore()

  21. OpenSemaphorev()

  22. CreateNamedPipe()

  23. CreateFileMapping()

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

EnterCriticalSection()

 

Item

Description

Function

EnterCriticalSection().

Use

Waits for ownership of the specified critical section object. The function returns when the calling thread is granted ownership.

Prototype

void EnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection);

Parameters

lpCriticalSection - [in, out] Pointer to the critical section object.

Return value

This function does not return a value.  This function can raise EXCEPTION_POSSIBLE_DEADLOCK if the critical section is corrupt or deadlock detection is enabled. Do not handle this exception; either continue execution or debug the application.

For Windows 2000/NT:  In low memory situations, EnterCriticalSection() can raise an exception. To avoid problems, use structured exception handling, or call the InitializeCriticalSectionAndSpinCount() function to pre-allocate the event used by EnterCriticalSection() instead of calling the InitializeCriticalSection() function, which forces EnterCriticalSection() to allocate the event.

Include file

<windows.h>

Remark

See below.

 

Table 1.

 

Remarks

 

The threads of a single process can use a critical section object for mutual-exclusion synchronization. The process is responsible for allocating the memory used by a critical section object, which it can do by declaring a variable of type CRITICAL_SECTION. Before using a critical section, some thread of the process must call InitializeCriticalSection() or InitializeCriticalSectionAndSpinCount() to initialize the object.

To enable mutually exclusive access to a shared resource, each thread calls the EnterCriticalSection() or TryEnterCriticalSection() function to request ownership of the critical section before executing any section of code that accesses the protected resource. The difference is that TryEnterCriticalSection() returns immediately, regardless of whether it obtained ownership of the critical section, while EnterCriticalSection() blocks until the thread can take ownership of the critical section. When it has finished executing the protected code, the thread uses the LeaveCriticalSection() function to relinquish ownership, enabling another thread to become owner and access the protected resource. The thread must call LeaveCriticalSection() once for each time that it entered the critical section. The thread enters the critical section each time EnterCriticalSection() and TryEnterCriticalSection() succeed. After a thread has ownership of a critical section, it can make additional calls to EnterCriticalSection() or TryEnterCriticalSection() without blocking its execution. This prevents a thread from deadlocking itself while waiting for a critical section that it already owns. Any thread of the process can use the DeleteCriticalSection() function to release the system resources that were allocated when the critical section object was initialized. After this function has been called, the critical section object can no longer be used for synchronization. If a thread terminates while it has ownership of a critical section, the state of the critical section is undefined.  If a critical section is deleted while it is still owned, the state of the threads waiting for ownership of the deleted critical section is undefined.

 

InitializeCriticalSectionAndSpinCount()

 

Item

Description

Function

InitializeCriticalSectionAndSpinCount().

Use

Initializes a critical section object and sets the spin count for the critical section.

Prototype

BOOL InitializeCriticalSectionAndSpinCount(

  LPCRITICAL_SECTION lpCriticalSection,

  DWORD dwSpinCount);

Parameters

lpCriticalSection - [in, out] Pointer to the critical section object.

dwSpinCount - [in] Spin count for the critical section object. On single-processor systems, the spin count is ignored and the critical section spin count is set to 0. On multiprocessor systems, if the critical section is unavailable, the calling thread will spin dwSpinCount times before performing a wait operation on a semaphore associated with the critical section. If the critical section becomes free during the spin operation, the calling thread avoids the wait operation. Windows 2000:  If the high-order bit is set, the function pre-allocates the event used by the EnterCriticalSection() function. Do not set this bit if you are creating a large number of critical section objects, because it will consume a significant amount of non-paged pool. This flag is not necessary on Windows XP and later, and it is ignored.

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().  For Windows Me/98/95:  This function has no return value. If the function fails, it will raise an exception.

Include file

<windows.h>

Remark

See below.

 

Table 2.

 

Some Remarks

 

The threads of a single process can use a critical section object for mutual-exclusion synchronization. There is no guarantee about the order in which threads will obtain ownership of the critical section, however, the system will be fair to all threads. The process is responsible for allocating the memory used by a critical section object, which it can do by declaring a variable of type CRITICAL_SECTION. Before using a critical section, some thread of the process must call the InitializeCriticalSection() or InitializeCriticalSectionAndSpinCount() function to initialize the object. You can subsequently modify the spin count by calling the SetCriticalSectionSpinCount() function. After a critical section object has been initialized, the threads of the process can specify the object in the EnterCriticalSection(), TryEnterCriticalSection(), or LeaveCriticalSection() function to provide mutually exclusive access to a shared resource. For similar synchronization between the threads of different processes, use a mutex object. A critical section object cannot be moved or copied. The process must also not modify the object, but must treat it as logically opaque. Use only the critical section functions to manage critical section objects. When you have finished using the critical section, call the DeleteCriticalSection() function.

A critical section object must be deleted before it can be reinitialized. Initializing a critical section that has already been initialized results in undefined behavior. The spin count is useful for critical sections of short duration that can experience high levels of contention. Consider a worst-case scenario, in which an application on an Symmetric Multi Processor (SMP) system has two or three threads constantly allocating and releasing memory from the heap. The application serializes the heap with a critical section. In the worst-case scenario, contention for the critical section is constant, and each thread makes an expensive call to the WaitForSingleObject() function. However, if the spin count is set properly, the calling thread will not immediately call WaitForSingleObject() when contention occurs. Instead, the calling thread can acquire ownership of the critical section if it is released during the spin operation. You can improve performance significantly by choosing a small spin count for a critical section of short duration. The heap manager uses a spin count of roughly 4000 for its per-heap critical sections. This gives great performance and scalability in almost all worst-case scenarios. To compile an application that uses this function, define the _WIN32_WINNT macro as 0x0403 or later.

 

LeaveCriticalSection()

 

Item

Description

Function

LeaveCriticalSection().

Use

Releases ownership of the specified critical section object.

Prototype

void LeaveCriticalSection(LPCRITICAL_SECTION lpCriticalSection);

Parameters

lpCriticalSection - [in, out] Pointer to the critical section object.

Return value

This function does not return a value.

Include file

<windows.h>

Remark

See below.

 

Table 3.

 

Another Remarks

 

The threads of a single process can use a critical-section object for mutual-exclusion synchronization. The process is responsible for allocating the memory used by a critical-section object, which it can do by declaring a variable of type CRITICAL_SECTION. Before using a critical section, some thread of the process must call the InitializeCriticalSection() or InitializeCriticalSectionAndSpinCount() function to initialize the object. A thread uses the EnterCriticalSection() or TryEnterCriticalSection() function to acquire ownership of a critical section object. To release its ownership, the thread must call LeaveCriticalSection once for each time that it entered the critical section. If a thread calls LeaveCriticalSection() when it does not have ownership of the specified critical section object, an error occurs that may cause another thread using EnterCriticalSection() to wait indefinitely.

Any thread of the process can use the DeleteCriticalSection() function to release the system resources that were allocated when the critical section object was initialized. After this function has been called, the critical section object can no longer be used for synchronization.

 

DeleteCriticalSection()

 

Item

Description

Function

DeleteCriticalSection().

Use

To release all resources used by an unowned critical section object.

Prototype

void DeleteCriticalSection(LPCRITICAL_SECTION lpCriticalSection);

Parameters

lpCriticalSection - [in, out] Pointer to the critical section object. The object must have been previously initialized with the InitializeCriticalSection() function.

Return value

This function does not return a value.

Include file

<windows.h>

Remark

Deleting a critical section object releases all system resources used by the object.  After a critical section object has been deleted, do not reference the object in any function that operates on critical sections (such as EnterCriticalSection(), TryEnterCriticalSection(), and LeaveCriticalSection()) other than InitializeCriticalSection() and InitializeCriticalSectionAndSpinCount(). If you attempt to do so, memory corruption and other unexpected errors can occur.

If a critical section is deleted while it is still owned, the state of the threads waiting for ownership of the deleted critical section is undefined.

 

Table 4.

 

Module32First()

 

Item

Description

Function

Module32First().

Use

To retrieve information about the first module associated with a process.

Prototype

BOOL WINAPI Module32First(HANDLE hSnapshot, LPMODULEENTRY32 lpme);

Parameters

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

lpme - [in, out] Pointer to a MODULEENTRY32 structure.

Return value

Returns TRUE if the first entry of the module 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 modules exist or the snapshot does not contain module information.

Include file

<tlhelp32.h>

Remark

The calling application must set the dwSize member of MODULEENTRY32 to the size, in bytes, of the structure.  To retrieve information about other modules associated with the specified process, use the Module32Next() function.

 

Table 5.

 

Module32Next()

 

Item

Description

Function

Module32Next().

Use

To retrieve information about the next module associated with a process or thread.

Prototype

BOOL WINAPI Module32Next(HANDLE hSnapshot, LPMODULEENTRY32 lpme);

Parameters

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

lpme - [out] Pointer to a MODULEENTRY32 structure.

Return value

Returns TRUE if the next entry of the module 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 more modules exist.

Include file

<tlhelp32.h>

Remark

To retrieve information about first module associated with a process, use the Module32First() function.

 

Table 6.

 

MsgWaitForMultipleObjects()

 

Item

Description

Function

MsgWaitForMultipleObjects().

Use

Returns when any one or all of the specified objects are in the signaled state or the time-out interval elapses. The objects can include input event objects, which you specify using the dwWakeMask parameter.  To enter an alertable wait state, use the MsgWaitForMultipleObjectsEx() function.

Prototype

DWORD MsgWaitForMultipleObjects( DWORD nCount, const HANDLE* pHandles, BOOL bWaitAll, DWORD dwMilliseconds, DWORD dwWakeMask );

Parameters

See below.

Return value

See below.

Include file

<windows.h>

Remark

See below.

 

Table 7.

 

Parameters

 

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

pHandles - [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 of objects of different types. It may not contain 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 states of all objects in the pHandles array have been set to signaled and an input event has been received. If this parameter is FALSE, the function returns when the state of any one of the objects is set to signaled or an input event has been received. In this 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 criteria specified by the bWaitAll or dwWakeMask parameter have not been 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.

dwWakeMask - [in] Input types for which an input event object handle will be added to the array of object handles. This parameter can be any combination of the following values.

 

Value

Meaning

QS_ALLEVENTS

An input, WM_TIMER, WM_PAINT, WM_HOTKEY, or posted message is in the queue. This value is a combination of QS_INPUT, QS_POSTMESSAGE, QS_TIMER, QS_PAINT, and QS_HOTKEY.

QS_ALLINPUT

Any message is in the queue. This value is a combination of QS_INPUT, QS_POSTMESSAGE, QS_TIMER, QS_PAINT, QS_HOTKEY, and QS_SENDMESSAGE.

QS_ALLPOSTMESSAGE

A posted message is in the queue. This value is cleared when you call GetMessage() or PeekMessage() without filtering messages.

QS_HOTKEY

A WM_HOTKEY message is in the queue.

QS_INPUT

An input message is in the queue. This value is a combination of QS_MOUSE and QS_KEY.

Windows 2003 Server and Windows XP:  This value also includes QS_RAWINPUT.

QS_KEY

A WM_KEYUP, WM_KEYDOWN, WM_SYSKEYUP, or WM_SYSKEYDOWN message is in the queue.

QS_MOUSE

A WM_MOUSEMOVE message or mouse-button message (WM_LBUTTONUP, WM_RBUTTONDOWN, and so on). This value is a combination of QS_MOUSEMOVE and QS_MOUSEBUTTON.

QS_MOUSEBUTTON

A mouse-button message (WM_LBUTTONUP, WM_RBUTTONDOWN, and so on).

QS_MOUSEMOVE

A WM_MOUSEMOVE message is in the queue.

QS_PAINT

A WM_PAINT message is in the queue.

QS_POSTMESSAGE

A posted message is in the queue. This value is cleared when you call GetMessage() or PeekMessage(), whether or not you are filtering messages.

QS_RAWINPUT

A raw input message is in the queue.  For Windows 2000/NT and Windows Me/98/95:  This value is not supported.

QS_SENDMESSAGE

A message sent by another thread or application is in the queue.

QS_TIMER

A WM_TIMER message is in the queue.

 

Table 8

 

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 pHandles array index of the object that satisfied the wait.

WAIT_OBJECT_0 + nCount

New input of the type specified in the dwWakeMask parameter is available in the thread's input queue. Functions such as PeekMessage(), GetMessage(), and WaitMessage() mark messages in the queue as old messages. Therefore, after you call one of these functions, a subsequent call to MsgWaitForMultipleObjects() will not return until new input of the specified type arrives. This value is also returned upon the occurrence of a system event that requires the thread's action, such as foreground activation. Therefore, MsgWaitForMultipleObjects() can return even though no appropriate input is available and even if dwWakeMask is set to 0. If this occurs, call GetMessage() or PeekMessage() to process the system event before trying the call to MsgWaitForMultipleObjects() again.

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 pHandles 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 and dwWakeMask parameters were not satisfied.

 

Table 9

 

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

 

Some Remarks

 

The MsgWaitForMultipleObjects() 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 conditions of the wait criteria to be met. When bWaitAll is TRUE, 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 have also been set to signaled. In the meantime, some other thread may get ownership of the mutex, thereby setting its state to non-signaled. When bWaitAll is TRUE, the function's wait is completed only when the states of all objects have been set to signaled and an input event has been received. Therefore, setting bWaitAll to TRUE prevents input from being processed until the state of all objects in the pHandles array have been set to signaled. For this reason, if you set bWaitAll to TRUE, you should use a short timeout value in dwMilliseconds. If you have a thread that creates windows waiting for all objects in the pHandles array, including input events specified by dwWakeMask, with no timeout interval, the system will deadlock. This is because threads that create windows must process messages. DDE sends message to all windows in the system. Therefore, if a thread creates windows, do not set the bWaitAll parameter to TRUE in calls to MsgWaitForMultipleObjects() made from that thread.

Note:  MsgWaitForMultipleObjects() does not return if there is unread input of the specified type in the message queue after the thread has called a function to check the queue. This is because functions such as PeekMessage(), GetMessage(), GetQueueStatus(), and WaitMessage() check the queue and then change the state information for the queue so that the input is no longer considered new. A subsequent call to MsgWaitForMultipleObjects() will not return until new input of the specified type arrives. The existing unread input (received prior to the last time the thread checked the queue) is ignored. 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 MsgWaitForMultipleObjects() function can specify handles of any of the following object types in the pHandles 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

 

The QS_ALLPOSTMESSAGE and QS_POSTMESSAGE flags differ in when they are cleared. QS_POSTMESSAGE is cleared when you call GetMessage() or PeekMessage(), whether or not you are filtering messages. QS_ALLPOSTMESSAGE is cleared when you call GetMessage() or PeekMessage() without filtering messages (wMsgFilterMin and wMsgFilterMax are 0). This can be useful when you call PeekMessage() multiple times to get messages in different ranges.

 

CreateEvent()

 

Item

Description

Function

CreateEvent().

Use

To create or opens a named or unnamed event object.

Prototype

HANDLE CreateEvent( LPSECURITY_ATTRIBUTES lpEventAttributes, BOOL bManualReset, BOOL bInitialState, LPCTSTR lpName );

Parameters

See below.

Return value

If the function succeeds, the return value is a handle to the event object. If the named event object existed before the function call, the function returns a handle to the existing object and GetLastError() returns ERROR_ALREADY_EXISTS.  If the function fails, the return value is NULL. To get extended error information, call GetLastError().

Include file

<windows.h>

Remark

Implemented as Unicode and ANSI versions. Note that Unicode support on Windows Me/98/95 requires Microsoft Layer for Unicode.  More remarks below.

 

Table 10.

 

Parameters

 

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

bManualReset - [in] If this parameter is TRUE, the function creates a manual-reset event object which requires use of the ResetEvent() function set the state to non-signaled. If this parameter is FALSE, the function creates an auto-reset event object, and system automatically resets the state to non-signaled after a single waiting thread has been released.

bInitialState - [in] If this parameter is TRUE, the initial state of the event object is signaled; otherwise, it is non-signaled.

lpName - [in] Pointer to a null-terminated string specifying the name of the event object. The name is limited to MAX_PATH characters. Name comparison is case sensitive. If lpName matches the name of an existing named event object, this function requests the EVENT_ALL_ACCESS access right. In this case, the bManualReset and bInitialState parameters are ignored because they have already been set by the creating process. If the lpEventAttributes parameter is not NULL, it determines whether the handle can be inherited, but its security-descriptor member is ignored.

If lpName is NULL, the event object is created without a name. If lpName matches the name of an existing semaphore, mutex, waitable timer, job, or file-mapping object, the function fails and the GetLastError() function returns ERROR_INVALID_HANDLE. This occurs because these objects share the same name space.

Terminal Services:  The name can have a "Global\" or "Local\" prefix to explicitly create the object in the global or session name space. The remainder of the name can contain any character except the backslash character (\). For Windows XP Home Edition:  Fast user switching is implemented using Terminal Services sessions. The first user to log on uses session 0, the next user to log on uses session 1, and so on. Kernel object names must follow the guidelines outlined for Terminal Services so that applications can support multiple users. For Windows 2000:  If Terminal Services is not running, the "Global\" and "Local\" prefixes are ignored. The remainder of the name can contain any character except the backslash character. For Windows NT 4.0 and earlier:  The name can contain any character except the backslash character. For Windows Me/98/95:  The name can contain any character except the backslash character. The empty string ("") is a valid object name.

 

Some Remarks

 

The handle returned by CreateEvent() has the EVENT_ALL_ACCESS access right and can be used in any function that requires a handle to an event object. Any thread of the calling process can specify the event-object handle in a call to one of the wait functions. The single-object wait functions return when the state of the specified object is signaled. The multiple-object wait functions can be instructed to return either when any one or when all of the specified objects are signaled. When a wait function returns, the waiting thread is released to continue its execution. The initial state of the event object is specified by the bInitialState parameter. Use the SetEvent() function to set the state of an event object to signaled. Use the ResetEvent() function to reset the state of an event object to non-signaled.

When the state of a manual-reset event object is signaled, it remains signaled until it is explicitly reset to non-signaled by the ResetEvent() function. Any number of waiting threads, or threads that subsequently begin wait operations for the specified event object, can be released while the object's state is signaled. When the state of an auto-reset event object is signaled, it remains signaled until a single waiting thread is released; the system then automatically resets the state to non-signaled. If no threads are waiting, the event object's state remains signaled.  Multiple processes can have handles of the same event object, enabling use of the object for interprocess synchronization. The following object-sharing mechanisms are available:

  1. A child process created by the CreateProcess() function can inherit a handle to an event object if the lpEventAttributes parameter of CreateEvent() enabled inheritance.

  2. A process can specify the event-object handle in a call to the DuplicateHandle() function to create a duplicate handle that can be used by another process.

  3. A process can specify the name of an event object in a call to the OpenEvent() or CreateEvent() function.

 

Use the CloseHandle() function to close the handle. The system closes the handle automatically when the process terminates. The event object is destroyed when its last handle has been closed. For Windows Me/98/95:  CreateEventW() is supported by the Microsoft Layer for Unicode. To use this, you must add certain files to your application, as outlined in Microsoft Layer for Unicode on Windows Me/98/95 Systems.

 

ResetEvent()

 

Item

Description

Function

ResetEvent().

Use

Sets the specified event object to the non-signaled state.

Prototype

BOOL ResetEvent(HANDLE hEvent);

Parameters

hEvent - [in] Handle to the event object. The CreateEvent() or OpenEvent() function returns this handle.  The handle must have the EVENT_MODIFY_STATE access right.

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

The state of an event object remains non-signaled until it is explicitly set to signaled by the SetEvent() or PulseEvent() function. This non-signaled state blocks the execution of any threads that have specified the event object in a call to one of the wait functions.

The ResetEvent function is used primarily for manual-reset event objects, which must be set explicitly to the non-signaled state. Auto-reset event objects automatically change from signaled to non-signaled after a single waiting thread is released.  Resetting an event that is already reset has no effect.

 

Table 11.

 

SetEvent()

 

Item

Description

Function

SetEvent().

Use

Sets the specified event object to the signaled state.

Prototype

BOOL SetEvent(HANDLE hEvent);

Parameters

hEvent - [in] Handle to the event object. The CreateEvent() or OpenEvent() function returns this handle.  The handle must have the EVENT_MODIFY_STATE access right.

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

The state of a manual-reset event object remains signaled until it is set explicitly to the non-signaled state by the ResetEvent() function. Any number of waiting threads, or threads that subsequently begin wait operations for the specified event object by calling one of the wait functions, can be released while the object's state is signaled.  The state of an auto-reset event object remains signaled until a single waiting thread is released, at which time the system automatically sets the state to non-signaled. If no threads are waiting, the event object's state remains signaled.  Setting an event that is already set has no effect.

 

Table 12.

 

EnumProcesses()

 

Item

Description

Function

EnumProcesses().

Use

To retrieve the process identifier for each process object in the system.

Prototype

BOOL EnumProcesses( DWORD* pProcessIds, DWORD cb, DWORD* pBytesReturned );

Parameters

pProcessIds - [out] Pointer to an array that receives the list of process identifiers.

cb - [in] Size of the pProcessIds array, in bytes.

pBytesReturned - [out] Number of bytes returned in the pProcessIds array.

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

<psapi.h>

Remark

It is a good idea to use a large array, because it is hard to predict how many processes there will be at the time you call EnumProcesses().

To determine how many processes were enumerated, divide the pBytesReturned value by sizeof(DWORD). There is no indication given when the buffer is too small to store all process identifiers. Therefore, if pBytesReturned equals cb, consider retrying the call with a larger array.

To obtain process handles for the processes whose identifiers you have just obtained, call the OpenProcess() function.

 

Table 13.

 

OpenProcess()

 

Item

Description

Function

OpenProcess().

Use

Opens an existing process object.

Prototype

HANDLE OpenProcess( DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwProcessId );

Parameters

dwDesiredAccess - [in] Access to the process object. This access right is checked against any security descriptor for the process.

bInheritHandle - [in] If this parameter is TRUE, the handle is inheritable. If the parameter is FALSE, the handle cannot be inherited.

dwProcessId - [in] Identifier of the process to open.

Return value

If the function succeeds, the return value is an open handle to the specified process. If the function fails, the return value is NULL. To get extended error information, call GetLastError().

Include file

<windows.h>

Remark

The handle returned by the OpenProcess() function can be used in any function that requires a handle to a process, such as the wait functions, provided the appropriate access rights were requested. When you are finished with the handle, be sure to close it using the CloseHandle() function.

 

Table 14.

 

EnumProcessModules()

 

Item

Description

Function

EnumProcessModules().

Use

Retrieves a handle for each module in the specified process.

Prototype

BOOL EnumProcessModules( HANDLE hProcess, HMODULE* lphModule, DWORD cb, LPDWORD lpcbNeeded);

Parameters

hProcess - [in] Handle to the process.

lphModule - [out] Pointer to the array that receives the list of module handles.

cb - [in] Size of the lphModule array, in bytes.

lpcbNeeded - [out] Number of bytes required to store all module handles in the lphModule array.

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

<psapi.h>

Remark

It is a good idea to specify a large array of HMODULE values, because it is hard to predict how many modules there will be in the process at the time you call EnumProcessModules(). To determine if the lphModule array is too small to hold all module handles for the process, compare the value returned in lpcbNeeded with the value specified in cb. If lpcbNeeded is greater than cb, increase the size of the array and call EnumProcessModules() again.

To determine how many modules were enumerated by the call to EnumProcessModules(), divide the resulting value in the lpcbNeeded parameter by sizeof(HMODULE). Do not call CloseHandle() on any of the handles returned by this function. The information comes from a snapshot, so there are no resources to be freed.

 

Table 15.

 

GetModuleBaseName()

 

Item

Description

Function

GetModuleBaseName().

Use

Retrieves the base name of the specified module.

Prototype

DWORD GetModuleBaseName( HANDLE hProcess, HMODULE hModule, LPTSTR lpBaseName, DWORD nSize);

Parameters

hProcess - [in] Handle to the process that contains the module. If this parameter is NULL, GetModuleBaseName() uses the current process. The handle must have the PROCESS_QUERY_INFORMATION and PROCESS_VM_READ access rights.

hModule - [in] Handle to the module. If this parameter is NULL, this function returns the name of the file used to create the calling process.

lpBaseName - [out] Pointer to the buffer that receives the base name of the module. If the base name is longer than maximum number of characters specified by the nSize parameter, the base name is truncated.

nSize - [in] Size of the lpBaseName buffer, in characters.

Return value

If the function succeeds, the return value specifies the length of the string copied to the buffer, in characters.  If the function fails, the return value is zero. To get extended error information, call GetLastError().

Include file

<psapi.h>

Remark

Implemented as Unicode and ANSI versions.

 

Table 16.

 

GetModuleFileNameEx()

 

Item

Description

Function

GetModuleFileNameEx().

Use

Retrieves the fully-qualified path for the file containing the specified module.

Prototype

DWORD GetModuleFileNameEx( HANDLE hProcess, HMODULE hModule, LPTSTR lpFilename, DWORD nSize );

Parameters

hProcess - [in] Handle to the process that contains the module. If this parameter is NULL, GetModuleFileNameEx() returns the path of the executable file for the calling process.

The handle must have the PROCESS_QUERY_INFORMATION and PROCESS_VM_READ access rights.

hModule - [in] Handle to the module.

lpFilename - [out] Pointer to the null-terminated buffer that receives the fully-qualified path to the module. If the size of the file name is larger than the value of the nSize parameter, the file name is truncated and null terminated.

nSize - [in] Size of the lpFilename buffer, in characters.

Return value

If the function succeeds, the return value specifies the length of the string copied to the buffer.  If the function fails, the return value is zero. To get extended error information, call GetLastError().

Include file

<psapi.h>

Remark

Implemented as Unicode and ANSI versions.

 

Table 17.

 

CommandLineToArgvW()

 

Item

Description

Function

CommandLineToArgvW().

Use

Parses a Unicode command-line string. It returns a pointer to a set of Unicode argument strings and a count of arguments, similar to the standard C run-time argv and argc values. The function provides a way to obtain a Unicode set of argv and argc values from a Unicode command-line string.

Prototype

LPWSTR* CommandLineToArgvW(LPCWSTR lpCmdLine, int* pNumArgs);

Parameters

lpCmdLine - [in] Pointer to a null-terminated Unicode command-line string. An application will usually directly pass on the value returned by a call to the GetCommandLineW() function.

If this parameter is the empty string, "", the function returns the path to the current executable file.

pNumArgs - [out] Pointer to an integer variable that receives the count of arguments parsed.

Return value

If the function succeeds, the return value is a non-NULL pointer to the constructed argument list, which is an array of Unicode strings.  If the function fails, the return value is NULL. To get extended error information, call GetLastError().

Include file

<windows.h>

Remark

Implemented only as Unicode. It is the caller's responsibility to free the memory used by the argument list when it is no longer needed. To free the memory, use a single call to the GlobalFree() function.

 

Table 18.

 

The following example demonstrates how to parse a Unicode command-line string. The code frees the memory for the argument list at exit.

#include <windows.h>

#include <stdio.h>

 

int __cdecl main(int argc, char * argv[])

{

   LPTSTR *szArglist;

   DWORD nArgs;

   int i;

 

#ifdef _UNICODE

   szArglist = CommandLineToArgvW(GetCommandLineW(), &nArgs);

   if (NULL == szArglist)

   {

      wprintf(TEXT("CommandLineToArgvW failed.\n"));

      return 0;

   }

   else

for( i=0; i<=argc; i++) printf("%ws\n", szArglist[i]);

#else

   szArglist = argv;

   nArgs = (DWORD) argc;

#endif

// ...

// Free memory allocated by CommandLineToArgvW for the arguments.

#ifdef _UNICODE

   GlobalFree(szArglist);

#endif

 

   return(1);

}

 

CreateMutex()

 

Item

Description

Function

CreateMutex().

Use

Creates or opens a named or unnamed mutex object.

Prototype

HANDLE CreateMutex( LPSECURITY_ATTRIBUTES lpMutexAttributes, BOOL bInitialOwner, LPCTSTR lpName);

Parameters

See below.

Return value

If the function succeeds, the return value is a handle to the newly created mutex object.  If the function fails, the return value is NULL. To get extended error information, call GetLastError().  If the mutex is a named mutex and the object existed before this function call, the return value is a handle to the existing object and GetLastError() returns ERROR_ALREADY_EXISTS.

Include file

<windows.h>

Remark

Implemented as Unicode and ANSI versions. Note that Unicode support on Windows Me/98/95 requires Microsoft Layer for Unicode. More remarks below.

 

Table 19.

 

Parameters

 

lpMutexAttributes - [in] Pointer to a SECURITY_ATTRIBUTES structure that determines whether the returned handle can be inherited by child processes. If lpMutexAttributes is NULL, the handle cannot be inherited.

The lpSecurityDescriptor member of the structure specifies a security descriptor for the new mutex. If lpMutexAttributes is NULL, the mutex gets a default security descriptor. The ACLs in the default security descriptor for a mutex come from the primary or impersonation token of the creator.

bInitialOwner - [in] If this value is TRUE and the caller created the mutex, the calling thread obtains initial ownership of the mutex object. Otherwise, the calling thread does not obtain ownership of the mutex. To determine if the caller created the mutex, see the Return Values section.

lpName - [in] Pointer to a null-terminated string specifying the name of the mutex object. The name is limited to MAX_PATH characters. Name comparison is case sensitive. If lpName matches the name of an existing named mutex object, this function requests the MUTEX_ALL_ACCESS access right. In this case, the bInitialOwner parameter is ignored because it has already been set by the creating process. If the lpMutexAttributes parameter is not NULL, it determines whether the handle can be inherited, but its security-descriptor member is ignored. If lpName is NULL, the mutex object is created without a name. If lpName matches the name of an existing event, semaphore, waitable timer, job, or file-mapping object, the function fails and the GetLastError() function returns ERROR_INVALID_HANDLE. This occurs because these objects share the same name space.

Terminal Services:  The name can have a "Global\" or "Local\" prefix to explicitly create the object in the global or session name space. The remainder of the name can contain any character except the backslash character (\). Windows XP Home Edition:  Fast user switching is implemented using Terminal Services sessions. The first user to log on uses session 0, the next user to log on uses session 1, and so on. Kernel object names must follow the guidelines outlined for Terminal Services so that applications can support multiple users. Windows 2000:  If Terminal Services is not running, the "Global\" and "Local\" prefixes are ignored. The remainder of the name can contain any character except the backslash character. Windows NT:  The name can contain any character except the backslash character. Windows Me/98/95:  The name can contain any character except the backslash character. The empty string ("") is a valid object name.

 

Some Remarks

 

The handle returned by CreateMutex() has the MUTEX_ALL_ACCESS access right and can be used in any function that requires a handle to a mutex object. Any thread of the calling process can specify the mutex-object handle in a call to one of the wait functions. The single-object wait functions return when the state of the specified object is signaled. The multiple-object wait functions can be instructed to return either when any one or when all of the specified objects are signaled. When a wait function returns, the waiting thread is released to continue its execution.

The state of a mutex object is signaled when it is not owned by any thread. The creating thread can use the bInitialOwner flag to request immediate ownership of the mutex. Otherwise, a thread must use one of the wait functions to request ownership. When the mutex's state is signaled, one waiting thread is granted ownership, the mutex's state changes to non-signaled, and the wait function returns. Only one thread can own a mutex at any given time. The owning thread uses the ReleaseMutex() function to release its ownership. The thread that owns a mutex can specify the same mutex in repeated wait function calls without blocking its execution. Typically, you would not wait repeatedly for the same mutex, but this mechanism prevents a thread from deadlocking itself while waiting for a mutex that it already owns. However, to release its ownership, the thread must call ReleaseMutex() once for each time that the mutex satisfied a wait. Two or more processes can call CreateMutex() to create the same named mutex. The first process actually creates the mutex, and subsequent processes open a handle to the existing mutex. This enables multiple processes to get handles of the same mutex, while relieving the user of the responsibility of ensuring that the creating process is started first. When using this technique, you should set the bInitialOwner flag to FALSE; otherwise, it can be difficult to be certain which process has initial ownership. Multiple processes can have handles of the same mutex object, enabling use of the object for interprocess synchronization. The following object-sharing mechanisms are available:

  1. A child process created by the CreateProcess() function can inherit a handle to a mutex object if the lpMutexAttributes parameter of CreateMutex() enabled inheritance.

  2. A process can specify the mutex-object handle in a call to the DuplicateHandle() function to create a duplicate handle that can be used by another process.

  3. A process can specify the name of a mutex object in a call to the OpenMutex() or CreateMutex() function.

 

Use the CloseHandle() function to close the handle. The system closes the handle automatically when the process terminates. The mutex object is destroyed when its last handle has been closed. For Windows Me/98/95:  CreateMutexW() is supported by the Microsoft Layer for Unicode. To use this, you must add certain files to your application, as outlined in Microsoft Layer for Unicode on Windows Me/98/95 Systems.

 

ReleaseMutex()

 

Item

Description

Function

ReleaseMutex().

Use

Releases ownership of the specified mutex object.

Prototype

BOOL ReleaseMutex(HANDLE hMutex);

Parameters

hMutex - [in] Handle to the mutex object. The CreateMutex() or OpenMutex() function returns this handle.  The handle must have the MUTEX_MODIFY_STATE access right.

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

The ReleaseMutex() function fails if the calling thread does not own the mutex object.  A thread obtains ownership of a mutex either by creating it with the bInitialOwner parameter set to TRUE or by specifying its handle in a call to one of the wait functions. When the thread no longer needs to own the mutex object, it calls the ReleaseMutex() function so that another thread can acquire ownership. A thread can specify a mutex that it already owns in a call to one of the wait functions without blocking its execution. This prevents a thread from deadlocking itself while waiting for a mutex that it already owns. However, to release its ownership, the thread must call ReleaseMutex() one time for each time that it obtained ownership (either through CreateMutex() or a wait function).

 

Table 20.

 

CreateSemaphore()

 

Item

Description

Function

CreateSemaphore().

Use

Creates or opens a named or unnamed semaphore object.

Prototype

HANDLE CreateSemaphore( LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, LONG lInitialCount, LONG lMaximumCount, LPCTSTR lpName );

Parameters

See below.

Return value

If the function succeeds, the return value is a handle to the semaphore object. If the named semaphore object existed before the function call, the function returns a handle to the existing object and GetLastError() returns ERROR_ALREADY_EXISTS.  If the function fails, the return value is NULL. To get extended error information, call GetLastError().

Include file

<windows.h>

Remark

Implemented as Unicode and ANSI versions. Note that Unicode support on Windows Me/98/95 requires Microsoft Layer for Unicode. More remarks below.

 

Table 21.

 

 

Parameters

 

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

lInitialCount - [in] Initial count for the semaphore object. This value must be greater than or equal to zero and less than or equal to lMaximumCount. The state of a semaphore is signaled when its count is greater than zero and non-signaled when it is zero. The count is decreased by one whenever a wait function releases a thread that was waiting for the semaphore. The count is increased by a specified amount by calling the ReleaseSemaphore() function.

lMaximumCount - [in] Maximum count for the semaphore object. This value must be greater than zero.

lpName - [in] Pointer to a null-terminated string specifying the name of the semaphore object. The name is limited to MAX_PATH characters. Name comparison is case sensitive. If lpName matches the name of an existing named semaphore object, this function requests the SEMAPHORE_ALL_ACCESS access right. In this case, the lInitialCount and lMaximumCount parameters are ignored because they have already been set by the creating process. If the lpSemaphoreAttributes parameter is not NULL, it determines whether the handle can be inherited, but its security-descriptor member is ignored.

If lpName is NULL, the semaphore object is created without a name. If lpName matches the name of an existing event, mutex, waitable timer, job, or file-mapping object, the function fails and the GetLastError() function returns ERROR_INVALID_HANDLE. This occurs because these objects share the same name space. Terminal Services:  The name can have a "Global\" or "Local\" prefix to explicitly create the object in the global or session name space. The remainder of the name can contain any character except the backslash character (\). Windows XP Home Edition:  Fast user switching is implemented using Terminal Services sessions. The first user to log on uses session 0, the next user to log on uses session 1, and so on. Kernel object names must follow the guidelines outlined for Terminal Services so that applications can support multiple users. Windows 2000:  If Terminal Services is not running, the "Global\" and "Local\" prefixes are ignored. The remainder of the name can contain any character except the backslash character. Windows NT:  The name can contain any character except the backslash character. Windows Me/98/95:  The name can contain any character except the backslash character. The empty string ("") is a valid object name.

 

Some Remarks

 

The handle returned by CreateSemaphore() has the SEMAPHORE_ALL_ACCESS access right and can be used in any function that requires a handle to a semaphore object. Any thread of the calling process can specify the semaphore-object handle in a call to one of the wait functions. The single-object wait functions return when the state of the specified object is signaled. The multiple-object wait functions can be instructed to return either when any one or when all of the specified objects are signaled. When a wait function returns, the waiting thread is released to continue its execution. The state of a semaphore object is signaled when its count is greater than zero and non-signaled when its count is equal to zero. The lInitialCount parameter specifies the initial count. Each time a waiting thread is released because of the semaphore's signaled state, the count of the semaphore is decreased by one. Use the ReleaseSemaphore() function to increment a semaphore's count by a specified amount. The count can never be less than zero or greater than the value specified in the lMaximumCount parameter. Multiple processes can have handles of the same semaphore object, enabling use of the object for interprocess synchronization. The following object-sharing mechanisms are available:

  1. A child process created by the CreateProcess() function can inherit a handle to a semaphore object if the lpSemaphoreAttributes parameter of CreateSemaphore() enabled inheritance.

  2. A process can specify the semaphore-object handle in a call to the DuplicateHandle() function to create a duplicate handle that can be used by another process.

  3. A process can specify the name of a semaphore object in a call to the OpenSemaphore() or CreateSemaphore() function.

 

Use the CloseHandle() function to close the handle. The system closes the handle automatically when the process terminates. The semaphore object is destroyed when its last handle has been closed. Windows Me/98/95:  CreateSemaphoreW() is supported by the Microsoft Layer for Unicode. To use this, you must add certain files to your application, as outlined in Microsoft Layer for Unicode on Windows Me/98/95 Systems.

 

ReleaseSemaphore()

 

Item

Description

Function

ReleaseSemaphore().

Use

Increases the count of the specified semaphore object by a specified amount.

Prototype

BOOL ReleaseSemaphore( HANDLE hSemaphore, LONG lReleaseCount, LPLONG lpPreviousCount );

Parameters

hSemaphore - [in] Handle to the semaphore object. The CreateSemaphore() or OpenSemaphore() function returns this handle. This handle must have the SEMAPHORE_MODIFY_STATE access right.

lReleaseCount - [in] Amount by which the semaphore object's current count is to be increased. The value must be greater than zero. If the specified amount would cause the semaphore's count to exceed the maximum count that was specified when the semaphore was created, the count is not changed and the function returns FALSE.

lpPreviousCount - [out] Pointer to a variable to receive the previous count for the semaphore. This parameter can be NULL if the previous count is not required.

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.

 

Some Remarks

 

The state of a semaphore object is signaled when its count is greater than zero and non-signaled when its count is equal to zero. The process that calls the CreateSemaphore() function specifies the semaphore's initial count. Each time a waiting thread is released because of the semaphore's signaled state, the count of the semaphore is decreased by one. Typically, an application uses a semaphore to limit the number of threads using a resource. Before a thread uses the resource, it specifies the semaphore handle in a call to one of the wait functions. When the wait function returns, it decreases the semaphore's count by one. When the thread has finished using the resource, it calls ReleaseSemaphore() to increase the semaphore's count by one.

Another use of ReleaseSemaphore() is during an application's initialization. The application can create a semaphore with an initial count of zero. This sets the semaphore's state to non-signaled and blocks all threads from accessing the protected resource. When the application finishes its initialization, it uses ReleaseSemaphore() to increase the count to its maximum value, to permit normal access to the protected resource. It is not possible to reduce the semaphore object count using ReleaseSemaphore(), because lReleaseCount cannot be a negative number. To temporarily restrict or reduce access, create a loop in which you call the WaitForSingleObject() function with a time-out interval of zero until the semaphore count has been reduced sufficiently. (Note that other threads can reduce the count while this loop is being executed.) To restore access, call ReleaseSemaphore() with the release count equal to the number of times WaitForSingleObject() was called in the loop.

 

OpenSemaphorev()

 

Item

Description

Function

OpenSemaphore().

Use

Opens an existing named semaphore object.

Prototype

HANDLE OpenSemaphore( DWORD dwDesiredAccess, BOOL bInheritHandle, LPCTSTR lpName );

Parameters

See below.

Return value

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

Include file

<windows.h>

Remark

Implemented as Unicode and ANSI versions. Note that Unicode support on Windows Me/98/95 requires Microsoft Layer for Unicode.  The OpenSemaphore() function enables multiple processes to open handles of the same semaphore object. The function succeeds only if some process has already created the semaphore by using the CreateSemaphore() function. The calling process can use the returned handle in any function that requires a handle to a semaphore object, such as the wait functions, subject to the limitations of the access specified in the dwDesiredAccess parameter. The handle can be duplicated by using the DuplicateHandle() function. Use the CloseHandle() function to close the handle. The system closes the handle automatically when the process terminates. The semaphore object is destroyed when its last handle has been closed. For Windows Me/98/95:   OpenSemaphoreW() is supported by the Microsoft Layer for Unicode. To use this, you must add certain files to your application, as outlined in Microsoft Layer for Unicode on Windows Me/98/95 Systems.

 

Table 23.

 

Parameters

 

dwDesiredAccess - [in] Access to the semaphore object. The function fails if the security descriptor of the specified object does not permit the requested access for the calling process.

bInheritHandle - [in] If this parameter is TRUE, a process created by the CreateProcess() function can inherit the handle; otherwise, the handle cannot be inherited.

lpName - [in] Pointer to a null-terminated string that names the semaphore to be opened. Name comparisons are case sensitive.

Terminal Services:  The name can have a "Global\" or "Local\" prefix to explicitly open an object in the global or session name space. The remainder of the name can contain any character except the backslash character (\).

Windows XP Home Edition:  Fast user switching is implemented using Terminal Services sessions. The first user to log on uses session 0, the next user to log on uses session 1, and so on. Kernel object names must follow the guidelines outlined for Terminal Services so that applications can support multiple users. Windows 2000:  If Terminal Services is not running, the "Global\" and "Local\" prefixes are ignored. The remainder of the name can contain any character except the backslash character. Windows NT 4.0 and earlier:  The name can contain any character except the backslash character. Windows Me/98/95:  The name can contain any character except the backslash character. The empty string ("") is a valid object name.

 

CreateNamedPipe()

 

Item

Description

Function

CreateNamedPipe().

Use

Creates an instance of a named pipe and returns a handle for subsequent pipe operations. A named pipe server process uses this function either to create the first instance of a specific named pipe and establish its basic attributes or to create a new instance of an existing named pipe.  Windows Me/98/95:  Named pipes cannot be created.

Prototype

HANDLE CreateNamedPipe( LPCTSTR lpName, DWORD dwOpenMode, DWORD dwPipeMode, DWORD nMaxInstances, DWORD nOutBufferSize, DWORD nInBufferSize, DWORD nDefaultTimeOut, LPSECURITY_ATTRIBUTES lpSecurityAttributes );

Parameters

See below.

Return value

If the function succeeds, the return value is a handle to the server end of a named pipe instance.  If the function fails, the return value is INVALID_HANDLE_VALUE. To get extended error information, call GetLastError().

Include file

<windows.h>

Remark

Implemented as Unicode and ANSI versions.  More remarks below

 

Table 24.

 

Parameters

 

lpName - [in] Pointer to the null-terminated string that uniquely identifies the pipe. The string must have the following form:

\\.\pipe\pipename

The pipename part of the name can include any character other than a backslash, including numbers and special characters. The entire pipe name string can be up to 256 characters long. Pipe names are not case sensitive. Windows Me/98/95:  Pipe names cannot include a colon. Therefore, if this pipe will be used from a Windows Me/98/95 client, do not include a colon in the name.

dwOpenMode - [in] Pipe access mode, the overlapped mode, the write-through mode, and the security access mode of the pipe handle.

CreateNamedPipe() fails if dwOpenMode specifies any flags other than those listed in the following tables.  This parameter must specify one of the following pipe access mode flags. The same mode must be specified for each instance of the pipe.

 

Mode

Meaning

PIPE_ACCESS_DUPLEX

The pipe is bi-directional; both server and client processes can read from and write to the pipe. This mode gives the server the equivalent of GENERIC_READ | GENERIC_WRITE access to the pipe. The client can specify GENERIC_READ or GENERIC_WRITE, or both, when it connects to the pipe using the CreateFile() function.

PIPE_ACCESS_INBOUND

The flow of data in the pipe goes from client to server only. This mode gives the server the equivalent of GENERIC_READ access to the pipe. The client must specify GENERIC_WRITE access when connecting to the pipe.

PIPE_ACCESS_OUTBOUND

The flow of data in the pipe goes from server to client only. This mode gives the server the equivalent of GENERIC_WRITE access to the pipe. The client must specify GENERIC_READ access when connecting to the pipe.

 

Table 25

 

This parameter can also include one or more of the following flags, which enable write-through mode and overlapped mode. These modes can be different for different instances of the same pipe.

 

Mode

Meaning

FILE_FLAG_FIRST_PIPE_INSTANCE

If you attempt to create multiple instances of a pipe with this flag, creation of the first instance succeeds, but creation of the next instance fails with ERROR_ACCESS_DENIED. Windows 2000/NT:  This flag is not supported until Windows 2000 SP2 and Windows XP.

FILE_FLAG_WRITE_THROUGH

Write-through mode is enabled. This mode affects only write operations on byte-type pipes and, then, only when the client and server processes are on different computers. If this mode is enabled, functions writing to a named pipe do not return until the data written is transmitted across the network and is in the pipe's buffer on the remote computer. If this mode is not enabled, the system enhances the efficiency of network operations by buffering data until a minimum number of bytes accumulate or until a maximum time elapses.

FILE_FLAG_OVERLAPPED

Overlapped mode is enabled. If this mode is enabled, functions performing read, write, and connect operations that may take a significant time to be completed can return immediately. This mode enables the thread that started the operation to perform other operations while the time-consuming operation executes in the background. For example, in overlapped mode, a thread can handle simultaneous input and output (I/O) operations on multiple instances of a pipe or perform simultaneous read and write operations on the same pipe handle. If overlapped mode is not enabled, functions performing read, write, and connect operations on the pipe handle do not return until the operation is finished. The ReadFileEx() and WriteFileEx() functions can only be used with a pipe handle in overlapped mode. The ReadFile(), WriteFile(), ConnectNamedPipe(), and TransactNamedPipe() functions can execute either synchronously or as overlapped operations.

 

Table 26

 

This parameter can include any combination of the following security access mode flags. These modes can be different for different instances of the same pipe. They can be specified without concern for what other dwOpenMode modes have been specified.

 

Mode

Meaning

WRITE_DAC

The caller will have write access to the named pipe's discretionary access control list (ACL).

WRITE_OWNER

The caller will have write access to the named pipe's owner.

ACCESS_SYSTEM_SECURITY

The caller will have write access to the named pipe's SACL.

 

Table 27

 

dwPipeMode - [in] Type, read, and wait modes of the pipe handle. One of the following type mode flags can be specified. The same type mode must be specified for each instance of the pipe. If you specify zero, the parameter defaults to byte-type mode.

 

Mode

Meaning

PIPE_TYPE_BYTE

Data is written to the pipe as a stream of bytes. This mode cannot be used with PIPE_READMODE_MESSAGE.

PIPE_TYPE_MESSAGE

Data is written to the pipe as a stream of messages. This mode can be used with either PIPE_READMODE_MESSAGE or PIPE_READMODE_BYTE.

 

Table 28

 

One of the following read mode flags can be specified. Different instances of the same pipe can specify different read modes. If you specify zero, the parameter defaults to byte-read mode.

 

Mode

Meaning

PIPE_READMODE_BYTE

Data is read from the pipe as a stream of bytes. This mode can be used with either PIPE_TYPE_MESSAGE or PIPE_TYPE_BYTE.

PIPE_READMODE_MESSAGE

Data is read from the pipe as a stream of messages. This mode can be only used if PIPE_TYPE_MESSAGE is also specified.

 

Table 29

 

One of the following wait mode flags can be specified. Different instances of the same pipe can specify different wait modes. If you specify zero, the parameter defaults to blocking mode.

 

Mode

Meaning

PIPE_WAIT

Blocking mode is enabled. When the pipe handle is specified in the ReadFile(), WriteFile(), or ConnectNamedPipe() function, the operations are not completed until there is data to read, all data is written, or a client is connected. Use of this mode can mean waiting indefinitely in some situations for a client process to perform an action.

PIPE_NOWAIT

Non-blocking mode is enabled. In this mode, ReadFile(), WriteFile(), and ConnectNamedPipe() always return immediately.

Note that non-blocking mode is supported for compatibility with Microsoft LAN Manager version 2.0 and should not be used to achieve asynchronous I/O with named pipes.

 

Table 30

 

nMaxInstances - [in] Maximum number of instances that can be created for this pipe. The first instance of the pipe can specify this value; the same number must be specified for other instances of the pipe. Acceptable values are in the range 1 through PIPE_UNLIMITED_INSTANCES.

If this parameter is PIPE_UNLIMITED_INSTANCES, the number of pipe instances that can be created is limited only by the availability of system resources. If nMaxInstances is greater than PIPE_UNLIMITED_INSTANCES, the return value is ERROR_INVALID_PARAMETER.

nOutBufferSize - [in] Number of bytes to reserve for the output buffer. For a discussion on sizing named pipe buffers, see the following Remarks section.

nInBufferSize - [in] Number of bytes to reserve for the input buffer. For a discussion on sizing named pipe buffers, see the following Remarks section.

nDefaultTimeOut - [in] Default time-out value, in milliseconds, if the WaitNamedPipe() function specifies NMPWAIT_USE_DEFAULT_WAIT. Each instance of a named pipe must specify the same value.

lpSecurityAttributes - [in] Pointer to a SECURITY_ATTRIBUTES structure that specifies a security descriptor for the new named pipe and determines whether child processes can inherit the returned handle. If lpSecurityAttributes is NULL, the named pipe gets a default security descriptor and the handle cannot be inherited. The ACLs in the default security descriptor for a named pipe grant full control to the LocalSystem account, administrators, and the creator owner. They also grant read access to members of the Everyone group and the anonymous account.

 

Some Remarks

 

To create an instance of a named pipe by using CreateNamedPipe(), the user must have FILE_CREATE_PIPE_INSTANCE access to the named pipe object. If a new named pipe is being created, the access control list (ACL) from the security attributes parameter defines the discretionary access control for the named pipe. All instances of a named pipe must specify the same pipe type (byte-type or message-type), pipe access (duplex, inbound, or outbound), instance count, and time-out value. If different values are used, this function fails and GetLastError() returns ERROR_ACCESS_DENIED. The client side of a named pipe starts out in byte mode, even if the server side is in message mode. To avoid problems receiving data, set the client side to message mode as well. The pipe server should not perform a blocking read operation until the pipe client has started. Otherwise, a race condition can occur. This typically occurs when initialization code, such as the C run-time, needs to lock and examine inherited handles. Every time a named pipe is created, the system creates the inbound and/or outbound buffers using non-paged pool, which is the physical memory used by the kernel. The number of pipe instances (as well as objects such as threads and processes) that you can create is limited by the available non-paged pool. Each read or write request requires space in the buffer for the read or write data, plus additional space for the internal data structures.

The input and output buffer sizes are advisory. The actual buffer size reserved for each end of the named pipe is either the system default, the system minimum or maximum, or the specified size rounded up to the next allocation boundary. The buffer size specified should be small enough that your process will not run out of non-paged pool, but large enough to accommodate typical requests. Whenever a pipe write operation occurs, the system first tries to charge the memory against the pipe write quota. If the remaining pipe write quota is enough to fulfill the request, the write operation completes immediately. If the remaining pipe write quota is too small to fulfill the request, the system will try to expand the buffers to accommodate the data using non-paged pool reserved for the process. The write operation will block until the data is read from the pipe so that the additional buffer quota can be released. Therefore, if your specified buffer size is too small, the system will grow the buffer as needed, but the downside is that the operation will block. If the operation is overlapped, a system thread is blocked; otherwise, the application thread is blocked. An instance of a named pipe is always deleted when the last handle to the instance of the named pipe is closed.

 

CreateFileMapping()

 

Item

Description

Function

CreateFileMapping().

Use

Creates or opens a named or unnamed file mapping object for the specified file.

Prototype

HANDLE CreateFileMapping( HANDLE hFile, LPSECURITY_ATTRIBUTES lpAttributes, DWORD flProtect, DWORD dwMaximumSizeHigh, DWORD dwMaximumSizeLow, LPCTSTR lpName );

Parameters

See below.

Return value

Implemented as Unicode and ANSI versions. Note that Unicode support on Windows Me/98/95 requires Microsoft Layer for Unicode.  If the function succeeds, the return value is a handle to the file mapping object. If the object existed before the function call, the function returns a handle to the existing object (with its current size, not the specified size) and GetLastError() returns ERROR_ALREADY_EXISTS. If the function fails, the return value is NULL. To get extended error information, call GetLastError().

Include file

<windows.h>

Remark

See below.

 

Table 31.

 

Parameters

 

hFile - [in] Handle to the file from which to create a mapping object. The file must be opened with access rights compatible with the protection flags specified by the flProtect parameter. It is recommended, though not required, that files you intend to map be opened for exclusive access. If hFile is INVALID_HANDLE_VALUE, the calling process must also specify a mapping object size in the dwMaximumSizeHigh and dwMaximumSizeLow parameters. In this case, CreateFileMapping() creates a file mapping object of the specified size backed by the operating-system paging file rather than by a named file in the file system. The file mapping object can be shared through duplication, through inheritance, or by name. The initial contents of the pages in the file mapping object are zero.

lpAttributes - [in] Pointer to a SECURITY_ATTRIBUTES structure that determines whether the returned handle can be inherited by child processes. If lpAttributes is NULL, the handle cannot be inherited.

The lpSecurityDescriptor member of the structure specifies a security descriptor for the new file mapping object. If lpAttributes is NULL, the file mapping object gets a default security descriptor. The Access Control Lists (ACLs) in the default security descriptor for a file mapping object come from the primary or impersonation token of the creator. Note that doing this involves potential security risks. To avoid these risks, use a valid SECURITY_ATTRIBUTES structure.

flProtect - [in] Protection desired for the file view, when the file is mapped. This parameter can be one of the following values.

 

Value

Meaning

PAGE_READONLY

Gives read-only access to the committed region of pages. An attempt to write to or execute the committed region results in an access violation. The file specified by the hFile parameter must have been created with the GENERIC_READ access right.

PAGE_READWRITE

Gives read/write access to the committed region of pages. The file specified by hFile must have been created with the GENERIC_READ and GENERIC_WRITE access rights.

PAGE_WRITECOPY

Gives copy-on-write access to the committed region of pages. The files specified by the hFile parameter must have been created with the GENERIC_READ and GENERIC_WRITE access rights.

 

Table 32

 

In addition, an application can specify certain section attributes by combining (using the bitwise OR operator) one or more of the following section attribute values with one of the preceding page protection values.

 

Value

Meaning

SEC_COMMIT

Allocates physical storage in memory or in the paging file on disk for all pages of a section. This is the default setting.

SEC_IMAGE

The file specified for a section's file mapping is an executable image file. Because the mapping information and file protection are taken from the image file, no other attributes are valid with SEC_IMAGE.

Windows Me/98/95:  This flag is not supported.

SEC_NOCACHE

All pages of a section are to be set as non-cacheable. Applications should not use this flag except when explicitly required for a device. Using the interlocked functions with memory mapped by a SEC_NOCACHE section can result in a STATUS_ILLEGAL_INSTRUCTION exception. Note that SEC_NOCACHE requires either the SEC_RESERVE or SEC_COMMIT to also be set.

Windows Me/98/95:  This flag is not supported.

SEC_RESERVE

Reserves all pages of a section without allocating physical storage. The reserved range of pages cannot be used by any other allocation operations until it is released. Reserved pages can be committed in subsequent calls to the VirtualAlloc() function. This attribute is valid only if the hFile parameter is INVALID_HANDLE_VALUE; that is, a file mapping object backed by the operating system paging file.

 

Table 33

 

dwMaximumSizeHigh - [in] High-order DWORD of the maximum size of the file mapping object.

dwMaximumSizeLow - [in] Low-order DWORD of the maximum size of the file mapping object. If this parameter and

dwMaximumSizeHigh are zero, the maximum size of the file mapping object is equal to the current size of the file identified by hFile.

An attempt to map a file with a length of zero in this manner fails with an error code of ERROR_FILE_INVALID. Applications should test for files with a length of zero and reject such files.

lpName - [in] Pointer to a null-terminated string specifying the name of the mapping object. If this parameter matches the name of an existing named mapping object, the function requests access to the mapping object with the protection specified by flProtect. If this parameter is NULL, the mapping object is created without a name. If lpName matches the name of an existing event, semaphore, mutex, waitable timer, or job object, the function fails and the GetLastError() function returns ERROR_INVALID_HANDLE. This occurs because these objects share the same name space. Terminal Services:  The name can have a "Global\" or "Local\" prefix to explicitly create the object in the global or session name space. The remainder of the name can contain any character except the backslash character (\). Windows XP Home Edition:  Fast user switching is implemented using Terminal Services sessions. The first user to log on uses session 0, the next user to log on uses session 1, and so on. Kernel object names must follow the guidelines outlined for Terminal Services so that applications can support multiple users. Windows 2000:  If Terminal Services is not running, the "Global\" and "Local\" prefixes are ignored. The remainder of the name can contain any character except the backslash character. Windows NT:  The name can contain any character except the backslash character. Windows Me/98/95:  The name can contain any character except the backslash character. The empty string ("") is a valid object name.

 

Some Remarks

 

After a file mapping object has been created, the size of the file must not exceed the size of the file mapping object; if it does, not all of the file's contents will be available for sharing. If an application specifies a size for the file mapping object that is larger than the size of the actual named file on disk, the file on disk is grown to match the specified size of the file mapping object. If the file cannot be grown, this results in a failure to create the file mapping object. GetLastError() will return ERROR_DISK_FULL. The handle that CreateFileMapping() returns has full access to the new file mapping object. It can be used with any function that requires a handle to a file mapping object. File mapping objects can be shared either through process creation, through handle duplication, or by name. Windows Me/98/95:  File handles that have been used to create file mapping objects must not be used in subsequent calls to file I/O functions, such as ReadFile() and WriteFile(). In general, if a file handle has been used in a successful call to the CreateFileMapping() function, do not use that handle unless you first close the corresponding file mapping object. Creating a file mapping object creates the potential for mapping a view of the file but does not map the view. The MapViewOfFile() and MapViewOfFileEx() functions map a view of a file into a process's address space.

With one important exception, file views derived from a single file mapping object are coherent, or identical, at a given time. If multiple processes have handles of the same file mapping object, they see a coherent view of the data when they map a view of the file. The exception has to do with remote files. Although CreateFileMapping() works with remote files, it does not keep them coherent. For example, if two computers both map a file as writable, and both change the same page, each computer will only see its own writes to the page. When the data gets updated on the disk, it is not merged. A mapped file and a file accessed by means of the input and output (I/O) functions ( ReadFile() and WriteFile()) are not necessarily coherent. To fully close a file mapping object, an application must unmap all mapped views of the file mapping object by calling UnmapViewOfFile(), and close the file mapping object handle by calling CloseHandle(). The order in which these functions are called does not matter. The call to UnmapViewOfFile() is necessary because mapped views of a file mapping object maintain internal open handles to the object, and a file mapping object will not close until all open handles to it are closed. Terminal Services sessions can use shared memory blocks to transfer data between processes spawned by those sessions. If you do this, keep in mind that shared memory cannot be used in situations where both of the following conditions exist:

  1. All of the processes using the shared memory block were not spawned by one session.

  2. All of the sessions share the same user logon credential.

 

To guard against an access violation, use structured exception handling to protect any code that writes to or reads from a memory mapped view. For Windows Me/98/95:  CreateFileMappingW() is supported by the Microsoft Layer for Unicode. To use this, you must add certain files to your application, as outlined in Microsoft Layer for Unicode on Windows 95/98/Me Systems.

 

Example Code

 

To implement a mapping-object creation function that fails if the object already exists, an application can use the following code.

hMap = CreateFileMapping(...);

 

if (hMap != NULL && GetLastError() == ERROR_ALREADY_EXISTS)

{

    CloseHandle(hMap);

    hMap = NULL;

}

return hMap;

 

 

-----------------------------------------------------Part 3/5-----------------------------------------------------------

 

 

 

 

 

 

 

 

 

 

 

Further reading and digging:

 

  1. Microsoft Visual C++, online MSDN.

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

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

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

 

 

 

 

 

 

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