VirtualBox

Changeset 95870 in vbox for trunk/src/VBox/Runtime/r3/win


Ignore:
Timestamp:
Jul 27, 2022 2:38:01 AM (3 years ago)
Author:
vboxsync
Message:

IPRT/nocrt: Split up the startup code and added the basic DLL startup code. bugref:10261

Location:
trunk/src/VBox/Runtime/r3/win
Files:
1 added
1 edited
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/r3/win/nocrt-startup-common-win.cpp

    r95834 r95870  
    11/* $Id$ */
    22/** @file
    3  * IPRT - No-CRT - Windows EXE startup code.
    4  *
    5  * @note Does not run static constructors and destructors!
     3 * IPRT - No-CRT - Common Windows startup code.
    64 */
    75
     
    4139#include <iprt/utf16.h>
    4240
    43 #ifdef IPRT_NO_CRT
    44 # include <iprt/asm.h>
    45 # include <iprt/nocrt/stdlib.h>
    46 #endif
    47 
    4841#include "internal/compiler-vcc.h"
    49 
    50 
    51 /*********************************************************************************************************************************
    52 *   Structures and Typedefs                                                                                                      *
    53 *********************************************************************************************************************************/
    54 #ifdef IPRT_NO_CRT
    55 typedef struct RTNOCRTATEXITCHUNK
    56 {
    57     PFNRTNOCRTATEXITCALLBACK apfnCallbacks[256];
    58 } RTNOCRTATEXITCHUNK;
    59 #endif
    6042
    6143
     
    7052RT_C_DECLS_END
    7153
    72 #ifdef IPRT_NO_CRT
    73 /** The first atexit() registration chunk. */
    74 static RTNOCRTATEXITCHUNK   g_aAtExitPrealloc;
    75 /** Array of atexit() callback chunk pointers. */
    76 static RTNOCRTATEXITCHUNK  *g_apAtExit[8192 / 256] = { &g_aAtExitPrealloc, };
    77 /** Chunk and callback index in one. */
    78 static volatile uint32_t    g_idxNextAtExit        = 0;
    79 #endif
    8054
    8155
    82 /*********************************************************************************************************************************
    83 *   External Symbols                                                                                                             *
    84 *********************************************************************************************************************************/
    85 extern DECLHIDDEN(void) InitStdHandles(PRTL_USER_PROCESS_PARAMETERS pParams); /* nocrt-streams-win.cpp */ /** @todo put in header */
    86 
    87 extern int main(int argc, char **argv, char **envp);    /* in program */
    88 
    89 
    90 #ifdef IPRT_NO_CRT
    91 extern "C"
    92 int rtnocrt_atexit(PFNRTNOCRTATEXITCALLBACK pfnCallback) RT_NOEXCEPT
    93 {
    94     AssertPtr(pfnCallback);
    95 
    96     /*
    97      * Allocate a table index.
    98      */
    99     uint32_t idx = ASMAtomicIncU32(&g_idxNextAtExit) - 1;
    100     AssertReturnStmt(idx < RT_ELEMENTS(g_apAtExit) * RT_ELEMENTS(g_apAtExit[0]->apfnCallbacks),
    101                      ASMAtomicDecU32(&g_idxNextAtExit), -1);
    102 
    103     /*
    104      * Make sure the table chunk is there.
    105      */
    106     uint32_t            idxChunk = idx / RT_ELEMENTS(g_apAtExit[0]->apfnCallbacks);
    107     RTNOCRTATEXITCHUNK *pChunk   = ASMAtomicReadPtrT(&g_apAtExit[idxChunk], RTNOCRTATEXITCHUNK *);
    108     if (!pChunk)
    109     {
    110         pChunk = (RTNOCRTATEXITCHUNK *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pChunk));
    111         AssertReturn(pChunk, -1); /* don't try decrement, someone could be racing us... */
    112 
    113         if (!ASMAtomicCmpXchgPtr(&g_apAtExit[idxChunk], pChunk, NULL))
    114         {
    115             HeapFree(GetProcessHeap(), 0, pChunk);
    116 
    117             pChunk = ASMAtomicReadPtrT(&g_apAtExit[idxChunk], RTNOCRTATEXITCHUNK *);
    118             Assert(pChunk);
    119         }
    120     }
    121 
    122     /*
    123      * Add our callback.
    124      */
    125     pChunk->apfnCallbacks[idxChunk % RT_ELEMENTS(pChunk->apfnCallbacks)] = pfnCallback;
    126     return 0;
    127 }
    128 #endif
    129 
    130 
    131 static int rtTerminateProcess(int32_t rcExit, bool fDoAtExit)
    132 {
    133 #ifdef IPRT_NO_CRT
    134     /*
    135      * Run atexit callback in reverse order.
    136      */
    137     if (fDoAtExit)
    138     {
    139         uint32_t idxAtExit = ASMAtomicReadU32(&g_idxNextAtExit);
    140         if (idxAtExit-- > 0)
    141         {
    142             uint32_t idxChunk    = idxAtExit / RT_ELEMENTS(g_apAtExit[0]->apfnCallbacks);
    143             uint32_t idxCallback = idxAtExit % RT_ELEMENTS(g_apAtExit[0]->apfnCallbacks);
    144             for (;;)
    145             {
    146                 RTNOCRTATEXITCHUNK *pChunk = ASMAtomicReadPtrT(&g_apAtExit[idxChunk], RTNOCRTATEXITCHUNK *);
    147                 if (pChunk)
    148                 {
    149                     do
    150                     {
    151                         PFNRTNOCRTATEXITCALLBACK pfnCallback = pChunk->apfnCallbacks[idxCallback];
    152                         if (pfnCallback) /* Can be NULL see registration code */
    153                             pfnCallback();
    154                     } while (idxCallback-- > 0);
    155                 }
    156                 if (idxChunk == 0)
    157                     break;
    158                 idxChunk--;
    159                 idxCallback = RT_ELEMENTS(g_apAtExit[0]->apfnCallbacks) - 1;
    160             }
    161         }
    162 
    163         rtVccInitializersRunTerm();
    164     }
    165 #else
    166     RT_NOREF(fDoAtExit);
    167 #endif
    168 
    169     /*
    170      * Terminate.
    171      */
    172     for (;;)
    173         NtTerminateProcess(NtCurrentProcess(), rcExit);
    174 }
    175 
    176 
    177 DECL_NO_INLINE(static, void) initProcExecPath(void)
     56void rtVccWinInitProcExecPath(void)
    17857{
    17958    WCHAR wszPath[RTPATH_MAX];
     
    19877}
    19978
    200 
    201 DECLASM(void) CustomMainEntrypoint(PPEB pPeb)
    202 {
    203     /*
    204      * Initialize stuff.
    205      */
    206     InitStdHandles(pPeb->ProcessParameters);
    207     initProcExecPath();
    208 
    209     RTEXITCODE rcExit;
    210 #ifdef IPRT_NO_CRT
    211     AssertCompile(sizeof(rcExit) == sizeof(int));
    212     rcExit = (RTEXITCODE)rtVccInitializersRunInit();
    213     if (rcExit == RTEXITCODE_SUCCESS)
    214 #endif
    215     {
    216         /*
    217          * Get and convert the command line to argc/argv format.
    218          */
    219         UNICODE_STRING const *pCmdLine = pPeb->ProcessParameters ? &pPeb->ProcessParameters->CommandLine : NULL;
    220         if (pCmdLine)
    221         {
    222             char *pszCmdLine = NULL;
    223             int rc = RTUtf16ToUtf8Ex(pCmdLine->Buffer, pCmdLine->Length / sizeof(WCHAR), &pszCmdLine, 0, NULL);
    224             if (RT_SUCCESS(rc))
    225             {
    226                 char **papszArgv;
    227                 int    cArgs = 0;
    228                 rc = RTGetOptArgvFromString(&papszArgv, &cArgs, pszCmdLine,
    229                                             RTGETOPTARGV_CNV_MODIFY_INPUT | RTGETOPTARGV_CNV_QUOTE_MS_CRT,  NULL);
    230                 if (RT_SUCCESS(rc))
    231                 {
    232                     /*
    233                      * Call the main function.
    234                      */
    235                     AssertCompile(sizeof(rcExit) == sizeof(int));
    236                     rcExit = (RTEXITCODE)main(cArgs, papszArgv, NULL /*envp*/);
    237                 }
    238                 else
    239                     rcExit = RTMsgErrorExitFailure("Error parsing command line: %Rrc\n", rc);
    240             }
    241             else
    242                 rcExit = RTMsgErrorExitFailure("Failed to convert command line to UTF-8: %Rrc\n", rc);
    243         }
    244         else
    245             rcExit = RTMsgErrorExitFailure("No command line\n");
    246         rtTerminateProcess(rcExit, true /*fDoAtExit*/);
    247     }
    248 #ifdef IPRT_NO_CRT
    249     else
    250     {
    251         RTMsgError("A C static initializor failed (%d)\n", rcExit);
    252         rtTerminateProcess(rcExit, false /*fDoAtExit*/);
    253     }
    254 #endif
    255 }
    256 
  • trunk/src/VBox/Runtime/r3/win/nocrt-startup-exe-win.cpp

    r95834 r95870  
    4141#include <iprt/utf16.h>
    4242
    43 #ifdef IPRT_NO_CRT
    44 # include <iprt/asm.h>
    45 # include <iprt/nocrt/stdlib.h>
    46 #endif
    47 
    4843#include "internal/compiler-vcc.h"
    49 
    50 
    51 /*********************************************************************************************************************************
    52 *   Structures and Typedefs                                                                                                      *
    53 *********************************************************************************************************************************/
    54 #ifdef IPRT_NO_CRT
    55 typedef struct RTNOCRTATEXITCHUNK
    56 {
    57     PFNRTNOCRTATEXITCALLBACK apfnCallbacks[256];
    58 } RTNOCRTATEXITCHUNK;
    59 #endif
    60 
    61 
    62 /*********************************************************************************************************************************
    63 *   Global Variables                                                                                                             *
    64 *********************************************************************************************************************************/
    65 RT_C_DECLS_BEGIN
    66 DECL_HIDDEN_DATA(char)      g_szrtProcExePath[RTPATH_MAX] = "Unknown.exe";
    67 DECL_HIDDEN_DATA(size_t)    g_cchrtProcExePath = 11;
    68 DECL_HIDDEN_DATA(size_t)    g_cchrtProcExeDir = 0;
    69 DECL_HIDDEN_DATA(size_t)    g_offrtProcName = 0;
    70 RT_C_DECLS_END
    71 
    72 #ifdef IPRT_NO_CRT
    73 /** The first atexit() registration chunk. */
    74 static RTNOCRTATEXITCHUNK   g_aAtExitPrealloc;
    75 /** Array of atexit() callback chunk pointers. */
    76 static RTNOCRTATEXITCHUNK  *g_apAtExit[8192 / 256] = { &g_aAtExitPrealloc, };
    77 /** Chunk and callback index in one. */
    78 static volatile uint32_t    g_idxNextAtExit        = 0;
    79 #endif
    8044
    8145
     
    8852
    8953
    90 #ifdef IPRT_NO_CRT
    91 extern "C"
    92 int rtnocrt_atexit(PFNRTNOCRTATEXITCALLBACK pfnCallback) RT_NOEXCEPT
    93 {
    94     AssertPtr(pfnCallback);
    95 
    96     /*
    97      * Allocate a table index.
    98      */
    99     uint32_t idx = ASMAtomicIncU32(&g_idxNextAtExit) - 1;
    100     AssertReturnStmt(idx < RT_ELEMENTS(g_apAtExit) * RT_ELEMENTS(g_apAtExit[0]->apfnCallbacks),
    101                      ASMAtomicDecU32(&g_idxNextAtExit), -1);
    102 
    103     /*
    104      * Make sure the table chunk is there.
    105      */
    106     uint32_t            idxChunk = idx / RT_ELEMENTS(g_apAtExit[0]->apfnCallbacks);
    107     RTNOCRTATEXITCHUNK *pChunk   = ASMAtomicReadPtrT(&g_apAtExit[idxChunk], RTNOCRTATEXITCHUNK *);
    108     if (!pChunk)
    109     {
    110         pChunk = (RTNOCRTATEXITCHUNK *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pChunk));
    111         AssertReturn(pChunk, -1); /* don't try decrement, someone could be racing us... */
    112 
    113         if (!ASMAtomicCmpXchgPtr(&g_apAtExit[idxChunk], pChunk, NULL))
    114         {
    115             HeapFree(GetProcessHeap(), 0, pChunk);
    116 
    117             pChunk = ASMAtomicReadPtrT(&g_apAtExit[idxChunk], RTNOCRTATEXITCHUNK *);
    118             Assert(pChunk);
    119         }
    120     }
    121 
    122     /*
    123      * Add our callback.
    124      */
    125     pChunk->apfnCallbacks[idxChunk % RT_ELEMENTS(pChunk->apfnCallbacks)] = pfnCallback;
    126     return 0;
    127 }
    128 #endif
    129 
    130 
    13154static int rtTerminateProcess(int32_t rcExit, bool fDoAtExit)
    13255{
     
    13760    if (fDoAtExit)
    13861    {
    139         uint32_t idxAtExit = ASMAtomicReadU32(&g_idxNextAtExit);
    140         if (idxAtExit-- > 0)
    141         {
    142             uint32_t idxChunk    = idxAtExit / RT_ELEMENTS(g_apAtExit[0]->apfnCallbacks);
    143             uint32_t idxCallback = idxAtExit % RT_ELEMENTS(g_apAtExit[0]->apfnCallbacks);
    144             for (;;)
    145             {
    146                 RTNOCRTATEXITCHUNK *pChunk = ASMAtomicReadPtrT(&g_apAtExit[idxChunk], RTNOCRTATEXITCHUNK *);
    147                 if (pChunk)
    148                 {
    149                     do
    150                     {
    151                         PFNRTNOCRTATEXITCALLBACK pfnCallback = pChunk->apfnCallbacks[idxCallback];
    152                         if (pfnCallback) /* Can be NULL see registration code */
    153                             pfnCallback();
    154                     } while (idxCallback-- > 0);
    155                 }
    156                 if (idxChunk == 0)
    157                     break;
    158                 idxChunk--;
    159                 idxCallback = RT_ELEMENTS(g_apAtExit[0]->apfnCallbacks) - 1;
    160             }
    161         }
    162 
     62        rtVccTermRunAtExit();
    16363        rtVccInitializersRunTerm();
    16464    }
     
    17575
    17676
    177 DECL_NO_INLINE(static, void) initProcExecPath(void)
    178 {
    179     WCHAR wszPath[RTPATH_MAX];
    180     UINT cwcPath = GetModuleFileNameW(NULL, wszPath, RT_ELEMENTS(wszPath));
    181     if (cwcPath)
    182     {
    183         char *pszDst = g_szrtProcExePath;
    184         int rc = RTUtf16ToUtf8Ex(wszPath, cwcPath, &pszDst, sizeof(g_szrtProcExePath), &g_cchrtProcExePath);
    185         if (RT_SUCCESS(rc))
    186         {
    187             g_cchrtProcExeDir = g_offrtProcName = RTPathFilename(pszDst) - g_szrtProcExePath;
    188             while (   g_cchrtProcExeDir >= 2
    189                    && RTPATH_IS_SLASH(g_szrtProcExePath[g_cchrtProcExeDir - 1])
    190                    && g_szrtProcExePath[g_cchrtProcExeDir - 2] != ':')
    191                 g_cchrtProcExeDir--;
    192         }
    193         else
    194             RTMsgError("initProcExecPath: RTUtf16ToUtf8Ex failed: %Rrc\n", rc);
    195     }
    196     else
    197         RTMsgError("initProcExecPath: GetModuleFileNameW failed: %Rhrc\n", GetLastError());
    198 }
    199 
    200 
    20177DECLASM(void) CustomMainEntrypoint(PPEB pPeb)
    20278{
     
    20480     * Initialize stuff.
    20581     */
     82    rtVccInitSecurityCookie();
    20683    InitStdHandles(pPeb->ProcessParameters);
    207     initProcExecPath();
     84    rtVccWinInitProcExecPath();
    20885
    20986    RTEXITCODE rcExit;
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette