3 * This file has no copyright assigned and is placed in the Public Domain.
4 * This file is a part of the mingw-runtime package.
5 * No warranty is given; refer to the file DISCLAIMER within the package.
7 * Initialization code for DLLs.
17 /* TLS initialization hook. */
18 extern const PIMAGE_TLS_CALLBACK __dyn_tls_init_callback;
20 /* Unlike normal crt1, I don't initialize the FPU, because the process
21 * should have done that already. I also don't set the file handle modes,
22 * because that would be rude. */
25 extern void __main ();
26 extern void __do_global_dtors ();
29 typedef void (* p_atexit_fn )(void);
30 static p_atexit_fn* first_atexit;
31 static p_atexit_fn* next_atexit;
36 /* This is based on the function in the Wine project's exit.c */
37 p_atexit_fn __dllonexit (p_atexit_fn, p_atexit_fn**, p_atexit_fn**);
40 extern BOOL WINAPI DllMain (HANDLE, DWORD, LPVOID);
42 extern void _pei386_runtime_relocator (void);
45 DllMainCRTStartup (HANDLE hDll, DWORD dwReason, LPVOID lpReserved)
49 if (dwReason == DLL_PROCESS_ATTACH)
53 printf ("%s: DLL_PROCESS_ATTACH (%d)\n", __FUNCTION__);
56 /* Initialize private atexit table for this dll.
57 32 is min size required by ANSI */
59 first_atexit = (p_atexit_fn*) malloc (32 * sizeof (p_atexit_fn));
60 if (first_atexit == NULL ) /* can't allocate memory */
66 next_atexit = first_atexit;
68 /* Initialize TLS callback. */
69 if (__dyn_tls_init_callback != NULL)
71 __dyn_tls_init_callback (hDll, DLL_THREAD_ATTACH, lpReserved);
74 /* Adust references to dllimported data (from other DLL's)
75 that have non-zero offsets. */
76 _pei386_runtime_relocator ();
79 /* From libgcc.a, __main calls global class constructors,
80 __do_global_ctors, which registers __do_global_dtors
81 as the first entry of the private atexit table we
82 have just initialised */
89 * Call the user-supplied DllMain subroutine.
90 * This has to come after initialization of atexit table and
91 * registration of global constructors.
92 * NOTE: DllMain is optional, so libmingw32.a includes a stub
93 * which will be used if the user does not supply one.
96 bRet = DllMain (hDll, dwReason, lpReserved);
97 /* Handle case where DllMain returns FALSE on attachment attempt. */
99 if ( (dwReason == DLL_PROCESS_ATTACH) && !bRet)
102 printf ("%s: DLL_PROCESS_ATTACH failed, cleaning up\n", __FUNCTION__);
105 __dll_exit (); /* Cleanup now. This will set first_atexit to NULL so we
106 know we've cleaned up */
109 if (dwReason == DLL_PROCESS_DETACH)
112 printf ("%s: DLL_PROCESS_DETACH (%d)\n", __FUNCTION__);
114 /* If not attached, return FALSE. Cleanup already done above
115 if failed attachment attempt. */
120 * We used to call __do_global_dtors () here. This is
121 * no longer necessary since __do_global_dtors is now
122 * registered at start (last out) of private atexit table.
132 /* Run LIFO terminators registered in private atexit table */
136 p_atexit_fn* __last = next_atexit - 1;
137 while ( __last >= first_atexit )
139 if ( *__last != NULL )
142 printf ("%s: Calling exit function 0x%x from 0x%x\n",
143 __FUNCTION__, (unsigned)(*__last),(unsigned)__last);
149 free ( first_atexit ) ;
150 first_atexit = NULL ;
153 Make sure output buffers opened by DllMain or
154 atexit-registered functions are flushed before detaching,
155 otherwise we can have problems with redirected output.
161 * The atexit exported from msvcrt.dll causes problems in DLLs.
162 * Here, we override the exported version of atexit with one that passes the
163 * private table initialised in DllMainCRTStartup to __dllonexit.
164 * That means we have to hide the mscvrt.dll atexit because the
165 * atexit defined here gets __dllonexit from the same lib.
169 atexit (p_atexit_fn pfn )
172 printf ("%s: registering exit function 0x%x at 0x%x\n",
173 __FUNCTION__, (unsigned)pfn, (unsigned)next_atexit);
175 return (__dllonexit (pfn, &first_atexit, &next_atexit)
180 * Likewise for non-ANSI function _onexit that may be called by
185 _onexit (_onexit_t pfn )
188 printf ("%s: registering exit function 0x%x at 0x%x\n",
189 __FUNCTION__, (unsigned)pfn, (unsigned)next_atexit);
191 return ((_onexit_t) __dllonexit ((p_atexit_fn)pfn, &first_atexit, &next_atexit));