xref: /reactos/sdk/lib/crt/startup/crtexe.c (revision c2c66aff)
1*c2c66affSColin Finck /**
2*c2c66affSColin Finck  * This file has no copyright assigned and is placed in the Public Domain.
3*c2c66affSColin Finck  * This file is part of the w64 mingw-runtime package.
4*c2c66affSColin Finck  * No warranty is given; refer to the file DISCLAIMER.PD within this package.
5*c2c66affSColin Finck  */
6*c2c66affSColin Finck 
7*c2c66affSColin Finck #undef CRTDLL
8*c2c66affSColin Finck #ifndef _DLL
9*c2c66affSColin Finck #define _DLL
10*c2c66affSColin Finck #endif
11*c2c66affSColin Finck 
12*c2c66affSColin Finck #define SPECIAL_CRTEXE
13*c2c66affSColin Finck 
14*c2c66affSColin Finck #include <oscalls.h>
15*c2c66affSColin Finck #include <internal.h>
16*c2c66affSColin Finck #include <process.h>
17*c2c66affSColin Finck #include <signal.h>
18*c2c66affSColin Finck #include <math.h>
19*c2c66affSColin Finck #include <stdlib.h>
20*c2c66affSColin Finck #include <tchar.h>
21*c2c66affSColin Finck #include <sect_attribs.h>
22*c2c66affSColin Finck #include <locale.h>
23*c2c66affSColin Finck 
24*c2c66affSColin Finck #ifndef __winitenv
25*c2c66affSColin Finck extern wchar_t *** __MINGW_IMP_SYMBOL(__winitenv);
26*c2c66affSColin Finck #define __winitenv (* __MINGW_IMP_SYMBOL(__winitenv))
27*c2c66affSColin Finck #endif
28*c2c66affSColin Finck 
29*c2c66affSColin Finck #ifndef __initenv
30*c2c66affSColin Finck extern char *** __MINGW_IMP_SYMBOL(__initenv);
31*c2c66affSColin Finck #define __initenv (* __MINGW_IMP_SYMBOL(__initenv))
32*c2c66affSColin Finck #endif
33*c2c66affSColin Finck 
34*c2c66affSColin Finck /* Hack, for bug in ld.  Will be removed soon.  */
35*c2c66affSColin Finck #if defined(__GNUC__)
36*c2c66affSColin Finck #define __ImageBase __MINGW_LSYMBOL(_image_base__)
37*c2c66affSColin Finck #endif
38*c2c66affSColin Finck 
39*c2c66affSColin Finck /* This symbol is defined by ld.  */
40*c2c66affSColin Finck extern IMAGE_DOS_HEADER __ImageBase;
41*c2c66affSColin Finck 
42*c2c66affSColin Finck extern void __cdecl _fpreset (void);
43*c2c66affSColin Finck #define SPACECHAR _T(' ')
44*c2c66affSColin Finck #define DQUOTECHAR _T('\"')
45*c2c66affSColin Finck 
46*c2c66affSColin Finck extern int * __MINGW_IMP_SYMBOL(_fmode);
47*c2c66affSColin Finck extern int * __MINGW_IMP_SYMBOL(_commode);
48*c2c66affSColin Finck 
49*c2c66affSColin Finck #undef _fmode
50*c2c66affSColin Finck extern int _fmode;
51*c2c66affSColin Finck extern int * __MINGW_IMP_SYMBOL(_commode);
52*c2c66affSColin Finck #define _commode (* __MINGW_IMP_SYMBOL(_commode))
53*c2c66affSColin Finck extern int _dowildcard;
54*c2c66affSColin Finck 
55*c2c66affSColin Finck extern _CRTIMP void __cdecl _initterm(_PVFV *, _PVFV *);
56*c2c66affSColin Finck 
57*c2c66affSColin Finck static int __cdecl check_managed_app (void);
58*c2c66affSColin Finck 
59*c2c66affSColin Finck extern _CRTALLOC(".CRT$XIA") _PIFV __xi_a[];
60*c2c66affSColin Finck extern _CRTALLOC(".CRT$XIZ") _PIFV __xi_z[];
61*c2c66affSColin Finck extern _CRTALLOC(".CRT$XCA") _PVFV __xc_a[];
62*c2c66affSColin Finck extern _CRTALLOC(".CRT$XCZ") _PVFV __xc_z[];
63*c2c66affSColin Finck 
64*c2c66affSColin Finck /* TLS initialization hook.  */
65*c2c66affSColin Finck extern const PIMAGE_TLS_CALLBACK __dyn_tls_init_callback;
66*c2c66affSColin Finck 
67*c2c66affSColin Finck extern _PVFV *__onexitbegin;
68*c2c66affSColin Finck extern _PVFV *__onexitend;
69*c2c66affSColin Finck 
70*c2c66affSColin Finck extern int mingw_app_type;
71*c2c66affSColin Finck 
72*c2c66affSColin Finck HINSTANCE __mingw_winmain_hInstance;
73*c2c66affSColin Finck _TCHAR *__mingw_winmain_lpCmdLine;
74*c2c66affSColin Finck DWORD __mingw_winmain_nShowCmd;
75*c2c66affSColin Finck 
76*c2c66affSColin Finck static int argc;
77*c2c66affSColin Finck extern void __main(void);
78*c2c66affSColin Finck #ifdef WPRFLAG
79*c2c66affSColin Finck static wchar_t **argv;
80*c2c66affSColin Finck static wchar_t **envp;
81*c2c66affSColin Finck #else
82*c2c66affSColin Finck static char **argv;
83*c2c66affSColin Finck static char **envp;
84*c2c66affSColin Finck #endif
85*c2c66affSColin Finck 
86*c2c66affSColin Finck static int argret;
87*c2c66affSColin Finck static int mainret=0;
88*c2c66affSColin Finck static int managedapp;
89*c2c66affSColin Finck static int has_cctor = 0;
90*c2c66affSColin Finck static _startupinfo startinfo;
91*c2c66affSColin Finck extern LPTOP_LEVEL_EXCEPTION_FILTER __mingw_oldexcpt_handler;
92*c2c66affSColin Finck 
93*c2c66affSColin Finck extern void _pei386_runtime_relocator (void);
94*c2c66affSColin Finck long CALLBACK _gnu_exception_handler (EXCEPTION_POINTERS * exception_data);
95*c2c66affSColin Finck #ifdef WPRFLAG
96*c2c66affSColin Finck static void duplicate_ppstrings (int ac, wchar_t ***av);
97*c2c66affSColin Finck #else
98*c2c66affSColin Finck static void duplicate_ppstrings (int ac, char ***av);
99*c2c66affSColin Finck #endif
100*c2c66affSColin Finck 
101*c2c66affSColin Finck static int __cdecl pre_c_init (void);
102*c2c66affSColin Finck static void __cdecl pre_cpp_init (void);
103*c2c66affSColin Finck static void __cdecl __mingw_prepare_except_for_msvcr80_and_higher (void);
104*c2c66affSColin Finck _CRTALLOC(".CRT$XIAA") _PIFV mingw_pcinit = pre_c_init;
105*c2c66affSColin Finck _CRTALLOC(".CRT$XCAA") _PVFV mingw_pcppinit = pre_cpp_init;
106*c2c66affSColin Finck 
107*c2c66affSColin Finck extern int _MINGW_INSTALL_DEBUG_MATHERR;
108*c2c66affSColin Finck 
109*c2c66affSColin Finck static int __cdecl
110*c2c66affSColin Finck pre_c_init (void)
111*c2c66affSColin Finck {
112*c2c66affSColin Finck   managedapp = check_managed_app ();
113*c2c66affSColin Finck   if (mingw_app_type)
114*c2c66affSColin Finck     __set_app_type(_GUI_APP);
115*c2c66affSColin Finck   else
116*c2c66affSColin Finck     __set_app_type (_CONSOLE_APP);
117*c2c66affSColin Finck   __onexitbegin = __onexitend = (_PVFV *) _encode_pointer ((_PVFV *)(-1));
118*c2c66affSColin Finck 
119*c2c66affSColin Finck   * __MINGW_IMP_SYMBOL(_fmode) = _fmode;
120*c2c66affSColin Finck   * __MINGW_IMP_SYMBOL(_commode) = _commode;
121*c2c66affSColin Finck 
122*c2c66affSColin Finck #ifdef WPRFLAG
123*c2c66affSColin Finck   _wsetargv();
124*c2c66affSColin Finck #else
125*c2c66affSColin Finck   _setargv();
126*c2c66affSColin Finck #endif
127*c2c66affSColin Finck   if (_MINGW_INSTALL_DEBUG_MATHERR == 1)
128*c2c66affSColin Finck     {
129*c2c66affSColin Finck       __setusermatherr (_matherr);
130*c2c66affSColin Finck     }
131*c2c66affSColin Finck 
132*c2c66affSColin Finck   if (__globallocalestatus == -1)
133*c2c66affSColin Finck     {
134*c2c66affSColin Finck     }
135*c2c66affSColin Finck   return 0;
136*c2c66affSColin Finck }
137*c2c66affSColin Finck 
138*c2c66affSColin Finck static void __cdecl
139*c2c66affSColin Finck pre_cpp_init (void)
140*c2c66affSColin Finck {
141*c2c66affSColin Finck   startinfo.newmode = _newmode;
142*c2c66affSColin Finck 
143*c2c66affSColin Finck #ifdef WPRFLAG
144*c2c66affSColin Finck   argret = __wgetmainargs(&argc,&argv,&envp,_dowildcard,&startinfo);
145*c2c66affSColin Finck #else
146*c2c66affSColin Finck   argret = __getmainargs(&argc,&argv,&envp,_dowildcard,&startinfo);
147*c2c66affSColin Finck #endif
148*c2c66affSColin Finck }
149*c2c66affSColin Finck 
150*c2c66affSColin Finck static int __cdecl __tmainCRTStartup (void);
151*c2c66affSColin Finck 
152*c2c66affSColin Finck int __cdecl WinMainCRTStartup (void);
153*c2c66affSColin Finck 
154*c2c66affSColin Finck int __cdecl WinMainCRTStartup (void)
155*c2c66affSColin Finck {
156*c2c66affSColin Finck   int ret = 255;
157*c2c66affSColin Finck #ifdef __SEH__
158*c2c66affSColin Finck   asm ("\t.l_startw:\n"
159*c2c66affSColin Finck     "\t.seh_handler __C_specific_handler, @except\n"
160*c2c66affSColin Finck     "\t.seh_handlerdata\n"
161*c2c66affSColin Finck     "\t.long 1\n"
162*c2c66affSColin Finck     "\t.rva .l_startw, .l_endw, _gnu_exception_handler ,.l_endw\n"
163*c2c66affSColin Finck     "\t.text"
164*c2c66affSColin Finck     );
165*c2c66affSColin Finck #endif
166*c2c66affSColin Finck   mingw_app_type = 1;
167*c2c66affSColin Finck   __security_init_cookie ();
168*c2c66affSColin Finck   ret = __tmainCRTStartup ();
169*c2c66affSColin Finck #ifdef __SEH__
170*c2c66affSColin Finck   asm ("\tnop\n"
171*c2c66affSColin Finck     "\t.l_endw: nop\n");
172*c2c66affSColin Finck #endif
173*c2c66affSColin Finck   return ret;
174*c2c66affSColin Finck }
175*c2c66affSColin Finck 
176*c2c66affSColin Finck int __cdecl mainCRTStartup (void);
177*c2c66affSColin Finck 
178*c2c66affSColin Finck #ifdef _WIN64
179*c2c66affSColin Finck int __mingw_init_ehandler (void);
180*c2c66affSColin Finck #endif
181*c2c66affSColin Finck 
182*c2c66affSColin Finck int __cdecl mainCRTStartup (void)
183*c2c66affSColin Finck {
184*c2c66affSColin Finck   int ret = 255;
185*c2c66affSColin Finck #ifdef __SEH__
186*c2c66affSColin Finck   asm ("\t.l_start:\n"
187*c2c66affSColin Finck     "\t.seh_handler __C_specific_handler, @except\n"
188*c2c66affSColin Finck     "\t.seh_handlerdata\n"
189*c2c66affSColin Finck     "\t.long 1\n"
190*c2c66affSColin Finck     "\t.rva .l_start, .l_end, _gnu_exception_handler ,.l_end\n"
191*c2c66affSColin Finck     "\t.text"
192*c2c66affSColin Finck     );
193*c2c66affSColin Finck #endif
194*c2c66affSColin Finck   mingw_app_type = 0;
195*c2c66affSColin Finck   __security_init_cookie ();
196*c2c66affSColin Finck   ret = __tmainCRTStartup ();
197*c2c66affSColin Finck #ifdef __SEH__
198*c2c66affSColin Finck   asm ("\tnop\n"
199*c2c66affSColin Finck     "\t.l_end: nop\n");
200*c2c66affSColin Finck #endif
201*c2c66affSColin Finck   return ret;
202*c2c66affSColin Finck }
203*c2c66affSColin Finck 
204*c2c66affSColin Finck static
205*c2c66affSColin Finck __declspec(noinline)
206*c2c66affSColin Finck int __cdecl
207*c2c66affSColin Finck __tmainCRTStartup (void)
208*c2c66affSColin Finck {
209*c2c66affSColin Finck   _TCHAR *lpszCommandLine = NULL;
210*c2c66affSColin Finck   STARTUPINFO StartupInfo;
211*c2c66affSColin Finck   WINBOOL inDoubleQuote = FALSE;
212*c2c66affSColin Finck   memset (&StartupInfo, 0, sizeof (STARTUPINFO));
213*c2c66affSColin Finck 
214*c2c66affSColin Finck #ifndef _WIN64
215*c2c66affSColin Finck   /* We need to make sure that this function is build with frame-pointer
216*c2c66affSColin Finck      and that we align the stack to 16 bytes for the sake of SSE ops in main
217*c2c66affSColin Finck      or in functions inlined into main.  */
218*c2c66affSColin Finck   lpszCommandLine = (_TCHAR *) alloca (32);
219*c2c66affSColin Finck   memset (lpszCommandLine, 0xcc, 32);
220*c2c66affSColin Finck #ifdef __GNUC__
221*c2c66affSColin Finck   asm  __volatile__  ("andl $-16, %%esp" : : : "%esp");
222*c2c66affSColin Finck #endif
223*c2c66affSColin Finck #endif
224*c2c66affSColin Finck 
225*c2c66affSColin Finck   if (mingw_app_type)
226*c2c66affSColin Finck     GetStartupInfo (&StartupInfo);
227*c2c66affSColin Finck   {
228*c2c66affSColin Finck     void *lock_free = NULL;
229*c2c66affSColin Finck     void *fiberid = ((PNT_TIB)NtCurrentTeb())->StackBase;
230*c2c66affSColin Finck     int nested = FALSE;
231*c2c66affSColin Finck     while((lock_free = InterlockedCompareExchangePointer ((volatile PVOID *) &__native_startup_lock,
232*c2c66affSColin Finck 							  fiberid, 0)) != 0)
233*c2c66affSColin Finck       {
234*c2c66affSColin Finck 	if (lock_free == fiberid)
235*c2c66affSColin Finck 	  {
236*c2c66affSColin Finck 	    nested = TRUE;
237*c2c66affSColin Finck 	    break;
238*c2c66affSColin Finck 	  }
239*c2c66affSColin Finck 	Sleep(1000);
240*c2c66affSColin Finck       }
241*c2c66affSColin Finck     if (__native_startup_state == __initializing)
242*c2c66affSColin Finck       {
243*c2c66affSColin Finck 	_amsg_exit (31);
244*c2c66affSColin Finck       }
245*c2c66affSColin Finck     else if (__native_startup_state == __uninitialized)
246*c2c66affSColin Finck       {
247*c2c66affSColin Finck 	__native_startup_state = __initializing;
248*c2c66affSColin Finck 	_initterm ((_PVFV *)(void *)__xi_a, (_PVFV *)(void *) __xi_z);
249*c2c66affSColin Finck       }
250*c2c66affSColin Finck     else
251*c2c66affSColin Finck       has_cctor = 1;
252*c2c66affSColin Finck 
253*c2c66affSColin Finck     if (__native_startup_state == __initializing)
254*c2c66affSColin Finck       {
255*c2c66affSColin Finck 	_initterm (__xc_a, __xc_z);
256*c2c66affSColin Finck 	__native_startup_state = __initialized;
257*c2c66affSColin Finck       }
258*c2c66affSColin Finck     _ASSERTE(__native_startup_state == __initialized);
259*c2c66affSColin Finck     if (! nested)
260*c2c66affSColin Finck       (VOID)InterlockedExchangePointer ((volatile PVOID *) &__native_startup_lock, 0);
261*c2c66affSColin Finck 
262*c2c66affSColin Finck     if (__dyn_tls_init_callback != NULL)
263*c2c66affSColin Finck       __dyn_tls_init_callback (NULL, DLL_THREAD_ATTACH, NULL);
264*c2c66affSColin Finck 
265*c2c66affSColin Finck     _pei386_runtime_relocator ();
266*c2c66affSColin Finck     __mingw_oldexcpt_handler = SetUnhandledExceptionFilter (_gnu_exception_handler);
267*c2c66affSColin Finck #ifdef _WIN64
268*c2c66affSColin Finck     __mingw_init_ehandler ();
269*c2c66affSColin Finck #endif
270*c2c66affSColin Finck     __mingw_prepare_except_for_msvcr80_and_higher ();
271*c2c66affSColin Finck 
272*c2c66affSColin Finck     _fpreset ();
273*c2c66affSColin Finck 
274*c2c66affSColin Finck     if (mingw_app_type)
275*c2c66affSColin Finck       {
276*c2c66affSColin Finck #ifdef WPRFLAG
277*c2c66affSColin Finck 	lpszCommandLine = (_TCHAR *) _wcmdln;
278*c2c66affSColin Finck #else
279*c2c66affSColin Finck 	lpszCommandLine = (char *) _acmdln;
280*c2c66affSColin Finck #endif
281*c2c66affSColin Finck 	while (*lpszCommandLine > SPACECHAR || (*lpszCommandLine && inDoubleQuote))
282*c2c66affSColin Finck 	  {
283*c2c66affSColin Finck 	    if (*lpszCommandLine == DQUOTECHAR)
284*c2c66affSColin Finck 	      inDoubleQuote = !inDoubleQuote;
285*c2c66affSColin Finck #ifdef _MBCS
286*c2c66affSColin Finck 	    if (_ismbblead (*lpszCommandLine))
287*c2c66affSColin Finck 	      {
288*c2c66affSColin Finck 		if (lpszCommandLine) /* FIXME: Why this check? Should I check for *lpszCommandLine != 0 too? */
289*c2c66affSColin Finck 		  lpszCommandLine++;
290*c2c66affSColin Finck 	      }
291*c2c66affSColin Finck #endif
292*c2c66affSColin Finck 	    ++lpszCommandLine;
293*c2c66affSColin Finck 	  }
294*c2c66affSColin Finck 	while (*lpszCommandLine && (*lpszCommandLine <= SPACECHAR))
295*c2c66affSColin Finck 	  lpszCommandLine++;
296*c2c66affSColin Finck 
297*c2c66affSColin Finck 	__mingw_winmain_hInstance = (HINSTANCE) &__ImageBase;
298*c2c66affSColin Finck 	__mingw_winmain_lpCmdLine = lpszCommandLine;
299*c2c66affSColin Finck 	__mingw_winmain_nShowCmd = StartupInfo.dwFlags & STARTF_USESHOWWINDOW ?
300*c2c66affSColin Finck 				    StartupInfo.wShowWindow : SW_SHOWDEFAULT;
301*c2c66affSColin Finck       }
302*c2c66affSColin Finck     duplicate_ppstrings (argc, &argv);
303*c2c66affSColin Finck     __main ();
304*c2c66affSColin Finck #ifdef WPRFLAG
305*c2c66affSColin Finck     __winitenv = envp;
306*c2c66affSColin Finck     /* C++ initialization.
307*c2c66affSColin Finck        gcc inserts this call automatically for a function called main, but not for wmain.  */
308*c2c66affSColin Finck     mainret = wmain (argc, argv, envp);
309*c2c66affSColin Finck #else
310*c2c66affSColin Finck     __initenv = envp;
311*c2c66affSColin Finck     mainret = main (argc, argv, envp);
312*c2c66affSColin Finck #endif
313*c2c66affSColin Finck     if (!managedapp)
314*c2c66affSColin Finck       exit (mainret);
315*c2c66affSColin Finck 
316*c2c66affSColin Finck     if (has_cctor == 0)
317*c2c66affSColin Finck       _cexit ();
318*c2c66affSColin Finck   }
319*c2c66affSColin Finck   return mainret;
320*c2c66affSColin Finck }
321*c2c66affSColin Finck 
322*c2c66affSColin Finck extern int mingw_initltsdrot_force;
323*c2c66affSColin Finck extern int mingw_initltsdyn_force;
324*c2c66affSColin Finck extern int mingw_initltssuo_force;
325*c2c66affSColin Finck extern int mingw_initcharmax;
326*c2c66affSColin Finck 
327*c2c66affSColin Finck static int __cdecl
328*c2c66affSColin Finck check_managed_app (void)
329*c2c66affSColin Finck {
330*c2c66affSColin Finck   PIMAGE_DOS_HEADER pDOSHeader;
331*c2c66affSColin Finck   PIMAGE_NT_HEADERS pPEHeader;
332*c2c66affSColin Finck   PIMAGE_OPTIONAL_HEADER32 pNTHeader32;
333*c2c66affSColin Finck   PIMAGE_OPTIONAL_HEADER64 pNTHeader64;
334*c2c66affSColin Finck 
335*c2c66affSColin Finck   /* Force to be linked.  */
336*c2c66affSColin Finck   mingw_initltsdrot_force=1;
337*c2c66affSColin Finck   mingw_initltsdyn_force=1;
338*c2c66affSColin Finck   mingw_initltssuo_force=1;
339*c2c66affSColin Finck   mingw_initcharmax=1;
340*c2c66affSColin Finck 
341*c2c66affSColin Finck   pDOSHeader = (PIMAGE_DOS_HEADER) &__ImageBase;
342*c2c66affSColin Finck   if (pDOSHeader->e_magic != IMAGE_DOS_SIGNATURE)
343*c2c66affSColin Finck     return 0;
344*c2c66affSColin Finck 
345*c2c66affSColin Finck   pPEHeader = (PIMAGE_NT_HEADERS)((char *)pDOSHeader + pDOSHeader->e_lfanew);
346*c2c66affSColin Finck   if (pPEHeader->Signature != IMAGE_NT_SIGNATURE)
347*c2c66affSColin Finck     return 0;
348*c2c66affSColin Finck 
349*c2c66affSColin Finck   pNTHeader32 = (PIMAGE_OPTIONAL_HEADER32) &pPEHeader->OptionalHeader;
350*c2c66affSColin Finck   switch (pNTHeader32->Magic)
351*c2c66affSColin Finck     {
352*c2c66affSColin Finck     case IMAGE_NT_OPTIONAL_HDR32_MAGIC:
353*c2c66affSColin Finck       if (pNTHeader32->NumberOfRvaAndSizes <= IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR)
354*c2c66affSColin Finck 	return 0;
355*c2c66affSColin Finck       return !! pNTHeader32->DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress;
356*c2c66affSColin Finck     case IMAGE_NT_OPTIONAL_HDR64_MAGIC:
357*c2c66affSColin Finck       pNTHeader64 = (PIMAGE_OPTIONAL_HEADER64)pNTHeader32;
358*c2c66affSColin Finck       if (pNTHeader64->NumberOfRvaAndSizes <= IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR)
359*c2c66affSColin Finck 	return 0;
360*c2c66affSColin Finck       return !! pNTHeader64->DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress;
361*c2c66affSColin Finck     }
362*c2c66affSColin Finck   return 0;
363*c2c66affSColin Finck }
364*c2c66affSColin Finck 
365*c2c66affSColin Finck #ifdef WPRFLAG
366*c2c66affSColin Finck static size_t wbytelen(const wchar_t *p)
367*c2c66affSColin Finck {
368*c2c66affSColin Finck 	size_t ret = 1;
369*c2c66affSColin Finck 	while (*p!=0) {
370*c2c66affSColin Finck 		ret++,++p;
371*c2c66affSColin Finck 	}
372*c2c66affSColin Finck 	return ret*2;
373*c2c66affSColin Finck }
374*c2c66affSColin Finck static void duplicate_ppstrings (int ac, wchar_t ***av)
375*c2c66affSColin Finck {
376*c2c66affSColin Finck 	wchar_t **avl;
377*c2c66affSColin Finck 	int i;
378*c2c66affSColin Finck 	wchar_t **n = (wchar_t **) malloc (sizeof (wchar_t *) * (ac + 1));
379*c2c66affSColin Finck 
380*c2c66affSColin Finck 	avl=*av;
381*c2c66affSColin Finck 	for (i=0; i < ac; i++)
382*c2c66affSColin Finck 	  {
383*c2c66affSColin Finck 		size_t l = wbytelen (avl[i]);
384*c2c66affSColin Finck 		n[i] = (wchar_t *) malloc (l);
385*c2c66affSColin Finck 		memcpy (n[i], avl[i], l);
386*c2c66affSColin Finck 	  }
387*c2c66affSColin Finck 	n[i] = NULL;
388*c2c66affSColin Finck 	*av = n;
389*c2c66affSColin Finck }
390*c2c66affSColin Finck #else
391*c2c66affSColin Finck static void duplicate_ppstrings (int ac, char ***av)
392*c2c66affSColin Finck {
393*c2c66affSColin Finck 	char **avl;
394*c2c66affSColin Finck 	int i;
395*c2c66affSColin Finck 	char **n = (char **) malloc (sizeof (char *) * (ac + 1));
396*c2c66affSColin Finck 
397*c2c66affSColin Finck 	avl=*av;
398*c2c66affSColin Finck 	for (i=0; i < ac; i++)
399*c2c66affSColin Finck 	  {
400*c2c66affSColin Finck 		size_t l = strlen (avl[i]) + 1;
401*c2c66affSColin Finck 		n[i] = (char *) malloc (l);
402*c2c66affSColin Finck 		memcpy (n[i], avl[i], l);
403*c2c66affSColin Finck 	  }
404*c2c66affSColin Finck 	n[i] = NULL;
405*c2c66affSColin Finck 	*av = n;
406*c2c66affSColin Finck }
407*c2c66affSColin Finck #endif
408*c2c66affSColin Finck 
409*c2c66affSColin Finck #ifdef __MINGW_SHOW_INVALID_PARAMETER_EXCEPTION
410*c2c66affSColin Finck #define __UNUSED_PARAM_1(x) x
411*c2c66affSColin Finck #else
412*c2c66affSColin Finck #define __UNUSED_PARAM_1	__UNUSED_PARAM
413*c2c66affSColin Finck #endif
414*c2c66affSColin Finck static void __cdecl
415*c2c66affSColin Finck __mingw_invalidParameterHandler (const wchar_t * __UNUSED_PARAM_1(expression),
416*c2c66affSColin Finck 				 const wchar_t * __UNUSED_PARAM_1(function),
417*c2c66affSColin Finck 				 const wchar_t * __UNUSED_PARAM_1(file),
418*c2c66affSColin Finck 				 unsigned int    __UNUSED_PARAM_1(line),
419*c2c66affSColin Finck 				 uintptr_t __UNUSED_PARAM(pReserved))
420*c2c66affSColin Finck {
421*c2c66affSColin Finck #ifdef __MINGW_SHOW_INVALID_PARAMETER_EXCEPTION
422*c2c66affSColin Finck   wprintf(L"Invalid parameter detected in function %s. File: %s Line: %u\n", function, file, line);
423*c2c66affSColin Finck   wprintf(L"Expression: %s\n", expression);
424*c2c66affSColin Finck #endif
425*c2c66affSColin Finck }
426*c2c66affSColin Finck 
427*c2c66affSColin Finck HANDLE __mingw_get_msvcrt_handle(void);
428*c2c66affSColin Finck 
429*c2c66affSColin Finck static void __cdecl
430*c2c66affSColin Finck __mingw_prepare_except_for_msvcr80_and_higher (void)
431*c2c66affSColin Finck {
432*c2c66affSColin Finck   _invalid_parameter_handler (*fIPH)(_invalid_parameter_handler) = NULL;
433*c2c66affSColin Finck 
434*c2c66affSColin Finck   fIPH = (void*)GetProcAddress (__mingw_get_msvcrt_handle(), "_set_invalid_parameter_handler");
435*c2c66affSColin Finck   if (fIPH)
436*c2c66affSColin Finck     (*fIPH)(__mingw_invalidParameterHandler);
437*c2c66affSColin Finck }
438