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

  1. /***
  2. *crtlib.c - CRT DLL initialization and termination routine (Win32, Dosx32)
  3. *
  4. *       Copyright (c) 1991-1997, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. *       This module contains initialization entry point for the CRT DLL
  8. *       in the Win32 environment. It also contains some of the supporting
  9. *       initialization and termination code.
  10. *
  11. *******************************************************************************/
  12.  
  13. #ifdef CRTDLL
  14.  
  15. #include <cruntime.h>
  16. #include <oscalls.h>
  17. #include <dos.h>
  18. #include <internal.h>
  19. #include <malloc.h>
  20. #include <mbctype.h>
  21. #include <mtdll.h>
  22. #include <process.h>
  23. #include <rterr.h>
  24. #include <stdio.h>
  25. #include <stdlib.h>
  26. #include <string.h>
  27. #include <awint.h>
  28. #include <tchar.h>
  29. #include <time.h>
  30. #include <dbgint.h>
  31.  
  32. /*
  33.  * flag set iff _CRTDLL_INIT was called with DLL_PROCESS_ATTACH
  34.  */
  35. static int proc_attached = 0;
  36.  
  37. /*
  38.  * command line, environment, and a few other globals
  39.  */
  40. wchar_t *_wcmdln = NULL;           /* points to wide command line */
  41. char *_acmdln = NULL;              /* points to command line */
  42.  
  43. char *_aenvptr = NULL;      /* points to environment block */
  44. wchar_t *_wenvptr = NULL;   /* points to wide environment block */
  45.  
  46. void (__cdecl * _aexit_rtn)(int) = _exit;   /* RT message return procedure */
  47.  
  48. extern int _newmode;    /* declared in <internal.h> */
  49.  
  50. int __error_mode = _OUT_TO_DEFAULT;
  51.  
  52. int __app_type = _UNKNOWN_APP;
  53.  
  54. static void __cdecl inherit(void);  /* local function */
  55.  
  56. /***
  57. *void __[w]getmainargs - get values for args to main()
  58. *
  59. *Purpose:
  60. *       This function invokes the command line parsing and copies the args
  61. *       to main back through the passsed pointers. The reason for doing
  62. *       this here, rather than having _CRTDLL_INIT do the work and exporting
  63. *       the __argc and __argv, is to support the linked-in option to have
  64. *       wildcard characters in filename arguments expanded.
  65. *
  66. *Entry:
  67. *       int *pargc              - pointer to argc
  68. *       _TCHAR ***pargv         - pointer to argv
  69. *       _TCHAR ***penvp         - pointer to envp
  70. *       int dowildcard          - flag (true means expand wildcards in cmd line)
  71. *       _startupinfo * startinfo- other info to be passed to CRT DLL
  72. *
  73. *Exit:
  74. *       No return value. Values for the arguments to main() are copied through
  75. *       the passed pointers.
  76. *
  77. *******************************************************************************/
  78.  
  79.  
  80. _CRTIMP void __cdecl __wgetmainargs (
  81.         int *pargc,
  82.         wchar_t ***pargv,
  83.         wchar_t ***penvp,
  84.         int dowildcard,
  85.         _startupinfo * startinfo)
  86. {
  87.  
  88.         /* set global new mode flag */
  89.         _newmode = startinfo->newmode;
  90.  
  91.         if ( dowildcard )
  92.             __wsetargv();   /* do wildcard expansion after parsing args */
  93.         else
  94.             _wsetargv();    /* NO wildcard expansion; just parse args */
  95.  
  96.         *pargc = __argc;
  97.         *pargv = __wargv;
  98.  
  99.         /*
  100.          * if wide environment does not already exist,
  101.          * create it from multibyte environment
  102.          */
  103.         if (!_wenviron)
  104.             __mbtow_environ();
  105.  
  106.         *penvp = _wenviron;
  107. }
  108.  
  109.  
  110.  
  111. _CRTIMP void __cdecl __getmainargs (
  112.         int *pargc,
  113.         char ***pargv,
  114.         char ***penvp,
  115.         int dowildcard
  116.         ,
  117.         _startupinfo * startinfo
  118.         )
  119. {
  120.  
  121.         /* set global new mode flag */
  122.         _newmode = startinfo->newmode;
  123.  
  124.         if ( dowildcard )
  125.             __setargv();    /* do wildcard expansion after parsing args */
  126.         else
  127.             _setargv();     /* NO wildcard expansion; just parse args */
  128.  
  129.         *pargc = __argc;
  130.         *pargv = __argv;
  131.         *penvp = _environ;
  132. }
  133.  
  134.  
  135. /***
  136. *BOOL _CRTDLL_INIT(hDllHandle, dwReason, lpreserved) - C DLL initialization.
  137. *
  138. *Purpose:
  139. *       This routine does the C runtime initialization.
  140. *
  141. *Entry:
  142. *
  143. *Exit:
  144. *
  145. *******************************************************************************/
  146.  
  147. BOOL WINAPI _CRTDLL_INIT(
  148.         HANDLE  hDllHandle,
  149.         DWORD   dwReason,
  150.         LPVOID  lpreserved
  151.         )
  152. {
  153.         unsigned tmposver;
  154.  
  155.         if ( dwReason == DLL_PROCESS_ATTACH ) {
  156.  
  157.             /*
  158.              * Get the full Win32 version. Stash it in a local variable
  159.              * temporarily.
  160.              */
  161.             tmposver = GetVersion();
  162.  
  163. #ifdef _M_IX86
  164.  
  165.             /*
  166.              * Make sure we are NOT running on Win32s
  167.              */
  168.             if ( ((tmposver & 0x00ff) == 3) && ((tmposver >> 31) & 1) ) {
  169.                 __crtMessageBoxA("MSVCRT.DLL for Win32\n\nError: MSVCRT.DLL is not compatible with Win32s.",
  170.                          "Microsoft Visual C++ Runtime Library",
  171.                          MB_OK|MB_ICONHAND|MB_SETFOREGROUND|MB_TASKMODAL);
  172.                 return FALSE;
  173.             }
  174.  
  175. #endif  /* _M_IX86 */
  176.  
  177.  
  178. #ifdef _MT
  179.             if ( !_heap_init(1) )   /* initialize heap */
  180. #else  /* _MT */
  181.             if ( !_heap_init(0) )   /* initialize heap */
  182. #endif  /* _MT */
  183.                 /*
  184.                  * The heap cannot be initialized, return failure to the
  185.                  * loader.
  186.                  */
  187.                 return FALSE;
  188.  
  189.             /*
  190.              * Store OS version
  191.              */
  192.             _osver = tmposver;
  193.  
  194.             _winminor = (_osver >> 8) & 0x00FF ;
  195.             _winmajor = _osver & 0x00FF ;
  196.             _winver = (_winmajor << 8) + _winminor;
  197.             _osver = (_osver >> 16) & 0x00FFFF ;
  198.  
  199. #ifdef _MT
  200.             if(!_mtinit())          /* initialize multi-thread */
  201.             {
  202.                 /*
  203.                  * If the DLL load is going to fail, we must clean up
  204.                  * all resources that have already been allocated.
  205.                  */
  206.                 _heap_term();       /* heap is now invalid! */
  207.  
  208.                 return FALSE;       /* fail DLL load on failure */
  209.             }
  210. #endif  /* _MT */
  211.  
  212.             _ioinit();          /* inherit file info */
  213.  
  214.             _aenvptr = (char *)__crtGetEnvironmentStringsA();
  215.  
  216.             _acmdln = (char *)GetCommandLineA();
  217.             _wcmdln = (wchar_t *)__crtGetCommandLineW();
  218.  
  219. #ifdef _MBCS
  220.             /*
  221.              * Initialize multibyte ctype table. Always done since it is
  222.              * needed for processing the environment strings.
  223.              */
  224.             __initmbctable();
  225. #endif  /* _MBCS */
  226.  
  227.             /*
  228.              * For CRT DLL, since we don't know the type (wide or multibyte)
  229.              * of the program, we create only the multibyte type since that
  230.              * is by far the most likely case. Wide environment will be created
  231.              * on demand as usual.
  232.              */
  233.  
  234.             _setenvp();             /* get environ info */
  235.  
  236.             _cinit();               /* do C data initialize */
  237.  
  238.             /*
  239.              * Increment flag indicating process attach notification
  240.              * has been received.
  241.              */
  242.             proc_attached++;
  243.  
  244.         }
  245.         else if ( dwReason == DLL_PROCESS_DETACH ) {
  246.                 /*
  247.                  * if a client process is detaching, make sure minimal
  248.                  * runtime termination is performed and clean up our
  249.                  * 'locks' (i.e., delete critical sections).
  250.                  */
  251.             if ( proc_attached > 0 ) {
  252.                 proc_attached--;
  253.  
  254.                 /*
  255.                  * Any basic clean-up done here may also need
  256.                  * to be done below if Process Attach is partly
  257.                  * processed and then a failure is encountered.
  258.                  */
  259.  
  260.                 if ( _C_Termination_Done == FALSE )
  261.                     _c_exit();
  262.  
  263. #ifdef _DEBUG
  264.                 /* Dump all memory leaks */
  265.                 if (_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) & _CRTDBG_LEAK_CHECK_DF)
  266.                 {
  267.                     _CrtSetDumpClient(NULL);
  268.                     _CrtDumpMemoryLeaks();
  269.                 }
  270. #endif  /* _DEBUG */
  271.  
  272.                 /* Shut down lowio */
  273.                 _ioterm();
  274. #ifdef _MT
  275.                 /* free TLS index, call _mtdeletelocks() */
  276.                 _mtterm();
  277. #endif  /* _MT */
  278.  
  279.                 /* This should be the last thing the C run-time does */
  280.                 _heap_term();   /* heap is now invalid! */
  281.  
  282.             }
  283.             else
  284.                 /* no prior process attach, just return */
  285.                 return FALSE;
  286.  
  287.         }
  288.         else if ( dwReason == DLL_THREAD_DETACH )
  289.         {
  290.             _freeptd(NULL);     /* free up per-thread CRT data */
  291.         }
  292.  
  293.         return TRUE;
  294. }
  295.  
  296. /***
  297. *_amsg_exit(rterrnum) - Fast exit fatal errors
  298. *
  299. *Purpose:
  300. *       Exit the program with error code of 255 and appropriate error
  301. *       message.
  302. *
  303. *Entry:
  304. *       int rterrnum - error message number (amsg_exit only).
  305. *
  306. *Exit:
  307. *       Calls exit() (for integer divide-by-0) or _exit() indirectly
  308. *       through _aexit_rtn [amsg_exit].
  309. *       For multi-thread: calls _exit() function
  310. *
  311. *Exceptions:
  312. *
  313. *******************************************************************************/
  314.  
  315. void __cdecl _amsg_exit (
  316.         int rterrnum
  317.         )
  318. {
  319.  
  320.         if ( (__error_mode == _OUT_TO_STDERR) || ((__error_mode ==
  321.                _OUT_TO_DEFAULT) && (__app_type == _CONSOLE_APP)) )
  322.             _FF_MSGBANNER();    /* write run-time error banner */
  323.  
  324.         _NMSG_WRITE(rterrnum);      /* write message */
  325.         _aexit_rtn(255);        /* normally _exit(255) */
  326. }
  327.  
  328.  
  329. #if defined (_M_IX86)
  330.  
  331. /*
  332.  * Functions to access user-visible, per-process variables
  333.  */
  334.  
  335. /*
  336.  * Macro to construct the name of the access function from the variable
  337.  * name.
  338.  */
  339. #define AFNAME(var) __p_ ## var
  340.  
  341. /*
  342.  * Macro to construct the access function's return value from the variable
  343.  * name.
  344.  */
  345. #define AFRET(var)  &var
  346.  
  347. /*
  348.  ***
  349.  ***  Template
  350.  ***
  351.  
  352. _CRTIMP __cdecl
  353. AFNAME() (void)
  354. {
  355.         return AFRET();
  356. }
  357.  
  358.  ***
  359.  ***
  360.  ***
  361.  */
  362.  
  363. #ifdef _DEBUG
  364.  
  365. _CRTIMP long *
  366. AFNAME(_crtAssertBusy) (void)
  367. {
  368.         return AFRET(_crtAssertBusy);
  369. }
  370.  
  371. _CRTIMP long *
  372. AFNAME(_crtBreakAlloc) (void)
  373. {
  374.         return AFRET(_crtBreakAlloc);
  375. }
  376.  
  377. _CRTIMP int *
  378. AFNAME(_crtDbgFlag) (void)
  379. {
  380.         return AFRET(_crtDbgFlag);
  381. }
  382.  
  383. #endif  /* _DEBUG */
  384.  
  385. _CRTIMP char ** __cdecl
  386. AFNAME(_acmdln) (void)
  387. {
  388.         return AFRET(_acmdln);
  389. }
  390.  
  391. _CRTIMP wchar_t ** __cdecl
  392. AFNAME(_wcmdln) (void)
  393. {
  394.         return AFRET(_wcmdln);
  395. }
  396.  
  397. _CRTIMP unsigned int * __cdecl
  398. AFNAME(_amblksiz) (void)
  399. {
  400.         return AFRET(_amblksiz);
  401. }
  402.  
  403. _CRTIMP int * __cdecl
  404. AFNAME(__argc) (void)
  405. {
  406.         return AFRET(__argc);
  407. }
  408.  
  409. _CRTIMP char *** __cdecl
  410. AFNAME(__argv) (void)
  411. {
  412.         return AFRET(__argv);
  413. }
  414.  
  415. _CRTIMP wchar_t *** __cdecl
  416. AFNAME(__wargv) (void)
  417. {
  418.         return AFRET(__wargv);
  419. }
  420.  
  421. _CRTIMP int * __cdecl
  422. AFNAME(_commode) (void)
  423. {
  424.         return AFRET(_commode);
  425. }
  426.  
  427. _CRTIMP int * __cdecl
  428. AFNAME(_daylight) (void)
  429. {
  430.         return AFRET(_daylight);
  431. }
  432.  
  433. _CRTIMP long * __cdecl
  434. AFNAME(_dstbias) (void)
  435. {
  436.         return AFRET(_dstbias);
  437. }
  438.  
  439. _CRTIMP char *** __cdecl
  440. AFNAME(_environ) (void)
  441. {
  442.         return AFRET(_environ);
  443. }
  444.  
  445. _CRTIMP wchar_t *** __cdecl
  446. AFNAME(_wenviron) (void)
  447. {
  448.         return AFRET(_wenviron);
  449. }
  450.  
  451. _CRTIMP int * __cdecl
  452. AFNAME(_fmode) (void)
  453. {
  454.         return AFRET(_fmode);
  455. }
  456.  
  457. _CRTIMP int * __cdecl
  458. AFNAME(_fileinfo) (void)
  459. {
  460.         return AFRET(_fileinfo);
  461. }
  462.  
  463. _CRTIMP char *** __cdecl
  464. AFNAME(__initenv) (void)
  465. {
  466.         return AFRET(__initenv);
  467. }
  468.  
  469. _CRTIMP wchar_t *** __cdecl
  470. AFNAME(__winitenv) (void)
  471. {
  472.         return AFRET(__winitenv);
  473. }
  474.  
  475. _CRTIMP FILE *
  476. AFNAME(_iob) (void)
  477. {
  478.         return &_iob[0];
  479. }
  480.  
  481. _CRTIMP unsigned char * __cdecl
  482. AFNAME(_mbctype) (void)
  483. {
  484.         return &_mbctype[0];
  485. }
  486.  
  487. _CRTIMP unsigned char * __cdecl
  488. AFNAME(_mbcasemap) (void)
  489. {
  490.         return &_mbcasemap[0];
  491. }
  492.  
  493. _CRTIMP int * __cdecl
  494. AFNAME(__mb_cur_max) (void)
  495. {
  496.         return AFRET(__mb_cur_max);
  497. }
  498.  
  499.  
  500. _CRTIMP unsigned int * __cdecl
  501. AFNAME(_osver) (void)
  502. {
  503.         return AFRET(_osver);
  504. }
  505.  
  506. _CRTIMP unsigned short ** __cdecl
  507. AFNAME(_pctype) (void)
  508. {
  509.         return AFRET(_pctype);
  510. }
  511.  
  512. _CRTIMP unsigned short ** __cdecl
  513. AFNAME(_pwctype) (void)
  514. {
  515.         return AFRET(_pwctype);
  516. }
  517.  
  518. _CRTIMP char **  __cdecl
  519. AFNAME(_pgmptr) (void)
  520. {
  521.         return AFRET(_pgmptr);
  522. }
  523.  
  524. _CRTIMP wchar_t ** __cdecl
  525. AFNAME(_wpgmptr) (void)
  526. {
  527.         return AFRET(_wpgmptr);
  528. }
  529.  
  530. _CRTIMP long * __cdecl
  531. AFNAME(_timezone) (void)
  532. {
  533.         return AFRET(_timezone);
  534. }
  535.  
  536. _CRTIMP char ** __cdecl
  537. AFNAME(_tzname) (void)
  538. {
  539.         return &_tzname[0];
  540. }
  541.  
  542. _CRTIMP unsigned int * __cdecl
  543. AFNAME(_winmajor) (void)
  544. {
  545.         return AFRET(_winmajor);
  546. }
  547.  
  548. _CRTIMP unsigned int * __cdecl
  549. AFNAME(_winminor) (void)
  550. {
  551.         return AFRET(_winminor);
  552. }
  553.  
  554. _CRTIMP unsigned int * __cdecl
  555. AFNAME(_winver) (void)
  556. {
  557.         return AFRET(_winver);
  558. }
  559.  
  560. #endif  /* defined (_M_IX86) */
  561.  
  562. #endif  /* CRTDLL */
  563.