diff options
author | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
---|---|---|
committer | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
commit | e611b132f9b8abe35b362e5870b74bce94a1e58e (patch) | |
tree | a5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/crt32/dllstuff/crtdll.c | |
download | NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2 NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip |
Diffstat (limited to 'private/crt32/dllstuff/crtdll.c')
-rw-r--r-- | private/crt32/dllstuff/crtdll.c | 376 |
1 files changed, 376 insertions, 0 deletions
diff --git a/private/crt32/dllstuff/crtdll.c b/private/crt32/dllstuff/crtdll.c new file mode 100644 index 000000000..a03adc428 --- /dev/null +++ b/private/crt32/dllstuff/crtdll.c @@ -0,0 +1,376 @@ +#ifdef CRTDLL +/*** +*crtdll.c - CRT initialization for a DLL using the CRTDLL model of C run-time +* +* Copyright (c) 1991-1994, Microsoft Corporation. All rights reserved. +* +*Purpose: +* This module contains the initialization entry point for the C run-time +* stub in this DLL. All C run-time code is located in the C Run-Time +* Library DLL "CRTDLL.DLL", except for a little bit of start-up code in +* the EXE, and this code in each DLL. This code is necessary to invoke +* the C++ constructors for the C++ code in this DLL. +* +* This entry point should either be specified as the DLL initialization +* entry point, or else it must be called by the DLL initialization entry +* point of the DLL with the same arguments that the entry point receives. +* +*Revision History: +* 05-19-92 SKS Initial version +* 08-01-92 SRW winxcpt.h replaced bu excpt.h which is included by oscalls.h +* 09-16-92 SKS Prepare for C8 C++ for MIPS by calling C++ constructors +* 09-29-92 SKS _CRT_DLL must be a WINAPI function! +* 05-11-93 SKS Add _DllMainCRTStartup as an alternative to _CRT_INIT +* 06-05-93 SRW Pin CRTDLL.DLL in memory once loaded. +* 06-07-93 GJF Added __proc_attached flag. +* 06-07-93 GJF Backed out SteveWo's change of 06-05 and put it into +* crtlib.c +* 06-08-93 SKS Clean up failure handling in _CRT_INIT +* 07-16-93 SRW ALPHA Merge +* 12-02-93 SKS Add atexit/_onexit support. These routines must be +* defined here so that DLL's that are linked with +* CRTDLL.LIB will get these versions (suitable for DLLs), +* not the versions of atexit/_onexit from CRTDLL.DLL, +* which are only suitable for an EXE file. +* 07-18-94 GJF Moved over Win32s support from VC 2.0 tree. +* +*******************************************************************************/ + +/* + * SPECIAL BUILD MACRO! Note that crtexe.c (and crtexew.c) is linked in with + * the client's code. It does not go into crtdll.dll! Therefore, it must be + * built under the _DLL switch (like user code) and CRTDLL must be undefined. + */ +#undef CRTDLL +#define _DLL + +#include <cruntime.h> +#include <oscalls.h> +#include <internal.h> +#include <stdlib.h> +#define _DECL_DLLMAIN /* enable prototypes for DllMain and _CRT_INIT */ +#include <process.h> + +/* + * routine in DLL to do initialization (in this case, C++ constructors) + */ +typedef void (_CALLTYPE1 *PF)(void); + +extern void _CALLTYPE4 _initterm(PF *, PF *); + +/* + * pointers to initialization sections + */ +extern PF __xc_a[], __xc_z[]; /* C++ initializers */ + +/* + * Flag identifying the host as Win32s or not-Win32s. + */ +int __win32sflag = 0; + +static int onexitflag = 0; + +/* + * flag set iff _CRTDLL_INIT was called with DLL_PROCESS_ATTACH + */ +static int __proc_attached = 0; + +/* + * Pointers to beginning and end of the table of function pointers manipulated + * by _onexit()/atexit(). The atexit/_onexit code is shared for both EXE's and + * DLL's but different behavior is required. These values are initialized to + * 0 by default and will be set to point to a malloc-ed memory block to mark + * this module as an DLL. + */ + +PF *__onexitbegin; +PF *__onexitend; + + +/* + * User routine DllMain is called on all notifications + */ + +extern BOOL WINAPI DllMain( + HANDLE hDllHandle, + DWORD dwReason, + LPVOID lpreserved + ) ; + +/*** +*BOOL WINAPI _CRT_INIT(hDllHandle, dwReason, lpreserved) - C++ DLL initialization. +* +*Purpose: +* This routine does the C runtime initialization for a DLL using CRTDLL. +* It may be specified as the entry point for the DLL, or it may be +* called by the routine that is the DLL entry point. +* +* On DLL_PROCESS_ATTACH, the C++ constructors for the DLL will be called. +* +* On DLL_PROCESS_DETACH, the C++ destructors and _onexit/atexit routines +* will be called. +* +*Entry: +* +*Exit: +* +*******************************************************************************/ + +BOOL WINAPI _CRT_INIT( + HANDLE hDllHandle, + DWORD dwReason, + LPVOID lpreserved + ) +{ + unsigned osver; + + /* + * First, set the __proc_attached flag + */ + if ( dwReason == DLL_PROCESS_ATTACH ) + __proc_attached++; + else if ( dwReason == DLL_PROCESS_DETACH ) { + if ( __proc_attached > 0 ) + __proc_attached--; + else + /* + * no prior process attach. just return failure. + */ + return FALSE; + } + + /* + * Get the host version (on first call). + */ + if ( __win32sflag == 0 ) { + osver = GetVersion(); + if ( ((osver & 0x00ff) == 3) && ((osver >> 31) & 1) ) + __win32sflag++; + else + __win32sflag--; + } + + + /* + * do C++ constructors (initializers) specific to this DLL + */ + + if ( dwReason == DLL_PROCESS_ATTACH ) { + + /* + * If the host is Win32s, create the onexit table and do C++ + * constructors only for the first connecting process. + */ + if ( (__win32sflag < 0) || (__proc_attached == 1) ) { + + if ( __win32sflag < 0 ) { + /* + * not Win32s! just malloc the table. + */ + if ( (__onexitbegin = (PF *)malloc(32 * + sizeof(PF))) == NULL ) + /* + * cannot allocate minimal required + * size. generate failure to load DLL + */ + return FALSE; + } + else if ( __proc_attached == 1 ) { + if ( (__onexitbegin = + (PF *)GlobalAlloc( GMEM_FIXED | + GMEM_SHARE, 32 * sizeof(PF) )) == + NULL ) + /* + * cannot allocate minimal required + * size. generate failure to load DLL + */ + return FALSE; + } + + *(__onexitbegin) = (PF) NULL; + + __onexitend = __onexitbegin; + + /* + * Invoke C++ constructors + */ + _initterm(__xc_a,__xc_z); + + } + } + else if ( dwReason == DLL_PROCESS_DETACH ) { + + if ( (__win32sflag < 0) || (__proc_attached == 0) ) + { + /* + * Any basic clean-up code that goes here must be + * duplicated below in _DllMainCRTStartup for the + * case where the user's DllMain() routine fails on a + * Process Attach notification. This does not include + * calling user C++ destructors, etc. + */ + + /* + * do _onexit/atexit() terminators + * (if there are any) + * + * These terminators MUST be executed in + * reverse order (LIFO)! + * + * NOTE: + * This code assumes that __onexitbegin + * points to the first valid onexit() + * entry and that __onexitend points + * past the last valid entry. If + * __onexitbegin == __onexitend, the + * table is empty and there are no + * routines to call. + */ + + if (__onexitbegin) { + PF * pfend = __onexitend; + + while ( -- pfend >= __onexitbegin ) + /* + * if current table entry is not + * NULL, call thru it. + */ + if ( *pfend != NULL ) + (**pfend)(); + + /* + * just in case Win32s doesn't clean up after + * us (any bets?), free the block holding + * onexit table + */ + if ( __win32sflag > 0 ) + GlobalFree( (HGLOBAL)__onexitbegin ); + else + free(__onexitbegin); + } + } + } + + return TRUE; +} + +/*** +*BOOL WINAPI _DllMainCRTStartup(hDllHandle, dwReason, lpreserved) - C++ DLL initialization. +* +*Purpose: +* This is an alternative entry point for DLL's linked with the C run-time +* libs, rather than using _CRT_INIT. The user should specify this routine +* as the DLL entry point, and define his/her own routine DllMain to get +* notifications in his/her code. CRT initialization/termination will be +* done before or after calling DllMain, as appropriate. +* +*Entry: +* +*Exit: +* +*******************************************************************************/ +BOOL WINAPI _DllMainCRTStartup( + HANDLE hDllHandle, + DWORD dwReason, + LPVOID lpreserved + ) +{ + BOOL retcode = TRUE; + + /* + * If this is a process detach notification, check that there has + * been a prior process attach notification. + */ + if ( (dwReason == DLL_PROCESS_DETACH) && (__proc_attached == 0) ) + return FALSE; + + if ( dwReason == DLL_PROCESS_ATTACH || dwReason == DLL_THREAD_ATTACH ) + retcode = _CRT_INIT(hDllHandle, dwReason, lpreserved); + + if ( retcode ) + retcode = DllMain(hDllHandle, dwReason, lpreserved); + + /* + * If _CRT_INIT successfully handles a Process Attach notification + * but the user's DllMain routine returns failure, we need to do + * clean-up of the C run-time similar to what _CRT_INIT does on a + * Process Detach Notification. + */ + + if ( dwReason == DLL_PROCESS_DETACH || dwReason == DLL_THREAD_DETACH ) + { + if ( _CRT_INIT(hDllHandle, dwReason, lpreserved) == FALSE ) + retcode = FALSE ; + } + + return retcode ; +} + +/*** +*_onexit, atexit - calls to DLL versioons of _onexit & atexit in CRTDLL.DLL +* +*Purpose: +* A DLL linked with CRTDLL.LIB must not call the standard _onexit or +* atexit exported from CRTDLL.DLL, but an EXE linked with CRTDLL.LIB +* will call the standard versions of those two routines. Since the +* names are exported from CRTDLL.DLL, we must define them here for DLLs. +* All DLLs linked with CRTDLL.LIB must pull in this startup object. +* +*Entry: +* Same as the regular versions of _onexit, atexit. +* +*Exit: +* Same as the regular versions of _onexit, atexit. +* +*Exceptions: +* +*******************************************************************************/ + +extern _onexit_t _CALLTYPE1 __dllonexit(_onexit_t, PF **, PF **); + +_onexit_t _CALLTYPE1 _onexit ( + _onexit_t func + ) +{ + unsigned osver; + _onexit_t retval; + + /* + * Get the host version (on first call). + */ + if ( __win32sflag == 0 ) { + osver = GetVersion(); + if ( ((osver & 0x00ff) == 3) && ((osver >> 31) & 1) ) + __win32sflag++; + else + __win32sflag--; + } + + /* + * If we are running in Win32s, test and set the flag used to + * serialize access. Note that we assume no process switch can take + * place between a successful test of the flag and the setting of + * the flag. + */ + if ( __win32sflag > 0 ) { + while ( onexitflag > 0 ) + Sleep(0); + onexitflag++; + } + + retval = __dllonexit(func, &__onexitbegin, &__onexitend); + + if ( __win32sflag > 0 ) + onexitflag--; + + return retval; +} + +int _CALLTYPE1 atexit ( + PF func + ) +{ + return (_onexit((_onexit_t)func) == NULL) ? -1 : 0; +} + +#endif /* CRTDLL */ |