user57 Posted July 19, 2021 Posted July 19, 2021 (edited) there was a recent update (my previos version was visual studio 2019 v16.4 updated to vs 2019 v16.10 (the exact version is not known so it must be between those versions) the code i used is windows xp compatible however this "build in trick" still makes my code still incompatible in the past your code useally gone to winmain() in some other codes i reconized that some code was added to my executable that actually was not needed at all so i was wondering why did my executable (what only printed MessageboxA) gone a lot bigger going after that i could understand that this code was added by something else and is executed before my code in winmain() is executed in other compilers or maybe settings? you didnt see this problem and it gone to winmain() directly then the executable was smaller too in my test executable it was just MessageboxA function and no need of executing some "other/more" code this time i had the same problem but this time it made the executable not only inefficient it also made it incompatible (to see here is that microsoft can add this code before your code and make it lets say windows 10 only "this runtime code then gets executed and says "windows 10 only" or "access denied" before your working code is executed) so i took a look what this code actually does do all begins with the function that is called before winmain() extern "C" DWORD WinMainCRTStartup(LPVOID) // <- called before winmain { __security_init_cookie // (unimportant for us) return __scrt_common_main(); // <-- calls next functions } the filename for this code is exe_winmain.cpp and useally is in a directory (or something close) called C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.24.28314\crt\src\vcruntime\exe_winmain.cpp CRT means: C runtime, so we actually know what we deal with in my case it use a unwanted function InitializeCriticalSectionEx (that i actually use nowhere in my code but the c runtime use it) so i looked how and where it do that the code cain is as follows: calls __scrt_common_main ->__scrt_common_main_seh src\vctools\crt\vcstartup\src\eh\i386\secchk.c : (call chain) 0, __SEH_prolog4 1, __scrt_initialize_crt // -> has function __cdecl __vcrt_initialize_locks(VS 16.4works with InitializeCriticalSectionEx and InitializeCriticalSectionAndSpinCount) (VS 16.10 only work with InitializeCriticalSectionEx) -> the VS 16.4 version checks if it can use InitializeCriticalSectionEx if it cant it use InitializeCriticalSectionAndSpinCount (the code use a function called try_get_function() to do so) VC\Tools\MSVC\14.29.30037\crt\src\vcruntime\locks.cpp this is the function with more details: (static void* __cdecl try_get_function( function_id const id, char const* const name, module_id const* const first_module_id, module_id const* const last_module_id ) noexcept ) but that is only important if we want to use InitializeCriticalSectionEx, if we want we just could use InitializeCriticalSectionAndSpinCount and this part would be solved 2, __scrt_acquire_startup_lock 3, _initterm_e (dont have InitializeCriticalSectionEx yet) (then _initterm is done a second time and has InitializeCriticalSectionEx in internal) 4, _initterm <--- second time without _e the function "_initterm" has 2 functions 1 is called __guard_check_icall_fptr (this function checks if the pointer is valid and is unimportant for this case) the other function calls several functions (__xc_a beginning list of functions and __xc_z (end of functions)) the second function in list of __xc_a has InitializeCriticalSectionEx in internal and is called: static _Init_lock (is a class constructor) and leads to _Init_locks _Init_locks is in a file called "xlock.cpp" folder: VC\Tools\MSVC\14.29.30037\crt\src\stl\xlock.cpp (c code) __thiscall _Init_locks::_Init_locks() noexcept { // initialize locks if (InterlockedIncrement(&init) == 0) { for (auto& elem : mtx) { _Mtxinit(&elem); // <- next step we looking for } } } here we look at function _Mtxinit filename that contain _Mtxinit "xmtx.cpp" folder: VC\Tools\MSVC\14.24.28314\crt\src\stl\xmtx.cpp (c code) void __CLRCALL_PURE_OR_CDECL _Mtxinit(_Rmtx* _Mtx) noexcept { // initialize mutex InitializeCriticalSectionEx(_Mtx, 4000, 0); // this variant } here also is the diffrens what has been changed: void __CLRCALL_PURE_OR_CDECL _Mtxinit(_Rmtx* _Mtx) noexcept { // initialize mutex __crtInitializeCriticalSectionEx(_Mtx, 4000, 0); // variant before } the function __crtInitializeCriticalSectionEx has a check if it do use InitializeCriticalSectionEx or if it do use InitializeCriticalSectionAndSpinCount (xp compatible) extern "C" BOOL __cdecl __crtInitializeCriticalSectionEx( LPCRITICAL_SECTION const lpCriticalSection, DWORD const dwSpinCount, DWORD const Flags) { // use InitializeCriticalSectionEx if it is available (only on Windows Vista+)... IFDYNAMICGETCACHEDFUNCTION( PFNINITIALIZECRITICALSECTIONEX, InitializeCriticalSectionEx, pfInitializeCriticalSectionEx) { return pfInitializeCriticalSectionEx(lpCriticalSection, dwSpinCount, Flags); } // ...otherwise fall back to using InitializeCriticalSectionAndSpinCount. InitializeCriticalSectionAndSpinCount(lpCriticalSection, dwSpinCount); return TRUE; } so even if your entire code would just use a single MessageboxA this CRT or "C runtime" starting/calling WinMainCRTStartup beforehand makes your application still incompatible, even if your code 100 % would work noticeable is that "they" can do this not only with a limit to windows vista, 7, 8, 8.1, or 10 they can add incompatible functions to that CRT code thus you might just upgrade your VS/Compiler and your code wont work even if the code is compatible its like a check "do this computer have windows 10" -> access denied -> no code is spawned (even tho your code would work) shame to microsoft for this one (the other code i tryed has a header file that use c++20 style (it are just type converters like you do with templates) but it doesnt use any windows functions)) in that sence that is a compiler question of the c++ style (type converter) not a "missing api" question, but still that CRT used that api even tho i dont have that InitializeCriticalSectionEx in my code and to fix up different types such as handles, int, float etc. for example over a template or type converter, again is a compiler question here is the rest of the callchain (before your code is executed) 5, __scrt_release_startup_lock 6, __scrt_get_dyn_tls_init_callback 7, __scrt_get_dyn_tls_dtor_callback 8 , __scrt_get_show_window_mode 9, _get_narrow_winmain_command_line 10, WinMain(our executable/our code is then executed) <-- here begins/comes our code/programm/app so everybody can easy understand why your code got "blocked" or will just maybe in future, so we know the trick beforehand :-) Edited July 25, 2021 by user57 more detail 1
RainyShadow Posted July 19, 2021 Posted July 19, 2021 Have you found how to fix this? I recently got VS 2019 and wanted to compile a few programs without SSE2, but so far haven't been able to build anything successfully. Not even sure if i set up the damn thing properly. Tried to follow some "Hello world" tutorial, but it shows selecting console project and i don't have this option here, pfff. I remember getting that update too.
UCyborg Posted July 19, 2021 Posted July 19, 2021 https://docs.microsoft.com/en-us/cpp/build/configuring-programs-for-windows-xp?view=msvc-160 Won't help if the code actually needs the latest compiler to compile though.
RainyShadow Posted July 20, 2021 Posted July 20, 2021 I managed to configure a console "hello world" program so it works in XP (and no stupid SSE2, yay!). I didn't find simple GUI program to test though, and the example when i started a new "Dialog project" was way over my head. I have been trying to get Miranda-ng, but it seems to have issues even without targeting XP. And not having touched any Visual Studio before kinda complicates things for me... @user57 Could you share that MessageboxA project? I'd like to try getting it built for XP.
Dibya Posted July 25, 2021 Posted July 25, 2021 Today i updated to 16.10 , Let see if i can figure out anything
user57 Posted August 5, 2021 Author Posted August 5, 2021 (edited) actually i gone for a solution i editet this cpp file to make use of the previos method but then something weird happend it still imported that function so i was like hmm you might forgotten something ? looked no then i debugged the application picture 01 then this message apeared (basicly it just says that i used a different c++ file to compile but actually this message always apears even tho i made > 10 compiles and > 10 changes) , i so looked if this file exits 2 or more times (no), i restarted vs (also compiled the same problem) also a few trys with rebuild solution/project and clean project deleting the entire project from hardrive and tryed again from beginning also lead to that picture that the c++ files doesnt match the compiled file in picture 02 (thats the one in the middle with the assembly code) you can see that it still used that old code (aka InitializeCriticalSectionEx not InitializeCriticalSectionAndSpinCount) even tho the cpp file is edited (picture 03) in picture 03 thats the one that shows the cpp file that should make that code as you see i first uncommented the code that creates InitializeCriticalSectionEx and replaced it with the common function InitializeCriticalSectionAndSpinCount a other method is i tryed to write c errors into that function, but instead of giving me a error message (because the code cant even work) it also compiled that old code with InitializeCriticalSectionEx do it have some kind of backfile ? maybe staticly skipped ? do somebody actually know why this is happening ? (it let me edit other internal cpp files but for some the code applied/changed does simply not happen, the files itself are changed i gone the folders and looked them with other editors) Edited August 6, 2021 by user57
user57 Posted December 21, 2022 Author Posted December 21, 2022 greetings all, we found the related information that caused that problem even tho we have no inside information, the information i posted is incredible accurate so here is what microsoft did, it probaly is useful information to know https://github.com/microsoft/STL/pull/1194/commits/faa3434d7e748fcfdc253ad2788a0e4fddfea105 explain that __crtInitializeCriticalSectionEx(&_M_critical_section, 4000, 0); // to InitializeCriticalSectionEx(&_M_critical_section, 4000, 0); it also explains why the dependency walker for versions up to 16.7 show a try to search for that functions (meant is that there these functions where found on dependency walker but not in the import list) 1
Recommended Posts
Please sign in to comment
You will be able to leave a comment after signing in
Sign In Now