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