Ignore:
Timestamp:
Feb 20, 2000, 5:27:24 AM (26 years ago)
Author:
bird
Message:

16-bit imports and import of global variables.
(But there are some problems left)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/win32k/dev32/d32init.c

    r2831 r2832  
    1 /* $Id: d32init.c,v 1.11 2000-02-19 23:51:59 bird Exp $
     1/* $Id: d32init.c,v 1.12 2000-02-20 04:27:23 bird Exp $
    22 *
    33 * d32init.c - 32-bits init routines.
     
    1414#define MAXSIZE_PROLOG 0x10             /* Note that this must be synced with */
    1515                                        /* the one used in calltab.asm.       */
    16 #define static
     16#define static                          /* just to make all symbols visible in the kernel debugger.  */
     17
    1718
    1819#define INCL_DOSERRORS
    1920#define INCL_NOPMAPI
    2021#define LDR_INCL_INITONLY
    21 
    2222
    2323/*******************************************************************************
     
    4444*******************************************************************************/
    4545static ULONG    readnum(const char *pszNum);
    46 static int      interpretFunctionProlog(char *p, BOOL fOverload);
    47 static int      procInit(void);
     46static signed char interpretFunctionProlog32(char *pach, BOOL fOverload);
     47static signed char interpretFunctionProlog16(char *pach, BOOL fOverload);
     48static int      ImportTabInit(void);
    4849
    4950
     
    291292    /* functionoverrides */
    292293    if (!options.fNoLoader)
    293         if (procInit() != NO_ERROR)
     294        if (ImportTabInit() != NO_ERROR)
    294295            return STATUS_DONE | STERR | ERROR_I24_QUIET_INIT_FAIL;
    295296
     
    338339
    339340    return i > 0 ? ulRet : ~0UL;
    340 }
    341 
    342 
    343 /**
    344  * Verifies the aImportTab.
    345  * @returns   0 if ok. !0 if not ok.
    346  * @remark    Called from IOCtl.
    347  */
    348 USHORT _loadds _Far32 _Pascal VerifyProcTab32(void)
    349 {
    350     int i;
    351     int cb;
    352 
    353     /* verify */
    354     for (i = 0; i < NBR_OF_KRNLIMPORTS; i++)
    355     {
    356         /* verify that it is found */
    357         if (!_aImportTab[i].fFound)
    358         {
    359             kprintf(("VerifyProcTab32: procedure no.%d was not found!\n", i));
    360             return STATUS_DONE | STERR | 1;
    361         }
    362 
    363         /* verify read/writeable. - FIXME */
    364         if (_aImportTab[i].ulAddress < 0xffe00000UL)
    365         {
    366             kprintf(("VerifyProcTab32: procedure no.%d has an invlalid address, %#08x!\n",
    367                      i, _aImportTab[i].ulAddress));
    368             return STATUS_DONE | STERR | 2;
    369         }
    370 
    371         switch (_aImportTab[i].fType)
    372         {
    373             case EPT_PROC:
    374             case EPT_PROCIMPORT:
    375                 /* verify known function prolog. */
    376                 if ((cb = interpretFunctionProlog((char*)_aImportTab[i].ulAddress, _aImportTab[i].fType == EPT_PROC))
    377                     <= 0 && cb + 5 >= MAXSIZE_PROLOG)
    378                 {
    379                     kprintf(("VerifyProcTab32: verify failed for procedure no.%d\n",i));
    380                     return STATUS_DONE | STERR | 3;
    381                 }
    382                 break;
    383 
    384             default:
    385                 kprintf(("VerifyProcTab32: only EPT_PROC is implemented\n",i));
    386                 return STATUS_DONE | STERR | 4;
    387         }
    388     }
    389 
    390     return STATUS_DONE;
    391341}
    392342
     
    446396
    447397/**
    448  * Interpret function prolog to find where to jmp back.
     398 * 32-bit! Interpret function prolog to find where to jmp back.
    449399 * @returns   Length of prolog need to be copied - which is also the offset of
    450400 *            where the jmp instr should be placed.
     
    454404 *                       FALSE: Function is to be imported.
    455405 */
    456 static int interpretFunctionProlog(char *pach, BOOL fOverload)
     406static signed char interpretFunctionProlog32(char *pach, BOOL fOverload)
    457407{
    458     int rc;
     408    int cb;
    459409
    460410    /*
     
    471421    {
    472422        if (pach[2] == 0xec)
    473             rc = 3;
     423            cb = 3;
    474424        else
    475             rc = 1;
    476         while (rc < 5)
     425            cb = 1;
     426        while (cb < 5)
    477427        {
    478428            /*
     
    481431             * There will never be any doubt when something goes wrong!
    482432             */
    483             switch(pach[rc])
     433            switch(pach[cb])
    484434            {
    485435                case 0x33: /* xor (ldrClose, ldrOpen) */
    486                     rc +=2;
     436                    cb +=2;
    487437                    break;
    488438                case 0x8b:
    489                     if (pach[rc+1] == 0x0d)
    490                         rc += 6;
     439                    if (pach[cb+1] == 0x0d)
     440                        cb += 6;
    491441                    else
    492                         rc += 2; /*????!*/
     442                        cb += 2; /*????!*/
    493443                    break;
    494444                case 0x8d: /* lea (ldrRead) */
    495                     rc += 3;
     445                    cb += 3;
    496446                    break;
    497447                case 0x83: /* sub (LDRQAppType) */
    498                     rc += 3;
     448                    cb += 3;
    499449                    break;
    500450                default:
    501                     kprintf(("interpretFunctionProlog: unknown instruction 0x%x\n", pach[rc]));
     451                    kprintf(("interpretFunctionProlog: unknown instruction 0x%x\n", pach[cb]));
    502452                    return 0;
    503453            }
     
    506456    else if (pach[0] == 0x55 && pach[1] == 0xa1) /* ldrEnum32bitRelRecs on WS4eB */
    507457    {
    508         rc = 1 + 5;
     458        cb = 1 + 5;
    509459    }
    510460    else
     
    512462        /* special case for IOSftReadAt and IOSftWriteAt */
    513463        if (fOverload == FALSE && pach[0] == 0xB8 && (pach[5] == 0xEB || pach[5] == 0x55))
    514             rc = 5;
     464            cb = 5;
    515465        else
    516             rc = 0;
     466            cb = 0;
    517467    }
    518468
    519     return rc;
     469    return (signed char)cb;
    520470}
    521471
     472
     473/**
     474 * 16-bit! Interpret function prolog to find where to jmp back.
     475 * @returns   Length of prolog need to be copied - which is also the offset of
     476 *            where the jmp instr should be placed.
     477 *            On error it returns 0.
     478 * @param     pach       Pointer to prolog.
     479 * @param     fOverload  TRUE:  Function is to be overloaded.
     480 *                       FALSE: Function is to be imported.
     481 */
     482static signed char interpretFunctionProlog16(char *pach, BOOL fOverload)
     483{
     484    int cb;
     485
     486    /*
     487     * Check for the well known prolog (the only that is supported now)
     488     * which is:
     489     *     push 2
     490     */
     491    if (*pach == 0x6A)                  /* push 2 (don't check for the 2) */
     492    {
     493        BOOL fForce;
     494        cb = 0;
     495        while (cb < 8 || fForce)
     496        {
     497            fForce = FALSE;
     498            switch (*pach)
     499            {
     500                case 0x50:              /* push ax */
     501                case 0x51:              /* push cx */
     502                case 0x52:              /* push dx */
     503                case 0x53:              /* push bx */
     504                case 0x54:              /* push sp */
     505                case 0x55:              /* push bp */
     506                case 0x56:              /* push si */
     507                case 0x57:              /* push di */
     508                    break;
     509
     510                case 0x2e:              /* cs segment override */
     511                case 0x36:              /* ss segment override */
     512                case 0x3e:              /* ds segment override */
     513                case 0x26:              /* es segment override */
     514                case 0x64:              /* fs segment override */
     515                case 0x65:              /* gs segment override */
     516                    fForce = TRUE;
     517                    break;
     518
     519                case 0x6a:              /* push <byte> */
     520                    pach++;
     521                    cb++;
     522                    break;
     523
     524                case 0x68:              /* push <word> */
     525                    pach += 2;
     526                    cb += 2;
     527                    break;
     528
     529                case 0x8b:              /* mov /r */
     530                    if ((pach[1] & 0xc0) == 10  /* ex. mov ax,bp+1114h */
     531                        || ((pach[1] & 0xc0) == 0 && (pach[1] & 0xc0) == 6)) /* ex. mov bp,0ff23h */
     532                    {   /* 16-bit displacement */
     533                        pach += 3;
     534                        cb += 3;
     535                    }
     536                    else
     537                        if ((pach[1] & 0xc0) == 0x40) /* ex. mov ax,[si]+4fh */
     538                    {   /* 8-bit displacement */
     539                        pach += 2;
     540                        cb += 2;
     541                    }
     542                    else
     543                    {   /* no displacement (only /r byte) */
     544                        pach++;
     545                        cb++;
     546                    }
     547                    break;
     548
     549                default:
     550                    kprintf(("interpretFunctionProlog: unknown instruction 0x%x 0x%x 0x%x\n", pach[0], pach[1], pach[2]));
     551                    return 0;
     552            }
     553            pach++;
     554            cb++;
     555        }
     556    }
     557
     558    fOverload = fOverload;
     559    return (signed char)cb;
     560}
     561
     562
     563/**
     564 * Verifies the aImportTab.
     565 * @returns   0 if ok. !0 if not ok.
     566 * @remark    Called from IOCtl.
     567 *            WARNING! VerifyImporTab32 is called before the initroutine!
     568 */
     569USHORT _loadds _Far32 _Pascal VerifyImportTab32(void)
     570{
     571    int i;
     572    int cb;
     573    int cbmin;
     574
     575    /* VerifyImporTab32 is called before the initroutine! */
     576    pulTKSSBase32 = (PULONG)_TKSSBase16;
     577
     578    /* verify */
     579    for (i = 0; i < NBR_OF_KRNLIMPORTS; i++)
     580    {
     581        /* verify that it is found */
     582        if (!_aImportTab[i].fFound)
     583        {
     584            kprintf(("VerifyImportTab32: procedure no.%d was not found!\n", i));
     585            return STATUS_DONE | STERR | 1;
     586        }
     587
     588        /* verify read/writeable. - FIXME */
     589        if (_aImportTab[i].ulAddress < 0xffe00000UL)
     590        {
     591            kprintf(("VerifyImportTab32: procedure no.%d has an invlalid address, %#08x!\n",
     592                     i, _aImportTab[i].ulAddress));
     593            return STATUS_DONE | STERR | 2;
     594        }
     595
     596        switch (_aImportTab[i].fType & ~EPT_BIT_MASK)
     597        {
     598            case EPT_PROC:
     599            case EPT_PROCIMPORT:
     600                /*
     601                 * Verify known function prolog.
     602                 */
     603                if (_aImportTab[i].fType & EPT_32BIT)
     604                {
     605                    cb = interpretFunctionProlog32((char*)_aImportTab[i].ulAddress, _aImportTab[i].fType == EPT_PROC32);
     606                    cbmin = 5;
     607                }
     608                else
     609                {
     610                    cb = interpretFunctionProlog16((char*)_aImportTab[i].ulAddress, _aImportTab[i].fType == EPT_PROC16);
     611                    cbmin = 8;
     612                }
     613
     614                /*
     615                 * Check result of the function prolog interpretations.
     616                 */
     617                if (cb <= 0 && cb + cbmin >= MAXSIZE_PROLOG)
     618                {   /* failed, too small or too large. */
     619                    kprintf(("VerifyImportTab32: verify failed for procedure no.%d (cd=%d)\n", i, cb));
     620                    return STATUS_DONE | STERR | 3;
     621                }
     622                break;
     623
     624            case EPT_VARIMPORT:
     625                /* do nothing! */
     626                break;
     627
     628            default:
     629                kprintf(("VerifyImportTab32: only EPT_PROC is implemented\n",i));
     630                return STATUS_DONE | STERR | 4;
     631        }
     632    }
     633
     634    return STATUS_DONE;
     635}
    522636
    523637
     
    526640 * @returns   NO_ERROR on success. !0 on error.
    527641 */
    528 static int procInit(void)
     642static int importTabInit(void)
    529643{
     644    /* This table must be updated with the overloading functions. */
     645    static unsigned auFuncs[NBR_OF_KRNLIMPORTS] =
     646    {
     647        (unsigned)myldrRead,
     648        (unsigned)myldrOpen,
     649        (unsigned)myldrClose,
     650        0,//(unsigned)myLDRQAppType,
     651        (unsigned)myldrEnum32bitRelRecs,
     652        0,
     653        0,
     654        0,
     655        0,
     656        0,
     657        0,
     658        0,
     659        0,
     660        (unsigned)&mytkExecPgm,
     661        0,
     662        0
     663    };
     664
    530665    int i;
    531666    int cb;
     667
    532668
    533669    /*
     
    536672    for (i = 0; i < NBR_OF_KRNLIMPORTS; i++)
    537673    {
    538         if (_aImportTab[i].fType != EPT_PROC && _aImportTab[i].fType != EPT_PROCIMPORT)
    539         {
    540             kprintf(("procInit: EPT_VAR is not supported. (procedure no.%d, cb=%d)\n", i, cb));
    541             return 1;
    542         }
    543         cb = interpretFunctionProlog((char*)_aImportTab[i].ulAddress, _aImportTab[i].fType == EPT_PROC);
     674        /* EPT_VARIMPORTs are skipped */
     675        if ((_aImportTab[i].fType & ~EPT_BIT_MASK) == EPT_VARIMPORT)
     676            continue;
     677
     678        if (_aImportTab[i].fType & EPT_32BIT)
     679            cb = interpretFunctionProlog32((char*)_aImportTab[i].ulAddress, _aImportTab[i].fType == EPT_PROC32);
     680        else
     681            cb = interpretFunctionProlog16((char*)_aImportTab[i].ulAddress, _aImportTab[i].fType == EPT_PROC16);
    544682        if (cb <= 0 || cb + 5 >= MAXSIZE_PROLOG)
    545683        {
    546             kprintf(("procInit: verify failed for procedure no.%d, cb=%d\n", i, cb));
     684            kprintf(("ImportTabInit: verify failed for procedure no.%d, cb=%d\n", i, cb));
    547685            return 1;
    548686        }
     
    556694        switch (_aImportTab[i].fType)
    557695        {
    558             case EPT_PROC:
     696            /*
     697             * 32-bit procedure overload.
     698             * The overloading procedure is found in the auFuncs table (at the same index
     699             *   as the overloaded procedure has in aImportTab).
     700             * The overloaded procedure is called by issuing a call to the callTab entry.
     701             */
     702            case EPT_PROC32:
    559703            {
    560                 cb = interpretFunctionProlog((char*)_aImportTab[i].ulAddress, TRUE);
     704                cb = _aImportTab[i].cbProlog = interpretFunctionProlog32((char*)_aImportTab[i].ulAddress, TRUE);
    561705                if (cb > 0 && cb + 5 < MAXSIZE_PROLOG)
    562706                {
    563                     static unsigned auFuncs[NBR_OF_KRNLIMPORTS] = /* This table must be updated with the overloading functions. */
    564                     {
    565                         (unsigned)myldrRead,
    566                         (unsigned)myldrOpen,
    567                         (unsigned)myldrClose,
    568                         0,//(unsigned)myLDRQAppType,
    569                         (unsigned)myldrEnum32bitRelRecs,
    570                         0,
    571                         0,
    572                         0,
    573                         0,
    574                         0,
    575                         0,
    576                         0,
    577                         0,
    578                         (unsigned)&mytkExecPgm
    579                     };
    580 
    581                     /* copy function prolog */
     707                    /*
     708                     * Copy function prolog which will be overwritten by the jmp to calltabl.
     709                     */
    582710                    memcpy(callTab[i], (void*)_aImportTab[i].ulAddress, (size_t)cb);
    583711
    584                     /* jump from calltab to original function */
     712                    /*
     713                     * Make jump instruction which jumps from calltab to original function.
     714                     * 0xE9 <four bytes displacement>
     715                     * Note: the displacement is relative to the next instruction
     716                     */
    585717                    callTab[i][cb] = 0xE9; /* jmp */
    586                     *(unsigned*)(void*)&callTab[i][cb+1] = _aImportTab[i].ulAddress + cb - (unsigned)&callTab[i][cb+5];
    587 
    588 
    589                     /* jump from original function to my function - an cli(?) could be needed here */
     718                    *(unsigned long*)(void*)&callTab[i][cb+1] = _aImportTab[i].ulAddress + cb - (unsigned long)&callTab[i][cb+5];
     719
     720                    /*
     721                     * Jump from original function to my function - an cli(?) could be needed here
     722                     */
    590723                    *(char*)_aImportTab[i].ulAddress = 0xE9; /* jmp */
    591                     *(unsigned*)(_aImportTab[i].ulAddress + 1) = auFuncs[i] - (_aImportTab[i].ulAddress + 5);
     724                    *(unsigned long*)(_aImportTab[i].ulAddress + 1) = auFuncs[i] - (_aImportTab[i].ulAddress + 5);
    592725                }
    593726                else
    594727                {   /* !fatal! - this could never happen really... */
    595                     kprintf(("procInit: FATAL verify failed for procedure no.%d when rehooking it!\n",i));
     728                    kprintf(("ImportTabInit: FATAL verify failed for procedure no.%d when rehooking it!\n",i));
    596729                    Int3(); /* ipe - later! */
    597730                    return 1;
     
    600733            }
    601734
    602             case EPT_PROCIMPORT:
     735
     736            /*
     737             * 16-bit procedure overload.
     738             * Currently disabled due to expected problems when calltab is a 32-bit segment.
     739             */
     740            case EPT_PROC16:
    603741            {
    604                 cb = interpretFunctionProlog((char*)_aImportTab[i].ulAddress, FALSE);
     742                kprintf(("ImportTabInit: Overloading 16-bit procedures are not supported yet!!! Calltable in 32-bit segment!\n", i));
     743                Int3();
     744
     745                cb = _aImportTab[i].cbProlog = interpretFunctionProlog16((char*)_aImportTab[i].ulAddress, TRUE);
     746                if (cb > 0 && cb + 8 < MAXSIZE_PROLOG) /* a 16:32 jump must be prefixed with 66h in a 16-bit segment */
     747                {
     748                    /*
     749                     * Copy function prolog which is to be overwritten.
     750                     */
     751                    memcpy(callTab[i], (void*)_aImportTab[i].ulAddress, (size_t)cb);
     752
     753                    /*
     754                     * Create far jump from calltab to original function.
     755                     * 0xEA <four byte target address> <two byte target selector>
     756                     */
     757                    callTab[i][cb] = 0xEA; /* jmp far ptr */
     758                    *(unsigned long*)(void*)&callTab[i][cb+1] = _aImportTab[i].offObject;
     759                    *(unsigned short*)(void*)&callTab[i][cb+5] = _aImportTab[i].usSel;
     760
     761                    /*
     762                     * jump from original function to my function - an cli(?) could be needed here
     763                     * 0x66 0xEA <four byte target address> <two byte target selector>
     764                     */
     765                    *(char*)(_aImportTab[i].ulAddress    ) = 0x66;    /* operandsize prefix */
     766                    *(char*)(_aImportTab[i].ulAddress + 1) = 0xEA;    /* jmp far ptr */
     767                    *(unsigned long*)(_aImportTab[i].ulAddress + 2) = auFuncs[i];   /* FIXME? */
     768                    *(unsigned short*)(_aImportTab[i].ulAddress + 6) = _R0FlatCS16; /* FIXME */
     769                }
     770                else
     771                {   /* !fatal! - this could never happen really... */
     772                    kprintf(("ImportTabInit: FATAL verify failed for procedure no.%d when rehooking it!\n",i));
     773                    Int3(); /* ipe - later! */
     774                    return 1;
     775                }
     776                break;
     777            }
     778
     779
     780            /*
     781             * 32-bit imported procedure
     782             * This is called by issuing a near call to the callTab entry.
     783             */
     784            case EPT_PROCIMPORT32:
     785            {
     786                cb = _aImportTab[i].cbProlog = interpretFunctionProlog32((char*)_aImportTab[i].ulAddress, FALSE);
    605787                if (cb > 0 && cb + 5 < MAXSIZE_PROLOG)
    606788                {
    607                     /* jump from calltab to original function */
     789                    /*
     790                     * Make jump instruction which jumps from calltab to original function.
     791                     * 0xE9 <four bytes displacement>
     792                     * Note: the displacement is relative to the next instruction
     793                     */
    608794                    callTab[i][0] = 0xE9; /* jmp */
    609795                    *(unsigned*)(void*)&callTab[i][1] = _aImportTab[i].ulAddress - (unsigned)&callTab[i][cb+5];
    610796                }
    611797                else
    612                 {   /* !fatal! - this could never happen really... */
    613                     kprintf(("procInit: FATAL verify failed for procedure no.%d when importing it!\n",i));
     798                {   /* !fatal! - this should never really happen... */
     799                    kprintf(("ImportTabInit: FATAL verify failed for procedure no.%d when importing it!\n",i));
    614800                    Int3(); /* ipe - later! */
    615801                    return 1;
     
    618804            }
    619805
     806
     807            /*
     808             * 16-bit imported procedure.
     809             * This is called by issuing a far call to the calltab entry.
     810             */
     811            case EPT_PROCIMPORT16:
     812            {
     813                cb = _aImportTab[i].cbProlog = interpretFunctionProlog16((char*)_aImportTab[i].ulAddress, FALSE);
     814                if (cb > 0 && cb + 8 < MAXSIZE_PROLOG)
     815                {
     816                    /*
     817                     * Create far jump from calltab to original function.
     818                     * 0xEA <four byte target address> <two byte target selector>
     819                     */
     820                    callTab[i][0] = 0xEA; /* jmp far ptr */
     821                    *(unsigned long*)(void*)&callTab[i][1] = _aImportTab[i].offObject;
     822                    *(unsigned short*)(void*)&callTab[i][5] = _aImportTab[i].usSel;
     823                }
     824                else
     825                {   /* !fatal! - this should never really happen... */
     826                    kprintf(("ImportTabInit: FATAL verify failed for procedure no.%d when importing it!\n",i));
     827                    Int3(); /* ipe - later! */
     828                    return 1;
     829                }
     830                break;
     831            }
     832
     833
     834            /*
     835             * 16/32-bit importe variable.
     836             * This is used by accessing the 32-bit flat address in the callTab.
     837             * callTab-entry + 4 holds the offset of the variable into the object.
     838             * callTab-entry + 8 holds the selector for the object. (These two fields is the 16:32-bit pointer to the variable.)
     839             * callTab-entry + a holds the 16-bit offset for the variable.
     840             * callTab-entry + c holds the selector for the object. (These two fiels is the 16:16-bit pointer to the variable.)
     841             */
     842            case EPT_VARIMPORT32:
     843            case EPT_VARIMPORT16:
     844                *(unsigned long*)(void*)&callTab[i][0] = _aImportTab[i].ulAddress;
     845                *(unsigned long*)(void*)&callTab[i][4] = _aImportTab[i].offObject;
     846                *(unsigned short*)(void*)&callTab[i][8] = _aImportTab[i].usSel;
     847                *(unsigned short*)(void*)&callTab[i][0xa] = (unsigned short)_aImportTab[i].offObject;
     848                *(unsigned short*)(void*)&callTab[i][0xc] = _aImportTab[i].usSel;
     849                break;
     850
    620851            default:
    621                 kprintf(("procInit: EPT_VAR is not supported. (procedure no.%d, cb=%d)\n", i, cb));
     852                kprintf(("ImportTabInit: unsupported type. (procedure no.%d, cb=%d)\n", i, cb));
    622853                Int3(); /* ipe - later! */
    623854                return 1;
Note: See TracChangeset for help on using the changeset viewer.