The Windows Disk Management 9








If you rename or delete a file and then restore it shortly afterward, the system searches the cache for file information to restore. Cached information includes its short/long name pair and creation time. If you call CreateFile() on a file that is pending deletion as a result of a previous call to DeleteFile(), the function fails. The operating system delays file deletion until all handles to the file are closed. GetLastError() returns ERROR_ACCESS_DENIED.

The dwDesiredAccess parameter can be zero, allowing the application to query file attributes without accessing the file if the application is running with adequate security settings. This is useful to test for the existence of a file without opening it for read and/or write access, or to obtain other statistics about the file or directory. For Windows Server 2003 and Windows XP/2000:  If CREATE_ALWAYS and FILE_ATTRIBUTE_NORMAL are specified, CreateFile() fails and sets 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. When an application creates a file across a network, it is better to use GENERIC_READ | GENERIC_WRITE for dwDesiredAccess than to use GENERIC_WRITE alone. The resulting code is 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 a file across a network can occasionally return ERROR_ACCESS_DENIED.


Synchronous and Asynchronous I/O Handles


CreateFile() provides for creating a file or device handle that is either synchronous or asynchronous. A synchronous handle behaves such that I/O function calls using that handle are blocked until they complete, while an asynchronous file handle makes it possible for the system to return immediately from I/O function calls, whether they completed the I/O operation or not. As stated previously, this synchronous versus asynchronous behavior is determined by specifying FILE_FLAG_OVERLAPPED within the dwFlagsAndAttributes parameter. There are several complexities and potential pitfalls when using asynchronous I/O;


File Streams


On NTFS file systems, you can use CreateFile() to create separate streams within a file.




An application cannot create a directory by using CreateFile(), therefore only the OPEN_EXISTING value is valid for dwCreationDisposition for this use case. To create a directory, the application must call CreateDirectory() or CreateDirectoryEx(). To open a directory using CreateFile(), specify the FILE_FLAG_BACKUP_SEMANTICS flag as part of dwFlagsAndAttributes. Appropriate security checks still apply when this flag is used without SE_BACKUP_NAME and SE_RESTORE_NAME privileges. When using CreateFile() to open a directory during defragmentation of a FAT or FAT32 file system volume, do not specify the MAXIMUM_ALLOWED access right. Access to the directory is denied if this is done. Specify the GENERIC_READ access right instead.


Physical Disks and Volumes


Direct access to the disk or to a volume is restricted. For more information, see "Changes to the file system and to the storage stack to restrict direct disk access and direct volume access in Windows Vista and in Windows Server 2008" in the Help and Support Knowledge Base at Changes to the file system and to the storage stack to restrict direct disk access and direct volume access in Windows Vista and in Windows Server 2008.

For Windows Server 2003 and Windows XP/2000 the direct access to the disk or to a volume is not restricted in this manner. You can use the CreateFile() function to open a physical disk drive or a volume, which returns a direct access storage device (DASD) handle that can be used with the DeviceIoControl() function. This enables you to access the disk or volume directly, for example such disk metadata as the partition table. However, this type of access also exposes the disk drive or volume to potential data loss, because an incorrect write to a disk using this mechanism could make its contents inaccessible to the operating system. To ensure data integrity, be sure to become familiar with DeviceIoControl() and how other APIs behave differently with a direct access handle as opposed to a file system handle. The following requirements must be met for such a call to succeed:


  1. The caller must have administrative privileges.
  2. The dwCreationDisposition parameter must have the OPEN_EXISTING flag.
  3. When opening a volume or floppy disk, the dwShareMode parameter must have the FILE_SHARE_WRITE flag.


Take note that the dwDesiredAccess parameter can be zero, allowing the application to query device attributes without accessing a device. This is useful for an application to determine the size of a floppy disk drive and the formats it supports without requiring a floppy disk in a drive, for instance. It can also be used for reading statistics without requiring higher-level data read/write permission. When opening a physical drive x, the lpFileName string should be the following form: \\.\PhysicalDriveX. Hard disk numbers start at zero. The following table shows some examples of physical drive strings.





Opens the first physical drive.


Opens the third physical drive.


To obtain the physical drive identifier for a volume, open a handle to the volume and call the DeviceIoControl() function with IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS. This control code returns the disk number and offset for each of the volume's one or more extents; a volume can span multiple physical disks. When opening a volume or removable media drive (for example, a floppy disk drive or flash memory thumb drive), the lpFileName string should be the following form: \\.\X:. Do not use a trailing backslash (\), which indicates the root directory of a drive. The following table shows some examples of drive strings.





Opens floppy disk drive A.


Opens the C: volume.


Opens the file system of the C: volume.


You can also open a volume by referring to its volume name. A volume contains one or more mounted file systems. Volume handles can be opened as noncached at the discretion of the particular file system, even when the noncached option is not specified in CreateFile(). You should assume that all Microsoft file systems open volume handles as noncached. The restrictions on noncached I/O for files also apply to volumes.

A file system may or may not require buffer alignment even though the data is noncached. However, if the noncached 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 noncached, and follow the noncached I/O restrictions. To read or write to the last few sectors of the volume, you must call DeviceIoControl() and specify FSCTL_ALLOW_EXTENDED_DASD_IO. This signals the file system driver not to perform any I/O boundary checks on partition read or write calls. Instead, boundary checks are performed by the device driver.


Changer Device


The IOCTL_CHANGER_* control codes for DeviceIoControl() accept a handle to a changer device. To open a changer device, use a file name of the following form: \\.\Changerx where x is a number that indicates which device to open, starting with zero. To open changer device zero in an application that is written in C or C++, use the following file name: "\\\\.\\Changer0".


Tape Drives


You can open tape drives by using a file name of the following form: \\.\TAPEx where x is a number that indicates which drive to open, starting with tape drive zero. To open tape drive zero in an application that is written in C or C++, use the following file name: "\\\\.\\TAPE0".


Communications Resources


The CreateFile() function can create a handle to a communications resource, such as the serial port COM1. For communications resources, the dwCreationDisposition parameter must be OPEN_EXISTING, the dwShareMode parameter must be zero (exclusive access), and the hTemplateFile parameter must be NULL. Read, write, or read/write access can be specified, and the handle can be opened for overlapped I/O. To specify a COM port number greater than 9, use the following syntax: "\\.\COM10". This syntax works for all port numbers and hardware that allows COM port numbers to be specified.




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.





Use the CONIN$ value to specify console input. Use the CONOUT$ value to specify console output. CONIN$ gets a handle to the console input buffer, even if the SetStdHandle() function redirects the standard input handle. To get the standard input handle, use the GetStdHandle() function.

CONOUT$ gets a handle to the active screen buffer, even if SetStdHandle() redirects the standard output handle. To get the standard output handle, use GetStdHandle().


GENERIC_READ | GENERIC_WRITE is preferred, but either one can limit access.


When opening CONIN$, specify FILE_SHARE_READ. When opening CONOUT$, specify FILE_SHARE_WRITE.

If the calling process inherits the console, or if a child process should be able to access the console, this parameter must be FILE_SHARE_READ | FILE_SHARE_WRITE.


If you want the console to be inherited, the bInheritHandle member of the SECURITY_ATTRIBUTES structure must be TRUE.


You should specify OPEN_EXISTING when using CreateFile() to open the console.






The following table shows various settings of dwDesiredAccess and lpFileName.







Opens console for input.



Opens console for output.



Causes CreateFile() to fail; GetLastError() returns ERROR_FILE_NOT_FOUND.




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.




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 after it is opened, the named pipe instance cannot be opened by another client. The access that is specified when a pipe is opened must be compatible with the access that is specified in the dwOpenMode parameter of the CreateNamedPipe() function. If the CreateNamedPipe() function was not successfully called on the server prior to this operation, a pipe will not exist and CreateFile() will fail with ERROR_FILE_NOT_FOUND. If there is at least one active pipe instance but there are no available listener pipes on the server, which means all pipe instances are currently connected, CreateFile() fails with ERROR_PIPE_BUSY.





< Windows Disk 8 | Win32 Programming Index Page | Windows Disk Index | Windows Disk 10 >