Ignore:
Timestamp:
Sep 2, 2000, 11:08:23 PM (25 years ago)
Author:
bird
Message:

Merged in the Grace branch. New Win32k!

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/win32k/ldr/myldrOpen.cpp

    r2838 r4164  
    1 /* $Id: myldrOpen.cpp,v 1.10 2000-02-21 09:24:01 bird Exp $
     1/* $Id: myldrOpen.cpp,v 1.11 2000-09-02 21:08:09 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
     20#define INCL_OS2KRNL_SEM
     21#define INCL_OS2KRNL_SEC
    1922
    2023/*******************************************************************************
     
    2326#include <os2.h>
    2427
     28#include "devSegDf.h"                   /* Win32k segment definitions. */
    2529#include "rmalloc.h"
    2630#include "malloc.h"
     
    2832#include <stdlib.h>
    2933#include <string.h>
     34#include <stdarg.h>
    3035
    3136#include "log.h"
     37#include "avl.h"
     38#include "options.h"
    3239#include <peexe.h>
    3340#include <exe386.h>
     41#include "elf.h"
    3442#include "OS2Krnl.h"
    3543#include "dev32.h"
     44#include "ldr.h"
     45#include "ldrCalls.h"
    3646#include "ModuleBase.h"
    3747#include "pe2lx.h"
    38 #include "elf.h"
    39 #include "avl.h"
    40 #include "ldr.h"
    41 #include "ldrCalls.h"
    42 #include "options.h"
    4348#include "myExecPgm.h"
    44 
    45 /*******************************************************************************
    46 *   Global Variables                                                           *
    47 *******************************************************************************/
    48 extern BOOL fQAppType;                  /* From LDRQAppType */
     49#include "env.h"
     50#include "vprintf.h"                    /* Make 100% sure we have va_start.  */
     51
     52
    4953
    5054/*******************************************************************************
    5155*   Internal Functions                                                         *
    5256*******************************************************************************/
    53 static unsigned getArgsLength(const char *pachArgs);
     57/* static */ APIRET     AddArgsToFront(int cArgs,  ...);
     58/* static */ APIRET     SetExecName(const char *pszExeName);
     59/* static */ APIRET     OpenPATH(PSFN phFile, char *pszFilename, PULONG pfl);
    5460
    5561
     
    5965 * @param     phFile       Pointer to file handler. Holds filehandle on output.
    6066 * @param     pszFilename  Pointer to filename.
    61  * @parma     param3       Probably some flags.
     67 * @parma     pfl          Pointer to some flags.
    6268 */
    63 ULONG LDRCALL myldrOpen(PSFN phFile, char *pszFilename, ULONG param3)
     69ULONG LDRCALL myldrOpen(PSFN phFile, PSZ pszFilename, PULONG pfl)
    6470{
    65     ULONG rc;
    66 
    67     /*
    68      * Try open the file (thats why this function is called anyway)
     71    static  int cNesting = 0;           /* This is an variable which hold the nesting */
     72                                        /* level of this function. This is useful     */
     73                                        /* when we call it recurcively.               */
     74                                        /* The maximum nesting level is currently 3.  */
     75                                        /* When the maximum depth has been reached    */
     76                                        /* we'll not intercept loading any longer!    */
     77    ULONG rc;                           /* Return value. */
     78
     79    /** @sketch
     80     * Try open the file (that's why this function is called anyway)
    6981     */
    70     rc = ldrOpen(phFile, pszFilename, param3);
    71 
    72     /* log sucesses */
     82    rc = ldrOpen(phFile, pszFilename, pfl);
    7383    if (rc == NO_ERROR)
    74         kprintf(("ldrOpen:  phFile=%#.4x, flags=%#.8x, pszFn=%s\n", *phFile, param3, pszFilename));
    75 
    76     /*
     84        kprintf(("myldrOpen-%d:  phFile=%#.4x, flags=%#.8x, pszFn=%s\n", cNesting, *phFile, pfl, pszFilename));
     85
     86
     87    /** @sketch
    7788     * Are we to intercept the loading?
    78      * - Only if open were succesful and one of the loaders are enabled.
     89     * - If open were successful.
     90     * - And Not too deep nesting.
     91     * - And that this isn't an unsupported load.
     92     * - And one of the loaders are enabled.
    7993     */
    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)
     94    if (rc == NO_ERROR
     95        && cNesting < 3
     96        && !isLdrStateLoadingUnsupported()
     97        && isAnyLoaderEnabled()
     98        )
     99    {
     100        union _u_ReadBufferPointers         /* Read buffer pointer(s). */
    96101        {
    97             kprintf(("ldrOpen: rmalloc(1024) failed\n"));
    98             return NO_ERROR;
     102            char               *pach;       /* Pointer to the buffer as char. */
     103            unsigned long      *pul;        /* Pointer to the buffer as unsigned long. */
     104            PIMAGE_DOS_HEADER   pMzHdr;     /* Use the buffer as a dosheader. */
     105            PIMAGE_NT_HEADERS   pNtHdrs;    /* Use the buffer as a NT header. */
     106        } u1;
     107        unsigned            cbFile;         /* Filesize (0xffffffff if call to SftFileSize failed - should _never_ happen though) */
     108        unsigned            cbRead;         /* Amount of the buffer which contains valid data. */
     109        char *              psz;            /* Multipurpose string pointer no.1. */
     110        char *              psz2;           /* Multipurpose string pointer no.2. */
     111        char *              psz3;           /* Multipurpose string pointer no.3. */
     112
     113        /** @sketch
     114         * Allocate read buffer from resident heap.
     115         * IF this fails THEN we'll simply return NO_ERROR.
     116         */
     117        u1.pach = (char*)rmalloc(640);
     118        if (u1.pach == NULL)
     119        {
     120            kprintf(("myldrOpen-%d: rmalloc(640) failed\n", cNesting));
     121            goto ret;
    99122        }
    100123
    101         /*
    102          * Try get the filesize
     124
     125        /** @sketch
     126         * Increment nesting level.
     127         */
     128        cNesting++;
     129
     130
     131        /** @sketch
     132         * Get the filesize. On failure filesize is set to ~0.
    103133         */
    104134        rc = SftFileSize(*phFile, (PULONG)SSToDS(&cbFile));
    105135        if (rc != NO_ERROR)
    106136        {
    107             kprintf(("ldrOpen: SftFileSize failed with rc=%d\n", rc));
     137            kprintf(("myldrOpen-%d: SftFileSize failed with rc=%d\n", cNesting, rc));
    108138            cbFile = (unsigned)~0;
    109139        }
    110140
    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)
     141
     142        /** @sketch
     143         *  Read the size of a DOS (ie. MZ) header.
     144         *  IF successful and more stuff in file THEN
     145         *      See if this is an recognizable module binary format:
     146         */
     147        cbRead = min(sizeof(IMAGE_DOS_HEADER), cbFile);
     148        rc = ldrRead(*phFile, 0UL, u1.pMzHdr, 0UL, cbRead, NULL);
     149        if (rc == NO_ERROR && cbRead < cbFile)
    117150        {
    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.
     151            /** @sketch
     152             * If LX header just give up at once.
    122153             */
    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
     154            if (u1.pMzHdr->e_magic == E32MAGIC)
     155                goto cleanup;
     156
     157            /** @sketch
     158             * IF PE or MZ header THEN
     159             */
     160            if (u1.pMzHdr->e_magic == IMAGE_DOS_SIGNATURE
     161                || u1.pNtHdrs->Signature == IMAGE_NT_SIGNATURE)
     162            {
     163                ULONG   offPe;          /* Offset to PE header. */
     164
     165                /** @sketch
     166                 * ---
     167                 * We now known that this is file has a MZ or a PE header. If it's
     168                 * a MZ header, we might end up with no "New" header or the "New"
     169                 * header might turn out to be a NE, LE, or LX header. I any of
     170                 * these non PE headers occur OS/2 will take care of it, we'll do nothing.
     171                 * ---
     172                 * IF PE loading is disable or MZ header and e_lfanew is invalid THEN
     173                 *     return (successfully) to the caller.
     174                 * ENDIF
     175                 * (Find the offset of the PE header while testing (offPe).)
    128176                 */
    129 
    130                 /* if PE loading is diable return to the caller */
    131                 if (options.fPE == FLAGS_PE_NOT)
     177                if (isPELoaderDisabled())
     178                    goto cleanup;
     179                if (u1.pMzHdr->e_magic == IMAGE_DOS_SIGNATURE)
    132180                {
    133                     rfree(pszBuffer);
    134                     return NO_ERROR;
     181                    offPe = u1.pMzHdr->e_lfanew;
     182                    if (offPe < sizeof(IMAGE_DOS_HEADER) || offPe > 0x04000000UL)
     183                        goto cleanup;
    135184                }
    136 
    137                 /*
    138                  * Read the PE header if it isn't what we allready have!
     185                else
     186                    offPe = 0;
     187
     188
     189                /** @sketch
     190                 * Read the PE header.
     191                 * If the read failes or not PE signature, there isn't anything for us to do.
    139192                 */
    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)
     193                rc = ldrRead(*phFile, offPe, u1.pach, 0UL, sizeof(IMAGE_NT_HEADERS), NULL);
     194                if (rc != NO_ERROR || u1.pNtHdrs->Signature != IMAGE_NT_SIGNATURE)
     195                    goto cleanup_noerror;
     196
     197
     198                /** @sketch
     199                 * PE signature found!
    149200                 */
    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                                  )
     201                kprintf(("myldrOpen-%d: PE executable...\n", cNesting));
     202
     203
     204                /** @sketch
     205                 * Use Pe2Lx?
     206                 *  - When Pe2Lx flag is set
     207                 *  - When the MIXED flag is set and the image isn't an executable
     208                 *    above the first 64MB private limit without relocations
     209                 */
     210                if (isPe2LxLoaderEnabled()
     211                    || (isMixedPeLoaderEnabled()
     212                        && ((u1.pNtHdrs->FileHeader.Characteristics & IMAGE_FILE_DLL)
     213                            || !(u1.pNtHdrs->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED)
     214                            || u1.pNtHdrs->OptionalHeader.ImageBase < 0x04000000UL /* 64MB */
    166215                            )
    167216                        )
    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)
     217                    )
     218                {   /** @sketch
     219                     *  Pe2Lx (Ring0 of course)
     220                     *      - Create a Pe2Lx class,
     221                     *      - initiate it
     222                     *      - Add the module to the module tree so we may find it later...
     223                     *      - Set the (file)handle state to 'our'.
     224                     *      - Set pExeModule to module pointer and loaderstate to our exe.
     225                     */
     226                    Pe2Lx * pPe2Lx = new Pe2Lx(*phFile);
     227                    if (pPe2Lx != NULL)
     228                    {
     229                        rc = pPe2Lx->init(pszFilename);
     230                        if (rc == NO_ERROR)
    177231                        {
    178                             rc = pPe2Lx->init(pszFilename);
     232                            kprintf(("myldrOpen-%d: Successfully init of Pe2Lx object.\n", cNesting));
     233                            rc = addModule(*phFile, NULL, MOD_TYPE_PE2LX, pPe2Lx);
    179234                            if (rc == NO_ERROR)
    180235                            {
    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"));
     236                                #pragma info(notrd)
     237                                SetState(*phFile, HSTATE_OUR);
     238                                #pragma info(restore)
     239                                if (pPe2Lx->isExe())
     240                                {
     241                                    setLdrStateLoadingOurEXE();
     242                                    pExeModule = getModuleBySFN(*phFile);
     243                                    #ifdef DEBUG
     244                                    if (pExeModule == NULL)
     245                                        kprintf(("myldrOpen-%d: getModuleBySFN failed when setting pExeModule! FATAL!\n", cNesting));
     246                                    #endif
     247                                }
    189248                            }
    190249                            else
    191                                 kprintf(("ldrOpen: Failed to init Pe2Lx object. rc=%d\n"));
    192                             if (rc != NO_ERROR)
    193                                 delete pPe2Lx;
     250                                kprintf(("myldrOpen-%d: Failed to add the module. rc=%d\n", cNesting));
    194251                        }
    195252                        else
    196                             kprintf(("ldrOpen: Failed to allocate Pe2Lx object.\n"));
     253                            kprintf(("myldrOpen-%d: Failed to init Pe2Lx object. rc=%d\n", cNesting));
     254                        if (rc != NO_ERROR)
     255                            delete pPe2Lx;
    197256                    }
    198257                    else
    199258                    {
    200                         /*
    201                          * Starting of PE.EXE enable?
     259                        kprintf(("myldrOpen-%d: Failed to allocate Pe2Lx object.\n", cNesting));
     260                        rc = ERROR_NOT_ENOUGH_MEMORY;
     261                    }
     262
     263                    goto cleanup;
     264                }
     265
     266
     267                /** @sketch
     268                 *  Using PE.EXE to start EXE?
     269                 *      - When the file is an EXE file and PE.EXE is enabled.
     270                 */
     271                if ((u1.pNtHdrs->FileHeader.Characteristics & IMAGE_FILE_DLL) == 0UL
     272                    && (options.fPE == FLAGS_PE_PE || options.fPE == FLAGS_PE_MIXED)
     273                    && (isLdrStateExecPgm() || isLdrStateQAppType())
     274                    )
     275                {
     276                    /** @sketch
     277                     * PE.EXE:
     278                     * Find pe.exe - look in current directory and thru the PATH.
     279                     * Note! We use the read buffer (u1.p*) as a storage for the
     280                     * pe.exe filename and path.
     281                     */
     282                    kprintf(("myldrOpen-%d: pe.exe - opening\n", cNesting));
     283                    ldrClose(*phFile);
     284                    strcpy(u1.pach, "PE.EXE");
     285                    rc = ldrOpen(phFile, u1.pach, pfl); /* This isn't recusive! */
     286                    if (rc != NO_ERROR)
     287                        rc = OpenPATH(phFile, u1.pach, pfl);
     288                    if (rc == NO_ERROR)
     289                    {
     290                        /** @sketch
     291                         * If we're in tkExecPgm state we'll have to shuffle the parameters
     292                         * and executable filename tkExecPgm were called with.
     293                         * If not tkExecPgm we can't do anything about parameters (and there is
     294                         * probably nothing to do either).
    202295                         */
    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;
     296                        kprintf(("myldrOpen-%d: pe.exe - %s\n", cNesting, u1.pach));
     297                        if (isLdrStateExecPgm() && fTkExecPgm)
     298                        {
     299                            rc = AddArgsToFront(2, ldrpFileNameBuf, achTkExecPgmFilename);
     300                            if (rc == NO_ERROR)
     301                            {
     302                                rc = SetExecName(ldrpFileNameBuf);
     303                                if (rc != NO_ERROR)
     304                                    kprintf(("myldrOpen-%d: pe.exe - failed to set pe.exe as execname. rc=%d\n", cNesting));
     305                            }
     306                            else
     307                                kprintf(("myldrOpen-%d: pe.exe - failed to add programname as argument. rc=%d\n", cNesting, rc));
     308                            goto cleanup_noerror;
    213309                        }
    214310                    }
     311                    else
     312                        kprintf(("myldrOpen-%d: pe.exe - couldn't find/open pe.exe\n", cNesting));
    215313                }
    216                 rfree(pszBuffer);
    217                 return NO_ERROR;
     314                goto cleanup;
    218315            }
    219             else
     316            /** @sketch End of PE Loading. */
     317
     318
     319            /** @sketch
     320             * ELF image?
     321             */
     322            if (*u1.pul == ELFMAGICLSB)
    220323            {
     324                if (isELFDisabled())
     325                    goto cleanup_noerror;
     326
    221327                /*
    222                  * ELF image?
     328                 * ELF signature found.
    223329                 */
    224                 if (pach[0] == ELFMAG0 && pach[1] == ELFMAG1 && pach[2] == ELFMAG2 && pach[3] == ELFMAG3)
     330                kprintf(("myldrOpen-%d: ELF image! - not implemented yet!\n", cNesting));
     331
     332                /*
     333                 * Do nothing more yet. NEED AN ELF LOADER!!!
     334                 */
     335                goto cleanup;
     336            }
     337
     338
     339            /** @sketch
     340             * Java image?
     341             */
     342            if (*u1.pul == 0xBEBAFECAUL) //CAh FEh BAh BEh
     343            {
     344                char *pszName = NULL;
     345                int   cchName;
     346
     347                if (isJAVADisabled())
     348                    goto cleanup_noerror;
     349
     350                /** @sketch
     351                 * Java signature found.
     352                 * Copy the name to a temporary buffer. (only if necessary)
     353                 * Remove the extention (.class) and insert a space between the name and the path.
     354                 *  (This is the needed processing of the class filename to make it a classpath
     355                 *   entry (path) and a class name (filename).)
     356                 * Try find the java executor in current dir or PATH: java.exe
     357                 */
     358                kprintf(("myldrOpen-%d: Jave image!\n", cNesting));
     359
     360                if (isLdrStateExecPgm() && fTkExecPgm)
    225361                {
    226                     /*
    227                      * ELF signature found.
     362                    /* Ooops we had to get the file name from the MFT. ldrpFileNameBuf is allways uppercased... */
     363                    /* MFT seems to hold uppercased filenames! ARG! But (by pure luck?) achTkExecPgmArguments is
     364                     * not uppercased (yet). Nothing could be simpler!
    228365                     */
    229                     kprintf(("ldrOpen: ELF executable! - not implemented yet!\n"));
    230 
    231                     /*
    232                      * Do nothing more yet. NEED AN ELF LOADER!!!
     366                    #if 1
     367                    psz3 = achTkExecPgmArguments;
     368                    #elif 0
     369                    psz3 = SecPathFromSFN(*phFile);
     370                    if (psz3 == NULL)
     371                        psz3 = ldrpFileNameBuf;
     372                    #else
     373                    psz3 = ldrpFileNameBuf;
     374                    #endif
     375                    cchName = strlen(psz3);
     376                    pszName = (char*)rmalloc(cchName + 2);
     377                    if (pszName == NULL)
     378                    {
     379                        rc = ERROR_NOT_ENOUGH_MEMORY;
     380                        goto cleanup;
     381                    }
     382                    memcpy(pszName, psz3, cchName+1);
     383
     384                    psz = pszName + strlen(pszName) - 1;
     385                    while (psz > pszName && *psz != '.' && *psz != '\\' && *psz != '/')
     386                        psz--;
     387                    if (*psz == '.')
     388                    {
     389                        cchName = psz - pszName;
     390                        *psz-- = '\0';
     391                        while (psz > pszName && *psz != '\\' && *psz != '/')
     392                            psz--;
     393
     394                        /* check for root and evt. make room for an extra slash. */
     395                        if (psz - pszName == 2)
     396                        {
     397                            memmove(psz + 1, psz, cchName - 1);
     398                            *psz++ = '\\';
     399                        }
     400                    }
     401                    /* check if no path */
     402                    if (psz == pszName)
     403                        memmove(pszName + 1, pszName, cchName + 1);
     404                    *psz = ' ';
     405                }
     406
     407                ldrClose(*phFile);
     408                rc = ldrOpen(phFile, ".\\JAVA.EXE", pfl);
     409                if (rc != NO_ERROR)
     410                    rc = OpenPATH(phFile, "JAVA.EXE", pfl);
     411                if (rc == NO_ERROR)
     412                {
     413                    kprintf(("myldrOpen-%d: java - %s\n", cNesting, ldrpFileNameBuf));
     414
     415                    /** @sketch
     416                     * To be able to execute any given class name we'll have to pass in the
     417                     * directory as -classpath. But -classpath seems to override the default
     418                     * and environmental CLASSPATHs. So, we'll have to pass in the value of
     419                     * the CLASSPATH env.var. or generate the default class path (what ever that is).
     420                     *
    233421                     */
    234                     rfree(pszBuffer);
    235                     return NO_ERROR;
     422                    if (isLdrStateExecPgm() && fTkExecPgm)
     423                    {
     424                        psz = u1.pach;
     425
     426                        /*
     427                         * Get classpath and add it as a parameter
     428                         */
     429                        strcpy(u1.pach, "-classpath ");
     430                        psz = u1.pach + strlen(u1.pach);
     431
     432                        psz3 = (char*)ScanEnv(GetEnv(TRUE), "CLASSPATH");
     433                        if (psz3 != NULL)
     434                        {   /* environment variable set */
     435                            if (strlen(psz3) > 640 - 11 - 1 - cchName) //check for overflow
     436                            {   // TODO? should reallocate...
     437                                memcpy(psz, psz3, 640 - 11 - 1 - cchName);
     438                                psz[640 - 11 - 1 - cchName] = '\0';
     439                            }
     440                            else
     441                                strcpy(psz, psz3);
     442                            psz += strlen(psz);
     443                        }
     444                        else
     445                        {
     446                            /* Make default classpath by taking the java.exe path + '..\lib\classes.zip' */
     447                            strcpy(psz, ldrpFileNameBuf);
     448                            psz3 = psz + strlen(psz) - 1;
     449                            while (psz3 > psz && *psz3 != '\\' && *psz3 != '/')
     450                                psz3--;
     451                            strcpy(++psz3, "..\\lib\\classes.zip");
     452                            psz = psz3 + strlen(psz3);
     453                        }
     454
     455                        /*
     456                         * Add the class directory (as the last classpath entry) and the class name.
     457                         * (Note. I may happen that there is no directory, but that don't matter
     458                         *        a space is allways preceding the class name.)
     459                         */
     460                        *psz++ = ';';
     461                        strcpy(psz, pszName);
     462                        if (pszName != NULL)
     463                            rfree(pszName);
     464
     465                        /*
     466                         * Setup JAVA.EXE as executable with the parameters we've build.
     467                         */
     468                        rc = AddArgsToFront(2, ldrpFileNameBuf, u1.pach);
     469                        kprintf(("myldrOpen-%d: java - Exe: %s  Args: %s\n", cNesting, ldrpFileNameBuf, u1.pach));
     470                        if (rc == NO_ERROR)
     471                        {
     472                            rc = SetExecName(ldrpFileNameBuf);
     473                            if (rc != NO_ERROR)
     474                                kprintf(("myldrOpen-%d: java - failed to set java.exe as execname. rc=%d\n", cNesting, rc));
     475                        }
     476                        else
     477                            kprintf(("myldrOpen-%d: java - failed to setup the parameters. rc=%d\n", cNesting, rc));
     478
     479                        goto cleanup_noerror;
     480                    }
    236481                }
     482                else
     483                    kprintf(("myldrOpen-%d: java - couldn't find/open java.exe\n", cNesting));
     484
     485
     486                /** @sketch
     487                 *  End of Java loading. (return)
     488                 */
     489                if (pszName != NULL)
     490                    rfree(pszName);
     491                goto cleanup;
    237492            }
     493
    238494        }
     495        else
     496        {
     497            /** @sketch
     498             *  ELSE - the reading size of a DOS header failed or file is smaller than the dos header.
     499             *      IF read failed or filesize is less than 4 bytes THEN
     500             *          return no_error to the caller.
     501             *      ENDIF
     502             */
     503            #ifdef DEBUG
     504            if (rc != NO_ERROR)
     505            {
     506                kprintf(("myldrOpen-%d: ldrRead failed cbRead=%d, cbFile=%d,  rc=%d\n", cNesting, cbRead, cbFile, rc));
     507                goto cleanup_noerror;
     508            }
     509            if (cbRead < 4)
     510            {
     511                kprintf(("myldrOpen-%d: File too small! cbFile=%d\n", cNesting, cbFile));
     512                goto cleanup_noerror;
     513            }
     514            #else
     515            if (rc != NO_ERROR || cbRead < 4) //just forget files less than 4 bytes!
     516                goto cleanup_noerror;
     517            #endif
     518        }
     519        /** @sketch ENDIF (dos header read) */
     520
     521
    239522
    240523        /*
    241          * Only unreconized files and readerror passes this point!
     524         * Only unreconized files passes this point!
    242525         *
    243526         * * Fileformats with lower priority should reside here. *
     
    245528         */
    246529
    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)
     530        /** @sketch
     531         *  UNIX styled script?
     532         *      - Starts with a hash (#)
     533         *      - And we're loading an EXE
     534         *      - And we're either in QAppType or ExecPgm state.
     535         *      - And that a bang (!) is the first char after the hash (ignoring blanks).
     536         */
     537        if (*u1.pach == '#'
     538            && isLdrStateLoadingEXE()
     539            && (isLdrStateQAppType() || isLdrStateExecPgm())
     540            )
    252541        {
    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         {
     542            if (isUNIXScriptDisabled())
     543                goto cleanup_noerror;
    264544            /*
    265              * UNIX styled script?
    266              * FIXME! Must be more than 64 bytes long?
    267              *        No options!
    268              *        Firstline < 64 bytes!
     545             * Look for a bang (!). Tabs and spaces are skipped, anything else result in error.
    269546             */
    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)
     547            psz = u1.pach + 1;
     548            while ((*psz == ' ' || *psz == '\t') && psz - u1.pach < cbRead)
     549                psz++;
     550            if (*psz == '!')
    274551            {
    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
     552                /** @sketch Found UNIX styled script! */
     553
     554                /** @sketch
     555                 * Read more of the script if necessary. (max is 256 chars (- Linux max is 127))
     556                 * Terminate the string read from the file to make sure with stop somewhere!
    283557                 */
    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')
     558                if (cbRead < cbFile /*&& cbRead != 256*/)
    291559                {
    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
     560                    cbRead = min(256, cbFile);
     561                    rc = ldrRead(*phFile, 0UL, u1.pach, 0UL, cbRead, NULL);
     562                }
     563                u1.pach[cbRead] = '\0';
     564
     565                if (rc == NO_ERROR)
     566                {
     567                    /** @sketch
     568                     * Parse out filename and optional arguments (if any).
     569                     * The result of the parsing is that:
     570                     *      psz will point at the executable name.
     571                     *      psz2 will point at the arguments.
     572                     *  Both strings are trimmed.
    299573                     */
    300                     pszEnd = pszStart;
    301                     kprintf(("ldrOpen: script debug 3\n"));
    302                     while (*pszEnd != '\0' && *pszEnd != '\r' && *pszEnd != '\n')
     574                    psz++;                                                  /* psz points to the bang, skip it. */
     575                    while (*psz == ' ' || *psz == '\t')                     /* skip blanks after bang */
     576                        psz++;
     577                    if (*psz == '\r' || *psz == '\n' || *psz == '\0')       /* End-of-line? */
    303578                    {
    304                         if (fFirst && (*pszEnd == ' ' || *pszEnd == '\t'))
     579                        kprintf(("myldrOpen-%d: script no executable name.\n", cNesting));
     580                        goto cleanup_noerror; /* other error code? */
     581                    }
     582                    psz2 = psz + 1;                                         /* Not end-of-line, so add 1 before searching for args. */
     583                    while (*psz2 != '\0' && *psz2 != '\n' && *psz2 != '\r'  /* skip executable name. */
     584                           && *psz2 != ' ' && *psz2 != '\t')
     585                        psz2++;
     586                    while (*psz2 == ' ' || *psz2 == '\t')                    /* skip blanks after executable - pad them with '\0'! */
     587                        *psz2++ = '\0';
     588
     589                    psz3 = psz2;
     590                    while (*psz3 != '\n' && *psz3 != '\r' && *psz3 != '\0') /* find end of parameters and terminate the string. */
     591                        psz3++;
     592                    *psz3 = '\0';
     593                    while (psz3 >= psz2 && (*psz3 == '\0' || *psz3 == ' ' || *psz3 == '\t')) /* trim args */
     594                        *psz3-- = '\0';
     595
     596
     597                    /** @sketch
     598                     *  IF tkExecPgm THEN
     599                     *      Correct parameters - ie. add exec name (as argv[0]),
     600                     *        arguments (psz2) as argv[1+], old exec name, and finally
     601                     *        the existing parameters (current argv[1+]).
     602                     *      Set the executable name.
     603                     *  ENDIF
     604                     *  Open the new executable file recursively. (psz)
     605                     */
     606                    if (isLdrStateExecPgm())
     607                    {
     608                        if (*psz2)
     609                           rc = AddArgsToFront(3, psz, psz2, achTkExecPgmFilename);
     610                        else
     611                           rc = AddArgsToFront(2, psz, achTkExecPgmFilename);
     612                        if (rc != NO_ERROR)
    305613                        {
    306                             *pszEnd = '\0';
    307                             fFirst = FALSE;
    308                             if (pszEnd[1] == '\0' || pszEnd[1] == '\r' || pszEnd[1] == '\n')
    309                                 fFirst = TRUE;
     614                            kprintf(("myldrOpen-%d: AddArgsToFront failed with rc=%d\n", cNesting));
     615                            goto cleanup_noerror;
    310616                        }
    311 
    312                         /* next */
    313                         pszEnd++;
    314                         cchToAdd++;
     617                        rc = SetExecName(psz);
     618                        if (rc != NO_ERROR)
     619                            kprintf(("myldrOpen-%d: SetExecName failed with rc=%d\n", cNesting));
    315620                    }
    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)
     621                    ldrClose(*phFile);
     622                    rc = myldrOpen(phFile, psz, pfl);
     623                    if (rc != NO_ERROR)
    324624                    {
    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)
     625                        psz2 = psz + strlen(psz);
     626                        if (psz + 4 >= psz2 || strcmp(psz2 - 4, ".EXE") != 0)
    336627                        {
    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                             }
     628                            strcpy(psz2, ".EXE");
     629                            rc = myldrOpen(phFile, psz, pfl);
     630                            *psz2 = '\0';
    397631                        }
    398632                        else
     633                            psz2 = NULL;
     634
     635                        //should we search the PATH??? For a starting, we'll do it.
     636                        if (rc != NO_ERROR
     637                            && (rc = OpenPATH(phFile, psz, pfl)) != NO_ERROR
     638                            && psz2 != NULL)
    399639                        {
    400                             kprintf(("ldrOpen: QueryBufferPointerFromFilename failed.\n"));
    401                             rc = ERROR_BAD_EXE_FORMAT; /*?*/
     640                            *psz2 = '.';
     641                            rc = OpenPATH(phFile, psz, pfl);
    402642                        }
    403643                    }
     
    405645                else
    406646                {
    407                     kprintf(("ldrOpen: no interpereter on the first line.\n"));
    408                     rc = ERROR_BAD_EXE_FORMAT; /*?*/
     647                    kprintf(("myldrOpen-%d: script - failed to read more of the script!, rc=%d cbRead=%d cbFile=%d.\n",
     648                             cNesting, rc, cbRead, cbFile));
    409649                }
     650
     651                goto cleanup;
    410652            }
    411653            else
    412654            {
    413                 kprintf(("ldrOpen: read of min(cbFile, 256) = %d failed, rc = %d\n", cchRead, rc));
     655                kprintf(("myldrOpen-%d: script - hash found but no bang (!).\n", cNesting));
    414656            }
    415         } /* else inn other formats here. */
    416         rfree(pszBuffer);
    417     }
     657        } /**@sketch ENDIF - UNIX styled script. */
     658
     659
     660
     661        /** @sketch
     662         *  REXX script?
     663         *      - Starts with a REXX start comment ('/','*')
     664         *      - And we're loading an EXE
     665         *      - And we're either in QAppType or ExecPgm state.
     666         *      - Extention:
     667         *          .RX and .REX are known to be pure REXX scripts.
     668         *          While .CMD has to invoked used the commandline OS2_SHELL or COMSPEC variable.
     669         */
     670        psz2 = pszFilename + strlen(pszFilename) - 1;
     671        while (psz2 > pszFilename && *psz2 != '.')
     672            psz2--;
     673        if (*psz2 == '.'
     674            && *u1.pach == '/' && u1.pach[1] == '*'
     675            && isLdrStateLoadingEXE()
     676            && (isLdrStateQAppType() || isLdrStateExecPgm())
     677            && (stricmp(psz2, ".RX") == 0 || stricmp(psz2, ".REX") == 0)
     678            )
     679        {
     680            if (isREXXScriptDisabled())
     681                goto cleanup_noerror;
     682
     683            /** @sketch
     684             * Found REXX styled script!
     685             * Find the REXX interpreter. We'll use kRx.exe to execute the REXX scripts.
     686             * (This interpreter could be embedded as a child of ModuleBase as it turned out
     687             * to be quite small about 700 bytes.)
     688             */
     689            kprintf(("myldrOpen-%d: Found REXX script\n", cNesting));
     690            ldrClose(*phFile);
     691            psz = "KRX.EXE";
     692            rc = ldrOpen(phFile, psz, pfl);
     693            if (rc != NO_ERROR)
     694                rc = OpenPATH(phFile, psz, pfl);
     695
     696            /** @sketch
     697             *  IF tkExecPgm THEN
     698             *      Correct parameters - ie. add exec name (as argv[0]), old exec name,
     699             *        and finally the existing parameters (current argv[1+]).
     700             *      Set the executable name.
     701             *  ENDIF
     702             */
     703             if (rc == NO_ERROR && isLdrStateExecPgm())
     704             {
     705                 rc = AddArgsToFront(2, ldrpFileNameBuf, achTkExecPgmFilename);
     706                 if (rc != NO_ERROR)
     707                 {
     708                     kprintf(("myldrOpen-%d: AddArgsToFront failed with rc=%d\n", cNesting));
     709                     goto cleanup_noerror;
     710                 }
     711                 rc = SetExecName(ldrpFileNameBuf);
     712                 if (rc != NO_ERROR)
     713                     kprintf(("myldrOpen-%d: SetExecName failed with rc=%d\n", cNesting));
     714
     715                 goto cleanup_noerror;
     716             }
     717             goto cleanup;
     718        } /**@sketch ENDIF - REXX styled script. */
     719
     720
     721        /*
     722         * Cleanup with rc set to NO_ERROR.
     723         */
     724    cleanup_noerror:
     725        rc = NO_ERROR;
     726
     727        /*
     728         * Cleanup without having rc set to NO_ERROR.
     729         * Decrement the nesting count.
     730         */
     731    cleanup:
     732        rfree(u1.pach);
     733        cNesting--;
     734    }
     735    #ifdef DEBUG
     736    else if (cNesting >= 3)
     737        kprintf(("myldrOpen-%d: cNesting = %d, which is too deep!\n", cNesting, cNesting));
     738    #endif
     739
     740ret:
     741    /** @sketch
     742     *  Return rc.
     743     */
    418744    return rc;
    419745}
     
    421747
    422748/**
    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.
     749 * Adds new arguments to the front of the startup arguments for the program about to be
     750 * executed.
     751 *
     752 * @returns   OS/2 return code.
     753 * @param     cArgs     Count of arguments to add. At least 1!!!
     754 * @param     ...       Pointers to the arguments to add.
     755 *                      The first argument have to be the executable name. This have to the
     756 *                        the only argument in the first string.
     757 *                      The other arguements are space separated, so you could add a bunch
     758 *                        of arguments in a single string!
     759 *                      The last argument should be the old first parameter if this is to be
     760 *                        preserved. The old first parameter is overwritten since it's
     761 *                        normally the executable name.
     762 *
     763 * @status    completly implemented.
    427764 * @author    knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
     765 * @remark    Implementation note:
     766 *  The arguments convention is as follows:
     767 *      First argument, which should be the executable name, is terminated with a '\0'.
     768 *        It starts at offset 0 into the argument buffer, of course.
     769 *      All other arguemnts are separated by a space and follows the immediately after the
     770 *        first argument.
     771 *      The arguments are terminated by a double nulltermination: '\0\0'.
    428772 */
    429 static unsigned getArgsLength(const char *pachArgs)
     773APIRET AddArgsToFront(int cArgs,  ...)
    430774{
    431     unsigned    cch = 1;
    432     const char *psz = pachArgs;
    433 
     775    va_list     vaarg;                  /* Variable length argument list. */
     776    int         cchOldArgs;             /* Length of the old arguments (including the first argument). */
     777                                        /* cchOldArgs = 1 means no arguments. It don't include the very last '\0' */
     778                                        /* (remember argumets are terminated with two '\0's). */
     779    int         iSecondArg;             /* Index of the second argument. (Used to skip the first argument.) */
     780                                        /* Used first on the original arguments and them when adding the first */
     781                                        /* new argument. */
     782    int         cchNewArgs;             /* Length of the new arguments to be inserted. */
     783    int         i;                      /* Loop variable. Current function argument. */
     784    char *      psz;                    /* General string pointer. */
     785
     786
     787    /** @sketch
     788     *  Assert that we're in the right state.
     789     *  Calc the length of the existing parameters.
     790     *  Calc the length of the new arguments to determin.
     791     *  Assert that the new arguments have length > 0.
     792     */
     793    #ifdef DEBUG
     794    if (!isLdrStateExecPgm())
     795    {
     796        kprintf(("AddArgsToFront: not in tkExecPgm state.\n"));
     797        return ERROR_INVALID_PARAMETER;
     798    }
     799    #endif
     800    if (!fTkExecPgm)
     801    {
     802        kprintf(("AddArgsToFront: called when not in tkExecPgm data is invalid!\n"));
     803        return ERROR_INVALID_PARAMETER;
     804    }
     805
     806    iSecondArg = strlen(&achTkExecPgmArguments[0]) + 1;
     807    psz = &achTkExecPgmArguments[iSecondArg];
    434808    while (*psz != '\0')
    435     {
    436         register unsigned cch2 = strlen(psz);
    437         cch += cch2;
    438         psz += cch2 + 1;
    439     }
    440 
    441     return cch;
     809        psz += strlen(psz) + 1;
     810    cchOldArgs = psz - &achTkExecPgmArguments[iSecondArg];
     811
     812    va_start(vaarg, cArgs);
     813    for (cchNewArgs = i = 0; i < cArgs; i++)
     814        cchNewArgs += strlen(va_arg(vaarg, char *)) + 1; /* 1 is for space or '\0'. */
     815    va_end(vaarg);
     816    #ifdef DEBUG
     817    if (cchNewArgs == 0)
     818    {
     819        kprintf(("AddArgsToFront: the size of the arguments to add is zero!\n"));
     820        return ERROR_INVALID_PARAMETER;
     821    }
     822    #endif
     823
     824
     825    /** @sketch
     826     *  Check if we have enough room for the new arguments. Fail if not enough.
     827     *  Move the existing arguments to make room for the new ones.
     828     *    !IMPORTANT! The first existing arguments (executable name) is skipped !IMPORTANT!
     829     *    !IMPORTANT! in this move as this have to be re-added in this call!    !IMPORTANT!
     830     */
     831    if (cchOldArgs + cchNewArgs + 1 > CCHARGUMENTS)
     832    {
     833        kprintf(("AddArgsToFront: argument buffer is too small to hold the arguments to add, cchOldArgs=%d, cchNewArgs=%d\n",
     834                 cchOldArgs, cchNewArgs));
     835        return ERROR_BAD_ARGUMENTS;
     836    }
     837
     838    if (cchOldArgs > 0)
     839    {
     840        memmove(&achTkExecPgmArguments[cchNewArgs], &achTkExecPgmArguments[iSecondArg],
     841                cchOldArgs + 1);
     842    }
     843    else
     844        achTkExecPgmArguments[cchNewArgs] = '\0';
     845
     846
     847    /** @sketch
     848     *  Copy new arguments.
     849     *  Since the first argument is special case we'll do it separately. (Uses '\0' as separator.)
     850     *    We assume that the entire first argument passed into this function should be the first argument!
     851     *    (This don't have to be true for the other arguments since these are space separated. You could
     852     *     pass in more than argument in a single string.)
     853     *  Loop thru the rest of the new arguments and add them with space as separator.
     854     */
     855    va_start(vaarg, cArgs);
     856    psz = va_arg(vaarg, char *);
     857    memcpy(&achTkExecPgmArguments[0], psz, (i = strlen(psz) + 1));
     858    psz = &achTkExecPgmArguments[i];
     859
     860    for (i = 1; i < cArgs; i++)
     861    {
     862        if (i > 1) *psz++ = ' ';    //Add space if not second argument.
     863        strcpy(psz, va_arg(vaarg, char *));
     864        psz += strlen(psz);
     865    }
     866    va_end(vaarg);
     867    if (cchOldArgs > 0) *psz++ = ' ';    //Add space if old arguments
     868
     869    #ifdef DEBUG /* assertion */
     870    if (psz != &achTkExecPgmArguments[cchNewArgs])
     871    {
     872        kprintf(("AddArgsToFront: !Assertion failed! psz didn't end up where it should! (psz -> %d should be %d)\n",
     873                 psz - &achTkExecPgmArguments[0], cchNewArgs));
     874        if (cchOldArgs <= 1)
     875            psz[0] = psz[1] = '\0';
     876    }
     877    #endif
     878
     879    return NO_ERROR;
    442880}
     881
     882
     883/**
     884 * Sets the executable name of the module.
     885 * This function is normally invoked after a different executable than the one requested was
     886 * opened. It does _NOT_ set the new executable name as the first argument, since it is more
     887 * convenient to this while calling AddArgsToFront to add other arguments.
     888 *
     889 * @returns   OS/2 return code.
     890 * @param     pszExecName   Pointer to new executable name.
     891 * @status    completly implemented.
     892 * @author    knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
     893 * @remark    .
     894 */
     895APIRET SetExecName(const char *pszExecName)
     896{
     897    #ifdef DEBUG
     898    int cch;
     899    cch = strlen(pszExecName);
     900    if (cch > CCHMAXPATH)
     901    {
     902        kprintf(("ChangeExecName: filename is too long! cch=%d. name=%s\n", cch, pszExecName));
     903        return ERROR_FILENAME_EXCED_RANGE;
     904    }
     905    if (!isLdrStateExecPgm())
     906    {
     907        kprintf(("ChangeExecName: called when not in tkExecPgm state!!! FATAL ERROR!\n"));
     908        return ERROR_INVALID_PARAMETER;
     909    }
     910    #endif
     911    if (!fTkExecPgm)
     912    {
     913        kprintf(("ChangeExecName: called when not in tkExecPgm data is invalid!!! FATAL ERROR!\n"));
     914        return ERROR_INVALID_PARAMETER;
     915    }
     916
     917    strcpy(achTkExecPgmFilename, pszExecName);
     918
     919    return 0;
     920}
     921
     922
     923/**
     924 * Opens a file using the PATH environment variable of the current process.
     925 * @returns   OS2 return code.
     926 * @param     phFile        Pointer to filehandle. The filehandle is set to the SFN for the opened
     927 *                          file on successful return.
     928 *                          The filehandle is 0 on failure.
     929 * @param     pszFilename   Pointer to filename buffer. This will hold the filename on input.
     930 *                          On successful return it holds the filepath found.
     931 *                          On failiure it's undefined.
     932 * @param     pfl           Some flags set by ldrOpen.
     933 * @sketch    stub
     934 * @author    knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
     935 * @remark
     936 */
     937APIRET OpenPATH(PSFN phFile, char *pszFilename, PULONG pfl)
     938{
     939    APIRET      rc;
     940    USHORT      TCBFailErr_save;
     941    int         cchFile;                /* Filename length + 1. */
     942    const char *pszFile;                /* Pointer to filename portion. */
     943    const char *pszPath = ScanEnv(GetEnv(FALSE), "PATH"); /* Current Process environment? */
     944
     945    /**@sketch
     946     *  No PATH environment.
     947     */
     948    if (pszPath == NULL)
     949        return ERROR_FILE_NOT_FOUND;
     950
     951    /**@sketch
     952     * Skip any paths in the filename.
     953     */
     954    pszFile = pszFilename + (cchFile = strlen(pszFilename));
     955    while (pszFile >= pszFilename && *pszFile != '\\' && *pszFile != '/')
     956        pszFile--;
     957    cchFile -= pszFile - pszFilename;
     958    pszFile++;
     959
     960    /**@sketch
     961     * We'll have to save the TCBFailErr since we don't want to cause
     962     * Hard Errors while searching invalid paths, etc. (ldrOpenPath does this!)
     963     */
     964    TCBFailErr_save = tcbGetTCBFailErr(tcbGetCur());
     965
     966    /**@ sketch
     967     *  Loop thru the PATH trying to open the specified file in each
     968     *  directory.
     969     */
     970    while (*pszPath != '\0')
     971    {
     972        const char *  pszNext;
     973        int           cchPath;
     974        char          chEnd;
     975        register char ch;
     976
     977        /*
     978         * Find end of this path.
     979         */
     980        while (*pszPath == ' ') pszPath++; //skip leading spaces.
     981        if (*pszPath == '"')
     982        {
     983            chEnd = '"';
     984            pszPath++;
     985        }
     986        else
     987            chEnd = ';';
     988        pszNext = pszPath;
     989        while ((ch = *pszNext) != chEnd && ch != '\0')
     990            pszNext++;
     991
     992        cchPath = pszNext - pszPath;
     993        if (chEnd == '"')
     994        {
     995            /* Skip anything between the " and the ; or string end. */
     996            while ((ch = *pszNext) != ';' && ch != '\0')
     997                pszNext++;
     998        }
     999        else
     1000        {
     1001            /* Trim the string. */
     1002            while (cchPath > 0 && pszPath[cchPath-1] == ' ') //??
     1003                cchPath--;
     1004        }
     1005
     1006        /*
     1007         *  No length? No Path! Or path'\'filename too long? => Next
     1008         */
     1009        if (cchPath > 0 && cchPath + cchFile + 1 < CCHMAXPATH)
     1010        {
     1011            static char     achFilename[CCHMAXPATH];
     1012            /*
     1013             * Build filename
     1014             */
     1015            memcpy(achFilename, pszPath, cchPath);
     1016            if ((ch = achFilename[cchPath - 1]) == '\\' || ch == '/')
     1017                cchPath--;
     1018            else
     1019                achFilename[cchPath] = '\\';
     1020             memcpy(&achFilename[cchPath + 1], pszFile, cchFile); /* cchFile = length + 1; hence we copy the terminator too. */
     1021
     1022            /*
     1023             * Try open the file.
     1024             */
     1025            rc = myldrOpen(phFile, achFilename, pfl);
     1026            switch (rc)
     1027            {
     1028                case ERROR_FILE_NOT_FOUND:          case ERROR_PATH_NOT_FOUND:          case ERROR_ACCESS_DENIED:           case ERROR_INVALID_ACCESS:
     1029                case ERROR_INVALID_DRIVE:           case ERROR_NOT_DOS_DISK:            case ERROR_REM_NOT_LIST:            case ERROR_BAD_NETPATH:
     1030                case ERROR_NETWORK_BUSY:            case ERROR_DEV_NOT_EXIST:           case ERROR_TOO_MANY_CMDS:           case ERROR_ADAP_HDW_ERR:
     1031                case ERROR_UNEXP_NET_ERR:           case ERROR_BAD_REM_ADAP:            case ERROR_NETNAME_DELETED:         case ERROR_BAD_DEV_TYPE:
     1032                case ERROR_NETWORK_ACCESS_DENIED:   case ERROR_BAD_NET_NAME:            case ERROR_TOO_MANY_SESS:           case ERROR_REQ_NOT_ACCEP:
     1033                case ERROR_INVALID_PASSWORD:        case ERROR_OPEN_FAILED:             case ERROR_INVALID_NAME:            case ERROR_FILENAME_EXCED_RANGE:
     1034                case ERROR_VC_DISCONNECTED:
     1035                    break;
     1036
     1037                case NO_ERROR:
     1038                    strcpy(pszFilename, achFilename);
     1039                default:
     1040                    tcbSetTCBFailErr(tcbGetCur(), TCBFailErr_save);
     1041                    return rc;
     1042            }
     1043        }
     1044        #ifdef DEBUG
     1045        else if (cchPath > 0)   kprintf(("OpenPATH: Path component is too long\n"));
     1046        #endif
     1047
     1048        /*
     1049         * Next
     1050         */
     1051        if (*pszNext == '\0')
     1052            break;
     1053        pszPath = pszNext + 1;
     1054    }
     1055
     1056
     1057    /*
     1058     * File is not found.
     1059     */
     1060    *phFile = 0;
     1061    tcbSetTCBFailErr(tcbGetCur(), TCBFailErr_save);
     1062    return ERROR_FILE_NOT_FOUND;
     1063}
Note: See TracChangeset for help on using the changeset viewer.