Beispiel #1
0
/***********************************************************************
 *           MakeProcInstance  (KERNEL.51)
 */
FARPROC16 WINAPI MakeProcInstance16( FARPROC16 func, HANDLE16 hInstance )
{
    struct thunk *thunk;
    BYTE *lfunc;
    SEGPTR thunkaddr;
    WORD hInstanceSelector;

    hInstanceSelector = GlobalHandleToSel16(hInstance);

    TRACE("(%p, %04x);\n", func, hInstance);

    if (!HIWORD(func)) {
      /* Win95 actually protects via SEH, but this is better for debugging */
      WARN("Ouch ! Called with invalid func %p !\n", func);
      return NULL;
    }

    if ( (GlobalHandleToSel16(CURRENT_DS) != hInstanceSelector)
      && (hInstance != 0)
      && (hInstance != 0xffff) )
    {
	/* calling MPI with a foreign DSEG is invalid ! */
        WARN("Problem with hInstance? Got %04x, using %04x instead\n",
                   hInstance,CURRENT_DS);
    }

    /* Always use the DSEG that MPI was entered with.
     * We used to set hInstance to GetTaskDS16(), but this should be wrong
     * as CURRENT_DS provides the DSEG value we need.
     * ("calling" DS, *not* "task" DS !) */
    hInstanceSelector = CURRENT_DS;
    hInstance = GlobalHandle16(hInstanceSelector);

    /* no thunking for DLLs */
    if (NE_GetPtr(FarGetOwner16(hInstance))->ne_flags & NE_FFLAGS_LIBMODULE)
	return func;

    thunkaddr = TASK_AllocThunk();
    if (!thunkaddr) return NULL;
    thunk = MapSL( thunkaddr );
    lfunc = MapSL( (SEGPTR)func );

    TRACE("(%p,%04x): got thunk %08x\n", func, hInstance, thunkaddr );
    if (((lfunc[0]==0x8c) && (lfunc[1]==0xd8)) || /* movw %ds, %ax */
    	((lfunc[0]==0x1e) && (lfunc[1]==0x58))    /* pushw %ds, popw %ax */
    ) {
    	WARN("This was the (in)famous \"thunk useless\" warning. We thought we have to overwrite with nop;nop;, but this isn't true.\n");
    }

    thunk->movw     = 0xb8;    /* movw instance, %ax */
    thunk->instance = hInstanceSelector;
    thunk->ljmp     = 0xea;    /* ljmp func */
    thunk->func     = func;
    return (FARPROC16)thunkaddr;
    /* CX reg indicates if thunkaddr != NULL, implement if needed */
}
Beispiel #2
0
/**********************************************************************
 *	    GetCodeInfo    (KERNEL.104)
 */
BOOL16 WINAPI GetCodeInfo16( FARPROC16 proc, SEGINFO *segInfo )
{
    NE_MODULE *pModule;
    SEGTABLEENTRY *pSeg;
    int segNr;

    if ( !TASK_GetCodeSegment( proc, &pModule, &pSeg, &segNr ) )
        return FALSE;

    /* Fill in segment information */

    segInfo->offSegment = pSeg->filepos;
    segInfo->cbSegment  = pSeg->size;
    segInfo->flags      = pSeg->flags;
    segInfo->cbAlloc    = pSeg->minsize;
    segInfo->h          = pSeg->hSeg;
    segInfo->alignShift = pModule->ne_align;

    if ( segNr == pModule->ne_autodata )
        segInfo->cbAlloc += pModule->ne_heap + pModule->ne_stack;

    /* Return module handle in %es */

    CURRENT_STACK16->es = GlobalHandleToSel16( pModule->self );

    return TRUE;
}
Beispiel #3
0
/***********************************************************************
 *           GetTaskDS   (KERNEL.155)
 *
 * Note: this function apparently returns a DWORD with LOWORD == HIWORD.
 * I don't think we need to bother with this.
 */
HINSTANCE16 WINAPI GetTaskDS16(void)
{
    TDB *pTask;

    if (!(pTask = TASK_GetCurrent())) return 0;
    return GlobalHandleToSel16(pTask->hInstance);
}
Beispiel #4
0
/***********************************************************************
 *           TaskNext   (TOOLHELP.64)
 */
BOOL16 WINAPI TaskNext16( TASKENTRY *lpte )
{
    TDB *pTask;
    INSTANCEDATA *pInstData;

    TRACE_(toolhelp)("(%p): task=%04x\n", lpte, lpte->hNext );
    if (!lpte->hNext) return FALSE;

    /* make sure that task and hInstance are valid (skip initial Wine task !) */
    while (1) {
        pTask = TASK_GetPtr( lpte->hNext );
        if (!pTask || pTask->magic != TDB_MAGIC) return FALSE;
        if (pTask->hInstance)
            break;
        lpte->hNext = pTask->hNext;
    }
    pInstData = MapSL( MAKESEGPTR( GlobalHandleToSel16(pTask->hInstance), 0 ) );
    lpte->hTask         = lpte->hNext;
    lpte->hTaskParent   = pTask->hParent;
    lpte->hInst         = pTask->hInstance;
    lpte->hModule       = pTask->hModule;
    lpte->wSS           = SELECTOROF( pTask->teb->WOW32Reserved );
    lpte->wSP           = OFFSETOF( pTask->teb->WOW32Reserved );
    lpte->wStackTop     = pInstData->stacktop;
    lpte->wStackMinimum = pInstData->stackmin;
    lpte->wStackBottom  = pInstData->stackbottom;
    lpte->wcEvents      = pTask->nEvents;
    lpte->hQueue        = pTask->hQueue;
    lstrcpynA( lpte->szModule, pTask->module_name, sizeof(lpte->szModule) );
    lpte->wPSPOffset    = 0x100;  /*??*/
    lpte->hNext         = pTask->hNext;
    return TRUE;
}
Beispiel #5
0
/***********************************************************************
 *           InitTask  (KERNEL.91)
 *
 * Called by the application startup code.
 */
void WINAPI InitTask16( CONTEXT *context )
{
    TDB *pTask;
    INSTANCEDATA *pinstance;
    SEGPTR ptr;

    context->Eax = 0;
    if (!(pTask = TASK_GetCurrent())) return;

    /* Note: we need to trust that BX/CX contain the stack/heap sizes,
       as some apps, notably Visual Basic apps, *modify* the heap/stack
       size of the instance data segment before calling InitTask() */

    /* Initialize the INSTANCEDATA structure */
    pinstance = MapSL( MAKESEGPTR(CURRENT_DS, 0) );
    pinstance->stackmin    = OFFSETOF(NtCurrentTeb()->WOW32Reserved) + sizeof( STACK16FRAME );
    pinstance->stackbottom = pinstance->stackmin; /* yup, that's right. Confused me too. */
    pinstance->stacktop    = ( pinstance->stackmin > LOWORD(context->Ebx) ?
                               pinstance->stackmin - LOWORD(context->Ebx) : 0 ) + 150;

    /* Initialize the local heap */
    if (LOWORD(context->Ecx))
        LocalInit16( GlobalHandleToSel16(pTask->hInstance), 0, LOWORD(context->Ecx) );

    /* Initialize implicitly loaded DLLs */
    NE_InitializeDLLs( pTask->hModule );
    NE_DllProcessAttach( pTask->hModule );

    /* Registers on return are:
     * ax     1 if OK, 0 on error
     * cx     stack limit in bytes
     * dx     cmdShow parameter
     * si     instance handle of the previous instance
     * di     instance handle of the new task
     * es:bx  pointer to command line inside PSP
     *
     * 0 (=%bp) is pushed on the stack
     */
    ptr = stack16_push( sizeof(WORD) );
    *(WORD *)MapSL(ptr) = 0;
    context->Esp -= 2;

    context->Eax = 1;

    if (!pTask->pdb.cmdLine[0]) context->Ebx = 0x80;
    else
    {
        LPBYTE p = &pTask->pdb.cmdLine[1];
        while ((*p == ' ') || (*p == '\t')) p++;
        context->Ebx = 0x80 + (p - pTask->pdb.cmdLine);
    }
    context->Ecx   = pinstance->stacktop;
    context->Edx   = pTask->nCmdShow;
    context->Esi   = (DWORD)pTask->hPrevInstance;
    context->Edi   = (DWORD)pTask->hInstance;
    context->SegEs = (WORD)pTask->hPDB;
}
Beispiel #6
0
/***********************************************************************
 *           KERNEL thread initialisation routine
 */
static void thread_attach(void)
{
    /* allocate the 16-bit stack (FIXME: should be done lazily) */
    HGLOBAL16 hstack = WOWGlobalAlloc16( GMEM_FIXED, 0x10000 );
    kernel_get_thread_data()->stack_sel = GlobalHandleToSel16( hstack );
    NtCurrentTeb()->WOW32Reserved = (void *)MAKESEGPTR( kernel_get_thread_data()->stack_sel,
                                                        0x10000 - sizeof(STACK16FRAME) );
    memset( (char *)GlobalLock16(hstack) + 0x10000 - sizeof(STACK16FRAME), 0, sizeof(STACK16FRAME) );
}
Beispiel #7
0
/***********************************************************************
 *           GetDummyModuleHandleDS   (KERNEL.602)
 */
WORD WINAPI GetDummyModuleHandleDS16(void)
{
    TDB *pTask;
    WORD selector;

    if (!(pTask = TASK_GetCurrent())) return 0;
    if (!(pTask->flags & TDBF_WIN32)) return 0;
    selector = GlobalHandleToSel16( pTask->hModule );
    CURRENT_DS = selector;
    return selector;
}
Beispiel #8
0
/**********************************************************************
 *	    TASK_GetCodeSegment
 *
 * Helper function for GetCodeHandle/GetCodeInfo: Retrieve the module
 * and logical segment number of a given code segment.
 *
 * 'proc' either *is* already a pair of module handle and segment number,
 * in which case there's nothing to do.  Otherwise, it is a pointer to
 * a function, and we need to retrieve the code segment.  If the pointer
 * happens to point to a thunk, we'll retrieve info about the code segment
 * where the function pointed to by the thunk resides, not the thunk itself.
 *
 * FIXME: if 'proc' is a SNOOP16 return stub, we should retrieve info about
 *        the function the snoop code will return to ...
 *
 */
static BOOL TASK_GetCodeSegment( FARPROC16 proc, NE_MODULE **ppModule,
                                 SEGTABLEENTRY **ppSeg, int *pSegNr )
{
    NE_MODULE *pModule = NULL;
    SEGTABLEENTRY *pSeg = NULL;
    int segNr=0;

    /* Try pair of module handle / segment number */
    pModule = GlobalLock16( HIWORD( proc ) );
    if ( pModule && pModule->ne_magic == IMAGE_OS2_SIGNATURE )
    {
        segNr = LOWORD( proc );
        if ( segNr && segNr <= pModule->ne_cseg )
            pSeg = NE_SEG_TABLE( pModule ) + segNr-1;
    }

    /* Try thunk or function */
    else
    {
        BYTE *thunk = MapSL( (SEGPTR)proc );
        WORD selector;

        if ((thunk[0] == 0xb8) && (thunk[3] == 0xea))
            selector = thunk[6] + (thunk[7] << 8);
        else
            selector = HIWORD( proc );

        pModule = NE_GetPtr( GlobalHandle16( selector ) );
        pSeg = pModule? NE_SEG_TABLE( pModule ) : NULL;

        if ( pModule )
            for ( segNr = 1; segNr <= pModule->ne_cseg; segNr++, pSeg++ )
                if ( GlobalHandleToSel16(pSeg->hSeg) == selector )
                    break;

        if ( pModule && segNr > pModule->ne_cseg )
            pSeg = NULL;
    }

    /* Abort if segment not found */

    if ( !pModule || !pSeg )
        return FALSE;

    /* Return segment data */

    if ( ppModule ) *ppModule = pModule;
    if ( ppSeg    ) *ppSeg    = pSeg;
    if ( pSegNr   ) *pSegNr   = segNr;

    return TRUE;
}
Beispiel #9
0
/***********************************************************************
 *           TASK_Create
 *
 * NOTE: This routine might be called by a Win32 thread. Thus, we need
 *       to be careful to protect global data structures. We do this
 *       by entering the Win16Lock while linking the task into the
 *       global task list.
 */
static TDB *TASK_Create( NE_MODULE *pModule, UINT16 cmdShow, LPCSTR cmdline, BYTE len )
{
    HTASK16 hTask;
    TDB *pTask;
    FARPROC16 proc;
    char curdir[MAX_PATH];
    HMODULE16 hModule = pModule ? pModule->self : 0;

      /* Allocate the task structure */

    hTask = GlobalAlloc16( GMEM_FIXED | GMEM_ZEROINIT, sizeof(TDB) );
    if (!hTask) return NULL;
    pTask = TASK_GetPtr( hTask );
    FarSetOwner16( hTask, hModule );

    /* Fill the task structure */

    pTask->hSelf = hTask;

    pTask->version       = pModule ? pModule->ne_expver : 0x0400;
    pTask->hModule       = hModule;
    pTask->hParent       = GetCurrentTask();
    pTask->magic         = TDB_MAGIC;
    pTask->nCmdShow      = cmdShow;

    GetCurrentDirectoryA( sizeof(curdir), curdir );
    GetShortPathNameA( curdir, curdir, sizeof(curdir) );
    pTask->curdrive = (curdir[0] - 'A') | 0x80;
    lstrcpynA( pTask->curdir, curdir + 2, sizeof(pTask->curdir) );

      /* Create the thunks block */

    TASK_CreateThunks( hTask, (char *)pTask->thunks - (char *)pTask, 7 );

      /* Copy the module name */

    if (hModule)
    {
        char name[sizeof(pTask->module_name)+1];
        size_t len;
        GetModuleName16( hModule, name, sizeof(name) );
        len = strlen(name) + 1;
        memcpy(pTask->module_name, name, min(len,sizeof(pTask->module_name)));
        pTask->compat_flags = GetProfileIntA( "Compatibility", name, 0 );
    }

      /* Allocate a selector for the PDB */

    pTask->hPDB = GLOBAL_CreateBlock( GMEM_FIXED, &pTask->pdb, sizeof(PDB16),
                                      hModule, WINE_LDT_FLAGS_DATA );

      /* Fill the PDB */

    pTask->pdb.int20 = 0x20cd;
    pTask->pdb.dispatcher[0] = 0x9a;  /* ljmp */
    proc = GetProcAddress16( GetModuleHandle16("KERNEL"), "DOS3Call" );
    memcpy( &pTask->pdb.dispatcher[1], &proc, sizeof(proc) );
    pTask->pdb.savedint22 = 0;
    pTask->pdb.savedint23 = 0;
    pTask->pdb.savedint24 = 0;
    pTask->pdb.fileHandlesPtr =
        MAKESEGPTR( GlobalHandleToSel16(pTask->hPDB), FIELD_OFFSET( PDB16, fileHandles ));
    pTask->pdb.hFileHandles = 0;
    memset( pTask->pdb.fileHandles, 0xff, sizeof(pTask->pdb.fileHandles) );
    /* FIXME: should we make a copy of the environment? */
    pTask->pdb.environment    = SELECTOROF(GetDOSEnvironment16());
    pTask->pdb.nbFiles        = 20;

    /* Fill the command line */

    if (!cmdline)
    {
        cmdline = GetCommandLineA();
        /* remove the first word (program name) */
        if (*cmdline == '"')
            if (!(cmdline = strchr( cmdline+1, '"' ))) cmdline = GetCommandLineA();
        while (*cmdline && (*cmdline != ' ') && (*cmdline != '\t')) cmdline++;
        while ((*cmdline == ' ') || (*cmdline == '\t')) cmdline++;
        len = strlen(cmdline);
    }
    if (len >= sizeof(pTask->pdb.cmdLine)) len = sizeof(pTask->pdb.cmdLine)-1;
    pTask->pdb.cmdLine[0] = len;
    memcpy( pTask->pdb.cmdLine + 1, cmdline, len );
    /* pTask->pdb.cmdLine[len+1] = 0; */

    TRACE("cmdline='%.*s' task=%04x\n", len, cmdline, hTask );

      /* Allocate a code segment alias for the TDB */

    pTask->hCSAlias = GLOBAL_CreateBlock( GMEM_FIXED, pTask, sizeof(TDB),
                                          pTask->hPDB, WINE_LDT_FLAGS_CODE );

      /* Default DTA overwrites command line */

    pTask->dta = MAKESEGPTR( pTask->hPDB, FIELD_OFFSET( PDB16, cmdLine ));

    /* Create scheduler event for 16-bit tasks */

    if ( !(pTask->flags & TDBF_WIN32) )
        NtCreateEvent( &pTask->hEvent, EVENT_ALL_ACCESS, NULL, NotificationEvent, FALSE );

    if (!initial_task) initial_task = hTask;

    return pTask;
}
Beispiel #10
0
/***********************************************************************
 *           GetTaskQueueES  (KERNEL.119)
 */
void WINAPI GetTaskQueueES16(void)
{
    CURRENT_STACK16->es = GlobalHandleToSel16( GetTaskQueue16(0) );
}
Beispiel #11
0
void WINAPI SNOOP16_Entry(FARPROC proc, LPBYTE args, CONTEXT86 *context) {
	DWORD		ordinal=0;
	DWORD		entry=(DWORD)MapSL( MAKESEGPTR(context->SegCs,LOWORD(context->Eip)) )-5;
	WORD		xcs = context->SegCs;
	SNOOP16_DLL	*dll = firstdll;
	SNOOP16_FUN	*fun = NULL;
	SNOOP16_RETURNENTRIES	**rets = &firstrets;
	SNOOP16_RETURNENTRY	*ret;
	unsigned	i=0;
	int		max;

	while (dll) {
		if (xcs == dll->funhandle) {
			fun = (SNOOP16_FUN*)entry;
			ordinal = fun-dll->funs;
			break;
		}
		dll=dll->next;
	}
	if (!dll) {
		FIXME("entrypoint 0x%08x not found\n",entry);
		return; /* oops */
	}
	while (*rets) {
		for (i=0;i<sizeof((*rets)->entry)/sizeof((*rets)->entry[0]);i++)
			if (!(*rets)->entry[i].origreturn)
				break;
		if (i!=sizeof((*rets)->entry)/sizeof((*rets)->entry[0]))
			break;
		rets = &((*rets)->next);
	}
	if (!*rets) {
		HANDLE16 hand = GlobalHandleToSel16(GLOBAL_Alloc(GMEM_ZEROINIT,65535,0,WINE_LDT_FLAGS_CODE));
		*rets = GlobalLock16(hand);
		(*rets)->rethandle = hand;
		i = 0;	/* entry 0 is free */
	}
	ret = &((*rets)->entry[i]);
	ret->lcall 	= 0x9a;
	ret->snr	= MAKELONG(sizeof(SNOOP16_RELAY),xsnr);
	ret->origreturn	= (FARPROC16)CALLER1REF;
	CALLER1REF	= MAKELONG((char*)&(ret->lcall)-(char*)((*rets)->entry),(*rets)->rethandle);
	ret->dll	= dll;
	ret->args	= NULL;
	ret->ordinal	= ordinal;
	ret->origSP	= LOWORD(context->Esp);

	context->Eip= LOWORD(fun->origfun);
	context->SegCs = HIWORD(fun->origfun);


	DPRINTF("%04x:CALL %s.%d: %s(",GetCurrentThreadId(), dll->name,ordinal,fun->name);
	if (fun->nrofargs>0) {
		max = fun->nrofargs;
		if (max>16) max=16;
		for (i=max;i--;)
			DPRINTF("%04x%s",*(WORD*)((char *) MapSL( MAKESEGPTR(context->SegSs,LOWORD(context->Esp)) )+8+sizeof(WORD)*i),i?",":"");
		if (max!=fun->nrofargs)
			DPRINTF(" ...");
	} else if (fun->nrofargs<0) {
		DPRINTF("<unknown, check return>");
		ret->args = HeapAlloc(GetProcessHeap(),0,16*sizeof(WORD));
		memcpy(ret->args,(LPBYTE)((char *) MapSL( MAKESEGPTR(context->SegSs,LOWORD(context->Esp)) )+8),sizeof(WORD)*16);
	}
	DPRINTF(") ret=%04x:%04x\n",HIWORD(ret->origreturn),LOWORD(ret->origreturn));
}
Beispiel #12
0
void
SNOOP16_RegisterDLL(HMODULE16 hModule,LPCSTR name) {
	SNOOP16_DLL	**dll = &(firstdll);
	char		*s;

	if (!TRACE_ON(snoop)) return;

        TRACE("hmod=%x, name=%s\n", hModule, name);

	if (!snr) {
		xsnr=GLOBAL_Alloc(GMEM_ZEROINIT,2*sizeof(*snr),0,WINE_LDT_FLAGS_CODE|WINE_LDT_FLAGS_32BIT);
		snr = GlobalLock16(xsnr);
		snr[0].pushbp	= 0x5566;
		snr[0].pusheax	= 0x50;
		snr[0].pushax	= 0x5066;
		snr[0].pushl	= 0x68;
		snr[0].realfun	= (DWORD)SNOOP16_Entry;
		snr[0].lcall 	= 0x9a;
		snr[0].callfromregs = (DWORD)__wine_call_from_16_regs;
		snr[0].seg      = wine_get_cs();
		snr[0].lret     = 0xcb66;

		snr[1].pushbp	= 0x5566;
		snr[1].pusheax	= 0x50;
		snr[1].pushax	= 0x5066;
		snr[1].pushl	= 0x68;
		snr[1].realfun	= (DWORD)SNOOP16_Return;
		snr[1].lcall 	= 0x9a;
		snr[1].callfromregs = (DWORD)__wine_call_from_16_regs;
		snr[1].seg      = wine_get_cs();
		snr[1].lret     = 0xcb66;
	}
	while (*dll) {
		if ((*dll)->hmod == hModule)
                {
                    /* another dll, loaded at the same address */
                    GlobalUnlock16((*dll)->funhandle);
                    GlobalFree16((*dll)->funhandle);
                    break;
                }
		dll = &((*dll)->next);
	}

	if (*dll)
		*dll = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *dll, sizeof(SNOOP16_DLL)+strlen(name));
	else
		*dll = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(SNOOP16_DLL)+strlen(name));	

	(*dll)->next	= NULL;
	(*dll)->hmod	= hModule;
	if ((s=strrchr(name,'\\')))
		name = s+1;
	strcpy( (*dll)->name, name );
	if ((s=strrchr((*dll)->name,'.')))
		*s='\0';
	(*dll)->funhandle = GlobalHandleToSel16(GLOBAL_Alloc(GMEM_ZEROINIT,65535,0,WINE_LDT_FLAGS_CODE));
	(*dll)->funs = GlobalLock16((*dll)->funhandle);
	if (!(*dll)->funs) {
		HeapFree(GetProcessHeap(),0,*dll);
		FIXME("out of memory\n");
		return;
	}
}