Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

376 lines
10 KiB

4 years ago
  1. #ifdef CRTDLL
  2. /***
  3. *crtdll.c - CRT initialization for a DLL using the CRTDLL model of C run-time
  4. *
  5. * Copyright (c) 1991-1994, Microsoft Corporation. All rights reserved.
  6. *
  7. *Purpose:
  8. * This module contains the initialization entry point for the C run-time
  9. * stub in this DLL. All C run-time code is located in the C Run-Time
  10. * Library DLL "CRTDLL.DLL", except for a little bit of start-up code in
  11. * the EXE, and this code in each DLL. This code is necessary to invoke
  12. * the C++ constructors for the C++ code in this DLL.
  13. *
  14. * This entry point should either be specified as the DLL initialization
  15. * entry point, or else it must be called by the DLL initialization entry
  16. * point of the DLL with the same arguments that the entry point receives.
  17. *
  18. *Revision History:
  19. * 05-19-92 SKS Initial version
  20. * 08-01-92 SRW winxcpt.h replaced bu excpt.h which is included by oscalls.h
  21. * 09-16-92 SKS Prepare for C8 C++ for MIPS by calling C++ constructors
  22. * 09-29-92 SKS _CRT_DLL must be a WINAPI function!
  23. * 05-11-93 SKS Add _DllMainCRTStartup as an alternative to _CRT_INIT
  24. * 06-05-93 SRW Pin CRTDLL.DLL in memory once loaded.
  25. * 06-07-93 GJF Added __proc_attached flag.
  26. * 06-07-93 GJF Backed out SteveWo's change of 06-05 and put it into
  27. * crtlib.c
  28. * 06-08-93 SKS Clean up failure handling in _CRT_INIT
  29. * 07-16-93 SRW ALPHA Merge
  30. * 12-02-93 SKS Add atexit/_onexit support. These routines must be
  31. * defined here so that DLL's that are linked with
  32. * CRTDLL.LIB will get these versions (suitable for DLLs),
  33. * not the versions of atexit/_onexit from CRTDLL.DLL,
  34. * which are only suitable for an EXE file.
  35. * 07-18-94 GJF Moved over Win32s support from VC 2.0 tree.
  36. *
  37. *******************************************************************************/
  38. /*
  39. * SPECIAL BUILD MACRO! Note that crtexe.c (and crtexew.c) is linked in with
  40. * the client's code. It does not go into crtdll.dll! Therefore, it must be
  41. * built under the _DLL switch (like user code) and CRTDLL must be undefined.
  42. */
  43. #undef CRTDLL
  44. #define _DLL
  45. #include <cruntime.h>
  46. #include <oscalls.h>
  47. #include <internal.h>
  48. #include <stdlib.h>
  49. #define _DECL_DLLMAIN /* enable prototypes for DllMain and _CRT_INIT */
  50. #include <process.h>
  51. /*
  52. * routine in DLL to do initialization (in this case, C++ constructors)
  53. */
  54. typedef void (_CALLTYPE1 *PF)(void);
  55. extern void _CALLTYPE4 _initterm(PF *, PF *);
  56. /*
  57. * pointers to initialization sections
  58. */
  59. extern PF __xc_a[], __xc_z[]; /* C++ initializers */
  60. /*
  61. * Flag identifying the host as Win32s or not-Win32s.
  62. */
  63. int __win32sflag = 0;
  64. static int onexitflag = 0;
  65. /*
  66. * flag set iff _CRTDLL_INIT was called with DLL_PROCESS_ATTACH
  67. */
  68. static int __proc_attached = 0;
  69. /*
  70. * Pointers to beginning and end of the table of function pointers manipulated
  71. * by _onexit()/atexit(). The atexit/_onexit code is shared for both EXE's and
  72. * DLL's but different behavior is required. These values are initialized to
  73. * 0 by default and will be set to point to a malloc-ed memory block to mark
  74. * this module as an DLL.
  75. */
  76. PF *__onexitbegin;
  77. PF *__onexitend;
  78. /*
  79. * User routine DllMain is called on all notifications
  80. */
  81. extern BOOL WINAPI DllMain(
  82. HANDLE hDllHandle,
  83. DWORD dwReason,
  84. LPVOID lpreserved
  85. ) ;
  86. /***
  87. *BOOL WINAPI _CRT_INIT(hDllHandle, dwReason, lpreserved) - C++ DLL initialization.
  88. *
  89. *Purpose:
  90. * This routine does the C runtime initialization for a DLL using CRTDLL.
  91. * It may be specified as the entry point for the DLL, or it may be
  92. * called by the routine that is the DLL entry point.
  93. *
  94. * On DLL_PROCESS_ATTACH, the C++ constructors for the DLL will be called.
  95. *
  96. * On DLL_PROCESS_DETACH, the C++ destructors and _onexit/atexit routines
  97. * will be called.
  98. *
  99. *Entry:
  100. *
  101. *Exit:
  102. *
  103. *******************************************************************************/
  104. BOOL WINAPI _CRT_INIT(
  105. HANDLE hDllHandle,
  106. DWORD dwReason,
  107. LPVOID lpreserved
  108. )
  109. {
  110. unsigned osver;
  111. /*
  112. * First, set the __proc_attached flag
  113. */
  114. if ( dwReason == DLL_PROCESS_ATTACH )
  115. __proc_attached++;
  116. else if ( dwReason == DLL_PROCESS_DETACH ) {
  117. if ( __proc_attached > 0 )
  118. __proc_attached--;
  119. else
  120. /*
  121. * no prior process attach. just return failure.
  122. */
  123. return FALSE;
  124. }
  125. /*
  126. * Get the host version (on first call).
  127. */
  128. if ( __win32sflag == 0 ) {
  129. osver = GetVersion();
  130. if ( ((osver & 0x00ff) == 3) && ((osver >> 31) & 1) )
  131. __win32sflag++;
  132. else
  133. __win32sflag--;
  134. }
  135. /*
  136. * do C++ constructors (initializers) specific to this DLL
  137. */
  138. if ( dwReason == DLL_PROCESS_ATTACH ) {
  139. /*
  140. * If the host is Win32s, create the onexit table and do C++
  141. * constructors only for the first connecting process.
  142. */
  143. if ( (__win32sflag < 0) || (__proc_attached == 1) ) {
  144. if ( __win32sflag < 0 ) {
  145. /*
  146. * not Win32s! just malloc the table.
  147. */
  148. if ( (__onexitbegin = (PF *)malloc(32 *
  149. sizeof(PF))) == NULL )
  150. /*
  151. * cannot allocate minimal required
  152. * size. generate failure to load DLL
  153. */
  154. return FALSE;
  155. }
  156. else if ( __proc_attached == 1 ) {
  157. if ( (__onexitbegin =
  158. (PF *)GlobalAlloc( GMEM_FIXED |
  159. GMEM_SHARE, 32 * sizeof(PF) )) ==
  160. NULL )
  161. /*
  162. * cannot allocate minimal required
  163. * size. generate failure to load DLL
  164. */
  165. return FALSE;
  166. }
  167. *(__onexitbegin) = (PF) NULL;
  168. __onexitend = __onexitbegin;
  169. /*
  170. * Invoke C++ constructors
  171. */
  172. _initterm(__xc_a,__xc_z);
  173. }
  174. }
  175. else if ( dwReason == DLL_PROCESS_DETACH ) {
  176. if ( (__win32sflag < 0) || (__proc_attached == 0) )
  177. {
  178. /*
  179. * Any basic clean-up code that goes here must be
  180. * duplicated below in _DllMainCRTStartup for the
  181. * case where the user's DllMain() routine fails on a
  182. * Process Attach notification. This does not include
  183. * calling user C++ destructors, etc.
  184. */
  185. /*
  186. * do _onexit/atexit() terminators
  187. * (if there are any)
  188. *
  189. * These terminators MUST be executed in
  190. * reverse order (LIFO)!
  191. *
  192. * NOTE:
  193. * This code assumes that __onexitbegin
  194. * points to the first valid onexit()
  195. * entry and that __onexitend points
  196. * past the last valid entry. If
  197. * __onexitbegin == __onexitend, the
  198. * table is empty and there are no
  199. * routines to call.
  200. */
  201. if (__onexitbegin) {
  202. PF * pfend = __onexitend;
  203. while ( -- pfend >= __onexitbegin )
  204. /*
  205. * if current table entry is not
  206. * NULL, call thru it.
  207. */
  208. if ( *pfend != NULL )
  209. (**pfend)();
  210. /*
  211. * just in case Win32s doesn't clean up after
  212. * us (any bets?), free the block holding
  213. * onexit table
  214. */
  215. if ( __win32sflag > 0 )
  216. GlobalFree( (HGLOBAL)__onexitbegin );
  217. else
  218. free(__onexitbegin);
  219. }
  220. }
  221. }
  222. return TRUE;
  223. }
  224. /***
  225. *BOOL WINAPI _DllMainCRTStartup(hDllHandle, dwReason, lpreserved) - C++ DLL initialization.
  226. *
  227. *Purpose:
  228. * This is an alternative entry point for DLL's linked with the C run-time
  229. * libs, rather than using _CRT_INIT. The user should specify this routine
  230. * as the DLL entry point, and define his/her own routine DllMain to get
  231. * notifications in his/her code. CRT initialization/termination will be
  232. * done before or after calling DllMain, as appropriate.
  233. *
  234. *Entry:
  235. *
  236. *Exit:
  237. *
  238. *******************************************************************************/
  239. BOOL WINAPI _DllMainCRTStartup(
  240. HANDLE hDllHandle,
  241. DWORD dwReason,
  242. LPVOID lpreserved
  243. )
  244. {
  245. BOOL retcode = TRUE;
  246. /*
  247. * If this is a process detach notification, check that there has
  248. * been a prior process attach notification.
  249. */
  250. if ( (dwReason == DLL_PROCESS_DETACH) && (__proc_attached == 0) )
  251. return FALSE;
  252. if ( dwReason == DLL_PROCESS_ATTACH || dwReason == DLL_THREAD_ATTACH )
  253. retcode = _CRT_INIT(hDllHandle, dwReason, lpreserved);
  254. if ( retcode )
  255. retcode = DllMain(hDllHandle, dwReason, lpreserved);
  256. /*
  257. * If _CRT_INIT successfully handles a Process Attach notification
  258. * but the user's DllMain routine returns failure, we need to do
  259. * clean-up of the C run-time similar to what _CRT_INIT does on a
  260. * Process Detach Notification.
  261. */
  262. if ( dwReason == DLL_PROCESS_DETACH || dwReason == DLL_THREAD_DETACH )
  263. {
  264. if ( _CRT_INIT(hDllHandle, dwReason, lpreserved) == FALSE )
  265. retcode = FALSE ;
  266. }
  267. return retcode ;
  268. }
  269. /***
  270. *_onexit, atexit - calls to DLL versioons of _onexit & atexit in CRTDLL.DLL
  271. *
  272. *Purpose:
  273. * A DLL linked with CRTDLL.LIB must not call the standard _onexit or
  274. * atexit exported from CRTDLL.DLL, but an EXE linked with CRTDLL.LIB
  275. * will call the standard versions of those two routines. Since the
  276. * names are exported from CRTDLL.DLL, we must define them here for DLLs.
  277. * All DLLs linked with CRTDLL.LIB must pull in this startup object.
  278. *
  279. *Entry:
  280. * Same as the regular versions of _onexit, atexit.
  281. *
  282. *Exit:
  283. * Same as the regular versions of _onexit, atexit.
  284. *
  285. *Exceptions:
  286. *
  287. *******************************************************************************/
  288. extern _onexit_t _CALLTYPE1 __dllonexit(_onexit_t, PF **, PF **);
  289. _onexit_t _CALLTYPE1 _onexit (
  290. _onexit_t func
  291. )
  292. {
  293. unsigned osver;
  294. _onexit_t retval;
  295. /*
  296. * Get the host version (on first call).
  297. */
  298. if ( __win32sflag == 0 ) {
  299. osver = GetVersion();
  300. if ( ((osver & 0x00ff) == 3) && ((osver >> 31) & 1) )
  301. __win32sflag++;
  302. else
  303. __win32sflag--;
  304. }
  305. /*
  306. * If we are running in Win32s, test and set the flag used to
  307. * serialize access. Note that we assume no process switch can take
  308. * place between a successful test of the flag and the setting of
  309. * the flag.
  310. */
  311. if ( __win32sflag > 0 ) {
  312. while ( onexitflag > 0 )
  313. Sleep(0);
  314. onexitflag++;
  315. }
  316. retval = __dllonexit(func, &__onexitbegin, &__onexitend);
  317. if ( __win32sflag > 0 )
  318. onexitflag--;
  319. return retval;
  320. }
  321. int _CALLTYPE1 atexit (
  322. PF func
  323. )
  324. {
  325. return (_onexit((_onexit_t)func) == NULL) ? -1 : 0;
  326. }
  327. #endif /* CRTDLL */