* DISCLAIMER: Ditto. * CRT_noglob.c: Reword copyright and disclaimer. Move Contributors section CONTRIBUTORS file. Remove RCS tags. * CRTFmode.c: Ditto. * CRTglob.c: Ditto. * CRTinit.c: Ditto. * crt1.c: Ditto. * crtdll.dev: Ditto. * dllcrt1.c: Ditto. * dllmain.c: Ditto. * gccmain.c: Ditto. * init.c: Ditto. * isascii.c: Ditto. * iscsym.c: Ditto. * iscsymf.c: Ditto. * jamfile: Ditto. * main.c: Ditto. * msvcrt.def.in: Ditto. * strcasecmp.c: Ditto. * toascii.c: Ditto. * wcscmpi.c: Ditto. * include/assert.h: Ditto. * include/conio.h: Ditto. * include/ctype.h: Ditto. * include/direct.h: Ditto. * include/dirent.h: Ditto. * include/dos.h: Ditto. * include/errno.h: Ditto. * include/excpt.h: Ditto. * include/fcntl.h: Ditto. * include/float.h: Ditto. * include/io.h: Ditto. * include/locale.h: Ditto. * include/malloc.h: Ditto. * include/math.h: Ditto. * include/process.h: Ditto. * include/setjmp.h: Ditto. * include/share.h: Ditto. * include/signal.h: Ditto. * include/stdio.h: Ditto. * include/stdlib.h: Ditto. * include/string.h: Ditto. * include/tchar.h: Ditto. * include/time.h: Ditto. * include/wchar.h: Ditto. * include/sys/locking.h: Ditto. * include/sys/param.h: Ditto. * include/sys/stat.h: Ditto. * include/sys/timeb.h: Ditto. * include/sys/types.h: Ditto. * include/sys/utime.h: Ditto. * mingwex/dirent.c: Ditto.
		
			
				
	
	
		
			184 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			184 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 * dllcrt1.c
 | 
						|
 * This file has no copyright assigned and is placed in the Public Domain.
 | 
						|
 * This file is a part of the mingw-runtime package.
 | 
						|
 * No warranty is given; refer to the file DISCLAIMER within the package.
 | 
						|
 *
 | 
						|
 * Initialization code for DLLs.
 | 
						|
 *
 | 
						|
 */
 | 
						|
#include <stdlib.h>
 | 
						|
#include <stdio.h>
 | 
						|
#include <io.h>
 | 
						|
#include <process.h>
 | 
						|
#include <errno.h>
 | 
						|
#include <windows.h>
 | 
						|
 | 
						|
/* Unlike normal crt1, I don't initialize the FPU, because the process
 | 
						|
 * should have done that already. I also don't set the file handle modes,
 | 
						|
 * because that would be rude. */
 | 
						|
 | 
						|
#ifdef	__GNUC__
 | 
						|
extern void __main ();
 | 
						|
extern void __do_global_dtors ();
 | 
						|
#endif
 | 
						|
 | 
						|
typedef void (* p_atexit_fn )(void);
 | 
						|
static p_atexit_fn* first_atexit;
 | 
						|
static p_atexit_fn* next_atexit;
 | 
						|
 | 
						|
static void
 | 
						|
__dll_exit (void);
 | 
						|
 | 
						|
/* This  is based on the function in the Wine project's exit.c */
 | 
						|
p_atexit_fn __dllonexit (p_atexit_fn, p_atexit_fn**, p_atexit_fn**);
 | 
						|
 | 
						|
 | 
						|
extern BOOL WINAPI DllMain (HANDLE, DWORD, LPVOID);
 | 
						|
 | 
						|
extern void _pei386_runtime_relocator (void);
 | 
						|
 | 
						|
BOOL WINAPI
 | 
						|
DllMainCRTStartup (HANDLE hDll, DWORD dwReason, LPVOID lpReserved)
 | 
						|
{
 | 
						|
  BOOL bRet;
 | 
						|
 | 
						|
  if (dwReason == DLL_PROCESS_ATTACH)
 | 
						|
    {
 | 
						|
 | 
						|
#ifdef DEBUG
 | 
						|
      printf ("%s: DLL_PROCESS_ATTACH (%d)\n", __FUNCTION__);
 | 
						|
#endif
 | 
						|
 | 
						|
      /* Initialize private atexit table for this dll.
 | 
						|
	 32 is min size required by ANSI */
 | 
						|
 | 
						|
      first_atexit = (p_atexit_fn*) malloc (32 * sizeof (p_atexit_fn));
 | 
						|
      if (first_atexit == NULL ) /* can't allocate memory */
 | 
						|
	{
 | 
						|
	  errno=ENOMEM;
 | 
						|
	  return FALSE;
 | 
						|
	}
 | 
						|
      *first_atexit =  NULL;
 | 
						|
      next_atexit = first_atexit;
 | 
						|
 | 
						|
      /* Adust references to dllimported data (from other DLL's)
 | 
						|
	 that have non-zero offsets.  */ 
 | 
						|
      _pei386_runtime_relocator ();
 | 
						|
 | 
						|
#ifdef	__GNUC__
 | 
						|
      /* From libgcc.a, __main calls global class constructors,
 | 
						|
	 __do_global_ctors, which registers __do_global_dtors
 | 
						|
	 as the first entry of the private atexit table we
 | 
						|
	 have just initialised  */
 | 
						|
      __main ();
 | 
						|
      	
 | 
						|
#endif
 | 
						|
   }
 | 
						|
 | 
						|
  /*
 | 
						|
   * Call the user-supplied DllMain subroutine.
 | 
						|
   * This has to come after initialization of atexit table and
 | 
						|
   * registration of global constructors.
 | 
						|
   * NOTE: DllMain is optional, so libmingw32.a includes a stub
 | 
						|
   *       which will be used if the user does not supply one.
 | 
						|
   */
 | 
						|
 | 
						|
  bRet = DllMain (hDll, dwReason, lpReserved);
 | 
						|
  /* Handle case where DllMain returns FALSE on attachment attempt.  */ 
 | 
						|
 | 
						|
  if ( (dwReason == DLL_PROCESS_ATTACH) && !bRet)
 | 
						|
    {
 | 
						|
#ifdef DEBUG
 | 
						|
      printf ("%s: DLL_PROCESS_ATTACH failed, cleaning up\n", __FUNCTION__);
 | 
						|
#endif
 | 
						|
 | 
						|
      __dll_exit ();     /* Cleanup now. This will set first_atexit to NULL so we
 | 
						|
			    know we've cleaned up	*/
 | 
						|
    }
 | 
						|
 | 
						|
  if (dwReason == DLL_PROCESS_DETACH)
 | 
						|
    {
 | 
						|
#ifdef DEBUG
 | 
						|
      printf ("%s: DLL_PROCESS_DETACH (%d)\n", __FUNCTION__);
 | 
						|
#endif
 | 
						|
      /* If not attached, return FALSE. Cleanup already done above
 | 
						|
	 if failed attachment attempt. */
 | 
						|
      if  (! first_atexit )
 | 
						|
        bRet = FALSE;
 | 
						|
      else
 | 
						|
	/*
 | 
						|
	 * We used to call __do_global_dtors () here. This is
 | 
						|
	 * no longer necessary since  __do_global_dtors is now
 | 
						|
	 * registered at start (last out) of private atexit table.
 | 
						|
	 */
 | 
						|
	__dll_exit ();
 | 
						|
    }
 | 
						|
  return bRet;
 | 
						|
}
 | 
						|
 | 
						|
static
 | 
						|
void
 | 
						|
__dll_exit(void)
 | 
						|
/* Run LIFO terminators registered in private atexit table */
 | 
						|
{
 | 
						|
  if ( first_atexit )
 | 
						|
    {
 | 
						|
      p_atexit_fn* __last = next_atexit - 1;
 | 
						|
      while ( __last >= first_atexit )
 | 
						|
	{	
 | 
						|
          if ( *__last != NULL )
 | 
						|
	    {
 | 
						|
#ifdef DEBUG
 | 
						|
	      printf ("%s: Calling exit function  0x%x from 0x%x\n",
 | 
						|
		      __FUNCTION__, (unsigned)(*__last),(unsigned)__last);
 | 
						|
#endif
 | 
						|
              (**__last) ();
 | 
						|
	    }
 | 
						|
	  __last--;
 | 
						|
	}
 | 
						|
      free ( first_atexit ) ;
 | 
						|
      first_atexit = NULL ;
 | 
						|
    }
 | 
						|
    /*
 | 
						|
       Make sure output buffers opened by DllMain or 
 | 
						|
       atexit-registered functions are flushed before detaching,
 | 
						|
       otherwise we can have problems with redirected output.
 | 
						|
     */
 | 
						|
    fflush (NULL);
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * The atexit exported from msvcrt.dll causes problems in DLLs.
 | 
						|
 * Here, we override the exported version of atexit with one that passes the
 | 
						|
 * private table initialised in DllMainCRTStartup to __dllonexit.
 | 
						|
 * That means we have to hide the mscvrt.dll atexit because the
 | 
						|
 * atexit defined here gets __dllonexit from the same lib. 
 | 
						|
 */
 | 
						|
 | 
						|
int
 | 
						|
atexit (p_atexit_fn pfn )
 | 
						|
{
 | 
						|
#ifdef DEBUG
 | 
						|
  printf ("%s: registering exit function  0x%x at 0x%x\n",
 | 
						|
	  __FUNCTION__, (unsigned)pfn, (unsigned)next_atexit);
 | 
						|
#endif
 | 
						|
  return (__dllonexit (pfn,  &first_atexit, &next_atexit)
 | 
						|
	  == NULL ? -1  : 0 );
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * Likewise for non-ANSI function _onexit that may be called by
 | 
						|
 * code in the dll. 
 | 
						|
 */
 | 
						|
 | 
						|
_onexit_t
 | 
						|
_onexit (_onexit_t pfn )
 | 
						|
{
 | 
						|
#ifdef DEBUG
 | 
						|
  printf ("%s: registering exit function  0x%x at 0x%x\n",
 | 
						|
	  __FUNCTION__, (unsigned)pfn, (unsigned)next_atexit);
 | 
						|
#endif
 | 
						|
  return ((_onexit_t) __dllonexit ((p_atexit_fn)pfn,  &first_atexit, &next_atexit));
 | 
						|
}
 |