Author: hbelusca
Date: Sun May 18 23:13:12 2014
New Revision: 63363
URL: http://svn.reactos.org/svn/reactos?rev=63363&view=rev
Log:
[KERNEL32]: Fix the newline adding (see r63361).
Modified:
trunk/reactos/dll/win32/kernel32/client/vdm.c
Modified: trunk/reactos/dll/win32/kernel32/client/vdm.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/kernel32/client/…
==============================================================================
--- trunk/reactos/dll/win32/kernel32/client/vdm.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/kernel32/client/vdm.c [iso-8859-1] Sun May 18 23:13:12 2014
@@ -284,14 +284,13 @@
if (StartupInfo->dwFlags & STARTF_USESTDHANDLES)
{
/* Set the standard handles */
- CheckVdm->StdIn = StartupInfo->hStdInput;
+ CheckVdm->StdIn = StartupInfo->hStdInput;
CheckVdm->StdOut = StartupInfo->hStdOutput;
CheckVdm->StdErr = StartupInfo->hStdError;
}
/* Allocate memory for the ANSI strings */
-
- /* For the command line we need to add two characters needed for newline '\r\n' */
+ // We need to add the two newline characters '\r\n' to the command line
AnsiCmdLine = (PCHAR)RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, CheckVdm->CmdLen + 2);
AnsiAppName = (PCHAR)RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, CheckVdm->AppLen);
AnsiCurDirectory = (PCHAR)RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, CheckVdm->CurDirectoryLen);
@@ -325,11 +324,11 @@
CheckVdm->CmdLen,
NULL,
NULL);
- /* Add a needed newline '\r\n' */
- CheckVdm->CmdLen--; // FIXME....
- AnsiCmdLine[CheckVdm->CmdLen ] = '\r';
- AnsiCmdLine[CheckVdm->CmdLen + 1] = '\n';
- CheckVdm->CmdLen += 2;
+ /* Add a needed newline '\r\n' and NULL-terminate */
+ CheckVdm->CmdLen--; // Rewind back to the NULL character
+ AnsiCmdLine[CheckVdm->CmdLen++] = '\r';
+ AnsiCmdLine[CheckVdm->CmdLen++] = '\n';
+ AnsiCmdLine[CheckVdm->CmdLen++] = 0;
/* Convert the short application name into an ANSI string */
WideCharToMultiByte(CP_ACP,
Author: hbelusca
Date: Sun May 18 22:10:45 2014
New Revision: 63361
URL: http://svn.reactos.org/svn/reactos?rev=63361&view=rev
Log:
[KERNEL32]
Usually the command line is made of the application name and its parameters. When launching a DOS program, BaseCheckVDM builds suitable ApplicationName and CommandLine strings "DOS-compatible". ApplicationName is left-trimmed for whitespace and then converted to short-path format, and CommandLine sees the application name part (its first token) removed. We didn't do it before, we do it now. Care is taken when quotes are present in ApplicationName. Finally DOS command lines usually receive a newline character, so we also add it there. This is how behave Windows: just put our ntvdm in Windows, and observe what it receives...
Modified:
trunk/reactos/dll/win32/kernel32/client/vdm.c
Modified: trunk/reactos/dll/win32/kernel32/client/vdm.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/kernel32/client/…
==============================================================================
--- trunk/reactos/dll/win32/kernel32/client/vdm.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/kernel32/client/vdm.c [iso-8859-1] Sun May 18 22:10:45 2014
@@ -93,6 +93,122 @@
STARTUPINFOA AnsiStartupInfo;
ULONG NumStrings = 5;
+ /* Parameters validation */
+ if (ApplicationName == NULL || CommandLine == NULL)
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ DPRINT1("Before: ApplicationName = '%S' ; CommandLine = '%S'\n", ApplicationName, CommandLine);
+
+ /* Trim leading whitespace from ApplicationName */
+ while (*ApplicationName == L' ' || *ApplicationName == L'\t')
+ ++ApplicationName;
+
+ /* Calculate the size of the short application name */
+ Length = GetShortPathNameW(ApplicationName, NULL, 0);
+ if (Length == 0)
+ {
+ Status = STATUS_OBJECT_PATH_INVALID;
+ goto Cleanup;
+ }
+
+ /* Allocate memory for the short application name */
+ ShortAppName = (PWCHAR)RtlAllocateHeap(RtlGetProcessHeap(),
+ HEAP_ZERO_MEMORY,
+ Length * sizeof(WCHAR));
+ if (!ShortAppName)
+ {
+ Status = STATUS_NO_MEMORY;
+ goto Cleanup;
+ }
+
+ /* Get the short application name */
+ if (GetShortPathNameW(ApplicationName, ShortAppName, Length) == 0)
+ {
+ /* Try to determine which error occurred */
+ switch (GetLastError())
+ {
+ case ERROR_NOT_ENOUGH_MEMORY:
+ {
+ Status = STATUS_NO_MEMORY;
+ break;
+ }
+
+ case ERROR_INVALID_PARAMETER:
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ break;
+ }
+
+ default:
+ {
+ Status = STATUS_OBJECT_PATH_INVALID;
+ }
+ }
+
+ goto Cleanup;
+ }
+
+ /* Trim leading whitespace from CommandLine */
+ while (*CommandLine == L' ' || *CommandLine == L'\t')
+ ++CommandLine;
+
+ /*
+ * CommandLine is usually formatted as: 'ApplicationName param0 ...'.
+ * So we want to strip the first token (ApplicationName) from it.
+ * Two cases are in fact possible:
+ * - either the first token is indeed ApplicationName, so we just skip it;
+ * - or the first token is not exactly ApplicationName, because it happened
+ * that somebody else already preprocessed CommandLine. Therefore we
+ * suppose that the first token corresponds to an application name and
+ * we skip it. Care should be taken when quotes are present in this token.
+ */
+
+ if (*CommandLine)
+ {
+ /* The first part of CommandLine should be the ApplicationName... */
+ Length = wcslen(ApplicationName);
+ if (Length <= wcslen(CommandLine) &&
+ _wcsnicmp(ApplicationName, CommandLine, Length) == 0)
+ {
+ /* Skip it */
+ CommandLine += Length;
+ }
+ /*
+ * ... but it is not, however we still have a token. We suppose that
+ * it corresponds to some sort of application name, so we skip it too.
+ */
+ else
+ {
+ /* Get rid of the first token. We stop when we see whitespace. */
+ while (*CommandLine && !(*CommandLine == L' ' || *CommandLine == L'\t'))
+ {
+ if (*CommandLine == L'\"')
+ {
+ /* We enter a quoted part, skip it */
+ ++CommandLine;
+ while (*CommandLine && *CommandLine++ != L'\"') ;
+ }
+ else
+ {
+ /* Go to the next character */
+ ++CommandLine;
+ }
+ }
+ }
+ }
+
+ /*
+ * Trim remaining whitespace from CommandLine that may be
+ * present between the application name and the parameters.
+ */
+ while (*CommandLine == L' ' || *CommandLine == L'\t')
+ ++CommandLine;
+
+ DPRINT1("After: ApplicationName = '%S' ; CommandLine = '%S'\n", ApplicationName, CommandLine);
+
+ /* Get the current directory */
if (CurrentDirectory == NULL)
{
/* Allocate memory for the current directory path */
@@ -109,46 +225,6 @@
/* Get the current directory */
GetCurrentDirectoryW(Length, CurrentDir);
CurrentDirectory = CurrentDir;
- }
-
- /* Calculate the size of the short application name */
- Length = GetShortPathNameW(ApplicationName, NULL, 0);
-
- /* Allocate memory for the short application name */
- ShortAppName = (PWCHAR)RtlAllocateHeap(RtlGetProcessHeap(),
- HEAP_ZERO_MEMORY,
- Length * sizeof(WCHAR));
- if (!ShortAppName)
- {
- Status = STATUS_NO_MEMORY;
- goto Cleanup;
- }
-
- /* Get the short application name */
- if (!GetShortPathNameW(ApplicationName, ShortAppName, Length))
- {
- /* Try to determine which error occurred */
- switch (GetLastError())
- {
- case ERROR_NOT_ENOUGH_MEMORY:
- {
- Status = STATUS_NO_MEMORY;
- break;
- }
-
- case ERROR_INVALID_PARAMETER:
- {
- Status = STATUS_INVALID_PARAMETER;
- break;
- }
-
- default:
- {
- Status = STATUS_OBJECT_PATH_INVALID;
- }
- }
-
- goto Cleanup;
}
/* Calculate the size of the short current directory path */
@@ -214,7 +290,9 @@
}
/* Allocate memory for the ANSI strings */
- AnsiCmdLine = (PCHAR)RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, CheckVdm->CmdLen);
+
+ /* For the command line we need to add two characters needed for newline '\r\n' */
+ AnsiCmdLine = (PCHAR)RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, CheckVdm->CmdLen + 2);
AnsiAppName = (PCHAR)RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, CheckVdm->AppLen);
AnsiCurDirectory = (PCHAR)RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, CheckVdm->CurDirectoryLen);
if (StartupInfo->lpDesktop) AnsiDesktop = (PCHAR)RtlAllocateHeap(RtlGetProcessHeap(),
@@ -247,6 +325,11 @@
CheckVdm->CmdLen,
NULL,
NULL);
+ /* Add a needed newline '\r\n' */
+ CheckVdm->CmdLen--; // FIXME....
+ AnsiCmdLine[CheckVdm->CmdLen ] = '\r';
+ AnsiCmdLine[CheckVdm->CmdLen + 1] = '\n';
+ CheckVdm->CmdLen += 2;
/* Convert the short application name into an ANSI string */
WideCharToMultiByte(CP_ACP,
@@ -417,12 +500,12 @@
/* Free the capture buffer */
CsrFreeCaptureBuffer(CaptureBuffer);
- /* Free the short paths */
+ /* Free the current directory, if it was allocated here, and its short path */
+ if (ShortCurrentDir) RtlFreeHeap(RtlGetProcessHeap(), 0, ShortCurrentDir);
+ if (CurrentDir) RtlFreeHeap(RtlGetProcessHeap(), 0, CurrentDir);
+
+ /* Free the short app name */
if (ShortAppName) RtlFreeHeap(RtlGetProcessHeap(), 0, ShortAppName);
- if (ShortCurrentDir) RtlFreeHeap(RtlGetProcessHeap(), 0, ShortCurrentDir);
-
- /* Free the current directory, if it was allocated here */
- if (CurrentDir) RtlFreeHeap(RtlGetProcessHeap(), 0, CurrentDir);
return Status;
}
Author: tkreuzer
Date: Sun May 18 16:25:40 2014
New Revision: 63356
URL: http://svn.reactos.org/svn/reactos?rev=63356&view=rev
Log:
[NTOSKRNL]
- Fix a bug in MiQueryAddressState that prevented it from returning a valid protection
- Add support for PAE and x64 to MiQueryAddressState
- Acquire the working set lock in MiQueryMemoryBasicInformation before MiQueryAddressState
- Fix RegionSize calculation in MiQueryMemoryBasicInformation
- Handle ZeroBits and Process->VmTopDown in NtAllocateVirtualMemory
- Fix a bug in calculating the ending address of a virtual allocation
- Gracefully handle Vad allocation failure
- Free Vad allocation on failure
- Write values back to usermode only in case of success
Modified:
trunk/reactos/ntoskrnl/include/internal/amd64/mm.h
trunk/reactos/ntoskrnl/mm/ARM3/miarm.h
trunk/reactos/ntoskrnl/mm/ARM3/virtual.c
Modified: trunk/reactos/ntoskrnl/include/internal/amd64/mm.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/…
==============================================================================
--- trunk/reactos/ntoskrnl/include/internal/amd64/mm.h [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/include/internal/amd64/mm.h [iso-8859-1] Sun May 18 16:25:40 2014
@@ -78,6 +78,7 @@
#define MI_ZERO_PTES (32)
/* FIXME - different architectures have different cache line sizes... */
#define MM_CACHE_LINE_SIZE 32
+#define MI_MAX_ZERO_BITS 53
/* Helper macros */
#define PAGE_MASK(x) ((x)&(~0xfff))
@@ -143,11 +144,13 @@
//#define TEB_BASE 0x7FFDE000
-/* On x86, these two are the same */
+/* On x64, these are the same */
#define MMPDE MMPTE
#define PMMPDE PMMPTE
#define MMPPE MMPTE
#define PMMPPE PMMPTE
+#define MMPXE MMPTE
+#define PMMPXE PMMPTE
#define MI_WRITE_VALID_PPE MI_WRITE_VALID_PTE
#define ValidKernelPpe ValidKernelPde
Modified: trunk/reactos/ntoskrnl/mm/ARM3/miarm.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/miarm.h?r…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/ARM3/miarm.h [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/ARM3/miarm.h [iso-8859-1] Sun May 18 16:25:40 2014
@@ -52,6 +52,7 @@
#define MI_LOWEST_VAD_ADDRESS (PVOID)MM_LOWEST_USER_ADDRESS
#define MI_DEFAULT_SYSTEM_PTE_COUNT 50000
+#define MI_MAX_ZERO_BITS 21
#endif /* !_M_AMD64 */
Modified: trunk/reactos/ntoskrnl/mm/ARM3/virtual.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/virtual.c…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/ARM3/virtual.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/ARM3/virtual.c [iso-8859-1] Sun May 18 16:25:40 2014
@@ -57,7 +57,7 @@
if (Vad->u.VadFlags.MemCommit == 1)
{
/* This is a committed VAD, so Assume the whole range is committed */
- CommittedPages = BYTES_TO_PAGES(EndingAddress - StartingAddress);
+ CommittedPages = (ULONG)BYTES_TO_PAGES(EndingAddress - StartingAddress);
/* Is the PDE demand-zero? */
PointerPde = MiAddressToPte(PointerPte);
@@ -1309,6 +1309,12 @@
PMMPTE PointerPte, ProtoPte;
PMMPDE PointerPde;
+#if (_MI_PAGING_LEVELS >= 3)
+ PMMPPE PointerPpe;
+#endif
+#if (_MI_PAGING_LEVELS >= 4)
+ PMMPXE PointerPxe;
+#endif
MMPTE TempPte, TempProtoPte;
BOOLEAN DemandZeroPte = TRUE, ValidPte = FALSE;
ULONG State = MEM_RESERVE, Protect = 0;
@@ -1321,27 +1327,70 @@
/* Get the PDE and PTE for the address */
PointerPde = MiAddressToPde(Va);
PointerPte = MiAddressToPte(Va);
+#if (_MI_PAGING_LEVELS >= 3)
+ PointerPpe = MiAddressToPpe(Va);
+#endif
+#if (_MI_PAGING_LEVELS >= 4)
+ PointerPxe = MiAddressToPxe(Va);
+#endif
/* Return the next range */
*NextVa = (PVOID)((ULONG_PTR)Va + PAGE_SIZE);
- /* Is the PDE demand-zero? */
- if (PointerPde->u.Long != 0)
- {
- /* It is not. Is it valid? */
+ do
+ {
+#if (_MI_PAGING_LEVELS >= 4)
+ /* Does the PXE exist? */
+ if (PointerPxe->u.Long == 0)
+ {
+ /* It does not, next range starts at the next PXE */
+ *NextVa = MiPxeToAddress(PointerPxe + 1);
+ break;
+ }
+
+ /* Is the PXE valid? */
+ if (PointerPxe->u.Hard.Valid == 0)
+ {
+ /* Is isn't, fault it in (make the PPE accessible) */
+ MiMakeSystemAddressValid(PointerPpe, TargetProcess);
+ }
+#endif
+#if (_MI_PAGING_LEVELS >= 3)
+ /* Does the PPE exist? */
+ if (PointerPpe->u.Long == 0)
+ {
+ /* It does not, next range starts at the next PPE */
+ *NextVa = MiPpeToAddress(PointerPpe + 1);
+ break;
+ }
+
+ /* Is the PPE valid? */
+ if (PointerPpe->u.Hard.Valid == 0)
+ {
+ /* Is isn't, fault it in (make the PDE accessible) */
+ MiMakeSystemAddressValid(PointerPde, TargetProcess);
+ }
+#endif
+
+ /* Does the PDE exist? */
+ if (PointerPde->u.Long == 0)
+ {
+ /* It does not, next range starts at the next PDE */
+ *NextVa = MiPdeToAddress(PointerPde + 1);
+ break;
+ }
+
+ /* Is the PDE valid? */
if (PointerPde->u.Hard.Valid == 0)
{
- /* Is isn't, fault it in */
- PointerPte = MiPteToAddress(PointerPde);
+ /* Is isn't, fault it in (make the PTE accessible) */
MiMakeSystemAddressValid(PointerPte, TargetProcess);
- ValidPte = TRUE;
- }
- }
- else
- {
- /* It is, skip it and move to the next PDE */
- *NextVa = MiPdeToAddress(PointerPde + 1);
- }
+ }
+
+ /* We have a PTE that we can access now! */
+ ValidPte = TRUE;
+
+ } while (FALSE);
/* Is it safe to try reading the PTE? */
if (ValidPte)
@@ -1708,6 +1757,9 @@
MemoryInfo.AllocationProtect = MmProtectToValue[Vad->u.VadFlags.Protection];
MemoryInfo.Type = MEM_PRIVATE;
+ /* Acquire the working set lock (shared is enough) */
+ MiLockProcessWorkingSetShared(TargetProcess, PsGetCurrentThread());
+
/* Find the largest chunk of memory which has the same state and protection mask */
MemoryInfo.State = MiQueryAddressState(Address,
Vad,
@@ -1722,6 +1774,16 @@
if ((NewState != MemoryInfo.State) || (NewProtect != MemoryInfo.Protect)) break;
Address = NextAddress;
}
+
+ /* Release the working set lock */
+ MiUnlockProcessWorkingSetShared(TargetProcess, PsGetCurrentThread());
+
+ /* Check if we went outside of the VAD */
+ if (((ULONG_PTR)Address >> PAGE_SHIFT) > Vad->EndingVpn)
+ {
+ /* Set the end of the VAD as the end address */
+ Address = (PVOID)((Vad->EndingVpn + 1) << PAGE_SHIFT);
+ }
/* Now that we know the last VA address, calculate the region size */
MemoryInfo.RegionSize = ((ULONG_PTR)Address - (ULONG_PTR)MemoryInfo.BaseAddress);
@@ -4088,11 +4150,11 @@
PEPROCESS Process;
PMEMORY_AREA MemoryArea;
PFN_NUMBER PageCount;
- PMMVAD Vad, FoundVad;
+ PMMVAD Vad = NULL, FoundVad;
NTSTATUS Status;
PMMSUPPORT AddressSpace;
PVOID PBaseAddress;
- ULONG_PTR PRegionSize, StartingAddress, EndingAddress;
+ ULONG_PTR PRegionSize, StartingAddress, EndingAddress, HighestAddress;
PEPROCESS CurrentProcess = PsGetCurrentProcess();
KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
PETHREAD CurrentThread = PsGetCurrentThread();
@@ -4106,7 +4168,7 @@
PAGED_CODE();
/* Check for valid Zero bits */
- if (ZeroBits > 21)
+ if (ZeroBits > MI_MAX_ZERO_BITS)
{
DPRINT1("Too many zero bits\n");
return STATUS_INVALID_PARAMETER_3;
@@ -4114,7 +4176,7 @@
/* Check for valid Allocation Types */
if ((AllocationType & ~(MEM_COMMIT | MEM_RESERVE | MEM_RESET | MEM_PHYSICAL |
- MEM_TOP_DOWN | MEM_WRITE_WATCH)))
+ MEM_TOP_DOWN | MEM_WRITE_WATCH | MEM_LARGE_PAGES)))
{
DPRINT1("Invalid Allocation Type\n");
return STATUS_INVALID_PARAMETER_5;
@@ -4159,16 +4221,16 @@
return STATUS_INVALID_PARAMETER_5;
}
- /* MEM_PHYSICAL can only be used if MEM_RESERVE is also used */
- if ((AllocationType & MEM_PHYSICAL) && !(AllocationType & MEM_RESERVE))
- {
- DPRINT1("MEM_WRITE_WATCH used without MEM_RESERVE\n");
- return STATUS_INVALID_PARAMETER_5;
- }
-
/* Check for valid MEM_PHYSICAL usage */
if (AllocationType & MEM_PHYSICAL)
{
+ /* MEM_PHYSICAL can only be used if MEM_RESERVE is also used */
+ if (!(AllocationType & MEM_RESERVE))
+ {
+ DPRINT1("MEM_PHYSICAL used without MEM_RESERVE\n");
+ return STATUS_INVALID_PARAMETER_5;
+ }
+
/* Only these flags are allowed with MEM_PHYSIAL */
if (AllocationType & ~(MEM_RESERVE | MEM_TOP_DOWN | MEM_PHYSICAL))
{
@@ -4200,7 +4262,7 @@
{
/* Make sure they are writable */
ProbeForWritePointer(UBaseAddress);
- ProbeForWriteUlong(URegionSize);
+ ProbeForWriteSize_t(URegionSize);
}
/* Capture their values */
@@ -4215,7 +4277,7 @@
_SEH2_END;
/* Make sure the allocation isn't past the VAD area */
- if (PBaseAddress >= MM_HIGHEST_VAD_ADDRESS)
+ if (PBaseAddress > MM_HIGHEST_VAD_ADDRESS)
{
DPRINT1("Virtual allocation base above User Space\n");
return STATUS_INVALID_PARAMETER_2;
@@ -4280,12 +4342,6 @@
//
// Fail on the things we don't yet support
//
- if (ZeroBits != 0)
- {
- DPRINT1("Zero bits not supported\n");
- Status = STATUS_INVALID_PARAMETER;
- goto FailPathNoLock;
- }
if ((AllocationType & MEM_LARGE_PAGES) == MEM_LARGE_PAGES)
{
DPRINT1("MEM_LARGE_PAGES not supported\n");
@@ -4304,18 +4360,6 @@
Status = STATUS_INVALID_PARAMETER;
goto FailPathNoLock;
}
- if ((AllocationType & MEM_TOP_DOWN) == MEM_TOP_DOWN)
- {
- DPRINT1("MEM_TOP_DOWN not supported\n");
- AllocationType &= ~MEM_TOP_DOWN;
- }
-
- if (Process->VmTopDown == 1)
- {
- DPRINT1("VmTopDown not supported\n");
- Status = STATUS_INVALID_PARAMETER;
- goto FailPathNoLock;
- }
//
// Check if the caller is reserving memory, or committing memory and letting
@@ -4326,7 +4370,7 @@
//
// Do not allow COPY_ON_WRITE through this API
//
- if ((Protect & PAGE_WRITECOPY) || (Protect & PAGE_EXECUTE_WRITECOPY))
+ if (Protect & (PAGE_WRITECOPY | PAGE_EXECUTE_WRITECOPY))
{
DPRINT1("Copy on write not allowed through this path\n");
Status = STATUS_INVALID_PAGE_PROTECTION;
@@ -4345,6 +4389,29 @@
PageCount = BYTES_TO_PAGES(PRegionSize);
EndingAddress = 0;
StartingAddress = 0;
+
+ //
+ // Check if ZeroBits were specified
+ //
+ if (ZeroBits != 0)
+ {
+ //
+ // Calculate the highest address and check if it's valid
+ //
+ HighestAddress = MAXULONG_PTR >> ZeroBits;
+ if (HighestAddress > (ULONG_PTR)MM_HIGHEST_VAD_ADDRESS)
+ {
+ Status = STATUS_INVALID_PARAMETER_3;
+ goto FailPathNoLock;
+ }
+ }
+ else
+ {
+ //
+ // Use the highest VAD address as maximum
+ //
+ HighestAddress = (ULONG_PTR)MM_HIGHEST_VAD_ADDRESS;
+ }
}
else
{
@@ -4353,8 +4420,8 @@
// expected 64KB granularity, and see where the ending address will
// fall based on the aligned address and the passed in region size
//
+ EndingAddress = ((ULONG_PTR)PBaseAddress + PRegionSize - 1) | (PAGE_SIZE - 1);
StartingAddress = ROUND_DOWN((ULONG_PTR)PBaseAddress, _64K);
- EndingAddress = ((ULONG_PTR)PBaseAddress + PRegionSize - 1) | (PAGE_SIZE - 1);
PageCount = BYTES_TO_PAGES(EndingAddress - StartingAddress);
}
@@ -4362,7 +4429,13 @@
// Allocate and initialize the VAD
//
Vad = ExAllocatePoolWithTag(NonPagedPool, sizeof(MMVAD_LONG), 'SdaV');
- ASSERT(Vad != NULL);
+ if (Vad == NULL)
+ {
+ DPRINT1("Failed to allocate a VAD!\n");
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ goto FailPathNoLock;
+ }
+
Vad->u.LongFlags = 0;
if (AllocationType & MEM_COMMIT) Vad->u.VadFlags.MemCommit = 1;
Vad->u.VadFlags.Protection = ProtectionMask;
@@ -4389,11 +4462,11 @@
if (!PBaseAddress)
{
/* Which way should we search? */
- if (AllocationType & MEM_TOP_DOWN)
+ if ((AllocationType & MEM_TOP_DOWN) || Process->VmTopDown)
{
/* Find an address top-down */
Result = MiFindEmptyAddressRangeDownTree(PRegionSize,
- (ULONG_PTR)MM_HIGHEST_VAD_ADDRESS,
+ HighestAddress,
_64K,
&Process->VadRoot,
&StartingAddress,
@@ -4419,9 +4492,11 @@
// Now we know where the allocation ends. Make sure it doesn't end up
// somewhere in kernel mode.
//
- NT_ASSERT(StartingAddress != 0);
+ ASSERT(StartingAddress != 0);
+ ASSERT(StartingAddress < (ULONG_PTR)MM_HIGHEST_USER_ADDRESS);
EndingAddress = (StartingAddress + PRegionSize - 1) | (PAGE_SIZE - 1);
- if ((PVOID)EndingAddress > MM_HIGHEST_VAD_ADDRESS)
+ ASSERT(EndingAddress > StartingAddress);
+ if (EndingAddress > HighestAddress)
{
Status = STATUS_NO_MEMORY;
goto FailPath;
@@ -4447,8 +4522,8 @@
//
// Write out the VAD fields for this allocation
//
- Vad->StartingVpn = (ULONG_PTR)StartingAddress >> PAGE_SHIFT;
- Vad->EndingVpn = (ULONG_PTR)EndingAddress >> PAGE_SHIFT;
+ Vad->StartingVpn = StartingAddress >> PAGE_SHIFT;
+ Vad->EndingVpn = EndingAddress >> PAGE_SHIFT;
//
// FIXME: Should setup VAD bitmap
@@ -4465,6 +4540,13 @@
MiUnlockProcessWorkingSetUnsafe(Process, CurrentThread);
//
+ // Make sure the actual region size is at least as big as the
+ // requested region size and update the value
+ //
+ ASSERT(PRegionSize <= (EndingAddress + 1 - StartingAddress));
+ PRegionSize = (EndingAddress + 1 - StartingAddress);
+
+ //
// Update the virtual size of the process, and if this is now the highest
// virtual size we have ever seen, update the peak virtual size to reflect
// this.
@@ -4497,6 +4579,9 @@
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
+ //
+ // Ignore exception!
+ //
}
_SEH2_END;
return STATUS_SUCCESS;
@@ -4814,6 +4899,14 @@
FailPath:
MmUnlockAddressSpace(AddressSpace);
+ if (!NT_SUCCESS(Status))
+ {
+ if (Vad != NULL)
+ {
+ ExFreePoolWithTag(Vad, 'SdaV');
+ }
+ }
+
//
// Check if we need to update the protection
//
@@ -4838,21 +4931,28 @@
if (ProcessHandle != NtCurrentProcess()) ObDereferenceObject(Process);
//
- // Use SEH to write back the base address and the region size. In the case
- // of an exception, we strangely do return back the exception code, even
- // though the memory *has* been allocated. This mimics Windows behavior and
- // there is not much we can do about it.
- //
- _SEH2_TRY
- {
- *URegionSize = PRegionSize;
- *UBaseAddress = (PVOID)StartingAddress;
- }
- _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
- {
- Status = _SEH2_GetExceptionCode();
- }
- _SEH2_END;
+ // Only write back results on success
+ //
+ if (NT_SUCCESS(Status))
+ {
+ //
+ // Use SEH to write back the base address and the region size. In the case
+ // of an exception, we strangely do return back the exception code, even
+ // though the memory *has* been allocated. This mimics Windows behavior and
+ // there is not much we can do about it.
+ //
+ _SEH2_TRY
+ {
+ *URegionSize = PRegionSize;
+ *UBaseAddress = (PVOID)StartingAddress;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
+ }
+
return Status;
}
Author: tkreuzer
Date: Sun May 18 14:59:31 2014
New Revision: 63354
URL: http://svn.reactos.org/svn/reactos?rev=63354&view=rev
Log:
[NTOSKRNL]
- Do not ASSERT that a page fault im MmArmAccessFault happens on an invalid page. Instead handle write-on-readonly-PTE faults (Copy-on-write still unhandled). This ASSERT was not triggered so far, since ARM3 mapped all pages as read/write regardless of protection! So all (page file backed) sections mapped into user space were writable and could be happily modified from user mode!
- Fix MI_MAKE_HARDWARE_PTE_USER, so that it respects the actual protection.
Modified:
trunk/reactos/ntoskrnl/mm/ARM3/miarm.h
trunk/reactos/ntoskrnl/mm/ARM3/pagfault.c
Modified: trunk/reactos/ntoskrnl/mm/ARM3/miarm.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/miarm.h?r…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/ARM3/miarm.h [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/ARM3/miarm.h [iso-8859-1] Sun May 18 14:59:31 2014
@@ -887,9 +887,10 @@
ASSERT(MappingPte <= MiHighestUserPte);
/* Start fresh */
- *NewPte = ValidKernelPte;
+ NewPte->u.Long = 0;
/* Set the protection and page */
+ NewPte->u.Hard.Valid = TRUE;
NewPte->u.Hard.Owner = TRUE;
NewPte->u.Hard.PageFrameNumber = PageFrameNumber;
NewPte->u.Long |= MmProtectToPteMask[ProtectionMask];
Modified: trunk/reactos/ntoskrnl/mm/ARM3/pagfault.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/pagfault.…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/ARM3/pagfault.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/ARM3/pagfault.c [iso-8859-1] Sun May 18 14:59:31 2014
@@ -1835,9 +1835,37 @@
ASSERT(MI_IS_PAGE_LARGE(PointerPde) == FALSE);
}
- /* Now capture the PTE. Ignore virtual faults for now */
+ /* Now capture the PTE. */
TempPte = *PointerPte;
- ASSERT(TempPte.u.Hard.Valid == 0);
+
+ /* Check if the PTE is valid */
+ if (TempPte.u.Hard.Valid)
+ {
+ /* Check if this is a write on a readonly PTE */
+ if (StoreInstruction)
+ {
+ /* Is this a copy on write PTE? */
+ if (TempPte.u.Hard.CopyOnWrite)
+ {
+ /* Not supported yet */
+ ASSERT(FALSE);
+ }
+
+ /* Is this a read-only PTE? */
+ if (!TempPte.u.Hard.Write)
+ {
+ /* Return the status */
+ MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
+ return STATUS_ACCESS_VIOLATION;
+ }
+ }
+
+ /* FIXME: Execution is ignored for now, since we don't have no-execute pages yet */
+
+ /* The fault has already been resolved by a different thread */
+ MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
+ return STATUS_SUCCESS;
+ }
/* Quick check for demand-zero */
if (TempPte.u.Long == (MM_READWRITE << MM_PTE_SOFTWARE_PROTECTION_BITS))