Why do some file operations take file names and others take handles?

Raymond Chen

Commenter Brian Friesen asks why some functions (like SetFileAttributes) take a file name, while others (like SetFileTime) take a handle and why we can’t have two versions of every API, one for each pattern.

Second question first: No need to wait for the kernel folks to write such a function; you can already do it yourself!

// Following “pidgin Hungarian” naming convention, which appears
// to be dominant in <winbase.h>…
BOOL SetFileTimesByNameW(LPCWSTR lpFileName,
                         CONST FILETIME *lpCreationTime,
                         CONST FILETIME *lpLastAccessTime,
                         CONST FILETIME *lpLastWriteTime)
{
  BOOL fRc = FALSE;
  HANDLE hFile = CreateFileW(lpFileName,
                             FILE_WRITE_ATTRIBUTES,
                             FILE_SHARE_READ | FILE_SHARE_WRITE |
                             FILE_SHARE_DELETE,
                             NULL, OPEN_EXISTING,
                             FILE_ATTRIBUTE_NORMAL, NULL);
  if (hFile != INVALID_HANDLE_VALUE) {
    fRc = SetFileTime(hFile, lpCreationTime, lpLastAccessTime,
                      lpLastWriteTime);
    CloseHandle(hFile);
  }
  return fRc;
}

Actually, there wouldn’t be two versions of every API but three: (1) handle-based, (2) ANSI, (3) Unicode. (Unless you decide to follow the lead of the NLS team and simply stop adding new ANSI interfaces, in which case you’re back to two.)

Back to the first question: Why are there some functions that take file names and some functions that take handles? Because that’s how MS-DOS did it back in 1983! The function to get file attributes took a file name, but the function to modify the file times took a handle. This convention carried over to Windows because Windows preserved the old MS-DOS calling convention for performing disk operations, even though by Windows for Workgroups was released in 1992, you weren’t really talking to MS-DOS any more. All that was left was the interface.

The NT team rewrote the operating system from scratch, and under the NT model, practically nothing was done by name. Nearly everything was done by handle. For example, to delete a file, you opened a handle to it and set the “delete on close” attribute, and then you closed the handle.

Of course, when NT became Windows NT, they had to adapt their interface to the old Windows way of doing things, although (whisper) under the covers, they just open the file and perform the operation on the handle, like our wrapper function above does.

0 comments

Discussion is closed.

Feedback usabilla icon