Compartir a través de


PathCchCanonicalizeEx doesn’t actually canonicalize filenames (AKA: Hey Larry, it helps to RTFM).

So I was working on some file path parsing logic the other day and I ran into a problem – I was converting a file name passed in on the command line to a long filename acceptable path (one starting with \\?\. As I mentioned before, the Win32 APIs that accept [\\?\](file://\\?\) filenames assume that the filename specified is a valid path to the filename. That means that filenames with [\\?\](file://\\?\) prefixes cannot have “.” or “..” characters in the filename.

The good news is that there’s a convenient API you can call that handles removing the “.” and “..” filename components – PathCchCanonicalizeEx. As the API documentation states, it “Simplifies a path by removing navigation elements such as "." and ".." to produce a direct, well-formed path.”

What the API documentation doesn’t state (which I unfortunately assumed) was that when presented with a relative pathname, the PathCchCanonicalizeEx API, the PathCchCanonicalizeEx API would convert the relative pathname to an absolute pathname.

Oops.

Note to self: Always read the API documentation. And don’t make assumptions about functionality that isn’t actually there.

Fortunately it appears that contrary to documentation, the PathIsRelative API works just fine in determining if an input filename is relative or absolute. So there’s an easy solution to the problem:

 wstring fileToCanonicalize;
if (PathIsRelative(inputFilename.c_str())
{
    fileToCanonicalize = GetCurrentDirectoryAsString();
    fileToCanonicalize += L"\\";
}
fileToCanonicalize += inputFilename;
PathCchCanonicalizeEx(..., fileToCanonicalize.c_str(), ...);