> "But for real if anyone knows how to get this to work on Windows 10 let me know!"
Since the May 2019 update, Windows 10 has supported declaring the code page in a manifest file.
In Visual Studio, you must add "/utf-8" to the compiler command line, this makes it parse the source code as a UTF-8 file, and makes it output UTF-8 string literals.
To make console output work, call the Win32 function "SetConsoleOutputCP(65001);"
To get support for opening files with names that aren't in your system codepage:
* Add this as an "Additional Manifest File" in Visual Studio project settings for the manifest tool
Additionally, there is an undocumented NTDLL function "RtlInitNlsTables" that sets the code page for the process. It is difficult to use without a lot of example code, but some app locale type tools (used to change locale for a process) make use of this function.
> and finally got the proper support in Windows 10
Not quite, you still can't use some features like longPathAware with the "ANSI" APIs. The preferred APIs for file paths are still the ones using wchar, although the UTF8 codepage is apparently the preferred method for non-path APIs and console IO, at least on the GDK.
> Windows is still like that if you use Win32 APIs directly.
Which is basically the only option for C and C++ developers, when using vanilla Visual Studio, unless they want to write libraries to be consumed by .NET instead, or use a third party framework.
It is either raw Win32 or MFC, don't even bother with WinUI.
Sure, but having used a lot of the windows system apis (admittedly - a lot of years ago) it was a complete hodgepodge of which api would take a char vs a wchar, and then they tried to hide the whole thing behind tchar, which just made it even harder to keep track of.
Basically - I agree: This shouldn't be a problem, and 7 months is a long time to wait for a basic fix. But there are a lot of footguns hanging around in windows code with respect to character encodings.
Which takes a long pointer to tchar string (LPTSTR) - so this behavior is dependent on the unicode settings of the project at compile time, even today.
For Windows this is entirely a compatibility thing. One could imagine a world in which that was not strictly necessary. A good best practice for a Win32 app is to always use 16-bit strings when calling system APIs and pretend the "ANSI" versions don't exist; I would not recommend anything else.
In NT the 8-bit versions generally do nothing but convert to 16-bit and call the "real" function. In recent versions (I think Win7 was the first to do this), AFAIK the 8-bit shims typically exist in another module, so if you don't use them they don't get loaded. In NT on ARM the 8-bit shims are not even there.
> It doubles the space for things like storing identifiers for programming languages
Which is why GetProcAddress() still takes an 8-bit string. Just because the kernel (and hence the syscall interface) uses 16-bit everywhere doesn't mean you can't use 8-bit strings in your own process, or that you can't selectively pick what makes sense for your use.
(By the way, none of what I'm saying is a criticism of UTF-8. I think it's a very clever encoding.)
> Nobody should go out of their way to integrate with Windows APIs
int writeConfigFile(ConfigFile file) {
#if defined(_WIN32)
// Windows-specific function
#elif defined(__linux__)
// Linux-specific function
#elif defined(__APPLE__)
// macOS-specific function
With modern C++, there's probably a way to do this in a nicer manner, and achieve runtime polymorphism with virtual functions or a lambda (function pointer) table.
As another sibling commenter wrote, .NET already has a platform-agnostic function to write to a `user program data` folder that nicely maps to the platform-specific directories. Other GC languages (Java, Go, etc) likely have similar abstractions.
As for scripting... A cross-platform project with scripts that also targets Windows should (in my opinion) have PowerShell `.ps1` scripts accompanying any `.sh` scripts. Better still, scripting should be done in a language that's truly platform-agnostic, like Python.
Thanks! I really should read up on this stuff at some point. I've actually never had to do any windows coding, so my knowledge about it is sorely lacking.
That's not an API. The article talks about some ntdll function, not supported by MS, and not documented by MS.
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.
> Win32 is the style that Windows apps are supposed to be and what people expect in a Windows app.
Maybe in the Windows XP era. None of the built-in apps in Windows 10 look like Win32 apps, apart from legacy stuff that hasn't been ported yet and now looks sorely out of place.
A semi-hidden API like this is a huge benefit to Microsoft itself, and a detriment to its competitors, or indeed, anyone who writes software that becomes a DLL in the next version of Windows.
If you write to a documented API (Win32, GINA, etc) your code is slower and possibly less capable than it could be.
If you write to the undocumented NT-native-API, you have to invest time and effort into understanding it, and risk having it change out from under you at the next rev.
Microsoft internally, and/or favored partners, get to use the faster, capable native API.
So, Windows developers have something of a dilemma to deal with, don't they?
Also, I'm given to understand they're callable as C functions.
He missed off Windows 8; if I'm not mistaken its written primarily in C++? Also the "native" language for programming against the Windows Runtime SDK is C++, although it can easily be consumed by others like .NET and JS.
> Microsoft could certainly make this easier by offering a "wWin32" project that only has the wide version of libraries
Using API functions ending with ...A (for the ANSI version) like CreateFileA is actually rather lowlevel style and means that you know what you do (the same holds for the ...W versions) and explicitly want it this way.
Normally, you use CreateFile and Visual C++ by default sets the proper preprocessor symbols such that CreateFileW will be used. If you pass a char*, you will get compile errors.
In other words: the infrastructure is there to avoid this kind of errors - and it is even used by default. But if you make it explicit in your code that the ANSI version of an API function (CreateFileA) should be used instead of using CreateFile, don't complain that the compiler does obey and this turns out to be a bad idea.
> This new crate is a generator. If this new generator requires access to the .winmd files or .h files from the SDK or whatever, where is the non-Windows builder going to get those from? And will this generator look for them there?
From memory (I haven't done Windows development in forever): there's a few projects that try to provide an open source version of the Windows API headers. The MingW project, for example, has a full set of drop-in replacement headers (meaning you can take code that compiled with Visual C++ and compile it directly with MingW's GCC and it should 'just work'). The LCC-Win64 project has a similar set of headers.
> "Too bad win32 is such a finicky and verbose API that's painful to use for anything beyond the simplest of dialogs. I tried. The MSDN documentation doesn't quite cut it. TheOldNewThing by Raymond Chen is a must-read to get it right."
If it's helpful, I'd like to mention that Charles Petzold's "Programming Windows" has been pretty much the reference for writing Win32 apps since the '90s. (It's the same person that wrote "Code" and "The Annotated Turing".) You probably want the 5th edition as that's the last pure Win32 version; the 6th edition seems to be oriented towards C# based WinRT apps.
> I'd love Microsoft to be a bit more open about what their C runtime actually does before a program linked to it loads. Of course, perhaps they are, and I've missed it.
The source code to the CRT ships with Visual Studio.
> Basically, the entrypoint for Win32 isn't actually WinMain, but WinMainCRTStartup.
The entry point is whatever appears in the PE header and you can name it whatever you want. It just so happens that the default linker settings point it at CRT, which calls into you. You can change this with linker settings.
Since the May 2019 update, Windows 10 has supported declaring the code page in a manifest file.
In Visual Studio, you must add "/utf-8" to the compiler command line, this makes it parse the source code as a UTF-8 file, and makes it output UTF-8 string literals.
To make console output work, call the Win32 function "SetConsoleOutputCP(65001);"
To get support for opening files with names that aren't in your system codepage:
* Create a manifest file as shown in https://learn.microsoft.com/en-us/windows/apps/design /globalizing/use-utf8-code-page
* Add this as an "Additional Manifest File" in Visual Studio project settings for the manifest tool
Additionally, there is an undocumented NTDLL function "RtlInitNlsTables" that sets the code page for the process. It is difficult to use without a lot of example code, but some app locale type tools (used to change locale for a process) make use of this function.
reply