Ignore:
Timestamp:
Jul 17, 2000, 12:43:41 AM (25 years ago)
Author:
bird
Message:

Checkin of current code in the Grace brance for backup purpose.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/GRACE/src/win32k/ldr/myldrOpen.cpp

    r2838 r3834  
    1 /* $Id: myldrOpen.cpp,v 1.10 2000-02-21 09:24:01 bird Exp $
     1/* $Id: myldrOpen.cpp,v 1.10.4.1 2000-07-16 22:43:36 bird Exp $
    22 *
    33 * myldrOpen - ldrOpen.
    44 *
    5  * Copyright (c) 1998-1999 knut st. osmundsen
     5 * Copyright (c) 1998-2000 knut st. osmundsen
    66 *
    77 * Project Odin Software License can be found in LICENSE.TXT
     
    1717
    1818#define INCL_OS2KRNL_IO
     19#define INCL_OS2KRNL_TCB
    1920
    2021/*******************************************************************************
     
    3031
    3132#include "log.h"
     33#include "avl.h"
     34#include "options.h"
    3235#include <peexe.h>
    3336#include <exe386.h>
     37#include "elf.h"
    3438#include "OS2Krnl.h"
    3539#include "dev32.h"
     40#include "ldr.h"
     41#include "ldrCalls.h"
    3642#include "ModuleBase.h"
    3743#include "pe2lx.h"
    38 #include "elf.h"
    39 #include "avl.h"
    40 #include "ldr.h"
    41 #include "ldrCalls.h"
    42 #include "options.h"
    4344#include "myExecPgm.h"
    44 
    45 /*******************************************************************************
    46 *   Global Variables                                                           *
    47 *******************************************************************************/
    48 extern BOOL fQAppType;                  /* From LDRQAppType */
     45#include "env.h"
     46#include "vprintf.h"                    /* Make 100% sure we have va_start.  */
     47
     48
    4949
    5050/*******************************************************************************
    5151*   Internal Functions                                                         *
    5252*******************************************************************************/
    53 static unsigned getArgsLength(const char *pachArgs);
     53/* static */ APIRET     AddArgsToFront(int cArgs,  ...);
     54/* static */ APIRET     SetExecName(const char *pszExeName);
     55/* static */ APIRET     OpenPATH(PSFN phFile, char *pszFilename, PULONG pfl);
    5456
    5557
     
    5961 * @param     phFile       Pointer to file handler. Holds filehandle on output.
    6062 * @param     pszFilename  Pointer to filename.
    61  * @parma     param3       Probably some flags.
     63 * @parma     pfl          Pointer to some flags.
    6264 */
    63 ULONG LDRCALL myldrOpen(PSFN phFile, char *pszFilename, ULONG param3)
     65ULONG LDRCALL myldrOpen(PSFN phFile, PSZ pszFilename, PULONG pfl)
    6466{
    65     ULONG rc;
    66 
    67     /*
     67    static  int cNesting = 0;           /* This is an variable which hold the nesting */
     68                                        /* level of this function. This is useful     */
     69                                        /* when we call it recurcively.               */
     70                                        /* The maximum nesting level is currently 3.  */
     71                                        /* When the maximum depth has been reached    */
     72                                        /* we'll not intercept loading any longer!    */
     73    ULONG rc;                           /* Return value. */
     74
     75    /** @sketch
    6876     * Try open the file (thats why this function is called anyway)
    6977     */
    70     rc = ldrOpen(phFile, pszFilename, param3);
    71 
    72     /* log sucesses */
     78    rc = ldrOpen(phFile, pszFilename, pfl);
    7379    if (rc == NO_ERROR)
    74         kprintf(("ldrOpen:  phFile=%#.4x, flags=%#.8x, pszFn=%s\n", *phFile, param3, pszFilename));
    75 
    76     /*
     80        kprintf(("myldrOpen-%d:  phFile=%#.4x, flags=%#.8x, pszFn=%s\n", cNesting, *phFile, pfl, pszFilename));
     81
     82
     83    /** @sketch
    7784     * Are we to intercept the loading?
    78      * - Only if open were succesful and one of the loaders are enabled.
     85     * - If open were successful.
     86     * - And Not too deep nesting.
     87     * - And that this isn't an unsupported load.
     88     * - And one of the loaders are enabled.
    7989     */
    80     if (rc == NO_ERROR && (options.fElf || options.fPE != FLAGS_PE_NOT || options.fScript))
    81     {
    82         char               *pszBuffer = (char*)rmalloc(640);        /* Read buffer. */
    83         PIMAGE_DOS_HEADER   pMzHdr = (PIMAGE_DOS_HEADER)pszBuffer;  /* Pointer to the buffer as it were a dosheader. */
    84         PIMAGE_NT_HEADERS   pNtHdrs = (PIMAGE_NT_HEADERS)pszBuffer; /* Pointer to the buffer as if it were an NT header. */
    85         char               *pach = pszBuffer;                       /* Finally an pointer to the buffer as if it were chars.. (which it is!) */
    86         PEXECPGMBUFFER      pBuffer;                                /* Pointer to a buffer containing the programname and arguments. */
    87                                                                     /* For scripts and PE.EXE this has to be changed to have correct */
    88                                                                     /* parameters sendt in to the program. */
    89         unsigned            cchRead = sizeof(IMAGE_DOS_HEADER);     /* Amount of the buffer which contains valid data. */
    90         unsigned            cbFile;                                 /* Filesize (0xffffffff if call to SftFileSize failed - should _never_ happen though)  */
    91 
    92         /*
    93          * Verify that rmalloc completed successfully.
    94          */
    95         if (pszBuffer == NULL)
     90    if (rc == NO_ERROR
     91        && cNesting < 3
     92        && !isLdrStateLoadingUnsupported()
     93        && isAnyLoaderEnabled()
     94        )
     95    {
     96        union _u_ReadBufferPointers         /* Read buffer pointer(s). */
    9697        {
    97             kprintf(("ldrOpen: rmalloc(1024) failed\n"));
     98            char               *pach;       /* Pointer to the buffer as char. */
     99            PIMAGE_DOS_HEADER   pMzHdr;     /* Use the buffer as a dosheader. */
     100            PIMAGE_NT_HEADERS   pNtHdrs;    /* Use the buffer as a NT header. */
     101        } u1;
     102        unsigned            cbFile;         /* Filesize (0xffffffff if call to SftFileSize failed - should _never_ happen though) */
     103        unsigned            cbRead;         /* Amount of the buffer which contains valid data. */
     104        char *              psz;            /* Multipurpose string pointer no.1. */
     105        char *              psz2;           /* Multipurpose string pointer no.2. */
     106        char *              psz3;           /* Multipurpose string pointer no.3. */
     107
     108        /** @sketch
     109         * Allocate read buffer from resident heap.
     110         * IF this fails THEN we'll simply return NO_ERROR.
     111         */
     112        u1.pach = (char*)rmalloc(640);
     113        if (u1.pach == NULL)
     114        {
     115            kprintf(("myldrOpen-%d: rmalloc(640) failed\n", cNesting));
    98116            return NO_ERROR;
    99117        }
    100118
    101         /*
    102          * Try get the filesize
     119
     120        /** @sketch
     121         * Increment nesting level.
     122         */
     123        cNesting++;
     124
     125
     126        /** @sketch
     127         * Get the filesize. On failure filesize is set to ~0.
    103128         */
    104129        rc = SftFileSize(*phFile, (PULONG)SSToDS(&cbFile));
    105130        if (rc != NO_ERROR)
    106131        {
    107             kprintf(("ldrOpen: SftFileSize failed with rc=%d\n", rc));
     132            kprintf(("myldrOpen-%d: SftFileSize failed with rc=%d\n", cNesting, rc));
    108133            cbFile = (unsigned)~0;
    109134        }
    110135
    111         /*
    112          * See if this is an recognizable module format.
    113          * This costs up to two disk reads!
    114          */
    115         rc = ldrRead(*phFile, 0UL, pMzHdr, 0UL, cchRead, NULL);
    116         if (rc == NO_ERROR)
     136
     137        /** @sketch
     138         *  Read the size of a DOS (ie. MZ) header.
     139         *  IF successful and more stuff in file THEN
     140         *      See if this is an recognizable module binary format:
     141         */
     142        cbRead = min(sizeof(IMAGE_DOS_HEADER), cbFile);
     143        rc = ldrRead(*phFile, 0UL, u1.pMzHdr, 0UL, cbRead, NULL);
     144        if (rc == NO_ERROR && cbRead < cbFile)
    117145        {
    118             /*
    119              * PE header?
    120              *  - If DOS Magic is found AND a valid e_lfanew (offset of NE/LX/LE/PE header) is found
    121              *  - OR if PE siganture is found.
     146            /** @sketch
     147             * If LX header just give up at once.
    122148             */
    123             if ((pMzHdr->e_magic == IMAGE_DOS_SIGNATURE &&
    124                  pMzHdr->e_lfanew > sizeof(IMAGE_DOS_HEADER) && pMzHdr->e_lfanew < 0x04000000UL) /* Larger than 64 bytes and less that 64MB. */
    125                 || *(PULONG)pach == IMAGE_NT_SIGNATURE)
    126             {   /*
    127                  * MZ or PE header found
     149            if (u1.pMzHdr->e_magic == E32MAGIC)
     150                goto cleanup;
     151
     152            /** @sketch
     153             * IF PE or MZ header THEN
     154             */
     155            if (u1.pMzHdr->e_magic == IMAGE_DOS_SIGNATURE
     156                || u1.pNtHdrs->Signature == IMAGE_NT_SIGNATURE)
     157            {
     158                ULONG   offPe;          /* Offset to PE header. */
     159
     160                /** @sketch
     161                 * ---
     162                 * We now known that this is file has a MZ or a PE header. If it's
     163                 * a MZ header, we might end up with no "New" header or the "New"
     164                 * header might turn out to be a NE, LE, or LX header. I any of
     165                 * these non PE headers occur OS/2 will take care of it, we'll do nothing.
     166                 * ---
     167                 * IF PE loading is disable or MZ header and e_lfanew is invalid THEN
     168                 *     return (successfully) to the caller.
     169                 * ENDIF
     170                 * (Find the offset of the PE header while testing (offPe).)
    128171                 */
    129 
    130                 /* if PE loading is diable return to the caller */
    131                 if (options.fPE == FLAGS_PE_NOT)
     172                if (isPELoaderDisabled())
     173                    goto cleanup;
     174                if (u1.pMzHdr->e_magic == IMAGE_DOS_SIGNATURE)
    132175                {
    133                     rfree(pszBuffer);
    134                     return NO_ERROR;
     176                    offPe = u1.pMzHdr->e_lfanew;
     177                    if (offPe < sizeof(IMAGE_DOS_HEADER) || offPe > 0x04000000UL)
     178                        goto cleanup;
    135179                }
    136 
    137                 /*
    138                  * Read the PE header if it isn't what we allready have!
     180                else
     181                    offPe = 0;
     182
     183
     184                /** @sketch
     185                 * Read the PE header.
     186                 * If the read failes or not PE signature, there isn't anything for us to do.
    139187                 */
    140                 cchRead = sizeof(IMAGE_NT_HEADERS);
    141                 if (*(PULONG)pach != IMAGE_NT_SIGNATURE)
    142                     rc = ldrRead(*phFile, pMzHdr->e_lfanew, pach, 0UL, cchRead, NULL);
    143                 else
    144                     rc = ldrRead(*phFile, 0UL, pach, 0UL, cchRead, NULL);
    145 
    146                 /*
    147                  * If successfully read, and a PE signature is present the continue and try load it!
    148                  * Else don't do anything, simply return NO_ERROR to the caller. (probably NE or LX exec)
     188                rc = ldrRead(*phFile, offPe, u1.pach, 0UL, sizeof(IMAGE_NT_HEADERS), NULL);
     189                if (rc != NO_ERROR || u1.pNtHdrs->Signature != IMAGE_NT_SIGNATURE)
     190                    goto cleanup_noerror;
     191
     192
     193                /** @sketch
     194                 * PE signature found!
    149195                 */
    150                 if (rc == NO_ERROR && *(PULONG)pach == IMAGE_NT_SIGNATURE)
    151                 {   /*
    152                      * PE signature found.
    153                      */
    154                     kprintf(("ldrOpen: PE executable...\n"));
    155 
    156                     /*
    157                      * PE2LX?
    158                      *  - When PE2LX flag is set
    159                      *  - OR when the MIXED flag is set and the image is with the first 64MB of memory.
    160                      */
    161                     if (options.fPE == FLAGS_PE_PE2LX
    162                         || (options.fPE == FLAGS_PE_MIXED
    163                             && !((pNtHdrs->FileHeader.Characteristics & IMAGE_FILE_DLL == 0UL)
    164                                  && pNtHdrs->OptionalHeader.ImageBase >= 0x04000000UL /* 64MB */
    165                                  )
     196                kprintf(("myldrOpen-%d: PE executable...\n", cNesting));
     197
     198
     199                /** @sketch
     200                 * Use Pe2Lx?
     201                 *  - When Pe2Lx flag is set
     202                 *  - When the MIXED flag is set and the image isn't an executable
     203                 *    above the first 64MB private limit without relocations
     204                 */
     205                if (isPe2LxLoaderEnabled()
     206                    || (isMixedPeLoaderEnabled()
     207                        && ((u1.pNtHdrs->FileHeader.Characteristics & IMAGE_FILE_DLL)
     208                            || !(u1.pNtHdrs->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED)
     209                            || u1.pNtHdrs->OptionalHeader.ImageBase < 0x04000000UL /* 64MB */
    166210                            )
    167211                        )
    168                     {   /*
    169                          * Pe2Lx (Ring0 of course)
    170                          * - Create a Pe2Lx class,
    171                          * - initiate it
    172                          * - Add the module to the module tree so we may find it later...
    173                          * - Set the handle state to 'our'.
    174                          */
    175                         Pe2Lx * pPe2Lx = new Pe2Lx(*phFile);
    176                         if (pPe2Lx != NULL)
     212                    )
     213                {   /** @sketch
     214                     *  Pe2Lx (Ring0 of course)
     215                     *      - Create a Pe2Lx class,
     216                     *      - initiate it
     217                     *      - Add the module to the module tree so we may find it later...
     218                     *      - Set the (file)handle state to 'our'.
     219                     *      - Set pExeModule to module pointer and loaderstate to our exe.
     220                     */
     221                    Pe2Lx * pPe2Lx = new Pe2Lx(*phFile);
     222                    if (pPe2Lx != NULL)
     223                    {
     224                        rc = pPe2Lx->init(pszFilename);
     225                        if (rc == NO_ERROR)
    177226                        {
    178                             rc = pPe2Lx->init(pszFilename);
     227                            kprintf(("myldrOpen-%d: Successfully init of Pe2Lx object.\n", cNesting));
     228                            rc = addModule(*phFile, NULL, MOD_TYPE_PE2LX, pPe2Lx);
    179229                            if (rc == NO_ERROR)
    180230                            {
    181                                 kprintf(("ldrOpen: Successfully init of Pe2Lx object.\n"));
    182                                 rc = addModule(*phFile, NULL, MOD_TYPE_PE2LX, pPe2Lx);
    183                                 if (rc == NO_ERROR)
    184                                     #pragma info(notrd)
    185                                     SetState(*phFile, HSTATE_OUR);
    186                                     #pragma info(restore)
    187                                 else
    188                                     kprintf(("ldrOpen: Failed to add the module. rc=%d\n"));
     231                                #pragma info(notrd)
     232                                SetState(*phFile, HSTATE_OUR);
     233                                #pragma info(restore)
     234                                if (pPe2Lx->isExe())
     235                                {
     236                                    setLdrStateLoadingOurEXE();
     237                                    pExeModule = getModuleBySFN(*phFile);
     238                                    #ifdef DEBUG
     239                                    if (pExeModule == NULL)
     240                                        kprintf(("myldrOpen-%d: getModuleBySFN failed when setting pExeModule! FATAL!\n", cNesting));
     241                                    #endif
     242                                }
    189243                            }
    190244                            else
    191                                 kprintf(("ldrOpen: Failed to init Pe2Lx object. rc=%d\n"));
    192                             if (rc != NO_ERROR)
    193                                 delete pPe2Lx;
     245                                kprintf(("myldrOpen-%d: Failed to add the module. rc=%d\n", cNesting));
    194246                        }
    195247                        else
    196                             kprintf(("ldrOpen: Failed to allocate Pe2Lx object.\n"));
     248                            kprintf(("myldrOpen-%d: Failed to init Pe2Lx object. rc=%d\n", cNesting));
     249                        if (rc != NO_ERROR)
     250                            delete pPe2Lx;
    197251                    }
    198252                    else
     253                        kprintf(("myldrOpen-%d: Failed to allocate Pe2Lx object.\n", cNesting));
     254
     255                     goto cleanup;
     256                }
     257
     258
     259                /** @sketch
     260                 *  Using PE.EXE to start EXE?
     261                 *      - When the file is an EXE file and PE.EXE is enabled.
     262                 */
     263                if ((u1.pNtHdrs->FileHeader.Characteristics & IMAGE_FILE_DLL == 0UL)
     264                    && (options.fPE == FLAGS_PE_PE || options.fPE == FLAGS_PE_MIXED)
     265                    && (isLdrStateExecPgm() || isLdrStateQAppType())
     266                    )
     267                {
     268                    /** @sketch
     269                     * PE.EXE:
     270                     * Find pe.exe - look in current directory and thru the PATH.
     271                     * Note! We use the read buffer (u1.p*) as a storage for the
     272                     * pe.exe filename and path.
     273                     */
     274                    kprintf(("myldrOpen-%d: pe.exe - opening\n", cNesting));
     275                    ldrClose(*phFile);
     276                    strcpy(u1.pach, "PE.EXE");
     277                    rc = ldrOpen(phFile, u1.pach, pfl); /* This isn't recusive! */
     278                    if (rc != NO_ERROR)
     279                        rc = OpenPATH(phFile, u1.pach, pfl);
     280                    if (rc == NO_ERROR)
    199281                    {
    200                         /*
    201                          * Starting of PE.EXE enable?
     282                        /** @sketch
     283                         * If we're in tkExecPgm state we'll have to shuffle the parameters
     284                         * and executable filename tkExecPgm were called with.
     285                         * If not tkExecPgm we can't do anything about parameters (and there is
     286                         * probably nothing to do either).
    202287                         */
    203                         if (options.fPE == FLAGS_PE_PE || options.fPE == FLAGS_PE_MIXED)
    204                         {   /*
    205                              * pe.exe - need the path!
    206                              */
    207                             kprintf(("ldrOpen: pe.exe - opening\n"));
    208                             ldrClose(*phFile);
    209                             rc = ldrOpen(phFile, "pe.exe", param3);  /* path....! problems! */
    210                             kprintf(("ldrOpen: pe.exe - open returned with rc = %d\n", rc));
    211                             rfree(pszBuffer);
    212                             return rc;
     288                        kprintf(("myldrOpen-%d: pe.exe - %s\n", cNesting, u1.pach));
     289                        if (isLdrStateExecPgm() && fTkExecPgm)
     290                        {
     291                            rc = AddArgsToFront(1, achTkExecPgmFilename);
     292                            if (rc == NO_ERROR)
     293                            {
     294                                rc = SetExecName(u1.pach);
     295                                if (rc != NO_ERROR)
     296                                    kprintf(("myldrOpen-%d: pe.exe - failed to set pe.exe as execname. rc=%d\n", cNesting));
     297                            }
     298                            else
     299                                kprintf(("myldrOpen-%d: pe.exe - failed to add programname as argument. rc=%d\n", cNesting, rc));
     300                            goto cleanup_noerror;
    213301                        }
    214302                    }
     303                    else
     304                        kprintf(("myldrOpen-%d: pe.exe - couldn't find/open pe.exe\n", cNesting));
    215305                }
    216                 rfree(pszBuffer);
    217                 return NO_ERROR;
     306                goto cleanup;
     307            }
     308            /** @sketch End of PE Loading. */
     309
     310
     311            /** @sketch
     312             * ELF image?
     313             */
     314            if (u1.pach[0] == ELFMAG0 && u1.pach[1] == ELFMAG1 && u1.pach[2] == ELFMAG2 && u1.pach[3] == ELFMAG3)
     315            {
     316                if (isELFDisabled())
     317                    goto cleanup_noerror;
     318
     319                /*
     320                 * ELF signature found.
     321                 */
     322                kprintf(("myldrOpen-%d: ELF image! - not implemented yet!\n", cNesting));
     323
     324                /*
     325                 * Do nothing more yet. NEED AN ELF LOADER!!!
     326                 */
     327                goto cleanup;
     328            }
     329
     330
     331            /** @sketch
     332             * Java image?
     333             */
     334            if (u1.pach[0] == 0xCA && u1.pach[1] == 0xFE && u1.pach[2] == 0xBA && u1.pach[3] == 0xBE)
     335            {
     336                if (isJAVADisabled())
     337                    goto cleanup_noerror;
     338
     339                /** @sketch
     340                 * Java signature found.
     341                 * Try find the java executor in current dir or PATH: java.exe
     342                 */
     343                kprintf(("myldrOpen-%d: Jave image!\n", cNesting));
     344                #if 1
     345                ldrClose(*phFile);
     346                strcpy(u1.pach, "JAVA.EXE");
     347                rc = ldrOpen(phFile, u1.pach, pfl);
     348                if (rc != NO_ERROR)
     349                    rc = OpenPATH(phFile, u1.pach, pfl);
     350                if (rc == NO_ERROR)
     351                {
     352                    kprintf(("myldrOpen-%d: java - %s\n", cNesting, u1.pach));
     353                    /** @sketch
     354                     * If we're in tkExecPgm state we'll have to create an extra agrument, the
     355                     * class name without a .class extention. We'll do this after the filename
     356                     * in the u1 buffer. This argument is of course added to the front.
     357                     * Then the Executable name is to be updated.
     358                     */
     359                    if (isLdrStateExecPgm() && fTkExecPgm)
     360                    {
     361                        psz = u1.pach + 1 + CCHMAXPATH; /* ASSUMES that buffer is at least CCHMAXPATH*2 + 1 */
     362                        strcpy(psz, pszFilename);
     363                        psz2 = psz + strlen(psz);
     364                        while (psz2 > psz && *psz2 != '\\' && *psz2 != '/')
     365                        {
     366                            if (*psz2 == '.')
     367                            {
     368                                *psz2 = '\0';
     369                                break;
     370                            }
     371                            psz2--;
     372                        }
     373
     374                        rc = AddArgsToFront(1, psz);
     375                        if (rc == NO_ERROR)
     376                        {
     377                            rc = SetExecName(u1.pach);
     378                            if (rc != NO_ERROR)
     379                                kprintf(("myldrOpen-%d: java - failed to set java.exe as execname. rc=%d\n", cNesting, rc));
     380                        }
     381                        else
     382                            kprintf(("myldrOpen-%d: java - failed to add programname as argument. rc=%d\n", cNesting, rc));
     383                        goto cleanup_noerror;
     384                    }
     385                }
     386                else
     387                    kprintf(("myldrOpen-%d: java - couldn't find/open java.exe\n", cNesting));
     388
     389                #endif
     390                /** @sketch
     391                 *  End of Java loading. (return)
     392                 */
     393                goto cleanup;
     394            }
     395        }
     396        else
     397        {
     398            /** @sketch
     399             *  ELSE - the reading size of a DOS header failed or file is smaller than the dos header.
     400             *      IF read failed or filesize is less than 4 bytes THEN
     401             *          return no_error to the caller.
     402             *      ENDIF
     403             */
     404            #ifdef DEBUG
     405            if (rc != NO_ERROR)
     406            {
     407                kprintf(("myldrOpen-%d: ldrRead failed cbRead=%d, cbFile=%d,  rc=%d\n", cNesting, cbRead, cbFile, rc));
     408                goto cleanup_noerror;
     409            }
     410            if (cbRead < 4)
     411            {
     412                kprintf(("myldrOpen-%d: File too small! cbFile=%d\n", cNesting, cbFile));
     413                goto cleanup_noerror;
     414            }
     415            #else
     416            if (rc != NO_ERROR || cbRead < 4) //just forget files less than 4 bytes!
     417                goto cleanup_noerror;
     418            #endif
     419        }
     420        /** @sketch ENDIF (dos header read) */
     421
     422
     423
     424        /*
     425         * Only unreconized files passes this point!
     426         *
     427         * * Fileformats with lower priority should reside here. *
     428         *
     429         */
     430
     431        /** @sketch
     432         *  UNIX styled script?
     433         *      - Starts with a hash (#)
     434         *      - And we're loading an EXE
     435         *      - And we're either in QAppType or ExecPgm state.
     436         *      - And that a bang (!) is the first char after the hash (ignoring blanks).
     437         */
     438        if (*u1.pach == '#'
     439            && isLdrStateLoadingEXE()
     440            && (isLdrStateQAppType() || isLdrStateExecPgm())
     441            )
     442        {
     443            if (isUNIXScriptDisabled())
     444                goto cleanup_noerror;
     445            /*
     446             * Look for a bang (!). Tabs and spaces are skipped, anything else result in error.
     447             */
     448            psz = u1.pach + 1;
     449            while ((*psz == ' ' || *psz == '\t') && psz - u1.pach < cbRead)
     450                psz++;
     451            if (*psz == '!')
     452            {
     453                /** @sketch Found UNIX styled script! */
     454
     455                /** @sketch
     456                 * Read more of the script if necessary. (max is 256 chars (- Linux max is 127))
     457                 * Terminate the string read from the file to make sure with stop somewhere!
     458                 */
     459                if (cbRead < cbFile /*&& cbRead != 256*/)
     460                {
     461                    cbRead = min(256, cbFile);
     462                    rc = ldrRead(*phFile, 0UL, u1.pach, 0UL, cbRead, NULL);
     463                }
     464                u1.pach[cbRead] = '\0';
     465
     466                if (rc == NO_ERROR)
     467                {
     468                    /** @sketch
     469                     * Parse out filename and optional arguments (if any).
     470                     * The result of the parsing is that:
     471                     *      psz will point at the executable name.
     472                     *      psz2 will point at the arguments.
     473                     *  Both strings are trimmed.
     474                     */
     475                    psz++;                                                  /* psz points to the bang, skip it. */
     476                    while (*psz == ' ' || *psz == '\t')                     /* skip blanks after bang */
     477                        psz++;
     478                    if (*psz == '\r' || *psz == '\n' || *psz == '\0')       /* End-of-line? */
     479                    {
     480                        kprintf(("myldrOpen-%d: script no executable name.\n", cNesting));
     481                        goto cleanup_noerror; /* other error code? */
     482                    }
     483                    psz2 = psz + 1;                                         /* Not end-of-line, so add 1 before searching for args. */
     484                    while (*psz2 != '\0' && *psz2 != '\n' && *psz2 != '\r'  /* skip executable name. */
     485                           && *psz2 != ' ' && *psz2 != '\t')
     486                        psz2++;
     487                    while (*psz2 == ' ' || *psz2 == '\t')                    /* skip blanks after executable - pad them with '\0'! */
     488                        *psz2++ = '\0';
     489
     490                    psz3 = psz2;
     491                    while (*psz3 != '\n' && *psz3 != '\r' && *psz3 != '\0') /* find end of parameters and terminate the string. */
     492                        psz3++;
     493                    *psz3 = '\0';
     494                    while (psz3 >= psz2 && (*psz3 == '\0' || *psz3 == ' ' || *psz3 == '\t')) /* trim args */
     495                        *psz3-- = '\0';
     496
     497
     498                    /** @sketch
     499                     *  IF tkExecPgm THEN
     500                     *      Correct parameters - ie. add exec name (as argv[0]),
     501                     *        arguments (psz2) as argv[1+], old exec name, and finally
     502                     *        the existing parameters (current argv[1+]).
     503                     *      Set the executable name.
     504                     *  ENDIF
     505                     *  Open the new executable file recursively. (psz)
     506                     */
     507                     if (isLdrStateExecPgm())
     508                     {
     509                         if (*psz2)
     510                            rc = AddArgsToFront(3, psz, psz2, achTkExecPgmFilename);
     511                         else
     512                            rc = AddArgsToFront(2, psz, achTkExecPgmFilename);
     513                         if (rc != NO_ERROR)
     514                         {
     515                             kprintf(("myldrOpen-%d: AddArgsToFront failed with rc=%d\n", cNesting));
     516                             goto cleanup_noerror;
     517                         }
     518                         rc = SetExecName(psz);
     519                         if (rc != NO_ERROR)
     520                             kprintf(("myldrOpen-%d: SetExecName failed with rc=%d\n", cNesting));
     521                     }
     522                     rc = myldrOpen(phFile, psz, pfl);
     523                }
     524                else
     525                {
     526                    kprintf(("myldrOpen-%d: script - failed to read more of the script!, rc=%d cbRead=%d cbFile=%d.\n",
     527                             cNesting, rc, cbRead, cbFile));
     528                }
     529
     530                goto cleanup;
    218531            }
    219532            else
    220533            {
    221                 /*
    222                  * ELF image?
    223                  */
    224                 if (pach[0] == ELFMAG0 && pach[1] == ELFMAG1 && pach[2] == ELFMAG2 && pach[3] == ELFMAG3)
    225                 {
    226                     /*
    227                      * ELF signature found.
    228                      */
    229                     kprintf(("ldrOpen: ELF executable! - not implemented yet!\n"));
    230 
    231                     /*
    232                      * Do nothing more yet. NEED AN ELF LOADER!!!
    233                      */
    234                     rfree(pszBuffer);
    235                     return NO_ERROR;
    236                 }
     534                kprintf(("myldrOpen-%d: script - hash found but no bang (!).\n", cNesting));
     535            }
     536        } /**@sketch ENDIF - UNIX styled script. */
     537
     538
     539
     540        /** @sketch
     541         *  REXX script?
     542         *      - Starts with a REXX start comment ('/','*')
     543         *      - And we're loading an EXE
     544         *      - And we're either in QAppType or ExecPgm state.
     545         *      - Extention is currently ignored....
     546         *          .RX and .REX are known to be pure REXX scripts.
     547         *          While .CMD has to invoked used the commandline OS2_SHELL or COMSPEC variable.
     548         */
     549        if (*u1.pach == '/' && u1.pach[1] == '*'
     550            && isLdrStateLoadingEXE()
     551            && (isLdrStateQAppType() || isLdrStateExecPgm())
     552            )
     553        {
     554            if (isREXXScriptDisabled())
     555                goto cleanup_noerror;
     556
     557            /** @sketch
     558             * Found REXX styled script!
     559             * Find the REXX interpreter. We'll use kRx.exe to execute the REXX scripts.
     560             * (This interpreter could be embedded as a child of ModuleBase as it turned out
     561             * to be quite small about 700 bytes.)
     562             */
     563            kprintf(("myldrOpen-%d: Found REXX script\n", cNesting));
     564            ldrClose(*phFile);
     565            strcpy(u1.pach, "KRX.EXE");
     566            rc = ldrOpen(phFile, u1.pach, pfl);
     567            if (rc != NO_ERROR)
     568                rc = OpenPATH(phFile, u1.pach, pfl);
     569
     570            /** @sketch
     571             *  IF tkExecPgm THEN
     572             *      Correct parameters - ie. add exec name (as argv[0]), old exec name,
     573             *        and finally the existing parameters (current argv[1+]).
     574             *      Set the executable name.
     575             *  ENDIF
     576             */
     577             if (rc == NO_ERROR && isLdrStateExecPgm())
     578             {
     579                 rc = AddArgsToFront(2, u1.pach, achTkExecPgmFilename);
     580                 if (rc != NO_ERROR)
     581                 {
     582                     kprintf(("myldrOpen-%d: AddArgsToFront failed with rc=%d\n", cNesting));
     583                     goto cleanup_noerror;
     584                 }
     585                 rc = SetExecName(u1.pach);
     586                 if (rc != NO_ERROR)
     587                     kprintf(("myldrOpen-%d: SetExecName failed with rc=%d\n", cNesting));
     588
     589                 goto cleanup_noerror;
     590             }
     591             goto cleanup;
     592        } /**@sketch ENDIF - REXX styled script. */
     593
     594
     595        /*
     596         * Cleanup with rc set to NO_ERROR.
     597         */
     598    cleanup_noerror:
     599        rc = NO_ERROR;
     600
     601        /*
     602         * Cleanup without having rc set to NO_ERROR.
     603         * Decrement the nesting count.
     604         */
     605    cleanup:
     606        rfree(u1.pach);
     607        cNesting--;
     608    }
     609    #ifdef DEBUG
     610    else if (cNesting >= 3)
     611        kprintf(("myldrOpen-%d: cNesting = %d, which is too deep!\n", cNesting, cNesting));
     612    #endif
     613
     614    /** @sketch
     615     *  Return rc.
     616     */
     617    return rc;
     618}
     619
     620
     621/**
     622 * Adds new arguments to the front of the startup arguments for the program about to be
     623 * executed.
     624 *
     625 * @returns   OS/2 return code.
     626 * @param     cArgs     Count of arguments to add. At least 1!!!
     627 * @param     ...       Pointers to the arguments to add.
     628 *                      The first argument have to be the executable name. This have to the
     629 *                        the only argument in the first string.
     630 *                      The other arguements are space separated, so you could add a bunch
     631 *                        of arguments in a single string!
     632 *                      The last argument should be the old first parameter if this is to be
     633 *                        preserved. The old first parameter is overwritten since it's
     634 *                        normally the executable name.
     635 *
     636 * @status    completly implemented.
     637 * @author    knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
     638 * @remark    Implementation note:
     639 *  The arguments convention is as follows:
     640 *      First argument, which should be the executable name, is terminated with a '\0'.
     641 *        It starts at offset 0 into the argument buffer, of course.
     642 *      All other arguemnts are separated by a space and follows the immediately after the
     643 *        first argument.
     644 *      The arguments are terminated by a double nulltermination: '\0\0'.
     645 */
     646APIRET AddArgsToFront(int cArgs,  ...)
     647{
     648    va_list     vaarg;                  /* Variable length argument list. */
     649    int         cchOldArgs;             /* Length of the old arguments (including the first argument). */
     650                                        /* cchOldArgs = 1 means no arguments. It don't include the very last '\0' */
     651                                        /* (remember argumets are terminated with two '\0's). */
     652    int         iSecondArg;             /* Index of the second argument. (Used to skip the first argument.) */
     653                                        /* Used first on the original arguments and them when adding the first */
     654                                        /* new argument. */
     655    int         cchNewArgs;             /* Length of the new arguments to be inserted. */
     656    int         i;                      /* Loop variable. Current function argument. */
     657    char *      psz;                    /* General string pointer. */
     658
     659
     660    /** @sketch
     661     *  Assert that we're in the right state.
     662     *  Calc the length of the existing parameters.
     663     *  Calc the length of the new arguments to determin.
     664     *  Assert that the new arguments have length > 0.
     665     */
     666    #ifdef DEBUG
     667    if (!isLdrStateExecPgm())
     668    {
     669        kprintf(("AddArgsToFront: not in tkExecPgm state.\n"));
     670        return ERROR_INVALID_PARAMETER;
     671    }
     672    #endif
     673    if (!fTkExecPgm)
     674    {
     675        kprintf(("AddArgsToFront: called when not in tkExecPgm data is invalid!\n"));
     676        return ERROR_INVALID_PARAMETER;
     677    }
     678
     679    cchOldArgs = iSecondArg = strlen(&achTkExecPgmArguments[0]) + 1;
     680    psz = &achTkExecPgmArguments[cchOldArgs];
     681    while (*psz != '\0')
     682        psz = &achTkExecPgmArguments[(cchOldArgs += strlen(psz) + 1)];
     683
     684    va_start(vaarg, cArgs);
     685    for (cchNewArgs = i = 0; i < cArgs; i++)
     686        cchNewArgs += strlen(va_arg(vaarg, char *)) + 1; /* 1 is for space or '\0'. */
     687    va_end(vaarg);
     688    #ifdef DEBUG
     689    if (cchNewArgs == 0)
     690    {
     691        kprintf(("AddArgsToFront: the size of the arguments to add is zero!\n"));
     692        return ERROR_INVALID_PARAMETER;
     693    }
     694    #endif
     695
     696
     697    /** @sketch
     698     *  Check if we have enough room for the new arguments. Fail if not enough.
     699     *  Move the existing arguments to make room for the new ones.
     700     *    !IMPORTANT! The first existing arguments (executable name) is skipped !IMPORTANT!
     701     *    !IMPORTANT! in this move as this have to be re-added in this call!    !IMPORTANT!
     702     */
     703    if (cchOldArgs + 1 + cchNewArgs > CCHARGUMENTS)
     704    {
     705        kprintf(("AddArgsToFront: argument buffer is too small to hold the arguments to add, cchOldArgs=%d, cchNewArgs=%d\n",
     706                 cchOldArgs, cchNewArgs));
     707        return ERROR_BAD_ARGUMENTS;
     708    }
     709
     710    if (cchOldArgs > 1)
     711    {
     712        memmove(&achTkExecPgmArguments[cchNewArgs], &achTkExecPgmArguments[iSecondArg],
     713                cchOldArgs - iSecondArg + 1);
     714    }
     715    else
     716        achTkExecPgmArguments[cchNewArgs + 1] = '\0';
     717
     718
     719    /** @sketch
     720     *  Copy new arguments.
     721     *  Since the first argument is special case we'll do it separately. (Uses '\0' as separator.)
     722     *    We assume that the entire first argument passed into this function should be the first argument!
     723     *    (This don't have to be true for the other arguments since these are space separated. You could
     724     *     pass in more than argument in a single string.)
     725     *  Loop thru the rest of the new arguments and add them with space as separator.
     726     */
     727    va_start(vaarg, cArgs);
     728    psz = va_arg(vaarg, char *);
     729    iSecondArg = strlen(psz) + 1;
     730    memcpy(&achTkExecPgmArguments[0], psz, iSecondArg);
     731
     732    psz = &achTkExecPgmArguments[iSecondArg];
     733    i = 2;                              /* one in advance to avoid a +1. */
     734    while (1)
     735    {
     736        strcpy(psz, va_arg(vaarg, char *));
     737        psz += strlen(psz);
     738        /* IF more arguments following (new or old) THEN add a space separator ELSE break loop */
     739        if (cchOldArgs > 1 || i < cArgs)
     740            *psz++ = ' ';
     741        else
     742            break;
     743        i++;
     744    }
     745    va_end(vaarg);
     746
     747    #ifdef DEBUG /* assertion */
     748    if (psz != &achTkExecPgmArguments[cchNewArgs])
     749    {
     750        kprintf(("AddArgsToFront: !Assertion failed! psz didn't end up where it should! (psz -> %d should be %d)\n",
     751                 psz - &achTkExecPgmArguments[0], cchNewArgs));
     752        if (cchOldArgs <= 1)
     753            psz[0] = psz[1] = '\0';
     754    }
     755    #endif
     756
     757    return NO_ERROR;
     758}
     759
     760
     761/**
     762 * Sets the executable name of the module.
     763 * This function is normally invoked after a different executable than the one requested was
     764 * opened. It does _NOT_ set the new executable name as the first argument, since it is more
     765 * convenient to this while calling AddArgsToFront to add other arguments.
     766 *
     767 * @returns   OS/2 return code.
     768 * @param     pszExecName   Pointer to new executable name.
     769 * @status    completly implemented.
     770 * @author    knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
     771 * @remark    .
     772 */
     773APIRET SetExecName(const char *pszExecName)
     774{
     775    #ifdef DEBUG
     776    int cch;
     777    cch = strlen(pszExecName);
     778    if (cch > CCHMAXPATH)
     779    {
     780        kprintf(("ChangeExecName: filename is too long! cch=%d. name=%s\n", cch, pszExecName));
     781        return ERROR_FILENAME_EXCED_RANGE;
     782    }
     783    if (!isLdrStateExecPgm())
     784    {
     785        kprintf(("ChangeExecName: called when not in tkExecPgm state!!! FATAL ERROR!\n"));
     786        return ERROR_INVALID_PARAMETER;
     787    }
     788    #endif
     789    if (!fTkExecPgm)
     790    {
     791        kprintf(("ChangeExecName: called when not in tkExecPgm data is invalid!!! FATAL ERROR!\n"));
     792        return ERROR_INVALID_PARAMETER;
     793    }
     794
     795    strcpy(achTkExecPgmFilename, pszExecName);
     796
     797    return 0;
     798}
     799
     800
     801/**
     802 * Opens a file using the PATH environment variable of the current process.
     803 * @returns   OS2 return code.
     804 * @param     phFile        Pointer to filehandle. The filehandle is set to the SFN for the opened
     805 *                          file on successful return.
     806 *                          The filehandle is 0 on failure.
     807 * @param     pszFilename   Pointer to filename buffer. This will hold the filename on input.
     808 *                          On successful return it holds the filepath found.
     809 *                          On failiure it's undefined.
     810 * @param     pfl           Some flags set by ldrOpen.
     811 * @sketch    stub
     812 * @author    knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
     813 * @remark
     814 */
     815APIRET OpenPATH(PSFN phFile, char *pszFilename, PULONG pfl)
     816{
     817    APIRET      rc;
     818    USHORT      TCBFailErr_save;
     819    int         cchFilename;            /* Filename length + 1. */
     820    const char *pszPath = ScanEnv(GetEnv(FALSE), "PATH"); /* Current Process environment? */
     821
     822    /**@sketch
     823     *  No PATH environment.
     824     */
     825    if (pszPath == NULL)
     826        return ERROR_FILE_NOT_FOUND;
     827
     828    cchFilename = strlen(pszFilename) + 1;
     829
     830    /**@sketch
     831     * We'll have to save the TCBFailErr since we don't want to cause
     832     * Hard Errors while searching invalid paths, etc. (ldrOpenPath does this!)
     833     */
     834    TCBFailErr_save = tcbGetTCBFailErr(tcbGetCur());
     835
     836    /**@ sketch
     837     *  Loop thru the PATH trying to open the specified file in each
     838     *  directory.
     839     */
     840    while (*pszPath != '\0')
     841    {
     842        const char *  pszNext = pszPath;
     843        int           cchPath;
     844        char          chEnd, ch;
     845
     846        /*
     847         * Find end of this path.
     848         */
     849        while (*pszPath == ' ') pszPath++; //skip leading spaces.
     850        chEnd = *pszPath == '"' ? '"' : ';';
     851        while ((ch = *pszNext) != chEnd && ch != '\0')
     852            pszNext++;
     853
     854        if (chEnd == '"')
     855        {
     856            cchPath = pszNext - (++pszPath); //pszPath points at '"' before incrementing it.
     857            if (ch != '\0')
     858                pszNext++;
     859        }
     860        else
     861        {
     862            /* Trim the string. */
     863            cchPath = pszNext - pszPath;
     864            while (cchPath > 0 && pszPath[cchPath-1] == ' ') //??
     865                cchPath--;
     866        }
     867
     868        /*
     869         *  No length? No Path! Or path'\'filename too long? => Next
     870         */
     871        if (cchPath > 0 && cchPath + cchFilename + 1 < CCHMAXPATH)
     872        {
     873            static char     achFilename[CCHMAXPATH];
     874            /*
     875             * Build filename
     876             */
     877            memcpy(achFilename, pszPath, cchPath);
     878            if ((ch = achFilename[cchPath - 1]) == '\\' || ch == '/')
     879                cchPath--;
     880            else
     881                achFilename[cchPath] = '\\';
     882            memcpy(&achFilename[cchPath + 1], pszFilename, cchFilename); /* cchFilename = length + 1; hence we copy the terminator too. */
     883
     884            /*
     885             * Try open the file.
     886             */
     887            rc = myldrOpen(phFile, achFilename, pfl);
     888            switch (rc)
     889            {
     890                case ERROR_FILE_NOT_FOUND:          case ERROR_PATH_NOT_FOUND:          case ERROR_ACCESS_DENIED:           case ERROR_INVALID_ACCESS:
     891                case ERROR_INVALID_DRIVE:           case ERROR_NOT_DOS_DISK:            case ERROR_REM_NOT_LIST:            case ERROR_BAD_NETPATH:
     892                case ERROR_NETWORK_BUSY:            case ERROR_DEV_NOT_EXIST:           case ERROR_TOO_MANY_CMDS:           case ERROR_ADAP_HDW_ERR:
     893                case ERROR_UNEXP_NET_ERR:           case ERROR_BAD_REM_ADAP:            case ERROR_NETNAME_DELETED:         case ERROR_BAD_DEV_TYPE:
     894                case ERROR_NETWORK_ACCESS_DENIED:   case ERROR_BAD_NET_NAME:            case ERROR_TOO_MANY_SESS:           case ERROR_REQ_NOT_ACCEP:
     895                case ERROR_INVALID_PASSWORD:        case ERROR_OPEN_FAILED:             case ERROR_INVALID_NAME:            case ERROR_FILENAME_EXCED_RANGE:
     896                case ERROR_VC_DISCONNECTED:
     897                    break;
     898
     899                case NO_ERROR:
     900                default:
     901                    tcbSetTCBFailErr(tcbGetCur(), TCBFailErr_save);
     902                    return rc;
    237903            }
    238904        }
     905        #ifdef DEBUG
     906        else if (cchPath > 0)   kprintf(("OpenPATH: Path component is too long\n"));
     907        #endif
    239908
    240909        /*
    241          * Only unreconized files and readerror passes this point!
    242          *
    243          * * Fileformats with lower priority should reside here. *
    244          *
    245          */
    246 
    247         /*
    248          * If the initial readoperation failed try to read a smaller amount, in case it is a small script...
    249          * 4 bytes is a small amount isn't it?
    250          */
    251         if (rc != NO_ERROR)
    252         {
    253             kprintf(("ldrOpen: first ldrread failed with rc=%d. tries to read 4 byte.\n", rc));
    254             cchRead = 4;
    255             if ((rc = ldrRead(*phFile, 0UL, pach, 0UL, cchRead, NULL)) != NO_ERROR)
    256                 kprintf(("ldrOpen: second ldrread failed with rc=%d.\n ", rc));
    257         }
    258 
    259         /*
    260          * Now we'll try again, UNIX styled script?
    261          */
    262         if (rc == NO_ERROR && *pach == '#' && pach[1] == '!')
    263         {
    264             /*
    265              * UNIX styled script?
    266              * FIXME! Must be more than 64 bytes long?
    267              *        No options!
    268              *        Firstline < 64 bytes!
    269              */
    270             kprintf(("ldrOpen: unix script?\n"));
    271             cchRead = min(cbFile, 256);
    272             rc = ldrRead(*phFile, 0UL, pach, 0UL, cchRead, NULL);
    273             if (rc == NO_ERROR)
    274             {
    275                 char *pszStart = pach+2;
    276                 kprintf(("ldrOpen: script debug 1\n"));
    277 
    278                 /* Make sure we don't read to much... */
    279                 pszBuffer[cchRead] = '\0';
    280 
    281                 /*
    282                  * Skip blanks
    283                  */
    284                 pszStart = pszBuffer + 2; /* skips the "#!" stuff. */
    285                 while (*pszStart != '\0' && (*pszStart == ' ' || *pszStart == '\t'))
    286                     pszStart++;
    287                 kprintf(("ldrOpen: script debug 2\n"));
    288 
    289                 /* anything left on the line? */
    290                 if (*pszStart != '\0' && *pszStart != '\r' && *pszStart != '\n')
    291                 {
    292                     char *      pszEnd;         /* Pointer to the end of the string(s) when the next step is finished. */
    293                     unsigned    cchToAdd = 1;   /* Chars to add */
    294                     BOOL        fFirst = TRUE;  /* Set if a '\0' has not been set yet.
    295                                                  * If this is clear, there are one or more parameters after the interpreter name. */
    296 
    297                     /*
    298                      * find linesize and make parameters ready for copying
    299                      */
    300                     pszEnd = pszStart;
    301                     kprintf(("ldrOpen: script debug 3\n"));
    302                     while (*pszEnd != '\0' && *pszEnd != '\r' && *pszEnd != '\n')
    303                     {
    304                         if (fFirst && (*pszEnd == ' ' || *pszEnd == '\t'))
    305                         {
    306                             *pszEnd = '\0';
    307                             fFirst = FALSE;
    308                             if (pszEnd[1] == '\0' || pszEnd[1] == '\r' || pszEnd[1] == '\n')
    309                                 fFirst = TRUE;
    310                         }
    311 
    312                         /* next */
    313                         pszEnd++;
    314                         cchToAdd++;
    315                     }
    316                     *pszEnd = '\0';
    317                     kprintf(("ldrOpen: script debug 4\n"));
    318 
    319                     /*
    320                      * If ldrQueryApp type we don't have any ExecPgm buffer we need to mess with.
    321                      * We'll simply try open the the interpreter.
    322                      */
    323                     if (fQAppType)
    324                     {
    325                         rc = ldrClose(*phFile);
    326                         rc = ldrOpen(phFile, pszStart, param3); /* FIXME, recusion! check that name not equal! Use flags to prevent race? */
    327                     }
    328                     else
    329                     {
    330                         /*
    331                          * Find the ExecPgm buffer.
    332                          */
    333                         pBuffer = QueryBufferPointerFromFilename(pszFilename);
    334                         kprintf(("ldrOpen: script debug 5\n"));
    335                         if (pBuffer != NULL)
    336                         {
    337                             unsigned cchArguments = getArgsLength(pBuffer->achArgs); /* minus the first argument. */
    338                             unsigned cchScriptnameDelta = strlen(pBuffer->szFilename) - strlen(pBuffer->achArgs); /* scriptname size difference. */
    339 
    340                             kprintf(("ldrOpen: script debug 6\n"));
    341 
    342                             /*
    343                              * Is there enough space in the struct?
    344                              */
    345                             if (cchArguments + cchToAdd + cchScriptnameDelta < sizeof(pBuffer->achArgs))
    346                             {
    347                                 kprintf(("ldrOpen: script debug 7\n"));
    348                                 /*
    349                                  * Open the interpreter.
    350                                  */
    351                                 rc = ldrClose(*phFile);
    352                                 rc = ldrOpen(phFile, pszStart, param3); /* FIXME, recusion! check that name not equal! Use flags to prevent race? */
    353                                 if (rc == NO_ERROR)
    354                                 {
    355                                     kprintf(("ldrOpen: script debug 8\n"));
    356                                     /* Make space for the addition arguments. */
    357                                     #ifdef DEBUG
    358                                     char *psz = &pBuffer->achArgs[0];
    359                                     int   i = 0;
    360                                     while (*psz != '\0')
    361                                     {
    362                                         kprintf(("Arg %d: %s\n", i++, psz));
    363                                         psz += 1 + strlen(psz);
    364                                     }
    365                                     #endif
    366                                     memmove(&pBuffer->achArgs[cchToAdd + cchScriptnameDelta],
    367                                             &pBuffer->achArgs[0], cchArguments);
    368 
    369                                     /*
    370                                      * Copy the arguments.
    371                                      */
    372                                     kprintf(("ldrOpen: script debug 8\n"));
    373                                     memcpy(&pBuffer->achArgs[0], pszStart, cchToAdd); /* Interpreter with arguments */
    374                                     if (!fFirst)
    375                                         pBuffer->achArgs[cchToAdd - 1] = ' ';
    376                                     strcpy(&pBuffer->achArgs[cchToAdd], pszFilename); /* Scriptname */
    377                                     kprintf(("ldrOpen: script debug a\n"));
    378 
    379                                     #ifdef DEBUG
    380                                     psz = &pBuffer->achArgs[0];
    381                                     i = 0;
    382                                     while (*psz != '\0')
    383                                     {
    384                                         kprintf(("Arg %d: %s\n", i++, psz));
    385                                         psz += 1 + strlen(psz);
    386                                     }
    387                                     #endif
    388                                 }
    389                                 else
    390                                     kprintf(("ldrOpen: failed to open interpreter (%s), rc=%d\n", pszStart, rc));
    391                             }
    392                             else
    393                             {
    394                                 kprintf(("ldrOpen: Argument buffer too small, %d\n", cchArguments + cchToAdd));
    395                                 rc = ERROR_BAD_EXE_FORMAT;
    396                             }
    397                         }
    398                         else
    399                         {
    400                             kprintf(("ldrOpen: QueryBufferPointerFromFilename failed.\n"));
    401                             rc = ERROR_BAD_EXE_FORMAT; /*?*/
    402                         }
    403                     }
    404                 }
    405                 else
    406                 {
    407                     kprintf(("ldrOpen: no interpereter on the first line.\n"));
    408                     rc = ERROR_BAD_EXE_FORMAT; /*?*/
    409                 }
    410             }
    411             else
    412             {
    413                 kprintf(("ldrOpen: read of min(cbFile, 256) = %d failed, rc = %d\n", cchRead, rc));
    414             }
    415         } /* else inn other formats here. */
    416         rfree(pszBuffer);
    417     }
    418     return rc;
     910         * Next
     911         */
     912        if (*pszNext == '\0')
     913            break;
     914        pszPath = pszNext + 1;
     915    }
     916
     917
     918    /*
     919     * File is not found.
     920     */
     921    *phFile = 0;
     922    tcbSetTCBFailErr(tcbGetCur(), TCBFailErr_save);
     923    return ERROR_FILE_NOT_FOUND;
    419924}
    420 
    421 
    422 /**
    423  * Get the lenght of the arguments.
    424  * @returns   Lenght in char, includes the two '\0's.
    425  * @param     pachArgs  Pointer to the ASCIIZs which makes up the arguments.
    426  * @status    completely implemented.
    427  * @author    knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
    428  */
    429 static unsigned getArgsLength(const char *pachArgs)
    430 {
    431     unsigned    cch = 1;
    432     const char *psz = pachArgs;
    433 
    434     while (*psz != '\0')
    435     {
    436         register unsigned cch2 = strlen(psz);
    437         cch += cch2;
    438         psz += cch2 + 1;
    439     }
    440 
    441     return cch;
    442 }
Note: See TracChangeset for help on using the changeset viewer.