Not really answering anything, just throwing wood into the fire and documenting some things from an offline conversation. My perspective, I know that Python's os.path Windows file path handling implementation ends up changing pretty frequently, and pretty much gives up on any sort of resolution if you're not actually on Windows, but there are plenty of places where Python has been very useful, even if it doesn't get it right 100% of the time (Something something systems can be complete or consistent something something). Python also has the newer pathlib library that separates the notion of a "pure path" from a "concrete path", where a pure path is for computation, while a concrete path has I/O operations and makes syscalls, which I think could be used to help alleviate some of this.
Consider something like: C:\Application\Data\Private\Link\.. . If you normalize this, you end up with C:\Application\Data\Private , but Link might be a junction and puts you at D:\ . As such, C:\Application\Data\Private\Link\.. should give you D:\ , but lexical processing gives you C:\Application\Data\Private and you suddenly can end up leaking data.
I don't know about the minifilter, but the junction behavior seems to be generally consistent with symlinks on Unix/Linux. I set up the directory structure (minus the private subdir) on Windows and pointed it at my CMake directory because I don't have a D: drive.
C:\Application\Data>dir
Volume in drive C is Windows
Volume Serial Number is 90F9-FA94
Directory of C:\Application\Data
02/27/2026 01:34 PM <DIR> .
02/27/2026 01:23 PM <DIR> ..
02/27/2026 01:34 PM <JUNCTION> Link [C:\Program Files\CMake]
0 File(s) 0 bytes
3 Dir(s) 598,418,132,992 bytes free
C:\Application\Data>cd C:\Application\Data\Link\..\
C:\Application\Data>dir
Volume in drive C is Windows
Volume Serial Number is 90F9-FA94
Directory of C:\Application\Data
02/27/2026 01:34 PM <DIR> .
02/27/2026 01:23 PM <DIR> ..
02/27/2026 01:34 PM <JUNCTION> Link [C:\Program Files\CMake]
0 File(s) 0 bytes
3 Dir(s) 598,418,132,992 bytes free
Jumping back up one in the command prompt takes you back to C:\Application\Data.
Just to make sure that it's not command prompt being clever, we have this little C program:
#include <stdio.h>
#include <windows.h>
char buffer[1024];
int main(int argc, char** argv) {
buffer[1023] = 0;
const char* directory = "C:\\Application\\Data\\Link\\..\\";
SetCurrentDirectory(directory);
GetCurrentDirectory(1023, buffer);
printf("Current directory: %s", buffer);
return 0;
}
PS C:\Application\Data> clang .\hello.c
PS C:\Application\Data> .\a.exe
Current directory: C:\Application\Data
PS C:\Application\Data>
I know that programs mess up symlinks all of the time, and hard-links are even worse, but I think that as long as you stay away from trying to actually resolve things,
That all said, if you ask the kernel to return the filepath to the file from a file handle, I would expect that to completely ignore symlinks and basically just walk the FS tree from the inode to the root (or however it wants to store that data). Using GetFinalPathNameByHandleA on Windows, struct kinfo_file on FreeBSD, and the /proc/self/fd dance on Linux should (and does seem to) return the fully resolved filepath, which can be confusing if you're using your current directory, which may not be fully resolved.
It looks like Foundation does use this, which raises some questions about how we want to interface this type with the Foundation behavior. Maybe we need to design in separate types for "resolved" vs "unresolved" filepaths? Unresolved filepaths can textually collapse things all day long, but can't be compared with resolved filepaths, which actually need to map to something on the disk. Looking at Python again, the pathlib does kind of have this notion with PurePath being purely a syntactic thing, and Path being an actual "concrete" path. You can use pure paths to construct paths for other operating system, but concrete paths only work on the OS that you're on since they involve making syscalls.