Exemplo n.º 1
0
/***********************************************************************
 *           WOWTHUNK_Init
 */
BOOL WOWTHUNK_Init(void)
{
    /* allocate the code selector for CallTo16 routines */
    LDT_ENTRY entry;
    WORD codesel = wine_ldt_alloc_entries(1);

    if (!codesel) return FALSE;
    wine_ldt_set_base( &entry, __wine_call16_start );
    wine_ldt_set_limit( &entry, (BYTE *)(&CallTo16_TebSelector + 1) - __wine_call16_start - 1 );
    wine_ldt_set_flags( &entry, WINE_LDT_FLAGS_CODE | WINE_LDT_FLAGS_32BIT );
    wine_ldt_set_entry( codesel, &entry );

      /* Patch the return addresses for CallTo16 routines */

    CallTo16_DataSelector = wine_get_ds();
    call16_ret_addr = MAKESEGPTR( codesel, (BYTE *)__wine_call_to_16_ret - __wine_call16_start );
    CALL32_CBClient_RetAddr =
        MAKESEGPTR( codesel, (BYTE *)CALL32_CBClient_Ret - __wine_call16_start );
    CALL32_CBClientEx_RetAddr =
        MAKESEGPTR( codesel, (BYTE *)CALL32_CBClientEx_Ret - __wine_call16_start );

    /* Prepare selector and offsets for DPMI event checking. */
    dpmi_checker_selector = codesel;
    dpmi_checker_offset_call = (BYTE *)DPMI_PendingEventCheck - __wine_call16_start;
    dpmi_checker_offset_cleanup = (BYTE *)DPMI_PendingEventCheck_Cleanup - __wine_call16_start;
    dpmi_checker_offset_return = (BYTE *)DPMI_PendingEventCheck_Return - __wine_call16_start;

    if (TRACE_ON(relay) || TRACE_ON(snoop)) RELAY16_InitDebugLists();

    return TRUE;
}
Exemplo n.º 2
0
/**************************************************************************
 *		DllEntryPoint   (KERNEL.669)
 */
BOOL WINAPI KERNEL_DllEntryPoint( DWORD reasion, HINSTANCE16 inst, WORD ds,
                                  WORD heap, DWORD reserved1, WORD reserved2 )
{
    static BOOL done;

    /* the entry point can be called multiple times */
    if (done) return TRUE;
    done = TRUE;

    /* create the shared heap for broken win95 native dlls */
    HeapCreate( HEAP_SHARED, 0, 0 );

    /* setup emulation of protected instructions from 32-bit code */
    if (GetVersion() & 0x80000000) RtlAddVectoredExceptionHandler( TRUE, INSTR_vectored_handler );

    /* Initialize 16-bit thunking entry points */
    if (!WOWTHUNK_Init()) return FALSE;

    /* Initialize DOS memory */
    if (!DOSMEM_Init()) return FALSE;

    /* Initialize special KERNEL entry points */

    NE_SetEntryPoint( inst, 178, GetWinFlags16() );

    NE_SetEntryPoint( inst, 454, wine_get_cs() );
    NE_SetEntryPoint( inst, 455, wine_get_ds() );

    NE_SetEntryPoint( inst, 183, DOSMEM_0000H );       /* KERNEL.183: __0000H */
    NE_SetEntryPoint( inst, 173, DOSMEM_BiosSysSeg );  /* KERNEL.173: __ROMBIOS */
    NE_SetEntryPoint( inst, 193, DOSMEM_BiosDataSeg ); /* KERNEL.193: __0040H */
    NE_SetEntryPoint( inst, 194, DOSMEM_BiosSysSeg );  /* KERNEL.194: __F000H */

    /* Initialize KERNEL.THHOOK */
    TASK_InstallTHHook(MapSL((SEGPTR)GetProcAddress16( inst, (LPCSTR)332 )));
    TASK_CreateMainTask();

    /* Initialize the real-mode selector entry points */
#define SET_ENTRY_POINT( num, addr ) \
    NE_SetEntryPoint( inst, (num), GLOBAL_CreateBlock( GMEM_FIXED, \
                      DOSMEM_MapDosToLinear(addr), 0x10000, inst, \
                      WINE_LDT_FLAGS_DATA ))

    SET_ENTRY_POINT( 174, 0xa0000 );  /* KERNEL.174: __A000H */
    SET_ENTRY_POINT( 181, 0xb0000 );  /* KERNEL.181: __B000H */
    SET_ENTRY_POINT( 182, 0xb8000 );  /* KERNEL.182: __B800H */
    SET_ENTRY_POINT( 195, 0xc0000 );  /* KERNEL.195: __C000H */
    SET_ENTRY_POINT( 179, 0xd0000 );  /* KERNEL.179: __D000H */
    SET_ENTRY_POINT( 190, 0xe0000 );  /* KERNEL.190: __E000H */
#undef SET_ENTRY_POINT

    /* Force loading of some dlls */
    LoadLibrary16( "system.drv" );
    LoadLibrary16( "comm.drv" );

    return TRUE;
}
Exemplo n.º 3
0
/**************************************************************************
 *		DllEntryPoint   (KERNEL.669)
 */
BOOL WINAPI KERNEL_DllEntryPoint( DWORD reasion, HINSTANCE16 inst, WORD ds,
                                  WORD heap, DWORD reserved1, WORD reserved2 )
{
    static int done;

    /* the entry point can be called multiple times */
    if (done) return TRUE;
    done = 1;

    /* Initialize 16-bit thunking entry points */
    if (!WOWTHUNK_Init()) return FALSE;

    /* Initialize DOS memory */
    if (!DOSMEM_Init()) return FALSE;

    /* Initialize special KERNEL entry points */

    NE_SetEntryPoint( inst, 178, GetWinFlags16() );

    NE_SetEntryPoint( inst, 454, wine_get_cs() );
    NE_SetEntryPoint( inst, 455, wine_get_ds() );

    NE_SetEntryPoint( inst, 183, DOSMEM_0000H );       /* KERNEL.183: __0000H */
    NE_SetEntryPoint( inst, 173, DOSMEM_BiosSysSeg );  /* KERNEL.173: __ROMBIOS */
    NE_SetEntryPoint( inst, 193, DOSMEM_BiosDataSeg ); /* KERNEL.193: __0040H */
    NE_SetEntryPoint( inst, 194, DOSMEM_BiosSysSeg );  /* KERNEL.194: __F000H */

    /* Initialize KERNEL.THHOOK */
    TASK_InstallTHHook(MapSL((SEGPTR)GetProcAddress16( inst, (LPCSTR)332 )));

    /* Initialize the real-mode selector entry points */
#define SET_ENTRY_POINT( num, addr ) \
    NE_SetEntryPoint( inst, (num), GLOBAL_CreateBlock( GMEM_FIXED, \
                      DOSMEM_MapDosToLinear(addr), 0x10000, inst, \
                      WINE_LDT_FLAGS_DATA ))

    SET_ENTRY_POINT( 174, 0xa0000 );  /* KERNEL.174: __A000H */
    SET_ENTRY_POINT( 181, 0xb0000 );  /* KERNEL.181: __B000H */
    SET_ENTRY_POINT( 182, 0xb8000 );  /* KERNEL.182: __B800H */
    SET_ENTRY_POINT( 195, 0xc0000 );  /* KERNEL.195: __C000H */
    SET_ENTRY_POINT( 179, 0xd0000 );  /* KERNEL.179: __D000H */
    SET_ENTRY_POINT( 190, 0xe0000 );  /* KERNEL.190: __E000H */
#undef SET_ENTRY_POINT

    /* Force loading of some dlls */
    LoadLibrary16( "system.drv" );

    return TRUE;
}
Exemplo n.º 4
0
/**********************************************************************
 *           K32WOWCallback16Ex         (KERNEL32.55)
 */
BOOL WINAPI K32WOWCallback16Ex( DWORD vpfn16, DWORD dwFlags,
                                DWORD cbArgs, LPVOID pArgs, LPDWORD pdwRetCode )
{
#ifdef __i386__
    /*
     * Arguments must be prepared in the correct order by the caller
     * (both for PASCAL and CDECL calling convention), so we simply
     * copy them to the 16-bit stack ...
     */
    char *stack = (char *)CURRENT_STACK16 - cbArgs;

    memcpy( stack, pArgs, cbArgs );

    if (dwFlags & (WCB16_REGS|WCB16_REGS_LONG))
    {
        CONTEXT *context = (CONTEXT *)pdwRetCode;

        if (TRACE_ON(relay))
        {
            DWORD count = cbArgs / sizeof(WORD);
            WORD * wstack = (WORD *)stack;

            DPRINTF("%04lx:CallTo16(func=%04lx:%04x,ds=%04lx",
                    GetCurrentThreadId(),
                    context->SegCs, LOWORD(context->Eip), context->SegDs );
            while (count) DPRINTF( ",%04x", wstack[--count] );
            DPRINTF(") ss:sp=%04x:%04x",
                    SELECTOROF(NtCurrentTeb()->WOW32Reserved), OFFSETOF(NtCurrentTeb()->WOW32Reserved) );
            DPRINTF(" ax=%04x bx=%04x cx=%04x dx=%04x si=%04x di=%04x bp=%04x es=%04x fs=%04x\n",
                    (WORD)context->Eax, (WORD)context->Ebx, (WORD)context->Ecx,
                    (WORD)context->Edx, (WORD)context->Esi, (WORD)context->Edi,
                    (WORD)context->Ebp, (WORD)context->SegEs, (WORD)context->SegFs );
            SYSLEVEL_CheckNotLevel( 2 );
        }

        if (context->EFlags & 0x00020000)  /* v86 mode */
        {
            EXCEPTION_REGISTRATION_RECORD frame;
            frame.Handler = vm86_handler;
            __wine_push_frame( &frame );
            __wine_enter_vm86( context );
            __wine_pop_frame( &frame );
        }
        else
        {
            /* push return address */
            if (dwFlags & WCB16_REGS_LONG)
            {
                stack -= sizeof(DWORD);
                *((DWORD *)stack) = HIWORD(call16_ret_addr);
                stack -= sizeof(DWORD);
                *((DWORD *)stack) = LOWORD(call16_ret_addr);
                cbArgs += 2 * sizeof(DWORD);
            }
            else
            {
                stack -= sizeof(SEGPTR);
                *((SEGPTR *)stack) = call16_ret_addr;
                cbArgs += sizeof(SEGPTR);
            }

            /*
             * Start call by checking for pending events.
             * Note that wine_call_to_16_regs overwrites context stack
             * pointer so we may modify it here without a problem.
             */
            if (NtCurrentTeb()->dpmi_vif)
            {
                context->SegSs = wine_get_ds();
                context->Esp   = (DWORD)stack;
                insert_event_check( context );
                cbArgs += (DWORD)stack - context->Esp;
            }

            _EnterWin16Lock();
            wine_call_to_16_regs( context, cbArgs, call16_handler );
            _LeaveWin16Lock();
        }

        if (TRACE_ON(relay))
        {
            DPRINTF("%04lx:RetFrom16() ss:sp=%04x:%04x ",
                    GetCurrentThreadId(), SELECTOROF(NtCurrentTeb()->WOW32Reserved),
                    OFFSETOF(NtCurrentTeb()->WOW32Reserved));
            DPRINTF(" ax=%04x bx=%04x cx=%04x dx=%04x bp=%04x sp=%04x\n",
                    (WORD)context->Eax, (WORD)context->Ebx, (WORD)context->Ecx,
                    (WORD)context->Edx, (WORD)context->Ebp, (WORD)context->Esp );
            SYSLEVEL_CheckNotLevel( 2 );
        }
    }
    else
    {
        DWORD ret;

        if (TRACE_ON(relay))
        {
            DWORD count = cbArgs / sizeof(WORD);
            WORD * wstack = (WORD *)stack;

            DPRINTF("%04lx:CallTo16(func=%04x:%04x,ds=%04x",
                    GetCurrentThreadId(), HIWORD(vpfn16), LOWORD(vpfn16),
                    SELECTOROF(NtCurrentTeb()->WOW32Reserved) );
            while (count) DPRINTF( ",%04x", wstack[--count] );
            DPRINTF(") ss:sp=%04x:%04x\n",
                    SELECTOROF(NtCurrentTeb()->WOW32Reserved), OFFSETOF(NtCurrentTeb()->WOW32Reserved) );
            SYSLEVEL_CheckNotLevel( 2 );
        }

        /* push return address */
        stack -= sizeof(SEGPTR);
        *((SEGPTR *)stack) = call16_ret_addr;
        cbArgs += sizeof(SEGPTR);

        /*
         * Actually, we should take care whether the called routine cleans up
         * its stack or not.  Fortunately, our wine_call_to_16 core doesn't rely on
         * the callee to do so; after the routine has returned, the 16-bit
         * stack pointer is always reset to the position it had before.
         */
        _EnterWin16Lock();
        ret = wine_call_to_16( (FARPROC16)vpfn16, cbArgs, call16_handler );
        if (pdwRetCode) *pdwRetCode = ret;
        _LeaveWin16Lock();

        if (TRACE_ON(relay))
        {
            DPRINTF("%04lx:RetFrom16() ss:sp=%04x:%04x retval=%08lx\n",
                    GetCurrentThreadId(), SELECTOROF(NtCurrentTeb()->WOW32Reserved),
                    OFFSETOF(NtCurrentTeb()->WOW32Reserved), ret);
            SYSLEVEL_CheckNotLevel( 2 );
        }
    }
#else
    assert(0);  /* cannot call to 16-bit on non-Intel architectures */
#endif  /* __i386__ */

    return TRUE;  /* success */
}
Exemplo n.º 5
0
/**********************************************************************
 *           K32WOWCallback16Ex         (KERNEL32.55)
 */
BOOL WINAPI K32WOWCallback16Ex( DWORD vpfn16, DWORD dwFlags,
                                DWORD cbArgs, LPVOID pArgs, LPDWORD pdwRetCode )
{
    /*
     * Arguments must be prepared in the correct order by the caller
     * (both for PASCAL and CDECL calling convention), so we simply
     * copy them to the 16-bit stack ...
     */
    char *stack = (char *)CURRENT_STACK16 - cbArgs;

    memcpy( stack, pArgs, cbArgs );

    if (dwFlags & (WCB16_REGS|WCB16_REGS_LONG))
    {
        CONTEXT *context = (CONTEXT *)pdwRetCode;

        if (TRACE_ON(relay))
        {
            DWORD count = cbArgs / sizeof(WORD);
            WORD * wstack = (WORD *)stack;

            TRACE_(relay)( "\1CallTo16(func=%04x:%04x", context->SegCs, LOWORD(context->Eip) );
            while (count) TRACE_(relay)( ",%04x", wstack[--count] );
            TRACE_(relay)( ") ss:sp=%04x:%04x ax=%04x bx=%04x cx=%04x dx=%04x si=%04x di=%04x bp=%04x ds=%04x es=%04x\n",
                           SELECTOROF(NtCurrentTeb()->WOW32Reserved),
                           OFFSETOF(NtCurrentTeb()->WOW32Reserved),
                           (WORD)context->Eax, (WORD)context->Ebx, (WORD)context->Ecx,
                           (WORD)context->Edx, (WORD)context->Esi, (WORD)context->Edi,
                           (WORD)context->Ebp, (WORD)context->SegDs, (WORD)context->SegEs );
            SYSLEVEL_CheckNotLevel( 2 );
        }

        if (context->EFlags & 0x00020000)  /* v86 mode */
        {
            EXCEPTION_REGISTRATION_RECORD frame;
            frame.Handler = vm86_handler;
            errno = 0;
            __wine_push_frame( &frame );
            __wine_enter_vm86( context );
            __wine_pop_frame( &frame );
            if (errno != 0)  /* enter_vm86 will fail with ENOSYS on x64 kernels */
            {
                WARN("__wine_enter_vm86 failed (errno=%d)\n", errno);
                if (errno == ENOSYS)
                    SetLastError(ERROR_NOT_SUPPORTED);
                else
                    SetLastError(ERROR_GEN_FAILURE);
                return FALSE;
            }
        }
        else
        {
            /* push return address */
            if (dwFlags & WCB16_REGS_LONG)
            {
                stack -= sizeof(DWORD);
                *((DWORD *)stack) = HIWORD(call16_ret_addr);
                stack -= sizeof(DWORD);
                *((DWORD *)stack) = LOWORD(call16_ret_addr);
                cbArgs += 2 * sizeof(DWORD);
            }
            else
            {
                stack -= sizeof(SEGPTR);
                *((SEGPTR *)stack) = call16_ret_addr;
                cbArgs += sizeof(SEGPTR);
            }

            /*
             * Start call by checking for pending events.
             * Note that wine_call_to_16_regs overwrites context stack
             * pointer so we may modify it here without a problem.
             */
            if (get_vm86_teb_info()->dpmi_vif)
            {
                context->SegSs = wine_get_ds();
                context->Esp   = (DWORD)stack;
                insert_event_check( context );
                cbArgs += (DWORD)stack - context->Esp;
            }

            _EnterWin16Lock();
            wine_call_to_16_regs( context, cbArgs, call16_handler );
            _LeaveWin16Lock();
        }

        if (TRACE_ON(relay))
        {
            TRACE_(relay)( "\1RetFrom16() ss:sp=%04x:%04x ax=%04x bx=%04x cx=%04x dx=%04x bp=%04x sp=%04x\n",
                           SELECTOROF(NtCurrentTeb()->WOW32Reserved),
                           OFFSETOF(NtCurrentTeb()->WOW32Reserved),
                           (WORD)context->Eax, (WORD)context->Ebx, (WORD)context->Ecx,
                           (WORD)context->Edx, (WORD)context->Ebp, (WORD)context->Esp );
            SYSLEVEL_CheckNotLevel( 2 );
        }
    }
    else
    {
        DWORD ret;

        if (TRACE_ON(relay))
        {
            DWORD count = cbArgs / sizeof(WORD);
            WORD * wstack = (WORD *)stack;

            TRACE_(relay)( "\1CallTo16(func=%04x:%04x,ds=%04x",
                           HIWORD(vpfn16), LOWORD(vpfn16), SELECTOROF(NtCurrentTeb()->WOW32Reserved) );
            while (count) TRACE_(relay)( ",%04x", wstack[--count] );
            TRACE_(relay)( ") ss:sp=%04x:%04x\n", SELECTOROF(NtCurrentTeb()->WOW32Reserved),
                           OFFSETOF(NtCurrentTeb()->WOW32Reserved) );
            SYSLEVEL_CheckNotLevel( 2 );
        }

        /* push return address */
        stack -= sizeof(SEGPTR);
        *((SEGPTR *)stack) = call16_ret_addr;
        cbArgs += sizeof(SEGPTR);

        /*
         * Actually, we should take care whether the called routine cleans up
         * its stack or not.  Fortunately, our wine_call_to_16 core doesn't rely on
         * the callee to do so; after the routine has returned, the 16-bit
         * stack pointer is always reset to the position it had before.
         */
        _EnterWin16Lock();
        ret = wine_call_to_16( (FARPROC16)vpfn16, cbArgs, call16_handler );
        if (pdwRetCode) *pdwRetCode = ret;
        _LeaveWin16Lock();

        if (TRACE_ON(relay))
        {
            TRACE_(relay)( "\1RetFrom16() ss:sp=%04x:%04x retval=%08x\n",
                           SELECTOROF(NtCurrentTeb()->WOW32Reserved),
                           OFFSETOF(NtCurrentTeb()->WOW32Reserved), ret );
            SYSLEVEL_CheckNotLevel( 2 );
        }
    }

    return TRUE;  /* success */
}