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 /* Unlike normal crt1, I don't initialize the FPU, because the process
18 * should have done that already. I also don't set the file handle modes,
19 * because that would be rude. */
22 extern void __main ();
23 extern void __do_global_dtors ();
26 typedef void (* p_atexit_fn )(void);
27 static p_atexit_fn* first_atexit;
28 static p_atexit_fn* next_atexit;
33 /* This is based on the function in the Wine project's exit.c */
34 p_atexit_fn __dllonexit (p_atexit_fn, p_atexit_fn**, p_atexit_fn**);
37 extern BOOL WINAPI DllMain (HANDLE, DWORD, LPVOID);
39 extern void _pei386_runtime_relocator (void);
42 DllMainCRTStartup (HANDLE hDll, DWORD dwReason, LPVOID lpReserved)
46 if (dwReason == DLL_PROCESS_ATTACH)
50 printf ("%s: DLL_PROCESS_ATTACH (%d)\n", __FUNCTION__);
53 /* Initialize private atexit table for this dll.
54 32 is min size required by ANSI */
56 first_atexit = (p_atexit_fn*) malloc (32 * sizeof (p_atexit_fn));
57 if (first_atexit == NULL ) /* can't allocate memory */
63 next_atexit = first_atexit;
65 /* Adust references to dllimported data (from other DLL's)
66 that have non-zero offsets. */
67 _pei386_runtime_relocator ();
70 /* From libgcc.a, __main calls global class constructors,
71 __do_global_ctors, which registers __do_global_dtors
72 as the first entry of the private atexit table we
73 have just initialised */
80 * Call the user-supplied DllMain subroutine.
81 * This has to come after initialization of atexit table and
82 * registration of global constructors.
83 * NOTE: DllMain is optional, so libmingw32.a includes a stub
84 * which will be used if the user does not supply one.
87 bRet = DllMain (hDll, dwReason, lpReserved);
88 /* Handle case where DllMain returns FALSE on attachment attempt. */
90 if ( (dwReason == DLL_PROCESS_ATTACH) && !bRet)
93 printf ("%s: DLL_PROCESS_ATTACH failed, cleaning up\n", __FUNCTION__);
96 __dll_exit (); /* Cleanup now. This will set first_atexit to NULL so we
97 know we've cleaned up */
100 if (dwReason == DLL_PROCESS_DETACH)
103 printf ("%s: DLL_PROCESS_DETACH (%d)\n", __FUNCTION__);
105 /* If not attached, return FALSE. Cleanup already done above
106 if failed attachment attempt. */
111 * We used to call __do_global_dtors () here. This is
112 * no longer necessary since __do_global_dtors is now
113 * registered at start (last out) of private atexit table.
123 /* Run LIFO terminators registered in private atexit table */
127 p_atexit_fn* __last = next_atexit - 1;
128 while ( __last >= first_atexit )
130 if ( *__last != NULL )
133 printf ("%s: Calling exit function 0x%x from 0x%x\n",
134 __FUNCTION__, (unsigned)(*__last),(unsigned)__last);
140 free ( first_atexit ) ;
141 first_atexit = NULL ;
144 Make sure output buffers opened by DllMain or
145 atexit-registered functions are flushed before detaching,
146 otherwise we can have problems with redirected output.
152 * The atexit exported from msvcrt.dll causes problems in DLLs.
153 * Here, we override the exported version of atexit with one that passes the
154 * private table initialised in DllMainCRTStartup to __dllonexit.
155 * That means we have to hide the mscvrt.dll atexit because the
156 * atexit defined here gets __dllonexit from the same lib.
160 atexit (p_atexit_fn pfn )
163 printf ("%s: registering exit function 0x%x at 0x%x\n",
164 __FUNCTION__, (unsigned)pfn, (unsigned)next_atexit);
166 return (__dllonexit (pfn, &first_atexit, &next_atexit)
171 * Likewise for non-ANSI function _onexit that may be called by
176 _onexit (_onexit_t pfn )
179 printf ("%s: registering exit function 0x%x at 0x%x\n",
180 __FUNCTION__, (unsigned)pfn, (unsigned)next_atexit);
182 return ((_onexit_t) __dllonexit ((p_atexit_fn)pfn, &first_atexit, &next_atexit));