Пример #1
0
/***********************************************************************
 *           WinNotify       (WINDEBUG.3)
 *  written without _any_ docu
 */
void WINAPI WinNotify16(CONTEXT86 *context)
{
	FIXME("(AX=%04x):stub.\n", AX_reg(context));
	switch (AX_reg(context))
	{
		case 0x000D:
		case 0x000E:
		case 0x0060:	/* do nothing */
				break;
		case 0x0062:
				break;
		case 0x0063:	/* do something complicated */
				break;
		case 0x0064:	/* do something complicated */
				break;
		case 0x0065:	/* do something complicated */
				break;
		case 0x0050:	/* do something complicated, now just return error */
				SET_CFLAG(context);
				break;
		case 0x0052:	/* do something complicated */
				break;
		default:
				break;
	}
}
Пример #2
0
void WINAPI VXD_TimerAPI ( CONTEXT86 *context )
{
    unsigned service = AX_reg(context);

    TRACE("[%04x] TimerAPI\n", (UINT16)service);

    switch(service)
    {
    case 0x0000: /* version */
        AX_reg(context) = VXD_WinVersion();
        RESET_CFLAG(context);
        break;

    case 0x0009: /* get system time selector */
        if ( !System_Time_Selector )
        {
            System_Time_Selector = SELECTOR_AllocBlock( &System_Time, sizeof(DWORD), WINE_LDT_FLAGS_DATA );
            CreateSystemTimer( 55, System_Time_Tick );
        }

        AX_reg(context) = System_Time_Selector;
        RESET_CFLAG(context);
        break;

    default:
        VXD_BARF( context, "VTDAPI" );
    }
}
Пример #3
0
/***********************************************************************
 *           VXD_Timer (WPROCS.405)
 */
void WINAPI VXD_Timer( CONTEXT86 *context )
{
    unsigned service = AX_reg(context);

    TRACE("[%04x] Virtual Timer\n", (UINT16)service);

    switch(service)
    {
    case 0x0000: /* version */
	AX_reg(context) = VXD_WinVersion();
	RESET_CFLAG(context);
	break;

    case 0x0100: /* clock tick time, in 840nsecs */
	context->Eax = NtGetTickCount();

	context->Edx = context->Eax >> 22;
	context->Eax <<= 10; /* not very precise */
	break;

    case 0x0101: /* current Windows time, msecs */
    case 0x0102: /* current VM time, msecs */
	context->Eax = NtGetTickCount();
	break;

    default:
	VXD_BARF( context, "VTD" );
    }
}
Пример #4
0
/**********************************************************************
 *	    INT_Int11Handler (WPROCS.117)
 *
 * Handler for int 11h (get equipment list).
 */
void WINAPI INT_Int11Handler( CONTEXT86 *context )
{
    int diskdrives = 0;
    int parallelports = 0;
    int serialports = 0;
    int x;

/* borrowed from Ralph Brown's interrupt lists

		    bits 15-14: number of parallel devices
		    bit     13: [Conv] Internal modem
		    bit     12: reserved
		    bits 11- 9: number of serial devices
		    bit      8: reserved
		    bits  7- 6: number of diskette drives minus one
		    bits  5- 4: Initial video mode:
				    00b = EGA,VGA,PGA
				    01b = 40 x 25 color
				    10b = 80 x 25 color
				    11b = 80 x 25 mono
		    bit      3: reserved
		    bit      2: [PS] =1 if pointing device
				[non-PS] reserved
		    bit      1: =1 if math co-processor
		    bit      0: =1 if diskette available for boot
*/
/*  Currently the only of these bits correctly set are:
		bits 15-14 		} Added by William Owen Smith,
		bits 11-9		} [email protected]
		bits 7-6
		bit  2			(always set)
*/

    if (GetDriveTypeA("A:\\") == DRIVE_REMOVABLE) diskdrives++;
    if (GetDriveTypeA("B:\\") == DRIVE_REMOVABLE) diskdrives++;
    if (diskdrives) diskdrives--;

    for (x=0; x < 9; x++)
    {
        char temp[16],name[16];

        sprintf(name,"COM%d",x+1);
        PROFILE_GetWineIniString("serialports",name,"*",temp,sizeof temp);
        if(strcmp(temp,"*"))
	    serialports++;

        sprintf(name,"LPT%d",x+1);
        PROFILE_GetWineIniString("parallelports",name,"*",temp,sizeof temp);
        if(strcmp(temp,"*"))
	    parallelports++;
    }
    if (serialports > 7)		/* 3 bits -- maximum value = 7 */
        serialports=7;
    if (parallelports > 3)		/* 2 bits -- maximum value = 3 */
        parallelports=3;

    AX_reg(context) = (diskdrives << 6) | (serialports << 9) |
                      (parallelports << 14) | 0x02;
}
Пример #5
0
/***********************************************************************
 *           VXD_APM (WPROCS.438)
 */
void WINAPI VXD_APM ( CONTEXT86 *context )
{
    unsigned service = AX_reg(context);

    TRACE("[%04x] APM\n", (UINT16)service);

    switch(service)
    {
    case 0x0000: /* version */
        AX_reg(context) = VXD_WinVersion();
        RESET_CFLAG(context);
        break;

    default:
        VXD_BARF( context, "APM" );
    }
}
Пример #6
0
/**********************************************************************
 *	    DOSVM_RawModeSwitchHandler
 *
 * DPMI Raw Mode Switch handler
 */
void WINAPI DOSVM_RawModeSwitchHandler( CONTEXT86 *context )
{
  CONTEXT86 rm_ctx;
  int ret;

  /* initialize real-mode context as per spec */
  memset(&rm_ctx, 0, sizeof(rm_ctx));
  rm_ctx.SegDs  = AX_reg(context);
  rm_ctx.SegEs  = CX_reg(context);
  rm_ctx.SegSs  = DX_reg(context);
  rm_ctx.Esp    = context->Ebx;
  rm_ctx.SegCs  = SI_reg(context);
  rm_ctx.Eip    = context->Edi;
  rm_ctx.Ebp    = context->Ebp;
  rm_ctx.SegFs  = 0;
  rm_ctx.SegGs  = 0;

  /* Copy interrupt state. */
  if (NtCurrentTeb()->dpmi_vif)
      rm_ctx.EFlags = V86_FLAG | VIF_MASK;
  else
      rm_ctx.EFlags = V86_FLAG;

  /* enter real mode again */
  TRACE("re-entering real mode at %04lx:%04lx\n",rm_ctx.SegCs,rm_ctx.Eip);
  ret = DOSVM_Enter( &rm_ctx );
  /* when the real-mode stuff call its mode switch address,
     DOSVM_Enter will return and we will continue here */

  if (ret<0) {
    ERR("Sync lost!\n");
    /* if the sync was lost, there's no way to recover */
    ExitProcess(1);
  }

  /* alter protected-mode context as per spec */
  context->SegDs   = LOWORD(rm_ctx.Eax);
  context->SegEs   = LOWORD(rm_ctx.Ecx);
  context->SegSs   = LOWORD(rm_ctx.Edx);
  context->Esp     = rm_ctx.Ebx;
  context->SegCs   = LOWORD(rm_ctx.Esi);
  context->Eip     = rm_ctx.Edi;
  context->Ebp     = rm_ctx.Ebp;
  context->SegFs   = 0;
  context->SegGs   = 0;

  /* Copy interrupt state. */
  if (rm_ctx.EFlags & VIF_MASK)
      NtCurrentTeb()->dpmi_vif = 1;
  else
      NtCurrentTeb()->dpmi_vif = 0;

  /* Return to new address and hope that we didn't mess up */
  TRACE("re-entering protected mode at %04lx:%08lx\n",
      context->SegCs, context->Eip);
}
Пример #7
0
static DWORD VxDCall_VWin32( DWORD service, CONTEXT86 *context )
{
  switch ( LOWORD(service) )
    {
    case 0x0000: /* GetVersion */
    {
        DWORD vers = GetVersion();
        return (LOBYTE(vers) << 8) | HIBYTE(vers);
    }
    break;

    case 0x0020: /* Get VMCPD Version */
    {
	DWORD parm = (DWORD) stack32_pop(context);

	FIXME("Get VMCPD Version(%08lx): partial stub!\n", parm);

	/* FIXME: This is what Win98 returns, it may
         *        not be correct in all situations.
         *        It makes Bleem! happy though.
         */

	return 0x0405;
    }

    case 0x0029: /* Int31/DPMI dispatch */
    {
	DWORD callnum = (DWORD) stack32_pop(context);
        DWORD parm    = (DWORD) stack32_pop(context);

        TRACE("Int31/DPMI dispatch(%08lx)\n", callnum);

	AX_reg(context) = callnum;
        CX_reg(context) = parm;
	INT_Int31Handler(context);

	return LOWORD(context->Eax);
    }
    break;

    case 0x002a: /* Int41 dispatch - parm = int41 service number */
    {
	DWORD callnum = (DWORD) stack32_pop(context);

	return callnum; /* FIXME: should really call INT_Int41Handler() */
    }
    break;

    default:
      FIXME("Unknown VWin32 service %08lx\n", service);
      break;
    }

  return 0xffffffff;
}
Пример #8
0
/***********************************************************************
 *           VXD_PageFile (WPROCS.433)
 */
void WINAPI VXD_PageFile( CONTEXT86 *context )
{
    unsigned	service = AX_reg(context);

    /* taken from Ralf Brown's Interrupt List */

    TRACE("[%04x] PageFile\n", (UINT16)service );

    switch(service)
    {
    case 0x00: /* get version, is this windows version? */
	TRACE("returning version\n");
        AX_reg(context) = VXD_WinVersion();
	RESET_CFLAG(context);
	break;

    case 0x01: /* get swap file info */
	TRACE("VxD PageFile: returning swap file info\n");
	AX_reg(context) = 0x00; /* paging disabled */
	context->Ecx = 0;   /* maximum size of paging file */
	/* FIXME: do I touch DS:SI or DS:DI? */
	RESET_CFLAG(context);
	break;

    case 0x02: /* delete permanent swap on exit */
	TRACE("VxD PageFile: supposed to delete swap\n");
	RESET_CFLAG(context);
	break;

    case 0x03: /* current temporary swap file size */
	TRACE("VxD PageFile: what is current temp. swap size\n");
	RESET_CFLAG(context);
	break;

    case 0x04: /* read or write?? INTERRUP.D */
    case 0x05: /* cancel?? INTERRUP.D */
    case 0x06: /* test I/O valid INTERRUP.D */
    default:
	VXD_BARF( context, "pagefile" );
	break;
    }
}
Пример #9
0
/***********************************************************************
 *           VXD_Comm (WPROCS.414)
 */
void WINAPI VXD_Comm( CONTEXT86 *context )
{
    unsigned	service = AX_reg(context);

    TRACE("[%04x] Comm\n", (UINT16)service);

    switch (service)
    {
    case 0x0000: /* get version */
	TRACE("returning version\n");
        AX_reg(context) = VXD_WinVersion();
	RESET_CFLAG(context);
	break;

    case 0x0001: /* set port global */
    case 0x0002: /* get focus */
    case 0x0003: /* virtualise port */
    default:
        VXD_BARF( context, "comm" );
    }
}
Пример #10
0
/***********************************************************************
 *           INT_Int41Handler (WPROCS.165)
 *
 */
void WINAPI INT_Int41Handler( CONTEXT86 *context )
{
    if ( ISV86(context) )
    {
        /* Real-mode debugger services */
        switch ( AX_reg(context) )
        {
        default:
            INT_BARF( context, 0x41 );
            break;
        }
    }
    else
    {
        /* Protected-mode debugger services */
        switch ( AX_reg(context) )
        {
        case 0x4f:
        case 0x50:
        case 0x150:
        case 0x51:
        case 0x52:
        case 0x152:
        case 0x59:
        case 0x5a:
        case 0x5b:
        case 0x5c:
        case 0x5d:
            /* Notifies the debugger of a lot of stuff. We simply ignore it
               for now, but some of the info might actually be useful ... */
            break;

        default:
            INT_BARF( context, 0x41 );
            break;
        }
    }
}
Пример #11
0
/***********************************************************************
 *           VXD_VXDLoader (WPROCS.439)
 */
void WINAPI VXD_VXDLoader( CONTEXT86 *context )
{
    unsigned service = AX_reg(context);

    TRACE("[%04x] VXDLoader\n", (UINT16)service);

    switch (service)
    {
    case 0x0000: /* get version */
	TRACE("returning version\n");
	AX_reg(context) = 0x0000;
	DX_reg(context) = VXD_WinVersion();
	RESET_CFLAG(context);
	break;

    case 0x0001: /* load device */
	FIXME("load device %04lx:%04x (%s)\n",
	      context->SegDs, DX_reg(context),
	      debugstr_a(MapSL(MAKESEGPTR(context->SegDs, DX_reg(context)))));
	AX_reg(context) = 0x0000;
	context->SegEs = 0x0000;
	DI_reg(context) = 0x0000;
	RESET_CFLAG(context);
	break;

    case 0x0002: /* unload device */
	FIXME("unload device (%08lx)\n", context->Ebx);
	AX_reg(context) = 0x0000;
	RESET_CFLAG(context);
	break;

    default:
	VXD_BARF( context, "VXDLDR" );
	AX_reg(context) = 0x000B; /* invalid function number */
	SET_CFLAG(context);
	break;
    }
}
Пример #12
0
/***********************************************************************
 *           VXD_VMM (WPROCS.401)
 */
void WINAPI VXD_VMM ( CONTEXT86 *context )
{
    unsigned service = AX_reg(context);

    TRACE("[%04x] VMM\n", (UINT16)service);

    switch(service)
    {
    case 0x0000: /* version */
        AX_reg(context) = VXD_WinVersion();
        RESET_CFLAG(context);
        break;

    case 0x026d: /* Get_Debug_Flag '/m' */
    case 0x026e: /* Get_Debug_Flag '/n' */
        AL_reg(context) = 0;
        RESET_CFLAG(context);
        break;

    default:
        VXD_BARF( context, "VMM" );
    }
}
Пример #13
0
/* (see dosmem.c, function DOSMEM_InitDPMI) */
static void StartPM( CONTEXT86 *context )
{
    UINT16 cs, ss, ds, es;
    CONTEXT86 pm_ctx;
    DWORD psp_ofs = (DWORD)(DOSVM_psp<<4);
    PDB16 *psp = (PDB16 *)psp_ofs;
    HANDLE16 env_seg = psp->environment;
    unsigned char selflags = WINE_LDT_FLAGS_DATA;

    RESET_CFLAG(context);
    dpmi_flag = AX_reg(context);
/* our mode switch wrapper have placed the desired CS into DX */
    cs = alloc_pm_selector( context->Edx, WINE_LDT_FLAGS_CODE );
/* due to a flaw in some CPUs (at least mine), it is best to mark stack segments as 32-bit if they
   can be used in 32-bit code. Otherwise, these CPUs may not set the high word of esp during a
   ring transition (from kernel code) to the 16-bit stack, and this causes trouble if executing
   32-bit code using this stack. */
    if (dpmi_flag & 1) selflags |= WINE_LDT_FLAGS_32BIT;
    ss = alloc_pm_selector( context->SegSs, selflags );
/* do the same for the data segments, just in case */
    if (context->SegDs == context->SegSs) ds = ss;
    else ds = alloc_pm_selector( context->SegDs, selflags );
    es = alloc_pm_selector( DOSVM_psp, selflags );
/* convert environment pointer, as the spec says, but we're a bit lazy about the size here... */
    psp->environment = alloc_pm_selector( env_seg, WINE_LDT_FLAGS_DATA );

    pm_ctx = *context;
    pm_ctx.SegCs = DOSVM_dpmi_segments->dpmi_sel;
/* our mode switch wrapper expects the new CS in DX, and the new SS in AX */
    pm_ctx.Eax   = ss;
    pm_ctx.Edx   = cs;
    pm_ctx.SegDs = ds;
    pm_ctx.SegEs = es;
    pm_ctx.SegFs = wine_get_fs();
    pm_ctx.SegGs = wine_get_gs();
    pm_ctx.EFlags &= ~V86_FLAG;

    TRACE("DOS program is now entering %d-bit protected mode\n", 
          DOSVM_IsDos32() ? 32 : 16);

    __TRY 
    {
        WOWCallback16Ex( 0, WCB16_REGS, 0, NULL, (DWORD *)&pm_ctx );
    } 
    __EXCEPT(dpmi_exception_handler) 
    { 
    } 
    __ENDTRY

    TRACE( "Protected mode DOS program is terminating\n" );

    /*
     * FIXME: Instead of calling ExitThread, we should release all
     *        allocated protected mode resources and call MZ_Exit
     *        using real mode context. See DPMI specification.
     */
    ExitThread( DPMI_retval );

#if 0
    wine_ldt_free_entries( psp->environment, 1 );
    psp->environment = env_seg;
    wine_ldt_free_entries(es,1);
    if (ds != ss) wine_ldt_free_entries(ds,1);
    wine_ldt_free_entries(ss,1);
    wine_ldt_free_entries(cs,1);
#endif
}
Пример #14
0
void WINAPI VXD_Win32s( CONTEXT86 *context )
{
    switch (AX_reg(context))
    {
    case 0x0000: /* Get Version */
        /*
         * Input:   None
         *
         * Output:  EAX: LoWord: Win32s Version (1.30)
         *               HiWord: VxD Version (200)
         *
         *          EBX: Build (172)
         *
         *          ECX: ???   (1)
         *
         *          EDX: Debugging Flags
         *
         *          EDI: Error Flag
         *               0 if OK,
         *               1 if VMCPD VxD not found
         */

        TRACE("GetVersion()\n");

	context->Eax = VXD_WinVersion() | (200 << 16);
        context->Ebx = 0;
        context->Ecx = 0;
        context->Edx = 0;
        context->Edi = 0;

        /*
         * If this is the first time we are called for this process,
         * hack the memory image of WIN32S16 so that it doesn't try
         * to access the GDT directly ...
         *
         * The first code segment of WIN32S16 (version 1.30) contains
         * an unexported function somewhere between the exported functions
         * SetFS and StackLinearToSegmented that tries to find a selector
         * in the LDT that maps to the memory image of the LDT itself.
         * If it succeeds, it stores this selector into a global variable
         * which will be used to speed up execution by using this selector
         * to modify the LDT directly instead of using the DPMI calls.
         *
         * To perform this search of the LDT, this function uses the
         * sgdt and sldt instructions to find the linear address of
         * the (GDT and then) LDT. While those instructions themselves
         * execute without problem, the linear address that sgdt returns
         * points (at least under Linux) to the kernel address space, so
         * that any subsequent access leads to a segfault.
         *
         * Fortunately, WIN32S16 still contains as a fallback option the
         * mechanism of using DPMI calls to modify LDT selectors instead
         * of direct writes to the LDT. Thus we can circumvent the problem
         * by simply replacing the first byte of the offending function
         * with an 'retf' instruction. This means that the global variable
         * supposed to contain the LDT alias selector will remain zero,
         * and hence WIN32S16 will fall back to using DPMI calls.
         *
         * The heuristic we employ to _find_ that function is as follows:
         * We search between the addresses of the exported symbols SetFS
         * and StackLinearToSegmented for the byte sequence '0F 01 04'
         * (this is the opcode of 'sgdt [si]'). We then search backwards
         * from this address for the last occurrence of 'CB' (retf) that marks
         * the end of the preceeding function. The following byte (which
         * should now be the first byte of the function we are looking for)
         * will be replaced by 'CB' (retf).
         *
         * This heuristic works for the retail as well as the debug version
         * of Win32s version 1.30. For versions earlier than that this
         * hack should not be necessary at all, since the whole mechanism
         * ('PERF130') was introduced only in 1.30 to improve the overall
         * performance of Win32s.
         */

        if (!W32S_offset)
        {
            HMODULE16 hModule = GetModuleHandle16("win32s16");
            SEGPTR func1 = (SEGPTR)GetProcAddress16(hModule, "SetFS");
            SEGPTR func2 = (SEGPTR)GetProcAddress16(hModule, "StackLinearToSegmented");

            if (   hModule && func1 && func2
                && SELECTOROF(func1) == SELECTOROF(func2))
            {
                BYTE *start = MapSL(func1);
                BYTE *end   = MapSL(func2);
                BYTE *p, *retv = NULL;
                int found = 0;

                for (p = start; p < end; p++)
                    if (*p == 0xCB) found = 0, retv = p;
                    else if (*p == 0x0F) found = 1;
                    else if (*p == 0x01 && found == 1) found = 2;
                    else if (*p == 0x04 && found == 2) { found = 3; break; }
                    else found = 0;

                if (found == 3 && retv)
                {
                    TRACE("PERF130 hack: "
                               "Replacing byte %02X at offset %04X:%04X\n",
                               *(retv+1), SELECTOROF(func1),
                                          OFFSETOF(func1) + retv+1-start);

                    *(retv+1) = (BYTE)0xCB;
                }
            }
        }

        /*
         * Mark process as Win32s, so that subsequent DPMI calls
         * will perform the W32S_APP2WINE/W32S_WINE2APP address shift.
         */
        W32S_offset = 0x10000;
        break;


    case 0x0001: /* Install Exception Handling */
        /*
         * Input:   EBX: Flat address of W32SKRNL Exception Data
         *
         *          ECX: LoWord: Flat Code Selector
         *               HiWord: Flat Data Selector
         *
         *          EDX: Flat address of W32SKRNL Exception Handler
         *               (this is equal to W32S_BackTo32 + 0x40)
         *
         *          ESI: SEGPTR KERNEL.HASGPHANDLER
         *
         *          EDI: SEGPTR phCurrentTask (KERNEL.THHOOK + 0x10)
         *
         * Output:  EAX: 0 if OK
         */

        TRACE("[0001] EBX=%lx ECX=%lx EDX=%lx ESI=%lx EDI=%lx\n",
                   context->Ebx, context->Ecx, context->Edx,
                   context->Esi, context->Edi);

        /* FIXME */

        context->Eax = 0;
        break;


    case 0x0002: /* Set Page Access Flags */
        /*
         * Input:   EBX: New access flags
         *               Bit 2: User Page if set, Supervisor Page if clear
         *               Bit 1: Read-Write if set, Read-Only if clear
         *
         *          ECX: Size of memory area to change
         *
         *          EDX: Flat start address of memory area
         *
         * Output:  EAX: Size of area changed
         */

        TRACE("[0002] EBX=%lx ECX=%lx EDX=%lx\n",
                   context->Ebx, context->Ecx, context->Edx);

        /* FIXME */

        context->Eax = context->Ecx;
        break;


    case 0x0003: /* Get Page Access Flags */
        /*
         * Input:   EDX: Flat address of page to query
         *
         * Output:  EAX: Page access flags
         *               Bit 2: User Page if set, Supervisor Page if clear
         *               Bit 1: Read-Write if set, Read-Only if clear
         */

        TRACE("[0003] EDX=%lx\n", context->Edx);

        /* FIXME */

        context->Eax = 6;
        break;


    case 0x0004: /* Map Module */
        /*
         * Input:   ECX: IMTE (offset in Module Table) of new module
         *
         *          EDX: Flat address of Win32s Module Table
         *
         * Output:  EAX: 0 if OK
         */

    if (!context->Edx || CX_reg(context) == 0xFFFF)
    {
        TRACE("MapModule: Initialization call\n");
        context->Eax = 0;
    }
    else
    {
        /*
         * Structure of a Win32s Module Table Entry:
         */
        struct Win32sModule
        {
            DWORD  flags;
            DWORD  flatBaseAddr;
            LPCSTR moduleName;
            LPCSTR pathName;
            LPCSTR unknown;
            LPBYTE baseAddr;
            DWORD  hModule;
            DWORD  relocDelta;
        };

        /*
         * Note: This function should set up a demand-paged memory image
         *       of the given module. Since mmap does not allow file offsets
         *       not aligned at 1024 bytes, we simply load the image fully
         *       into memory.
         */

        struct Win32sModule *moduleTable =
                            (struct Win32sModule *)W32S_APP2WINE(context->Edx);
        struct Win32sModule *module = moduleTable + context->Ecx;

        IMAGE_NT_HEADERS *nt_header = PE_HEADER(module->baseAddr);
        IMAGE_SECTION_HEADER *pe_seg = PE_SECTIONS(module->baseAddr);

        HFILE image = _lopen(module->pathName, OF_READ);
        BOOL error = (image == HFILE_ERROR);
        UINT i;

        TRACE("MapModule: Loading %s\n", module->pathName);

        for (i = 0;
             !error && i < nt_header->FileHeader.NumberOfSections;
             i++, pe_seg++)
            if(!(pe_seg->Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA))
            {
                DWORD  off  = pe_seg->PointerToRawData;
                DWORD  len  = pe_seg->SizeOfRawData;
                LPBYTE addr = module->baseAddr + pe_seg->VirtualAddress;

                TRACE("MapModule: "
                           "Section %d at %08lx from %08lx len %08lx\n",
                           i, (DWORD)addr, off, len);

                if (   _llseek(image, off, SEEK_SET) != off
                    || _lread(image, addr, len) != len)
                    error = TRUE;
            }

        _lclose(image);

        if (error)
            ERR("MapModule: Unable to load %s\n", module->pathName);

        else if (module->relocDelta != 0)
        {
            IMAGE_DATA_DIRECTORY *dir = nt_header->OptionalHeader.DataDirectory
                                      + IMAGE_DIRECTORY_ENTRY_BASERELOC;
            IMAGE_BASE_RELOCATION *r = (IMAGE_BASE_RELOCATION *)
                (dir->Size? module->baseAddr + dir->VirtualAddress : 0);

            TRACE("MapModule: Reloc delta %08lx\n", module->relocDelta);

            while (r && r->VirtualAddress)
            {
                LPBYTE page  = module->baseAddr + r->VirtualAddress;
                WORD *TypeOffset = (WORD *)(r + 1);
                int count = (r->SizeOfBlock - sizeof(*r)) / sizeof(*TypeOffset);

                TRACE("MapModule: %d relocations for page %08lx\n",
                           count, (DWORD)page);

                for(i = 0; i < count; i++)
                {
                    int offset = TypeOffset[i] & 0xFFF;
                    int type   = TypeOffset[i] >> 12;
                    switch(type)
                    {
                    case IMAGE_REL_BASED_ABSOLUTE:
                        break;
                    case IMAGE_REL_BASED_HIGH:
                        *(WORD *)(page+offset) += HIWORD(module->relocDelta);
                        break;
                    case IMAGE_REL_BASED_LOW:
                        *(WORD *)(page+offset) += LOWORD(module->relocDelta);
                        break;
                    case IMAGE_REL_BASED_HIGHLOW:
                        *(DWORD*)(page+offset) += module->relocDelta;
                        break;
                    default:
                        WARN("MapModule: Unsupported fixup type\n");
                        break;
                    }
                }

                r = (IMAGE_BASE_RELOCATION *)((LPBYTE)r + r->SizeOfBlock);
            }
        }

        context->Eax = 0;
        RESET_CFLAG(context);
    }
    break;


    case 0x0005: /* UnMap Module */
        /*
         * Input:   EDX: Flat address of module image
         *
         * Output:  EAX: 1 if OK
         */

        TRACE("UnMapModule: %lx\n", (DWORD)W32S_APP2WINE(context->Edx));

        /* As we didn't map anything, there's nothing to unmap ... */

        context->Eax = 1;
        break;


    case 0x0006: /* VirtualAlloc */
        /*
         * Input:   ECX: Current Process
         *
         *          EDX: Flat address of arguments on stack
         *
         *   DWORD *retv     [out] Flat base address of allocated region
         *   LPVOID base     [in]  Flat address of region to reserve/commit
         *   DWORD  size     [in]  Size of region
         *   DWORD  type     [in]  Type of allocation
         *   DWORD  prot     [in]  Type of access protection
         *
         * Output:  EAX: NtStatus
         */
    {
        DWORD *stack  = (DWORD *)W32S_APP2WINE(context->Edx);
        DWORD *retv   = (DWORD *)W32S_APP2WINE(stack[0]);
        LPVOID base   = (LPVOID) W32S_APP2WINE(stack[1]);
        DWORD  size   = stack[2];
        DWORD  type   = stack[3];
        DWORD  prot   = stack[4];
        DWORD  result;

        TRACE("VirtualAlloc(%lx, %lx, %lx, %lx, %lx)\n",
                   (DWORD)retv, (DWORD)base, size, type, prot);

        if (type & 0x80000000)
        {
            WARN("VirtualAlloc: strange type %lx\n", type);
            type &= 0x7fffffff;
        }

        if (!base && (type & MEM_COMMIT) && prot == PAGE_READONLY)
        {
            WARN("VirtualAlloc: NLS hack, allowing write access!\n");
            prot = PAGE_READWRITE;
        }

        result = (DWORD)VirtualAlloc(base, size, type, prot);

        if (W32S_WINE2APP(result))
            *retv            = W32S_WINE2APP(result),
            context->Eax = STATUS_SUCCESS;
        else
            *retv            = 0,
            context->Eax = STATUS_NO_MEMORY;  /* FIXME */
    }
    break;


    case 0x0007: /* VirtualFree */
        /*
         * Input:   ECX: Current Process
         *
         *          EDX: Flat address of arguments on stack
         *
         *   DWORD *retv     [out] TRUE if success, FALSE if failure
         *   LPVOID base     [in]  Flat address of region
         *   DWORD  size     [in]  Size of region
         *   DWORD  type     [in]  Type of operation
         *
         * Output:  EAX: NtStatus
         */
    {
        DWORD *stack  = (DWORD *)W32S_APP2WINE(context->Edx);
        DWORD *retv   = (DWORD *)W32S_APP2WINE(stack[0]);
        LPVOID base   = (LPVOID) W32S_APP2WINE(stack[1]);
        DWORD  size   = stack[2];
        DWORD  type   = stack[3];
        DWORD  result;

        TRACE("VirtualFree(%lx, %lx, %lx, %lx)\n",
                   (DWORD)retv, (DWORD)base, size, type);

        result = VirtualFree(base, size, type);

        if (result)
            *retv            = TRUE,
            context->Eax = STATUS_SUCCESS;
        else
            *retv            = FALSE,
            context->Eax = STATUS_NO_MEMORY;  /* FIXME */
    }
    break;


    case 0x0008: /* VirtualProtect */
        /*
         * Input:   ECX: Current Process
         *
         *          EDX: Flat address of arguments on stack
         *
         *   DWORD *retv     [out] TRUE if success, FALSE if failure
         *   LPVOID base     [in]  Flat address of region
         *   DWORD  size     [in]  Size of region
         *   DWORD  new_prot [in]  Desired access protection
         *   DWORD *old_prot [out] Previous access protection
         *
         * Output:  EAX: NtStatus
         */
    {
        DWORD *stack    = (DWORD *)W32S_APP2WINE(context->Edx);
        DWORD *retv     = (DWORD *)W32S_APP2WINE(stack[0]);
        LPVOID base     = (LPVOID) W32S_APP2WINE(stack[1]);
        DWORD  size     = stack[2];
        DWORD  new_prot = stack[3];
        DWORD *old_prot = (DWORD *)W32S_APP2WINE(stack[4]);
        DWORD  result;

        TRACE("VirtualProtect(%lx, %lx, %lx, %lx, %lx)\n",
                   (DWORD)retv, (DWORD)base, size, new_prot, (DWORD)old_prot);

        result = VirtualProtect(base, size, new_prot, old_prot);

        if (result)
            *retv            = TRUE,
            context->Eax = STATUS_SUCCESS;
        else
            *retv            = FALSE,
            context->Eax = STATUS_NO_MEMORY;  /* FIXME */
    }
    break;


    case 0x0009: /* VirtualQuery */
        /*
         * Input:   ECX: Current Process
         *
         *          EDX: Flat address of arguments on stack
         *
         *   DWORD *retv                     [out] Nr. bytes returned
         *   LPVOID base                     [in]  Flat address of region
         *   LPMEMORY_BASIC_INFORMATION info [out] Info buffer
         *   DWORD  len                      [in]  Size of buffer
         *
         * Output:  EAX: NtStatus
         */
    {
        DWORD *stack  = (DWORD *)W32S_APP2WINE(context->Edx);
        DWORD *retv   = (DWORD *)W32S_APP2WINE(stack[0]);
        LPVOID base   = (LPVOID) W32S_APP2WINE(stack[1]);
        LPMEMORY_BASIC_INFORMATION info =
                        (LPMEMORY_BASIC_INFORMATION)W32S_APP2WINE(stack[2]);
        DWORD  len    = stack[3];
        DWORD  result;

        TRACE("VirtualQuery(%lx, %lx, %lx, %lx)\n",
                   (DWORD)retv, (DWORD)base, (DWORD)info, len);

        result = VirtualQuery(base, info, len);

        *retv            = result;
        context->Eax = STATUS_SUCCESS;
    }
    break;


    case 0x000A: /* SetVirtMemProcess */
        /*
         * Input:   ECX: Process Handle
         *
         *          EDX: Flat address of region
         *
         * Output:  EAX: NtStatus
         */

        TRACE("[000a] ECX=%lx EDX=%lx\n",
                   context->Ecx, context->Edx);

        /* FIXME */

        context->Eax = STATUS_SUCCESS;
        break;


    case 0x000B: /* ??? some kind of cleanup */
        /*
         * Input:   ECX: Process Handle
         *
         * Output:  EAX: NtStatus
         */

        TRACE("[000b] ECX=%lx\n", context->Ecx);

        /* FIXME */

        context->Eax = STATUS_SUCCESS;
        break;


    case 0x000C: /* Set Debug Flags */
        /*
         * Input:   EDX: Debug Flags
         *
         * Output:  EDX: Previous Debug Flags
         */

        FIXME("[000c] EDX=%lx\n", context->Edx);

        /* FIXME */

        context->Edx = 0;
        break;


    case 0x000D: /* NtCreateSection */
        /*
         * Input:   EDX: Flat address of arguments on stack
         *
         *   HANDLE32 *retv      [out] Handle of Section created
         *   DWORD  flags1       [in]  (?? unknown ??)
         *   DWORD  atom         [in]  Name of Section to create
         *   LARGE_INTEGER *size [in]  Size of Section
         *   DWORD  protect      [in]  Access protection
         *   DWORD  flags2       [in]  (?? unknown ??)
         *   HFILE32 hFile       [in]  Handle of file to map
         *   DWORD  psp          [in]  (Win32s: PSP that hFile belongs to)
         *
         * Output:  EAX: NtStatus
         */
    {
        DWORD *stack    = (DWORD *)   W32S_APP2WINE(context->Edx);
        HANDLE *retv  = (HANDLE *)W32S_APP2WINE(stack[0]);
        DWORD  flags1   = stack[1];
        DWORD  atom     = stack[2];
        LARGE_INTEGER *size = (LARGE_INTEGER *)W32S_APP2WINE(stack[3]);
        DWORD  protect  = stack[4];
        DWORD  flags2   = stack[5];
        HANDLE hFile    = DosFileHandleToWin32Handle(stack[6]);
        DWORD  psp      = stack[7];

        HANDLE result = INVALID_HANDLE_VALUE;
        char name[128];

        TRACE("NtCreateSection(%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx)\n",
                   (DWORD)retv, flags1, atom, (DWORD)size, protect, flags2,
                   (DWORD)hFile, psp);

        if (!atom || GlobalGetAtomNameA(atom, name, sizeof(name)))
        {
            TRACE("NtCreateSection: name=%s\n", atom? name : NULL);

            result = CreateFileMappingA(hFile, NULL, protect,
                                          size? size->s.HighPart : 0,
                                          size? size->s.LowPart  : 0,
                                          atom? name : NULL);
        }

        if (result == INVALID_HANDLE_VALUE)
            WARN("NtCreateSection: failed!\n");
        else
            TRACE("NtCreateSection: returned %lx\n", (DWORD)result);

        if (result != INVALID_HANDLE_VALUE)
            *retv            = result,
            context->Eax = STATUS_SUCCESS;
        else
            *retv            = result,
            context->Eax = STATUS_NO_MEMORY;   /* FIXME */
    }
    break;


    case 0x000E: /* NtOpenSection */
        /*
         * Input:   EDX: Flat address of arguments on stack
         *
         *   HANDLE32 *retv  [out] Handle of Section opened
         *   DWORD  protect  [in]  Access protection
         *   DWORD  atom     [in]  Name of Section to create
         *
         * Output:  EAX: NtStatus
         */
    {
        DWORD *stack    = (DWORD *)W32S_APP2WINE(context->Edx);
        HANDLE *retv  = (HANDLE *)W32S_APP2WINE(stack[0]);
        DWORD  protect  = stack[1];
        DWORD  atom     = stack[2];

        HANDLE result = INVALID_HANDLE_VALUE;
        char name[128];

        TRACE("NtOpenSection(%lx, %lx, %lx)\n",
                   (DWORD)retv, protect, atom);

        if (atom && GlobalGetAtomNameA(atom, name, sizeof(name)))
        {
            TRACE("NtOpenSection: name=%s\n", name);

            result = OpenFileMappingA(protect, FALSE, name);
        }

        if (result == INVALID_HANDLE_VALUE)
            WARN("NtOpenSection: failed!\n");
        else
            TRACE("NtOpenSection: returned %lx\n", (DWORD)result);

        if (result != INVALID_HANDLE_VALUE)
            *retv            = result,
            context->Eax = STATUS_SUCCESS;
        else
            *retv            = result,
            context->Eax = STATUS_NO_MEMORY;   /* FIXME */
    }
    break;


    case 0x000F: /* NtCloseSection */
        /*
         * Input:   EDX: Flat address of arguments on stack
         *
         *   HANDLE32 handle  [in]  Handle of Section to close
         *   DWORD *id        [out] Unique ID  (?? unclear ??)
         *
         * Output:  EAX: NtStatus
         */
    {
        DWORD *stack    = (DWORD *)W32S_APP2WINE(context->Edx);
        HANDLE handle = stack[0];
        DWORD *id       = (DWORD *)W32S_APP2WINE(stack[1]);

        TRACE("NtCloseSection(%lx, %lx)\n", (DWORD)handle, (DWORD)id);

        CloseHandle(handle);
        if (id) *id = 0; /* FIXME */

        context->Eax = STATUS_SUCCESS;
    }
    break;


    case 0x0010: /* NtDupSection */
        /*
         * Input:   EDX: Flat address of arguments on stack
         *
         *   HANDLE32 handle  [in]  Handle of Section to duplicate
         *
         * Output:  EAX: NtStatus
         */
    {
        DWORD *stack    = (DWORD *)W32S_APP2WINE(context->Edx);
        HANDLE handle = stack[0];
        HANDLE new_handle;

        TRACE("NtDupSection(%lx)\n", (DWORD)handle);

        DuplicateHandle( GetCurrentProcess(), handle,
                         GetCurrentProcess(), &new_handle,
                         0, FALSE, DUPLICATE_SAME_ACCESS );
        context->Eax = STATUS_SUCCESS;
    }
    break;


    case 0x0011: /* NtMapViewOfSection */
        /*
         * Input:   EDX: Flat address of arguments on stack
         *
         *   HANDLE32 SectionHandle       [in]     Section to be mapped
         *   DWORD    ProcessHandle       [in]     Process to be mapped into
         *   DWORD *  BaseAddress         [in/out] Address to be mapped at
         *   DWORD    ZeroBits            [in]     (?? unclear ??)
         *   DWORD    CommitSize          [in]     (?? unclear ??)
         *   LARGE_INTEGER *SectionOffset [in]     Offset within section
         *   DWORD *  ViewSize            [in]     Size of view
         *   DWORD    InheritDisposition  [in]     (?? unclear ??)
         *   DWORD    AllocationType      [in]     (?? unclear ??)
         *   DWORD    Protect             [in]     Access protection
         *
         * Output:  EAX: NtStatus
         */
    {
        DWORD *  stack          = (DWORD *)W32S_APP2WINE(context->Edx);
        HANDLE SectionHandle  = stack[0];
        DWORD    ProcessHandle  = stack[1]; /* ignored */
        DWORD *  BaseAddress    = (DWORD *)W32S_APP2WINE(stack[2]);
        DWORD    ZeroBits       = stack[3];
        DWORD    CommitSize     = stack[4];
        LARGE_INTEGER *SectionOffset = (LARGE_INTEGER *)W32S_APP2WINE(stack[5]);
        DWORD *  ViewSize       = (DWORD *)W32S_APP2WINE(stack[6]);
        DWORD    InheritDisposition = stack[7];
        DWORD    AllocationType = stack[8];
        DWORD    Protect        = stack[9];

        LPBYTE address = (LPBYTE)(BaseAddress?
			W32S_APP2WINE(*BaseAddress) : 0);
        DWORD  access = 0, result;

        switch (Protect & ~(PAGE_GUARD|PAGE_NOCACHE))
        {
            case PAGE_READONLY:           access = FILE_MAP_READ;  break;
            case PAGE_READWRITE:          access = FILE_MAP_WRITE; break;
            case PAGE_WRITECOPY:          access = FILE_MAP_COPY;  break;

            case PAGE_EXECUTE_READ:       access = FILE_MAP_READ;  break;
            case PAGE_EXECUTE_READWRITE:  access = FILE_MAP_WRITE; break;
            case PAGE_EXECUTE_WRITECOPY:  access = FILE_MAP_COPY;  break;
        }

        TRACE("NtMapViewOfSection"
                   "(%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx)\n",
                   (DWORD)SectionHandle, ProcessHandle, (DWORD)BaseAddress,
                   ZeroBits, CommitSize, (DWORD)SectionOffset, (DWORD)ViewSize,
                   InheritDisposition, AllocationType, Protect);
        TRACE("NtMapViewOfSection: "
                   "base=%lx, offset=%lx, size=%lx, access=%lx\n",
                   (DWORD)address, SectionOffset? SectionOffset->s.LowPart : 0,
                   ViewSize? *ViewSize : 0, access);

        result = (DWORD)MapViewOfFileEx(SectionHandle, access,
                            SectionOffset? SectionOffset->s.HighPart : 0,
                            SectionOffset? SectionOffset->s.LowPart  : 0,
                            ViewSize? *ViewSize : 0, address);

        TRACE("NtMapViewOfSection: result=%lx\n", result);

        if (W32S_WINE2APP(result))
        {
            if (BaseAddress) *BaseAddress = W32S_WINE2APP(result);
            context->Eax = STATUS_SUCCESS;
        }
        else
            context->Eax = STATUS_NO_MEMORY; /* FIXME */
    }
    break;


    case 0x0012: /* NtUnmapViewOfSection */
        /*
         * Input:   EDX: Flat address of arguments on stack
         *
         *   DWORD  ProcessHandle  [in]  Process (defining address space)
         *   LPBYTE BaseAddress    [in]  Base address of view to be unmapped
         *
         * Output:  EAX: NtStatus
         */
    {
        DWORD *stack          = (DWORD *)W32S_APP2WINE(context->Edx);
        DWORD  ProcessHandle  = stack[0]; /* ignored */
        LPBYTE BaseAddress    = (LPBYTE)W32S_APP2WINE(stack[1]);

        TRACE("NtUnmapViewOfSection(%lx, %lx)\n",
                   ProcessHandle, (DWORD)BaseAddress);

        UnmapViewOfFile(BaseAddress);

        context->Eax = STATUS_SUCCESS;
    }
    break;


    case 0x0013: /* NtFlushVirtualMemory */
        /*
         * Input:   EDX: Flat address of arguments on stack
         *
         *   DWORD   ProcessHandle  [in]  Process (defining address space)
         *   LPBYTE *BaseAddress    [in?] Base address of range to be flushed
         *   DWORD  *ViewSize       [in?] Number of bytes to be flushed
         *   DWORD  *unknown        [???] (?? unknown ??)
         *
         * Output:  EAX: NtStatus
         */
    {
        DWORD *stack          = (DWORD *)W32S_APP2WINE(context->Edx);
        DWORD  ProcessHandle  = stack[0]; /* ignored */
        DWORD *BaseAddress    = (DWORD *)W32S_APP2WINE(stack[1]);
        DWORD *ViewSize       = (DWORD *)W32S_APP2WINE(stack[2]);
        DWORD *unknown        = (DWORD *)W32S_APP2WINE(stack[3]);

        LPBYTE address = (LPBYTE)(BaseAddress? W32S_APP2WINE(*BaseAddress) : 0);
        DWORD  size    = ViewSize? *ViewSize : 0;

        TRACE("NtFlushVirtualMemory(%lx, %lx, %lx, %lx)\n",
                   ProcessHandle, (DWORD)BaseAddress, (DWORD)ViewSize,
                   (DWORD)unknown);
        TRACE("NtFlushVirtualMemory: base=%lx, size=%lx\n",
                   (DWORD)address, size);

        FlushViewOfFile(address, size);

        context->Eax = STATUS_SUCCESS;
    }
    break;


    case 0x0014: /* Get/Set Debug Registers */
        /*
         * Input:   ECX: 0 if Get, 1 if Set
         *
         *          EDX: Get: Flat address of buffer to receive values of
         *                    debug registers DR0 .. DR7
         *               Set: Flat address of buffer containing values of
         *                    debug registers DR0 .. DR7 to be set
         * Output:  None
         */

        FIXME("[0014] ECX=%lx EDX=%lx\n",
                   context->Ecx, context->Edx);

        /* FIXME */
        break;


    case 0x0015: /* Set Coprocessor Emulation Flag */
        /*
         * Input:   EDX: 0 to deactivate, 1 to activate coprocessor emulation
         *
         * Output:  None
         */

        TRACE("[0015] EDX=%lx\n", context->Edx);

        /* We don't care, as we always have a coprocessor anyway */
        break;


    case 0x0016: /* Init Win32S VxD PSP */
        /*
         * If called to query required PSP size:
         *
         *     Input:  EBX: 0
         *     Output: EDX: Required size of Win32s VxD PSP
         *
         * If called to initialize allocated PSP:
         *
         *     Input:  EBX: LoWord: Selector of Win32s VxD PSP
         *                  HiWord: Paragraph of Win32s VxD PSP (DOSMEM)
         *     Output: None
         */

        if (context->Ebx == 0)
            context->Edx = 0x80;
        else
        {
            PDB16 *psp = MapSL( MAKESEGPTR( BX_reg(context), 0 ));
            psp->nbFiles = 32;
            psp->fileHandlesPtr = MAKELONG(HIWORD(context->Ebx), 0x5c);
            memset((LPBYTE)psp + 0x5c, '\xFF', 32);
        }
        break;


    case 0x0017: /* Set Break Point */
        /*
         * Input:   EBX: Offset of Break Point
         *          CX:  Selector of Break Point
         *
         * Output:  None
         */

        FIXME("[0017] EBX=%lx CX=%x\n",
                   context->Ebx, CX_reg(context));

        /* FIXME */
        break;


    case 0x0018: /* VirtualLock */
        /*
         * Input:   ECX: Current Process
         *
         *          EDX: Flat address of arguments on stack
         *
         *   DWORD *retv     [out] TRUE if success, FALSE if failure
         *   LPVOID base     [in]  Flat address of range to lock
         *   DWORD  size     [in]  Size of range
         *
         * Output:  EAX: NtStatus
         */
    {
        DWORD *stack  = (DWORD *)W32S_APP2WINE(context->Edx);
        DWORD *retv   = (DWORD *)W32S_APP2WINE(stack[0]);
        LPVOID base   = (LPVOID) W32S_APP2WINE(stack[1]);
        DWORD  size   = stack[2];
        DWORD  result;

        TRACE("VirtualLock(%lx, %lx, %lx)\n",
                   (DWORD)retv, (DWORD)base, size);

        result = VirtualLock(base, size);

        if (result)
            *retv            = TRUE,
            context->Eax = STATUS_SUCCESS;
        else
            *retv            = FALSE,
            context->Eax = STATUS_NO_MEMORY;  /* FIXME */
    }
    break;


    case 0x0019: /* VirtualUnlock */
        /*
         * Input:   ECX: Current Process
         *
         *          EDX: Flat address of arguments on stack
         *
         *   DWORD *retv     [out] TRUE if success, FALSE if failure
         *   LPVOID base     [in]  Flat address of range to unlock
         *   DWORD  size     [in]  Size of range
         *
         * Output:  EAX: NtStatus
         */
    {
        DWORD *stack  = (DWORD *)W32S_APP2WINE(context->Edx);
        DWORD *retv   = (DWORD *)W32S_APP2WINE(stack[0]);
        LPVOID base   = (LPVOID) W32S_APP2WINE(stack[1]);
        DWORD  size   = stack[2];
        DWORD  result;

        TRACE("VirtualUnlock(%lx, %lx, %lx)\n",
                   (DWORD)retv, (DWORD)base, size);

        result = VirtualUnlock(base, size);

        if (result)
            *retv            = TRUE,
            context->Eax = STATUS_SUCCESS;
        else
            *retv            = FALSE,
            context->Eax = STATUS_NO_MEMORY;  /* FIXME */
    }
    break;


    case 0x001A: /* KGetSystemInfo */
        /*
         * Input:   None
         *
         * Output:  ECX:  Start of sparse memory arena
         *          EDX:  End of sparse memory arena
         */

        TRACE("KGetSystemInfo()\n");

        /*
         * Note: Win32s reserves 0GB - 2GB for Win 3.1 and uses 2GB - 4GB as
         *       sparse memory arena. We do it the other way around, since
         *       we have to reserve 3GB - 4GB for Linux, and thus use
         *       0GB - 3GB as sparse memory arena.
         *
         *       FIXME: What about other OSes ?
         */

        context->Ecx = W32S_WINE2APP(0x00000000);
        context->Edx = W32S_WINE2APP(0xbfffffff);
        break;


    case 0x001B: /* KGlobalMemStat */
        /*
         * Input:   ESI: Flat address of buffer to receive memory info
         *
         * Output:  None
         */
    {
        struct Win32sMemoryInfo
        {
            DWORD DIPhys_Count;       /* Total physical pages */
            DWORD DIFree_Count;       /* Free physical pages */
            DWORD DILin_Total_Count;  /* Total virtual pages (private arena) */
            DWORD DILin_Total_Free;   /* Free virtual pages (private arena) */

            DWORD SparseTotal;        /* Total size of sparse arena (bytes ?) */
            DWORD SparseFree;         /* Free size of sparse arena (bytes ?) */
        };

        struct Win32sMemoryInfo *info =
                       (struct Win32sMemoryInfo *)W32S_APP2WINE(context->Esi);

        FIXME("KGlobalMemStat(%lx)\n", (DWORD)info);

        /* FIXME */
    }
    break;


    case 0x001C: /* Enable/Disable Exceptions */
        /*
         * Input:   ECX: 0 to disable, 1 to enable exception handling
         *
         * Output:  None
         */

        TRACE("[001c] ECX=%lx\n", context->Ecx);

        /* FIXME */
        break;


    case 0x001D: /* VirtualAlloc called from 16-bit code */
        /*
         * Input:   EDX: Segmented address of arguments on stack
         *
         *   LPVOID base     [in]  Flat address of region to reserve/commit
         *   DWORD  size     [in]  Size of region
         *   DWORD  type     [in]  Type of allocation
         *   DWORD  prot     [in]  Type of access protection
         *
         * Output:  EAX: NtStatus
         *          EDX: Flat base address of allocated region
         */
    {
        DWORD *stack  = MapSL( MAKESEGPTR( LOWORD(context->Edx), HIWORD(context->Edx) ));
        LPVOID base   = (LPVOID)W32S_APP2WINE(stack[0]);
        DWORD  size   = stack[1];
        DWORD  type   = stack[2];
        DWORD  prot   = stack[3];
        DWORD  result;

        TRACE("VirtualAlloc16(%lx, %lx, %lx, %lx)\n",
                   (DWORD)base, size, type, prot);

        if (type & 0x80000000)
        {
            WARN("VirtualAlloc16: strange type %lx\n", type);
            type &= 0x7fffffff;
        }

        result = (DWORD)VirtualAlloc(base, size, type, prot);

        if (W32S_WINE2APP(result))
            context->Edx = W32S_WINE2APP(result),
            context->Eax = STATUS_SUCCESS;
        else
            context->Edx = 0,
            context->Eax = STATUS_NO_MEMORY;  /* FIXME */
	TRACE("VirtualAlloc16: returning base %lx\n", context->Edx);
    }
    break;


    case 0x001E: /* VirtualFree called from 16-bit code */
        /*
         * Input:   EDX: Segmented address of arguments on stack
         *
         *   LPVOID base     [in]  Flat address of region
         *   DWORD  size     [in]  Size of region
         *   DWORD  type     [in]  Type of operation
         *
         * Output:  EAX: NtStatus
         *          EDX: TRUE if success, FALSE if failure
         */
    {
        DWORD *stack  = MapSL( MAKESEGPTR( LOWORD(context->Edx), HIWORD(context->Edx) ));
        LPVOID base   = (LPVOID)W32S_APP2WINE(stack[0]);
        DWORD  size   = stack[1];
        DWORD  type   = stack[2];
        DWORD  result;

        TRACE("VirtualFree16(%lx, %lx, %lx)\n",
                   (DWORD)base, size, type);

        result = VirtualFree(base, size, type);

        if (result)
            context->Edx = TRUE,
            context->Eax = STATUS_SUCCESS;
        else
            context->Edx = FALSE,
            context->Eax = STATUS_NO_MEMORY;  /* FIXME */
    }
    break;


    case 0x001F: /* FWorkingSetSize */
        /*
         * Input:   EDX: 0 if Get, 1 if Set
         *
         *          ECX: Get: Buffer to receive Working Set Size
         *               Set: Buffer containing Working Set Size
         *
         * Output:  NtStatus
         */
    {
        DWORD *ptr = (DWORD *)W32S_APP2WINE(context->Ecx);
        BOOL set = context->Edx;

        TRACE("FWorkingSetSize(%lx, %lx)\n", (DWORD)ptr, (DWORD)set);

        if (set)
            /* We do it differently ... */;
        else
            *ptr = 0x100;

        context->Eax = STATUS_SUCCESS;
    }
    break;


    default:
	VXD_BARF( context, "W32S" );
    }
Пример #15
0
/**********************************************************************
 *         DOSVM_Int31Handler (WINEDOS16.149)
 *
 * Handler for int 31h (DPMI).
 */
void WINAPI DOSVM_Int31Handler( CONTEXT86 *context )
{
    RESET_CFLAG(context);
    switch(AX_reg(context))
    {
    case 0x0000:  /* Allocate LDT descriptors */
        TRACE( "allocate LDT descriptors (%d)\n", CX_reg(context) );
        {
            WORD sel =  AllocSelectorArray16( CX_reg(context) );
            if(!sel) 
            {
               TRACE( "failed\n" );
               SET_AX( context, 0x8011 ); /* descriptor unavailable */
               SET_CFLAG( context );
            } 
            else 
            { 
                TRACE( "success, array starts at 0x%04x\n", sel );
                SET_AX( context, sel );      
            }
        }
        break;

    case 0x0001:  /* Free LDT descriptor */
        TRACE( "free LDT descriptor (0x%04x)\n", BX_reg(context) );
        if (FreeSelector16( BX_reg(context) ))
        {
            SET_AX( context, 0x8022 );  /* invalid selector */
            SET_CFLAG( context );
        }
        else
        {
            /* If a segment register contains the selector being freed, */
            /* set it to zero. */
            if (!((context->SegDs^BX_reg(context)) & ~3)) context->SegDs = 0;
            if (!((context->SegEs^BX_reg(context)) & ~3)) context->SegEs = 0;
            if (!((context->SegFs^BX_reg(context)) & ~3)) context->SegFs = 0;
            if (!((context->SegGs^BX_reg(context)) & ~3)) context->SegGs = 0;
        }
        break;

    case 0x0002:  /* Real mode segment to descriptor */
        TRACE( "real mode segment to descriptor (0x%04x)\n", BX_reg(context) );
        {
            WORD entryPoint = 0;  /* KERNEL entry point for descriptor */
            switch(BX_reg(context))
            {
            case 0x0000: entryPoint = 183; break;  /* __0000H */
            case 0x0040: entryPoint = 193; break;  /* __0040H */
            case 0xa000: entryPoint = 174; break;  /* __A000H */
            case 0xb000: entryPoint = 181; break;  /* __B000H */
            case 0xb800: entryPoint = 182; break;  /* __B800H */
            case 0xc000: entryPoint = 195; break;  /* __C000H */
            case 0xd000: entryPoint = 179; break;  /* __D000H */
            case 0xe000: entryPoint = 190; break;  /* __E000H */
            case 0xf000: entryPoint = 194; break;  /* __F000H */
            default:
                FIXME("Real mode segment (%x) to descriptor: no longer supported\n",
                      BX_reg(context));
                SET_CFLAG( context );
                break;
            }
            if (entryPoint)
            {
                FARPROC16 proc = GetProcAddress16( GetModuleHandle16( "KERNEL" ),
                                                   (LPCSTR)(ULONG_PTR)entryPoint );
                SET_AX( context, LOWORD(proc) );
            }
        }
        break;

    case 0x0003:  /* Get next selector increment */
        TRACE("get selector increment (__AHINCR)\n");
        context->Eax = __AHINCR;
        break;

    case 0x0004:  /* Lock selector (not supported) */
        FIXME("lock selector not supported\n");
        context->Eax = 0;  /* FIXME: is this a correct return value? */
        break;

    case 0x0005:  /* Unlock selector (not supported) */
        FIXME("unlock selector not supported\n");
        context->Eax = 0;  /* FIXME: is this a correct return value? */
        break;

    case 0x0006:  /* Get selector base address */
        TRACE( "get selector base address (0x%04x)\n", BX_reg(context) );
        {
            LDT_ENTRY entry;
            WORD sel = BX_reg(context);
            wine_ldt_get_entry( sel, &entry );
            if (wine_ldt_is_empty(&entry))
            {
                context->Eax = 0x8022;  /* invalid selector */
                SET_CFLAG(context);
            }
            else
            {
                void *base = wine_ldt_get_base(&entry);
                SET_CX( context, HIWORD(base) );
                SET_DX( context, LOWORD(base) );
            }
        }
        break;

    case 0x0007:  /* Set selector base address */
        {
            DWORD base = MAKELONG( DX_reg(context), CX_reg(context) );
            WORD  sel = BX_reg(context);
            TRACE( "set selector base address (0x%04x,0x%08lx)\n", sel, base );

            /* check if Win16 app wants to access lower 64K of DOS memory */
            if (base < 0x10000 && DOSVM_IsWin16())
                DOSMEM_MapDosLayout();

            SetSelectorBase( sel, base );
        }
        break;

    case 0x0008:  /* Set selector limit */
        {
            DWORD limit = MAKELONG( DX_reg(context), CX_reg(context) );
            TRACE( "set selector limit (0x%04x,0x%08lx)\n",
                   BX_reg(context), limit );
            SetSelectorLimit16( BX_reg(context), limit );
        }
        break;

    case 0x0009:  /* Set selector access rights */
        TRACE( "set selector access rights(0x%04x,0x%04x)\n",
               BX_reg(context), CX_reg(context) );
        SelectorAccessRights16( BX_reg(context), 1, CX_reg(context) );
        break;

    case 0x000a:  /* Allocate selector alias */
        TRACE( "allocate selector alias (0x%04x)\n", BX_reg(context) );
        SET_AX( context, AllocCStoDSAlias16( BX_reg(context) ) );
        if (!AX_reg(context))
        {
            SET_AX( context, 0x8011 );  /* descriptor unavailable */
            SET_CFLAG(context);
        }
        break;

    case 0x000b:  /* Get descriptor */
        TRACE( "get descriptor (0x%04x)\n", BX_reg(context) );
        {
            LDT_ENTRY *entry = (LDT_ENTRY*)CTX_SEG_OFF_TO_LIN( context,
                                                               context->SegEs, 
                                                               context->Edi );
            wine_ldt_get_entry( BX_reg(context), entry );
        }
        break;

    case 0x000c:  /* Set descriptor */
        TRACE( "set descriptor (0x%04x)\n", BX_reg(context) );
        {
            LDT_ENTRY *entry = (LDT_ENTRY*)CTX_SEG_OFF_TO_LIN( context,
                                                               context->SegEs, 
                                                               context->Edi );
            wine_ldt_set_entry( BX_reg(context), entry );
        }
        break;

    case 0x000d:  /* Allocate specific LDT descriptor */
        FIXME( "allocate descriptor (0x%04x), stub!\n", BX_reg(context) );
        SET_AX( context, 0x8011 ); /* descriptor unavailable */
        SET_CFLAG( context );
        break;

    case 0x000e:  /* Get Multiple Descriptors (1.0) */
        FIXME( "get multiple descriptors - unimplemented\n" );
        break;

    case 0x000f:  /* Set Multiple Descriptors (1.0) */
        FIXME( "set multiple descriptors - unimplemented\n" );
        break;

    case 0x0100:  /* Allocate DOS memory block */
        TRACE( "allocate DOS memory block (0x%x paragraphs)\n", BX_reg(context) );
        {
            DWORD dw = GlobalDOSAlloc16( (DWORD)BX_reg(context) << 4 );
            if (dw) {
                SET_AX( context, HIWORD(dw) );
                SET_DX( context, LOWORD(dw) );
            } else {
                SET_AX( context, 0x0008 ); /* insufficient memory */
                SET_BX( context, DOSMEM_Available() >> 4 );
                SET_CFLAG(context);
            }
            break;
        }

    case 0x0101:  /* Free DOS memory block */
        TRACE( "free DOS memory block (0x%04x)\n", DX_reg(context) );
        {
            WORD error = GlobalDOSFree16( DX_reg(context) );
            if (error) {
                SET_AX( context, 0x0009 ); /* memory block address invalid */
                SET_CFLAG( context );
            }
        }
        break;

    case 0x0102: /* Resize DOS Memory Block */
        FIXME( "resize DOS memory block (0x%04x, 0x%x paragraphs) - unimplemented\n", 
               DX_reg(context), BX_reg(context) );
        break;

    case 0x0200: /* get real mode interrupt vector */
        TRACE( "get realmode interupt vector (0x%02x)\n",
               BL_reg(context) );
        {
            FARPROC16 proc = DOSVM_GetRMHandler( BL_reg(context) );
            SET_CX( context, SELECTOROF(proc) );
            SET_DX( context, OFFSETOF(proc) );
        }
        break;

    case 0x0201: /* set real mode interrupt vector */
        TRACE( "set realmode interrupt vector (0x%02x, 0x%04x:0x%04x)\n", 
               BL_reg(context), CX_reg(context), DX_reg(context) );
        DOSVM_SetRMHandler( BL_reg(context), 
                            (FARPROC16)MAKESEGPTR(CX_reg(context), DX_reg(context)) );
        break;

    case 0x0202:  /* Get Processor Exception Handler Vector */
        FIXME( "Get Processor Exception Handler Vector (0x%02x)\n",
               BL_reg(context) );
        if (DOSVM_IsDos32()) 
        {
            SET_CX( context, 0 );
            context->Edx = 0;
        } 
        else 
        {
            SET_CX( context, 0 );
            SET_DX( context, 0 );
        }
        break;

    case 0x0203:  /* Set Processor Exception Handler Vector */
         FIXME( "Set Processor Exception Handler Vector (0x%02x)\n",
                BL_reg(context) );
         break;

    case 0x0204:  /* Get protected mode interrupt vector */
        TRACE("get protected mode interrupt handler (0x%02x)\n",
              BL_reg(context));
        if (DOSVM_IsDos32()) 
        {
            FARPROC48 handler = DOSVM_GetPMHandler48( BL_reg(context) );
            SET_CX( context, handler.selector );
            context->Edx = handler.offset;
        } 
        else 
        {
            FARPROC16 handler = DOSVM_GetPMHandler16( BL_reg(context) );
            SET_CX( context, SELECTOROF(handler) );
            SET_DX( context, OFFSETOF(handler) );
        }
        break;

    case 0x0205:  /* Set protected mode interrupt vector */
        TRACE("set protected mode interrupt handler (0x%02x,0x%04x:0x%08lx)\n",
              BL_reg(context), CX_reg(context), context->Edx);
        if (DOSVM_IsDos32()) 
        {
            FARPROC48 handler;
            handler.selector = CX_reg(context);
            handler.offset = context->Edx;
            DOSVM_SetPMHandler48( BL_reg(context), handler );
        } 
        else 
        {
            FARPROC16 handler;
            handler = (FARPROC16)MAKESEGPTR( CX_reg(context), DX_reg(context)); 
            DOSVM_SetPMHandler16( BL_reg(context), handler );
        }
        break;

    case 0x0300:  /* Simulate real mode interrupt */
        TRACE( "Simulate real mode interrupt %02x.\n", BL_reg(context));
        DOSVM_CallRMInt( context );
        break;

    case 0x0301:  /* Call real mode procedure with far return */
        TRACE( "Call real mode procedure with far return.\n" );
        DOSVM_CallRMProc( context, FALSE );
        break;

    case 0x0302:  /* Call real mode procedure with interrupt return */
        TRACE( "Call real mode procedure with interrupt return.\n" );
        DOSVM_CallRMProc( context, TRUE );
        break;

    case 0x0303:  /* Allocate Real Mode Callback Address */
        TRACE( "Allocate real mode callback address.\n" );
        DOSVM_AllocRMCB( context );
        break;

    case 0x0304:  /* Free Real Mode Callback Address */
        TRACE( "Free real mode callback address.\n" );
        DOSVM_FreeRMCB( context );
        break;

    case 0x0305:  /* Get State Save/Restore Addresses */
        TRACE("get state save/restore addresses\n");
        /* we probably won't need this kind of state saving */
        SET_AX( context, 0 );

        /* real mode: just point to the lret */
        SET_BX( context, DOSVM_dpmi_segments->wrap_seg );
        SET_CX( context, 2 );

        /* protected mode: don't have any handler yet... */
        /* FIXME: Use DI in 16-bit DPMI and EDI in 32-bit DPMI */
        FIXME("no protected-mode dummy state save/restore handler yet\n");
        SET_SI( context, 0 );
        context->Edi = 0;
        break;

    case 0x0306:  /* Get Raw Mode Switch Addresses */
        TRACE("get raw mode switch addresses\n");

        /* real mode, point to standard DPMI return wrapper */
        SET_BX( context, DOSVM_dpmi_segments->wrap_seg );
        SET_CX( context, 0 );

        /* protected mode, point to DPMI call wrapper */
        /* FIXME: Use DI in 16-bit DPMI and EDI in 32-bit DPMI */
        /* FIXME: Doesn't work in DPMI32... */
        SET_SI( context, DOSVM_dpmi_segments->dpmi_sel );
        context->Edi = 8; /* offset of the INT 0x31 call */
        break;

    case 0x0400:  /* Get DPMI version */
        TRACE("get DPMI version\n");
        {
            SYSTEM_INFO si;

            GetSystemInfo(&si);
            SET_AX( context, 0x005a );  /* DPMI version 0.90 */
            SET_BX( context, 0x0005 );  /* Flags: 32-bit, virtual memory */
            SET_CL( context, si.wProcessorLevel );
            SET_DX( context, 0x0870 );  /* Master/slave interrupt controller base */
        }
        break;

    case 0x0401:  /* Get DPMI Capabilities (1.0) */
        FIXME( "get dpmi capabilities - unimplemented\n");
        break;

    case 0x0500:  /* Get free memory information */
        TRACE("get free memory information\n");
        {
            MEMORYSTATUS status;

            /* the layout is just the same as MEMMANINFO, but without
             * the dwSize entry.
             */
            struct
            {
                DWORD dwLargestFreeBlock;
                DWORD dwMaxPagesAvailable;
                DWORD dwMaxPagesLockable;
                DWORD dwTotalLinearSpace;
                DWORD dwTotalUnlockedPages;
                DWORD dwFreePages;
                DWORD dwTotalPages;
                DWORD dwFreeLinearSpace;
                DWORD dwSwapFilePages;
                WORD  wPageSize;
            } *info = CTX_SEG_OFF_TO_LIN( context, context->SegEs, context->Edi );

            GlobalMemoryStatus( &status );
            info->wPageSize            = getpagesize();
            info->dwLargestFreeBlock   = status.dwAvailVirtual;
            info->dwMaxPagesAvailable  = info->dwLargestFreeBlock / info->wPageSize;
            info->dwMaxPagesLockable   = info->dwMaxPagesAvailable;
            info->dwTotalLinearSpace   = status.dwTotalVirtual / info->wPageSize;
            info->dwTotalUnlockedPages = info->dwTotalLinearSpace;
            info->dwFreePages          = info->dwMaxPagesAvailable;
            info->dwTotalPages         = info->dwTotalLinearSpace;
            info->dwFreeLinearSpace    = info->dwMaxPagesAvailable;
            info->dwSwapFilePages      = status.dwTotalPageFile / info->wPageSize;
            break;
        }

    case 0x0501:  /* Allocate memory block */
        {
            DWORD size = MAKELONG( CX_reg(context), BX_reg(context) );
            BYTE *ptr;

            TRACE( "allocate memory block (%ld bytes)\n", size );

            ptr = (BYTE *)DPMI_xalloc( size );
            if (!ptr)
            {
                SET_AX( context, 0x8012 );  /* linear memory not available */
                SET_CFLAG(context);
            } 
            else 
            {
                SET_BX( context, HIWORD(ptr) );
                SET_CX( context, LOWORD(ptr) );
                SET_SI( context, HIWORD(ptr) );
                SET_DI( context, LOWORD(ptr) );
            }
            break;
        }

    case 0x0502:  /* Free memory block */
        {
            DWORD handle = MAKELONG( DI_reg(context), SI_reg(context) );
            TRACE( "free memory block (0x%08lx)\n", handle );
            DPMI_xfree( (void *)handle );
        }
        break;

    case 0x0503:  /* Resize memory block */
        {
            DWORD size = MAKELONG( CX_reg(context), BX_reg(context) );
            DWORD handle = MAKELONG( DI_reg(context), SI_reg(context) );
            BYTE *ptr;

            TRACE( "resize memory block (0x%08lx, %ld bytes)\n", handle, size );

            ptr = (BYTE *)DPMI_xrealloc( (void *)handle, size );
            if (!ptr)
            {
                SET_AX( context, 0x8012 );  /* linear memory not available */
                SET_CFLAG(context);
            } else {
                SET_BX( context, HIWORD(ptr) );
                SET_CX( context, LOWORD(ptr) );
                SET_SI( context, HIWORD(ptr) );
                SET_DI( context, LOWORD(ptr) );
            }
        }
        break;

    case 0x0507:  /* Set page attributes (1.0) */
        FIXME( "set page attributes - unimplemented\n" );
        break;  /* Just ignore it */

    case 0x0600:  /* Lock linear region */
        TRACE( "lock linear region - ignored (no paging)\n" );
        break;

    case 0x0601:  /* Unlock linear region */
        TRACE( "unlock linear region - ignored (no paging)\n" );
        break;

    case 0x0602:  /* Mark real mode region as pageable */
        TRACE( "mark real mode region as pageable - ignored (no paging)\n" );
        break;

    case 0x0603:  /* Relock real mode region */
        TRACE( "relock real mode region - ignored (no paging)\n" );
        break;

    case 0x0604:  /* Get page size */
        TRACE("get pagesize\n");
        SET_BX( context, HIWORD(getpagesize()) );
        SET_CX( context, LOWORD(getpagesize()) );
        break;

    case 0x0700: /* Mark pages as paging candidates */
        TRACE( "mark pages as paging candidates - ignored (no paging)\n" );
        break;

    case 0x0701: /* Discard pages */
        TRACE( "discard pages - ignored (no paging)\n" );
        break;

    case 0x0702:  /* Mark page as demand-paging candidate */
        TRACE( "mark page as demand-paging candidate - ignored (no paging)\n" );
        break;

    case 0x0703:  /* Discard page contents */
        TRACE( "discard page contents - ignored (no paging)\n" );
        break;

    case 0x0800:  /* Physical address mapping */
        FIXME( "physical address mapping (0x%08lx) - unimplemented\n", 
               MAKELONG(CX_reg(context),BX_reg(context)) );
        break;

    case 0x0900:  /* Get and Disable Virtual Interrupt State */
        TRACE( "Get and Disable Virtual Interrupt State: %ld\n", 
               NtCurrentTeb()->dpmi_vif );
        SET_AL( context, NtCurrentTeb()->dpmi_vif ? 1 : 0 );
        NtCurrentTeb()->dpmi_vif = 0;
        break;

    case 0x0901:  /* Get and Enable Virtual Interrupt State */
        TRACE( "Get and Enable Virtual Interrupt State: %ld\n", 
               NtCurrentTeb()->dpmi_vif );
        SET_AL( context, NtCurrentTeb()->dpmi_vif ? 1 : 0 );
        NtCurrentTeb()->dpmi_vif = 1;
        break;

    case 0x0902:  /* Get Virtual Interrupt State */
        TRACE( "Get Virtual Interrupt State: %ld\n", 
               NtCurrentTeb()->dpmi_vif );
        SET_AL( context, NtCurrentTeb()->dpmi_vif ? 1 : 0 );
        break;

    case 0x0e00:  /* Get Coprocessor Status (1.0) */
        /*
         * Return status in AX bits:
         * B0    - MPv (MP bit in the virtual MSW/CR0)
         *         0 = numeric coprocessor is disabled for this client
         *         1 = numeric coprocessor is enabled for this client
         * B1    - EMv (EM bit in the virtual MSW/CR0)
         *         0 = client is not emulating coprocessor instructions
         *         1 = client is emulating coprocessor instructions
         * B2    - MPr (MP bit from the actual MSW/CR0)
         *         0 = numeric coprocessor is not present
         *         1 = numeric coprocessor is present
         * B3    - EMr (EM bit from the actual MSW/CR0)
         *         0 = host is not emulating coprocessor instructions
         *         1 = host is emulating coprocessor instructions
         * B4-B7 - coprocessor type
         *         00H = no coprocessor
         *         02H = 80287
         *         03H = 80387
         *         04H = 80486 with numeric coprocessor
         *         05H-0FH = reserved for future numeric processors
         */
        TRACE( "Get Coprocessor Status\n" );
        SET_AX( context, 69 ); /* 486, coprocessor present and enabled */ 
        break;

    case 0x0e01: /* Set Coprocessor Emulation (1.0) */
        /*
         * See function 0x0e00.
         * BX bit B0 is new value for MPv.
         * BX bit B1 is new value for EMv.
         */
        if (BX_reg(context) != 1)
            FIXME( "Set Coprocessor Emulation to %d - unimplemented\n", 
                   BX_reg(context) );
        else
            TRACE( "Set Coprocessor Emulation - ignored\n" );
        break;

    default:
        INT_BARF( context, 0x31 );
        SET_AX( context, 0x8001 );  /* unsupported function */
        SET_CFLAG(context);
        break;
    }  
}
Пример #16
0
/**********************************************************************
 *	    INT_Int12Handler (WPROCS.118)
 *
 * Handler for int 12h (get memory size).
 */
void WINAPI INT_Int12Handler( CONTEXT86 *context )
{
    AX_reg(context) = 640;
}
Пример #17
0
/**********************************************************************
 *	    DOSVM_Int33Handler
 *
 * Handler for int 33h (MS MOUSE).
 */
void WINAPI DOSVM_Int33Handler( CONTEXT *context )
{
    switch (AX_reg(context))
    {
    case 0x0000:
        TRACE("Reset mouse driver and request status\n");
        INT33_ResetMouse( context );
        break;

    case 0x0001:
        TRACE("Show mouse cursor, old hide count: %d\n",
              mouse_info.hide_count);
        if (mouse_info.hide_count >= 1)
            mouse_info.hide_count--;
        if (!mouse_info.hide_count)
            VGA_ShowMouse( TRUE );
        break;

    case 0x0002:
        TRACE("Hide mouse cursor, old hide count: %d\n",
              mouse_info.hide_count);
        if(!mouse_info.hide_count)
            VGA_ShowMouse( FALSE );            
        mouse_info.hide_count++;
        break;

    case 0x0003:
        TRACE("Return mouse position and button status: (%d,%d) and %d\n",
              mouse_info.x, mouse_info.y, mouse_info.but);
        SET_BX( context, mouse_info.but );
        SET_CX( context, mouse_info.x );
        SET_DX( context, mouse_info.y );
        break;

    case 0x0004:
        FIXME("Position mouse cursor\n");
        break;

    case 0x0005:
        TRACE("Return Mouse button press Information for %s mouse button\n",
              BX_reg(context) ? "right" : "left");
        if (BX_reg(context)) 
        {
            SET_BX( context, mouse_info.rbcount );
            mouse_info.rbcount = 0;
            SET_CX( context, mouse_info.rlastx );
            SET_DX( context, mouse_info.rlasty );
        } 
        else 
        {
            SET_BX( context, mouse_info.lbcount );
            mouse_info.lbcount = 0;
            SET_CX( context, mouse_info.llastx );
            SET_DX( context, mouse_info.llasty );
        }
        SET_AX( context, mouse_info.but );
        break;

    case 0x0007:
        FIXME("Define horizontal mouse cursor range %d..%d\n",
              CX_reg(context), DX_reg(context));
        break;

    case 0x0008:
        FIXME("Define vertical mouse cursor range %d..%d\n",
              CX_reg(context), DX_reg(context));
        break;

    case 0x0009:
        FIXME("Define graphics mouse cursor\n");
        break;

    case 0x000A:
        FIXME("Define text mouse cursor\n");
        break;

    case 0x000B:
        TRACE("Read Mouse motion counters\n");
        {
            int dx = ((int)mouse_info.x - (int)mouse_info.oldx)
                * (mouse_info.HMPratio / 8);
            int dy = ((int)mouse_info.y - (int)mouse_info.oldy)
                * (mouse_info.VMPratio / 8);

            SET_CX( context, (WORD)dx );
            SET_DX( context, (WORD)dy );

            mouse_info.oldx = mouse_info.x;
            mouse_info.oldy = mouse_info.y;
        }
        break;

    case 0x000C:
        TRACE("Define mouse interrupt subroutine\n");
        mouse_info.callmask = CX_reg(context);
        mouse_info.callback = (FARPROC16)MAKESEGPTR(context->SegEs, 
                                                    DX_reg(context));
        break;

    case 0x000F:
        TRACE("Set mickey/pixel ratio\n");
        mouse_info.HMPratio = CX_reg(context);
        mouse_info.VMPratio = DX_reg(context);
        break;

    case 0x0010:
        FIXME("Define screen region for update\n");
        break;

    case 0x0021:
        TRACE("Software reset\n");
        INT33_ResetMouse( context );
        break;

    default:
        INT_BARF(context,0x33);
    }
}
Пример #18
0
/***********************************************************************
 *           VXD_Shell (WPROCS.423)
 */
void WINAPI VXD_Shell( CONTEXT86 *context )
{
    unsigned	service = DX_reg(context);

    TRACE("[%04x] Shell\n", (UINT16)service);

    switch (service) /* Ralf Brown says EDX, but I use DX instead */
    {
    case 0x0000:
	TRACE("returning version\n");
        AX_reg(context) = VXD_WinVersion();
	context->Ebx = 1; /* system VM Handle */
	break;

    case 0x0001:
    case 0x0002:
    case 0x0003:
        /* SHELL_SYSMODAL_Message
	ebx virtual maschine handle
	eax message box flags
	ecx address of message
	edi address of caption
	return response in eax
	*/
    case 0x0004:
	/* SHELL_Message
	ebx virtual maschine handle
	eax message box flags
	ecx address of message
	edi address of caption
	esi address callback
	edx reference data for callback
	return response in eax
	*/
    case 0x0005:
	VXD_BARF( context, "shell" );
	break;

    case 0x0006: /* SHELL_Get_VM_State */
	TRACE("VxD Shell: returning VM state\n");
	/* Actually we don't, not yet. We have to return a structure
         * and I am not to sure how to set it up and return it yet,
         * so for now let's do nothing. I can (hopefully) get this
         * by the next release
         */
	/* RESET_CFLAG(context); */
	break;

    case 0x0007:
    case 0x0008:
    case 0x0009:
    case 0x000A:
    case 0x000B:
    case 0x000C:
    case 0x000D:
    case 0x000E:
    case 0x000F:
    case 0x0010:
    case 0x0011:
    case 0x0012:
    case 0x0013:
    case 0x0014:
    case 0x0015:
    case 0x0016:
	VXD_BARF( context, "SHELL" );
	break;

    /* the new Win95 shell API */
    case 0x0100:     /* get version */
        AX_reg(context) = VXD_WinVersion();
	break;

    case 0x0104:   /* retrieve Hook_Properties list */
    case 0x0105:   /* call Hook_Properties callbacks */
	VXD_BARF( context, "SHELL" );
	break;

    case 0x0106:   /* install timeout callback */
	TRACE("VxD Shell: ignoring shell callback (%ld sec.)\n", context->Ebx);
	SET_CFLAG(context);
	break;

    case 0x0107:   /* get version of any VxD */
    default:
	VXD_BARF( context, "SHELL" );
	break;
    }
}
Пример #19
0
void WINAPI XMS_Handler( CONTEXT86 *context )
{
    switch(AH_reg(context))
    {
    case 0x00:   /* Get XMS version number */
        TRACE("get XMS version number\n");
        SET_AX( context, 0x0200 ); /* 2.0 */
        SET_BX( context, 0x0000 ); /* internal revision */
        SET_DX( context, 0x0001 ); /* HMA exists */
        break;
    case 0x08:   /* Query Free Extended Memory */
    {
        MEMORYSTATUS status;

        TRACE("query free extended memory\n");
        GlobalMemoryStatus( &status );
        SET_DX( context, status.dwAvailVirtual >> 10 );
        SET_AX( context, status.dwAvailVirtual >> 10 );
        TRACE("returning largest %dK, total %dK\n", AX_reg(context), DX_reg(context));
    }
    break;
    case 0x09:   /* Allocate Extended Memory Block */
        TRACE("allocate extended memory block (%dK)\n",
            DX_reg(context));
	SET_DX( context, GlobalAlloc16(GMEM_MOVEABLE, (DWORD)DX_reg(context)<<10) );
	SET_AX( context, DX_reg(context) ? 1 : 0 );
	if (!DX_reg(context)) SET_BL( context, 0xA0 ); /* out of memory */
	break;
    case 0x0a:   /* Free Extended Memory Block */
	TRACE("free extended memory block %04x\n",DX_reg(context));
       if(!DX_reg(context) || GlobalFree16(DX_reg(context))) {
         SET_AX( context, 0 );    /* failure */
         SET_BL( context, 0xa2 ); /* invalid handle */
       } else
         SET_AX( context, 1 );    /* success */
	break;
    case 0x0b:   /* Move Extended Memory Block */
    {
	MOVESTRUCT*move=CTX_SEG_OFF_TO_LIN(context,
	    context->SegDs,context->Esi);
        BYTE*src,*dst;
        TRACE("move extended memory block\n");
        src=XMS_Offset(&move->Source);
        dst=XMS_Offset(&move->Dest);
	memcpy(dst,src,move->Length);
	if (move->Source.Handle) GlobalUnlock16(move->Source.Handle);
	if (move->Dest.Handle) GlobalUnlock16(move->Dest.Handle);
	break;
    }
    case 0x88:   /* Query Any Free Extended Memory */
    {
        MEMORYSTATUS status;
        SYSTEM_INFO  info;

        TRACE("query any free extended memory\n");

        GlobalMemoryStatus( &status );
        GetSystemInfo( &info );
        context->Eax = status.dwAvailVirtual >> 10;
        context->Edx = status.dwAvailVirtual >> 10;
        context->Ecx = (DWORD)info.lpMaximumApplicationAddress;
        SET_BL( context, 0 ); /* No errors. */

        TRACE("returning largest %dK, total %dK, highest 0x%x\n",
              context->Eax, context->Edx, context->Ecx);
    }
    break;
    default:
        INT_BARF( context, 0x31 );
        SET_AX( context, 0x0000 ); /* failure */
        SET_BL( context, 0x80 );   /* function not implemented */
        break;
    }
}
Пример #20
0
/**********************************************************************
 *	    INT_Int15Handler (WPROCS.121)
 *
 * Handler for int 15h
 */
void WINAPI INT_Int15Handler( CONTEXT86 *context )
{
    switch(AH_reg(context))
    {
    case 0x84: /* read joystick information */
        FIXME("Read joystick information not implemented\n");

        /* FIXME: report status as if no game port exists */
        switch(DX_reg(context))
        {
        case 0x0: /* read joystick switches */
            AL_reg(context) = 0x0; /* all switches open */
            break;
        case 0x1: /* read joystick position */
            AX_reg(context) = 0x0;
            BX_reg(context) = 0x0;
            CX_reg(context) = 0x0;
            DX_reg(context) = 0x0;
            break;
	default:
            INT_BARF( context, 0x15 );
            break;
        }

        RESET_CFLAG(context);

        break;

    case 0x88: /* get size of memory above 1 M */
        AX_reg(context) = 64;  /* FIXME: are 64K ok? */
        RESET_CFLAG(context);
        break;

    case 0xc0: /* GET CONFIGURATION */
        if (ISV86(context)) /* real */
            context->SegEs = 0xf000;
        else
            context->SegEs = DOSMEM_BiosSysSeg;
        BX_reg(context) = 0xe6f5;
        AH_reg(context) = 0x0;
        RESET_CFLAG(context);
        break;
    case 0xc2:
	switch(AL_reg(context))
	{
	case 0x00: /* Enable-Disable Pointing Device (mouse) */
	    /* BH = newstate, 00h = disabled 01h = enabled */
	    switch(BH_reg(context))
	    {
	        case 0x00:
	    	    FIXME("Disable Pointing Device - not implemented\n");
		    break;
	    	case 0x01:
	    	    FIXME("Enable Pointing Device - not implemented\n");
		    break;
	    	default:
		    INT_BARF( context, 0x15 );
		    break;
	    }
	    AH_reg(context) = 0x00; /* successful */
	    break;
	case 0x02: /* Set Sampling Rate */
	    /* BH = sampling rate */
	    FIXME("Set Sampling Rate - not implemented\n");
	    AH_reg(context) = 0x00; /* successful */
	    break;
	case 0x04: /* Get Pointing Device Type */
	    FIXME("Get Pointing Device Type - not implemented\n");
	    BH_reg(context) = 0x01;/*Device id FIXME what is it supposed to be?*/
	    break;
	default:
	    INT_BARF( context, 0x15 );
	}
        break;

    default:
        INT_BARF( context, 0x15 );
    }
}