Fix longstanding bug in keyboard driver

svn path=/trunk/; revision=1775
This commit is contained in:
David Welch 2001-04-04 22:21:32 +00:00
parent 8d1e0c87b3
commit b7437fe01a
11 changed files with 834 additions and 691 deletions

View file

@ -7,20 +7,10 @@
HANDLE OutputHandle; HANDLE OutputHandle;
HANDLE InputHandle; HANDLE InputHandle;
void debug_printf(char* fmt, ...) VOID STDCALL
{ ApcRoutine(PVOID Context,
va_list args; PIO_STATUS_BLOCK IoStatus,
char buffer[255]; ULONG Reserved)
va_start(args,fmt);
vsprintf(buffer,fmt,args);
WriteConsoleA(OutputHandle, buffer, strlen(buffer), NULL, NULL);
va_end(args);
}
VOID STDCALL ApcRoutine(PVOID Context,
PIO_STATUS_BLOCK IoStatus,
ULONG Reserved)
{ {
printf("(apc.exe) ApcRoutine(Context %p)\n", Context); printf("(apc.exe) ApcRoutine(Context %p)\n", Context);
} }

View file

@ -695,26 +695,18 @@ NTSTATUS STDCALL KbdDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp)
case IRP_MJ_READ: case IRP_MJ_READ:
DPRINT("Handling Read request\n"); DPRINT("Handling Read request\n");
DPRINT("Queueing packet\n"); DPRINT("Queueing packet\n");
IoMarkIrpPending(Irp);
IoStartPacket(DeviceObject,Irp,NULL,NULL); IoStartPacket(DeviceObject,Irp,NULL,NULL);
Status = STATUS_PENDING; return(STATUS_PENDING);
break;
default: default:
Status = STATUS_NOT_IMPLEMENTED; Status = STATUS_NOT_IMPLEMENTED;
break; break;
} }
if (Status==STATUS_PENDING) Irp->IoStatus.Status = Status;
{ Irp->IoStatus.Information = 0;
DPRINT("Marking irp pending\n"); IoCompleteRequest(Irp,IO_NO_INCREMENT);
IoMarkIrpPending(Irp);
}
else
{
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp,IO_NO_INCREMENT);
}
DPRINT("Status %d\n",Status); DPRINT("Status %d\n",Status);
return(Status); return(Status);
} }

View file

@ -27,17 +27,19 @@
#define FIELD_OFFSET(type,fld) ((LONG)&(((type *)0)->fld)) #define FIELD_OFFSET(type,fld) ((LONG)&(((type *)0)->fld))
#endif #endif
/* GLOBAL VARIABLES **********************************************************/
/* GLOBAL VARIABLES ***********************************************************/
extern WINBOOL bIsFileApiAnsi; extern WINBOOL bIsFileApiAnsi;
extern HANDLE hProcessHeap; extern HANDLE hProcessHeap;
extern HANDLE hBaseDir; extern HANDLE hBaseDir;
/* FUNCTION PROTOTYPES ********************************************************/ extern CRITICAL_SECTION DllLock;
/* FUNCTION PROTOTYPES *******************************************************/
BOOLEAN STDCALL IsConsoleHandle(HANDLE Handle); BOOLEAN STDCALL IsConsoleHandle(HANDLE Handle);
WINBOOL STDCALL CloseConsoleHandle(HANDLE Handle); WINBOOL STDCALL CloseConsoleHandle(HANDLE Handle);
#endif /* ndef _INCLUDE_KERNEL32_KERNEL32_H */ #endif /* ndef _INCLUDE_KERNEL32_KERNEL32_H */

File diff suppressed because it is too large Load diff

View file

@ -1,4 +1,4 @@
/* $Id: dllmain.c,v 1.17 2001/01/20 18:37:08 ekohl Exp $ /* $Id: dllmain.c,v 1.18 2001/04/04 22:21:30 dwelch Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries * PROJECT: ReactOS system libraries
@ -9,6 +9,8 @@
* Created 01/11/98 * Created 01/11/98
*/ */
/* INCLUDES ******************************************************************/
#include <ddk/ntddk.h> #include <ddk/ntddk.h>
#include <ntdll/csr.h> #include <ntdll/csr.h>
#include <ntdll/ldr.h> #include <ntdll/ldr.h>
@ -19,6 +21,7 @@
#define NDEBUG #define NDEBUG
#include <kernel32/kernel32.h> #include <kernel32/kernel32.h>
/* GLOBALS *******************************************************************/
extern UNICODE_STRING SystemDirectory; extern UNICODE_STRING SystemDirectory;
extern UNICODE_STRING WindowsDirectory; extern UNICODE_STRING WindowsDirectory;
@ -32,8 +35,13 @@ WINBOOL STDCALL DllMain (HANDLE hInst,
ULONG ul_reason_for_call, ULONG ul_reason_for_call,
LPVOID lpReserved); LPVOID lpReserved);
/* Critical section for various kernel32 data structures */
CRITICAL_SECTION DllLock;
static NTSTATUS OpenBaseDirectory(PHANDLE DirHandle) /* FUNCTIONS *****************************************************************/
static NTSTATUS
OpenBaseDirectory(PHANDLE DirHandle)
{ {
OBJECT_ATTRIBUTES ObjectAttributes; OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING Name; UNICODE_STRING Name;
@ -68,15 +76,16 @@ static NTSTATUS OpenBaseDirectory(PHANDLE DirHandle)
} }
BOOL WINAPI DllMainCRTStartup(HANDLE hDll, DWORD dwReason, LPVOID lpReserved) BOOL WINAPI
DllMainCRTStartup(HANDLE hDll, DWORD dwReason, LPVOID lpReserved)
{ {
return(DllMain(hDll,dwReason,lpReserved)); return(DllMain(hDll,dwReason,lpReserved));
} }
WINBOOL STDCALL
WINBOOL STDCALL DllMain(HANDLE hInst, DllMain(HANDLE hInst,
ULONG ul_reason_for_call, ULONG ul_reason_for_call,
LPVOID lpReserved) LPVOID lpReserved)
{ {
DPRINT("DllMain(hInst %x, ul_reason_for_call %d)\n", DPRINT("DllMain(hInst %x, ul_reason_for_call %d)\n",
hInst, ul_reason_for_call); hInst, ul_reason_for_call);
@ -127,6 +136,9 @@ WINBOOL STDCALL DllMain(HANDLE hInst,
DbgPrint("Failed to open object base directory: expect trouble\n"); DbgPrint("Failed to open object base directory: expect trouble\n");
} }
/* Initialize the DLL critical section */
RtlInitializeCriticalSection(&DllLock);
/* Insert more dll attach stuff here! */ /* Insert more dll attach stuff here! */
DllInitialized = TRUE; DllInitialized = TRUE;
@ -138,13 +150,16 @@ WINBOOL STDCALL DllMain(HANDLE hInst,
DPRINT("DLL_PROCESS_DETACH\n"); DPRINT("DLL_PROCESS_DETACH\n");
if (DllInitialized == TRUE) if (DllInitialized == TRUE)
{ {
/* Insert more dll detach stuff here! */ /* Insert more dll detach stuff here! */
/* Delete DLL critical section */
RtlDeleteCriticalSection (&DllLock);
/* Close object base directory */ /* Close object base directory */
NtClose(hBaseDir); NtClose(hBaseDir);
RtlFreeUnicodeString (&SystemDirectory); RtlFreeUnicodeString (&SystemDirectory);
RtlFreeUnicodeString (&WindowsDirectory); RtlFreeUnicodeString (&WindowsDirectory);
} }
break; break;
} }

View file

@ -389,6 +389,11 @@ MmGetReferenceCountPage(PVOID PhysicalAddress);
BOOLEAN BOOLEAN
MmIsUsablePage(PVOID PhysicalAddress); MmIsUsablePage(PVOID PhysicalAddress);
#define MM_PAGEOP_PAGEIN (1)
#define MM_PAGEOP_PAGEOUT (2)
#define MM_PAGEOP_PAGESYNCH (3)
#define MM_PAGEOP_ACCESSFAULT (4)
typedef struct _MM_PAGEOP typedef struct _MM_PAGEOP
{ {
/* Type of operation. */ /* Type of operation. */
@ -425,7 +430,7 @@ MmReleasePageOp(PMM_PAGEOP PageOp);
PMM_PAGEOP PMM_PAGEOP
MmGetPageOp(PMEMORY_AREA MArea, ULONG Pid, PVOID Address, MmGetPageOp(PMEMORY_AREA MArea, ULONG Pid, PVOID Address,
PMM_SECTION_SEGMENT Segment, ULONG Offset); PMM_SECTION_SEGMENT Segment, ULONG Offset, ULONG OpType);
VOID VOID
MiDebugDumpNonPagedPool(BOOLEAN NewOnly); MiDebugDumpNonPagedPool(BOOLEAN NewOnly);
@ -455,4 +460,6 @@ MmIsAccessedAndResetAccessPage(struct _EPROCESS* Process, PVOID Address);
SWAPENTRY SWAPENTRY
MmGetSavedSwapEntryPage(PVOID PhysicalAddress); MmGetSavedSwapEntryPage(PVOID PhysicalAddress);
#define STATUS_MM_RESTART_OPERATION (0xD0000001)
#endif #endif

View file

@ -1,6 +1,23 @@
/* $Id: resource.c,v 1.4 2000/04/05 15:50:29 ekohl Exp $ /*
* ReactOS kernel
* Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
*
* 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: resource.c,v 1.5 2001/04/04 22:21:31 dwelch Exp $
* *
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
* FILE: ntoskrnl/io/resource.c * FILE: ntoskrnl/io/resource.c
* PURPOSE: Hardware resource managment * PURPOSE: Hardware resource managment
@ -23,64 +40,79 @@ static CONFIGURATION_INFORMATION SystemConfigurationInformation =
/* FUNCTIONS *****************************************************************/ /* FUNCTIONS *****************************************************************/
PCONFIGURATION_INFORMATION PCONFIGURATION_INFORMATION STDCALL
STDCALL
IoGetConfigurationInformation(VOID) IoGetConfigurationInformation(VOID)
{ {
return(&SystemConfigurationInformation); return(&SystemConfigurationInformation);
} }
NTSTATUS NTSTATUS STDCALL
STDCALL
IoReportResourceUsage(PUNICODE_STRING DriverClassName, IoReportResourceUsage(PUNICODE_STRING DriverClassName,
PDRIVER_OBJECT DriverObject, PDRIVER_OBJECT DriverObject,
PCM_RESOURCE_LIST DriverList, PCM_RESOURCE_LIST DriverList,
ULONG DriverListSize, ULONG DriverListSize,
PDEVICE_OBJECT DeviceObject, PDEVICE_OBJECT DeviceObject,
PCM_RESOURCE_LIST DeviceList, PCM_RESOURCE_LIST DeviceList,
ULONG DeviceListSize, ULONG DeviceListSize,
BOOLEAN OverrideConflict, BOOLEAN OverrideConflict,
PBOOLEAN ConflictDetected) PBOOLEAN ConflictDetected)
/*
* FUNCTION: Reports hardware resources in the
* \Registry\Machine\Hardware\ResourceMap tree, so that a subsequently
* loaded driver cannot attempt to use the same resources.
* ARGUMENTS:
* DriverClassName - The class of driver under which the resource
* information should be stored.
* DriverObject - The driver object that was input to the
* DriverEntry.
* DriverList - Resources that claimed for the driver rather than
* per-device.
* DriverListSize - Size in bytes of the DriverList.
* DeviceObject - The device object for which resources should be
* claimed.
* DeviceList - List of resources which should be claimed for the
* device.
* DeviceListSize - Size of the per-device resource list in bytes.
* OverrideConflict - True if the resources should be cliamed
* even if a conflict is found.
* ConflictDetected - Points to a variable that receives TRUE if
* a conflict is detected with another driver.
*/
{ {
UNIMPLEMENTED; UNIMPLEMENTED;
} }
NTSTATUS NTSTATUS STDCALL
STDCALL
IoAssignResources(PUNICODE_STRING RegistryPath, IoAssignResources(PUNICODE_STRING RegistryPath,
PUNICODE_STRING DriverClassName, PUNICODE_STRING DriverClassName,
PDRIVER_OBJECT DriverObject, PDRIVER_OBJECT DriverObject,
PDEVICE_OBJECT DeviceObject, PDEVICE_OBJECT DeviceObject,
PIO_RESOURCE_REQUIREMENTS_LIST RequestedResources, PIO_RESOURCE_REQUIREMENTS_LIST RequestedResources,
PCM_RESOURCE_LIST* AllocatedResources) PCM_RESOURCE_LIST* AllocatedResources)
{ {
UNIMPLEMENTED; UNIMPLEMENTED;
} }
NTSTATUS NTSTATUS STDCALL
STDCALL
IoQueryDeviceDescription(PINTERFACE_TYPE BusType, IoQueryDeviceDescription(PINTERFACE_TYPE BusType,
PULONG BusNumber, PULONG BusNumber,
PCONFIGURATION_TYPE ControllerType, PCONFIGURATION_TYPE ControllerType,
PULONG ControllerNumber, PULONG ControllerNumber,
PCONFIGURATION_TYPE PeripheralType, PCONFIGURATION_TYPE PeripheralType,
PULONG PeripheralNumber, PULONG PeripheralNumber,
PIO_QUERY_DEVICE_ROUTINE CalloutRoutine, PIO_QUERY_DEVICE_ROUTINE CalloutRoutine,
PVOID Context) PVOID Context)
{ {
UNIMPLEMENTED; UNIMPLEMENTED;
} }
NTSTATUS NTSTATUS STDCALL
STDCALL IoReportHalResourceUsage (PUNICODE_STRING HalDescription,
IoReportHalResourceUsage ( ULONG Unknown1,
PUNICODE_STRING HalDescription, ULONG Unknown2,
ULONG Unknown1, ULONG Unknown3)
ULONG Unknown2,
ULONG Unknown3
)
{ {
UNIMPLEMENTED; UNIMPLEMENTED;
} }
/* EOF */ /* EOF */

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
/* $Id: mm.c,v 1.46 2001/03/16 18:11:23 dwelch Exp $ /* $Id: mm.c,v 1.47 2001/04/04 22:21:31 dwelch Exp $
* *
* COPYRIGHT: See COPYING in the top directory * COPYRIGHT: See COPYING in the top directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -285,49 +285,60 @@ NTSTATUS MmNotPresentFault(KPROCESSOR_MODE Mode,
{ {
MmLockAddressSpace(AddressSpace); MmLockAddressSpace(AddressSpace);
} }
MemoryArea = MmOpenMemoryAreaByAddress(AddressSpace, (PVOID)Address);
if (MemoryArea == NULL) /*
* Call the memory area specific fault handler
*/
do
{ {
DbgPrint("%s:%d\n",__FILE__,__LINE__); MemoryArea = MmOpenMemoryAreaByAddress(AddressSpace, (PVOID)Address);
if (!FromMdl) if (MemoryArea == NULL)
{ {
MmUnlockAddressSpace(AddressSpace); DbgPrint("%s:%d\n",__FILE__,__LINE__);
} if (!FromMdl)
return(STATUS_UNSUCCESSFUL); {
} MmUnlockAddressSpace(AddressSpace);
}
switch (MemoryArea->Type) Status = STATUS_UNSUCCESSFUL;
{ }
case MEMORY_AREA_SYSTEM: else
Status = STATUS_UNSUCCESSFUL; {
break; switch (MemoryArea->Type)
{
case MEMORY_AREA_SECTION_VIEW_COMMIT: case MEMORY_AREA_SYSTEM:
Status = MmNotPresentFaultSectionView(AddressSpace, Status = STATUS_UNSUCCESSFUL;
MemoryArea, break;
(PVOID)Address,
Locked); case MEMORY_AREA_SECTION_VIEW_COMMIT:
break; Status = MmNotPresentFaultSectionView(AddressSpace,
MemoryArea,
case MEMORY_AREA_VIRTUAL_MEMORY: (PVOID)Address,
Status = MmNotPresentFaultVirtualMemory(AddressSpace, Locked);
MemoryArea, break;
(PVOID)Address,
Locked); case MEMORY_AREA_VIRTUAL_MEMORY:
break; Status = MmNotPresentFaultVirtualMemory(AddressSpace,
MemoryArea,
case MEMORY_AREA_SHARED_DATA: (PVOID)Address,
Status = Locked);
MmCreateVirtualMapping(PsGetCurrentProcess(), break;
(PVOID)PAGE_ROUND_DOWN(Address),
PAGE_READONLY, case MEMORY_AREA_SHARED_DATA:
(ULONG)MmSharedDataPagePhysicalAddress); Status =
break; MmCreateVirtualMapping(PsGetCurrentProcess(),
(PVOID)PAGE_ROUND_DOWN(Address),
default: PAGE_READONLY,
Status = STATUS_UNSUCCESSFUL; (ULONG)MmSharedDataPagePhysicalAddress);
break; break;
default:
Status = STATUS_UNSUCCESSFUL;
break;
}
}
} }
while (Status == STATUS_MM_RESTART_OPERATION);
DPRINT("Completed page fault handling\n"); DPRINT("Completed page fault handling\n");
if (!FromMdl) if (!FromMdl)
{ {

View file

@ -1,4 +1,4 @@
/* $Id: pageop.c,v 1.4 2001/03/16 18:11:23 dwelch Exp $ /* $Id: pageop.c,v 1.5 2001/04/04 22:21:31 dwelch Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -71,7 +71,7 @@ MmReleasePageOp(PMM_PAGEOP PageOp)
PMM_PAGEOP PMM_PAGEOP
MmGetPageOp(PMEMORY_AREA MArea, ULONG Pid, PVOID Address, MmGetPageOp(PMEMORY_AREA MArea, ULONG Pid, PVOID Address,
PMM_SECTION_SEGMENT Segment, ULONG Offset) PMM_SECTION_SEGMENT Segment, ULONG Offset, ULONG OpType)
/* /*
* FUNCTION: Get a page operation descriptor corresponding to * FUNCTION: Get a page operation descriptor corresponding to
* the memory area and either the segment, offset pair or the * the memory area and either the segment, offset pair or the
@ -160,6 +160,7 @@ MmGetPageOp(PMEMORY_AREA MArea, ULONG Pid, PVOID Address,
PageOp->Thread = PsGetCurrentThread(); PageOp->Thread = PsGetCurrentThread();
PageOp->Abandoned = FALSE; PageOp->Abandoned = FALSE;
PageOp->Status = STATUS_PENDING; PageOp->Status = STATUS_PENDING;
PageOp->OpType = OpType;
KeInitializeEvent(&PageOp->CompletionEvent, NotificationEvent, FALSE); KeInitializeEvent(&PageOp->CompletionEvent, NotificationEvent, FALSE);
MmPageOpHashTable[Hash] = PageOp; MmPageOpHashTable[Hash] = PageOp;

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
/* $Id: section.c,v 1.55 2001/04/03 17:25:49 dwelch Exp $ /* $Id: section.c,v 1.56 2001/04/04 22:21:31 dwelch Exp $
* *
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
* FILE: ntoskrnl/mm/section.c * FILE: ntoskrnl/mm/section.c
@ -388,7 +388,8 @@ MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
/* /*
* Get or create a page operation descriptor * Get or create a page operation descriptor
*/ */
PageOp = MmGetPageOp(MemoryArea, 0, 0, Segment, Offset.u.LowPart); PageOp = MmGetPageOp(MemoryArea, 0, 0, Segment, Offset.u.LowPart,
MM_PAGEOP_PAGEIN);
if (PageOp == NULL) if (PageOp == NULL)
{ {
DPRINT1("MmGetPageOp failed\n"); DPRINT1("MmGetPageOp failed\n");
@ -422,11 +423,21 @@ MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
DPRINT1("Woke for page op before completion\n"); DPRINT1("Woke for page op before completion\n");
KeBugCheck(0); KeBugCheck(0);
} }
/*
* If this wasn't a pagein then restart the operation
*/
if (PageOp->OpType != MM_PAGEOP_PAGEIN)
{
MmLockAddressSpace(AddressSpace);
MmReleasePageOp(PageOp);
return(STATUS_MM_RESTART_OPERATION);
}
/* /*
* If the thread handling this fault has failed then we don't retry * If the thread handling this fault has failed then we don't retry
*/ */
if (!NT_SUCCESS(PageOp->Status)) if (!NT_SUCCESS(PageOp->Status))
{ {
MmLockAddressSpace(AddressSpace);
return(PageOp->Status); return(PageOp->Status);
} }
MmLockAddressSpace(AddressSpace); MmLockAddressSpace(AddressSpace);
@ -670,6 +681,9 @@ MmAccessFaultSectionView(PMADDRESS_SPACE AddressSpace,
PVOID NewPage; PVOID NewPage;
PVOID NewAddress; PVOID NewAddress;
NTSTATUS Status; NTSTATUS Status;
ULONG PAddress;
LARGE_INTEGER Offset;
PMM_PAGEOP PageOp;
/* /*
* Check if the page has been paged out or has already been set readwrite * Check if the page has been paged out or has already been set readwrite
@ -680,6 +694,13 @@ MmAccessFaultSectionView(PMADDRESS_SPACE AddressSpace,
return(STATUS_SUCCESS); return(STATUS_SUCCESS);
} }
/*
* Find the offset of the page
*/
PAddress = (ULONG)PAGE_ROUND_DOWN(((ULONG)Address));
Offset.QuadPart = (PAddress - (ULONG)MemoryArea->BaseAddress) +
MemoryArea->Data.SectionData.ViewOffset;
/* /*
* Lock the segment * Lock the segment
*/ */
@ -688,6 +709,9 @@ MmAccessFaultSectionView(PMADDRESS_SPACE AddressSpace,
MmLockSection(Section); MmLockSection(Section);
MmLockSectionSegment(Segment); MmLockSectionSegment(Segment);
/*
* Check if we are doing COW
*/
if (!(Segment->Characteristics & IMAGE_SECTION_CHAR_DATA)) if (!(Segment->Characteristics & IMAGE_SECTION_CHAR_DATA))
{ {
MmUnlockSection(Section); MmUnlockSection(Section);
@ -695,34 +719,81 @@ MmAccessFaultSectionView(PMADDRESS_SPACE AddressSpace,
return(STATUS_UNSUCCESSFUL); return(STATUS_UNSUCCESSFUL);
} }
/*
* Get or create a pageop
*/
PageOp = MmGetPageOp(MemoryArea, 0, 0, Segment, Offset.u.LowPart,
MM_PAGEOP_ACCESSFAULT);
if (PageOp == NULL)
{
DPRINT1("MmGetPageOp failed\n");
KeBugCheck(0);
}
/*
* Wait for any other operations to complete
*/
if (PageOp->Thread != PsGetCurrentThread())
{
MmUnlockSectionSegment(Segment);
MmUnlockSection(Section);
MmUnlockAddressSpace(AddressSpace);
Status = KeWaitForSingleObject(&PageOp->CompletionEvent,
0,
KernelMode,
FALSE,
NULL);
/*
* Check for various strange conditions
*/
if (Status != STATUS_SUCCESS)
{
DPRINT1("Failed to wait for page op\n");
KeBugCheck(0);
}
if (PageOp->Status == STATUS_PENDING)
{
DPRINT1("Woke for page op before completion\n");
KeBugCheck(0);
}
/*
* Restart the operation
*/
MmLockAddressSpace(AddressSpace);
MmReleasePageOp(PageOp);
return(STATUS_MM_RESTART_OPERATION);
}
/*
* Release locks now we have the pageop
*/
MmUnlockSectionSegment(Segment);
MmUnlockSection(Section);
MmUnlockAddressSpace(AddressSpace);
/* /*
* Allocate a page * Allocate a page
*/ */
NewPage = MmAllocPage(0); NewPage = MmAllocPage(0);
while (NewPage == NULL) while (NewPage == NULL)
{ {
MmUnlockSectionSegment(Segment);
MmUnlockSection(Section);
MmUnlockAddressSpace(AddressSpace);
MmWaitForFreePages(); MmWaitForFreePages();
MmLockAddressSpace(AddressSpace);
if (!MmIsPagePresent(NULL, Address) ||
MmGetPageProtect(NULL, Address) & PAGE_READWRITE)
{
MmUnlockAddressSpace(AddressSpace);
return(STATUS_SUCCESS);
}
MmLockSection(Section);
MmLockSectionSegment(Segment);
NewPage = MmAllocPage(0); NewPage = MmAllocPage(0);
} }
/*
* Copy the old page
*/
OldPage = MmGetPhysicalAddressForProcess(NULL, Address); OldPage = MmGetPhysicalAddressForProcess(NULL, Address);
NewAddress = ExAllocatePageWithPhysPage((ULONG)NewPage); NewAddress = ExAllocatePageWithPhysPage((ULONG)NewPage);
memcpy(NewAddress, (PVOID)PAGE_ROUND_DOWN(Address), PAGESIZE); memcpy(NewAddress, (PVOID)PAGE_ROUND_DOWN(Address), PAGESIZE);
ExUnmapPage(NewAddress); ExUnmapPage(NewAddress);
/*
* Set the PTE to point to the new page
*/
MmLockAddressSpace(AddressSpace);
Status = MmCreateVirtualMapping(PsGetCurrentProcess(), Status = MmCreateVirtualMapping(PsGetCurrentProcess(),
Address, Address,
MemoryArea->Attributes, MemoryArea->Attributes,
@ -736,8 +807,9 @@ MmAccessFaultSectionView(PMADDRESS_SPACE AddressSpace,
{ {
MmLockPage((PVOID)MmGetPhysicalAddressForProcess(NULL, Address)); MmLockPage((PVOID)MmGetPhysicalAddressForProcess(NULL, Address));
} }
MmUnlockSectionSegment(Segment); PageOp->Status = STATUS_SUCCESS;
MmUnlockSection(Section); KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
MmReleasePageOp(PageOp);
return(STATUS_SUCCESS); return(STATUS_SUCCESS);
} }

View file

@ -1,4 +1,4 @@
/* $Id: virtual.c,v 1.45 2001/03/25 02:34:29 dwelch Exp $ /* $Id: virtual.c,v 1.46 2001/04/04 22:21:31 dwelch Exp $
* *
* COPYRIGHT: See COPYING in the top directory * COPYRIGHT: See COPYING in the top directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -91,90 +91,7 @@ MmWritePageVirtualMemory(PMADDRESS_SPACE AddressSpace,
PMEMORY_AREA MArea, PMEMORY_AREA MArea,
PVOID Address) PVOID Address)
{ {
SWAPENTRY se; return(STATUS_UNSUCCESSFUL);
ULONG Flags;
PHYSICAL_ADDRESS PhysicalAddress;
PMDL Mdl;
NTSTATUS Status;
/*
* FIXME: What should we do if an i/o operation is pending on
* this page
*/
/*
* If the memory area is readonly then there is nothing to do
*/
if (MArea->Attributes & PAGE_READONLY ||
MArea->Attributes & PAGE_EXECUTE_READ)
{
return(STATUS_SUCCESS);
}
/*
* Set the page to readonly. This ensures the current contents aren't
* modified while we are writing it to swap.
*/
MmSetPageProtect(AddressSpace->Process,
Address,
PAGE_READONLY);
/*
* If the page isn't dirty then there is nothing to do.
*/
if (!MmIsPageDirty(AddressSpace->Process, Address))
{
MmSetPageProtect(AddressSpace->Process,
Address,
MArea->Attributes);
return(STATUS_SUCCESS);
}
PhysicalAddress = MmGetPhysicalAddress(Address);
/*
* If we haven't already allocated a swap entry for this page
* then allocate one
*/
if ((se = MmGetSavedSwapEntryPage((PVOID)PhysicalAddress.u.LowPart)) != 0)
{
se = MmAllocSwapPage();
if (se == 0)
{
MmSetPageProtect(AddressSpace->Process,
Address,
MArea->Attributes);
return(STATUS_UNSUCCESSFUL);
}
MmSetSavedSwapEntryPage((PVOID)PhysicalAddress.u.LowPart, se);
}
/*
* Set the flags so other threads will know what we are doing
*/
Flags = MmGetFlagsPage((PVOID)PhysicalAddress.u.LowPart);
Flags = Flags | MM_PHYSICAL_PAGE_MPW_PENDING;
MmSetFlagsPage((PVOID)PhysicalAddress.u.LowPart, Flags);
/*
* Build an mdl to hold the page for writeout
*/
Mdl = MmCreateMdl(NULL, NULL, PAGESIZE);
MmBuildMdlFromPages(Mdl, (PULONG)&PhysicalAddress.u.LowPart);
/*
* Unlock the address space and write out the page to swap.
*/
MmUnlockAddressSpace(AddressSpace);
Status = MmWriteToSwapPage(se, Mdl);
/*
* Cleanup
*/
MmLockAddressSpace(AddressSpace);
Flags = MmGetFlagsPage((PVOID)PhysicalAddress.u.LowPart);
Flags = Flags & (~MM_PHYSICAL_PAGE_MPW_PENDING);
MmSetFlagsPage((PVOID)PhysicalAddress.u.LowPart,Flags);
/*
* If we successfully wrote the page then reset the dirty bit
*/
if (NT_SUCCESS(Status))
{
MmSetCleanPage(AddressSpace->Process, Address);
}
return(Status);
} }
@ -188,6 +105,24 @@ ULONG MmPageOutVirtualMemory(PMADDRESS_SPACE AddressSpace,
SWAPENTRY SwapEntry; SWAPENTRY SwapEntry;
NTSTATUS Status; NTSTATUS Status;
PMDL Mdl; PMDL Mdl;
PMM_PAGEOP PageOp;
/*
* Get or create a pageop
*/
PageOp = MmGetPageOp(MemoryArea, AddressSpace->Process->UniqueProcessId,
(PVOID)PAGE_ROUND_DOWN(Address), NULL, 0,
MM_PAGEOP_PAGEOUT);
if (PageOp->Thread != PsGetCurrentThread())
{
/*
* On the assumption that handling pageouts speedly rather than
* in strict order is better abandon this one.
*/
(*Ul) = FALSE;
MmReleasePageOp(PageOp);
return(STATUS_UNSUCCESSFUL);
}
/* /*
* Paging out code or readonly data is easy. * Paging out code or readonly data is easy.
@ -199,7 +134,11 @@ ULONG MmPageOutVirtualMemory(PMADDRESS_SPACE AddressSpace,
MmDeleteVirtualMapping(PsGetCurrentProcess(), Address, FALSE, MmDeleteVirtualMapping(PsGetCurrentProcess(), Address, FALSE,
NULL, &PhysicalAddress); NULL, &PhysicalAddress);
MmDereferencePage((PVOID)PhysicalAddress); MmDereferencePage((PVOID)PhysicalAddress);
*Ul = TRUE; *Ul = TRUE;
PageOp->Status = STATUS_SUCCESS;
KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
MmReleasePageOp(PageOp);
return(1); return(1);
} }
@ -213,6 +152,9 @@ ULONG MmPageOutVirtualMemory(PMADDRESS_SPACE AddressSpace,
MmRemovePageFromWorkingSet(AddressSpace->Process, Address); MmRemovePageFromWorkingSet(AddressSpace->Process, Address);
MmDereferencePage((PVOID)PhysicalAddress); MmDereferencePage((PVOID)PhysicalAddress);
*Ul = TRUE; *Ul = TRUE;
PageOp->Status = STATUS_SUCCESS;
KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
MmReleasePageOp(PageOp);
return(1); return(1);
} }
@ -230,6 +172,9 @@ ULONG MmPageOutVirtualMemory(PMADDRESS_SPACE AddressSpace,
MemoryArea->Attributes, MemoryArea->Attributes,
PhysicalAddress); PhysicalAddress);
*Ul = FALSE; *Ul = FALSE;
PageOp->Status = STATUS_UNSUCCESSFUL;
KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
MmReleasePageOp(PageOp);
return(0); return(0);
} }
} }
@ -248,6 +193,9 @@ ULONG MmPageOutVirtualMemory(PMADDRESS_SPACE AddressSpace,
MemoryArea->Attributes, MemoryArea->Attributes,
PhysicalAddress); PhysicalAddress);
*Ul = FALSE; *Ul = FALSE;
PageOp->Status = STATUS_UNSUCCESSFUL;
KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
MmReleasePageOp(PageOp);
return(0); return(0);
} }
@ -257,6 +205,9 @@ ULONG MmPageOutVirtualMemory(PMADDRESS_SPACE AddressSpace,
MmRemovePageFromWorkingSet(AddressSpace->Process, Address); MmRemovePageFromWorkingSet(AddressSpace->Process, Address);
MmDereferencePage((PVOID)PhysicalAddress); MmDereferencePage((PVOID)PhysicalAddress);
*Ul = TRUE; *Ul = TRUE;
PageOp->Status = STATUS_SUCCESS;
KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
MmReleasePageOp(PageOp);
return(1); return(1);
} }
@ -312,7 +263,8 @@ MmNotPresentFaultVirtualMemory(PMADDRESS_SPACE AddressSpace,
* Get or create a page operation * Get or create a page operation
*/ */
PageOp = MmGetPageOp(MemoryArea, (ULONG)PsGetCurrentProcessId(), PageOp = MmGetPageOp(MemoryArea, (ULONG)PsGetCurrentProcessId(),
(PVOID)PAGE_ROUND_DOWN(Address), NULL, 0); (PVOID)PAGE_ROUND_DOWN(Address), NULL, 0,
MM_PAGEOP_PAGEIN);
if (PageOp == NULL) if (PageOp == NULL)
{ {
DPRINT1("MmGetPageOp failed"); DPRINT1("MmGetPageOp failed");
@ -344,6 +296,14 @@ MmNotPresentFaultVirtualMemory(PMADDRESS_SPACE AddressSpace,
DPRINT1("Woke for page op before completion\n"); DPRINT1("Woke for page op before completion\n");
KeBugCheck(0); KeBugCheck(0);
} }
/*
* If this wasn't a pagein then we need to restart the handling
*/
if (PageOp->OpType != MM_PAGEOP_PAGEIN)
{
MmReleasePageOp(PageOp);
return(STATUS_MM_RESTART_OPERATION);
}
/* /*
* If the thread handling this fault has failed then we don't retry * If the thread handling this fault has failed then we don't retry
*/ */