The MinGW.org Windows System Libraries
修订版 | 7b37e9a66a0faf14dc59b7f3bc7dda51db1e9703 (tree) |
---|---|
时间 | 2021-05-24 04:54:29 |
作者 | Keith Marshall <keith@user...> |
Commiter | Keith Marshall |
Implement a generic legacy platform support infrastructure.
@@ -1,3 +1,10 @@ | ||
1 | +2021-05-23 Keith Marshall <keith@users.osdn.me> | |
2 | + | |
3 | + Add a makefile clarification comment. | |
4 | + | |
5 | + * Makefile.in (msvcrt_repl_funcs): Explain inclusion... | |
6 | + (free, realloc): ...these. | |
7 | + | |
1 | 8 | 2021-04-11 Keith Marshall <keith@users.osdn.me> |
2 | 9 | |
3 | 10 | Prepare and publish MinGW.org WSL-5.4.2 release. |
@@ -270,6 +270,12 @@ $(addsuffix .def,$(all_msvcrt)): %.def: msvcrt.def.in | ||
270 | 270 | # |
271 | 271 | msvcrt_repl_prefix := __msvcrt |
272 | 272 | msvcrt_repl_funcs := printf fprintf sprintf vprintf vfprintf vsprintf |
273 | + | |
274 | +# Likewise, for the MinGW wrappers which allow free() and realloc() | |
275 | +# to operate on both regularly-aligned, and on over-aligned, blocks | |
276 | +# of heap memory; (Microsoft require distinct functions for their | |
277 | +# implementations of regularly-aligned and over-aligned allocation). | |
278 | +# | |
273 | 279 | msvcrt_repl_funcs += free realloc |
274 | 280 | |
275 | 281 | # This is kludgey, but dlltool lacks the selectivity to do the job |
@@ -1,3 +1,24 @@ | ||
1 | +2021-05-23 Keith Marshall <keith@users.osdn.me> | |
2 | + | |
3 | + Implement a generic legacy platform support infrastructure. | |
4 | + | |
5 | + * lib/availapi.c: New file; it implements... | |
6 | + (__kernel32_entry_point, __bound_dll_entry_point) | |
7 | + (__unbound_dll_entry_point): ...these run-time link helper functions. | |
8 | + | |
9 | + * include/legacy.h: New file. | |
10 | + (__kernel32_entry_point, __bound_dll_entry_point) | |
11 | + (__unbound_dll_entry_point): Declare them. | |
12 | + (__legacy_support): New inline error notifier; implement it. | |
13 | + (API_UNCHECKED, API_UNSUPPORTED): Define them. | |
14 | + (ERROR_OLD_WIN_VERSION): Duplicate. | |
15 | + | |
16 | + * Makefile.in (libkernel32.a): Integrate... | |
17 | + (k32entry.$OBJEXT, bound.$OBJECT): ...these; they provide... | |
18 | + (__kernel32_entry_point, __bound_dll_entry_point): ...these; add | |
19 | + build rules, as appropriate, incorporating... | |
20 | + (NO_ALIGN_FLAGS): ...this new macro. | |
21 | + | |
1 | 22 | 2021-05-09 Keith Marshall <keith@users.osdn.me> |
2 | 23 | |
3 | 24 | Correct TreeView_GetItemRect() syntax; cf. MinGW-Issue #41041. |
@@ -7,7 +7,7 @@ PACKAGE_TARNAME := @PACKAGE_TARNAME@ | ||
7 | 7 | PACKAGE_VERSION := @PACKAGE_VERSION@ |
8 | 8 | |
9 | 9 | # Written by Keith Marshall <keithmarshall@users.sourceforge.net> |
10 | -# Copyright (C) 2014-2017, MinGW.org Project | |
10 | +# Copyright (C) 2014-2017, 2021, MinGW.org Project | |
11 | 11 | # |
12 | 12 | # |
13 | 13 | # Permission is hereby granted, free of charge, to any person obtaining a |
@@ -125,6 +125,16 @@ lib%.a: %.def | ||
125 | 125 | $(if $(filter-out $<,$^),$(AR) $(ARFLAGS) $@ $(filter-out $<,$^)) |
126 | 126 | |
127 | 127 | vpath %.c ${srcdir}/lib |
128 | +libkernel32.a: k32entry.$(OBJEXT) bound.$(OBJEXT) | |
129 | + | |
130 | +NO_ALIGN_FLAGS := -fno-align-jumps -fno-align-functions | |
131 | +bound.$(OBJEXT) unbound.$(OBJEXT): %.$(OBJEXT): availapi.c | |
132 | + $(CC) -c $(ALL_CFLAGS) $(NO_ALIGN_FLAGS) -D_$* $< -o $@ | |
133 | + | |
134 | +bound_dll_api_list := k32entry | |
135 | +$(addsuffix .$(OBJEXT),$(bound_dll_api_list)): %.$(OBJEXT): availapi.c | |
136 | + $(CC) -c $(ALL_CFLAGS) $(NO_ALIGN_FLAGS) -D_bound -D_lib=$* $< -o $@ | |
137 | + | |
128 | 138 | libuuid.a: ativscp-uuid.$(OBJEXT) cguid-uuid.$(OBJEXT) |
129 | 139 | libuuid.a: comcat-uuid.$(OBJEXT) devguid.$(OBJEXT) docobj-uuid.$(OBJEXT) |
130 | 140 | libuuid.a: exdisp-uuid.$(OBJEXT) extras-uuid.$(OBJEXT) hlguids-uuid.$(OBJEXT) |
@@ -0,0 +1,98 @@ | ||
1 | +/* | |
2 | + * legacy.h | |
3 | + * | |
4 | + * Run-time binding helper routines, to facilitate access to APIs which | |
5 | + * may not be universally supported, while allowing for graceful fall-back | |
6 | + * action, when running on legacy Windows versions. | |
7 | + * | |
8 | + * $Id$ | |
9 | + * | |
10 | + * Written by Keith Marshall <keith@users.osdn.me> | |
11 | + * Copyright (C) 2021, MinGW.org Project | |
12 | + * | |
13 | + * | |
14 | + * Permission is hereby granted, free of charge, to any person obtaining a | |
15 | + * copy of this software and associated documentation files (the "Software"), | |
16 | + * to deal in the Software without restriction, including without limitation | |
17 | + * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
18 | + * and/or sell copies of the Software, and to permit persons to whom the | |
19 | + * Software is furnished to do so, subject to the following conditions: | |
20 | + * | |
21 | + * The above copyright notice and this permission notice (including the next | |
22 | + * paragraph) shall be included in all copies or substantial portions of the | |
23 | + * Software. | |
24 | + * | |
25 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
26 | + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
27 | + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
28 | + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
29 | + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
30 | + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |
31 | + * DEALINGS IN THE SOFTWARE. | |
32 | + * | |
33 | + */ | |
34 | +#ifndef _LEGACY_H | |
35 | +#define _LEGACY_H | |
36 | + | |
37 | +/* Dynamic legacy support is dependent of standard Windows-API | |
38 | + * features, which are declared in <winbase.h>, and implemented | |
39 | + * in kernel32.dll; the supplementary API helper functions, which | |
40 | + * are declared herein, are all implemented as extensions within | |
41 | + * libkernel32.a, whence they will be statically linked. | |
42 | + */ | |
43 | +#include <winbase.h> | |
44 | + | |
45 | +_BEGIN_C_DECLS | |
46 | + | |
47 | +/* Manifest constants to represent the resolution state of any | |
48 | + * DLL entry-point; this is assumed to be recorded in a static | |
49 | + * "void *" pointer, specific to each entry-point, initialized | |
50 | + * to "API_UNCHECKED", and passed to the resolver, whence the | |
51 | + * return value, (which may be either an actual entry-point | |
52 | + * function pointer, or "API_UNSUPPORTED"), should be assigned | |
53 | + * in place of the initial "API_UNCHECKED" value. | |
54 | + */ | |
55 | +#define API_UNCHECKED (void *)(-1) | |
56 | +#define API_UNSUPPORTED (void *)(0) | |
57 | + | |
58 | +/* The following is a duplicate of the error code, as nominally | |
59 | + * defined in <winerror.h>; DO NOT define it conditionally, since | |
60 | + * that would deny the compiler an opportunity to verify that it | |
61 | + * is a faithful duplicate, if <winerror.h> is included first. | |
62 | + */ | |
63 | +#define ERROR_OLD_WIN_VERSION 1150L | |
64 | + | |
65 | +/* DLL-specific entry-point resolvers; declare as "pure", to | |
66 | + * avoid GCC's penchant for burdening the code with unnecessary | |
67 | + * register saves, and restores of memory, at point of call. | |
68 | + */ | |
69 | +extern __attribute__((pure)) | |
70 | +void *__kernel32_entry_point (void *, const char *); | |
71 | + | |
72 | +/* Entry-point resolvers for named DLLs, (explicitly bound at | |
73 | + * link-time, or dynamically loaded, respectively); declared as | |
74 | + * "pure" for same reason as above. | |
75 | + */ | |
76 | +extern __attribute__((pure)) | |
77 | +void *__bound_dll_entry_point (void *, const char *, const char *); | |
78 | + | |
79 | +/* Whereas the preceding resolver assumes that the DLL named by | |
80 | + * its first "const char *" argument has been explicitly bound at | |
81 | + * link-time, (and will return "API_UNSUPPORTED" if it has not), | |
82 | + * the following will load the DLL if necessary, (but it will NOT | |
83 | + * increment the reference count, if the DLL is already mapped | |
84 | + * into the process address space). | |
85 | + */ | |
86 | +extern __attribute__((pure)) | |
87 | +void *__unbound_dll_entry_point (void *, const char *, const char *); | |
88 | + | |
89 | +/* The following helper function, which is ALWAYS expanded in-line, | |
90 | + * provides a convenient mechanism for returning an error status code, | |
91 | + * while also setting said code as Windows last error. | |
92 | + */ | |
93 | +__CRT_ALIAS int __legacy_support( int status ) | |
94 | +{ SetLastError( status ); return status; } | |
95 | + | |
96 | +_END_C_DECLS | |
97 | + | |
98 | +#endif /* !_LEGACY_H: $RCSfile$: end of file */ |
@@ -0,0 +1,168 @@ | ||
1 | +/* | |
2 | + * availapi.c | |
3 | + * | |
4 | + * Provides generic DLL entry-point lookup helper functions, to facilitate | |
5 | + * run-time linking of API functions which may not be supported in legacy | |
6 | + * versions of Windows. | |
7 | + * | |
8 | + * $Id$ | |
9 | + * | |
10 | + * Written by Keith Marshall <keith@users.osdn.me> | |
11 | + * Copyright (C) 2021, MinGW.org Project | |
12 | + * | |
13 | + * | |
14 | + * Permission is hereby granted, free of charge, to any person obtaining a | |
15 | + * copy of this software and associated documentation files (the "Software"), | |
16 | + * to deal in the Software without restriction, including without limitation | |
17 | + * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
18 | + * and/or sell copies of the Software, and to permit persons to whom the | |
19 | + * Software is furnished to do so, subject to the following conditions: | |
20 | + * | |
21 | + * The above copyright notice and this permission notice (including the next | |
22 | + * paragraph) shall be included in all copies or substantial portions of the | |
23 | + * Software. | |
24 | + * | |
25 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
26 | + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
27 | + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
28 | + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
29 | + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
30 | + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |
31 | + * DEALINGS IN THE SOFTWARE. | |
32 | + * | |
33 | + * | |
34 | + * Compile this module multiple times, once for each entry-point resolver | |
35 | + * which is required; the specifics of the resolver are determined thus: | |
36 | + * | |
37 | + * $ gcc -c -D_bound availapi.c -o bound.o | |
38 | + * | |
39 | + * will create a generic resolver, named __bound_dll_entry_point(), which | |
40 | + * will resolve entry-points ONLY within DLLs which have been explicitly | |
41 | + * loaded beforehand. Conversely: | |
42 | + * | |
43 | + * $ gcc -c -D_unbound availapi.c -o unbound.o | |
44 | + * | |
45 | + * will create a generic resolver, named __unbound_dll_entry_point(); this | |
46 | + * will attempt to load a named DLL, if it is not already mapped, before it | |
47 | + * attempts to resolve a named entry-point within it. Finally: | |
48 | + * | |
49 | + * $ gcc -c -D_lib=DLLNAME [-D_bound] availapi.c -o dllentry.o | |
50 | + * | |
51 | + * will create a resolver specific to the DLL specified by DLLNAME, (the | |
52 | + * file-name only part of the DLL name, WITHOUT either the ".dll" suffix, | |
53 | + * or any preceding directory path qualification; this resolver will be | |
54 | + * named __DLLNAME_entry_point(). If the "-D_lib=DLLNAME" specification | |
55 | + * is accompanied by the optional "-D_bound" flag, this resolver will be | |
56 | + * implemented as a thin wrapper around __bound_dll_entry_point(); OTOH, | |
57 | + * if the "-D_bound" flag is not specified, it will be implemented as a | |
58 | + * thin wrapper around __unbound_dll_entry_point(). | |
59 | + * | |
60 | + */ | |
61 | +#include "legacy.h" | |
62 | + | |
63 | +#if defined _lib | |
64 | +/* The entry-point resolver is to be associated with a specifically | |
65 | + * named DLL; define a set of mappings between preferred object file | |
66 | + * names (aliases), and their associated DLL names; (note that this | |
67 | + * facility is primarily provided to accommodate makefile mapping of | |
68 | + * resolver object file names to DLL names; the DLLNAME reference, | |
69 | + * within the command line "-D_lib=DLLNAME" specification, is given | |
70 | + * as the alias, but within the resolver FUNCTION name, it is ALWAYS | |
71 | + * set to match the "DLL Name" entry from the following table): | |
72 | + * | |
73 | + * Alias DLL Name | |
74 | + * -------- -------- */ | |
75 | +# define k32entry kernel32 | |
76 | + | |
77 | +/* Provide a set of macros, to derive the entry-point resolver name, | |
78 | + * and its associated DLL name, from the command line assignment for | |
79 | + * the object file's base name: | |
80 | + */ | |
81 | +# define _dll(_lib) _as_string(_lib) ".dll" | |
82 | +# define _entry(_lib) __##_lib##_entry_point | |
83 | +# define _entry_point(_lib) _entry(_lib) | |
84 | +# define _as_string(_name) #_name | |
85 | + | |
86 | +/* Implement the appropriately named entry-point resolver function... | |
87 | + */ | |
88 | +void *_entry_point(_lib) (void *hook, const char *procname) | |
89 | +# if defined _bound | |
90 | +{ /* ...in terms of the appropiate resolver for a DLL which is | |
91 | + * expected to have been implicitly loaded, (i.e. explicitly | |
92 | + * bound to the executable, at link-time)... | |
93 | + */ | |
94 | + return __bound_dll_entry_point( hook, _dll(_lib), procname ); | |
95 | +} | |
96 | +# else | |
97 | +{ /* ...or otherwise, for a DLL which MAY need to be explicitly | |
98 | + * loaded, on demand. | |
99 | + */ | |
100 | + return __unbound_dll_entry_point( hook, _dll(_lib), procname ); | |
101 | +} | |
102 | +# endif | |
103 | +#elif defined _bound | |
104 | +/* This entry-point resolver is to be generic, w.r.t. the DLL name | |
105 | + * with which it will be associated, but will require that the named | |
106 | + * DLL has been explicitly bound to the application, at link-time. | |
107 | + */ | |
108 | +void *__bound_dll_entry_point | |
109 | +( void *hook, const char *dllname, const char *procname ) | |
110 | +{ | |
111 | + /* If the passed entry-point hook has already been assigned, then | |
112 | + * there is nothing more to do, other than to return it... | |
113 | + */ | |
114 | + if( hook == API_UNCHECKED ) | |
115 | + { /* ...otherwise, we perform a DLL entry-point lookup, considering | |
116 | + * only DLLs which are already mapped into the address space of the | |
117 | + * calling process, and subsequently updating the hook to represent | |
118 | + * the entry-point, or mark it as permanently unsupported. | |
119 | + */ | |
120 | + HMODULE dll = GetModuleHandleA( dllname ); | |
121 | + hook = (dll == NULL) ? GetProcAddress( dll, procname ) : API_UNSUPPORTED; | |
122 | + } | |
123 | + /* In any case, we return the (possibly updated) hook, which should | |
124 | + * then be recorded by the caller. | |
125 | + */ | |
126 | + return hook; | |
127 | +} | |
128 | +#elif defined _unbound | |
129 | +/* This entry-point resolver performs a similar function to that above, | |
130 | + * except that it will attempt to explicitly load any named DLL which is | |
131 | + * not already mapped into the address space of the calling process. | |
132 | + */ | |
133 | +void *__unbound_dll_entry_point | |
134 | +( void *hook, const char *dllname, const char *procname ) | |
135 | +{ | |
136 | + /* If the passed entry-point hook has already been assigned, then | |
137 | + * there is nothing more to do, other than to return it... | |
138 | + */ | |
139 | + if( hook == API_UNCHECKED ) | |
140 | + { /* ...otherwise, we perform a DLL entry-point lookup, loading | |
141 | + * the named DLL, if it has not yet been mapped into the address | |
142 | + * space of the calling process... | |
143 | + */ | |
144 | + HMODULE dll = GetModuleHandleA( dllname ); | |
145 | + if( (dll == NULL) && ((dll = LoadLibraryA( dllname )) == NULL) ) | |
146 | + /* | |
147 | + * ...marking the hook as permanently unsupported, in the | |
148 | + * event of failure to map the DLL... | |
149 | + */ | |
150 | + return hook = API_UNSUPPORTED; | |
151 | + | |
152 | + /* ...otherwise, updating it to reflect the lookup result. | |
153 | + */ | |
154 | + hook = GetProcAddress( dll, procname ); | |
155 | + } | |
156 | + /* In any case, we return the (possibly updated) hook, which should | |
157 | + * then be recorded by the caller. | |
158 | + */ | |
159 | + return hook; | |
160 | +} | |
161 | +#else | |
162 | +/* None of the mandatory -D_spec arguments have been specified; we need | |
163 | + * at least one of... | |
164 | + */ | |
165 | +# error "A -D_lib=DLLNAME, -D_bound, or -D_unbound argument is required." | |
166 | +#endif | |
167 | + | |
168 | +/* $RCSfile$: end of file */ |