• R/O
  • HTTP
  • SSH
  • HTTPS

提交

标签
No Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

The MinGW.org Windows System Libraries


Commit MetaInfo

修订版475f0b6dd1ccc2714a75aa2a36a73c95e73c15c0 (tree)
时间2021-05-26 00:06:58
作者Keith Marshall <keith@user...>
CommiterKeith Marshall

Log Message

Add "legacy-safe" emulation of Microsoft's version helpers API.

更改概述

差异

--- a/w32api/ChangeLog
+++ b/w32api/ChangeLog
@@ -1,5 +1,21 @@
11 2021-05-25 Keith Marshall <keith@users.osdn.me>
22
3+ Add "legacy-safe" emulation of Microsoft's version helpers API.
4+
5+ * include/versionhelpers.h: New file; it defines the API, as specified
6+ in Microsoft's official "Version Helper" on-line documentation.
7+
8+ * lib/osvercmp.c: New file; it implements...
9+ (__mingw_osver_at_least, __mingw_osver_server): ...these "legacy-safe"
10+ helper functions; deployed as regular object modules, included in...
11+ (libkernel32.a): ...this W32API import library, they wrap calls to...
12+ (VerSetConditionMask, VerifyVersionInfoA): ...these KERNEL32.DLL
13+ functions, forwarding calls only if supported.
14+
15+ * Makefile.in (kernel32.a): Add osvercmp.$OBJEXT dependency.
16+
17+2021-05-25 Keith Marshall <keith@users.osdn.me>
18+
319 Correct an entry-point look-up logic defect.
420
521 * lib/availapi.c (__bound_dll_entry_point) [dll == NULL]: Should be...
--- a/w32api/Makefile.in
+++ b/w32api/Makefile.in
@@ -125,7 +125,7 @@ lib%.a: %.def
125125 $(if $(filter-out $<,$^),$(AR) $(ARFLAGS) $@ $(filter-out $<,$^))
126126
127127 vpath %.c ${srcdir}/lib
128-libkernel32.a: k32entry.$(OBJEXT) bound.$(OBJEXT)
128+libkernel32.a: $(addsuffix .$(OBJEXT),k32entry bound osvercmp)
129129
130130 NO_ALIGN_FLAGS := -fno-align-jumps -fno-align-functions
131131 bound.$(OBJEXT) unbound.$(OBJEXT): %.$(OBJEXT): availapi.c
--- /dev/null
+++ b/w32api/include/versionhelpers.h
@@ -0,0 +1,103 @@
1+/*
2+ * versionhelpers.h
3+ *
4+ * A MinGW emulation of the API implementation, first provided by Microsoft
5+ * as a component of the Windows-8.1 software development kit, with addition
6+ * of fail-safe support for use on legacy Windows versions.
7+ *
8+ * Note that use of the APIs, declared herein, is NOT recommended; usually,
9+ * there are better ways to check for availablity of specific features, than
10+ * to blindly rely on OS version number comparisons.
11+ *
12+ *
13+ * $Id$
14+ *
15+ * Written by Keith Marshall <keith@users.osdn.me>
16+ * Copyright (C) 2021, MinGW.org Project
17+ *
18+ *
19+ * Permission is hereby granted, free of charge, to any person obtaining a
20+ * copy of this software and associated documentation files (the "Software"),
21+ * to deal in the Software without restriction, including without limitation
22+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
23+ * and/or sell copies of the Software, and to permit persons to whom the
24+ * Software is furnished to do so, subject to the following conditions:
25+ *
26+ * The above copyright notice and this permission notice (including the next
27+ * paragraph) shall be included in all copies or substantial portions of the
28+ * Software.
29+ *
30+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
31+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
32+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
33+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
34+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
35+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
36+ * DEALINGS IN THE SOFTWARE.
37+ *
38+ */
39+#ifndef _VERSIONHELPERS_H
40+#define _VERSIONHELPERS_H
41+#pragma GCC system_header
42+
43+#include <windef.h>
44+
45+_BEGIN_C_DECLS
46+
47+/* These API declarations have been written from scratch, without reference,
48+ * in any way, to the original Microsoft implementation. Although Microsoft
49+ * did not provide their implementation until publication of the Win-8.1 SDK,
50+ * it is understood, from their public documentation, that the underlying API
51+ * has been available since Win-2K, and that the Win-8.1 SDK implementation
52+ * is backward-compatible with all Win-NT versions since then; however, it
53+ * is not clear how fail-safe it may be, should a dependent application be
54+ * deployed on Win-9x, Win-NT4, or earlier.
55+ *
56+ * To address this uncertainty, this MinGW implementation is based on the
57+ * following pair of wrapper functions, provided in LIBMINGW32.A; these will
58+ * delegate to the VerifyVersionInfo() API, after confirming that the host
59+ * platform supports it, while exhibiting suitable fail-safe behaviour, in
60+ * case it does not.
61+ */
62+BOOL __mingw_osver_at_least( DWORD, DWORD, DWORD );
63+BOOL __mingw_osver_server( void );
64+
65+/* The actual version helper APIs take the form of in-line functions.
66+ */
67+#define VERSIONHELPERAPI \
68+static __inline__ __attribute__((__always_inline__)) BOOL
69+
70+/* This first pair of functions require distinct implementations...
71+ */
72+VERSIONHELPERAPI IsWindowsServer()
73+{ return __mingw_osver_server(); }
74+
75+VERSIONHELPERAPI
76+IsWindowsVersionOrGreater( WORD __major, WORD __minor, WORD __sp )
77+{ return __mingw_osver_at_least( __major, __minor, __sp ); }
78+
79+/* ...while the remainder are sufficiently generic to lend themselves to
80+ * instantiation by use of a common convenience macro:
81+ */
82+#undef __mingw_generic_version_helper
83+#define __mingw_generic_version_helper( FUNCTION, M, N, S ) \
84+VERSIONHELPERAPI FUNCTION( void ){ return __mingw_osver_at_least( M, N, S ); }
85+
86+__mingw_generic_version_helper( IsWindowsXPOrGreater, 5, 1, 0 )
87+__mingw_generic_version_helper( IsWindowsXPSP1OrGreater, 5, 1, 1 )
88+__mingw_generic_version_helper( IsWindowsXPSP2OrGreater, 5, 1, 2 )
89+__mingw_generic_version_helper( IsWindowsXPSP3OrGreater, 5, 1, 3 )
90+__mingw_generic_version_helper( IsWindowsVistaOrGreater, 6, 0, 0 )
91+__mingw_generic_version_helper( IsWindowsVistaSP1OrGreater, 6, 0, 0 )
92+__mingw_generic_version_helper( IsWindowsVistaSP2OrGreater, 6, 0, 2 )
93+__mingw_generic_version_helper( IsWindows7OrGreater, 6, 1, 0 )
94+__mingw_generic_version_helper( IsWindows7SP1OrGreater, 6, 1, 1 )
95+__mingw_generic_version_helper( IsWindows8OrGreater, 6, 2, 0 )
96+__mingw_generic_version_helper( IsWindows8Point1OrGreater, 6, 3, 0 )
97+__mingw_generic_version_helper( IsWindows10OrGreater, 10, 0, 0 )
98+
99+#undef __mingw_generic_version_helper
100+
101+_END_C_DECLS
102+
103+#endif /* !_VERSIONHELPERS_H: $RCSfile$: end of file */
--- /dev/null
+++ b/w32api/lib/osvercmp.c
@@ -0,0 +1,178 @@
1+/*
2+ * osvercmp.c
3+ *
4+ * Implements a pair of wrappers for the WinAPI VerifyVersionInfo() API,
5+ * to facilitate provision of support for a MinGW emulation of Microsoft's
6+ * <versionhelpers.h>. Although Microsoft first provided this as part of
7+ * the SDK for Windows-8.1, the underlying VerifyVersionInfo() API has
8+ * been supported since Win2K; the wrappers, implemented herein, extend
9+ * support to legacy platforms, providing fail-safe handling on earlier
10+ * platforms, which lack the VerifyVersionInfo() API.
11+ *
12+ *
13+ * $Id$
14+ *
15+ * Written by Keith Marshall <keith@users.osdn.me>
16+ * Copyright (C) 2021, MinGW.org Project
17+ *
18+ *
19+ * Permission is hereby granted, free of charge, to any person obtaining a
20+ * copy of this software and associated documentation files (the "Software"),
21+ * to deal in the Software without restriction, including without limitation
22+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
23+ * and/or sell copies of the Software, and to permit persons to whom the
24+ * Software is furnished to do so, subject to the following conditions:
25+ *
26+ * The above copyright notice and this permission notice (including the next
27+ * paragraph) shall be included in all copies or substantial portions of the
28+ * Software.
29+ *
30+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
31+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
32+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
33+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
34+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
35+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
36+ * DEALINGS IN THE SOFTWARE.
37+ *
38+ *
39+ * Since the underlying VerifyVersionInfo() API was not introduced until
40+ * Win-2K, and MinGW's WinAPI is nominally compiled with legacy version
41+ * guarantees for Win-NT4 only, we must create a clean slate...
42+ *
43+ */
44+#undef NTDDI_VERSION
45+#undef _WIN32_WINDOWS
46+#undef _WIN32_WINNT
47+
48+/* ...whence we may request exposure of, and access to, the necessary
49+ * Win-2K API features; (note that this does not preclude use on earlier
50+ * legacy platforms, since the implementation incorporates appropriate
51+ * fail-safe handling).
52+ */
53+#define _WIN32_WINNT _WIN32_WINNT_WIN2K
54+
55+#include <winbase.h>
56+#include <versionhelpers.h>
57+
58+#include "legacy.h"
59+
60+/* We need a function pointer type definition, matching the signature of
61+ * VerifyVersionInfo(), so that we may verify its availability, BEFORE we
62+ * attempt to invoke it indirectly.
63+ */
64+typedef BOOL WINAPI (*validator_fn)( OSVERSIONINFOEXA *, DWORD, DWORDLONG );
65+
66+static validator_fn __mingw_osver_comparator( void )
67+{
68+ /* Internal helper function, to look up, and store, the entry point
69+ * address of VerifyVersionInfo(), if it is available in KERNEL32.DLL;
70+ * (note that this is a one-time initialization, within the lifetime
71+ * of the calling process).
72+ */
73+ static void *entry = API_UNCHECKED;
74+ entry = __kernel32_entry_point( entry, "VerifyVersionInfoA" );
75+ return (validator_fn)(entry);
76+}
77+
78+/* For OS version comparisons, we need to inspect the major, and minor
79+ * version numbers, both for the base OS, and any applied service packs...
80+ */
81+static const WORD __mingw_osver_mask = VER_MAJORVERSION
82+| VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR;
83+
84+static DWORDLONG __mingw_osver_test( void )
85+{ /* ...selecting the "greater-than-or-equal" comparison mode for each,
86+ * in turn, as facilitated by this internal helper function; (note
87+ * that, once again, this performs a one-time initialization of the
88+ * comparison selector, for each item of version information).
89+ */
90+ static DWORDLONG test = 0LL;
91+ if( test == 0LL )
92+ { /* We need to initialize it, on this occasion; loop over the bits
93+ * of the comparison selector mask, associating the appropriate
94+ * comparison type with each which is set.
95+ */
96+ for( DWORD mask = 1; mask < __mingw_osver_mask; mask <<= 1 )
97+ if( (mask & __mingw_osver_mask) != 0 )
98+ VER_SET_CONDITION( test, mask, VER_GREATER_EQUAL );
99+ }
100+ return test;
101+}
102+
103+BOOL __mingw_osver_at_least( DWORD __major, DWORD __minor, DWORD __sp )
104+{
105+ /* This is the public entry point, through which OS version number
106+ * comparison requests may be directed to VerifyVersionInfo()...
107+ */
108+ validator_fn chk;
109+ if( (chk = __mingw_osver_comparator()) != (validator_fn)(API_UNSUPPORTED) )
110+ {
111+ /* ...subject to initialization having established a valid entry
112+ * point address, to which we pass the request via the pointer.
113+ */
114+ OSVERSIONINFOEXA osinfo =
115+ { sizeof osinfo, __major, __minor, 0, 0, "", __sp, 0, 0, 0, 0 };
116+ return chk( &osinfo, __mingw_osver_mask, __mingw_osver_test() );
117+ }
118+
119+ /* If we get to here, initialization failed to identify a valid
120+ * entry point address, for VerifyVersionInfo(); this represents
121+ * the fail-safe handling, for legacy platforms.
122+ */
123+ SetLastError( ERROR_OLD_WIN_VERSION );
124+ return FALSE;
125+}
126+
127+/* In the case of the server platform identification test, we again
128+ * must perform an OS version check, but this must be augmented by a
129+ * product type assessment...
130+ */
131+static const WORD __mingw_osplatform_mask = VER_PRODUCT_TYPE
132+| __mingw_osver_mask;
133+
134+static DWORDLONG __mingw_osplatform_test( void )
135+{ /* ...for which (a copy of) the version number comparison selector
136+ * must be augmented by addition of an equality comparator selector
137+ * for the server product type identifier; (as previously, this is
138+ * again established as a one-time initialization).
139+ */
140+ static DWORDLONG test = 0LL;
141+ if( test == 0LL )
142+ { /* We need to initialize it, on this occasion.
143+ */
144+ test = __mingw_osver_test();
145+ VER_SET_CONDITION( test, VER_PRODUCT_TYPE, VER_EQUAL );
146+ }
147+ return test;
148+}
149+
150+BOOL __mingw_osver_server( void )
151+{ /* This alternative public entry point is specific to the server
152+ * platform identification test; as in the preceding case of more
153+ * generalized version number comparisons, this is also delegated
154+ * to the VerifyVersionInfo() API, using the same entry point
155+ * reference pointer...
156+ */
157+ validator_fn chk;
158+ if( (chk = __mingw_osver_comparator()) != (validator_fn)(API_UNSUPPORTED) )
159+ {
160+ /* ...once again, subject to successful initialization; in this
161+ * case, it is the server characterization property which is of
162+ * primary interest, but we do also require an OS version which
163+ * corresponds to Win-2K, or later.
164+ */
165+ OSVERSIONINFOEXA osinfo =
166+ { sizeof osinfo, 5, 0, 0, 0, "", 0, 0, 0, VER_NT_SERVER, 0 };
167+ return chk( &osinfo, __mingw_osplatform_mask, __mingw_osplatform_test() );
168+ }
169+
170+ /* If we get to here, initialization failed to identify a valid
171+ * entry point address, for VerifyVersionInfo(); this represents
172+ * the fail-safe handling, for legacy platforms.
173+ */
174+ SetLastError( ERROR_OLD_WIN_VERSION );
175+ return FALSE;
176+}
177+
178+/* $RCSfile$: end of file */