VirtualBox

Ignore:
Timestamp:
Sep 1, 2022 8:34:00 PM (2 years ago)
Author:
vboxsync
Message:

Installer/win/Stub*: Built in no-CRT mode. Documented and reworked the resource structures a bit. bugref:10261

Location:
trunk/src/VBox/Installer/win/StubBld
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Installer/win/StubBld/VBoxStubBld.cpp

    r96407 r96571  
    3939#include "VBoxStubBld.h"
    4040
    41 HRESULT GetFile (const char* pszFilePath,
    42                  HANDLE* phFile,
    43                  DWORD* pdwFileSize)
    44 {
    45     HRESULT hr = S_OK;
    46     *phFile = CreateFile(pszFilePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    47     if (INVALID_HANDLE_VALUE == *phFile)
    48         hr = HRESULT_FROM_WIN32(GetLastError());
     41
     42static HRESULT GetFile(const char *pszFilePath, HANDLE *phFile, DWORD *pcbFile)
     43{
     44    HANDLE hFile = CreateFileA(pszFilePath, GENERIC_READ, FILE_SHARE_READ, NULL,
     45                               OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
     46    if (hFile != INVALID_HANDLE_VALUE)
     47    {
     48        SetLastError(NO_ERROR);
     49        LARGE_INTEGER cbFile;
     50        if (GetFileSizeEx(hFile, &cbFile))
     51        {
     52            if (cbFile.HighPart == 0)
     53            {
     54                *pcbFile = cbFile.LowPart;
     55                *phFile  = hFile;
     56                return S_OK;
     57            }
     58            fprintf(stderr, "error: File '%s' is too large: %llu bytes\n", pszFilePath, cbFile.QuadPart);
     59        }
     60        else
     61            fprintf(stderr, "error: GetFileSizeEx failed on '%s': %lu\n", pszFilePath, GetLastError());
     62        CloseHandle(hFile);
     63    }
    4964    else
    50     {
    51         *pdwFileSize = ::GetFileSize(*phFile, NULL);
    52         if (!*pdwFileSize)
    53             hr = HRESULT_FROM_WIN32(GetLastError());
    54     }
    55     return hr;
    56 }
    57 
    58 HRESULT UpdateResource(HANDLE hFile,
    59                        DWORD dwFileSize,
    60                        HANDLE hResourceUpdate,
    61                        const char *pszResourceType,
    62                        const char *pszResourceId)
    63 {
    64     HRESULT hr = S_OK;
    65 
    66     HANDLE hMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
    67     PVOID pvFile = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, dwFileSize);
    68     if (!UpdateResourceA(hResourceUpdate, pszResourceType, pszResourceId,
    69                          MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), pvFile, dwFileSize))
    70         hr = HRESULT_FROM_WIN32(GetLastError());
    71 
    72     if (pvFile)
    73         UnmapViewOfFile(pvFile);
    74 
    75     if (hMap)
     65        fprintf(stderr, "error: CreateFileA failed on '%s': %lu\n", pszFilePath, GetLastError());
     66    *phFile = INVALID_HANDLE_VALUE;
     67    return E_FAIL;
     68}
     69
     70static HRESULT MyUpdateResource(HANDLE hFile, DWORD cbFile, HANDLE hResourceUpdate,
     71                                const char *pszResourceType, const char *pszResourceId)
     72{
     73    HRESULT hr   = E_FAIL;
     74    HANDLE  hMap = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
     75    if (hMap != NULL)
     76    {
     77        PVOID pvFile = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, cbFile);
     78        if (pvFile)
     79        {
     80            if (UpdateResourceA(hResourceUpdate, pszResourceType, pszResourceId,
     81                                MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), pvFile, cbFile))
     82                hr = S_OK;
     83            else
     84                fprintf(stderr, "error: UpdateResourceA failed: %lu\n", GetLastError());
     85
     86            UnmapViewOfFile(pvFile);
     87        }
     88        else
     89            fprintf(stderr, "error: MapViewOfFile failed: %lu\n", GetLastError());
    7690        CloseHandle(hMap);
    77 
     91    }
     92    else
     93        fprintf(stderr, "error: CreateFileMappingW failed: %lu\n", GetLastError());
    7894    return hr;
    7995}
     
    8399{
    84100    HANDLE hFile = INVALID_HANDLE_VALUE;
    85     DWORD dwFileSize = 0;
    86     HRESULT hr = GetFile(pszFilePath, &hFile, &dwFileSize);
     101    DWORD cbFile = 0;
     102    HRESULT hr = GetFile(pszFilePath, &hFile, &cbFile);
    87103    if (SUCCEEDED(hr))
    88104    {
    89         hr = UpdateResource(hFile, dwFileSize, hResourceUpdate, pszResourceType, pszResourceId);
     105        hr = MyUpdateResource(hFile, cbFile, hResourceUpdate, pszResourceType, pszResourceId);
    90106        if (FAILED(hr))
    91107            printf("ERROR: Error updating resource for file %s!", pszFilePath);
     108        CloseHandle(hFile);
    92109    }
    93110    else
    94111        hr = HRESULT_FROM_WIN32(GetLastError());
    95 
    96     if (hFile != INVALID_HANDLE_VALUE)
    97         CloseHandle(hFile);
    98112    return hr;
    99113}
     
    130144int main(int argc, char* argv[])
    131145{
    132     HRESULT hr = S_OK;
    133     int rcExit = RTEXITCODE_SUCCESS;
    134 
    135     char szSetupStub[_MAX_PATH] = {"VBoxStub.exe"};
    136     char szOutput[_MAX_PATH] = {"VirtualBox-MultiArch.exe"};
    137     HANDLE hUpdate = NULL;
    138 
    139     do /* goto avoidance "loop" */
    140     {
    141         printf(VBOX_PRODUCT " Stub Builder v%d.%d.%d.%d\n",
    142                VBOX_VERSION_MAJOR, VBOX_VERSION_MINOR, VBOX_VERSION_BUILD, VBOX_SVN_REV);
    143 
    144         if (argc < 2)
    145             printf("WARNING: No parameters given! Using default values!\n");
    146 
    147         VBOXSTUBBUILDPKG stbBuildPkg[VBOXSTUB_MAX_PACKAGES] = {{{0}}};
    148         VBOXSTUBPKG stbPkg[VBOXSTUB_MAX_PACKAGES] = {{0}};
    149         VBOXSTUBPKGHEADER stbHeader =
    150         {
    151             "vbox$tub",    /* File magic. */
    152             1,             /* Version. */
    153             0              /* No files yet. */
    154         };
    155 
    156         for (int i=1; i<argc; i++)
    157         {
    158             if (!stricmp(argv[i], "-out") && argc > i+1)
    159             {
    160                 hr = StringCchCopy(szOutput, _MAX_PATH, argv[i+1]);
    161                 i++;
    162             }
    163 
    164             else if (!stricmp(argv[i], "-stub") && argc > i+1)
    165             {
    166                 hr = StringCchCopy(szSetupStub, _MAX_PATH, argv[i+1]);
    167                 i++;
    168             }
    169 
    170             else if (!stricmp(argv[i], "-target-all") && argc > i+1)
    171             {
    172                 hr = StringCchCopy(stbBuildPkg[stbHeader.byCntPkgs].szSourcePath, _MAX_PATH, argv[i+1]);
    173                 stbBuildPkg[stbHeader.byCntPkgs].byArch = VBOXSTUBPKGARCH_ALL;
    174                 stbHeader.byCntPkgs++;
    175                 i++;
    176             }
    177 
    178             else if (!stricmp(argv[i], "-target-x86") && argc > i+1)
    179             {
    180                 hr = StringCchCopy(stbBuildPkg[stbHeader.byCntPkgs].szSourcePath, _MAX_PATH, argv[i+1]);
    181                 stbBuildPkg[stbHeader.byCntPkgs].byArch = VBOXSTUBPKGARCH_X86;
    182                 stbHeader.byCntPkgs++;
    183                 i++;
    184             }
    185 
    186             else if (!stricmp(argv[i], "-target-amd64") && argc > i+1)
    187             {
    188                 hr = StringCchCopy(stbBuildPkg[stbHeader.byCntPkgs].szSourcePath, _MAX_PATH, argv[i+1]);
    189                 stbBuildPkg[stbHeader.byCntPkgs].byArch = VBOXSTUBPKGARCH_AMD64;
    190                 stbHeader.byCntPkgs++;
    191                 i++;
    192             }
     146    /*
     147     * Parse arguments.
     148     */
     149    const char *pszSetupStub = "VBoxStub.exe";
     150    const char *pszOutput    = "VirtualBox-MultiArch.exe";
     151
     152    printf(VBOX_PRODUCT " Stub Builder v%d.%d.%d.%d\n",
     153           VBOX_VERSION_MAJOR, VBOX_VERSION_MINOR, VBOX_VERSION_BUILD, VBOX_SVN_REV);
     154
     155    struct VBOXSTUBBUILDPKG
     156    {
     157        const char     *pszSrcPath;
     158        VBOXSTUBPKGARCH enmArch;
     159    }                   aBuildPkgs[VBOXSTUB_MAX_PACKAGES] = { { NULL } };
     160    VBOXSTUBPKGHEADER   StubHdr =
     161    {
     162        /*.szMagic = */   VBOXSTUBPKGHEADER_MAGIC_SZ,
     163        /*.cPackages = */ 0
     164    };
     165
     166    for (int i = 1; i < argc; i++)
     167    {
     168        const char *pszArg = argv[i];
     169        if (   strcmp(pszArg, "--help") == 0
     170            || strcmp(pszArg, "-help") == 0
     171            || strcmp(pszArg, "-h") == 0
     172            || strcmp(pszArg, "-?") == 0)
     173        {
     174            printf("usage: %s -out <installer.exe> -stub <stub.exe> [-target-all <file>] [-target-<arch> <file>]\n", argv[0]);
     175            return RTEXITCODE_SUCCESS;
     176        }
     177
     178        /* The remaining options all take a while. */
     179        if (   strcmp(pszArg, "-out")
     180            && strcmp(pszArg, "-stub")
     181            && strcmp(pszArg, "-target-all")
     182            && strcmp(pszArg, "-target-x86")
     183            && strcmp(pszArg, "-target-amd64"))
     184        {
     185            fprintf(stderr, "syntax error: Invalid parameter: %s\n", argv[i]);
     186            return RTEXITCODE_SYNTAX;
     187        }
     188
     189        i++;
     190        if (i >= argc)
     191        {
     192            fprintf(stderr, "syntax error: Option '%s' takes a value argument!\n", pszArg);
     193            return RTEXITCODE_SYNTAX;
     194        }
     195        const char *pszValue = argv[i];
     196
     197        /* Process the individual options. */
     198        if (strcmp(pszArg, "-out") == 0)
     199            pszOutput = pszValue;
     200        else if (strcmp(pszArg, "-stub") == 0)
     201            pszSetupStub = pszValue;
     202        else
     203        {
     204            if (StubHdr.cPackages >= RT_ELEMENTS(aBuildPkgs))
     205            {
     206                fprintf(stderr, "error: Too many packages specified!\n");
     207                return RTEXITCODE_FAILURE;
     208            }
     209            aBuildPkgs[StubHdr.cPackages].pszSrcPath = pszValue;
     210            if (strcmp(pszArg, "-target-all") == 0)
     211                aBuildPkgs[StubHdr.cPackages].enmArch = VBOXSTUBPKGARCH_ALL;
     212            else if (strcmp(pszArg, "-target-amd64") == 0)
     213                aBuildPkgs[StubHdr.cPackages].enmArch = VBOXSTUBPKGARCH_AMD64;
     214            else if (strcmp(pszArg, "-target-x86") == 0)
     215                aBuildPkgs[StubHdr.cPackages].enmArch = VBOXSTUBPKGARCH_X86;
    193216            else
    194217            {
    195                 printf("ERROR: Invalid parameter: %s\n", argv[i]);
    196                 hr = E_INVALIDARG;
    197                 break;
    198             }
    199             if (FAILED(hr))
    200             {
    201                 printf("ERROR: StringCchCopy failed: %#lx\n", hr);
    202                 break;
    203             }
    204         }
    205         if (FAILED(hr))
    206             break;
    207 
    208         if (stbHeader.byCntPkgs <= 0)
    209         {
    210             printf("ERROR: No packages defined! Exiting.\n");
    211             break;
    212         }
    213 
    214         printf("Stub: %s\n", szSetupStub);
    215         printf("Output: %s\n", szOutput);
    216         printf("# Packages: %u\n", stbHeader.byCntPkgs);
    217 
    218         if (!CopyFile(szSetupStub, szOutput, FALSE))
    219         {
    220             hr = HRESULT_FROM_WIN32(GetLastError());
    221             printf("ERROR: Could not create stub loader: %#lx\n", hr);
    222             break;
    223         }
    224 
    225         hUpdate = BeginUpdateResource(szOutput, FALSE);
    226 
    227         PVBOXSTUBPKG pPackage = stbPkg;
    228         char szHeaderName[_MAX_PATH] = {0};
    229 
    230         for (BYTE i = 0; i < stbHeader.byCntPkgs; i++)
    231         {
    232             printf("Integrating (Platform %d): %s\n", stbBuildPkg[i].byArch, stbBuildPkg[i].szSourcePath);
    233 
    234             /* Construct resource name. */
    235             hr = StringCchPrintf(pPackage->szResourceName, _MAX_PATH, "BIN_%02d", i);
    236             pPackage->byArch = stbBuildPkg[i].byArch;
     218                fprintf(stderr, "internal error: %u\n", __LINE__);
     219                return RTEXITCODE_FAILURE;
     220            }
     221            StubHdr.cPackages++;
     222        }
     223    }
     224
     225    if (StubHdr.cPackages == 0)
     226    {
     227        fprintf(stderr, "syntax error: No packages specified! Exiting.\n");
     228        return RTEXITCODE_SYNTAX;
     229    }
     230
     231    printf("Stub:       %s\n", pszSetupStub);
     232    printf("Output:     %s\n", pszOutput);
     233    printf("# Packages: %u\n", StubHdr.cPackages);
     234
     235    /*
     236     * Copy the stub over the output file.
     237     */
     238    if (!CopyFile(pszSetupStub, pszOutput, FALSE))
     239    {
     240        fprintf(stderr, "ERROR: Could not copy the stub loader: %lu\n", GetLastError());
     241        return RTEXITCODE_SYNTAX;
     242    }
     243
     244    /*
     245     * Start updating the resources of the output file.
     246     */
     247    HANDLE hUpdate = BeginUpdateResourceA(pszOutput, FALSE);
     248    if (hUpdate)
     249    {
     250        /*
     251         * Add the file one by one to the output file.
     252         */
     253        HRESULT hrc = S_OK;
     254        for (BYTE i = 0; i < StubHdr.cPackages; i++)
     255        {
     256            printf("Integrating (Platform %d): %s\n", aBuildPkgs[i].enmArch, aBuildPkgs[i].pszSrcPath);
     257
     258            /*
     259             * Create the package header.
     260             */
     261            VBOXSTUBPKG Package = {0};
     262            Package.enmArch = aBuildPkgs[i].enmArch;
     263
     264            /* The resource name */
     265            hrc = StringCchPrintf(Package.szResourceName, sizeof(Package.szResourceName), "BIN_%02d", i);
     266            if (FAILED(hrc))
     267            {
     268                fprintf(stderr, "Internal error: %u\n", __LINE__);
     269                break;
     270            }
    237271
    238272            /* Construct final name used when extracting. */
    239             hr = StringCchCopy(pPackage->szFileName, _MAX_PATH, MyPathFilename(stbBuildPkg[i].szSourcePath));
    240 
    241             /* Integrate header into binary. */
    242             hr = StringCchPrintf(szHeaderName, _MAX_PATH, "HDR_%02d", i);
    243             hr = UpdateResource(hUpdate, RT_RCDATA, szHeaderName, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), pPackage, sizeof(VBOXSTUBPKG));
    244 
    245             /* Integrate file into binary. */
    246             hr = IntegrateFile(hUpdate, RT_RCDATA, pPackage->szResourceName, stbBuildPkg[i].szSourcePath);
    247             if (FAILED(hr))
    248             {
    249                 printf("ERROR: Could not integrate binary %s (%s): %#lx\n",
    250                          pPackage->szResourceName, pPackage->szFileName, hr);
    251                 rcExit = RTEXITCODE_FAILURE;
    252             }
    253 
    254             pPackage++;
    255         }
    256 
    257         if (FAILED(hr))
    258             break;
    259 
    260         if (!UpdateResource(hUpdate, RT_RCDATA, "MANIFEST", MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), &stbHeader, sizeof(VBOXSTUBPKGHEADER)))
    261         {
    262             hr = HRESULT_FROM_WIN32(GetLastError());
    263             break;
    264         }
    265 
    266         if (!EndUpdateResource(hUpdate, FALSE))
    267         {
    268             hr = HRESULT_FROM_WIN32(GetLastError());
    269             break;
    270         }
    271 
    272         printf("Integration done!\n");
    273 
    274     } while (0);
    275 
    276     hUpdate = NULL;
    277 
    278     if (FAILED(hr))
    279     {
    280         printf("ERROR: Building failed! Last error: %lu\n", GetLastError());
    281         rcExit = RTEXITCODE_FAILURE;
    282     }
    283     return rcExit;
    284 }
     273            hrc = StringCchCopy(Package.szFilename, sizeof(Package.szFilename), MyPathFilename(aBuildPkgs[i].pszSrcPath));
     274            if (FAILED(hrc))
     275            {
     276                fprintf(stderr, "ERROR: Filename is too long: %s\n", aBuildPkgs[i].pszSrcPath);
     277                break;
     278            }
     279
     280            /*
     281             * Add the package header to the binary.
     282             */
     283            char szHeaderName[32];
     284            hrc = StringCchPrintf(szHeaderName, sizeof(szHeaderName), "HDR_%02d", i);
     285            if (FAILED(hrc))
     286            {
     287                fprintf(stderr, "Internal error: %u\n", __LINE__);
     288                break;
     289            }
     290
     291            if (!UpdateResourceA(hUpdate, RT_RCDATA, szHeaderName, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
     292                                 &Package, sizeof(Package)))
     293            {
     294                fprintf(stderr, "ERROR: UpdateResourceA failed for the package header: %lu\n", GetLastError());
     295                hrc = E_FAIL;
     296                break;
     297            }
     298
     299            /*
     300             * Add the file content under the BIN_xx resource name.
     301             */
     302            hrc = IntegrateFile(hUpdate, RT_RCDATA, Package.szResourceName, aBuildPkgs[i].pszSrcPath);
     303            if (FAILED(hrc))
     304                break;
     305        }
     306        if (SUCCEEDED(hrc))
     307        {
     308            /*
     309             * Now add the header/manifest and complete the operation.
     310             */
     311            if (UpdateResourceA(hUpdate, RT_RCDATA, "MANIFEST", MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
     312                                &StubHdr, sizeof(StubHdr)))
     313            {
     314                if (EndUpdateResourceA(hUpdate, FALSE /*fDiscard*/))
     315                {
     316                    printf("Successfully created the installer\n");
     317                    return RTEXITCODE_SUCCESS;
     318                }
     319                fprintf(stderr, "ERROR: EndUpdateResourceA failed: %lu\n", GetLastError());
     320            }
     321            else
     322                fprintf(stderr, "ERROR: UpdateResourceA failed for the installer header/manifest: %lu\n", GetLastError());
     323        }
     324
     325        EndUpdateResourceA(hUpdate, TRUE /*fDiscard*/);
     326        hUpdate = NULL;
     327    }
     328    else
     329        fprintf(stderr, "error: BeginUpdateResource failed: %lu\n", GetLastError());
     330    return RTEXITCODE_FAILURE;
     331}
  • trunk/src/VBox/Installer/win/StubBld/VBoxStubBld.h

    r96407 r96571  
    3232#endif
    3333
     34#include <iprt/types.h>
     35#include <iprt/assertcompile.h>
     36
     37/**/
    3438#define VBOXSTUB_MAX_PACKAGES 128
    3539
     40/** */
     41#define VBOXSTUBPKGHEADER_MAGIC_SZ  "VBoxInstV1\0\0\0\0"
     42
     43/**
     44 * VBox installer stub header, aka "MANIFEST".
     45 *
     46 * This just holds the number of packages present in the image.
     47 */
    3648typedef struct VBOXSTUBPKGHEADER
    3749{
    38     /** Some magic string not defined by this header? Turns out it's a write only
    39      *  field... */
    40     char    szMagic[9];
    41     /* Inbetween szMagic and dwVersion there are 3 bytes of implicit padding. */
    42     /** Some version number not defined by this header? Also write only field.
    43      *  Should be a uint32_t, not DWORD. */
    44     DWORD   dwVersion;
    45     /** Number of packages following the header. byte is prefixed 'b', not 'by'!
    46      *  Use uint8_t instead of BYTE. */
    47     BYTE    byCntPkgs;
    48     /* There are 3 bytes of implicit padding here. */
     50    /** Magic value/string (VBOXSTUBPKGHEADER_MAGIC_SZ) */
     51    char    szMagic[11 + 4];
     52    /** Number of packages following the header. */
     53    uint8_t cPackages;
    4954} VBOXSTUBPKGHEADER;
     55AssertCompileSize(VBOXSTUBPKGHEADER, 16);
    5056typedef VBOXSTUBPKGHEADER *PVBOXSTUBPKGHEADER;
    5157
    5258typedef enum VBOXSTUBPKGARCH
    5359{
    54     VBOXSTUBPKGARCH_ALL = 0,
     60    /** Always extract.   */
     61    VBOXSTUBPKGARCH_ALL = 1,
     62    /** Extract on x86 hosts. */
    5563    VBOXSTUBPKGARCH_X86,
     64    /** Extract on AMD64 hosts. */
    5665    VBOXSTUBPKGARCH_AMD64
    5766} VBOXSTUBPKGARCH;
    5867
     68/**
     69 * Package header/descriptor.
     70 *
     71 * This is found as "HDR_xx" where xx is replaced by the decimal package number,
     72 * zero padded to two digits.
     73 */
    5974typedef struct VBOXSTUBPKG
    6075{
    61     BYTE byArch;
    62     /** Probably the name of the PE resource or something, read the source to
    63      *  find out for sure.  Don't use _MAX_PATH, define your own max lengths! */
    64     char szResourceName[_MAX_PATH];
    65     char szFileName[_MAX_PATH];
     76    /** The architecture for the file. */
     77    VBOXSTUBPKGARCH enmArch;
     78    /** The name of the resource holding the file bytes.
     79     * This is a pointless field, because the resource name is "BIN_xx"
     80     * corresponding to the name of the resource containing this struct. */
     81    char szResourceName[28];
     82    /** The filename.   */
     83    char szFilename[224];
    6684} VBOXSTUBPKG;
     85AssertCompileSize(VBOXSTUBPKG, 256);
    6786typedef VBOXSTUBPKG *PVBOXSTUBPKG;
    6887
    69 /* Only for construction. */
    70 /* Since it's only used by VBoxStubBld.cpp, why not just keep it there? */
    71 
    72 typedef struct VBOXSTUBBUILDPKG
    73 {
    74     char szSourcePath[_MAX_PATH];
    75     BYTE byArch;
    76 } VBOXSTUBBUILDPKG;
    77 typedef VBOXSTUBBUILDPKG *PVBOXSTUBBUILDPKG;
    78 
    7988#endif /* !VBOX_INCLUDED_SRC_StubBld_VBoxStubBld_h */
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