home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / vc98 / crt / src / dllcrt0.c < prev    next >
C/C++ Source or Header  |  1998-06-17  |  11KB  |  371 lines

  1. /***
  2. *dllcrt0.c - C runtime initialization routine for a DLL with linked-in C R-T
  3. *
  4. *       Copyright (c) 1989-1997, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. *       This the startup routine for a DLL which is linked with its own
  8. *       C run-time code.  It is similar to the routine _mainCRTStartup()
  9. *       in the file CRT0.C, except that there is no main() in a DLL.
  10. *
  11. *******************************************************************************/
  12.  
  13. #ifdef _WIN32
  14.  
  15. #ifndef CRTDLL
  16.  
  17. #include <cruntime.h>
  18. #include <dos.h>
  19. #include <internal.h>
  20. #include <mtdll.h>
  21. #include <stdlib.h>
  22. #include <string.h>
  23. #include <rterr.h>
  24. #include <oscalls.h>
  25. #define _DECL_DLLMAIN   /* enable prototypes for DllMain and _CRT_INIT */
  26. #include <process.h>
  27. #include <awint.h>
  28. #include <tchar.h>
  29. #include <dbgint.h>
  30.  
  31. /*
  32.  * flag set iff _CRTDLL_INIT was called with DLL_PROCESS_ATTACH
  33.  */
  34. static int __proc_attached = 0;
  35.  
  36. /*
  37.  * command line, environment, and a few other globals
  38.  */
  39. char *_acmdln;              /* points to command line */
  40.  
  41. char *_aenvptr = NULL;      /* points to environment block */
  42. wchar_t *_wenvptr = NULL;   /* points to wide environment block */
  43.  
  44. void (__cdecl * _aexit_rtn)(int) = _exit;   /* RT message return procedure */
  45.  
  46. /*
  47.  * _error_mode and _apptype, together, determine how error messages are
  48.  * written out.
  49.  */
  50. int __error_mode = _OUT_TO_DEFAULT;
  51. int __app_type = _UNKNOWN_APP;
  52.  
  53. /*
  54.  * User routine DllMain is called on all notifications
  55.  */
  56. extern BOOL WINAPI DllMain(
  57.         HANDLE  hDllHandle,
  58.         DWORD   dwReason,
  59.         LPVOID  lpreserved
  60.         ) ;
  61.  
  62. /* _pRawDllMain MUST be a common variable, not extern nor initialized! */
  63.  
  64. BOOL (WINAPI *_pRawDllMain)(HANDLE, DWORD, LPVOID);
  65.  
  66. /***
  67. *BOOL WINAPI _CRT_INIT(hDllHandle, dwReason, lpreserved) -
  68. *       C Run-Time initialization for a DLL linked with a C run-time library.
  69. *
  70. *Purpose:
  71. *       This routine does the C run-time initialization or termination.
  72. *       For the multi-threaded run-time library, it also cleans up the
  73. *       multi-threading locks on DLL termination.
  74. *
  75. *Entry:
  76. *
  77. *Exit:
  78. *
  79. *NOTES:
  80. *       This routine must be the entry point for the DLL.
  81. *
  82. *******************************************************************************/
  83.  
  84. BOOL WINAPI _CRT_INIT(
  85.         HANDLE  hDllHandle,
  86.         DWORD   dwReason,
  87.         LPVOID  lpreserved
  88.         )
  89. {
  90.         /*
  91.          * Start-up code only gets executed when the process is initialized
  92.          */
  93.  
  94.         if ( dwReason == DLL_PROCESS_ATTACH )
  95.         {
  96.  
  97.             /*
  98.              * Get the full Win32 version
  99.              */
  100.             _osver = GetVersion();
  101.  
  102. #ifdef _MT
  103.             if ( !_heap_init(1) )   /* initialize heap */
  104. #else  /* _MT */
  105.             if ( !_heap_init(0) )   /* initialize heap */
  106. #endif  /* _MT */
  107.                 return FALSE;       /* fail to load DLL */
  108.  
  109.             _winminor = (_osver >> 8) & 0x00FF ;
  110.             _winmajor = _osver & 0x00FF ;
  111.             _winver = (_winmajor << 8) + _winminor;
  112.             _osver = (_osver >> 16) & 0x00FFFF ;
  113.  
  114. #ifdef _MT
  115.             if(!_mtinit())          /* initialize multi-thread */
  116.             {
  117.                 _heap_term();       /* heap is now invalid! */
  118.                 return FALSE;       /* fail to load DLL */
  119.             }
  120. #endif  /* _MT */
  121.  
  122.             _acmdln = (char *)GetCommandLineA();
  123.             _aenvptr = (char *)__crtGetEnvironmentStringsA();
  124.  
  125.             _ioinit();              /* initialize lowio */
  126.  
  127.             _setargv();             /* get cmd line info */
  128.             _setenvp();             /* get environ info */
  129.  
  130.             _cinit();               /* do C data initialize */
  131.  
  132.             /*
  133.              * increment flag to indicate process attach notification
  134.              * has been received
  135.              */
  136.             __proc_attached++;
  137.         }
  138.  
  139.         else if ( dwReason == DLL_PROCESS_DETACH )
  140.         {
  141.             if ( __proc_attached > 0 )
  142.             {
  143.                 __proc_attached--;
  144.  
  145.                 /*
  146.                  * Any basic clean-up code that goes here must be duplicated
  147.                  * below in _DllMainCRTStartup for the case where the user's
  148.                  * DllMain() routine fails on a Process Attach notification.
  149.                  * This does not include calling user C++ destructors, etc.
  150.                  */
  151.  
  152.                 if ( _C_Termination_Done == FALSE )
  153.                     _cexit();
  154.  
  155. #ifdef _DEBUG
  156.                 /* Dump all memory leaks */
  157.                 if (_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) & _CRTDBG_LEAK_CHECK_DF)
  158.                     _CrtDumpMemoryLeaks();
  159. #endif  /* _DEBUG */
  160.  
  161.                 /* Shut down lowio */
  162.                 _ioterm();
  163.  
  164. #ifdef _MT
  165.                 _mtterm();
  166. #endif  /* _MT */
  167.  
  168.                 /* This should be the last thing the C run-time does */
  169.                 _heap_term();   /* heap is now invalid! */
  170.             }
  171.             else
  172.                 /* no prior process attach, just return */
  173.                 return FALSE;
  174.         }
  175. #ifdef _MT
  176.         else if ( dwReason == DLL_THREAD_DETACH )
  177.         {
  178.             _freeptd(NULL);         /* free up per-thread CRT data */
  179.         }
  180. #endif  /* _MT */
  181.  
  182.         return TRUE ;
  183. }
  184.  
  185. /***
  186. *BOOL WINAPI _DllMainCRTStartup(hDllHandle, dwReason, lpreserved) -
  187. *       C Run-Time initialization for a DLL linked with a C run-time library.
  188. *
  189. *Purpose:
  190. *       This routine does the C run-time initialization or termination
  191. *       and then calls the user code notification handler "DllMain".
  192. *       For the multi-threaded run-time library, it also cleans up the
  193. *       multi-threading locks on DLL termination.
  194. *
  195. *Entry:
  196. *
  197. *Exit:
  198. *
  199. *NOTES:
  200. *       This routine is the preferred entry point. _CRT_INIT may also be
  201. *       used, or the user may supply his/her own entry and call _CRT_INIT
  202. *       from within it, but this is not the preferred method.
  203. *
  204. *******************************************************************************/
  205.  
  206. BOOL WINAPI _DllMainCRTStartup(
  207.         HANDLE  hDllHandle,
  208.         DWORD   dwReason,
  209.         LPVOID  lpreserved
  210.         )
  211. {
  212.         BOOL retcode = TRUE;
  213.  
  214.         /*
  215.          * If this is a process detach notification, check that there has
  216.          * has been a prior process attach notification.
  217.          */
  218.         if ( (dwReason == DLL_PROCESS_DETACH) && (__proc_attached == 0) )
  219.             /*
  220.              * no prior process attach notification. just return
  221.              * without doing anything.
  222.              */
  223.             return FALSE;
  224.  
  225.         if ( dwReason == DLL_PROCESS_ATTACH || dwReason == DLL_THREAD_ATTACH )
  226.         {
  227.             if ( _pRawDllMain )
  228.                 retcode = (*_pRawDllMain)(hDllHandle, dwReason, lpreserved);
  229.  
  230.             if ( retcode )
  231.                 retcode = _CRT_INIT(hDllHandle, dwReason, lpreserved);
  232.  
  233.             if ( !retcode )
  234.                 return FALSE;
  235.         }
  236.  
  237.         retcode = DllMain(hDllHandle, dwReason, lpreserved);
  238.  
  239.         if ( (dwReason == DLL_PROCESS_ATTACH) && !retcode )
  240.             /*
  241.              * The user's DllMain routine returned failure, the C runtime
  242.              * needs to be cleaned up. Do this by calling _CRT_INIT again,
  243.              * this time imitating DLL_PROCESS_DETACH. Note this will also
  244.              * clear the __proc_attached flag so the cleanup will not be
  245.              * repeated upon receiving the real process detach notification.
  246.              */
  247.             _CRT_INIT(hDllHandle, DLL_PROCESS_DETACH, lpreserved);
  248.  
  249.         if ( (dwReason == DLL_PROCESS_DETACH) ||
  250.              (dwReason == DLL_THREAD_DETACH) )
  251.         {
  252.             if ( _CRT_INIT(hDllHandle, dwReason, lpreserved) == FALSE )
  253.                 retcode = FALSE ;
  254.  
  255.             if ( retcode && _pRawDllMain )
  256.                 retcode = (*_pRawDllMain)(hDllHandle, dwReason, lpreserved);
  257.         }
  258.  
  259.         return retcode ;
  260. }
  261.  
  262.  
  263. /***
  264. *_amsg_exit(rterrnum) - Fast exit fatal errors
  265. *
  266. *Purpose:
  267. *       Exit the program with error code of 255 and appropriate error
  268. *       message.
  269. *
  270. *Entry:
  271. *       int rterrnum - error message number (amsg_exit only).
  272. *
  273. *Exit:
  274. *       Calls exit() (for integer divide-by-0) or _exit() indirectly
  275. *       through _aexit_rtn [amsg_exit].
  276. *       For multi-thread: calls _exit() function
  277. *
  278. *Exceptions:
  279. *
  280. *******************************************************************************/
  281.  
  282. void __cdecl _amsg_exit (
  283.         int rterrnum
  284.         )
  285. {
  286.         if ( (__error_mode == _OUT_TO_STDERR) || ((__error_mode ==
  287.                _OUT_TO_DEFAULT) && (__app_type == _CONSOLE_APP)) )
  288.             _FF_MSGBANNER();    /* write run-time error banner */
  289.  
  290.         _NMSG_WRITE(rterrnum);      /* write message */
  291.         _aexit_rtn(255);        /* normally _exit(255) */
  292. }
  293.  
  294.  
  295. #endif  /* CRTDLL */
  296.  
  297. #else  /* _WIN32 */
  298.  
  299. #include <cruntime.h>
  300. #include <dos.h>
  301. #include <internal.h>
  302. #include <stdlib.h>
  303. #include <string.h>
  304. #include <dbgint.h>
  305. #include <macos\fragload.h>
  306.  
  307. /*
  308.  * User routine DllMain is called on all notifications
  309.  */
  310.  
  311. OSErr _DllInit(InitBlockPtr pinitBlk);
  312. void _DllExit(void);
  313. void _CALLTYPE1 _cexit (void);
  314.  
  315. /***
  316. *OSErr _DllMainCRTStartup(void) -
  317. *       C Run-Time initialization for a DLL linked with a C run-time library.
  318. *
  319. *Purpose:
  320. *       This routine does the C run-time initialization or termination
  321. *       and then calls the user code notification handler "DllMain".
  322. *
  323. *Entry:
  324. *
  325. *Exit:
  326. *
  327. *NOTES:
  328. *       This routine is the preferred entry point.
  329. *
  330. *******************************************************************************/
  331.  
  332. OSErr _DllMainCRTStartup(InitBlockPtr pinitBlk)
  333. {
  334.         OSErr ret;
  335.  
  336.         __cinit();
  337.  
  338.         //return the user routine value
  339.         ret = _DllInit(pinitBlk);
  340.  
  341.         return ret ;
  342. }
  343.  
  344.  
  345. /***
  346. *OSErr _DllMainCRTExit(void) -
  347. *       C Run-Time termination for a DLL linked with a C run-time library.
  348. *
  349. *Purpose:
  350. *       This routine does the C run-time termination
  351. *       and then calls the user code notification handler "DllExit".
  352. *
  353. *Entry:
  354. *
  355. *Exit:
  356. *
  357. *NOTES:
  358. *       This routine is the preferred entry point.
  359. *
  360. *******************************************************************************/
  361.  
  362. void _DllMainCRTExit()
  363. {
  364.         //currently don't care the return value user routine returns
  365.         //we could return user returns if this is an issue
  366.         _DllExit();
  367.         _cexit();
  368. }
  369.  
  370. #endif  /* _WIN32 */
  371.