Example #1
0
int
__tmainCRTStartup(
    void
) {
    unsigned int osplatform = 0;
    unsigned int winver = 0;
    unsigned int winmajor = 0;
    unsigned int winminor = 0;
    unsigned int osver = 0;
    int initret;
    int mainret = 0;
    OSVERSIONINFOA* posvi;
    int managedapp;
#ifdef _WINMAIN_
    _TUCHAR* lpszCommandLine;
    STARTUPINFO StartupInfo;

    __try {
        /*
        Note: MSDN specifically notes that GetStartupInfo returns no error, and throws unspecified SEH if it fails, so
        the very general exception handler below is appropriate
        */
        GetStartupInfo(&StartupInfo);
    } __except (EXCEPTION_EXECUTE_HANDLER) {
        return 255;
    }

#endif  /* _WINMAIN_ */
    /*
     * Dynamically allocate the OSVERSIONINFOA buffer, so we avoid
     * triggering the /GS buffer overrun detection.  That can't be
     * used here, since the guard cookie isn't available until we
     * initialize it from here!
     */
    posvi = (OSVERSIONINFOA*)HeapAlloc(GetProcessHeap(), 0, sizeof(OSVERSIONINFOA));

    if (!posvi) {
        fast_error_exit(_RT_HEAP);
        return 255;
    }

    /*
     * Get the full Win32 version
     */
    posvi->dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);

    if (!GetVersionExA(posvi)) {
        HeapFree(GetProcessHeap(), 0, posvi);
        return 255;
    }

    osplatform = posvi->dwPlatformId;
    winmajor = posvi->dwMajorVersion;
    winminor = posvi->dwMinorVersion;
    /*
     * The somewhat bizarre calculations of _osver and _winver are
     * required for backward compatibility (used to use GetVersion)
     */
    osver = (posvi->dwBuildNumber) & 0x07fff;
    HeapFree(GetProcessHeap(), 0, posvi);

    if (osplatform != VER_PLATFORM_WIN32_NT) {
        osver |= 0x08000;
    }

    winver = (winmajor << 8) + winminor;
    _set_osplatform(osplatform);
    _set_winver(winver);
    _set_winmajor(winmajor);
    _set_winminor(winminor);
    _set_osver(osver);
    /*
     * Determine if this is a managed application
     */
    managedapp = check_managed_app();

    if (!_heap_init(1)) {               /* initialize heap */
        fast_error_exit(_RT_HEAPINIT);    /* write message and die */
    }

    if (!_mtinit()) {                   /* initialize multi-thread */
        fast_error_exit(_RT_THREAD);    /* write message and die */
    }

    /* Enable buffer count checking if linking against static lib */
    _CrtSetCheckCount(TRUE);
    /*
     * Initialize the Runtime Checks stuff
     */
#ifdef _RTC
    _RTC_Initialize();
#endif  /* _RTC */
    /*
     * Guard the remainder of the initialization code and the call
     * to user's main, or WinMain, function in a __try/__except
     * statement.
     */

    __try {
        if (_ioinit() < 0) {            /* initialize lowio */
            _amsg_exit(_RT_LOWIOINIT);
        }

        /* get wide cmd line info */
        _tcmdln = (_TSCHAR*)GetCommandLineT();
        /* get wide environ info */
        _tenvptr = (_TSCHAR*)GetEnvironmentStringsT();

        if (_tsetargv() < 0) {
            _amsg_exit(_RT_SPACEARG);
        }

        if (_tsetenvp() < 0) {
            _amsg_exit(_RT_SPACEENV);
        }

        initret = _cinit(TRUE);                  /* do C data initialize */

        if (initret != 0) {
            _amsg_exit(initret);
        }

#ifdef _WINMAIN_
        lpszCommandLine = _twincmdln();
        mainret = _tWinMain((HINSTANCE)&__ImageBase,
                            NULL,
                            lpszCommandLine,
                            StartupInfo.dwFlags & STARTF_USESHOWWINDOW
                            ? StartupInfo.wShowWindow
                            : SW_SHOWDEFAULT
                           );
#else  /* _WINMAIN_ */
        _tinitenv = _tenviron;
        mainret = _tmain(__argc, _targv, _tenviron);
#endif  /* _WINMAIN_ */

        if (!managedapp) {
            exit(mainret);
        }

        _cexit();
    } __except (_XcptFilter(GetExceptionCode(), GetExceptionInformation())) {
        /*
         * Should never reach here
         */
        mainret = GetExceptionCode();

        if (!managedapp) {
            _exit(mainret);
        }

        _c_exit();
    } /* end of try - except */

    return mainret;
}
Example #2
0
int
__tmainCRTStartup(
    void
) {
#ifdef _WINMAIN_
    _TUCHAR* lpszCommandLine;
    STARTUPINFO StartupInfo;
    BOOL inDoubleQuote = FALSE;

    __try {
        /*
        Note: MSDN specifically notes that GetStartupInfo returns no error, and throws unspecified SEH if it fails, so
        the very general exception handler below is appropriate
        */
        GetStartupInfo(&StartupInfo);
    } __except (EXCEPTION_EXECUTE_HANDLER) {
        return 255;
    }

#endif  /* _WINMAIN_ */

    /*
     * Guard the initialization code and the call to user's main, or
     * WinMain, function in a __try/__except statement.
     */

    __try {
        /*
         * There is a possiblity that the module where this object is
         * linked into is a mixed module. In all the cases we gurantee that
         * native initialization will occur before managed initialization.
         * Also in anycase this code should never be called when some other
         * code is initializing native code, that's why we exit in that case.
         *
         * Do runtime startup initializers.
         *
         * Note: the only possible entry we'll be executing here is for
         * __lconv_init, pulled in from charmax.obj only if the EXE was
         * compiled with -J.  All other .CRT$XI* initializers are only
         * run as part of the CRT itself, and so for the CRT DLL model
         * are not found in the EXE.  For that reason, we call _initterm,
         * not _initterm_e, because __lconv_init will never return failure,
         * and _initterm_e is not exported from the CRT DLL.
         *
         * Note further that, when using the CRT DLL, executing the
         * .CRT$XI* initializers is only done for an EXE, not for a DLL
         * using the CRT DLL.  That is to make sure the -J setting for
         * the EXE is not overriden by that of any DLL.
         */
        void* lock_free = 0;
        void* fiberid = ((PNT_TIB)NtCurrentTeb())->StackBase;
        int nested = FALSE;

        while ((lock_free = InterlockedCompareExchangePointer((volatile PVOID*)&__native_startup_lock, fiberid, 0)) != 0) {
            if (lock_free == fiberid) {
                nested = TRUE;
                break;
            }

            /* some other thread is running native startup/shutdown during a cctor/domain unload.
                Should only happen if this DLL was built using the Everett-compat loader lock fix in vcclrit.h
            */
            /* wait for the other thread to complete init before we return */
            Sleep(1000);
        }

        if (__native_startup_state == __initializing) {
            _amsg_exit(_RT_CRT_INIT_CONFLICT);
        } else if (__native_startup_state == __uninitialized) {
            __native_startup_state = __initializing;
#ifndef _SYSCRT

            if (_initterm_e(__xi_a, __xi_z) != 0) {
                return 255;
            }

#else  /* _SYSCRT */
            _initterm((_PVFV*)(void*)__xi_a, (_PVFV*)(void*)__xi_z);
#endif  /* _SYSCRT */
        } else {
            has_cctor = 1;
        }

        /*
        * do C++ constructors (initializers) specific to this EXE
        */
        if (__native_startup_state == __initializing) {
            _initterm(__xc_a, __xc_z);
            __native_startup_state = __initialized;
        }

        _ASSERTE(__native_startup_state == __initialized);

        if (!nested) {
            /* For X86, the definition of InterlockedExchangePointer wrongly causes warning C4312 */
#pragma warning(push)
#pragma warning(disable:4312)
            InterlockedExchangePointer((volatile PVOID*)&__native_startup_lock, 0);
#pragma warning(pop)
        }

        /*
         * If we have any dynamically initialized __declspec(thread)
         * variables, then invoke their initialization for the primary
         * thread used to start the process, by calling __dyn_tls_init
         * through a callback defined in tlsdyn.obj.
         */
        if (__dyn_tls_init_callback != NULL &&
                _IsNonwritableInCurrentImage((PBYTE)&__dyn_tls_init_callback)) {
            __dyn_tls_init_callback(NULL, DLL_THREAD_ATTACH, NULL);
        }

        /* Enable buffer count checking if linking against static lib */
        _CrtSetCheckCount(TRUE);
#ifdef _WINMAIN_
        /*
         * Skip past program name (first token in command line).
         * Check for and handle quoted program name.
         */
#ifdef WPRFLAG

        /* OS may not support "W" flavors */
        if (_wcmdln == NULL) {
            return 255;
        }

        lpszCommandLine = (wchar_t*)_wcmdln;
#else  /* WPRFLAG */
        lpszCommandLine = (unsigned char*)_acmdln;
#endif  /* WPRFLAG */

        while (*lpszCommandLine > SPACECHAR ||
                (*lpszCommandLine && inDoubleQuote)) {
            /*
             * Flip the count from 1 to 0 or 0 to 1 if current character
             * is DOUBLEQUOTE
             */
            if (*lpszCommandLine == DQUOTECHAR) {
                inDoubleQuote = !inDoubleQuote;
            }

#ifdef _MBCS

            if (_ismbblead(*lpszCommandLine)) {
                if (lpszCommandLine) {
                    lpszCommandLine++;
                }
            }

#endif  /* _MBCS */
            ++lpszCommandLine;
        }

        /*
         * Skip past any white space preceeding the second token.
         */
        while (*lpszCommandLine && (*lpszCommandLine <= SPACECHAR)) {
            lpszCommandLine++;
        }

#ifdef WPRFLAG
        mainret = wWinMain(
#else  /* WPRFLAG */
        mainret = WinMain(
#endif  /* WPRFLAG */
                      (HINSTANCE)&__ImageBase,
                      NULL,
                      lpszCommandLine,
                      StartupInfo.dwFlags & STARTF_USESHOWWINDOW
                      ? StartupInfo.wShowWindow
                      : SW_SHOWDEFAULT
                  );
#else  /* _WINMAIN_ */
#ifdef WPRFLAG
        __winitenv = envp;
        mainret = wmain(argc, argv, envp);
#else  /* WPRFLAG */
        __initenv = envp;
        mainret = main(argc, argv, envp);
#endif  /* WPRFLAG */
#endif  /* _WINMAIN_ */

        /*
         * Note that if the exe is managed app, we don't really need to
         * call exit or _c_exit. .cctor should be able to take care of
         * this.
         */
        if (!managedapp)
            exit(mainret);
        if (has_cctor == 0)
            _cexit();
    } __except (_XcptFilter(GetExceptionCode(), GetExceptionInformation())) {
        /*
         * Should never reach here
         */
        mainret = GetExceptionCode();

        /*
         * Note that if the exe is managed app, we don't really need to
         * call exit or _c_exit. .cctor should be able to take care of
         * this.
         */
        if (!managedapp) {
            _exit(mainret);
        }

        if (has_cctor == 0) {
            _cexit();
        }
    } /* end of try - except */

    return mainret;
}
Example #3
0
BOOL WINAPI _CRT_INIT(
    HANDLE  hDllHandle,
    DWORD   dwReason,
    LPVOID  lpreserved
) {
    unsigned int osplatform = 0;
    unsigned int winver = 0;
    unsigned int winmajor = 0;
    unsigned int winminor = 0;
    unsigned int osver = 0;

    /*
     * Start-up code only gets executed when the process is initialized
     */

    if (dwReason == DLL_PROCESS_ATTACH) {
        /*
         * Dynamically allocate the OSVERSIONINFOA buffer, so we avoid
         * triggering the /GS buffer overrun detection.  That can't be
         * used here, since the guard cookie isn't available until we
         * initialize it from here!
         */
        OSVERSIONINFOA* posvi =
            (OSVERSIONINFOA*)HeapAlloc(GetProcessHeap(), 0, sizeof(OSVERSIONINFOA));

        if (!posvi) {
            return FALSE;
        }

        /*
         * Get the full Win32 version
         */
        posvi->dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);

        if (!GetVersionExA(posvi)) {
            HeapFree(GetProcessHeap(), 0, posvi);
            return FALSE;
        }

        osplatform = posvi->dwPlatformId;
        winmajor = posvi->dwMajorVersion;
        winminor = posvi->dwMinorVersion;
        /*
         * The somewhat bizarre calculations of _osver and _winver are
         * required for backward compatibility (used to use GetVersion)
         */
        osver = (posvi->dwBuildNumber) & 0x07fff;
        HeapFree(GetProcessHeap(), 0, posvi);

        if (osplatform != VER_PLATFORM_WIN32_NT) {
            osver |= 0x08000;
        }

        winver = (winmajor << 8) + winminor;
        _set_osplatform(osplatform);
        _set_winver(winver);
        _set_winmajor(winmajor);
        _set_winminor(winminor);
        _set_osver(osver);

        if (!_heap_init(1)) {   /* initialize heap */
            return FALSE;    /* fail to load DLL */
        }

        if (!_mtinit()) {       /* initialize multi-thread */
            _heap_term();       /* heap is now invalid! */
            return FALSE;       /* fail to load DLL */
        }

        /*
         * Initialize the Runtime Checks stuff
         */
#ifdef _RTC
        _RTC_Initialize();
#endif  /* _RTC */
        _acmdln = (char*)GetCommandLineA();
        _aenvptr = (char*)__crtGetEnvironmentStringsA();

        if (_ioinit() < 0) {    /* initialize lowio */
            _mtterm();          /* free TLS index, call _mtdeletelocks() */
            _heap_term();       /* heap is now invalid! */
            return FALSE;       /* fail to load DLL */
        }

        if (_setargv() < 0 ||   /* get cmd line info */
                _setenvp() < 0 ||   /* get environ info */
                _cinit(FALSE) != 0) { /* do C data initialize, but don't init floating point */
            _ioterm();          /* shut down lowio */
            _mtterm();          /* free TLS index, call _mtdeletelocks() */
            _heap_term();       /* heap is now invalid! */
            return FALSE;       /* fail to load DLL */
        }

        /* Enable buffer count checking if linking against static lib */
        _CrtSetCheckCount(TRUE);
        /*
         * increment flag to indicate process attach notification
         * has been received
         */
        __proc_attached++;
    } else if (dwReason == DLL_PROCESS_DETACH) {
        if (__proc_attached > 0) {
            __proc_attached--;

            /*
             * 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.
             */

            if (_C_Termination_Done == FALSE) {
                _cexit();
            }

#ifdef _DEBUG

            /* Dump all memory leaks */
            if (_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) & _CRTDBG_LEAK_CHECK_DF) {
                _CrtDumpMemoryLeaks();
            }

#endif  /* _DEBUG */
            /*
             * What remains is to clean up the system resources we have
             * used (handles, critical sections, memory,...,etc.). This
             * needs to be done if the whole process is NOT terminating.
             */
#ifndef _DEBUG

            if (lpreserved == NULL) {
#endif  /* _DEBUG */
                /*
                 * The process is NOT terminating so we must clean up...
                 */
                /* Shut down lowio */
                _ioterm();
                _mtterm();
                /* This should be the last thing the C run-time does */
                _heap_term();   /* heap is now invalid! */
#ifndef _DEBUG
            }

#endif  /* _DEBUG */
        } else
            /* no prior process attach, just return */
        {
            return FALSE;
        }
    } else if (dwReason == DLL_THREAD_ATTACH) {
        _ptiddata ptd;
        /* Initialize FlsGetValue function pointer */
        __set_flsgetvalue();

        if (((ptd = _calloc_crt(1, sizeof(struct _tiddata))) != NULL)) {
            if (FLS_SETVALUE(__flsindex, (LPVOID)ptd)) {
                /*
                 * Initialize of per-thread data
                 */
                _initptd(ptd, NULL);
                ptd->_tid = GetCurrentThreadId();
                ptd->_thandle = (uintptr_t)(-1);
            } else {
                _free_crt(ptd);
                return FALSE;
            }
        } else {
            return FALSE;
        }
    } else if (dwReason == DLL_THREAD_DETACH) {
        _freeptd(NULL);         /* free up per-thread CRT data */
    }

    return TRUE ;
}
Example #4
0
BOOL WINAPI _CRT_INIT(
        HANDLE  hDllHandle,
        DWORD   dwReason,
        LPVOID  lpreserved
        )
{
        /*
         * If this is a process detach notification, check that there has
         * been a prior (successful) process attachment.
         */
        if ( dwReason == DLL_PROCESS_DETACH ) {
            if ( __proc_attached > 0 )
                __proc_attached--;
            else
                /*
                 * no prior process attach. just return failure.
                 */
                return FALSE;
        }

#ifdef _M_IX86

        /*
         * Set the local copy of the Pentium FDIV adjustment flag
         */

        _adjust_fdiv = * _imp___adjust_fdiv;

#endif  /* _M_IX86 */

        /*
         * do C++ constructors (initializers) specific to this DLL
         */

        if ( dwReason == DLL_PROCESS_ATTACH ) {
            /*
             * There is a possiblity that the module where this object is
             * linked into is a mixed module. In all the cases we gurantee
             * that native initialization will occur before managed
             * initialization.  Also in anycase this code should never be
             * called when some other code is initializing native code,
             * that's why we exit in that case.
             *
             * The case that is illegal is when managed code is executed for
             * the first time in loader lock. But there can be case when dll is
             * loaded in LoadLibrary and CLR could be already loaded in this
             * case it is perfectly OK to execute .cctor.
             */

            void *lock_free=0;
            void *fiberid=((PNT_TIB)NtCurrentTeb())->StackBase;

            int nested=FALSE;
            while((lock_free=InterlockedCompareExchangePointer((volatile PVOID *)&__native_startup_lock, fiberid, 0))!=0)
            {
                if(lock_free==fiberid)
                {
                    nested=TRUE;
                    break;
                }

                /* some other thread is running native startup/shutdown during a cctor/domain unload.
                    Should only happen if this DLL was built using the Everett-compat loader lock fix in vcclrit.h
                */
                /* wait for the other thread to complete init before we return */
                Sleep(1000);
            }

            if (__native_startup_state != __uninitialized)
            {
                _amsg_exit( _RT_CRT_INIT_CONFLICT);
            }
            else
            {
                /*
                * Set the native startup state to initializing.
                */
                __native_startup_state = __initializing;


                /*
                * Invoke C initializers.
                */

#ifndef _SYSCRT
                if (_initterm_e( __xi_a, __xi_z ) != 0)
                    return FALSE;
#else  /* _SYSCRT */
                _initterm((_PVFV *)(void *)__xi_a, (_PVFV *)(void *)__xi_z);
#endif  /* _SYSCRT */
                /*
                * Invoke C++ constructors
                */
                _initterm(__xc_a,__xc_z);

                /*
                * Set the native initialization state to initialized.
                */
                __native_startup_state = __initialized;
            }
            if(!nested)
            {
                /* For X86, the definition of InterlockedExchangePointer wrongly causes warning C4312 */
#pragma warning(push)
#pragma warning(disable:4312)
                InterlockedExchangePointer((volatile PVOID *)&__native_startup_lock,0);
#pragma warning(pop)
            }

            /*
             * If we have any dynamically initialized __declspec(thread)
             * variables, then invoke their initialization for the thread on
             * which the DLL is being loaded, by calling __dyn_tls_init through
             * a callback defined in tlsdyn.obj.  We can't rely on the OS
             * calling __dyn_tls_init with DLL_PROCESS_ATTACH because, on
             * Win2K3 and before, that call happens before the CRT is
             * initialized.
             */
            if (__dyn_tls_init_callback != NULL &&
                _IsNonwritableInCurrentImage((PBYTE)&__dyn_tls_init_callback))
            {
                __dyn_tls_init_callback(hDllHandle, DLL_THREAD_ATTACH,
                                        lpreserved);
            }

            /* Enable buffer count checking if linking against static lib */
            _CrtSetCheckCount(TRUE);

            /*
             * Increment the process attached flag.
             */
            __proc_attached++;

        }
        else if ( dwReason == DLL_PROCESS_DETACH )
        {

            /*
             * 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.
             */

            void *lock_free=0;
            while((lock_free=InterlockedCompareExchangePointer((volatile PVOID *)&__native_startup_lock, (PVOID)1, 0))!=0)
            {
                /* some other thread is running native startup/shutdown during a cctor/domain unload.
                    Should only happen if this DLL was built using the Everett-compat loader lock fix in vcclrit.h
                */
                /* wait for the other thread to complete init before we return */
                Sleep(1000);
            }

            if(__native_startup_state!=__initialized)
            {
                /* somehow we are in a very bad state running shutdown when we have not started */
                _amsg_exit( _RT_CRT_INIT_CONFLICT);
            }
            else
            {
                _PVFV * onexitbegin = (_PVFV *)_decode_pointer(__onexitbegin);
                if (onexitbegin)
                {
                    _PVFV * onexitend = (_PVFV *)_decode_pointer(__onexitend);
                    while ( --onexitend >= onexitbegin )
                        /*
                        * if current table entry is not
                        * NULL, call thru it.
                        */
                        if ( *onexitend != NULL )
                            (**onexitend)();

                    /*
                    * free the block holding onexit table to
                    * avoid memory leaks.  Also zero the ptr
                    * variables so that they are clearly cleaned up.
                    */

                    _free_crt ( onexitbegin ) ;

                    __onexitbegin = __onexitend = (_PVFV *)_encoded_null();
                }
                __native_startup_state = __uninitialized;
                /* For X86, the definition of InterlockedExchangePointer wrongly causes warning C4312 */
#pragma warning(push)
#pragma warning(disable:4312)
                InterlockedExchangePointer((volatile PVOID *)&__native_startup_lock,0);
#pragma warning(pop)
            }
       }

       return TRUE;
}