Why does IsPathRelative return FALSE for paths that are drive-relative?

MSDN distinguishes between fully-qualified and relative paths. According to that discussion:

A file name is relative to the current directory if it does not begin with one of the following:

  • A UNC name,
  • A disk designator with a backslash,
  • A single backslash, for example, "\directory" or "\file.txt". This is also referred to as an absolute path.

If a file name begins with only a disk designator but not the backslash after the colon, it is interpreted as a relative path to the current directory on the drive with the specified letter.

A path is also said to be relative if it contains "double-dots"; that is, two periods together in one component of the path.

Relative paths can combine both example types, for example "C:..\tmp.txt".

Okay, so what exactly is the definition of a relative path?

It's sort of like art. You know it when you see it.

There are some things that are clearly absolute paths. These are known as fully-qualified paths. They specify both a volume designator and a path relative to the root of that volume.

There are also some things that are clearly relative paths, like dir\file.txt.

And then there are these weird intermediate cases that everybody understands but nobody really knows how to classify like C:..\dir\file.txt.

Here's a table of possibilities.

Example Classification IsPathRelative?
\\Server\Share\Dir\File.txt UNC absolute No
C:\Dir\File.txt Drive absolute No
C:Dir\File.txt Drive relative No
\Dir\File.txt Rooted No
Dir\File.txt Relative Yes

The first two rows and the last row are not controversial. The third and fourth rows, on the other hand, are problematic. They live in this shadowy world, half-absolute and half-relative.

Comments (23)
  1. Antonio Rodríguez says:

    For me, the definition of relative path is “any path whose meaning can change if the current directory changes”. With that definition, I’d say that third and fourth rows in the table should be considered relative paths (they depend, respectively, on drive C’s current path, and on the current directory’s drive letter). But, anyway, if the table describes how IsPathRelative() works, it’s not open to discussion. You may not like it, but it just describes how things are.

    That said, I use relative paths whenever I can – it eases installing the software or web app in a different system, with maybe a different directory structure. But I use them only for filesystem objects that are only strictly directly bellow the base, or at most one level above it, and always in the same drive. My programs only generate relative paths in those conditions. Cases three and four are in the gray area, and IMHO, they should be avoided, even if they are perfectly legal. Case three is specially dangerous and open to subtle Heisenbugs.

    1. Kevin says:

      The current drive is not the current directory. Each drive has a different “the current directory”, true, but that doesn’t make the current drive part of “the” (really a) current directory.

      1. Antonio Rodríguez says:

        Actually, in Windows NT, it’s just the opposite way. There is only a current directory. Just one. And it includes the drive letter – which is referred to as the “current drive”. The other drive’s current directories are stored in environment variables, and recalled whenever the process changes the current drive (through a call to SetCurrentDirectory() with just the drive letter as the parameter). All of this emulates the behavior of drives and current directories in MS-DOS 2.0 and up, which in turn was designed to be compatible with MS-DOS 1.0 and CP/M (both lacked support for subdirectories and hard drives).

        Raymond has written a few articles about it:

  2. xcomcmdr says:

    What about cases with .\File.txt.

    I had a program for which I had to use the shim CorrectFilePaths in order to run.

    According to API Monitor, it tried and failed to open files with paths such as “.\scores.dat”

    Meanwhile, I, Bash, and CMD interpret it as a relative path just fine.

    1. Dave Bacher says:

      That would depend on the working directory when the call was made – and so if you, bash and cmd interpret it correctly, it seems likely the program, a plug-in or a loaded library have changed the current working directory for the process. For example, if you launch via a shortcut or a launcher app, that could set the working directory before running the app.

      1. Ted M says:

        Never mind if you run it elevated for compatibility reasons, the current directory is System32

  3. Stéphan Leclercq says:

    If you want to be picky, *all* of the examples are shadowy because they are all relative to something… At least to the (possibly virtual) workstation that tries to access the file. My c:\ drive is not your c:\ drive, my \\contoso\ server is not your \\contoso\ server… It all depends on your point of view.

    Indeed it would be best for the IsPathRelative to actually return the classification column and let the application decide which case is relative and which is absolute.

    1. Antonio Rodríguez says:

      Yes, it’s being too picky :-) . In the Universe, there is no way to set an immutable reference point, so there is no way to strictly talk about “absolutes”. And yet we do it at all times in everyway life. We use all kinds of absolutes (date and time, latitude and longitude, temperature…) which are, in fact, relative to a pair of arbitrarily chosen origin and measurement unit. But maybe I’m getting a bit too philosophical…

    2. florian says:

      There’s an interesting write-up [0] on Win32 paths, and how they are translated to “NT” paths. RtlDetermineDosPathNameType_U seems to be the function to get the classification from Raymond’s table.

      [0] https://googleprojectzero.blogspot.ch/2016/02/the-definitive-guide-on-win32-to-nt.html

  4. skSdnW says:

    I don’t agree with this design. I think most people really just want to know if the path is relative to something (drive or directory) or a full path that does not depend on something else inside the process.

    Does not really belong in the table but “A:B:C” if a fun thing to think about. Does not work in most places but is actually stream C in file B in the current directory of drive A.

    1. Stéphan Leclercq says:

      A: being a floppy drive, it is likely that it uses FAT, which does not support alternate streams :-)

      1. Jan Ringoš says:

        I assign A: and B: to my flash drives and some of them are formatted as NTFS ;)

        1. Ian Yates says:

          I quite like making B: the “backup” drive. Why waste a couple of perfectly good letters? :)

          I feel many network admins just aren’t aware of junction points and the ease with which you can mount volumes in empty NTFS folders. I find it really helpful for those times where some software vendor insists their stuff only works on C:, but there will be a lot of “stuff”. Mount another volume and their app won’t know the difference (99% of the time at least)

    2. Roland Kaufmann says:

      What about “C:D”? Is it stream D in file C in the current directory, or file D in the current directory on drive C? (Most APIs interpret as the latter I guess)

  5. pete.d says:

    Sorry, I could not find in the above the answer to the question “Why does IsPathRelative return FALSE for paths that are drive-relative?”

    I see a table confirming that it does. And I see a quote from MSDN that indicates that such paths *are* relative, even though IsPathRelative() returns FALSE. But no explanation as to WHY this is the case.

  6. Mason Wheeler says:

    > \Dir\File.txt

    All right. Under what circumstances is the Windows API going to interpret this as belonging on a drive other than C: ?

    1. skSdnW says:

      “\dir\file.txt” is in root of the current drive and who says all systems have a “C:”? Back in the DOS days one would do “A:” and then everything was relative to the floppy and “copy \xyz C:” would copy xyz from the root of the A: drive to the current directory of C:.

  7. Andre says:

    What about that double dots comment? Does this mean C:\Dir\..\File.txt is relative? Because it doesn’t look relative to me.

  8. Osxpert says:

    Maybe I’m stupid but I can’t seem to find the explanation on why IsPathRelative (incorrectly) return false for drive relative paths…

  9. cheong00 says:

    Relevent discussions on MSDN forum where someone passing “C:” to DirectoryInfo constructor gets current directory instead of “C:\”, if the EXE locates somewhere in C drive.


    Talking about how path can accidentally treated as type 3 instead of type 2 when you’re not aware of this.

    1. Joshua says:

      That’s because c: is drive relative.

      1. cheong00 says:

        Lo and behold, the special .NET rule is that, even if your application have current working directory on C drive and then it passes “D:”, it’ll still be interpreted as your “current working directory on C drive”.

  10. “It’s sort of like art. You know it when you see it.”

    No, it isn’t. A relative path is one that requires information from outside to successfully resolved (namely, the current folder) and whose meaning can potentially change across different machines or when the structure of a disk changes.

    Also, the third row only works in Command Prompt. I’ve lost the count of how many times I’ve tried to use it and failed.

Comments are closed.

Skip to main content