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

  1. /***
  2. *crtexe.c - Initialization for client EXE using CRT DLL (Win32, Dosx32)
  3. *
  4. *       Copyright (c) 1991-1997, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. *       Set up call to client's main() or WinMain().
  8. *
  9. *******************************************************************************/
  10.  
  11. #ifndef _MAC
  12.  
  13. #ifdef CRTDLL
  14.  
  15. /*
  16.  * SPECIAL BUILD MACROS! Note that crtexe.c (and crtexew.c) is linked in with
  17.  * the client's code. It does not go into crtdll.dll! Therefore, it must be
  18.  * built under the _DLL switch (like user code) and CRTDLL must be undefined.
  19.  * The symbol SPECIAL_CRTEXE is turned on to suppress the normal CRT DLL
  20.  * definition of _fmode and _commode using __declspec(dllexport).  Otherwise
  21.  * this module would not be able to refer to both the local and DLL versions
  22.  * of these two variables.
  23.  */
  24.  
  25. #undef  CRTDLL
  26. #define _DLL
  27.  
  28. #define SPECIAL_CRTEXE
  29.  
  30. #include <cruntime.h>
  31. #include <oscalls.h>
  32. #include <internal.h>
  33.  
  34. #include <math.h>
  35. #include <rterr.h>
  36. #include <stdlib.h>
  37. #include <tchar.h>
  38.  
  39.  
  40. /*
  41.  * wWinMain is not yet defined in winbase.h. When it is, this should be
  42.  * removed.
  43.  */
  44.  
  45. int
  46. WINAPI
  47. wWinMain(
  48.     HINSTANCE hInstance,
  49.     HINSTANCE hPrevInstance,
  50.     LPWSTR lpCmdLine,
  51.     int nShowCmd
  52.     );
  53.  
  54. #define SPACECHAR   _T(' ')
  55. #define DQUOTECHAR  _T('\"')
  56.  
  57.  
  58. #ifdef _M_IX86
  59.  
  60. /*
  61.  * The local copy of the Pentium FDIV adjustment flag
  62.  * and the address of the flag in MSVCRT*.DLL.
  63.  */
  64.  
  65. extern int _adjust_fdiv;
  66.  
  67. extern int * _imp___adjust_fdiv;
  68.  
  69. #endif  /* _M_IX86 */
  70.  
  71.  
  72. /* default floating point precision - X86 only! */
  73.  
  74. #ifdef _M_IX86
  75. extern void _setdefaultprecision();
  76. #endif  /* _M_IX86 */
  77.  
  78.  
  79. /*
  80.  * Declare function used to install a user-supplied _matherr routine.
  81.  */
  82. _CRTIMP void __setusermatherr( int (__cdecl *)(struct _exception *) );
  83.  
  84.  
  85. /*
  86.  * Declare the names of the exports corresponding to _fmode and _commode
  87.  */
  88.  
  89. #ifdef _M_IX86
  90.  
  91. #define _IMP___FMODE    (__p__fmode())
  92. #define _IMP___COMMODE  (__p__commode())
  93.  
  94. #else  /* _M_IX86 */
  95.  
  96. /* assumed to be MIPS or Alpha */
  97.  
  98. #define _IMP___FMODE    __imp__fmode
  99. #define _IMP___COMMODE  __imp__commode
  100.  
  101. #endif  /* _M_IX86 */
  102.  
  103.  
  104. #if !defined (_M_IX86)
  105. extern int * _IMP___FMODE;      /* exported from the CRT DLL */
  106. extern int * _IMP___COMMODE;    /* these names are implementation-specific */
  107. #endif  /* !defined (_M_IX86) */
  108.  
  109. extern int _fmode;          /* must match the definition in <stdlib.h> */
  110. extern int _commode;        /* must match the definition in <internal.h> */
  111.  
  112. extern int _dowildcard;     /* passed to __getmainargs() */
  113.  
  114. /*
  115.  * Declare/define communal that serves as indicator the default matherr
  116.  * routine is being used.
  117.  */
  118. int __defaultmatherr;
  119.  
  120. /*
  121.  * routine in DLL to do initialization (in this case, C++ constructors)
  122.  */
  123. extern void __cdecl _initterm(_PVFV *, _PVFV *);
  124.  
  125. /*
  126.  * pointers to initialization sections
  127.  */
  128. extern _PVFV __xi_a[], __xi_z[];    /* C++ initializers */
  129. extern _PVFV __xc_a[], __xc_z[];    /* C++ initializers */
  130.  
  131.  
  132. /*
  133.  * Pointers to beginning and end of the table of function pointers manipulated
  134.  * by _onexit()/atexit().  The atexit/_onexit code is shared for both EXE's and
  135.  * DLL's but different behavior is required.  These values are set to -1 to
  136.  * mark this module as an EXE.
  137.  */
  138.  
  139. extern _PVFV *__onexitbegin;
  140. extern _PVFV *__onexitend;
  141.  
  142.  
  143. /***
  144. *void mainCRTStartup(void)
  145. *
  146. *Purpose:
  147. *       This routine does the C runtime initialization, calls main(), and
  148. *       then exits.  It never returns.
  149. *
  150. *Entry:
  151. *
  152. *Exit:
  153. *
  154. *******************************************************************************/
  155.  
  156. #ifdef _WINMAIN_
  157.  
  158. #ifdef WPRFLAG
  159. void wWinMainCRTStartup(
  160. #else  /* WPRFLAG */
  161. void WinMainCRTStartup(
  162. #endif  /* WPRFLAG */
  163.  
  164. #else  /* _WINMAIN_ */
  165.  
  166. #ifdef WPRFLAG
  167. void wmainCRTStartup(
  168. #else  /* WPRFLAG */
  169. void mainCRTStartup(
  170. #endif  /* WPRFLAG */
  171.  
  172. #endif  /* _WINMAIN_ */
  173.         void
  174.         )
  175. {
  176.         int argc;   /* three standard arguments to main */
  177.         _TSCHAR **argv;
  178.         _TSCHAR **envp;
  179.  
  180.         int mainret;
  181.  
  182. #ifdef _WINMAIN_
  183.         _TUCHAR *lpszCommandLine;
  184.         STARTUPINFO StartupInfo;
  185. #endif  /* _WINMAIN_ */
  186.  
  187.         _startupinfo    startinfo;
  188.  
  189.         /*
  190.          * Guard the initialization code and the call to user's main, or
  191.          * WinMain, function in a __try/__except statement.
  192.          */
  193.  
  194.         __try {
  195.             /*
  196.              * Set __app_type properly
  197.              */
  198. #ifdef _WINMAIN_
  199.             __set_app_type(_GUI_APP);
  200. #else  /* _WINMAIN_ */
  201.             __set_app_type(_CONSOLE_APP);
  202. #endif  /* _WINMAIN_ */
  203.  
  204.             /*
  205.              * Mark this module as an EXE file so that atexit/_onexit
  206.              * will do the right thing when called, including for C++
  207.              * d-tors.
  208.              */
  209.             __onexitbegin = __onexitend = (_PVFV *)(-1);
  210.  
  211.             /*
  212.              * Propogate the _fmode and _commode variables to the DLL
  213.              */
  214.             *_IMP___FMODE = _fmode;
  215.             *_IMP___COMMODE = _commode;
  216.  
  217. #ifdef _M_IX86
  218.             /*
  219.              * Set the local copy of the Pentium FDIV adjustment flag
  220.              */
  221.  
  222.             _adjust_fdiv = * _imp___adjust_fdiv;
  223. #endif  /* _M_IX86 */
  224.  
  225.             /*
  226.              * Call _setargv(), which will call the __setargv() in this
  227.              * module if SETARGV.OBJ is linked with the EXE.  If
  228.              * SETARGV.OBJ is not linked with the EXE, a _dummy setargv()
  229.              * will be called.
  230.              */
  231. #ifdef WPRFLAG
  232.             _wsetargv();
  233. #else  /* WPRFLAG */
  234.             _setargv();
  235. #endif  /* WPRFLAG */
  236.  
  237.             /*
  238.              * If the user has supplied a _matherr routine then set
  239.              * __pusermatherr to point to it.
  240.              */
  241.             if ( !__defaultmatherr )
  242.                 __setusermatherr(_matherr);
  243.  
  244. #ifdef _M_IX86
  245.             _setdefaultprecision();
  246. #endif  /* _M_IX86 */
  247.  
  248.             /*
  249.              * Do runtime startup initializers.
  250.              */
  251.             _initterm( __xi_a, __xi_z );
  252.  
  253.  
  254.             /*
  255.              * Get the arguments for the call to main. Note this must be
  256.              * done explicitly, rather than as part of the dll's
  257.              * initialization, to implement optional expansion of wild
  258.              * card chars in filename args
  259.              */
  260.  
  261. #ifdef WPRFLAG
  262.             startinfo.newmode = _newmode;
  263.  
  264.             __wgetmainargs(&argc, &argv, &envp, _dowildcard, &startinfo);
  265. #else  /* WPRFLAG */
  266.             startinfo.newmode = _newmode;
  267.  
  268.             __getmainargs(&argc, &argv, &envp, _dowildcard, &startinfo);
  269. #endif  /* WPRFLAG */
  270.  
  271.             /*
  272.              * do C++ constructors (initializers) specific to this EXE
  273.              */
  274.             _initterm( __xc_a, __xc_z );
  275.  
  276. #ifdef _WINMAIN_
  277.             /*
  278.              * Skip past program name (first token in command line).
  279.              * Check for and handle quoted program name.
  280.                  */
  281. #ifdef WPRFLAG
  282.             /* OS may not support "W" flavors */
  283.             if (_wcmdln == NULL)
  284.                 return;
  285.             lpszCommandLine = (wchar_t *)_wcmdln;
  286. #else  /* WPRFLAG */
  287.             lpszCommandLine = (unsigned char *)_acmdln;
  288. #endif  /* WPRFLAG */
  289.  
  290.             if ( *lpszCommandLine == DQUOTECHAR ) {
  291.                 /*
  292.                  * Scan, and skip over, subsequent characters until
  293.                  * another double-quote or a null is encountered.
  294.                  */
  295.                 while ( *++lpszCommandLine && (*lpszCommandLine
  296.                         != DQUOTECHAR) );
  297.                 /*
  298.                  * If we stopped on a double-quote (usual case), skip
  299.                  * over it.
  300.                  */
  301.                 if ( *lpszCommandLine == DQUOTECHAR )
  302.                     lpszCommandLine++;
  303.             }
  304.             else {
  305.                 while (*lpszCommandLine > SPACECHAR)
  306.                     lpszCommandLine++;
  307.             }
  308.  
  309.             /*
  310.              * Skip past any white space preceeding the second token.
  311.              */
  312.             while (*lpszCommandLine && (*lpszCommandLine <= SPACECHAR)) {
  313.                 lpszCommandLine++;
  314.             }
  315.  
  316.             StartupInfo.dwFlags = 0;
  317.             GetStartupInfo( &StartupInfo );
  318.  
  319. #ifdef WPRFLAG
  320.             mainret = wWinMain(
  321. #else  /* WPRFLAG */
  322.             mainret = WinMain(
  323. #endif  /* WPRFLAG */
  324.                        GetModuleHandle(NULL),
  325.                        NULL,
  326.                        lpszCommandLine,
  327.                        StartupInfo.dwFlags & STARTF_USESHOWWINDOW
  328.                         ? StartupInfo.wShowWindow
  329.                         : SW_SHOWDEFAULT
  330.                       );
  331. #else  /* _WINMAIN_ */
  332.  
  333. #ifdef WPRFLAG
  334.             __winitenv = envp;
  335.             mainret = wmain(argc, argv, envp);
  336. #else  /* WPRFLAG */
  337.             __initenv = envp;
  338.             mainret = main(argc, argv, envp);
  339. #endif  /* WPRFLAG */
  340.  
  341. #endif  /* _WINMAIN_ */
  342.  
  343.             exit(mainret);
  344.         }
  345.         __except ( _XcptFilter(GetExceptionCode(), GetExceptionInformation()) )
  346.         {
  347.             /*
  348.              * Should never reach here
  349.              */
  350.             _exit( GetExceptionCode() );
  351.  
  352.         } /* end of try - except */
  353.  
  354. }
  355.  
  356.  
  357. #endif  /* CRTDLL */
  358.  
  359. #else  /* _MAC */
  360.  
  361. #include <cruntime.h>
  362. #include <internal.h>
  363. #include <stdlib.h>
  364. #include <fltintrn.h>
  365. #include <dbgint.h>
  366.  
  367. /*
  368.  * routine in DLL to do initialization (in this case, C++ constructors)
  369.  */
  370. extern void __cdecl _initterm(PFV *, PFV *);
  371. extern void __cdecl _DoExitSpecial(int, int, PFV *, PFV *, PFV *, PFV *, PFV *, PFV *);
  372. static char * __cdecl _p2cstr_internal ( unsigned char * str );
  373. static void * memcpy_internal ( void * dst, const void * src,   size_t count);
  374. int __cdecl main(int, char **, char **);             /*generated by compiler*/
  375. void _TestExit(int);
  376.  
  377. /*
  378.  * pointers to initialization functions
  379.  */
  380.  
  381. extern PFV __xi_a ;
  382.  
  383. extern PFV __xi_z ;
  384.  
  385. extern PFV __xc_a ;  /* C++ initializers */
  386.  
  387. extern PFV __xc_z ;
  388.  
  389. extern PFV __xp_a ;  /* C pre-terminators */
  390.  
  391. extern PFV __xp_z ;
  392.  
  393. extern PFV __xt_a ;   /* C terminators */
  394.  
  395. extern PFV __xt_z ;
  396.  
  397. extern PFV *__onexitbegin;
  398. extern PFV *__onexitend;
  399.  
  400. /*this globals are defined in DLL */
  401. extern int __argc;
  402.  
  403. extern char **__argv;
  404. /***
  405. *void mainCRTStartup(void)
  406. *
  407. *Purpose:
  408. *       This routine does the C runtime initialization, calls main(), and
  409. *       then exits.  It never returns.
  410. *
  411. *Entry:
  412. *
  413. *Exit:
  414. *
  415. *******************************************************************************/
  416.  
  417. void mainCRTStartup(
  418.         void
  419.         )
  420. {
  421.         int argc = 1;   /* three standard arguments to main */
  422.         char *argv[2];
  423.         char **environ = NULL;
  424.         int mainret;
  425.         char szPgmName[32];
  426.         char *pArg;
  427.         extern unsigned int dwSPStartup;
  428.         extern  void * GetSP(void);
  429.  
  430.         dwSPStartup = (unsigned int)GetSP();
  431.         memcpy_internal(szPgmName, (char *)0x910, sizeof(szPgmName));
  432.         pArg = _p2cstr_internal(szPgmName);
  433.         argv[0] = pArg;
  434.         argv[1] = NULL;
  435.  
  436.         __argc = 1;
  437.         __argv = argv;
  438.  
  439.         /*
  440.          * Mark this module as an EXE file so that atexit/_onexit
  441.          * will do the right thing when called, including for C++
  442.          * d-tors.
  443.          */
  444.         __onexitbegin = __onexitend = (_PVFV *)(-1);
  445.  
  446.         /*
  447.          * Do runtime startup initializers.
  448.          */
  449.         _initterm( &__xi_a, &__xi_z );
  450.  
  451.         /*
  452.          * do C++ constructors (initializers) specific to this EXE
  453.          */
  454.         _initterm( &__xc_a, &__xc_z );
  455.  
  456.         mainret = main(argc, argv, environ);
  457.  
  458.         //strictly testing hook
  459.         _TestExit(mainret);
  460.  
  461.         /*
  462.          * This will do special term for the App in the right order
  463.          */
  464.         _DoExitSpecial( mainret,
  465.                         0,
  466.                         &__xp_a,
  467.                         &__xp_z,
  468.                         &__xt_a,
  469.                         &__xt_z,
  470.                         __onexitbegin,
  471.                         __onexitend );
  472. }
  473.  
  474. static char * __cdecl _p2cstr_internal (
  475.         unsigned char * str
  476.         )
  477. {
  478.         unsigned char *pchSrc;
  479.         unsigned char *pchDst;
  480.         int  cch;
  481.  
  482.         if ( str && *str )
  483.         {
  484.             pchDst = str;
  485.             pchSrc = str + 1;
  486.  
  487.  
  488.             for ( cch=*pchDst; cch; --cch )
  489.             {
  490.                 *pchDst++ = *pchSrc++;
  491.             }
  492.  
  493.             *pchDst = '\0';
  494.         }
  495.  
  496.         return( str );
  497. }
  498.  
  499.  
  500. static void * memcpy_internal (
  501.         void * dst,
  502.         const void * src,
  503.         size_t count
  504.         )
  505. {
  506.         void * ret = dst;
  507.  
  508.         /*
  509.          * copy from lower addresses to higher addresses
  510.          */
  511.         while (count--) {
  512.             *(char *)dst = *(char *)src;
  513.             dst = (char *)dst + 1;
  514.             src = (char *)src + 1;
  515.         }
  516.  
  517.         return(ret);
  518. }
  519.  
  520. #endif  /* _MAC */
  521.