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