The Windows Process, thread and synchronization: Functions, structures and other related items used in program examples ofWindows Process, Thread & Synchronization 1,Windows Process, Thread & Synchronization 2,Windows Process, Thread & Synchronization 3,Windows Process, Thread & Synchronization 4,Windows Process, Thread & Synchronization 5 andWindows Process, Thread & Synchronization 6, wherever applicable. To learn about function you can jump toC & C++ function tutorials.
The Page Index:
GetEnvironmentStrings()
|
Item | Description |
Function | GetEnvironmentVariable(). |
Use | Retrieves the contents of the specified variable from the environment block of the calling process. The contents are in the form of a null-terminated string of characters. |
Prototype | DWORD GetEnvironmentVariable( LPCTSTR lpName, LPTSTR lpBuffer, DWORD nSize ); |
Parameters | lpName - [in] Pointer to a null-terminated string that specifies the name of the environment variable. lpBuffer - [out] Pointer to a buffer that receives the contents of the specified environment variable. An environment variable has a maximum size limit of 32,767 characters, including the null-terminating character. nSize - [in] Size of the buffer pointed to by the lpBuffer parameter, in bytes. |
Return value | If the function succeeds, the return value is the number of bytes stored in the buffer pointed to bylpBuffer, not including the terminating null character. IflpBuffer is not large enough to hold the data, the return value is the buffer size, in bytes, required to hold the value string and its terminating null character. If the function fails, the return value is zero. If the specified environment variable was not found in the environment block, GetLastError() returns ERROR_ENVVAR_NOT_FOUND. |
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. Windows Me/98/95: GetEnvironmentVariableW() 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 2. |
SetEnvironmentVariable()
Item | Description |
Function | SetEnvironmentVariable(). |
Use | Sets the contents of the specified environment variable for the current process. |
Prototype | BOOL SetEnvironmentVariable(LPCTSTR lpName, LPCTSTR lpValue); |
Parameters | lpName - [in] Pointer to a null-terminated string that specifies the name of the environment variable. The operating system creates the environment variable if it does not exist and lpValue is not NULL. lpValue - [in] Pointer to a null-terminated string that specifies the contents of the environment variable. An environment variable has a maximum size limit of 32,767 characters, including the trailing null terminator. If this parameter is NULL, the variable is deleted from the current process's environment. |
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. Note that Unicode support on Windows Me/98/95 requires Microsoft Layer for Unicode. This function has no effect on the system environment variables or the environment variables of other processes. Windows Me/98/95: SetEnvironmentVariableW() 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 3. |
GetEnvironmentStrings()
Item | Description |
Function | GetEnvironmentStrings(). |
Use | Retrieves the environment variables for the current process. |
Prototype | LPVOID GetEnvironmentStrings(void); |
Parameters | This function has no parameters. |
Return value | If the function succeeds, the return value is a pointer to the environment block of the current process. If the function fails, the return value is NULL. |
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 GetEnvironmentStrings() function returns a pointer to a block of memory that contains the environment variables of the calling process. Treat this memory as read-only; do not modify it directly. To add or change an environment variable, use theGetEnvironmentVariable() and SetEnvironmentVariable() functions. When the block returned by GetEnvironmentStrings() is no longer needed, it should be freed by calling theFreeEnvironmentStrings() function. Windows Me/98/95: GetEnvironmentStringsW() 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 4. |
FreeEnvironmentStrings()
Item | Description |
Function | FreeEnvironmentStrings(). |
Use | Frees a block of environment strings. |
Prototype | BOOL FreeEnvironmentStrings(LPTSTR lpszEnvironmentBlock); |
Parameters | lpszEnvironmentBlock - [in] Pointer to a block of environment strings. The pointer to the block must be obtained by calling theGetEnvironmentStrings() 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 | Implemented as Unicode and ANSI versions. Note that Unicode support on Windows Me/98/95 requires Microsoft Layer for Unicode. Windows Me/98/95: FreeEnvironmentStringsW() 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 5. |
Item | Description |
Function | CreateWaitableTimer(). |
Use | Creates or opens a waitable timer object. |
Prototype | HANDLE CreateWaitableTimer( LPSECURITY_ATTRIBUTES lpTimerAttributes, BOOL bManualReset, LPCTSTR lpTimerName ); |
Parameters | See below. |
Return value | If the function succeeds, the return value is a handle to the timer object. If the named timer object exists 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 6. |
Parameters
lpTimerAttributes - [in] Pointer to a SECURITY_ATTRIBUTES structure that specifies a security descriptor for the new timer object and determines whether child processes can inherit the returned handle. If lpTimerAttributes is NULL, the timer object gets a default security descriptor and the handle cannot be inherited. The ACLs in the default security descriptor for a timer come from the primary or impersonation token of the creator. bManualReset - [in] If this parameter is TRUE, the timer is a manual-reset notification timer. Otherwise, the timer is a synchronization timer. lpTimerName - [in] Pointer to a null-terminated string specifying the name of the timer object. The name is limited to MAX_PATH characters. Name comparison is case sensitive. If lpTimerName is NULL, the timer object is created without a name. If lpTimerName matches the name of an existing event, semaphore, mutex, job, or file-mapping object, the function fails and GetLastError() returnsERROR_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 98/Me: The name can contain any character except the backslash character. The empty string ("") is a valid object name.
Some Remarks
The handle returned by CreateWaitableTimer() is created with the TIMER_ALL_ACCESS access right. This handle can be used in any function that requires a handle to a timer object. Any thread of the calling process can specify the timer object handle in a call to one of the wait functions. Multiple processes can have handles to the same timer object, enabling use of the object for interprocess synchronization.
A process created by the CreateProcess() function can inherit a handle to a timer object if thelpTimerAttributes parameter of CreateWaitableTimer() enables inheritance.
A process can specify the timer object handle in a call to the DuplicateHandle() function. The resulting handle can be used by another process.
A process can specify the name of a timer object in a call to the OpenWaitableTimer() or CreateWaitableTimer() function.
Use the CloseHandle() function to close the handle. The system closes the handle automatically when the process terminates. The timer object is destroyed when its last handle has been closed.Windows Me/98: CreateWaitableTimerW() 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.
Item | Description |
Function | GetStdHandle(). |
Use | Retrieves a handle for the standard input, standard output, or standard error device. |
Prototype | HANDLE GetStdHandle(DWORD nStdHandle); |
Parameters | See below. |
Return value | If the function succeeds, the return value is a handle to the specified device, or a redirected handle set by a previous call to SetStdHandle(). The handle has GENERIC_READ and GENERIC_WRITE access rights, unless the application has usedSetStdHandle() to set a standard handle with lesser access. If the function fails, the return value is INVALID_HANDLE_VALUE. To get extended error information, call GetLastError(). If an application does not have associated standard handles, such as a service running on an interactive desktop, and has not redirected them, the return value is NULL. |
Include file | <windows.h> |
Remark | Handles returned by GetStdHandle() can be used by applications that need to read from or write to the console. When a console is created, the standard input handle is a handle to the console's input buffer, and the standard output and standard error handles are handles of the console's active screen buffer. These handles can be used by theReadFile() and WriteFile() functions, or by any of the console functions that access the console input buffer or a screen buffer (for example, theReadConsoleInput(),WriteConsole(), or GetConsoleScreenBufferInfo() functions). The standard handles of a process may be redirected by a call to SetStdHandle(), in which caseGetStdHandle() returns the redirected handle. If the standard handles have been redirected, you can specify the CONIN$ value in a call to the CreateFile() function to get a handle to a console's input buffer. Similarly, you can specify theCONOUT$ value to get a handle to a console's active screen buffer. |
Table 7. |
Parameters
nStdHandle - [in] Standard device for which a handle is to be returned. This parameter can be one of the following values.
Value | Meaning |
STD_INPUT_HANDLE | Handle to the standard input device. Initially, this is a handle to the console input buffer, CONIN$. |
STD_OUTPUT_HANDLE | Handle to the standard output device. Initially, this is a handle to the active console screen buffer,CONOUT$. |
STD_ERROR_HANDLE | Handle to the standard error device. Initially, this is a handle to the active console screen buffer,CONOUT$. |
Table 8 |
Item | Description |
Function | CreatePipe(). |
Use | Creates an anonymous pipe, and returns handles to the read and write ends of the pipe. |
Prototype | BOOL CreatePipe( PHANDLE hReadPipe, PHANDLE hWritePipe, LPSECURITY_ATTRIBUTES lpPipeAttributes, DWORD nSize); |
Parameters | hReadPipe - [out] Pointer to a variable that receives the read handle for the pipe. hWritePipe - [out] Pointer to a variable that receives the write handle for the pipe. lpPipeAttributes - [in] Pointer to a SECURITY_ATTRIBUTES structure that determines whether the returned handle can be inherited by child processes. If lpPipeAttributes is NULL, the handle cannot be inherited. The lpSecurityDescriptor member of the structure specifies a security descriptor for the new pipe. If lpPipeAttributes is NULL, the pipe gets a default security descriptor. The ACLs in the default security descriptor for a pipe come from the primary or impersonation token of the creator. nSize - [in] Size of the buffer for the pipe, in bytes. The size is only a suggestion; the system uses the value to calculate an appropriate buffering mechanism. If this parameter is zero, the system uses the default buffer size. |
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 | CreatePipe() creates the pipe, assigning the specified pipe size to the storage buffer.CreatePipe() also creates handles that the process uses to read from and write to the buffer in subsequent calls to theReadFile() and WriteFile() functions. To read from the pipe, a process uses the read handle in a call to the ReadFile() function. ReadFile() returns when one of the following is true: a write operation completes on the write end of the pipe, the number of bytes requested has been read, or an error occurs. When a process usesWriteFile() to write to an anonymous pipe, the write operation is not completed until all bytes are written. If the pipe buffer is full before all bytes are written, WriteFile() does not return until another process or thread usesReadFile() to make more buffer space available. Anonymous pipes are implemented using a named pipe with a unique name. Therefore, you can often pass a handle to an anonymous pipe to a function that requires a handle to a named pipe. |
Table 9. |
Item | Description |
Function | DuplicateHandle(). |
Use | Duplicates an object handle. |
Prototype | BOOL DuplicateHandle( HANDLE hSourceProcessHandle, HANDLE hSourceHandle, HANDLE hTargetProcessHandle, LPHANDLE lpTargetHandle, DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwOptions ); |
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 10. |
Parameters
hSourceProcessHandle - [in] Handle to the process with the handle to duplicate. The handle must have the PROCESS_DUP_HANDLE access right. hSourceHandle - [in] Handle to duplicate. This is an open object handle that is valid in the context of the source process. For a list of objects whose handles can be duplicated, see the following Remarks section. hTargetProcessHandle - [in] Handle to the process that is to receive the duplicated handle. The handle must have the PROCESS_DUP_HANDLE access right. lpTargetHandle - [out] Pointer to a variable that receives the duplicate handle. This handle value is valid in the context of the target process. If hSourceHandle is a pseudo handle returned by GetCurrentProcess() or GetCurrentThread(),DuplicateHandle() converts it to a real handle to a process or thread, respectively. If lpTargetHandle is NULL, the function duplicates the handle, but does not return the duplicate handle value to the caller. This behavior exists only for backward compatibility with previous versions of this function. You should not use this feature, as you will lose system resources until the target process terminates. |
dwDesiredAccess - [in] Access requested for the new handle. For the flags that can be specified for each object type, see the following Remarks section. This parameter is ignored if the dwOptions parameter specifies the DUPLICATE_SAME_ACCESS flag. Otherwise, the flags that can be specified depend on the type of object whose handle is to be duplicated.
bInheritHandle - [in] Indicates whether the handle is inheritable. If TRUE, the duplicate handle can be inherited by new processes created by the target process. If FALSE, the new handle cannot be inherited.
dwOptions - [in] Optional actions. This parameter can be zero, or any combination of the following values.
Value | Meaning |
DUPLICATE_CLOSE_SOURCE | Closes the source handle. This occurs regardless of any error status returned. |
DUPLICATE_SAME_ACCESS | Ignores the dwDesiredAccess parameter. The duplicate handle has the same access as the source handle. |
Table 11 |
Some Remarks
The duplicate handle refers to the same object as the original handle. Therefore, any changes to the object are reflected through both handles. For example, the current file mark for a file handle is always the same for both handles. DuplicateHandle() can be called by either the source process or the target process (or a process that is both the source and target process). For example, a process can useDuplicateHandle() to create a non-inheritable duplicate of an inheritable handle, or a handle with different access than the original handle.The source process uses the GetCurrentProcess() function to get a handle to itself. This handle is a pseudo handle, butDuplicateHandle() converts it to a real process handle. To get the target process handle, it may be necessary to use some form of interprocess communication (for example, a named pipe or shared memory) to communicate the process identifier to the source process. The source process can use this identifier in theOpenProcess() function to obtain a handle to the target process. If the process that calls DuplicateHandle() is not also the target process, the source process must use interprocess communication to pass the value of the duplicate handle to the target process. DuplicateHandle() can duplicate handles to the following types of objects.
Object | Description |
Access token | The handle is returned by theCreateRestrictedToken(),DuplicateToken(),DuplicateTokenEx(),OpenProcessToken(), or OpenThreadToken() function. |
Change notification | The handle is returned by theFindFirstChangeNotification() function. |
Communications device | The handle is returned by theCreateFile() function. |
Console input | The handle is returned by theCreateFile() function when CONIN$ is specified, or by the GetStdHandle() function whenSTD_INPUT_HANDLE is specified. Console handles can be duplicated for use only in the same process. |
Console screen buffer | The handle is returned by theCreateFile() function when CONOUT$ is specified, or by the GetStdHandle() function whenSTD_OUTPUT_HANDLE is specified. Console handles can be duplicated for use only in the same process. |
Desktop | The handle is returned by theGetThreadDesktop() function. |
Event | The handle is returned by theCreateEvent() or OpenEvent() function. |
File | The handle is returned by theCreateFile() function. |
File mapping | The handle is returned by theCreateFileMapping() function. |
Job | The handle is returned by theCreateJobObject() function. |
Mailslot | The handle is returned by theCreateMailslot() function. |
Mutex | The handle is returned by theCreateMutex() or OpenMutex() function. |
Pipe | A named pipe handle is returned by the CreateNamedPipe() or CreateFile() function. An anonymous pipe handle is returned by theCreatePipe() function. |
Process | The handle is returned by theCreateProcess(),GetCurrentProcess(), or OpenProcess() function. |
Registry key | The handle is returned by theRegCreateKey(),RegCreateKeyEx(),RegOpenKey(), or RegOpenKeyEx() function. Note that registry key handles returned by theRegConnectRegistry() function cannot be used in a call to DuplicateHandle(). Windows Me/98/95: You cannot use DuplicateHandle to duplicate registry key handles. |
Semaphore | The handle is returned by theCreateSemaphore() or OpenSemaphore() function. |
Socket | The handle is returned by the socket or accept function. |
Thread | The handle is returned by theCreateProcess(),CreateThread(),CreateRemoteThread(), or GetCurrentThread() function |
Timer | The handle is returned by theCreateWaitableTimer() or OpenWaitableTimer() function. |
Window station | The handle is returned by theGetProcessWindowStation() function. |
Table 12 |
Note that DuplicateHandle() should not be used to duplicate handles to I/O completion ports. In this case, no error is returned, but the duplicate handle cannot be used. In addition to STANDARD_RIGHTS_REQUIRED, the following access rights can be specified in the dwDesiredAccess parameter for the different object types:
Desktop Security and Access Rights.
File Security and Access Rights.
File-Mapping Security and Access Rights.
Job Object Security and Access Rights.
Process Security and Access Rights.
Registry Key Security and Access Rights.
Synchronization Object Security and Access Rights.
Thread Security and Access Rights.
Window-Station Security and Access Rights.
In some cases, the new handle can have more access rights than the original handle. However, in other cases, DuplicateHandle() cannot create a handle with more access rights than the original. For example, a file handle created with the GENERIC_READ access right cannot be duplicated so that it has both theGENERIC_READ and GENERIC_WRITE access right.
Item | Description |
Function | GetCurrentProcess(). |
Use | Retrieves a pseudo handle for the current process. |
Prototype | HANDLE GetCurrentProcess(void); |
Parameters | This function has no parameters. |
Return value | The return value is a pseudo handle to the current process. |
Include file | <windows.h> |
Remark | A pseudo handle is a special constant, currently (HANDLE)-1, that is interpreted as the current process handle. For compatibility with future operating systems, it is best to callGetCurrentProcess() instead of hard-coding this constant value. The calling process can use a pseudo handle to specify its own process whenever a process handle is required. Pseudo handles are not inherited by child processes. This handle has the maximum possible access to the process 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 PROCESS_ALL_ACCESS. A process can create a "real" handle to itself that is valid in the context of other processes, or that can be inherited by other processes, by specifying the pseudo handle as the source handle in a call to the DuplicateHandle() function. A process can also use the OpenProcess() function to open a real handle to itself. The pseudo handle need not be closed when it is no longer needed. Calling the CloseHandle() function with a pseudo handle has no effect. If the pseudo handle is duplicated by DuplicateHandle(), the duplicate handle must be closed. |
Table 13. |
Item | Description |
Function | CreateFile(). |
Use | Creates or opens a file, directory, physical disk, volume, console buffer, tape drive, communications resource, mailslot, or named pipe. The function returns a handle that can be used to access the object. Windows Me/98/95: The file system restricts CreateFile() to creating or opening files; you cannot create or open the other objects mentioned above. |
Prototype | HANDLE CreateFile( LPCTSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile ); |
Parameters | See below. |
Return value | If the function succeeds, the return value is an open handle to the specified file. If the specified file exists before the function call and dwCreationDisposition is CREATE_ALWAYS or OPEN_ALWAYS, a call to GetLastError() returns ERROR_ALREADY_EXISTS (even though the function has succeeded). If the file does not exist before the call, GetLastError() returns zero. If the function fails, the return value isINVALID_HANDLE_VALUE. 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 14. |
Parameters
lpFileName - [in] Pointer to a null-terminated string that specifies the name of the object to create or open.
In the ANSI version of this function, the name is limited to MAX_PATH characters. To extend this limit to 32,767 wide characters, call the Unicode version of the function and prepend "\\?\" to the path. Windows Me/98/95: This string must not exceed MAX_PATH characters.
dwDesiredAccess - [in] Access to the object (reading, writing, or both). You cannot request an access mode that conflicts with the sharing mode specified in a previous open request whose handle is still open. If this parameter is zero, the application can query file and device attributes without accessing the device. This is useful if an application wants to determine the size of a floppy disk drive and the formats it supports without requiring a floppy in the drive. It can also be used to test for the file's or directory's existence without opening it for read or write access.
dwShareMode - [in] Sharing mode of the object (reading, writing, both, or neither). You cannot request a sharing mode that conflicts with the access mode specified in a previous open request whose handle is still open. Doing so would result in a sharing violation (ERROR_SHARING_VIOLATION).If this parameter is zero and CreateFile succeeds, the object cannot be shared and cannot be opened again until the handle is closed. To enable other processes to share the object while your process has it open, use a combination of one or more of the following values to specify the access mode they can request when they open the object. These sharing options remain in effect until you close the handle to the object.
Value | Meaning |
FILE_SHARE_DELETE | Enables subsequent open operations on the object to request delete access. Otherwise, other processes cannot open the object if they request delete access. For Windows Me/98/95: This flag is not supported. |
FILE_SHARE_READ | Enables subsequent open operations on the object to request read access. Otherwise, other processes cannot open the object if they request read access. |
FILE_SHARE_WRITE | Enables subsequent open operations on the object to request write access. Otherwise, other processes cannot open the object if they request write access. |
Table 15 |
lpSecurityAttributes - [in] Pointer to a SECURITY_ATTRIBUTES structure that determines whether the returned handle can be inherited by child processes. If lpSecurityAttributes is NULL, the handle cannot be inherited. The lpSecurityDescriptor member of the structure specifies a security descriptor for the object. If lpSecurityAttributes is NULL, the object gets a default security descriptor. The ACLs in the default security descriptor for a file or directory are inherited from its parent directory. Note that the target file system must support security on files and directories for this parameter to have an effect on them. (This is indicated whenGetVolumeInformation() returns FS_PERSISTENT_ACLS).CreateFile() ignores lpSecurityDescriptor when opening an existing file, but continues to use the other structure members.
dwCreationDisposition - [in] Action to take on files that exist, and which action to take when files do not exist. For more information about this parameter, see the Remarks section. This parameter must be one of the following values.
Value | Meaning |
CREATE_ALWAYS | Creates a new file. If the file exists, the function overwrites the file, clears the existing attributes, combines the specified file attributes and flags with FILE_ATTRIBUTE_ARCHIVE, but does not set the security descriptor specified by theSECURITY_ATTRIBUTESstructure. |
CREATE_NEW | Creates a new file. The function fails if the specified file already exists. |
OPEN_ALWAYS | Opens the file, if it exists. If the file does not exist, the function creates the file as ifdwCreationDisposition were CREATE_NEW. |
OPEN_EXISTING | Opens the file. The function fails if the file does not exist. For a discussion of why you should use OPEN_EXISTING for devices, see Remarks. |
TRUNCATE_EXISTING | Opens the file and truncates it so that its size is zero bytes. The calling process must open the file with the GENERIC_WRITE access right. The function fails if the file does not exist. |
Table 16 |
dwFlagsAndAttributes - [in] File attributes and flags. The following file attributes and flags are used only for file objects, not other types of objects created by CreateFile(). When CreateFile() opens an existing file, it combines the file flags with existing file attributes, and ignores any supplied file attributes. This parameter can include any combination of the file attributes (noting that all other file attributes override FILE_ATTRIBUTE_NORMAL).
Attribute | Meaning |
FILE_ATTRIBUTE_ARCHIVE | The file should be archived. Applications use this attribute to mark files for backup or removal. |
FILE_ATTRIBUTE_ENCRYPTED | The file or directory is encrypted. For a file, this means that all data in the file is encrypted. For a directory, this means that encryption is the default for newly created files and subdirectories. This flag has no effect if FILE_ATTRIBUTE_SYSTEM is also specified. |
FILE_ATTRIBUTE_HIDDEN | The file is hidden. It is not to be included in an ordinary directory listing. |
FILE_ATTRIBUTE_NORMAL | The file has no other attributes set. This attribute is valid only if used alone. |
FILE_ATTRIBUTE_NOT_CONTENT_INDEXED | The file will not be indexed by the content indexing service. |
FILE_ATTRIBUTE_OFFLINE | The data of the file is not immediately available. This attribute indicates that the file data has been physically moved to offline storage. This attribute is used byRemote Storage, the hierarchical storage management software. Applications should not arbitrarily change this attribute. |
FILE_ATTRIBUTE_READONLY | The file is read only. Applications can read the file but cannot write to it or delete it. |
FILE_ATTRIBUTE_SYSTEM | The file is part of or is used exclusively by the operating system. |
FILE_ATTRIBUTE_TEMPORARY | The file is being used for temporary storage. File systems avoid writing data back to mass storage if sufficient cache memory is available, because often the application deletes the temporary file shortly after the handle is closed. In that case, the system can entirely avoid writing the data. Otherwise, the data will be written after the handle is closed. |
Table 17 |
This parameter can also include any combination of the following flags.
Flag | Meaning |
FILE_FLAG_BACKUP_SEMANTICS | The file is being opened or created for a backup or restore operation. The system ensures that the calling process overrides file security checks, provided it has theSE_BACKUP_NAME and SE_RESTORE_NAME privileges. You can also set this flag to obtain a handle to a directory. Where indicated, a directory handle can be passed to some functions in place of a file handle. Windows Me/98/95: This flag is not supported. |
FILE_FLAG_DELETE_ON_CLOSE | The system is to delete the file immediately after all of its handles have been closed, not just the specified handle but also any other open or duplicated handles. If there are existing open handles to the file, the call fails unless they were all opened with theFILE_SHARE_DELETE share mode. Subsequent open requests for the file will fail, unless they specify the FILE_SHARE_DELETE share mode. |
FILE_FLAG_NO_BUFFERING | The system is to open the file with no system caching. This flag has no effect on hard disk caching. When combined with FILE_FLAG_OVERLAPPED, the flag gives maximum asynchronous performance, because the I/O does not rely on the synchronous operations of the memory manager. However, some I/O operations will take longer, because data is not being held in the cache. Also, the file metadata may still be cached. To flush the metadata to disk, use the FlushFileBuffers() function. An application must meet certain requirements when working with files opened with FILE_FLAG_NO_BUFFERING: File access must begin at byte offsets within the file that are integer multiples of the volume's sector size. File access must be for numbers of bytes that are integer multiples of the volume's sector size. For example, if the sector size is 512 bytes, an application can request reads and writes of 512, 1024, or 2048 bytes, but not of 335, 981, or 7171 bytes. Buffer addresses for read and write operations should be sector aligned (aligned on addresses in memory that are integer multiples of the volume's sector size). Depending on the disk, this requirement may not be enforced. One way to align buffers on integer multiples of the volume sector size is to use VirtualAlloc() to allocate the buffers. It allocates memory that is aligned on addresses that are integer multiples of the operating system's memory page size. Because both memory page and volume sector sizes are powers of 2, this memory is also aligned on addresses that are integer multiples of a volume's sector size. An application can determine a volume's sector size by calling the GetDiskFreeSpace() function. |
FILE_FLAG_OPEN_NO_RECALL | The file data is requested, but it should continue to reside in remote storage. It should not be transported back to local storage. This flag is intended for use by remote storage systems. |
FILE_FLAG_OPEN_REPARSE_POINT | The system is to inhibit the reparse behavior of NTFS reparse points. When the file is opened, a file handle is returned, whether the filter that controls the reparse point is operational or not. This flag cannot be used with the CREATE_ALWAYS flag. |
FILE_FLAG_OVERLAPPED | The file is being opened or created for asynchronous I/O. When the operation is finished, the event specified to the call in the OVERLAPPED structure is set to the signaled state. Operations that take a significant amount of time to process return ERROR_IO_PENDING. If this flag is specified, the file can be used for simultaneous read and write operations. The system does not maintain the file pointer; therefore you must pass the file position to the read and write functions in the OVERLAPPED structure or update the file pointer. If this flag is not specified, then I/O operations are serialized, even if the calls to the read and write functions specify an OVERLAPPED structure. |
FILE_FLAG_POSIX_SEMANTICS | Indicates that the file is to be accessed according to POSIX rules. This includes allowing multiple files with names, differing only in case, for file systems that support such naming. Use care when using this option because files created with this flag may not be accessible by applications written for MS-DOS or 16-bit Windows. |
FILE_FLAG_RANDOM_ACCESS | Indicates that the file is accessed randomly. The system can use this as a hint to optimize file caching. |
FILE_FLAG_SEQUENTIAL_SCAN | Indicates that the file is to be accessed sequentially from beginning to end. The system can use this as a hint to optimize file caching. If an application moves the file pointer for random access, optimum caching may not occur; however, correct operation is still guaranteed. Specifying this flag can increase performance for applications that read large files using sequential access. Performance gains can be even more noticeable for applications that read large files mostly sequentially, but occasionally skip over small ranges of bytes. |
FILE_FLAG_WRITE_THROUGH | Instructs the system to write through any intermediate cache and go directly to disk. If FILE_FLAG_NO_BUFFERING is not also specified, so that system caching is in effect, then the data is written to the system cache, but is flushed to disk without delay. If FILE_FLAG_NO_BUFFERING is also specified, so that system caching is not in effect, then the data is immediately flushed to disk without going through the system cache. The operating system also requests a write-through the hard disk cache to persistent media. However, not all hardware supports this write-through capability. |
Table 18 |
If the CreateFile() function opens the client side of a named pipe, the dwFlagsAndAttributes parameter can also contain Security Quality of Service information. When the calling application specifies the SECURITY_SQOS_PRESENT flag, the dwFlagsAndAttributes parameter can contain one or more of the following values.
Value | Meaning |
SECURITY_ANONYMOUS | Impersonate the client at the Anonymous impersonation level. |
SECURITY_CONTEXT_TRACKING | The security tracking mode is dynamic. If this flag is not specified, the security tracking mode is static. |
SECURITY_DELEGATION | Impersonate the client at the Delegation impersonation level. |
SECURITY_EFFECTIVE_ONLY | Only the enabled aspects of the client's security context are available to the server. If you do not specify this flag, all aspects of the client's security context are available. This allows the client to limit the groups and privileges that a server can use while impersonating the client. |
SECURITY_IDENTIFICATION | Impersonate the client at the Identification impersonation level. |
SECURITY_IMPERSONATION | Impersonate the client at the Impersonation impersonation level. |
Table 19 |
hTemplateFile - [in] Handle to a template file, with the GENERIC_READ access right. The template file supplies file attributes and extended attributes for the file being created. This parameter can be NULL. If opening an existing file, CreateFile() ignores the template file. Windows Me/98/95: The hTemplateFile parameter must be NULL. If you supply a handle, the call fails and GetLastError() returns ERROR_NOT_SUPPORTED.
Some Remarks
Use the CloseHandle() function to close an object handle returned by CreateFile(). Windows Server 2003, Windows XP, Windows 2000: A sharing violation will occur if an attempt is made to open a file or directory for deletion on a remote computer when the value of the dwDesiredAccess parameter is theDELETE access flag OR'ed with any other access flag, and the remote file or directory has not been opened with FILE_SHARE_DELETE. To avoid the sharing violation in this scenario, open the remote file or directory with theDELETE access right only or call DeleteFile() without first opening the file or directory for deletion. Some file systems, such as NTFS, support compression or encryption for individual files and directories. On volumes formatted for such a file system, a new file inherits the compression and encryption attributes of its directory. You cannot use CreateFile() to control compression on a file or directory.
Windows Server 2003, Windows XP, Windows 2000: For backward compatibility purposes, CreateFile() does not apply inheritance rules when you specify a security descriptor inlpSecurityAttributes. To support inheritance, functions that later query the security descriptor of this object may heuristically determine and report that inheritance is in effect. For Windows Me/98/95: CreateFileW() 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.
Files
If you are attempting to create a file on a floppy drive that does not have a floppy disk or a CD-ROM drive that does not have a CD, the system displays a message box asking the user to insert a disk or a CD, respectively. To prevent the system from displaying this message box, call the SetErrorMode() function with SEM_FAILCRITICALERRORS. Windows Server 2003, Windows XP, Windows 2000: If CREATE_ALWAYS and FILE_ATTRIBUTE_NORMAL are specified, CreateFile() will fail and set the last error to ERROR_ACCESS_DENIED if the file exists and has the FILE_ATTRIBUTE_HIDDEN or FILE_ATTRIBUTE_SYSTEM attribute. To avoid the error, specify the same attributes as the existing file.
If you rename or delete a file, then restore it shortly thereafter, the system searches the cache for file information to restore. Cached information includes its short/long name pair and creation time. Windows Me/98/95: This remark does not apply. If you call CreateFile() on a file that is pending deletion as a result of a previous call toDeleteFile(), the function fails. The operating system delays file deletion until all handles to the file are closed. GetLastError() returns ERROR_ACCESS_DENIED. When an application creates a file across the network, it is better to useGENERIC_READ | GENERIC_WRITE than to use GENERIC_WRITE alone. The resulting code will be faster because the redirector can use the cache manager and send fewer SMBs with more data. This combination also avoids an issue where writing to the file across the network can occasionally returnERROR_ACCESS_DENIED.
Directories
An application cannot create a directory with CreateFile(); it must call CreateDirectory() or CreateDirectoryEx() to create a directory. Opening a directory with CreateFile() requires the FILE_FLAG_BACKUP_SEMANTICS flag. When using CreateFile() to open a directory during defragmentation of a FAT or FAT32 volume, do not specify the MAXIMUM_ALLOWED access right. Access to the directory will be denied if this is done. Specify the GENERIC_READ access right instead.
Physical Disks and Volumes
You can use the CreateFile() function to open a physical disk drive or a volume. The function returns a handle that can be used with the DeviceIoControl() function. This enables you to access the disk's partition table. It is potentially dangerous to do so, since an incorrect write to a disk could make its contents inaccessible. The following requirements must be met for such a call to succeed:
The caller must have administrative privileges.
The dwCreationDisposition parameter must have the OPEN_EXISTING flag.
When opening a volume or floppy disk, the dwShareMode parameter must have the FILE_SHARE_WRITE flag.
When opening a physical drive, x, thelpFileName string should be of the form: \\.\PHYSICALDRIVE<x>
Hard disk numbers start at zero. The following table shows some example physical drive strings.
String | Meaning |
\\.\PHYSICALDRIVE0 | Opens the first physical drive. |
\\.\PHYSICALDRIVE2 | Opens the third physical drive. |
Table |
When opening a volume or floppy drive, the lpFileName string should be of the form: \\.\<x>:
Do not use a trailing backslash. This would indicate the root directory of the drive. The following table shows some example drive strings.
String | Meaning |
\\.\A: | Opens drive A (floppy drive). |
\\.\C: | Opens drive C (volume). |
Table 20 |
You can also open a volume by referring to its volume name. Volume handles may be opened as non-cached at the discretion of the file system, even when the non-cached option is not specified with CreateFile(). You should assume that all Microsoft file systems open volume handles as non-cached. The restrictions on non-cached I/O for files apply to volumes as well. A file system may or may not require buffer alignment even though the data is non-cached. However, if the non-cached option is specified when opening a volume, buffer alignment is enforced regardless of the file system on the volume. It is recommended on all file systems that you open volume handles as non-cached and follow the non-cached I/O restrictions.
Tape Drives
You can open tape drives using a file name of the form: \\.\TAPE<x>. Where <x> is a number indicating which drive to open, starting with tape drive 0. To open tape drive 0 in an application written in C or C++, use the file name "\\\\.\\TAPE0". For Windows Me/98/95: Opening tape drives is not supported.
Communications Resources
The CreateFile() function can create a handle to a communications resource, such as the serial portCOM1. For communications resources, the dwCreationDisposition parameter must be OPEN_EXISTING, and the hTemplate parameter must be NULL. Read, write, or read/write access can be specified, and the handle can be opened for overlapped I/O.
Consoles
The CreateFile() function can create a handle to console input (CONIN$). If the process has an open handle to it as a result of inheritance or duplication, it can also create a handle to the active screen buffer (CONOUT$). The calling process must be attached to an inherited console or one allocated by the AllocConsole() function. For console handles, set the CreateFile() parameters as follows.
Parameters | Value |
lpFileName | Use the CONIN$ value to specify console input and the CONOUT$ value to specify console output. CONIN$ gets a handle to the console's input buffer, even if theSetStdHandle() function redirected the standard input handle. To get the standard input handle, use the GetStdHandle() function. CONOUT$ gets a handle to the active screen buffer, even ifSetStdHandle() redirected the standard output handle. To get the standard output handle, use GetStdHandle(). |
dwDesiredAccess | GENERIC_READ | GENERIC_WRITE is preferred, but either one can limit access. |
dwShareMode | When opening CONIN$, be sure to specify FILE_SHARE_READ. When opening CONOUT$, be sure to specify FILE_SHARE_WRITE. If the calling process inherited the console or if a child process should be able to access the console, this parameter must be FILE_SHARE_READ | FILE_SHARE_WRITE. |
lpSecurityAttributes | If you want the console to be inherited, the bInheritHandle member of the SECURITY_ATTRIBUTES structure must be TRUE. |
dwCreationDisposition | You should specify OPEN_EXISTING when using CreateFile() to open the console. |
dwFlagsAndAttributes | Ignored. |
hTemplateFile | Ignored. |
Table 21 |
The following list shows the effects of various settings of dwDesiredAccess and lpFileName.
lpFileName | dwDesiredAccess | Result |
CON | GENERIC_READ | Opens console for input. |
CON | GENERIC_WRITE | Opens console for output. |
CON | GENERIC_READ GENERIC_WRITE | Causes CreateFile() to fail; GetLastError() returns ERROR_FILE_NOT_FOUND. For Windows Me/98/95: Causes CreateFile() to fail; GetLastError() returns ERROR_PATH_NOT_FOUND. |
Table 22 |
Mailslots
If CreateFile() opens the client end of a mailslot, the function returns INVALID_HANDLE_VALUE if the mailslot client attempts to open a local mailslot before the mailslot server has created it with the CreateMailSlot() function.
Pipes
If CreateFile() opens the client end of a named pipe, the function uses any instance of the named pipe that is in the listening state. The opening process can duplicate the handle as many times as required but, once opened, the named pipe instance cannot be opened by another client. The access specified when a pipe is opened must be compatible with the access specified in the dwOpenMode parameter of the CreateNamedPipe() function.
Item | Description |
Function | ReadFile(). |
Use | Reads data from a file, starting at the position indicated by the file pointer. This function is designed for both synchronous and asynchronous operation. The ReadFileEx() function is designed solely for asynchronous operation. |
Prototype | BOOL ReadFile( HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped ); |
Parameters | See below. |
Return value | The ReadFile() function returns when one of the following conditions is met: a write operation completes on the write end of the pipe, the number of bytes requested has been read, or an error occurs.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 return value is nonzero and the number of bytes read is zero, the file pointer was beyond the current end of the file at the time of the read operation. However, if the file was opened withFILE_FLAG_OVERLAPPED and lpOverlapped is not NULL, the return value is zero andGetLastError() returns ERROR_HANDLE_EOF when the file pointer goes beyond the current end of file. |
Include file | <windows.h> |
Remark | See below. |
Table 23. |
Parameters
hFile - [in] Handle to the file to be read. The file handle must have been created with the GENERIC_READ access right.
For asynchronous read operations, hFile can be any handle opened with the FILE_FLAG_OVERLAPPED flag by the CreateFile() function, or a socket handle returned by the socket or accept function. Windows Me/98/95: For asynchronous read operations, hFile can be a communications resource opened with the FILE_FLAG_OVERLAPPED flag by CreateFile(), or a socket handle returned by socket or accept. You cannot perform asynchronous read operations on mailslots, named pipes, or disk files.
lpBuffer - [out] Pointer to the buffer that receives the data read from the file.
nNumberOfBytesToRead - [in] Number of bytes to be read from the file.
lpNumberOfBytesRead - [out] Pointer to the variable that receives the number of bytes read.ReadFile() sets this value to zero before doing any work or error checking. If this parameter is zero when ReadFile() returns TRUE on a named pipe, the other end of the message-mode pipe called theWriteFile() function with nNumberOfBytesToWrite set to zero. If lpOverlapped is NULL,lpNumberOfBytesRead cannot be NULL. If lpOverlapped is not NULL, lpNumberOfBytesRead can be NULL. If this is an overlapped read operation, you can get the number of bytes read by calling GetOverlappedResult(). If hFile is associated with an I/O completion port, you can get the number of bytes read by callingGetQueuedCompletionStatus().
If I/O completion ports are used and you are using a callback routine to free the memory allocated to the OVERLAPPED structure pointed to by the lpOverlapped parameter, specify NULL as the value of this parameter to avoid a memory corruption problem during the de-allocation. This memory corruption problem will cause an invalid number of bytes to be returned in this parameter. For Windows Me/98/95: This parameter cannot be NULL.
lpOverlapped - [in] Pointer to an OVERLAPPED structure. This structure is required if hFile was created withFILE_FLAG_OVERLAPPED.
If hFile was opened withFILE_FLAG_OVERLAPPED, the lpOverlapped parameter must not be NULL. It must point to a validOVERLAPPED structure. If hFile was created with FILE_FLAG_OVERLAPPED and lpOverlapped is NULL, the function can incorrectly report that the read operation is complete. If hFile was opened withFILE_FLAG_OVERLAPPED and lpOverlapped is not NULL, the read operation starts at the offset specified in theOVERLAPPED structure and ReadFile() may return before the read operation has been completed. In this case,ReadFile() returns FALSE and the GetLastError() function returns ERROR_IO_PENDING. This allows the calling process to continue while the read operation finishes. The event specified in the OVERLAPPED structure is set to the signaled state upon completion of the read operation. The caller must adjust the position of the file pointer upon completion. If hFile was not opened withFILE_FLAG_OVERLAPPED and lpOverlapped is NULL, the read operation starts at the current file position andReadFile() does not return until the operation has been completed. The system updates the file pointer upon completion.
If hFile is not opened withFILE_FLAG_OVERLAPPED and lpOverlapped is not NULL, the read operation starts at the offset specified in theOVERLAPPED structure. ReadFile() does not return until the read operation has been completed. The system updates the file pointer upon completion. Windows 95/98/Me: For operations on files, disks, pipes, or mailslots, this parameter must be NULL; a pointer to an OVERLAPPED structure causes the call to fail. However, you can perform overlapped I/O on serial and parallel ports.
Some Remarks
If part of the file is locked by another process and the read operation overlaps the locked portion, this function fails. An application must meet certain requirements when working with files opened with FILE_FLAG_NO_BUFFERING:
File access must begin at byte offsets within the file that are integer multiples of the volume's sector size. To determine a volume's sector size, call the GetDiskFreeSpace() function.
File access must be for numbers of bytes that are integer multiples of the volume's sector size. For example, if the sector size is 512 bytes, an application can request reads and writes of 512, 1024, or 2048 bytes, but not of 335, 981, or 7171 bytes.
Buffer addresses for read and write operations must be sector aligned (aligned on addresses in memory that are integer multiples of the volume's sector size). One way to sector align buffers is to use the VirtualAlloc() function to allocate the buffers. This function allocates memory that is aligned on addresses that are integer multiples of the system's page size. Because both page and volume sector sizes are powers of 2, memory aligned by multiples of the system's page size is also aligned by multiples of the volume's sector size.
Accessing the input buffer while a read operation is using the buffer may lead to corruption of the data read into that buffer. Applications must not read from, write to, reallocate, or free the input buffer that a read operation is using until the read operation completes. Characters can be read from the console input buffer by using ReadFile() with a handle to console input. The console mode determines the exact behavior of the ReadFile() function.If a named pipe is being read in message mode and the next message is longer than the nNumberOfBytesToRead parameter specifies,ReadFile() returns FALSE and GetLastError() returns ERROR_MORE_DATA. The remainder of the message may be read by a subsequent call to theReadFile() or PeekNamedPipe() function. When reading from a communications device, the behavior ofReadFile() is governed by the current communication time-outs as set and retrieved using the SetCommTimeouts() and GetCommTimeouts() functions. Unpredictable results can occur if you fail to set the time-out values. If ReadFile() attempts to read from a mailslot whose buffer is too small, the function returns FALSE and GetLastError() returns ERROR_INSUFFICIENT_BUFFER. If the anonymous write pipe handle has been closed andReadFile() attempts to read using the corresponding anonymous read pipe handle, the function returns FALSE and GetLastError() returns ERROR_BROKEN_PIPE. The ReadFile() function may fail and return ERROR_INVALID_USER_BUFFER orERROR_NOT_ENOUGH_MEMORY whenever there are too many outstanding asynchronous I/O requests. TheReadFile() code to check for the end-of-file condition (eof) differs for synchronous and asynchronous read operations. When a synchronous read operation reaches the end of a file, ReadFile() returns TRUE and sets *lpNumberOfBytesRead to zero. The following sample code tests for end-of-file for a synchronous read operation:
// Attempt a synchronous read operation.
bResult = ReadFile(hFile, &inBuffer, nBytesToRead, &nBytesRead, NULL) ;
// Check for end of file.
if (bResult && nBytesRead == 0, )
{
// we're at the end of the file
}
An asynchronous read operation can encounter the end of a file during the initiating call to ReadFile(), or during subsequent asynchronous operation. If EOF is detected atReadFile() time for an asynchronous read operation, ReadFile() returns FALSE and GetLastError() returns ERROR_HANDLE_EOF. If EOF is detected during subsequent asynchronous operation, the call toGetOverlappedResult() to obtain the results of that operation returns FALSE andGetLastError() returns ERROR_HANDLE_EOF. To cancel all pending asynchronous I/O operations, use theCancelIo() function. This function only cancels operations issued by the calling thread for the specified file handle. I/O operations that are canceled complete with the error ERROR_OPERATION_ABORTED. If you are attempting to read from a floppy drive that does not have a floppy disk, the system displays a message box prompting the user to retry the operation. To prevent the system from displaying this message box, call the SetErrorMode() function with SEM_NOOPENFILEERRORBOX. The following sample code illustrates testing for end-of-file for an asynchronous read operation:
// set up overlapped structure fields
gOverLapped.Offset = 0;
gOverLapped.OffsetHigh = 0;
gOverLapped.hEvent = hEvent;
// attempt an asynchronous read operation
bResult = ReadFile(hFile, &inBuffer, nBytesToRead, &nBytesRead, &gOverlapped);
// if there was a problem, or the async. operation's still pending...
if (!bResult)
{
// deal with the error code
switch (dwError = GetLastError())
{
case ERROR_HANDLE_EOF:
{
// we have reached the end of the file during the call to ReadFile code to handle that
}
case ERROR_IO_PENDING:
{
// asynchronous i/o is still in progress do something else for a while
GoDoSomethingElse();
// check on the results of the asynchronous read
bResult = GetOverlappedResult(hFile, &gOverlapped, &nBytesRead, FALSE);
// if there was a problem...
if (!bResult)
{
// deal with the error code
switch (dwError = GetLastError())
{
case ERROR_HANDLE_EOF:
{
// we have reached the end of the file during asynchronous operation
}
// deal with other error cases
} // end switch (dwError = GetLastError())
}
} // end case
// deal with other error cases
}// end switch (dwError = GetLastError())
} // end if
---------------------------------------------------Part 4/5-----------------------------------------------------
Further reading and digging:
Microsoft Visual C++, online MSDN.
Structure, enum, union and typedef story can be foundinC struct, enum, typedef etc.
For Multi-bytes, Unicode characters and Localization please refer toUnicode & Multibyte 1 (Story) andUnicode & Multibyte 2 (Implementation).
Check the best selling C / C++ and Windows books at Amazon.com.