The Definitive Guide on Win32 to NT Path Conversion (2016)
googleprojectzero.blogspot.com
googleprojectzero.blogspot.com
It's hard to believe that after all these years this is still a problem but I guess a clunky foundation doesn't prevent one from being successful.
now that takes the cake
I prefer to think of it as a contiguous block of null terminated strings terminated by an empty string. (Just as '\0' terminates a C string, the empty string terminates such a list.)
The ugliness might be deliberate, to make developers conclude "that must be some Windows internal BS, probably undocumented" when they see it in debugger, profiler or other places.
Not at all. It is consistently named with internal NT APIs that are used like that intentionally. The people working at that layer follow such naming conventions without irony.
I know, but these are mostly not part of WinAPI either. The public API surface has very good names, WriteFile or CreateDirectory is IMO better than POSIX write or mkdir.
In all seriousness, Ken Thompson was asked what was the one thing we wanted to change in Unix if he could, and his answer was that he would spell "creat" with an "e"[1]. And funnily enough, he actually did in Go[2].
[1]: https://unix.stackexchange.com/questions/10893/what-did-ken-... [2]: https://github.com/golang/go/commit/c90d392ce3d3203e0c32b3f9...
So let's assume there's no time difference between writing the long or short form of that function. There's only one other direction to consider, which is reading.
Try to approach the following question without personal bias. If you have never worked with either API, which function name would be more self-explanatory for you? ConvertStringSecurityDescriptorToSecurityDescriptorA or sec_sddl_to_desc?
But sometimes people confuse unfamiliarity with ugliness, being bad or wrong, and having worked with a lot of these stuff I feel this is often a mischaracterization. Unfamiliarity doesn't always make it bad.
I think the formatting ate the superscript here.
Yeah, I think it did.
Isn't this just a pure bug? I'm quite surprised such an intimidating behavior still exists in today's Windows...
CreateFile is Win32 API, not Native API. NtCreateFile would be Native API.
- The main driver is named C:\ because DOS used A:\ and B:\ for floppy disks! C'mon, floppy disks were not used as the main disk since god knows why (I think even MS-DOS itself was already supposed to run from HDDs and not floppy disks).
- I can't have a file named LPT1, COM, AUX, PRN, NUL, etc. This would be fine, however I can't even have a file named aux.ext, for example. I know this is for compatibility purposes with DOS, however the fact that the error message is terrible does not help.
-255 char limit. I know that you can use an API that allows more characters than this, however this does not work everywhere (last time I remember having problems to access those files in Windows Explorer; I think they fixed this in the latest versions of Windows 10, though).
- Some common characters are prohibit in filenames, like ? or :. Unix has some limitations too, however the Windows are much more ridiculous.
- In 64 bits systems, C:\Windows\SysWoW64\system32 is for 32 bits DLLs, while C:\Windows\system32 is for 64 bits DLLs. I really is curious why Microsoft choose this one, it is not like they needed for legacy software [1] (since 64 bits were new systems not old ones).
I mean, most of the Windows WTFs are for compatibility purposes, however Unix has a much more sensible path rules even if you consider that Unix has much more history than Windows. There is much less WTFs in Unix paths (like /usr/bin vs /bin, or /opt vs. /usr/local).
I can't really understand what is going on with Windows paths. Unix paths are far more sane to me IMO.
[1]: If someone can link to me the reason why I would be thankful. I know that Microsoft engineers are not stupid, I just find it really curious why C:\Windows\system64 was not used, for example.
Oh wait, Windows doesn't have grep.
It was important that programs compiled for a 32-bit windows could run without modifications on a 64-bit windows system. While some amount of 32-bit application recompiles or rewrites was inevitable, a surprising number of them could get by without modifications thanks to Microsoft's emulation & compatibility efforts.
"wow64", or windows on window64, is an emulator of sorts to run 32 bit programs in a 64-bit windows environment with various behavior changes designed to trick 32-bit applications into thinking they were really running on a 32-bit system. The syswow64\system32 thing is one such effort.
If I have a 32-bit program running I may have hard coded paths to files or libraries my program needs. If my program does a fopen("C:\Windows\System32\whatever", mode) expecting to find a dll and it's not there or cannot be opened because that's now where 64-bit dlls live, my program will blow up.
So, when running in wow64 mode, the path "C:\Windows\System32" resolves to "C:\Windows\SysWow64\System32" when running a 32-bit program on 64-bit Windows. When running a 64-bit program, it resolves to what you'd "expect", "C\Windows\System32". That's a strange name for a 64-bit system folder, as you note, but imagine if it were something like system64 -- then if I want to support both 32 & 64 bit systems, I'd need different paths and logic in my program (and it's installer, and in all my tests, and ...) to switch between the two areas for 32-bit and 64-bit systems. By having the folder use the same name (from the program's perspective) everything gets a lot simpler.
This same approach happens when you are looking at Program Files vs Program Files (x86), and in the registry, where HKLM\SOFTWARE\ is 64-bit, while HKLM\SOFTWARE\WOW6432Node\ is for 32-on-64.
This emulation is so complete that it is actually difficult for a 32-bit program with awareness of Microsoft's emulation to actually find the files in SysWow64\System32. If for example, I had an installer program that wants to install my software for both kinds of system, it is difficult if you don't follow best practices and use 2 MSI installers for each bitness and wrap them in a bootstrapping installer program.
I learned all this the hard way, by shipping a 32 & 64 bit windows library. We offer both 32 & 64 bit versions because it has to work with old 32-bit software, even to this day. It is quite confusing but if you squint hard, understand their reasoning and follow it through all the use cases it makes a decent amount of sense.
That said the same library worked on a variety of Linux and Unix-like systems too, and packaging & installation process there was much more straightforward and predictable for me, the developer.
"The 32 is just part of the name and doesn’t mean anything." -- Raymond Chen
The long answer:
"There are quite a number of existing 32-bit programs that hard-code the System32 path rather than calling the GetSystemDirectory function. When these programs are recompiled for 64-bit Windows, they will still try to access the System32 directory, expecting to find 64-bit files (because the program is now compiled 64-bit). Paths written into configuration files or the registry need to be meaningful to both 32-bit and 64-bit processes, yet need to refer to the appropriate directory depending on the “bitness” of the program doing the asking."
https://docs.microsoft.com/en-us/previous-versions/technet-m...
Basically System32 is the system directory regardless of the bitness of the OS. What matters is the bitness of the program being executed. If a 32bit program accesses System32 on a 64bit machine, it's silently redirected to a folder containing 32bit libraries.