Pyrogenesis  13997
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
wstartup.cpp
Go to the documentation of this file.
1 /* Copyright (c) 2010 Wildfire Games
2  *
3  * Permission is hereby granted, free of charge, to any person obtaining
4  * a copy of this software and associated documentation files (the
5  * "Software"), to deal in the Software without restriction, including
6  * without limitation the rights to use, copy, modify, merge, publish,
7  * distribute, sublicense, and/or sell copies of the Software, and to
8  * permit persons to whom the Software is furnished to do so, subject to
9  * the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included
12  * in all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
18  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21  */
22 
23 /*
24  * windows-specific startup code
25  */
26 
27 #include "precompiled.h"
29 
31 
32 /*
33 
34 Shutdown
35 --------
36 
37 our shutdown function must be called after static C++ dtors, since they
38 may use wpthread and wtime functions. how to accomplish this?
39 
40 hooking ExitProcess is one way of ensuring we're the very last bit of
41 code to be called. this has several big problems, though:
42 - if other exit paths (such as CorExitProcess) are added by MS and
43  triggered via external code injected into our process, we miss our cue
44  to shut down. one annoying consequence would be that the Aken driver
45  remains loaded. however, users also can terminate our process at any
46  time, so we need to safely handle lack of shutdown anyway.
47 - IAT hooking breaks if kernel32 is delay-loaded (who knows what
48  people are going to do..)
49 - Detours-style trampolines are nonportable (the Detours library currently
50  only ships with code to handle IA-32) and quite risky, since antivirus
51  programs may flag this activity.
52 
53 having all exit paths call our shutdown and then _cexit would work,
54 provided we actually find and control all of them (unhandled exceptions
55 and falling off the end of the last thread are non-obvious examples).
56 that aside, it'd require changes to calling code, and we're trying to
57 keep this mess hidden and transparent to users.
58 
59 the remaining alternative is to use atexit. this approach has the
60 advantage of being covered by the CRT runtime checks and leak detector,
61 because those are shut down after the atexit handlers are called.
62 however, it does require that our shutdown callback to be the very last,
63 i.e. registered first. fortunately, the init stage can guarantee this.
64 
65 
66 Init
67 ----
68 
69 For the same reasons as above, our init really should happen before static
70 C++ ctors are called.
71 
72 using WinMain as the entry point and then calling the application's main()
73 doesn't satisy the above requirement, and is expressly forbidden by ANSI C.
74 (VC apparently makes use of this and changes its calling convention.
75 if we call it, everything appears to work but stack traces in release
76 mode are incorrect, since symbol addresses are off by 4 bytes.)
77 
78 another alternative is re#defining the app's main function to app_main,
79 having the OS call our main, and then dispatching to app_main.
80 however, this leads to trouble when another library (e.g. SDL) wants to
81 do the same.
82 moreover, this file is compiled into a static library and used both for
83 the 0ad executable as well as the separate self-test. this means
84 we can't enable the main() hook for one and disable it in the other.
85 
86 requiring users to call us at the beginning of main is brittle in general,
87 comes after static ctors, and is difficult to achieve in external code
88 such as the (automatically generated) self-test.
89 
90 commandeering the entry point, doing init there and then calling
91 mainCRTStartup would work, but doesn't allow the use of atexit for shutdown
92 (nor any other non-stateless CRT functions to be called during init).
93 
94 the way out is to have an init-and-call-atexit function triggered by means
95 of the CRT init mechanism. we arrange init order such that this happens
96 before static C++ ctors, thus meeting all of the above requirements.
97 (note: this is possible because crtexe.c and its .CRT$XI and .CRT$XC
98 sections holding static initializers and ctors are linked into the
99 application, not the CRT DLL.)
100 
101 */
102 
103 
104 // reference: see http://www.codeguru.com/cpp/misc/misc/threadsprocesses/article.php/c6945__1
105 
107 {
110  return 0;
111 }
112 
113 
114 // insert our initialization function after _cinit and XIU ("User") block
115 #if ARCH_AMD64
116 # define SECTION_ATTRIBUTES read
117 #else
118 # define SECTION_ATTRIBUTES read,write
119 #endif
120 #pragma section(".CRT$XIV", long,SECTION_ATTRIBUTES)
121 #undef SECTION_ATTRIBUTES
122 EXTERN_C __declspec(allocate(".CRT$XIV")) int(*wstartup_pInitAndRegisterShutdown)() = wstartup_InitAndRegisterShutdown;
123 #pragma comment(linker, "/include:" STRINGIZE(DECORATED_NAME(wstartup_pInitAndRegisterShutdown)))
static __declspec(align(64)) TimerState timerStates[2]
#define EXTERN_C
void winit_CallInitFunctions()
call each registered function.
Definition: winit.cpp:87
EXTERN_C int wstartup_InitAndRegisterShutdown()
Definition: wstartup.cpp:106
void winit_CallShutdownFunctions()
Definition: winit.cpp:92