VirtualBox

Changeset 93085 in vbox for trunk/src


Ignore:
Timestamp:
Dec 27, 2021 4:55:00 AM (3 years ago)
Author:
vboxsync
Message:

Main/Unattended: Some more work on the OS/2 unattended installation.

Location:
trunk/src/VBox/Main
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/include/UnattendedInstaller.h

    r92768 r93085  
    219219
    220220    /**
    221      * Creates and formats (FAT12) a floppy image, then opens a VFS for it.
     221     * Creates and formats (FAT12) a floppy image.
     222     *
     223     * This can be overridden to do more preparation work or/and create a different
     224     * sized floppy.
    222225     *
    223226     * @returns COM status code.
    224227     * @param   pszFilename     The path to the image file.
    225228     * @param   fOverwrite      Whether to overwrite the file.
    226      * @param   phVfs           Where to return a writable VFS handle to the newly
     229     * @param   phVfsFile       Where to return a read-writable handle to the newly
    227230     *                          created image.
    228231     */
    229     HRESULT newAuxFloppyImage(const char *pszFilename, bool fOverwrite, PRTVFS phVfs);
     232    virtual HRESULT newAuxFloppyImage(const char *pszFilename, bool fOverwrite, PRTVFSFILE phVfsFile);
    230233
    231234    /**
     
    250253     */
    251254    HRESULT addScriptToFloppyImage(BaseTextScript *pEditor, RTVFS hVfs);
     255
     256    /**
     257     * Copy an arbritrary file onto the floopy image.
     258     *
     259     * @returns COM status code.
     260     * @param   hVfs            The VFS to add it to.
     261     * @param   pszSrc          The source filename.
     262     * @param   pszDst          The destination filename (on @a hVfs).
     263     */
     264    HRESULT addFileToFloppyImage(RTVFS hVfs, const char *pszSrc, const char *pszDst);
    252265
    253266    /**
     
    421434    bool bootFromAuxiliaryIso() const       { return false; }
    422435};
     436
     437
     438/**
     439 * OS/2 installer.
     440 */
     441class UnattendedOs2Installer : public UnattendedInstaller
     442{
     443public:
     444    DECLARE_TRANSLATE_METHODS(UnattendedOs2Installer)
     445
     446    UnattendedOs2Installer(Unattended *pParent, Utf8Str const &rStrHints);
     447    ~UnattendedOs2Installer()                           {}
     448
     449    /* Remaster original ISO with auxiliary floppy used for el torito floppy emulation: */
     450    bool isOriginalIsoNeeded()     const RT_OVERRIDE    { return false; }
     451    bool isAuxiliaryFloppyNeeded() const RT_OVERRIDE    { return true; }
     452    bool isAuxiliaryIsoNeeded()    const RT_OVERRIDE    { return true; }
     453
     454protected:
     455    HRESULT replaceAuxFloppyImageBootSector(RTVFSFILE hVfsFile) RT_NOEXCEPT;
     456    HRESULT newAuxFloppyImage(const char *pszFilename, bool fOverwrite, PRTVFSFILE phVfsFile) RT_OVERRIDE;
     457    HRESULT copyFilesToAuxFloppyImage(RTVFS hVfs) RT_OVERRIDE;
     458    HRESULT addFilesToAuxVisoVectors(RTCList<RTCString> &rVecArgs, RTCList<RTCString> &rVecFiles,
     459                                     RTVFS hVfsOrgIso, bool fOverwrite) RT_OVERRIDE;
     460
     461    HRESULT splitResponseFile() RT_NOEXCEPT;
     462
     463    /**
     464     * Splits up the given file into sub-files and writes them out with the auxilary
     465     * path base as prefix.
     466     *
     467     * The source file contains @@VBOX_SPLITTER_START[filename]@@ and
     468     * @@VBOX_SPLITTER_END[filename]@@  markup that is used to split it up.  Any
     469     * text between END and START tags are ignored and can be used for comments.
     470     *
     471     * @returns COM status code (error info set).
     472     * @param   pszFileToSplit      The name of the file to split.
     473     * @param   rVecSplitFiles      Vector where names of the sub-files are appended
     474     *                              (without any path or prefix).
     475     */
     476    HRESULT splitFile(const char *pszFileToSplit, RTCList<RTCString> &rVecSplitFiles) RT_NOEXCEPT;
     477
     478    /**
     479     * Splits up the given editor output into sub-files and writes them out with the
     480     * auxilary path base as prefix.
     481     *
     482     * The source file contains @@VBOX_SPLITTER_START[filename]@@ and
     483     * @@VBOX_SPLITTER_END[filename]@@  markup that is used to split it up.  Any
     484     * text between END and START tags are ignored and can be used for comments.
     485     *
     486     * @returns COM status code (error info set).
     487     * @param   pEditor             The editor which output should be split.
     488     * @param   rVecSplitFiles      Vector where names of the sub-files are appended
     489     *                              (without any path or prefix).
     490     */
     491    HRESULT splitFile(BaseTextScript *pEditor, RTCList<RTCString> &rVecSplitFiles) RT_NOEXCEPT;
     492
     493    HRESULT splitFileInner(const char *pszFileToSplit, RTCList<RTCString> &rVecSplitFiles,
     494                           const char *pszSrc, size_t cbLeft) RT_NOEXCEPT;
     495
     496    /** The OS2SE20.SRC path (\OS2IMAGES). */
     497    Utf8Str mStrOs2Images;
     498    /** Files split out from os2_response_files.rsp (bare filenames, no paths). */
     499    RTCList<RTCString> mVecSplitFiles;
     500};
     501
    423502
    424503
  • trunk/src/VBox/Main/src-server/UnattendedInstaller.cpp

    r93082 r93085  
    4444#endif
    4545#include <iprt/formats/iso9660.h>
     46#include <iprt/formats/fat.h>
    4647#include <iprt/cpp/path.h>
    4748
     
    6768    }
    6869    else if (enmOsType >= VBOXOSTYPE_OS2 && enmOsType < VBOXOSTYPE_Linux)
    69     {
    70         /** @todo OS/2 */
    71     }
     70        pUinstaller = new UnattendedOs2Installer(pParent, strDetectedOSHints);
    7271    else
    7372    {
     
    317316
    318317    /*
    319      * Create the image and get a VFS to it.
    320      */
    321     RTVFS   hVfs;
    322     HRESULT hrc = newAuxFloppyImage(getAuxiliaryFloppyFilePath().c_str(), fOverwrite, &hVfs);
     318     * Create the image.
     319     */
     320    RTVFSFILE hVfsFile;
     321    HRESULT hrc = newAuxFloppyImage(getAuxiliaryFloppyFilePath().c_str(), fOverwrite, &hVfsFile);
    323322    if (SUCCEEDED(hrc))
    324323    {
    325324        /*
    326          * Call overridable method to copies the files onto it.
     325         * Open the FAT file system so we can copy files onto the floppy.
    327326         */
    328         hrc = copyFilesToAuxFloppyImage(hVfs);
    329 
    330         /*
    331          * Relase the VFS.  On failure, delete the floppy image so the operation can
    332          * be repeated in non-overwrite mode and we don't leave any mess behind.
    333          */
    334         RTVfsRelease(hVfs);
    335 
     327        RTERRINFOSTATIC ErrInfo;
     328        RTVFS           hVfs;
     329        int vrc = RTFsFatVolOpen(hVfsFile, false /*fReadOnly*/,  0 /*offBootSector*/, &hVfs, RTErrInfoInitStatic(&ErrInfo));
     330        RTVfsFileRelease(hVfsFile);
     331        if (RT_SUCCESS(vrc))
     332        {
     333            /*
     334             * Call overridable method to copies the files onto it.
     335             */
     336            hrc = copyFilesToAuxFloppyImage(hVfs);
     337
     338            /*
     339             * Release the VFS.  On failure, delete the floppy image so the operation can
     340             * be repeated in non-overwrite mode and so that we don't leave any mess behind.
     341             */
     342            RTVfsRelease(hVfs);
     343        }
     344        else if (RTErrInfoIsSet(&ErrInfo.Core))
     345            hrc = mpParent->setErrorBoth(E_FAIL, vrc,
     346                                         tr("Failed to open FAT file system on newly created floppy image '%s': %Rrc: %s"),
     347                                         getAuxiliaryFloppyFilePath().c_str(), vrc, ErrInfo.Core.pszMsg);
     348        else
     349            hrc = mpParent->setErrorBoth(E_FAIL, vrc,
     350                                         tr("Failed to open FAT file system onnewly created floppy image '%s': %Rrc"),
     351                                         getAuxiliaryFloppyFilePath().c_str(), vrc);
    336352        if (FAILED(hrc))
    337353            RTFileDelete(getAuxiliaryFloppyFilePath().c_str());
     
    340356}
    341357
    342 HRESULT UnattendedInstaller::newAuxFloppyImage(const char *pszFilename, bool fOverwrite, PRTVFS phVfs)
     358HRESULT UnattendedInstaller::newAuxFloppyImage(const char *pszFilename, bool fOverwrite, PRTVFSFILE phVfsFile)
    343359{
    344360    /*
     
    361377        if (RT_SUCCESS(vrc))
    362378        {
    363             /*
    364              * Open the FAT VFS.
    365              */
    366             RTERRINFOSTATIC ErrInfo;
    367             RTVFS           hVfs;
    368             vrc = RTFsFatVolOpen(hVfsFile, false /*fReadOnly*/,  0 /*offBootSector*/, &hVfs, RTErrInfoInitStatic(&ErrInfo));
    369             if (RT_SUCCESS(vrc))
    370             {
    371                 *phVfs = hVfs;
    372                 RTVfsFileRelease(hVfsFile);
    373                 LogRelFlow(("UnattendedInstaller::newAuxFloppyImage: created, formatted and opened '%s'\n", pszFilename));
    374                 return S_OK;
    375             }
    376 
    377             if (RTErrInfoIsSet(&ErrInfo.Core))
    378                 hrc = mpParent->setErrorBoth(E_FAIL, vrc, tr("Failed to open newly created floppy image '%s': %Rrc: %s"),
    379                                              pszFilename, vrc, ErrInfo.Core.pszMsg);
    380             else
    381                 hrc = mpParent->setErrorBoth(E_FAIL, vrc, tr("Failed to open newly created floppy image '%s': %Rrc"),
    382                                              pszFilename, vrc);
    383         }
    384         else
    385             hrc = mpParent->setErrorBoth(E_FAIL, vrc, tr("Failed to format floppy image '%s': %Rrc"), pszFilename, vrc);
     379            *phVfsFile = hVfsFile;
     380            LogRelFlow(("UnattendedInstaller::newAuxFloppyImage: created and formatted  '%s'\n", pszFilename));
     381            return S_OK;
     382        }
     383
     384        hrc = mpParent->setErrorBoth(E_FAIL, vrc, tr("Failed to format floppy image '%s': %Rrc"), pszFilename, vrc);
    386385        RTVfsFileRelease(hVfsFile);
    387386        RTFileDelete(pszFilename);
     
    391390    return hrc;
    392391}
    393 
    394392
    395393HRESULT UnattendedInstaller::copyFilesToAuxFloppyImage(RTVFS hVfs)
     
    441439                                     pEditor->getDefaultFilename(), getAuxiliaryFloppyFilePath().c_str());
    442440    return hrc;
    443 
     441}
     442
     443HRESULT UnattendedInstaller::addFileToFloppyImage(RTVFS hVfs, const char *pszSrc, const char *pszDst)
     444{
     445    HRESULT hrc;
     446
     447    /*
     448     * Open the source file.
     449     */
     450    RTVFSIOSTREAM hVfsIosSrc;
     451    int vrc = RTVfsIoStrmOpenNormal(pszSrc, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE, &hVfsIosSrc);
     452    if (RT_SUCCESS(vrc))
     453    {
     454        /*
     455         * Open the destination file.
     456         */
     457        RTVFSFILE hVfsFileDst;
     458        vrc = RTVfsFileOpen(hVfs, pszDst,
     459                            RTFILE_O_WRITE | RTFILE_O_CREATE_REPLACE | RTFILE_O_DENY_ALL | (0660 << RTFILE_O_CREATE_MODE_SHIFT),
     460                            &hVfsFileDst);
     461        if (RT_SUCCESS(vrc))
     462        {
     463            /*
     464             * Do the copying.
     465             */
     466            RTVFSIOSTREAM hVfsIosDst = RTVfsFileToIoStream(hVfsFileDst);
     467            vrc = RTVfsUtilPumpIoStreams(hVfsIosSrc, hVfsIosDst, 0);
     468            if (RT_SUCCESS(vrc))
     469                hrc = S_OK;
     470            else
     471                hrc = mpParent->setErrorBoth(VBOX_E_FILE_ERROR, vrc, tr("Error writing copying '%s' to floppy image '%s': %Rrc"),
     472                                             pszSrc, getAuxiliaryFloppyFilePath().c_str(), vrc);
     473            RTVfsIoStrmRelease(hVfsIosDst);
     474            RTVfsFileRelease(hVfsFileDst);
     475        }
     476        else
     477            hrc = mpParent->setErrorBoth(VBOX_E_FILE_ERROR, vrc, tr("Error opening '%s' on floppy image '%s' for writing: %Rrc"),
     478                                         pszDst, getAuxiliaryFloppyFilePath().c_str(), vrc);
     479
     480        RTVfsIoStrmRelease(hVfsIosSrc);
     481    }
     482    else
     483        hrc = mpParent->setErrorBoth(VBOX_E_FILE_ERROR, vrc, tr("Error opening '%s' for copying onto floppy image '%s': %Rrc"),
     484                                     pszSrc, getAuxiliaryFloppyFilePath().c_str(), vrc);
     485    return hrc;
    444486}
    445487
     
    813855
    814856
     857
     858/*********************************************************************************************************************************
     859*   Implementation of UnattendedOs2Installer                                                                                     *
     860*********************************************************************************************************************************/
     861
     862UnattendedOs2Installer::UnattendedOs2Installer(Unattended *pParent, Utf8Str const &rStrHints)
     863    : UnattendedInstaller(pParent,
     864                          "os2_response_files.rsp", "os2_postinstall.cmd",
     865                          "OS2.RSP",                "VBOXPOST.CMD",
     866                          DeviceType_Floppy)
     867{
     868    Assert(!isOriginalIsoNeeded());
     869    Assert(isAuxiliaryFloppyNeeded());
     870    Assert(isAuxiliaryIsoIsVISO());
     871    Assert(bootFromAuxiliaryIso());
     872    mStrAuxiliaryInstallDir = "S:\\";
     873
     874    /* Extract the info from the hints variable: */
     875    RTCList<RTCString, RTCString *> Pairs = rStrHints.split(" ");
     876    size_t i = Pairs.size();
     877    Assert(i > 0);
     878    while (i -- > 0)
     879    {
     880        RTCString const rStr = Pairs[i];
     881        if (rStr.startsWith("OS2SE20.SRC="))
     882            mStrOs2Images = rStr.substr(sizeof("OS2SE20.SRC=") - 1);
     883        else
     884            AssertMsgFailed(("Unknown hint: %s\n", rStr.c_str()));
     885    }
     886}
     887
     888
     889HRESULT UnattendedOs2Installer::replaceAuxFloppyImageBootSector(RTVFSFILE hVfsFile) RT_NOEXCEPT
     890{
     891    /*
     892     * Find the bootsector.  Because the ArcaOS ISOs doesn't contain any floppy
     893     * images, we cannot just lift it off one of those.  Instead we'll locate it
     894     * in the SYSINSTX.COM utility, i.e. the tool which installs it onto floppies
     895     * and harddisks.  The SYSINSTX.COM utility is a NE executable and we don't
     896     * have issues with compressed pages like with LX images.
     897     *
     898     * The utility seems always to be located on disk 0.
     899     */
     900    RTVFS   hVfsOrgIso;
     901    HRESULT hrc = openInstallIsoImage(&hVfsOrgIso);
     902    if (SUCCEEDED(hrc))
     903    {
     904        char szPath[256];
     905        int vrc = RTPathJoin(szPath, sizeof(szPath), mStrOs2Images.c_str(), "DISK_0/SYSINSTX.COM");
     906        if (RT_SUCCESS(vrc))
     907        {
     908            RTVFSFILE hVfsSysInstX;
     909            vrc = RTVfsFileOpen(hVfsOrgIso, szPath, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_NONE, &hVfsSysInstX);
     910            if (RT_SUCCESS(vrc))
     911            {
     912                /*
     913                 * Scan the image looking for a 512 block ending with a DOS signature
     914                 * and starting with a three byte jump followed by an OEM name string.
     915                 */
     916                uint8_t *pbBootSector = NULL;
     917                uint64_t off          = 0;
     918                bool     fEof         = false;
     919                uint8_t  abBuf[_8K]   = {0};
     920                do
     921                {
     922                    /* Read the next chunk. */
     923                    memmove(abBuf, &abBuf[sizeof(abBuf) - 512], 512); /* Move up the last 512 (all zero the first time around). */
     924                    size_t cbRead = 0;
     925                    vrc = RTVfsFileReadAt(hVfsSysInstX, off, &abBuf[512], sizeof(abBuf) - 512, &cbRead);
     926                    if (RT_FAILURE(vrc))
     927                        break;
     928                    fEof = cbRead != sizeof(abBuf) - 512;
     929                    off += cbRead;
     930
     931                    /* Scan it. */
     932                    size_t   cbLeft = sizeof(abBuf);
     933                    uint8_t *pbCur  = abBuf;
     934                    while (cbLeft >= 512)
     935                    {
     936                        /* Look for the DOS signature (0x55 0xaa) at the end of the sector: */
     937                        uint8_t *pbHit = (uint8_t *)memchr(pbCur + 510, 0x55, cbLeft - 510 - 1);
     938                        if (!pbHit)
     939                            break;
     940                        if (pbHit[1] == 0xaa)
     941                        {
     942                            uint8_t *pbStart = pbHit - 510;
     943                            if (   pbStart[0] == 0xeb        /* JMP imm8 */
     944                                && pbStart[1] >= 3 + 8 + sizeof(FATEBPB) - 2 /* must jump after the FATEBPB */
     945                                && RT_C_IS_ALNUM(pbStart[3]) /* ASSUME OEM string starts with two letters (typically 'IBM x.y')*/
     946                                && RT_C_IS_ALNUM(pbStart[4]))
     947                            {
     948                                FATEBPB *pBpb = (FATEBPB *)&pbStart[3 + 8];
     949                                if (   pBpb->bExtSignature == FATEBPB_SIGNATURE
     950                                    && (   memcmp(pBpb->achType, "FAT     ", sizeof(pBpb->achType)) == 0
     951                                        || memcmp(pBpb->achType, FATEBPB_TYPE_FAT12, sizeof(pBpb->achType)) == 0))
     952                                {
     953                                    pbBootSector = pbStart;
     954                                    break;
     955                                }
     956                            }
     957                        }
     958
     959                        /* skip */
     960                        pbCur  = pbHit - 510 + 1;
     961                        cbLeft = &abBuf[sizeof(abBuf)] - pbCur;
     962                    }
     963                } while (!fEof);
     964
     965                if (pbBootSector)
     966                {
     967                    if (pbBootSector != abBuf)
     968                        pbBootSector = (uint8_t *)memmove(abBuf, pbBootSector, 512);
     969
     970                    /*
     971                     * We've now got a bootsector.  So, we need to copy the EBPB
     972                     * from the destination image before replacing it.
     973                     */
     974                    vrc = RTVfsFileReadAt(hVfsFile, 0, &abBuf[512], 512, NULL);
     975                    if (RT_SUCCESS(vrc))
     976                    {
     977                        memcpy(&pbBootSector[3 + 8], &abBuf[512 + 3 + 8], sizeof(FATEBPB));
     978
     979                        /*
     980                         * Write it.
     981                         */
     982                        vrc = RTVfsFileWriteAt(hVfsFile, 0, pbBootSector, 512, NULL);
     983                        if (RT_SUCCESS(vrc))
     984                        {
     985                            LogFlowFunc(("Successfully installed new bootsector\n"));
     986                            hrc = S_OK;
     987                        }
     988                        else
     989                            hrc = mpParent->setErrorBoth(VBOX_E_FILE_ERROR, vrc, tr("Failed to write bootsector: %Rrc"), vrc);
     990                    }
     991                    else
     992                        hrc = mpParent->setErrorBoth(VBOX_E_FILE_ERROR, vrc, tr("Failed to read bootsector: %Rrc"), vrc);
     993                }
     994                else if (RT_FAILURE(vrc))
     995                    hrc = mpParent->setErrorBoth(VBOX_E_FILE_ERROR, vrc, tr("Error reading SYSINSTX.COM: %Rrc"), vrc);
     996                else
     997                    hrc = mpParent->setErrorBoth(E_FAIL, VERR_NOT_FOUND,
     998                                                 tr("Unable to locate bootsector template in SYSINSTX.COM"));
     999                RTVfsFileRelease(hVfsSysInstX);
     1000            }
     1001            else
     1002                hrc = mpParent->setErrorBoth(VBOX_E_FILE_ERROR, vrc, tr("Failed to open SYSINSTX.COM: %Rrc"), vrc);
     1003        }
     1004        else
     1005            hrc = mpParent->setErrorBoth(VBOX_E_FILE_ERROR, vrc, tr("Failed to construct SYSINSTX.COM path"));
     1006        RTVfsRelease(hVfsOrgIso);
     1007    }
     1008    return hrc;
     1009
     1010}
     1011
     1012HRESULT UnattendedOs2Installer::newAuxFloppyImage(const char *pszFilename, bool fOverwrite, PRTVFSFILE phVfsFile)
     1013{
     1014    /*
     1015     * Open the image file.
     1016     */
     1017    HRESULT     hrc;
     1018    RTVFSFILE   hVfsFile;
     1019    uint64_t    fOpen = RTFILE_O_READWRITE | RTFILE_O_DENY_ALL | (0660 << RTFILE_O_CREATE_MODE_SHIFT);
     1020    if (fOverwrite)
     1021        fOpen |= RTFILE_O_CREATE_REPLACE;
     1022    else
     1023        fOpen |= RTFILE_O_OPEN;
     1024    int vrc = RTVfsFileOpenNormal(pszFilename, fOpen, &hVfsFile);
     1025    if (RT_SUCCESS(vrc))
     1026    {
     1027        /*
     1028         * Format it.
     1029         */
     1030        vrc = RTFsFatVolFormat288(hVfsFile, false /*fQuick*/);
     1031        if (RT_SUCCESS(vrc))
     1032        {
     1033            /*
     1034             * Now we install the OS/2 boot sector on it.
     1035             */
     1036            hrc = replaceAuxFloppyImageBootSector(hVfsFile);
     1037            if (SUCCEEDED(hrc))
     1038            {
     1039                *phVfsFile = hVfsFile;
     1040                LogRelFlow(("UnattendedInstaller::newAuxFloppyImage: created and formatted  '%s'\n", pszFilename));
     1041                return S_OK;
     1042            }
     1043        }
     1044        else
     1045            hrc = mpParent->setErrorBoth(E_FAIL, vrc, tr("Failed to format floppy image '%s': %Rrc"), pszFilename, vrc);
     1046        RTVfsFileRelease(hVfsFile);
     1047        RTFileDelete(pszFilename);
     1048    }
     1049    else
     1050        hrc = mpParent->setErrorBoth(E_FAIL, vrc, tr("Failed to create floppy image '%s': %Rrc"), pszFilename, vrc);
     1051    return hrc;
     1052}
     1053
     1054
     1055HRESULT UnattendedOs2Installer::splitResponseFile() RT_NOEXCEPT
     1056{
     1057    if (mVecSplitFiles.size() == 0)
     1058    {
     1059#if 0
     1060        Utf8Str strResponseFile;
     1061        int vrc = strResponseFile.assignNoThrow(mpParent->i_getAuxiliaryBasePath());
     1062        if (RT_SUCCESS(vrc))
     1063            vrc = strResponseFile.appendNoThrow(mMainScript.getDefaultFilename());
     1064        if (RT_SUCCESS(vrc))
     1065            return splitFile(strResponseFile.c_str(), mVecSplitFiles);
     1066        return mpParent->setErrorVrc(vrc);
     1067#else
     1068        return splitFile(&mMainScript, mVecSplitFiles);
     1069#endif
     1070    }
     1071    return S_OK;
     1072}
     1073
     1074HRESULT UnattendedOs2Installer::copyFilesToAuxFloppyImage(RTVFS hVfs)
     1075{
     1076    /*
     1077     * Make sure we've split the files already.
     1078     */
     1079    HRESULT hrc = splitResponseFile();
     1080    if (FAILED(hrc))
     1081        return hrc;
     1082
     1083    /*
     1084     * We need to copy over the files needed to boot OS/2.
     1085     */
     1086    static struct
     1087    {
     1088        bool        fMandatory;
     1089        const char *apszNames[2];
     1090        const char *apszDisks[3];
     1091        const char *pszMinVer;
     1092        const char *pszMaxVer;
     1093    } const s_aFiles[] =
     1094    {
     1095        { true, { "OS2BOOT",      NULL          }, { "DISK_0", NULL,     NULL }, "2.1",  NULL }, /* 2.0 did not have OS2BOOT */
     1096        { true, { "OS2LDR",       NULL          }, { "DISK_0", NULL,     NULL }, NULL,   NULL },
     1097        { true, { "OS2LDR.MSG",   NULL          }, { "DISK_0", NULL,     NULL }, NULL,   NULL },
     1098        { true, { "OS2KRNL",      "OS2KRNLI"    }, { "DISK_0", NULL,     NULL }, NULL,   NULL },
     1099        { true, { "OS2DUMP",      NULL          }, { "DISK_0", NULL,     NULL }, NULL,   NULL },
     1100        //
     1101        { true, { "ANSICALL.DLL", NULL          }, { "DISK_1", "DISK_2", NULL }, NULL,   NULL },
     1102        { true, { "BKSCALLS.DLL", NULL          }, { "DISK_1", "DISK_2", NULL }, NULL,   NULL },
     1103        { true, { "BMSCALLS.DLL", NULL          }, { "DISK_1", "DISK_2", NULL }, NULL,   NULL },
     1104        { true, { "BVHINIT.DLL",  NULL          }, { "DISK_1", "DISK_2", NULL }, NULL,   NULL },
     1105        { true, { "BVSCALLS.DLL", NULL          }, { "DISK_1", "DISK_2", NULL }, NULL,   NULL },
     1106        { true, { "CDFS.IFS",     NULL          }, { "DISK_1", "DISK_2", NULL }, NULL,   NULL },
     1107        { true, { "CLOCK01.SYS",  NULL          }, { "DISK_1", "DISK_2", NULL }, NULL,   NULL },
     1108        { true, { "COUNT437.SYS", "COUNTRY.SYS" }, { "DISK_1", "DISK_2", NULL }, NULL,   NULL },
     1109        { true, { "DOS.SYS",      NULL          }, { "DISK_1", "DISK_2", NULL }, NULL,   NULL },
     1110        { true, { "DOSCALL1.DLL", NULL          }, { "DISK_1", "DISK_2", NULL }, NULL,   NULL },
     1111        { true, { "IBM1FLPY.ADD", NULL          }, { "DISK_1", "DISK_2", NULL }, NULL,   NULL },
     1112        { true, { "IBM1S506.ADD", NULL          }, { "DISK_1", "DISK_2", NULL }, NULL,   NULL },
     1113        { true, { "IBMIDECD.FLT", NULL          }, { "DISK_1", "DISK_2", NULL }, "4.0",  NULL }, /* not in 2.1 & Warp3  */
     1114        { true, { "IBMKBD.SYS", "KBD01.SYS"/*?*/}, { "DISK_1", "DISK_2", NULL }, NULL,   NULL},
     1115        { true, { "ISAPNP.SNP",   NULL          }, { "DISK_1", "DISK_2", NULL }, "4.0",  NULL }, /* not in 2.1 */
     1116        { true, { "KBDBASE.SYS",  NULL          }, { "DISK_1", "DISK_2", NULL }, "3.0",  NULL }, /* not in 2.1 */
     1117        { true, { "KBDCALLS.DLL", NULL          }, { "DISK_1", "DISK_2", NULL }, NULL,   NULL },
     1118        { true, { "KEYBOARD.DCP", NULL          }, { "DISK_1", "DISK_2", NULL }, NULL,   NULL },
     1119        { true, { "MOUCALLS.DLL", NULL          }, { "DISK_1", "DISK_2", NULL }, NULL,   NULL },
     1120        { true, { "MSG.DLL",      NULL          }, { "DISK_1", "DISK_2", NULL }, NULL,   NULL },
     1121        { true, { "NAMPIPES.DLL", NULL          }, { "DISK_1", "DISK_2", NULL }, NULL,   NULL },
     1122        { true, { "NLS.DLL",      NULL          }, { "DISK_1", "DISK_2", NULL }, NULL,   NULL },
     1123        { true, { "OS2CDROM.DMD", NULL          }, { "DISK_1", "DISK_2", NULL }, NULL,   NULL },
     1124        { true, { "OS2CHAR.DLL",  NULL          }, { "DISK_1", "DISK_2", NULL }, NULL,   NULL },
     1125        { true, { "OS2DASD.DMD",  NULL          }, { "DISK_1", "DISK_2", NULL }, NULL,   NULL },
     1126        { true, { "OS2LVM.DMD",   NULL          }, { "DISK_1", "DISK_2", NULL }, "4.5",  NULL },
     1127        { true, { "OS2VER",       NULL          }, { "DISK_0", NULL,     NULL }, NULL,   NULL },
     1128        { true, { "PNP.SYS",      NULL          }, { "DISK_1", "DISK_2", NULL }, "4.0",  NULL },
     1129        { true, { "QUECALLS.DLL", NULL          }, { "DISK_1", "DISK_2", NULL }, NULL,   NULL },
     1130        { true, { "RESOURCE.SYS", NULL          }, { "DISK_1", "DISK_2", NULL }, "3.0",  NULL }, /* not in 2.1*/
     1131        { true, { "SCREEN01.SYS", NULL          }, { "DISK_1", "DISK_2", NULL }, NULL,   NULL },
     1132        { true, { "SESMGR.DLL",   NULL          }, { "DISK_1", "DISK_2", NULL }, NULL,   NULL },
     1133        { true, { "TESTCFG.SYS",  NULL          }, { "DISK_1", "DISK_2", NULL }, NULL,   NULL },
     1134        { true, { "VIO437.DCP",   "VTBL850.DCP" }, { "DISK_1", "DISK_2", NULL }, NULL,   NULL },
     1135        { true, { "VIOCALLS.DLL", NULL          }, { "DISK_1", "DISK_2", NULL }, NULL,   NULL },
     1136    };
     1137
     1138
     1139    RTVFS hVfsOrgIso;
     1140    hrc = openInstallIsoImage(&hVfsOrgIso);
     1141    if (SUCCEEDED(hrc))
     1142    {
     1143        for (size_t i = 0; i < RT_ELEMENTS(s_aFiles); i++)
     1144        {
     1145            bool fCopied = false;
     1146            for (size_t iDisk = 0; iDisk < RT_ELEMENTS(s_aFiles[i].apszDisks) && s_aFiles[i].apszDisks[iDisk] && !fCopied; iDisk++)
     1147            {
     1148                for (size_t iName = 0; iName < RT_ELEMENTS(s_aFiles[i].apszNames) && s_aFiles[i].apszNames[iName]; iName++)
     1149                {
     1150                    char szPath[256];
     1151                    int vrc = RTPathJoin(szPath, sizeof(szPath), mStrOs2Images.c_str(), s_aFiles[i].apszDisks[iDisk]);
     1152                    if (RT_SUCCESS(vrc))
     1153                        vrc = RTPathAppend(szPath, sizeof(szPath), s_aFiles[i].apszNames[iName]);
     1154                    AssertRCBreakStmt(vrc, hrc = mpParent->setErrorBoth(E_FAIL, vrc, tr("RTPathJoin/Append failed for %s: %Rrc"),
     1155                                                                        s_aFiles[i].apszNames[iName], vrc));
     1156                    RTVFSFILE hVfsSrc;
     1157                    vrc = RTVfsFileOpen(hVfsOrgIso, szPath, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_NONE, &hVfsSrc);
     1158                    if (RT_SUCCESS(vrc))
     1159                    {
     1160                        RTVFSFILE hVfsDst;
     1161                        vrc = RTVfsFileOpen(hVfs, s_aFiles[i].apszNames[0],
     1162                                            RTFILE_O_WRITE | RTFILE_O_CREATE_REPLACE | RTFILE_O_DENY_NONE
     1163                                            | (0755 << RTFILE_O_CREATE_MODE_SHIFT), &hVfsDst);
     1164                        if (RT_SUCCESS(vrc))
     1165                        {
     1166                            RTVFSIOSTREAM hVfsIosSrc = RTVfsFileToIoStream(hVfsSrc);
     1167                            RTVFSIOSTREAM hVfsIosDst = RTVfsFileToIoStream(hVfsDst);
     1168                            vrc = RTVfsUtilPumpIoStreams(hVfsIosSrc, hVfsIosDst, 0);
     1169                            RTVfsIoStrmRelease(hVfsIosDst);
     1170                            RTVfsFileRelease(hVfsDst);
     1171                            RTVfsIoStrmRelease(hVfsIosSrc);
     1172                            if (RT_FAILURE(vrc))
     1173                                hrc = mpParent->setErrorBoth(VBOX_E_FILE_ERROR, vrc, tr("Failed to write %s to the floppy: %Rrc"),
     1174                                                             s_aFiles[i].apszNames, vrc);
     1175                        }
     1176                        else
     1177                            hrc = mpParent->setErrorBoth(VBOX_E_FILE_ERROR, vrc, tr("Failed to open %s on floppy: %Rrc"),
     1178                                                         s_aFiles[i].apszNames, vrc);
     1179
     1180                        RTVfsFileRelease(hVfsSrc);
     1181                        fCopied = true;
     1182                        break;
     1183                    }
     1184                }
     1185            }
     1186            if (FAILED(hrc))
     1187                break;
     1188            if (!fCopied)
     1189            {
     1190                /** @todo do version filtering.   */
     1191                hrc = mpParent->setErrorBoth(E_FAIL, VERR_FILE_NOT_FOUND,
     1192                                             tr("Failed to locate '%s' needed for the install floppy"), s_aFiles[i].apszNames[0]);
     1193                break;
     1194            }
     1195        }
     1196        RTVfsRelease(hVfsOrgIso);
     1197    }
     1198
     1199    /*
     1200     * In addition, we need to add a CONFIG.SYS and the startup script.
     1201     */
     1202    if (SUCCEEDED(hrc))
     1203    {
     1204        Utf8Str strSrc;
     1205        try
     1206        {
     1207            strSrc = mpParent->i_getAuxiliaryBasePath();
     1208            strSrc.append("CONFIG.SYS");
     1209        }
     1210        catch (std::bad_alloc &)
     1211        {
     1212            return E_OUTOFMEMORY;
     1213        }
     1214        hrc = addFileToFloppyImage(hVfs, strSrc.c_str(), "CONFIG.SYS");
     1215    }
     1216
     1217    /*
     1218     * We also want a ALTF2ON.$$$ file so we can see which drivers are loaded
     1219     * and where it might get stuck.
     1220     */
     1221    if (SUCCEEDED(hrc))
     1222    {
     1223        RTVFSFILE hVfsFile;
     1224        int vrc = RTVfsFileOpen(hVfs, "ALTF2ON.$$$",
     1225                                RTFILE_O_WRITE | RTFILE_O_CREATE_REPLACE | RTFILE_O_DENY_NONE
     1226                                | (0755 << RTFILE_O_CREATE_MODE_SHIFT), &hVfsFile);
     1227        if (RT_SUCCESS(vrc))
     1228        {
     1229            /** @todo buggy fat vfs: cannot write empty files */
     1230            RTVfsFileWrite(hVfsFile, RT_STR_TUPLE("\r\n"), NULL);
     1231            RTVfsFileRelease(hVfsFile);
     1232        }
     1233        else
     1234            hrc = mpParent->setErrorBoth(E_FAIL, VERR_FILE_NOT_FOUND, tr("Failed to create 'ALTF2ON.$$$' on the install floppy"));
     1235    }
     1236
     1237    return hrc;
     1238}
     1239
     1240HRESULT UnattendedOs2Installer::addFilesToAuxVisoVectors(RTCList<RTCString> &rVecArgs, RTCList<RTCString> &rVecFiles,
     1241                                                         RTVFS hVfsOrgIso, bool fOverwrite)
     1242{
     1243    /*
     1244     * Make sure we've split the files already.
     1245     */
     1246    HRESULT hrc = splitResponseFile();
     1247    if (FAILED(hrc))
     1248        return hrc;
     1249
     1250    /*
     1251     * Add our stuff to the vectors.
     1252     */
     1253    try
     1254    {
     1255        /* Remaster ISO. */
     1256        rVecArgs.append() = "--no-file-mode";
     1257        rVecArgs.append() = "--no-dir-mode";
     1258
     1259        rVecArgs.append() = "--import-iso";
     1260        rVecArgs.append(mpParent->i_getIsoPath());
     1261
     1262        rVecArgs.append() = "--file-mode=0444";
     1263        rVecArgs.append() = "--dir-mode=0555";
     1264
     1265        /* Add the boot floppy to the ISO: */
     1266        rVecArgs.append() = "--eltorito-new-entry";
     1267        rVecArgs.append() = "--eltorito-add-image";
     1268        rVecArgs.append(mStrAuxiliaryFloppyFilePath);
     1269        rVecArgs.append() = "--eltorito-floppy-288";
     1270
     1271
     1272        /* Add the response files and postinstall files to the ISO: */
     1273        Utf8Str const &rStrAuxPrefix = mpParent->i_getAuxiliaryBasePath();
     1274        size_t i = mVecSplitFiles.size();
     1275        while (i-- > 0)
     1276        {
     1277            RTCString const &rStrFile = mVecSplitFiles[i];
     1278            rVecArgs.append().assign("VBoxCID/").append(rStrFile).append('=').append(rStrAuxPrefix).append(rStrFile);
     1279        }
     1280    }
     1281    catch (std::bad_alloc &)
     1282    {
     1283        return E_OUTOFMEMORY;
     1284    }
     1285
     1286    /*
     1287     * Call parent.
     1288     */
     1289    return UnattendedInstaller::addFilesToAuxVisoVectors(rVecArgs, rVecFiles, hVfsOrgIso, fOverwrite);
     1290}
     1291
     1292/**
     1293 * Helper for splitFile.
     1294 */
     1295const char *splitFileLocateSubstring(const char *pszSrc, size_t cchSrc, const char *pszSubstring, size_t cchSubstring)
     1296{
     1297    char const ch0 = *pszSubstring;
     1298    while (cchSrc >= cchSubstring)
     1299    {
     1300        const char *pszHit0 = (const char *)memchr(pszSrc, ch0, cchSrc - cchSubstring + 1);
     1301        if (pszHit0)
     1302        {
     1303            if (memcmp(pszHit0, pszSubstring, cchSubstring) == 0)
     1304                return pszHit0;
     1305        }
     1306        else
     1307            break;
     1308        cchSrc -= pszHit0 - pszSrc + 1;
     1309        pszSrc  = pszHit0 + 1;
     1310    }
     1311    return NULL;
     1312}
     1313
     1314/**
     1315 * Worker for splitFile().
     1316 */
     1317HRESULT UnattendedOs2Installer::splitFileInner(const char *pszFileToSplit, RTCList<RTCString> &rVecSplitFiles,
     1318                                               const char *pszSrc, size_t cbLeft) RT_NOEXCEPT
     1319{
     1320    static const char  s_szPrefix[] = "@@VBOX_SPLITTER_";
     1321    const char * const pszStart     = pszSrc;
     1322    const char * const pszEnd       = &pszSrc[cbLeft];
     1323    while (cbLeft > 0)
     1324    {
     1325        /*
     1326         * Locate the next split start marker (everything before it is ignored).
     1327         */
     1328        const char *pszMarker = splitFileLocateSubstring(pszSrc, cbLeft, s_szPrefix, sizeof(s_szPrefix) - 1);
     1329        if (pszMarker)
     1330            pszMarker += sizeof(s_szPrefix) - 1;
     1331        else
     1332            break;
     1333        if (strncmp(pszMarker, RT_STR_TUPLE("START[")) != 0)
     1334            return mpParent->setErrorBoth(E_FAIL, VERR_PARSE_ERROR,
     1335                                          tr("Unexpected splitter tag in '%s' at offset %p: @@VBOX_SPLITTER_%.64s"),
     1336                                          pszFileToSplit, pszMarker - pszStart, pszMarker);
     1337        pszMarker += sizeof("START[") - 1;
     1338        const char *pszTail = splitFileLocateSubstring(pszMarker, pszEnd - pszMarker, RT_STR_TUPLE("]@@"));
     1339        if (   !pszTail
     1340            || pszTail - pszMarker > 64
     1341            || memchr(pszMarker, '\\', pszTail - pszMarker)
     1342            || memchr(pszMarker, '/', pszTail - pszMarker)
     1343            || memchr(pszMarker, ':', pszTail - pszMarker)
     1344           )
     1345            return mpParent->setErrorBoth(E_FAIL, VERR_PARSE_ERROR,
     1346                                          tr("Malformed splitter tag in '%s' at offset %p: @@VBOX_SPLITTER_START[%.64s"),
     1347                                          pszFileToSplit, pszMarker - pszStart, pszMarker);
     1348        int vrc = RTStrValidateEncodingEx(pszMarker, pszTail - pszMarker, RTSTR_VALIDATE_ENCODING_EXACT_LENGTH);
     1349        if (RT_FAILURE(vrc))
     1350            return mpParent->setErrorBoth(E_FAIL, vrc,
     1351                                          tr("Malformed splitter tag in '%s' at offset %p: @@VBOX_SPLITTER_START[%.*Rhxs"),
     1352                                          pszFileToSplit, pszMarker - pszStart, pszTail - pszMarker, pszMarker);
     1353        const char *pszFilename;
     1354        try
     1355        {
     1356            pszFilename = rVecSplitFiles.append().assign(pszMarker, pszTail - pszMarker).c_str();
     1357        }
     1358        catch (std::bad_alloc &)
     1359        {
     1360            return E_OUTOFMEMORY;
     1361        }
     1362        const char *pszDocStart = pszTail + sizeof("]@@") - 1;
     1363        while (RT_C_IS_SPACE(*pszDocStart))
     1364            if (*pszDocStart++ == '\n')
     1365                break;
     1366
     1367        /* Advance. */
     1368        pszSrc = pszDocStart;
     1369        cbLeft = pszEnd - pszDocStart;
     1370
     1371        /*
     1372         * Locate the matching end marker (there cannot be any other markers inbetween).
     1373         */
     1374        const char * const pszDocEnd = pszMarker = splitFileLocateSubstring(pszSrc, cbLeft, s_szPrefix, sizeof(s_szPrefix) - 1);
     1375        if (pszMarker)
     1376            pszMarker += sizeof(s_szPrefix) - 1;
     1377        else
     1378            return mpParent->setErrorBoth(E_FAIL, VERR_PARSE_ERROR,
     1379                                          tr("No END splitter tag for '%s' in '%s'"), pszFilename, pszFileToSplit);
     1380        if (strncmp(pszMarker, RT_STR_TUPLE("END[")) != 0)
     1381            return mpParent->setErrorBoth(E_FAIL, VERR_PARSE_ERROR,
     1382                                          tr("Unexpected splitter tag in '%s' at offset %p: @@VBOX_SPLITTER_%.64s"),
     1383                                          pszFileToSplit, pszMarker - pszStart, pszMarker);
     1384        pszMarker += sizeof("END[") - 1;
     1385        size_t const cchFilename = strlen(pszFilename);
     1386        if (   strncmp(pszMarker, pszFilename, cchFilename) != 0
     1387            || pszMarker[cchFilename] != ']'
     1388            || pszMarker[cchFilename + 1] != '@'
     1389            || pszMarker[cchFilename + 2] != '@')
     1390            return mpParent->setErrorBoth(E_FAIL, VERR_PARSE_ERROR,
     1391                                          tr("Mismatching splitter tag for '%s' in '%s' at offset %p: @@VBOX_SPLITTER_END[%.64Rhxs"),
     1392                                          pszFilename, pszFileToSplit, pszMarker - pszStart, pszMarker);
     1393
     1394        /* Advance. */
     1395        pszSrc = pszMarker + cchFilename + sizeof("]@@") - 1;
     1396        cbLeft = pszEnd - pszSrc;
     1397
     1398        /*
     1399         * Write out the file.
     1400         */
     1401        Utf8Str strDstFilename;
     1402        vrc = strDstFilename.assignNoThrow(mpParent->i_getAuxiliaryBasePath());
     1403        if (RT_SUCCESS(vrc))
     1404            vrc = strDstFilename.appendNoThrow(pszFilename);
     1405        if (RT_SUCCESS(vrc))
     1406        {
     1407            RTFILE hFile;
     1408            vrc = RTFileOpen(&hFile, strDstFilename.c_str(), RTFILE_O_CREATE_REPLACE | RTFILE_O_WRITE | RTFILE_O_DENY_WRITE);
     1409            if (RT_SUCCESS(vrc))
     1410            {
     1411                vrc = RTFileWrite(hFile, pszDocStart, pszDocEnd - pszDocStart, NULL);
     1412                if (RT_SUCCESS(vrc))
     1413                    vrc = RTFileClose(hFile);
     1414                else
     1415                    RTFileClose(hFile);
     1416                if (RT_FAILURE(vrc))
     1417                    return mpParent->setErrorBoth(VBOX_E_FILE_ERROR, vrc, tr("Error writing '%s' (split out from '%s'): %Rrc"),
     1418                                                  strDstFilename.c_str(), pszFileToSplit, vrc);
     1419            }
     1420            else
     1421                return mpParent->setErrorBoth(VBOX_E_FILE_ERROR, vrc,
     1422                                              tr("File splitter failed to open output file '%s' in '%s': %Rrc (%s)"),
     1423                                              pszFilename, pszFileToSplit, vrc, strDstFilename.c_str());
     1424        }
     1425        else
     1426            return mpParent->setErrorBoth(VBOX_E_FILE_ERROR, vrc,
     1427                                          tr("File splitter failed to construct path for '%s' in '%s': %Rrc"),
     1428                                          pszFilename, pszFileToSplit, vrc);
     1429    }
     1430
     1431    return S_OK;
     1432}
     1433
     1434HRESULT UnattendedOs2Installer::splitFile(const char *pszFileToSplit, RTCList<RTCString> &rVecSplitFiles) RT_NOEXCEPT
     1435{
     1436    /*
     1437     * Read the whole source file into memory, making sure it's zero terminated.
     1438     */
     1439    HRESULT hrc;
     1440    void   *pvSrc;
     1441    size_t  cbSrc;
     1442    int vrc = RTFileReadAllEx(pszFileToSplit, 0 /*off*/, _16M /*cbMax*/,
     1443                              RTFILE_RDALL_F_TRAILING_ZERO_BYTE | RTFILE_RDALL_F_FAIL_ON_MAX_SIZE | RTFILE_RDALL_O_DENY_WRITE,
     1444                              &pvSrc, &cbSrc);
     1445    if (RT_SUCCESS(vrc))
     1446    {
     1447        /*
     1448         * Do the actual splitting in a worker function to avoid needing to
     1449         * thing about calling RTFileReadAllFree in error paths.
     1450         */
     1451        hrc = splitFileInner(pszFileToSplit, rVecSplitFiles, (const char *)pvSrc, cbSrc);
     1452        RTFileReadAllFree(pvSrc, cbSrc);
     1453    }
     1454    else
     1455        hrc = mpParent->setErrorBoth(VBOX_E_FILE_ERROR, vrc, tr("Failed to read '%s' for splitting up: %Rrc"),
     1456                                     pszFileToSplit, vrc);
     1457    return hrc;
     1458}
     1459
     1460HRESULT UnattendedOs2Installer::splitFile(BaseTextScript *pEditor, RTCList<RTCString> &rVecSplitFiles) RT_NOEXCEPT
     1461{
     1462    /*
     1463     * Get the output from the editor.
     1464     */
     1465    Utf8Str strSrc;
     1466    HRESULT hrc = pEditor->saveToString(strSrc);
     1467    if (SUCCEEDED(hrc))
     1468    {
     1469        /*
     1470         * Do the actual splitting.
     1471         */
     1472        hrc = splitFileInner(pEditor->getDefaultFilename(), rVecSplitFiles, strSrc.c_str(), strSrc.length());
     1473    }
     1474    return hrc;
     1475}
     1476
     1477
     1478
    8151479//////////////////////////////////////////////////////////////////////////////////////////////////////
    8161480/*
  • trunk/src/VBox/Main/src-server/UnattendedScript.cpp

    r91502 r93085  
    5959    static const char s_szPrefixCond[]     = "@@VBOX_COND_";
    6060    static const char s_szPrefixCondEnd[]  = "@@VBOX_COND_END@@";
     61    static const char s_szPrefixSplitter[] = "@@VBOX_SPLITTER";
    6162
    6263    struct
     
    128129            if (   pszPlaceholder[cchPlaceholder - 1] != '@'
    129130                || pszPlaceholder[cchPlaceholder - 2] != '@'
    130                 || (   strncmp(pszPlaceholder, s_szPrefixInsert, sizeof(s_szPrefixInsert) - 1) != 0
    131                     && strncmp(pszPlaceholder, s_szPrefixCond,   sizeof(s_szPrefixCond)   - 1) != 0 ) )
     131                || (   strncmp(pszPlaceholder, s_szPrefixInsert,   sizeof(s_szPrefixInsert)   - 1) != 0
     132                    && strncmp(pszPlaceholder, s_szPrefixCond,     sizeof(s_szPrefixCond)     - 1) != 0
     133                    && strncmp(pszPlaceholder, s_szPrefixSplitter, sizeof(s_szPrefixSplitter) - 1) != 0 ) )
    132134            {
    133135                hrc = mpSetError->setError(E_FAIL, tr("Malformed template placeholder '%.*s'"),
     
    188190             *                    one from the condition.
    189191             */
    190             else
     192            else if (strncmp(pszPlaceholder, s_szPrefixSplitter, sizeof(s_szPrefixSplitter) - 1) != 0)
    191193            {
    192194                Assert(strncmp(pszPlaceholder, s_szPrefixCond, sizeof(s_szPrefixCond) - 1) == 0);
     
    208210                                                   offPlaceholder, offPlaceholder);
    209211                    break;
     212                }
     213            }
     214            /*
     215             * @@VBOX_SPLITTER_START/END[filename]@@: Ignored in this pass.
     216             */
     217            else
     218            {
     219                if (fOutputting)
     220                {
     221                    try
     222                    {
     223                        rStrDst.append(pszPlaceholder, cchPlaceholder);
     224                    }
     225                    catch (std::bad_alloc &)
     226                    {
     227                        hrc = E_OUTOFMEMORY;
     228                        break;
     229                    }
    210230                }
    211231            }
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