BOOL __cdecl
__CRTDLL_INIT(
        HANDLE  hDllHandle,
        DWORD   dwReason,
        LPVOID  lpreserved
        )
{
        BOOL term_all = FALSE;

        if ( dwReason == DLL_PROCESS_ATTACH ) {
            if ( !_heap_init() )    /* initialize heap */
                /*
                 * The heap cannot be initialized, return failure to the
                 * loader.
                 */
                return FALSE;

            if(!_mtinit())          /* initialize multi-thread */
            {
                /*
                 * If the DLL load is going to fail, we must clean up
                 * all resources that have already been allocated.
                 */
                _heap_term();       /* heap is now invalid! */

                return FALSE;       /* fail DLL load on failure */
            }

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

            _wcmdln = GetCommandLineW();

#if !defined(_CRT_APP) || defined(_KERNELX)
            _aenvptr = (char *)__crtGetEnvironmentStringsA();
            _acmdln = GetCommandLineA();
#else /* !defined(_CRT_APP) || defined(_KERNELX) */
            // We cannot call GetCommandLineA in the App CRT:
            if (!__copy_to_char(_wcmdln, &_acmdln))
            {
                _acmdln = NULL;
            }
#endif /* !defined(_CRT_APP) || defined(_KERNELX) */

#if !defined(_CRT_APP) || defined(_KERNELX)
#ifdef _MBCS
            /*
             * Initialize multibyte ctype table. Always done since it is
             * needed for processing the environment strings.
             */
            __initmbctable();
#endif  /* _MBCS */

            if (_setenvp() < 0 ||   /* get environ info */
                _cinit(FALSE) != 0)  /* do C data initialize */
            {
                term_all = TRUE;
            }
#else  /* !defined(_CRT_APP) || defined(_KERNELX) */
            if (_cinit(FALSE) != 0)  /* do C data initialize */
            {
                term_all = TRUE;
            }
#endif  /* !defined(_CRT_APP) || defined(_KERNELX) */

            if (term_all)
            {
#if defined(_CRT_APP) && !defined(_KERNELX)
                _free_crt(_acmdln);
                _acmdln = NULL;
#endif
                _ioterm();          /* shut down lowio */
                _mtterm();          /* free TLS index, call _mtdeletelocks() */
                _heap_term();       /* heap is now invalid! */
                return FALSE;       /* fail DLL load on failure */
            }

            /*
             * Increment flag indicating process attach notification
             * has been received.
             */
            proc_attached++;

        }
        else if ( dwReason == DLL_PROCESS_DETACH ) {
            /*
             * if a client process is detaching, make sure minimal
             * runtime termination is performed and clean up our
             * 'locks' (i.e., delete critical sections).
             */
            if ( proc_attached > 0 ) {
                proc_attached--;
                __try {

                    /*
                     * Any basic clean-up done here may also need
                     * to be done below if Process Attach is partly
                     * processed and then a failure is encountered.
                     */

                    if ( _C_Termination_Done == FALSE )
                        _cexit();

                    __crtdll_callstaticterminators();

                    /* Free all allocated CRT memory */
                    __freeCrtMemory();

#ifdef _DEBUG
                    /* Dump all memory leaks */
                    if (_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) & _CRTDBG_LEAK_CHECK_DF)
                    {
                        _CrtSetDumpClient(NULL);
                        _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.
                     */

                    /* If dwReason is DLL_PROCESS_DETACH, lpreserved is NULL
                     * if FreeLibrary has been called or the DLL load failed
                     * and non-NULL if the process is terminating.
                     */
                    if ( lpreserved == NULL )
                    {
#if defined(_CRT_APP) && !defined(_KERNELX)
                        _free_crt(_acmdln);
                        _acmdln = NULL;
#endif
                        /*
                         * The process is NOT terminating so we must clean up...
                         */
                        _ioterm();

                        /* free TLS index, call _mtdeletelocks() */
                        _mtterm();

                        /* This should be the last thing the C run-time does */
                        _heap_term();   /* heap is now invalid! */
                    }

                }
                __finally {
                    /* we shouldn't really have to care about this, because
                       letting an exception escape from DllMain(DLL_PROCESS_DETACH) should
                       result in process termination. Unfortunately, Windows up to Win7 as of now
                       just silently swallows the exception.

                       I have considered all kinds of tricks, but decided to leave it up to OS
                       folks to fix this.

                       For the time being just remove our FLS callback during phase 2 unwind
                       that would otherwise be left pointing to unmapped address space.
                       */
                     if ( lpreserved == NULL && __flsindex != FLS_OUT_OF_INDEXES )
                         _mtterm();
                }
            }
            else
                /* no prior process attach, just return */
                return FALSE;
Beispiel #2
0
/***
*int _cenvarg(argv, envp, argblk, envblk, name) - set up cmd line/environ
*
*Purpose:
*       Set up the block forms of  the environment and the command line.
*       If "envp" is null, "_environ" is used instead.
*
*Entry:
*       _TSCHAR **argv   - argument vector
*       _TSCHAR **envp   - environment vector
*       _TSCHAR **argblk - pointer to pointer set to malloc'ed space for args
*       _TSCHAR **envblk - pointer to pointer set to malloc'ed space for env
*       _TSCHAR *name    - name of program being invoked
*
*Exit:
*       returns 0 if ok, -1 if fails
*       stores through argblk and envblk
*       (calls malloc)
*
*Exceptions:
*
*******************************************************************************/

#ifdef WPRFLAG
int __cdecl _wcenvarg (
#else  /* WPRFLAG */
int __cdecl _cenvarg (
#endif  /* WPRFLAG */
        const _TSCHAR * const *argv,
        const _TSCHAR * const *envp,
        _TSCHAR **argblk,
        _TSCHAR **envblk,
        const _TSCHAR *name
        )
{
        REG1 const _TSCHAR * const *vp;
        REG2 unsigned tmp;
        REG3 _TSCHAR *cptr;
        unsigned arg_len;
        unsigned env_len;
        int cfi_len;            /* counts the number of file handles in CFI */
        int retval = 0;

        /*
         * Null environment pointer "envp" means use global variable,
         * "_environ"
         */

        int cwd_start;
        int cwd_end;            /* length of "cwd" strings in environment */

        _TSCHAR envpfx[] = _T("SystemRoot");
        _TSCHAR *envbuf = NULL;
        int envsize = 0;
        int defined = 0;

        /*
         * Allocate space for command line string
         *  tmp counts the number of bytes in the command line string
         *      including spaces between arguments
         *  An empty string is special -- 2 bytes
         */

        for (vp = argv, tmp = 2; *vp; tmp += (unsigned int)_tcslen(*vp++) + 1) ;

        arg_len = tmp;

        /*
         * Allocate space for the command line plus 2 null bytes
         */

        if ( (*argblk = _calloc_crt(tmp, sizeof(_TSCHAR))) == NULL)
        {
                *envblk = NULL;
                errno = ENOMEM;
                _doserrno = E_nomem;
                return(-1);
        }

        if (_ERRCHECK_EINVAL(_tdupenv_s_crt(&envbuf, NULL, envpfx)) != 0)
        {
                retval = -1;
                goto error;
        }

        envsize = (int)_tcslen(envpfx) + 2;
        if (envbuf != NULL)
        {
            envsize += (int)_tcslen(envbuf);
        }

        /*
         * Allocate space for environment strings
         *  tmp counts the number of bytes in the environment strings
         *      including nulls between strings
         *  Also add "_C_FILE_INFO=" string
         */
        if (envp)
                for (vp = envp, tmp = 2; *vp; tmp += (unsigned int)_tcslen(*vp++) + 1) ;

        /*
         * The _osfile and _osfhnd arrays are passed as binary data in
         * dospawn.c
         */
        cfi_len = 0;    /* no _C_FILE_INFO */

        if (!envp)
                *envblk = NULL;
        else {
                /*
                 * Now that we've decided to pass our own environment block,
                 * compute the size of the "current directory" strings to
                 * propagate to the new environment.
                 */

#ifdef WPRFLAG
                /*
                 * Make sure wide environment exists.
                 */
                if (!_wenvptr)
                {
                        if ((_wenvptr = (wchar_t *)__crtGetEnvironmentStringsW()) == NULL)
                        {
                                retval = -1;
                                goto error;
                        }
                }
#else  /* WPRFLAG */
                if (!_aenvptr)
                {
                        if ((_aenvptr = (char *)__crtGetEnvironmentStringsA()) == NULL)
                        {
                                retval = -1;
                                goto error;
                        }
                }
#endif  /* WPRFLAG */

                /*
                 * search for the first one
                 */
                for (cwd_start = 0;
                     _tenvptr[cwd_start] != _T('\0') &&
                       _tenvptr[cwd_start] != _T('=');
                     cwd_start += (int)_tcslen(&_tenvptr[cwd_start]) + 1)
                {
                }

                /* find the total size of all contiguous ones */
                cwd_end = cwd_start;
                while (_tenvptr[cwd_end+0] == _T('=') &&
                       _tenvptr[cwd_end+1] != _T('\0') &&
                       _tenvptr[cwd_end+2] == _T(':') &&
                       _tenvptr[cwd_end+3] == _T('='))
                {
                        cwd_end += 4 + (int)_tcslen(&_tenvptr[cwd_end+4]) + 1;
                }
                tmp += cwd_end - cwd_start;

                /*
                 * Allocate space for the environment strings plus extra null byte
                 */
                env_len = tmp;

                /*
                 * Check if SystemRoot is already defined in environment provided
                 */
                for (vp = envp; *vp; vp++) {
                        if (_tcsncicmp(*vp, envpfx, _tcslen(envpfx)) == 0) {
                                defined = 1;
                                break;
                        }
                }

                if (!defined)
                        tmp += envsize;

                if( !(*envblk = _calloc_crt(tmp, sizeof(_TSCHAR))) )
                {
                        _free_crt(*argblk);
                        *argblk = NULL;
                        errno = ENOMEM;
                        _doserrno = E_nomem;
                        retval = -1;
                        goto done;
                }
        }

        /*
         * Build the command line by concatenating the argument strings
         * with spaces between, and two null bytes at the end.
         * NOTE: The argv[0] argument is followed by a null.
         */

        cptr = *argblk;
        vp = argv;

        if (!*vp)       /* Empty argument list ? */
                ++cptr; /* just two null bytes */
        else {          /* argv[0] must be followed by a null */
                _ERRCHECK(_tcscpy_s(cptr, arg_len - (cptr - *argblk), *vp));
                cptr += (int)_tcslen(*vp++) + 1;
        }

        while( *vp ) {
                _ERRCHECK(_tcscpy_s(cptr, arg_len - (cptr - *argblk), *vp));
                cptr += (int)_tcslen(*vp++);
                *cptr++ = ' ';
        }

        *cptr = cptr[ -1 ] = _T('\0'); /* remove extra blank, add double null */

        /*
         * Build the environment block by concatenating the environment
         * strings with nulls between and two null bytes at the end
         */

        cptr = *envblk;

        if (envp != NULL) {
                /*
                 * Copy the "cwd" strings to the new environment.
                 */
                memcpy(cptr, &_tenvptr[cwd_start], (cwd_end - cwd_start) * sizeof(_TSCHAR));
                cptr += cwd_end - cwd_start;

                /*
                 * Copy the environment strings from "envp".
                 */
                vp = envp;
                while( *vp ) {
                        _ERRCHECK(_tcscpy_s(cptr, env_len - (cptr - *envblk), *vp));
                        cptr += 1 + (int)_tcslen(*vp++);
                }

                if (!defined) {
                        /*
                         * Copy SystemRoot to the new environment.
                         */
                        _ERRCHECK(_tcscpy_s(cptr, envsize, envpfx));
                        _ERRCHECK(_tcscat_s(cptr, envsize, _T("=")));
                        if (envbuf != NULL)
                        {
                            _ERRCHECK(_tcscat_s(cptr, envsize, envbuf));
                        }
                        cptr += envsize;
                }
        }

        if (cptr != NULL) {
                if (cptr == *envblk) {
                        /*
                         * Empty environment block ... this requires two
                         * nulls.
                         */
                        *cptr++ = _T('\0');
                }
                /*
                 * Extra null terminates the segment
                 */
                *cptr = _T('\0');
        }

        goto done;

error:
        _free_crt(*argblk);
        *argblk = NULL;
        *envblk = NULL;

done:

#ifdef WPRFLAG
        if (_wenvptr)
                _free_crt(_wenvptr);
        _wenvptr = NULL;
#else  /* WPRFLAG */
        if (_aenvptr)
                _free_crt(_aenvptr);
        _aenvptr = NULL;
#endif  /* WPRFLAG */
        if (envbuf)
                _free_crt(envbuf);

        return retval;
}
Beispiel #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 ;
}
Beispiel #4
0
/***
*int _cenvarg(argv, envp, argblk, envblk, name) - set up cmd line/environ
*
*Purpose:
*       Set up the block forms of  the environment and the command line.
*       If "envp" is null, "_environ" is used instead.
*       File handle info is passed in the environment if _fileinfo is !0.
*
*Entry:
*       _TSCHAR **argv   - argument vector
*       _TSCHAR **envp   - environment vector
*       _TSCHAR **argblk - pointer to pointer set to malloc'ed space for args
*       _TSCHAR **envblk - pointer to pointer set to malloc'ed space for env
*       _TSCHAR *name    - name of program being invoked
*
*Exit:
*       returns 0 if ok, -1 if fails
*       stores through argblk and envblk
*       (calls malloc)
*
*Exceptions:
*
*******************************************************************************/

#ifdef WPRFLAG
int __cdecl _wcenvarg (
#else  /* WPRFLAG */
int __cdecl _cenvarg (
#endif  /* WPRFLAG */
        const _TSCHAR * const *argv,
        const _TSCHAR * const *envp,
        _TSCHAR **argblk,
        _TSCHAR **envblk,
        const _TSCHAR *name
        )
{
        REG1 const _TSCHAR * const *vp;
        REG2 unsigned tmp;
        REG3 _TSCHAR *cptr;
        unsigned arg_len;
        int cfi_len;            /* counts the number of file handles in CFI */

        /*
         * Null environment pointer "envp" means use global variable,
         * "_environ"
         */

        int cwd_start;
        int cwd_end;            /* length of "cwd" strings in environment */

        /*
         * Allocate space for command line string
         *  tmp counts the number of bytes in the command line string
         *      including spaces between arguments
         *  An empty string is special -- 2 bytes
         */

        for (vp = argv, tmp = 2; *vp; tmp += _tcslen(*vp++) + 1) ;

        arg_len = tmp;

        /*
         * Allocate space for the command line plus 2 null bytes
         */

        if ( (*argblk = _malloc_crt(tmp * sizeof(_TSCHAR))) == NULL)
        {
                *envblk = NULL;
                errno = ENOMEM;
                _doserrno = E_nomem;
                return(-1);
        }

        /*
         * Allocate space for environment strings
         *  tmp counts the number of bytes in the environment strings
         *      including nulls between strings
         *  Also add "_C_FILE_INFO=" string
         */
        if (envp)
                for (vp = envp, tmp = 2; *vp; tmp += _tcslen(*vp++) + 1) ;

        /*
         * The _osfile and _osfhnd arrays are passed as binary data in
         * dospawn.c
         */
        cfi_len = 0;    /* no _C_FILE_INFO */

        if (!envp)
                *envblk = NULL;
        else {
                /*
                 * Now that we've decided to pass our own environment block,
                 * compute the size of the "current directory" strings to
                 * propagate to the new environment.
                 */

#ifdef WPRFLAG
            /*
             * Make sure wide environment exists.
             */
            if (!_wenvptr)
            {
                    if ((_wenvptr = (wchar_t *)__crtGetEnvironmentStringsW()) == NULL)
                    return -1;
            }
#else  /* WPRFLAG */
            if (!_aenvptr)
            {
                    if ((_aenvptr = (char *)__crtGetEnvironmentStringsA()) == NULL)
                    return -1;
            }
#endif  /* WPRFLAG */

            /*
                 * search for the first one
                 */
                for (cwd_start = 0;
                     _tenvptr[cwd_start] != _T('\0') &&
                       _tenvptr[cwd_start] != _T('=');
                     cwd_start += _tcslen(&_tenvptr[cwd_start]) + 1)
                {
                }

                /* find the total size of all contiguous ones */
                cwd_end = cwd_start;
                while (_tenvptr[cwd_end+0] == _T('=') &&
                       _tenvptr[cwd_end+1] != _T('\0') &&
                       _tenvptr[cwd_end+2] == _T(':') &&
                       _tenvptr[cwd_end+3] == _T('='))
                {
                        cwd_end += 4 + _tcslen(&_tenvptr[cwd_end+4]) + 1;
                }
                tmp += cwd_end - cwd_start;

                /*
                 * Allocate space for the environment strings plus extra null byte
                 */
                if( !(*envblk = _malloc_crt(tmp * sizeof(_TSCHAR))) )
            {
                        _free_crt(*argblk);
                        *argblk = NULL;
                        errno = ENOMEM;
                        _doserrno = E_nomem;
                        return(-1);
                }

        }

        /*
         * Build the command line by concatenating the argument strings
         * with spaces between, and two null bytes at the end.
         * NOTE: The argv[0] argument is followed by a null.
         */

        cptr = *argblk;
        vp = argv;

        if (!*vp)       /* Empty argument list ? */
                ++cptr; /* just two null bytes */
        else {          /* argv[0] must be followed by a null */
                _tcscpy(cptr, *vp);
                cptr += _tcslen(*vp++) + 1;
        }

        while( *vp ) {
                _tcscpy(cptr, *vp);
                cptr += _tcslen(*vp++);
                *cptr++ = ' ';
        }

        *cptr = cptr[ -1 ] = _T('\0'); /* remove extra blank, add double null */

        /*
         * Build the environment block by concatenating the environment
         * strings with nulls between and two null bytes at the end
         */

        cptr = *envblk;

        if (envp != NULL) {
                /*
                 * Copy the "cwd" strings to the new environment.
                 */
                memcpy(cptr, &_tenvptr[cwd_start], (cwd_end - cwd_start) * sizeof(_TSCHAR));
                cptr += cwd_end - cwd_start;

                /*
                 * Copy the environment strings from "envp".
                 */
                vp = envp;
                while( *vp ) {
                        _tcscpy(cptr, *vp);
                        cptr += 1 + _tcslen(*vp++);
                }
        }

        if (cptr != NULL) {
                if (cptr == *envblk) {
                        /*
                         * Empty environment block ... this requires two
                         * nulls.
                         */
                        *cptr++ = _T('\0');
                }
                /*
                 * Extra null terminates the segment
                 */
                *cptr = _T('\0');
        }

#ifdef WPRFLAG
        _free_crt(_wenvptr);
        _wenvptr = NULL;
#else  /* WPRFLAG */
        _free_crt(_aenvptr);
        _aenvptr = NULL;
#endif  /* WPRFLAG */
        return(0);
}