Ejemplo n.º 1
0
/***********************************************************************
 *           NE_LoadAllSegments
 */
BOOL NE_LoadAllSegments( NE_MODULE *pModule )
{
    int i;
    SEGTABLEENTRY * pSegTable = NE_SEG_TABLE(pModule);

    if (pModule->ne_flags & NE_FFLAGS_SELFLOAD)
    {
        HFILE16 hFile16;
        HGLOBAL16 sel;
        /* Handle self-loading modules */
        SELFLOADHEADER *selfloadheader;
        HMODULE16 mod = GetModuleHandle16("KERNEL");
        void *oldstack;
        WORD args[2];

        TRACE_(module)("%.*s is a self-loading module!\n",
                       *((BYTE*)pModule + pModule->ne_restab),
                       (char *)pModule + pModule->ne_restab + 1);
        if (!NE_LoadSegment( pModule, 1 )) return FALSE;
        selfloadheader = MapSL( MAKESEGPTR(SEL(pSegTable->hSeg), 0) );
        selfloadheader->EntryAddrProc = GetProcAddress16(mod,"EntryAddrProc");
        selfloadheader->MyAlloc       = GetProcAddress16(mod,"MyAlloc");
        selfloadheader->SetOwner      = GetProcAddress16(mod,"FarSetOwner");
        sel = GlobalAlloc16( GMEM_ZEROINIT, 0xFF00 );
        pModule->self_loading_sel = SEL(sel);
        FarSetOwner16( sel, pModule->self );
		oldstack = getWOW32Reserved();
        setWOW32Reserved((void *)MAKESEGPTR(pModule->self_loading_sel,
                                                           0xff00 - sizeof(STACK16FRAME) ));

        hFile16 = NE_OpenFile(pModule);
        TRACE_(dll)("CallBootAppProc(hModule=0x%04x,hf=0x%04x)\n",
              pModule->self,hFile16);
        args[1] = pModule->self;
        args[0] = hFile16;
        WOWCallback16Ex( (DWORD)selfloadheader->BootApp, WCB16_PASCAL, sizeof(args), args, NULL );
	TRACE_(dll)("Return from CallBootAppProc\n");
        _lclose16(hFile16);
		setWOW32Reserved(oldstack);

        for (i = 2; i <= pModule->ne_cseg; i++)
            if (!NE_LoadSegment( pModule, i )) return FALSE;
    }
    else
    {
        for (i = 1; i <= pModule->ne_cseg; i++)
            if (!NE_LoadSegment( pModule, i )) return FALSE;
    }
    return TRUE;
}
Ejemplo n.º 2
0
/***********************************************************************
 *           NE_LoadAllSegments
 */
BOOL NE_LoadAllSegments( NE_MODULE *pModule )
{
    int i;
    SEGTABLEENTRY * pSegTable = (SEGTABLEENTRY *) NE_SEG_TABLE(pModule);

    if (pModule->flags & NE_FFLAGS_SELFLOAD)
    {
        HANDLE hf;
        HFILE16 hFile16;
        HGLOBAL16 sel;
        /* Handle self-loading modules */
        SELFLOADHEADER *selfloadheader;
        HMODULE16 mod = GetModuleHandle16("KERNEL");
        DWORD oldstack;

        TRACE_(module)("%.*s is a self-loading module!\n",
		     *((BYTE*)pModule + pModule->name_table),
		     (char *)pModule + pModule->name_table + 1);
        if (!NE_LoadSegment( pModule, 1 )) return FALSE;
        selfloadheader = MapSL( MAKESEGPTR(SEL(pSegTable->hSeg), 0) );
        selfloadheader->EntryAddrProc = GetProcAddress16(mod,"EntryAddrProc");
        selfloadheader->MyAlloc       = GetProcAddress16(mod,"MyAlloc");
        selfloadheader->SetOwner      = GetProcAddress16(mod,"FarSetOwner");
        sel = GlobalAlloc16( GMEM_ZEROINIT, 0xFF00 );
        pModule->self_loading_sel = SEL(sel);
        FarSetOwner16( sel, pModule->self );
        oldstack = NtCurrentTeb()->WOW32Reserved;
        NtCurrentTeb()->WOW32Reserved = MAKESEGPTR(pModule->self_loading_sel,
                                               0xff00 - sizeof(STACK16FRAME) );

        DuplicateHandle( GetCurrentProcess(), NE_OpenFile(pModule),
                         GetCurrentProcess(), &hf, 0, FALSE, DUPLICATE_SAME_ACCESS );
        hFile16 = Win32HandleToDosFileHandle( hf );
        TRACE_(dll)("CallBootAppProc(hModule=0x%04x,hf=0x%04x)\n",
              pModule->self,hFile16);
        NE_CallTo16_word_ww(selfloadheader->BootApp, pModule->self,hFile16);
	TRACE_(dll)("Return from CallBootAppProc\n");
        _lclose16(hFile16);
        NtCurrentTeb()->WOW32Reserved = oldstack;

        for (i = 2; i <= pModule->seg_count; i++)
            if (!NE_LoadSegment( pModule, i )) return FALSE;
    }
    else
    {
        for (i = 1; i <= pModule->seg_count; i++)
            if (!NE_LoadSegment( pModule, i )) return FALSE;
    }
    return TRUE;
}
Ejemplo n.º 3
0
/***********************************************************************
 *           NE_LoadSegment
 */
BOOL NE_LoadSegment( NE_MODULE *pModule, WORD segnum )
{
    WORD count;
    DWORD pos;
    const struct relocation_entry_s *rep;
    int size;
    SEGTABLEENTRY *pSegTable = NE_SEG_TABLE( pModule );
    SEGTABLEENTRY *pSeg = pSegTable + segnum - 1;

    if (pSeg->flags & NE_SEGFLAGS_LOADED)
    {
	/* self-loader ? -> already loaded it */
	if (pModule->ne_flags & NE_FFLAGS_SELFLOAD)
	    return TRUE;

	/* leave, except for DGROUP, as this may be the second instance */
	if (segnum != pModule->ne_autodata)
            return TRUE;
    }

    if (!pSeg->filepos) return TRUE;  /* No file image, just return */

    TRACE_(module)("Loading segment %d, hSeg=%04x, flags=%04x\n",
                    segnum, pSeg->hSeg, pSeg->flags );
    pos = pSeg->filepos << pModule->ne_align;
    if (pSeg->size) size = pSeg->size;
    else size = pSeg->minsize ? pSeg->minsize : 0x10000;

    if (pModule->ne_flags & NE_FFLAGS_SELFLOAD && segnum > 1)
    {
 	/* Implement self-loading segments */
 	SELFLOADHEADER *selfloadheader;
        void *oldstack;
        HFILE16 hFile16;
        WORD args[3];
        DWORD ret;

 	selfloadheader = MapSL( MAKESEGPTR(SEL(pSegTable->hSeg),0) );
        oldstack = getWOW32Reserved();
		setWOW32Reserved((void *)MAKESEGPTR(pModule->self_loading_sel,
                                                           0xff00 - sizeof(STACK16FRAME)));

        hFile16 = NE_OpenFile( pModule );
        TRACE_(dll)("Call LoadAppSegProc(hmodule=0x%04x,hf=%x,segnum=%d)\n",
                    pModule->self,hFile16,segnum );
        args[2] = pModule->self;
        args[1] = hFile16;
        args[0] = segnum;
        WOWCallback16Ex( (DWORD)selfloadheader->LoadAppSeg, WCB16_PASCAL, sizeof(args), args, &ret );
        pSeg->hSeg = LOWORD(ret);
        TRACE_(dll)("Ret LoadAppSegProc: hSeg=0x%04x\n", pSeg->hSeg);
        _lclose16( hFile16 );
		setWOW32Reserved(oldstack);

        pSeg->flags |= NE_SEGFLAGS_LOADED;
        return TRUE;
    }
    else if (!(pSeg->flags & NE_SEGFLAGS_ITERATED))
    {
        void *mem = GlobalLock16(pSeg->hSeg);
        if (!NE_READ_DATA( pModule, mem, pos, size ))
            return FALSE;
        pos += size;
    }
    else
    {
        /*
          The following bit of code for "iterated segments" was written without
          any documentation on the format of these segments. It seems to work,
          but may be missing something.
        */
        const char *buff = NE_GET_DATA( pModule, pos, size );
        const char* curr = buff;
        char *mem = GlobalLock16(pSeg->hSeg);

        pos += size;
        if (buff == NULL) return FALSE;

        while(curr < buff + size) {
            unsigned int rept = ((const short *)curr)[0];
            unsigned int len =  ((const short *)curr)[1];

            curr += 2*sizeof(short);
            while (rept--)
            {
                memcpy( mem, curr, len );
                mem += len;
            }
            curr += len;
        }
    }

    pSeg->flags |= NE_SEGFLAGS_LOADED;

    /* Perform exported function prolog fixups */
    NE_FixupSegmentPrologs( pModule, segnum );

    if (!(pSeg->flags & NE_SEGFLAGS_RELOC_DATA))
        return TRUE;  /* No relocation data, we are done */

    if (!NE_READ_DATA( pModule, &count, pos, sizeof(count) ) || !count) return TRUE;
    pos += sizeof(count);

    TRACE("Fixups for %.*s, segment %d, hSeg %04x\n",
          *((BYTE *)pModule + pModule->ne_restab),
          (char *)pModule + pModule->ne_restab + 1,
          segnum, pSeg->hSeg );

    if (!(rep = NE_GET_DATA( pModule, pos, count * sizeof(struct relocation_entry_s) )))
        return FALSE;

    return apply_relocations( pModule, rep, count, segnum );
}
Ejemplo n.º 4
0
/***********************************************************************
 *           NE_LoadSegment
 */
BOOL NE_LoadSegment( NE_MODULE *pModule, WORD segnum )
{
    SEGTABLEENTRY *pSegTable, *pSeg;
    WORD *pModuleTable;
    WORD count, i, offset, next_offset;
    HMODULE16 module;
    FARPROC16 address = 0;
    HFILE hf;
    DWORD res;
    struct relocation_entry_s *rep, *reloc_entries;
    char *func_name;
    int size;
    char* mem;

    char buffer[256];
    int ordinal, additive;
    unsigned short *sp;

    pSegTable = NE_SEG_TABLE( pModule );
    pSeg = pSegTable + segnum - 1;

    if (pSeg->flags & NE_SEGFLAGS_LOADED)
    {
	/* self-loader ? -> already loaded it */
	if (pModule->flags & NE_FFLAGS_SELFLOAD)
	    return TRUE;

	/* leave, except for DGROUP, as this may be the second instance */
	if (segnum != pModule->dgroup)
            return TRUE;
    }

    if (!pSeg->filepos) return TRUE;  /* No file image, just return */

    pModuleTable = NE_MODULE_TABLE( pModule );

    hf = NE_OpenFile( pModule );
    TRACE_(module)("Loading segment %d, hSeg=%04x, flags=%04x\n",
                    segnum, pSeg->hSeg, pSeg->flags );
    SetFilePointer( hf, pSeg->filepos << pModule->alignment, NULL, SEEK_SET );
    if (pSeg->size) size = pSeg->size;
    else size = pSeg->minsize ? pSeg->minsize : 0x10000;
    mem = GlobalLock16(pSeg->hSeg);
    if (pModule->flags & NE_FFLAGS_SELFLOAD && segnum > 1)
    {
 	/* Implement self-loading segments */
 	SELFLOADHEADER *selfloadheader;
        DWORD oldstack;
        HANDLE hFile32;
        HFILE16 hFile16;

 	selfloadheader = MapSL( MAKESEGPTR(SEL(pSegTable->hSeg),0) );
 	oldstack = NtCurrentTeb()->WOW32Reserved;
 	NtCurrentTeb()->WOW32Reserved = MAKESEGPTR(pModule->self_loading_sel,
                                               0xff00 - sizeof(STACK16FRAME));

	TRACE_(dll)("CallLoadAppSegProc(hmodule=0x%04x,hf=0x%04x,segnum=%d\n",
		pModule->self,hf,segnum );
        DuplicateHandle( GetCurrentProcess(), hf, GetCurrentProcess(), &hFile32,
                         0, FALSE, DUPLICATE_SAME_ACCESS );
        hFile16 = Win32HandleToDosFileHandle( hFile32 );
 	pSeg->hSeg = NE_CallTo16_word_www( selfloadheader->LoadAppSeg,
                                           pModule->self, hFile16, segnum );
	TRACE_(dll)("Ret CallLoadAppSegProc: hSeg = 0x%04x\n", pSeg->hSeg);
        _lclose16( hFile16 );
 	NtCurrentTeb()->WOW32Reserved = oldstack;
    }
    else if (!(pSeg->flags & NE_SEGFLAGS_ITERATED))
        ReadFile(hf, mem, size, &res, NULL);
    else {
      /*
	 The following bit of code for "iterated segments" was written without
	 any documentation on the format of these segments. It seems to work,
	 but may be missing something. If you have any doc please either send
	 it to me or fix the code yourself. [email protected]
      */
      char* buff = HeapAlloc(GetProcessHeap(), 0, size);
      char* curr = buff;

      if(buff == NULL) {
          WARN_(dll)("Memory exausted!");
          return FALSE;
      }

      ReadFile(hf, buff, size, &res, NULL);
      while(curr < buff + size) {
	unsigned int rept = *((short*) curr);
	curr = (char *)(((short*) curr) + 1);
	unsigned int len = *((short*) curr);
	curr = (char *)(((short*) curr) + 1);
	for(; rept > 0; rept--) {
	  char* bytes = curr;
	  unsigned int byte;
	  for(byte = 0; byte < len; byte++)
	    *mem++ = *bytes++;
	}
	curr += len;
      }
      HeapFree(GetProcessHeap(), 0, buff);
    }

    pSeg->flags |= NE_SEGFLAGS_LOADED;

    /* Perform exported function prolog fixups */
    NE_FixupSegmentPrologs( pModule, segnum );

    if (!(pSeg->flags & NE_SEGFLAGS_RELOC_DATA))
        return TRUE;  /* No relocation data, we are done */

    ReadFile(hf, &count, sizeof(count), &res, NULL);
    if (!count) return TRUE;

    TRACE_(fixup)("Fixups for %.*s, segment %d, hSeg %04x\n",
                   *((BYTE *)pModule + pModule->name_table),
                   (char *)pModule + pModule->name_table + 1,
                   segnum, pSeg->hSeg );
    TRACE_(segment)("Fixups for %.*s, segment %d, hSeg %04x\n",
                   *((BYTE *)pModule + pModule->name_table),
                   (char *)pModule + pModule->name_table + 1,
                   segnum, pSeg->hSeg );

    reloc_entries = (struct relocation_entry_s *)HeapAlloc(GetProcessHeap(), 0, count * sizeof(struct relocation_entry_s));
    if(reloc_entries == NULL) {
        WARN_(fixup)("Not enough memory for relocation entries!");
        return FALSE;
    }
    if (!ReadFile( hf, reloc_entries, count * sizeof(struct relocation_entry_s), &res, NULL) ||
        (res != count * sizeof(struct relocation_entry_s)))
    {
        WARN_(fixup)("Unable to read relocation information\n" );
        return FALSE;
    }

    /*
     * Go through the relocation table one entry at a time.
     */
    rep = reloc_entries;
    for (i = 0; i < count; i++, rep++)
    {
	/*
	 * Get the target address corresponding to this entry.
	 */

	/* If additive, there is no target chain list. Instead, add source
	   and target */
	additive = rep->relocation_type & NE_RELFLAG_ADDITIVE;
	rep->relocation_type &= 0x3;

	switch (rep->relocation_type)
	{
	  case NE_RELTYPE_ORDINAL:
            module = pModuleTable[rep->target1-1];
	    ordinal = rep->target2;
            address = NE_GetEntryPoint( module, ordinal );
            if (!address)
            {
                NE_MODULE *pTarget = NE_GetPtr( module );
                if (!pTarget)
                    WARN_(module)("Module not found: %04x, reference %d of module %*.*s\n",
                             module, rep->target1,
                             *((BYTE *)pModule + pModule->name_table),
                             *((BYTE *)pModule + pModule->name_table),
                             (char *)pModule + pModule->name_table + 1 );
                else
                {
                    ERR_(fixup)("No implementation for %.*s.%d, setting to 0xdeadbeef\n",
                            *((BYTE *)pTarget + pTarget->name_table),
                            (char *)pTarget + pTarget->name_table + 1,
                            ordinal );
                    address = (FARPROC16)0xdeadbeef;
                }
            }
            if (TRACE_ON(fixup))
            {
                NE_MODULE *pTarget = NE_GetPtr( module );
                TRACE_(fixup)("%d: %.*s.%d=%04x:%04x %s\n", i + 1,
                       *((BYTE *)pTarget + pTarget->name_table),
                       (char *)pTarget + pTarget->name_table + 1,
                       ordinal, HIWORD(address), LOWORD(address),
                       NE_GetRelocAddrName( rep->address_type, additive ) );
            }
	    break;

	  case NE_RELTYPE_NAME:
            module = pModuleTable[rep->target1-1];
            func_name = (char *)pModule + pModule->import_table + rep->target2;
            memcpy( buffer, func_name+1, *func_name );
            buffer[(BYTE)*func_name] = '\0';
            func_name = buffer;
            ordinal = NE_GetOrdinal( module, func_name );
            address = NE_GetEntryPoint( module, ordinal );

            if (ERR_ON(fixup) && !address)
            {
                NE_MODULE *pTarget = NE_GetPtr( module );
                ERR_(fixup)("No implementation for %.*s.%s, setting to 0xdeadbeef\n",
                    *((BYTE *)pTarget + pTarget->name_table),
                    (char *)pTarget + pTarget->name_table + 1, func_name );
            }
            if (!address) address = (FARPROC16) 0xdeadbeef;
            if (TRACE_ON(fixup))
            {
	        NE_MODULE *pTarget = NE_GetPtr( module );
                TRACE_(fixup)("%d: %.*s.%s=%04x:%04x %s\n", i + 1,
                       *((BYTE *)pTarget + pTarget->name_table),
                       (char *)pTarget + pTarget->name_table + 1,
                       func_name, HIWORD(address), LOWORD(address),
                       NE_GetRelocAddrName( rep->address_type, additive ) );
            }
	    break;

	  case NE_RELTYPE_INTERNAL:
	    if ((rep->target1 & 0xff) == 0xff)
	    {
		address  = NE_GetEntryPoint( pModule->self, rep->target2 );
	    }
	    else
	    {
                address = (FARPROC16)MAKESEGPTR( SEL(pSegTable[rep->target1-1].hSeg), rep->target2 );
	    }

	    TRACE_(fixup)("%d: %04x:%04x %s\n",
                   i + 1, HIWORD(address), LOWORD(address),
                   NE_GetRelocAddrName( rep->address_type, additive ) );
	    break;

	  case NE_RELTYPE_OSFIXUP:
	    /* Relocation type 7:
	     *
	     *    These appear to be used as fixups for the Windows
	     * floating point emulator.  Let's just ignore them and
	     * try to use the hardware floating point.  Linux should
	     * successfully emulate the coprocessor if it doesn't
	     * exist.
	     */
	    TRACE_(fixup)("%d: TYPE %d, OFFSET %04x, TARGET %04x %04x %s\n",
                   i + 1, rep->relocation_type, rep->offset,
                   rep->target1, rep->target2,
                   NE_GetRelocAddrName( rep->address_type, additive ) );
	    continue;
	}

	offset  = rep->offset;

        /* Apparently, high bit of address_type is sometimes set; */
        /* we ignore it for now */
	if (rep->address_type > NE_RADDR_OFFSET32)
        {
            char module[10];
            GetModuleName16( pModule->self, module, sizeof(module) );
            ERR_(fixup)("WARNING: module %s: unknown reloc addr type = 0x%02x. Please report.\n",
                 module, rep->address_type );
        }

        if (additive)
        {
            sp = MapSL( MAKESEGPTR( SEL(pSeg->hSeg), offset ) );
            TRACE_(fixup)("    %04x:%04x\n", offset, *sp );
            switch (rep->address_type & 0x7f)
            {
            case NE_RADDR_LOWBYTE:
                *(BYTE *)sp += LOBYTE((int)address);
                break;
            case NE_RADDR_OFFSET16:
		*sp += LOWORD(address);
                break;
            case NE_RADDR_POINTER32:
		*sp += LOWORD(address);
		*(sp+1) = HIWORD(address);
                break;
            case NE_RADDR_SELECTOR:
		/* Borland creates additive records with offset zero. Strange, but OK */
                if (*sp)
                    ERR_(fixup)("Additive selector to %04x.Please report\n",*sp);
		else
                    *sp = HIWORD(address);
                break;
            default:
                goto unknown;
            }
        }
        else  /* non-additive fixup */
        {
            do
            {
                sp = MapSL( MAKESEGPTR( SEL(pSeg->hSeg), offset ) );
                next_offset = *sp;
                TRACE_(fixup)("    %04x:%04x\n", offset, *sp );
                switch (rep->address_type & 0x7f)
                {
                case NE_RADDR_LOWBYTE:
                    *(BYTE *)sp = LOBYTE((int)address);
                    break;
                case NE_RADDR_OFFSET16:
                    *sp = LOWORD(address);
                    break;
                case NE_RADDR_POINTER32:
                    *(FARPROC16 *)sp = address;
                    break;
                case NE_RADDR_SELECTOR:
                    *sp = SELECTOROF(address);
                    break;
                default:
                    goto unknown;
                }
                if (next_offset == offset) break;  /* avoid infinite loop */
                if (next_offset >= GlobalSize16(pSeg->hSeg)) break;
                offset = next_offset;
            } while (offset != 0xffff);
        }
    }

    HeapFree(GetProcessHeap(), 0, reloc_entries);
    return TRUE;

unknown:
    WARN_(fixup)("WARNING: %d: unknown ADDR TYPE %d,  "
         "TYPE %d,  OFFSET %04x,  TARGET %04x %04x\n",
         i + 1, rep->address_type, rep->relocation_type,
         rep->offset, rep->target1, rep->target2);
    HeapFree(GetProcessHeap(), 0, reloc_entries);
    return FALSE;
}