Move common code from __p__osplatform.c and __p__osplatform_emul.c into
new helper function get_osplatform_helper which deduplicate code.
Do not treat zero value in _osplatform as uninitialized value as it is a
valid platform id value. Use additional variable for checking whether
_osplatform is initialized or not.
When function GetVersionExA on non-i386 systems fails then return
value 2 (WinNT) which is better default than the value 0 (Win32s) as
Win32s is i386-only.
On i386 builds use GetVersion function as GetVersionExA is not available on
older Windows NT systems.
---
mingw-w64-crt/misc/__p__osplatform.c | 16 +++---
mingw-w64-crt/misc/__p__osplatform_emul.c | 59 +++++++++++++++++++++--
2 files changed, 62 insertions(+), 13 deletions(-)
diff --git a/mingw-w64-crt/misc/__p__osplatform.c
b/mingw-w64-crt/misc/__p__osplatform.c
index b22bf1b1a18a..d36382edb42e 100644
--- a/mingw-w64-crt/misc/__p__osplatform.c
+++ b/mingw-w64-crt/misc/__p__osplatform.c
@@ -15,6 +15,9 @@ unsigned int* (__cdecl
*__MINGW_IMP_SYMBOL(__p__osplatform))(void) = __p__osplat
#include <windows.h>
#include <msvcrt.h>
+#define GET_OSPLATFORM_HELPER_ONLY
+#include "__p__osplatform_emul.c"
+
static unsigned int* _osplatform_ptr;
static unsigned int _osplatform_static;
@@ -23,16 +26,13 @@ unsigned int* __cdecl __p__osplatform(void)
if (!_osplatform_ptr)
{
HMODULE msvcrt = __mingw_get_msvcrt_handle();
- if (msvcrt)
- _osplatform_ptr = (unsigned int*)GetProcAddress(msvcrt,
"_osplatform");
- if (!_osplatform_ptr)
+ unsigned int* ptr = msvcrt ? (unsigned int*)GetProcAddress(msvcrt,
"_osplatform") : NULL;
+ if (!ptr)
{
- OSVERSIONINFOA osvi;
- osvi.dwOSVersionInfoSize = sizeof(osvi);
- if (GetVersionExA(&osvi))
- _osplatform_static = osvi.dwPlatformId;
- _osplatform_ptr = &_osplatform_static;
+ _osplatform_static = get_osplatform_helper();
+ ptr = &_osplatform_static;
}
+ (void)InterlockedExchangePointer((PVOID*)&_osplatform_ptr, ptr);
}
return _osplatform_ptr;
}
diff --git a/mingw-w64-crt/misc/__p__osplatform_emul.c
b/mingw-w64-crt/misc/__p__osplatform_emul.c
index 5e6f0082dd43..34141e5e7067 100644
--- a/mingw-w64-crt/misc/__p__osplatform_emul.c
+++ b/mingw-w64-crt/misc/__p__osplatform_emul.c
@@ -6,19 +6,68 @@
#include <windows.h>
+static unsigned int get_osplatform_helper(void)
+{
+ OSVERSIONINFOA osvi;
+#ifdef __i386__
+ HMODULE kernel32;
+ WINBOOL (WINAPI *kernel32_GetVersionExA)(LPOSVERSIONINFOA);
+ DWORD raw_ver;
+ WORD maj_ver;
+ BOOL is_nt;
+#endif
+
+ osvi.dwOSVersionInfoSize = sizeof(osvi);
+
+#ifdef __i386__
+ /* GetVersionExA is not available on older WinNT and Win32s versions but
+ * returns full 32-bit for platform id (2^32 possible values).
+ * GetVersion returns in highest bit identification if system is WinNT and
+ * in low 8 bits returns major os system version (Win9x starts at 4).
+ * So load GetVersionExA dynamically and on failure fallback to GetVersion.
+ */
+ kernel32 = GetModuleHandleA("kernel32.dll");
+ kernel32_GetVersionExA = kernel32 ? GetProcAddress(kernel32,
"GetVersionExA") : NULL;
+ if (kernel32_GetVersionExA && kernel32_GetVersionExA(&osvi))
+ return osvi.dwPlatformId;
+
+ raw_ver = GetVersion();
+ maj_ver = raw_ver & 0xff;
+ is_nt = !(raw_ver >> 31);
+ if (is_nt)
+ return VER_PLATFORM_WIN32_NT;
+ else if (maj_ver >= 4)
+ return VER_PLATFORM_WIN32_WINDOWS;
+ else
+ return VER_PLATFORM_WIN32s;
+#else
+ /* On non-i386 platforms is GetVersionExA always available.
+ * In case of failures return value 2 (WinNT) which is sane default.
+ * Value 0 (Win32s) is not a sane default as Win32s is i386-only.
+ */
+ if (GetVersionExA(&osvi))
+ return osvi.dwPlatformId;
+ else
+ return VER_PLATFORM_WIN32_NT;
+#endif
+}
+
+#ifndef GET_OSPLATFORM_HELPER_ONLY
+
#undef _osplatform
static unsigned int _osplatform;
unsigned int* __cdecl __p__osplatform(void);
unsigned int* __cdecl __p__osplatform(void)
{
- if (!_osplatform)
+ static long init = 0;
+ if (!init)
{
- OSVERSIONINFOA osvi;
- osvi.dwOSVersionInfoSize = sizeof(osvi);
- if (GetVersionExA(&osvi))
- _osplatform = osvi.dwPlatformId;
+ (void)InterlockedExchange((long*)&_osplatform,
get_osplatform_helper());
+ (void)InterlockedExchange(&init, 1);
}
return &_osplatform;
}
unsigned int* (__cdecl *__MINGW_IMP_SYMBOL(__p__osplatform))(void) =
__p__osplatform;
+
+#endif
--
2.20.1
_______________________________________________
Mingw-w64-public mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/mingw-w64-public