Fixed int 10 problems

Guard pages for all thread stacks

svn path=/trunk/; revision=1744
This commit is contained in:
David Welch 2001-03-29 01:14:00 +00:00
parent d9925196f3
commit ca5d9b1a2d
8 changed files with 400 additions and 20 deletions

View file

@ -101,6 +101,7 @@ void InitVGAMode()
// FIXME: Use Vidport to map the memory properly // FIXME: Use Vidport to map the memory properly
vidmem = (char *)(0xd0000000 + 0xa0000); vidmem = (char *)(0xd0000000 + 0xa0000);
memset(&vxba, 0, sizeof(vxba));
vxba.Eax = 0x0012; vxba.Eax = 0x0012;
vps = VideoPortInt10(NULL, &vxba); vps = VideoPortInt10(NULL, &vxba);
// setMode(Mode12); // setMode(Mode12);

View file

@ -25,6 +25,7 @@ typedef ULONG SWAPENTRY;
#define MEMORY_AREA_CACHE_SEGMENT (10) #define MEMORY_AREA_CACHE_SEGMENT (10)
#define MEMORY_AREA_SHARED_DATA (11) #define MEMORY_AREA_SHARED_DATA (11)
#define MEMORY_AREA_WORKING_SET (12) #define MEMORY_AREA_WORKING_SET (12)
#define MEMORY_AREA_KERNEL_STACK (13)
#define PAGE_TO_SECTION_PAGE_DIRECTORY_OFFSET(x) \ #define PAGE_TO_SECTION_PAGE_DIRECTORY_OFFSET(x) \
((x) / (4*1024*1024)) ((x) / (4*1024*1024))

View file

@ -75,11 +75,24 @@ Ke386CallBios(UCHAR Int, PKV86M_REGISTERS Regs)
Regs->Vif = 1; Regs->Vif = 1;
Regs->PStatus = &Status; Regs->PStatus = &Status;
WRITE_PORT_UCHAR((PUCHAR)0xea, 0);
/* /*
* Execute the BIOS interrupt * Execute the BIOS interrupt
*/ */
Ki386RetToV86Mode(Regs, &ORegs); Ki386RetToV86Mode(Regs, &ORegs);
WRITE_PORT_UCHAR((PUCHAR)0xea, 1);
if (!NT_SUCCESS(Status))
{
DPRINT1("Ke386CallBios() failed (Status %x)\n", Status);
}
else
{
DPRINT1("Ke386CallBios succeeded\n");
}
/* /*
* Copy the return values back to the caller * Copy the return values back to the caller
*/ */

View file

@ -64,10 +64,12 @@ _Ki386ContextSwitch:
* Set the base of the TEB selector to the base of the TEB for * Set the base of the TEB selector to the base of the TEB for
* this thread. * this thread.
*/ */
pushl %ebx
pushl KTHREAD_TEB(%ebx) pushl KTHREAD_TEB(%ebx)
pushl $TEB_SELECTOR pushl $TEB_SELECTOR
call _KeSetBaseGdtSelector call _KeSetBaseGdtSelector
addl $8, %esp addl $8, %esp
popl %ebx
/* /*
* Set the current thread information in the PCR * Set the current thread information in the PCR

View file

@ -1,6 +1,6 @@
/* /*
* ReactOS kernel * ReactOS kernel
* Copyright (C) 2000 ReactOS Team * Copyright (C) 2000, 2001 ReactOS Team
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -40,6 +40,7 @@
#define IOPL_FLAG ((1 << 12) | (1 << 13)) #define IOPL_FLAG ((1 << 12) | (1 << 13))
#define INTERRUPT_FLAG (1 << 9) #define INTERRUPT_FLAG (1 << 9)
#define TRAP_FLAG (1 << 8) #define TRAP_FLAG (1 << 8)
#define DIRECTION_FLAG (1 << 10)
#define VALID_FLAGS (0xDFF) #define VALID_FLAGS (0xDFF)
@ -53,7 +54,7 @@ KeV86GPF(PKV86M_TRAP_FRAME VTf, PKTRAP_FRAME Tf)
PULONG dsp; PULONG dsp;
BOOL BigDataPrefix = FALSE; BOOL BigDataPrefix = FALSE;
BOOL BigAddressPrefix = FALSE; BOOL BigAddressPrefix = FALSE;
// BOOL RepPrefix = FALSE; BOOL RepPrefix = FALSE;
ULONG i = 0; ULONG i = 0;
BOOL Exit = FALSE; BOOL Exit = FALSE;
@ -82,10 +83,18 @@ KeV86GPF(PKV86M_TRAP_FRAME VTf, PKTRAP_FRAME Tf)
Tf->Eip++; Tf->Eip++;
break; break;
/* rep prefix */
case 0xFC:
RepPrefix = TRUE;
i++;
Tf->Eip++;
break;
/* sti */ /* sti */
case 0xFB: case 0xFB:
if (BigDataPrefix || BigAddressPrefix) if (BigDataPrefix || BigAddressPrefix || RepPrefix)
{ {
*VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
return(1); return(1);
} }
if (VTf->regs->Flags & KV86M_EMULATE_CLI_STI) if (VTf->regs->Flags & KV86M_EMULATE_CLI_STI)
@ -99,8 +108,9 @@ KeV86GPF(PKV86M_TRAP_FRAME VTf, PKTRAP_FRAME Tf)
/* cli */ /* cli */
case 0xFA: case 0xFA:
if (BigDataPrefix || BigAddressPrefix) if (BigDataPrefix || BigAddressPrefix || RepPrefix)
{ {
*VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
return(1); return(1);
} }
if (VTf->regs->Flags & KV86M_EMULATE_CLI_STI) if (VTf->regs->Flags & KV86M_EMULATE_CLI_STI)
@ -114,6 +124,11 @@ KeV86GPF(PKV86M_TRAP_FRAME VTf, PKTRAP_FRAME Tf)
/* pushf */ /* pushf */
case 0x9C: case 0x9C:
if (RepPrefix)
{
*VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
return(1);
}
if (VTf->regs->Flags & KV86M_EMULATE_CLI_STI) if (VTf->regs->Flags & KV86M_EMULATE_CLI_STI)
{ {
Tf->Eip++; Tf->Eip++;
@ -153,6 +168,11 @@ KeV86GPF(PKV86M_TRAP_FRAME VTf, PKTRAP_FRAME Tf)
/* popf */ /* popf */
case 0x9D: case 0x9D:
if (RepPrefix)
{
*VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
return(1);
}
if (VTf->regs->Flags & KV86M_EMULATE_CLI_STI) if (VTf->regs->Flags & KV86M_EMULATE_CLI_STI)
{ {
Tf->Eip++; Tf->Eip++;
@ -192,6 +212,11 @@ KeV86GPF(PKV86M_TRAP_FRAME VTf, PKTRAP_FRAME Tf)
/* iret */ /* iret */
case 0xCF: case 0xCF:
if (RepPrefix)
{
*VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
return(1);
}
if (VTf->regs->Flags & KV86M_EMULATE_CLI_STI) if (VTf->regs->Flags & KV86M_EMULATE_CLI_STI)
{ {
Tf->Eip = sp[0]; Tf->Eip = sp[0];
@ -215,9 +240,14 @@ KeV86GPF(PKV86M_TRAP_FRAME VTf, PKTRAP_FRAME Tf)
/* out imm8, al */ /* out imm8, al */
case 0xE6: case 0xE6:
if (RepPrefix)
{
*VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
return(1);
}
if (VTf->regs->Flags & KV86M_ALLOW_IO_PORT_ACCESS) if (VTf->regs->Flags & KV86M_ALLOW_IO_PORT_ACCESS)
{ {
WRITE_PORT_UCHAR((PUCHAR)(ULONG)ip[1], WRITE_PORT_UCHAR((PUCHAR)(ULONG)ip[i + 1],
Tf->Eax & 0xFF); Tf->Eax & 0xFF);
Tf->Eip = Tf->Eip + 2; Tf->Eip = Tf->Eip + 2;
return(0); return(0);
@ -227,9 +257,21 @@ KeV86GPF(PKV86M_TRAP_FRAME VTf, PKTRAP_FRAME Tf)
/* out imm8, ax */ /* out imm8, ax */
case 0xE7: case 0xE7:
if (RepPrefix)
{
*VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
return(1);
}
if (VTf->regs->Flags & KV86M_ALLOW_IO_PORT_ACCESS) if (VTf->regs->Flags & KV86M_ALLOW_IO_PORT_ACCESS)
{
if (!BigDataPrefix)
{ {
WRITE_PORT_USHORT((PUSHORT)(ULONG)ip[1], Tf->Eax & 0xFFFF); WRITE_PORT_USHORT((PUSHORT)(ULONG)ip[1], Tf->Eax & 0xFFFF);
}
else
{
WRITE_PORT_ULONG((PULONG)(ULONG)ip[1], Tf->Eax);
}
Tf->Eip = Tf->Eip + 2; Tf->Eip = Tf->Eip + 2;
return(0); return(0);
} }
@ -238,6 +280,11 @@ KeV86GPF(PKV86M_TRAP_FRAME VTf, PKTRAP_FRAME Tf)
/* out dx, al */ /* out dx, al */
case 0xEE: case 0xEE:
if (RepPrefix)
{
*VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
return(1);
}
if (VTf->regs->Flags & KV86M_ALLOW_IO_PORT_ACCESS) if (VTf->regs->Flags & KV86M_ALLOW_IO_PORT_ACCESS)
{ {
WRITE_PORT_UCHAR((PUCHAR)(Tf->Edx & 0xFFFF), Tf->Eax & 0xFF); WRITE_PORT_UCHAR((PUCHAR)(Tf->Edx & 0xFFFF), Tf->Eax & 0xFF);
@ -249,9 +296,23 @@ KeV86GPF(PKV86M_TRAP_FRAME VTf, PKTRAP_FRAME Tf)
/* out dx, ax */ /* out dx, ax */
case 0xEF: case 0xEF:
if (RepPrefix)
{
*VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
return(1);
}
if (VTf->regs->Flags & KV86M_ALLOW_IO_PORT_ACCESS) if (VTf->regs->Flags & KV86M_ALLOW_IO_PORT_ACCESS)
{ {
WRITE_PORT_USHORT((PUSHORT)(Tf->Edx & 0xFFFF), Tf->Eax & 0xFFFF); if (!BigDataPrefix)
{
WRITE_PORT_USHORT((PUSHORT)(Tf->Edx & 0xFFFF),
Tf->Eax & 0xFFFF);
}
else
{
WRITE_PORT_ULONG((PULONG)(Tf->Edx & 0xFFFF),
Tf->Eax);
}
Tf->Eip = Tf->Eip + 1; Tf->Eip = Tf->Eip + 1;
return(0); return(0);
} }
@ -260,6 +321,11 @@ KeV86GPF(PKV86M_TRAP_FRAME VTf, PKTRAP_FRAME Tf)
/* in al, imm8 */ /* in al, imm8 */
case 0xE4: case 0xE4:
if (RepPrefix)
{
*VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
return(1);
}
if (VTf->regs->Flags & KV86M_ALLOW_IO_PORT_ACCESS) if (VTf->regs->Flags & KV86M_ALLOW_IO_PORT_ACCESS)
{ {
UCHAR v; UCHAR v;
@ -275,6 +341,11 @@ KeV86GPF(PKV86M_TRAP_FRAME VTf, PKTRAP_FRAME Tf)
/* in ax, imm8 */ /* in ax, imm8 */
case 0xE5: case 0xE5:
if (RepPrefix)
{
*VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
return(1);
}
if (VTf->regs->Flags & KV86M_ALLOW_IO_PORT_ACCESS) if (VTf->regs->Flags & KV86M_ALLOW_IO_PORT_ACCESS)
{ {
USHORT v; USHORT v;
@ -290,6 +361,11 @@ KeV86GPF(PKV86M_TRAP_FRAME VTf, PKTRAP_FRAME Tf)
/* in al, dx */ /* in al, dx */
case 0xEC: case 0xEC:
if (RepPrefix)
{
*VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
return(1);
}
if (VTf->regs->Flags & KV86M_ALLOW_IO_PORT_ACCESS) if (VTf->regs->Flags & KV86M_ALLOW_IO_PORT_ACCESS)
{ {
UCHAR v; UCHAR v;
@ -305,6 +381,11 @@ KeV86GPF(PKV86M_TRAP_FRAME VTf, PKTRAP_FRAME Tf)
/* in ax, dx */ /* in ax, dx */
case 0xED: case 0xED:
if (RepPrefix)
{
*VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
return(1);
}
if (VTf->regs->Flags & KV86M_ALLOW_IO_PORT_ACCESS) if (VTf->regs->Flags & KV86M_ALLOW_IO_PORT_ACCESS)
{ {
USHORT v; USHORT v;
@ -318,11 +399,236 @@ KeV86GPF(PKV86M_TRAP_FRAME VTf, PKTRAP_FRAME Tf)
Exit = TRUE; Exit = TRUE;
break; break;
/* outsb */
case 0x6E:
if (VTf->regs->Flags & KV86M_ALLOW_IO_PORT_ACCESS)
{
ULONG Count;
PUCHAR Port;
PUCHAR Buffer;
ULONG Offset;
Count = 1;
if (RepPrefix)
{
Count = Tf->Ecx;
if (!BigAddressPrefix)
{
Count = Count & 0xFFFF;
}
}
Port = (PUCHAR)(Tf->Edx & 0xFFFF);
Offset = Tf->Edi;
if (!BigAddressPrefix)
{
Offset = Offset & 0xFFFF;
}
Buffer = (PUCHAR)((Tf->Es * 16) + Offset);
for (; Count > 0; Count--)
{
WRITE_PORT_UCHAR(Port, *Buffer);
if (Tf->Eflags & DIRECTION_FLAG)
{
Buffer++;
}
else
{
Buffer--;
}
}
Tf->Eip++;
return(0);
}
Exit = TRUE;
break;
/* insw/insd */
case 0x6F:
if (VTf->regs->Flags & KV86M_ALLOW_IO_PORT_ACCESS)
{
ULONG Count;
PUCHAR Port;
PUSHORT BufferS;
PULONG BufferL;
ULONG Offset;
Count = 1;
if (RepPrefix)
{
Count = Tf->Ecx;
if (!BigAddressPrefix)
{
Count = Count & 0xFFFF;
}
}
Port = (PUCHAR)(Tf->Edx & 0xFFFF);
Offset = Tf->Edi;
if (!BigAddressPrefix)
{
Offset = Offset & 0xFFFF;
}
if (BigDataPrefix)
{
BufferL = (PULONG)((Tf->Es * 16) + Offset);
}
else
{
BufferS = (PUSHORT)((Tf->Es * 16) + Offset);
}
for (; Count > 0; Count--)
{
if (BigDataPrefix)
{
WRITE_PORT_ULONG((PULONG)Port, *BufferL);
}
else
{
WRITE_PORT_USHORT((PUSHORT)Port, *BufferS);
}
if (Tf->Eflags & DIRECTION_FLAG)
{
if (BigDataPrefix)
{
BufferL++;
}
else
{
BufferS++;
}
}
else
{
if (BigDataPrefix)
{
BufferL--;
}
else
{
BufferS--;
}
}
}
Tf->Eip++;
return(0);
}
Exit = TRUE;
break;
/* insb */ /* insb */
case 0x6C: case 0x6C:
if (VTf->regs->Flags & KV86M_ALLOW_IO_PORT_ACCESS) if (VTf->regs->Flags & KV86M_ALLOW_IO_PORT_ACCESS)
{ {
ULONG Count;
PUCHAR Port;
PUCHAR Buffer;
ULONG Offset;
Count = 1;
if (RepPrefix)
{
Count = Tf->Ecx;
if (!BigAddressPrefix)
{
Count = Count & 0xFFFF;
}
}
Port = (PUCHAR)(Tf->Edx & 0xFFFF);
Offset = Tf->Edi;
if (!BigAddressPrefix)
{
Offset = Offset & 0xFFFF;
}
Buffer = (PUCHAR)((Tf->Es * 16) + Offset);
for (; Count > 0; Count--)
{
*Buffer = READ_PORT_UCHAR(Port);
if (Tf->Eflags & DIRECTION_FLAG)
{
Buffer++;
}
else
{
Buffer--;
}
}
Tf->Eip++;
return(0);
}
Exit = TRUE;
break;
/* insw/insd */
case 0x6D:
if (VTf->regs->Flags & KV86M_ALLOW_IO_PORT_ACCESS)
{
ULONG Count;
PUCHAR Port;
PUSHORT BufferS;
PULONG BufferL;
ULONG Offset;
Count = 1;
if (RepPrefix)
{
Count = Tf->Ecx;
if (!BigAddressPrefix)
{
Count = Count & 0xFFFF;
}
}
Port = (PUCHAR)(Tf->Edx & 0xFFFF);
Offset = Tf->Edi;
if (!BigAddressPrefix)
{
Offset = Offset & 0xFFFF;
}
if (BigDataPrefix)
{
BufferL = (PULONG)((Tf->Es * 16) + Offset);
}
else
{
BufferS = (PUSHORT)((Tf->Es * 16) + Offset);
}
for (; Count > 0; Count--)
{
if (BigDataPrefix)
{
*BufferL = READ_PORT_ULONG((PULONG)Port);
}
else
{
*BufferS = READ_PORT_USHORT((PUSHORT)Port);
}
if (Tf->Eflags & DIRECTION_FLAG)
{
if (BigDataPrefix)
{
BufferL++;
}
else
{
BufferS++;
}
}
else
{
if (BigDataPrefix)
{
BufferL--;
}
else
{
BufferS--;
}
}
}
Tf->Eip++;
return(0);
} }
Exit = TRUE; Exit = TRUE;
break; break;
@ -360,7 +666,7 @@ KeV86GPF(PKV86M_TRAP_FRAME VTf, PKTRAP_FRAME Tf)
/* FIXME: Don't allow the BIOS to write to sensitive I/O ports */ /* FIXME: Don't allow the BIOS to write to sensitive I/O ports */
} }
DPRINT("V86GPF unhandled\n"); DPRINT1("V86GPF unhandled (was %x)\n", ip[i]);
*VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION; *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
return(1); return(1);
} }

View file

@ -52,12 +52,17 @@ PiSuspendThreadNormalRoutine(PVOID NormalContext,
PVOID SystemArgument1, PVOID SystemArgument1,
PVOID SystemArgument2); PVOID SystemArgument2);
/* GLOBALS *******************************************************************/
#define TAG_THREAD_STACK TAG('T', 'S', 'T', 'K')
/* FUNCTIONS *****************************************************************/ /* FUNCTIONS *****************************************************************/
VOID
KeFreeStackPage(PVOID Context, PVOID Address, ULONG PhysAddr)
{
if (PhysAddr != 0)
{
MmDereferencePage((PVOID)PhysAddr);
}
}
NTSTATUS NTSTATUS
HalReleaseTask(PETHREAD Thread) HalReleaseTask(PETHREAD Thread)
/* /*
@ -70,7 +75,11 @@ HalReleaseTask(PETHREAD Thread)
if (Thread->Tcb.StackLimit != (ULONG)&init_stack) if (Thread->Tcb.StackLimit != (ULONG)&init_stack)
{ {
ExFreePool((PVOID)Thread->Tcb.StackLimit); MmFreeMemoryArea(MmGetKernelAddressSpace(),
(PVOID)Thread->Tcb.StackLimit,
MM_STACK_SIZE,
KeFreeStackPage,
NULL);
} }
Thread->Tcb.StackLimit = 0; Thread->Tcb.StackLimit = 0;
Thread->Tcb.InitialStack = NULL; Thread->Tcb.InitialStack = NULL;
@ -86,8 +95,11 @@ KeInitializeThread(PKPROCESS Process, PKTHREAD Thread, BOOLEAN First)
*/ */
{ {
PVOID KernelStack; PVOID KernelStack;
NTSTATUS Status;
extern unsigned int init_stack_top; extern unsigned int init_stack_top;
extern unsigned int init_stack; extern unsigned int init_stack;
PMEMORY_AREA StackArea;
ULONG i;
KeInitializeDispatcherHeader(&Thread->DispatcherHeader, KeInitializeDispatcherHeader(&Thread->DispatcherHeader,
InternalThreadType, InternalThreadType,
@ -96,8 +108,27 @@ KeInitializeThread(PKPROCESS Process, PKTHREAD Thread, BOOLEAN First)
InitializeListHead(&Thread->MutantListHead); InitializeListHead(&Thread->MutantListHead);
if (!First) if (!First)
{ {
KernelStack = ExAllocatePoolWithTag(NonPagedPool, MM_STACK_SIZE, KernelStack = NULL;
TAG_THREAD_STACK); Status = MmCreateMemoryArea(NULL,
MmGetKernelAddressSpace(),
MEMORY_AREA_KERNEL_STACK,
&KernelStack,
MM_STACK_SIZE,
0,
&StackArea,
FALSE);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to create thread stack\n");
KeBugCheck(0);
}
for (i = 0; i < (MM_STACK_SIZE / PAGESIZE); i++)
{
Status = MmCreateVirtualMapping(NULL,
KernelStack + (i * PAGESIZE),
PAGE_EXECUTE_READWRITE,
(ULONG)MmAllocPage(0));
}
Thread->InitialStack = KernelStack + MM_STACK_SIZE; Thread->InitialStack = KernelStack + MM_STACK_SIZE;
Thread->StackBase = KernelStack + MM_STACK_SIZE; Thread->StackBase = KernelStack + MM_STACK_SIZE;
Thread->StackLimit = (ULONG)KernelStack; Thread->StackLimit = (ULONG)KernelStack;

View file

@ -16,8 +16,8 @@
/* GLOBALS *******************************************************************/ /* GLOBALS *******************************************************************/
/* static */ UCHAR OrigIVT[1024]; static UCHAR OrigIVT[1024];
/* static UCHAR OrigBDA[]; */ static UCHAR OrigBDA[256];
/* static UCHAR OrigEBDA[]; */ /* static UCHAR OrigEBDA[]; */
/* FUNCTIONS *****************************************************************/ /* FUNCTIONS *****************************************************************/
@ -30,12 +30,22 @@ NtEarlyInitVdm(VOID)
* map is still active so we can just copy the data from low memory. * map is still active so we can just copy the data from low memory.
*/ */
memcpy(OrigIVT, (PVOID)0x0, 1024); memcpy(OrigIVT, (PVOID)0x0, 1024);
memcpy(OrigBDA, (PVOID)0x400, 256);
} }
NTSTATUS STDCALL NtVdmControl(ULONG ControlCode, NTSTATUS STDCALL NtVdmControl(ULONG ControlCode,
PVOID ControlData) PVOID ControlData)
{ {
switch (ControlCode)
{
case 0:
memcpy(ControlData, OrigIVT, 1024); memcpy(ControlData, OrigIVT, 1024);
break;
case 1:
memcpy(ControlData, OrigBDA, 256);
break;
}
return(STATUS_SUCCESS); return(STATUS_SUCCESS);
} }

View file

@ -12,6 +12,7 @@ InitializeVideoAddressSpace(VOID)
ULONG ViewSize; ULONG ViewSize;
PUCHAR TextMap; PUCHAR TextMap;
CHAR IVT[1024]; CHAR IVT[1024];
CHAR BDA[256];
/* /*
* Open the physical memory section * Open the physical memory section
@ -99,5 +100,20 @@ InitializeVideoAddressSpace(VOID)
*/ */
memcpy((PVOID)0x0, IVT, 1024); memcpy((PVOID)0x0, IVT, 1024);
/*
* Get the BDA from the kernel
*/
Status = NtVdmControl(1, BDA);
if (!NT_SUCCESS(Status))
{
DbgPrint("NtVdmControl failed (status %x)\n", Status);
return(0);
}
/*
* Copy the BDA into the right place
*/
memcpy((PVOID)0x400, BDA, 256);
return(1); return(1);
} }