Windows System Programming Third Edition


Chapter 3. Advanced File and Directory Processing, and the Registry



Download 3.41 Mb.
Page4/31
Date31.07.2017
Size3.41 Mb.
#24970
1   2   3   4   5   6   7   8   9   ...   31

Chapter 3. Advanced File and Directory Processing, and the Registry


File systems provide more than sequential processing; they must also provide direct access, file locking, directory processing, and file attribute management. Starting with direct file access, which is required by database, file management, and many other systems, this chapter shows how to manage file pointers to access files at any location. In particular, it is necessary to show how to use Windows' 64-bit file pointers, because the NTFS can support huge files.

The next step is to show how to scan directory contents and how to manage and interpret file attributes, such as time stamps, access, and size. Finally, file locking protects files from concurrent modification by more than one process.

The final topic is the Windows registry, a centralized database that contains configuration information for applications and for the system itself. Registry access functions and program structure are similar to the file and directory management functions, as shown by the final program example, so this short topic is included at the chapter's end rather than creating a separate chapter for it.

The 64-Bit File System


Win32 and Win64, with the NTFS, support 64-bit file addresses so that files can, in principle, be as long as 264 bytes.

The 232-byte length limit of 32-bit file systems constrains file lengths to 4GB (4 x 109 bytes). This limit is a serious constraint with some applications, including large database and multimedia systems, so any complete modern OS must support much larger files. Files larger than 4GB are sometimes called huge files.

Needless to say, many applications will never need huge files, so, for many programmers, 32-bit file addresses will be adequate for years to come. It is, however, a good idea to start working with 64-bit addresses from the beginning of a new development project, given the rapid pace of technical change and disk capacity growth,[1] cost improvements, and application requirements.

[1] At the time this is being written, even inexpensive laptop systems contain 40GB or more of disk capacity, so files larger than 4GB are possible and sometimes necessary, even on small systems.

Win32, despite the 64-bit file addresses and the support for huge files, is still a 32-bit OS API because of its 32-bit memory addressing, as discussed in Chapter 5; Win64 is required for 64-bit memory addresses.

прямоугольник 13

File Pointers


Windows, just like UNIX, the C library, and nearly every other OS, maintains a file pointer with each open file handle, indicating the current byte location in the file. The next WriteFile or ReadFile operation will start transferring data sequentially to or from that location and increment the file pointer by the number of bytes transferred. Opening the file with CreateFile sets the pointer to zero, indicating the start of the file, and the handle's pointer is advanced with each successive read or write. The crucial operation required for direct file access is the ability to set the file pointer to an arbitrary value, using SetFilePointer.

SetFilePointer shows, for the first time, how Windows handles the 64-bit NTFS. The techniques are not always pretty with this function, and SetFilePointer is easiest to use with small files.

DWORD SetFilePointer (

HANDLE hFile,

LONG lDistanceToMove,

PLONG lpDistanceToMoveHigh,

DWORD dwMoveMethod)

Return: The low-order DWORD (unsigned) of the new file pointer. The high-order portion of the new file pointer goes to the DWORD indicated by lpDistanceToMoveHigh (if non-NULL). In case of error, the return value is 0xFFFFFFFF.


Parameters


hFile is the handle of an open file with read or write access (or both).

lDistanceToMove is the 32-bit LONGsigned distance to move or unsigned file position, depending on the value of dwMoveMethod.

lpDistanceToMoveHigh points to the high-order portion of the move distance. If this value is NULL, the function can operate only on files whose length is limited to 2322. This parameter is also used to receive the high-order return value of the file pointer.[2] The low-order portion is the function's return value.

[2] Windows is not consistent, as can be seen by comparing SetFilePointer with GetCurrentDirectory. In some cases, distinct input and output parameters are used.

dwMoveMethod specifies one of three move modes.


  • FILE_BEGIN: Position the file pointer from the start of the file, interpreting DistanceToMove as unsigned.

  • FILE_CURRENT: Move the pointer forward or backward from the current position, interpreting DistanceToMove as signed. Positive is forward.

  • FILE_END: Position the pointer backward or forward from the end of file.

It is possible to use this function to obtain the file length by specifying a zero-length move from the end of file.

The method of representing 64-bit file positions causes complexities because the function return can represent both a file position and an error code. For example, suppose that the actual position is location 2321 (that is, 0xFFFFFFFF) and that the call also specifies the high-order move distance. Invoke GetLastError to determine whether the return value is a valid file position or whether the function failed, in which case the return value would not be NO_ERROR. This explains why file lengths are limited to 2322 when the high-order component is omitted.

Another confusing factor is that the high- and low-order components are separated and treated differently. The low-order address is treated as a call by value and returned by the function, whereas the high-order address is a call by reference and is both input and output.

Fortunately, 32-bit file addresses are sufficient for most programming tasks. Nonetheless, the programming examples take the long view and "do it right" using 64-bit arithmetic.


64-Bit Arithmetic


It is not difficult to perform the 64-bit file pointer arithmetic, and our example programs use Microsoft C's LARGE_INTEGER 64-bit data type, which is a union of a LONGLONG (called QuadPart) and two 32-bit quantities (LowPart, a DWORD, and HighPart, a LONG). LONGLONG supports all the arithmetic operations. There is also a ULONGLONG, which is unsigned.

lseek (in UNIX) and fseek (in the C library) are similar to SetFilePointer. Both systems also advance the file position during read and write operations.


Specifying File Position with an Overlapped Structure


Windows provides another way to set the file position that does not require SetFilePointer. Recall that the final parameter to both ReadFile and WriteFile is the address of an overlapped structure, and this value has always been NULL in the previous examples. Two members of this structure are Offset and OffsetHigh. You can set the appropriate values in an overlapped structure, and the I/O operation can start at the specified location. The file pointer is changed to point past the last byte transferred, but the overlapped structure values are not changed. The overlapped structure also has a handle member, hEvent, that must be set to NULL. Note: This technique will not work with Windows 9x as the overlapped pointer must be NULL when processing files.

Caution: Even though this example uses an overlapped structure, this is not overlapped I/O, which is covered in Chapter 14.

The overlapped structure is especially convenient when updating a file record, as illustrated in the following code fragment; otherwise, separate SetFilePointer calls would be required before the ReadFile and WriteFile calls. The hEvent field is the last of five fields, as is shown in the initialization statement. The LARGE_INTEGER data type is used to compute the file position.

OVERLAPPED ov = { 0, 0, 0, 0, NULL };

RECORD r; /* Definition not shown

but it includes the RefCount field. */

LONGLONG n;

LARGE_INGETER FilePos;

DWORD nRead, nWrite;

...


/* Update the reference count in the nth record. */

FilePos.QuadPart = n * sizeof (RECORD);

ov.Offset = FilePos.LowPart;

ov.OffsetHigh = FilePos.HighPart;

ReadFile (hFile, r, sizeof (RECORD), &nRead, &ov);

r.RefCount++; /* Update the record. */

WriteFile (hFile, r, sizeof (RECORD), &nWrite, &ov);

If the file handle was created with the FILE_FLAG_NO_BUFFERING CreateFile flag, then both the file position and the record size (byte count) must be multiples of the disk volume's sector size. Physical disk information, including sector size, is returned by GeTDiskFreeSpace.

Overlapped structures will be used again later in this chapter to specify file lock regions and in Chapter 14 for asynchronous I/O and direct file access.




Directory: bitstream -> NAU
bitstream -> A mathematical theory of communication
bitstream -> Images of Fairfax in Modern Literature and Film Andrew Hopper
bitstream -> Amphitheater High School’s Outdoor Classroom: a study in the Application of Design
bitstream -> Ethics of Climate Change: Adopting an Empirical Approach to Moral Concern
bitstream -> The Age of Revolution in the Indian Ocean, Bay of Bengal and South China Sea: a maritime Perspective
bitstream -> Methodism and Culture
bitstream -> Review of coastal ecosystem management to improve the health and resilience of the Great Barrier Reef World Heritage Area
bitstream -> Present state of the area
NAU -> International significance of icao alphabet for flight safety
NAU -> Performance comparison of android runtime and dalvik environments on an android device

Download 3.41 Mb.

Share with your friends:
1   2   3   4   5   6   7   8   9   ...   31




The database is protected by copyright ©ininet.org 2024
send message

    Main page