1+ #pragma comment(lib, "Version.lib")
2+
3+ #include <Windows.h>
4+ #include <stdio.h>
5+ #include <stdlib.h>
6+ #include "c4Log.h"
7+
8+ typedef struct {
9+ WORD major ;
10+ WORD minor ;
11+ WORD build ;
12+ WORD revision ;
13+ } Version ;
14+
15+ static int GetDllVersion (const wchar_t * path , Version * out_version ) {
16+ DWORD dummy ;
17+ DWORD size = GetFileVersionInfoSizeW (path , & dummy );
18+ if ( size == 0 ) { return 0 ; }
19+
20+ BYTE * buffer = (BYTE * )malloc (size );
21+ if ( !buffer ) { return 0 ; }
22+ if ( !GetFileVersionInfoW (path , 0 , size , buffer ) ) {
23+ c4log (kC4DefaultLog , kC4LogVerbose , "GetFileVersionInfoW failed: %lu" , GetLastError ());
24+ free (buffer );
25+ return 0 ;
26+ }
27+
28+ VS_FIXEDFILEINFO * fileInfo ;
29+ UINT len = 0 ;
30+ if ( !VerQueryValueA (buffer , "\\" , (LPVOID * )& fileInfo , & len ) ) {
31+ c4log (kC4DefaultLog , kC4LogVerbose , "VerQueryValueA failed: %lu" , GetLastError ());
32+ free (buffer );
33+ return 0 ;
34+ }
35+
36+ if ( fileInfo ) {
37+ out_version -> major = HIWORD (fileInfo -> dwFileVersionMS );
38+ out_version -> minor = LOWORD (fileInfo -> dwFileVersionMS );
39+ out_version -> build = HIWORD (fileInfo -> dwFileVersionLS );
40+ out_version -> revision = LOWORD (fileInfo -> dwFileVersionLS );
41+ free (buffer );
42+ return 1 ;
43+ }
44+
45+ c4log (kC4DefaultLog , kC4LogVerbose , "VerQueryValueA returned NULL" );
46+ free (buffer );
47+ return 0 ;
48+ }
49+
50+ static int CompareVersions (const Version * a , const Version * b ) {
51+ if ( a -> major != b -> major ) return a -> major < b -> major ? -1 : 1 ;
52+ if ( a -> minor != b -> minor ) return a -> minor < b -> minor ? -1 : 1 ;
53+ if ( a -> build != b -> build ) return a -> build < b -> build ? -1 : 1 ;
54+ if ( a -> revision != b -> revision ) return a -> revision < b -> revision ? -1 : 1 ;
55+ return 0 ;
56+ }
57+
58+ void CheckCppRuntime () {
59+ HMODULE hMod = GetModuleHandleA ("msvcp140.dll" );
60+ if ( !hMod ) { hMod = LoadLibraryA ("msvcp140d.dll" ); }
61+
62+ if ( !hMod ) {
63+ c4log (kC4DefaultLog , kC4LogWarning , "msvcp140.dll not loaded yet, unable to check version..." );
64+ return ;
65+ }
66+
67+ wchar_t path [MAX_PATH ];
68+ if ( GetModuleFileNameW (hMod , path , MAX_PATH ) == 0 ) {
69+ c4log (kC4DefaultLog , kC4LogWarning , "Unable to determine msvcp140.dll filename to check version..." );
70+ return ;
71+ }
72+
73+ Version loaded = {0 };
74+ if ( !GetDllVersion (path , & loaded ) ) {
75+ c4log (kC4DefaultLog , kC4LogWarning , "Unable to get version of msvcp140.dll to check..." );
76+ return ;
77+ }
78+
79+ Version expected = {14 , 36 , 32457 , 0 };
80+ int cmp = CompareVersions (& loaded , & expected );
81+ if ( cmp < 0 ) {
82+ c4log (kC4DefaultLog , kC4LogWarning , "msvcp140.dll version is older than expected: %u.%u.%u.%u < %u.%u.%u.%u" ,
83+ loaded .major , loaded .minor , loaded .revision , loaded .build , expected .major , expected .minor ,
84+ expected .revision , expected .build );
85+ c4log (kC4DefaultLog , kC4LogWarning , "This may cause instability in your application" );
86+ }
87+ }
88+
89+ BOOL APIENTRY DllMain (HMODULE hModule , DWORD ul_reason_for_call , LPVOID lpReserved ) {
90+ switch ( ul_reason_for_call ) {
91+ case DLL_PROCESS_ATTACH :
92+ CheckCppRuntime ();
93+ break ;
94+ default :
95+ break ;
96+ }
97+ return TRUE;
98+ }
0 commit comments