File and Directory Management
This section introduces the basic functions for file and directory management.
File Management
Windows provides a number of functions, which are generally straightforward, to manage files. The following functions delete, copy, and rename files. There is also a function to create temporary file names.Delete files by specifying the file names. Recall that all absolute pathnames start with a drive letter or a server name. In general it is not possible to delete an open file (it is possible in Windows 9x and UNIX); attempting to do so will result in an error. This limitation can be beneficial as it can prevent an open file from being deleted inadvertently.
BOOL DeleteFile (LPCTSTR lpFileName)
Copy an entire file using a single function.
BOOL CopyFile (
LPCTSTR lpExistingFileName,
LPCTSTR lpNewFileName,
BOOL fFailIfExists)
CopyFile copies the named existing file and assigns the specified new name to the copy. If a file with the new name already exists, it will be replaced only if fFailIfExists is FALSE.Under NT5, it is possible to create a hard link between two files with the CreateHardLink function, which is similar to a UNIX hard link. With a hard link, a file can have two separate names. Note that there is only one file, so a change to the file will be available regardless of which name was used to open the file.
BOOL CreateHardLink (
LPCTSTR lpFileName,
LPCTSTR lpExistingFileName,
BOOL lpSecurityAttributes)
The first two arguments, while in the opposite order, are used as in CopyFile. The two file names, the new name and the existing name, must occur in the same file system volume, but they can be in different directories. The security attributes, if any, apply to the new file name.Close examination of Microsoft documentation shows a "number of links" member field in the BY_HANDLE_FILE_INFO structure, and this link count is used to determine whether or not a file can be deleted. DeleteFile removes the name from the file system directory, but the actual file cannot be deleted until the "number of links" count reaches 0.There is no soft link, although shortcuts are supported by the Windows shells, which interpret the file contents to locate the actual file, but not by Windows. Shortcuts provide soft link-like features, but only to shell users.A pair of functions is available to rename, or "move," a file. These functions also work for directories. (DeleteFile and CopyFile are restricted to files.)
BOOL MoveFile (
LPCTSTR lpExistingFileName,
LPCTSTR lpNewFileName)
BOOL MoveFileEx (
LPCTSTR lpExistingFileName,
LPCTSTR lpNewFileName,
DWORD dwFlags)
MoveFile fails if the new file already exists; use MoveFileEx for existing files. Note the Ex suffix is commonly used to create an enhanced version of an existing function in order to provide additional functionality.
Parameters
lpExistingFileName specifies the name of the existing file or directory.lpNewFileName specifies the new file or directory name, which cannot already exist in the case of MoveFile. A new file can be on a different file system or drive, but new directories must be on the same drive. If NULL, the existing file is deleted.dwFlags specifies options as follows:
- MOVEFILE_REPLACE_EXISTING
Use this option to replace an existing file. - MOVEFILE_WRITETHROUGH
Use this option to ensure that the function does not return until the copied file is flushed through to the disk. - MOVEFILE_COPY_ALLOWED
When the new file is on a different volume, the move is achieved with a CopyFile followed by a DeleteFile. - MOVEFILE_DELAY_UNTIL_REBOOT
This flag, which cannot be used in conjunction with MOVEFILE_COPY_ALLOWED, is restricted to administrators and ensures that the file move does not take effect until the system restarts.
There are a couple of important limitations when you're moving (renaming) files.
- Windows 9x does not implement MoveFileEx; you must perform a CopyFile followed by a DeleteFile. This means that two copies will exist temporarily, which could be a problem with a nearly full disk or a large file. The effect on file time attributes is different from that of a true move.
- Wildcards are not allowed in file or directory names. Specify the actual name.
Directory Management
Creating or deleting a directory involves a pair of simple functions.
BOOL CreateDirectory (
LPCTSTR lpPathName,
LPSECURITY_ATTRIBUTES lpSecurityAttributes)
BOOL RemoveDirectory (LPCTSTR lpPathName)
lpPathName points to a null-terminated string with the name of the directory that is to be created or deleted. The security attributes, as with other functions, should be NULL for the time being; Chapter 15 describes file and object security. Only an empty directory can be removed.A process has a current, or working, directory, just as in UNIX. Furthermore, each individual drive keeps a working directory. The programmer can both get and set the current directory. The first function sets the directory.
BOOL SetCurrentDirectory (LPCTSTR lpPathName)
lpPathName is the path to the new current directory. It can be a relative path or a fully qualified path starting with either a drive letter and colon, such as D:, or a UNC name (such as \\ACCTG_SERVER\PUBLIC).If the directory path is simply a drive name (such as A: or C:), the working directory becomes the working directory on the specified drive. For example, if the working directories are set in the sequence
C:\MSDEV
INCLUDE
A:\MEMOS\TODO
C:
then the resulting working directory will be
C:\MSDEV\INCLUDE
The next function returns the fully qualified pathname into a buffer provided by the programmer.
Return: The string length of the returned pathname, or the required buffer size if the buffer is not large enough; zero if the function fails.
DWORD GetCurrentDirectory (DWORD cchCurDir,
LPTSTR lpCurDir)
cchCurDir is the character (not byte) length of the buffer for the directory name. The length must allow for the terminating null character. lpCurDir points to the buffer to receive the pathname string.Notice that if the buffer is too small for the pathname, the return value tells how large the buffer should be. Therefore, the test for function failure should test both for zero and for the result being larger than the cchCurDir argument.This method of returning strings and their lengths is common in Windows and must be handled carefully. Program 2-6 illustrates a typical code fragment that performs the logic. Similar logic occurs in other examples. The method is not always consistent, however. Some functions return a Boolean, and the length parameter is used twice; it is set with the length of the buffer before the call, and the function changes the value. LookupAccountName in Chapter 15 is one of many examples.An alternative approach, illustrated with the GetFileSecurity function in Program 15-4, is to make two function calls with a buffer memory allocation in between. The first call gets the string length, which is used in the memory allocation. The second call gets the actual string. The simplest approach in this case is to allocate a string holding MAX_PATH characters.
