13 ms·
Microsoft_craziness.h (2018)
- tmaly 5y agoI am just curious why are there functions/code in a .h file?
- rytcio 5y agoThis is a single file library. To include it in a project, in the header you put: #include "Microsoft_craziness.h"` Then in a c/cpp file: #define MICROSOFT_CRAZINESS_IMPLEMENTATION #include "Microsoft_craziness.h" The define causes the actual functions to be put in, while without it only the declarations are included.
- tentacleuno 5y agoThis file was about 400 lines before we started adding these comments. You might think that's way too much code to do something as simple as finding a few library and executable paths. I agree. However, Microsoft's own solution to this problem, called "vswhere", is a mere EIGHT THOUSAND LINE PROGRAM, spread across 70 files, that they posted to github unironically. I am not making this up: https://github.com/Microsoft/vswhere https://github.com/Microsoft/vswhere Such a seemingly simple problem and yet we have two very complicated solutions. Just goes to show how convoluted things can get at Microsoft scale.
- alexfromapex 5y agoReminds me of something I read earlier mentioning "design by consortium" where the complexity of something goes up because there's so many people working on it and not enough straightforward documentation
- shadowgovt 5y agoAnd sometimes (which is I think what most applies to Microsoft) too many authorities that must be pleased and nobody with imperial power to say "In the interests of simplifying, we're going to piss off key stakeholders for a period of time." Microsoft's OS team has, at points in the past, rebuilt data structures from C++ to C with very specific memory footprints rather than break, for example, Photoshop (which was getting more performance from running its own OS structure allocator instead of calling the APIs designed to allocate structures). Simple ecosystems and simple software usually have the same thing in common: they are either young, or they've recently survived an extinction-level-event. Older systems with many dynamic constraints breed complex webs.
- joe-collins 5y ago> Simple ecosystems and simple software usually have the same thing in common: they are either young, or they've recently survived an extinction-level-event. Older systems with many dynamic constraints breed complex webs. At the risk of digression, I wish some of the "small government" crowd would realize this.
- tompazourek 5y agoYes, the important keyword here is "seemingly". :)
- ChrisSD 5y ago`vswhere` is for querying a variety of information about all visual studio installs. It does far more than the "simple" problem of finding libraries.
- 323 5y agoBut how do you find vswhere? I have VS installed on my system, yet vswhere is not in PATH.
- Spivak 5y ago> vswhere is included with the installer as of Visual Studio 2017 version 15.2 and later, and can be found at the following location: %ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe The irony is that there is absolutely no guarantee that this path is stable so in 2025 I'm sure there will be a wherevswhere.exe
- ChrisSD 5y agoThere is a guarantee that this path is stable: https://github.com/Microsoft/vswhere/wiki/Installing https://github.com/Microsoft/vswhere/wiki/Installing > This is a fixed location that will be maintained.
- glandium 5y ago"Windows 10 will be the last Windows". Guarantees work as long as they don't change their mind.
- ziml77 5y agoFind me one place where Microsoft officially documented that there would be no version of Windows past 10.
- chrismorgan 5y ago
- grammarnazzzi 5y ago> Just goes to show how convoluted things can get at Microsoft scale. It's not so much a problem of "scale" as simply poor architecture, neglected technical debt and outright incompetance
- throwawaywindev 5y agoThat’s why you use COM or WinRT with strong contracts.
- pjc50 5y agoDoesn't help you when what you need is MSVCRT.
- AlanYx 5y ago>"apparently, not all valid Windows file paths can even be converted correctly to UTF-8" What is the author referring to here?
- reubenmorais 5y agoWindows paths can contain unpaired UTF-16 surrogates, which are not representable in UTF-8.
- deleted 5y ago[deleted]
- masklinn 5y agoWindows paths are sequences of utf-16 code units, so they can contain unpaired surrogates which are not legal in unicode (and therefore UTF-8). That’s why on windows Rust’s OsStr is an extension of UTF8 called WTF8, which allows surrogates (then again “traditional” unix paths are just bags of bytes so it’s not like windows is any worse).
- ChrisSD 5y agoWindows is actually quite a bit better. The APIs require you to use an encoding. The multibyte `A` APIs can be whatever encoding the current process is using and will be automatically converted to valid UTF-16. The `W` APIs are for UTF-16. The issue is the latter does not enforce valid UTF-16. So in practice the only way invalid UTF-16 shows up is from malicious programs (or people testing their handling of non-unicode).
- fredoralive 5y agoThe W mode was the only way to do Unicode until relatively recently, A was just legacy pre-Unicode encodings. So there's presumbably a fair chance for older Unicode apps to accidentally mess up the encoding, especially if it's really old stuff from back during the UCS2 era which didn't have paired wide characters (although I suspect at that time most stuff would use A functions in order to work on Windows 9x).
- Aardwolf 5y agoSomething I always wondered about Visual Studio and Windows programming: If you compile a C++ program with Visual Studio, it gets dynamic dependencies on some visual studio DLLs. DLLs that are not necessarily installed by default on the Windows of the target user you're compiling for. So the question is: MS created both Windows and Visual Studio. So why can't Visual Studio compile to something that works by default on the Windows of the target audience without requiring them to install those additional DLLs? Doesn't the win32 API provide enough, and can't Visual Studio statically link in whatever extras it needs, or those extras be added to the Windows API that is present by default if they're that necessary? Also, given that Windows comes with pre-installed programs that were written in C++, how did those programs get compiled to not require those Visual Studio dependencies, are MS not using Visual Studio themselves internally?
- ChrisSD 5y ago> can't Visual Studio statically link in whatever extras it needs It can but you have to change some options (`/MT` iirc). And if you want to be really minimalist you only need to statically link the runtime (if you avoid using the C++ standard library).
- quietbritishjim 5y agoThe slight trickiness with this is that if you have any C/C++ libraries that you link into your application, then you need to static link those too. The problem with dynamically linking against a library while statically linking against VS runtime is that you basically end up with two or more copies of the runtime running at once in your application (e.g. two copies of any internal data structures used to manage memory with malloc/free/new/delete). For similar reasons, you can't have static libraries that are used by higher-level dynamic libraries (e.g. gRPC dynamically linked with protobuf statically linked). In the end, the easiest solution is usually to pick static linking or dynamic linking and use it for everything, although it's possible not to if you're really careful. Having said that, statically linking everything, including the Visual Studio runtime, works really well and I'd recommend it.
- muizelaar 5y agoHere's a version in Rust: https://github.com/alexcrichton/cc-rs/blob/main/src/windows_registry.rs https://github.com/alexcrichton/cc-rs/blob/main/src/windows_...
- mastax 5y agoWell, llvm-config is 719 lines with few comments. At least it doesn't have to use COM and the registry, though.
- glandium 5y agoBut llvm-config only works for the exact clang/llvm version it comes with. You can't use it to find any install of clang/llvm on your system.
- malft 5y agowchar_t *value = (wchar_t *)malloc(length); // The documentation says that if the string for some reason was not stored with zero-termination, we need to manually terminate it. Sigh! if (value[length]) { value[length+1] = 0; }
- 323 5y agoYou have buffer overflows in your code, `length` and `length+1` are past the buffer end.
- creato 5y agoI’m sure that’s why this person posted this snippet. wchar_t is also more than one byte, so the buffer is at most half as big as the code appears to expect.
- 323 5y agoI thought it was parent's code. Source seems to take into account the buffer overflow: DWORD length = required_length + 2; // The +2 is for the maybe optional zero later on. Probably we are over-allocating.
- malf 5y agoDoes it? If required_length is 10, it allocates 12 bytes, and writes element 13, which is byte 26 and 27.
- seritools 5y ago`RegQueryValueExW`'s last parameter is in and out, so that `length` is set to the actual written length after the call. It might cause an OOB write though, with a data race on the registry key (if the key's value happens to grow in length by a char or two between the calls, time of check time of use yada yada).
- 5y ago
- hereforphone 5y agoI've programmed in some capacity for a long time. I never got into MS programming, except when I was a kid with DOS and some BASICs (gwbasic, mostly). The reason I've stayed away from MS is that it's always felt inelegant to me. Not only are the systems clunky but the code just looks so ugly to me. AnExtremelyLongFunctionNameThatWrapsTwiceOnTheScreen(MsI.BillGates.IncrementValueOnlyIfNotInWindows95). It is not an elegant system by any stretch of the imagination. Same goes for Powershell.
- WesleyJohnson 5y agoLong function names are often self-documenting in terms of what they're supposed to do, even if not the how. What's more clear? find_windows_kit_root_with_key find_kit
- shiryel 5y agoThe ideal solution is to use modules/classes and parameters names to contextualize, eg: Windows.find_kit_root(key) And is even better if your language supports pattern match on the parameters like elixir, so you can "overload" the function with many types of arguments, eg: Windows.find_kit_root(%User{key: key}) Windows.find_kit_root(%Admin{key: key}) Providing different behaviors to the same function name
- bullen 5y agoOr you can upvote this: https://developercommunity.visualstudio.com/t/allow-redistribution-of-the-clexe-compiler/975508 https://developercommunity.visualstudio.com/t/allow-redistri...
- deleted 5y ago[deleted]
- john567 5y agoI solved this problem in 2017 when they changed things around a bit. CMD /c vcvarsall.bat x64 && set Then dump the VC specific environment variables in a file and you are good. I implemented this in tundra a very nice and fast build system. It's in Lua... you can look at it here https://github.com/deplinenoise/tundra/blob/master/scripts/tundra/tools/msvc-vscommon-next.lua https://github.com/deplinenoise/tundra/blob/master/scripts/t...
- modeless 5y ago'vcvarsall.bat' is not recognized as an internal or external command, operable program or batch file. The problem this code is solving is equivalent to finding vcvarsall.bat in the first place.
- john567 5y agoWhich is trivial. For all versions of Visual Studio it's has always been in the same location. They changed the directory structure somewhat around 2017 but it was a minor change. Also, if you want to run that command you need to run it from the developer command prompt. Otherwise it's location isn't in your path but like I said this script is always in the same location and what it does is that it sets up the environment for you and it's configurable via parameters.
- modeless 5y agoIt is decidedly not trivial because people can and do choose to install Visual Studio to any random path they want. You can't assume that it is in C:\Program Files (x86) or %ProgramFiles(x86)% or anything like that, if you care about making reliable software. And there is no guarantee that future versions won't change the directory structure again. In fact there's practically a guarantee that they will someday. I am well aware that you can use the developer command prompt (in which case you don't need to run that command at all, it would be redundant). But it's a ridiculous and extremely annoying requirement to impose on your users.
- AndyKelley 5y agoHere's the equivalent code in Zig, in case you want a still-maintained, up-to-date file. It's just called "windows_sdk.cpp". https://github.com/ziglang/zig/blob/master/src/windows_sdk.cpp https://github.com/ziglang/zig/blob/master/src/windows_sdk.c...
- shmerl 5y agohttp://www.netzmafia.de/service/windows95.html http://www.netzmafia.de/service/windows95.html
- npsimons 5y ago> // The fact that we have to do this at all > // is stupid, and the actual maneuvers we need to go through > // are just painful. If programming were like this all the time, > // I would quit. Yup. Exactly why I refuse to ever work on Windows again, and won't even bother targeting it from other platforms. Total waste of my time and talent.
- kazinator 5y agoWhat I don't understand why or where you would use this .h file. It can't be part of an end-user application, because looking for Visual Studio on an end user's machine is futile. Maybe if you're writing some kind of extension for Visual Studio? The comments in the header point to some lack of understanding on the author's part: // HOW TO USE THIS CODE // // The purpose of this file is to find the folders that contain libraries // you may need to link against, on Windows, if you are linking with any // compiled C or C++ code. This will be necessary for many non-C++ programming // language environments that want to provide compatibility. // This needs to clarify the exact situation. Because the normal end-user application cannot be looking for Visual Studio materials. It is completely wrong-headed. They either do not exist, or else were installed by some other application, almost certainly in its own folder. (On this side of year 2000, no application installer should be putting libraries into a system folder.) The folders that contain libraries you may need to link against are found by default; you don't have to tell your program where to look for user32.dll or kernel32.dll. Any non-system library is in your own folder: you ship that library with your program, and it goes into C:\Program Files\YourProgram\bin or whatever. Any .DLL files which are in the same folder as your .EXE will be found by it automatically; there is no need to write code to look for anything. // We find the place where the Visual Studio libraries live (for example, That place is nowhere, on 99.999% of the installed Windows machines on the planet. Unless you mean some other application's C\Program Files\OtherApplication\bin folder, where you have no business looking or using. // libvcruntime.lib), where the linker and compiler executables live // (for example, link.exe), and where the Windows SDK libraries reside // (kernel32.lib, libucrt.lib). kernel32.lib is a kind of liking stub; the library per se is kernel32.dll, which is a system component. .lib files are not even required for using .dll files; for instance, you can use .dll files via dynamic FFI in various languages, without a .lib file. Projects built with Visual Studio generally not have to worry where kernel32.lib has been installed; the tooling takes care of that. Programmers don't have to specify that themselves in project files. It could be a concern if you use some external build system; it would then need some configuration mechanism to point various toolchain-related variables at all the correct directories. A program using "microsoft_craziness.h" could be built which runs on the that build machine and produces a batch file full of environment variable assignments, or whatever. That I can see.