- Change the protection in WriteProcessMemory if it is necessary.
Modified: trunk/reactos/lib/kernel32/mem/procmem.c

Modified: trunk/reactos/lib/kernel32/mem/procmem.c
--- trunk/reactos/lib/kernel32/mem/procmem.c	2005-10-24 17:21:23 UTC (rev 18743)
+++ trunk/reactos/lib/kernel32/mem/procmem.c	2005-10-24 17:23:42 UTC (rev 18744)
@@ -58,17 +58,99 @@
 	SIZE_T *lpNumberOfBytesWritten
 	)
 {
-	NTSTATUS Status;
+	NTSTATUS Status, ProtectStatus;
+	MEMORY_BASIC_INFORMATION MemInfo;
+	ULONG Length;
+	BOOLEAN UnProtect;
 
-	Status = NtWriteVirtualMemory( hProcess, lpBaseAddress, (LPVOID)lpBuffer, nSize,
-		(PULONG)lpNumberOfBytesWritten
-		);
+	if (lpNumberOfBytesWritten)
+	{
+	    *lpNumberOfBytesWritten = 0;
+	}
 
-	if (!NT_SUCCESS(Status))
-     	{
+	while (nSize)
+	{
+	    Status = NtQueryVirtualMemory(hProcess, 
+					  lpBaseAddress,
+					  MemoryBasicInformation,
+					  &MemInfo,
+					  sizeof(MEMORY_BASIC_INFORMATION),
+					  NULL);
+
+	    if (!NT_SUCCESS(Status))
+	    {
+		SetLastErrorByStatus(Status);
+		return FALSE;
+	    }
+	    Length = MemInfo.RegionSize - ((ULONG_PTR)lpBaseAddress - (ULONG_PTR)MemInfo.BaseAddress);
+	    if (Length > nSize)
+	    {
+		Length = nSize;
+	    }
+	    UnProtect = MemInfo.Protect & (PAGE_READWRITE|PAGE_WRITECOPY|PAGE_EXECUTE_READWRITE|PAGE_EXECUTE_WRITECOPY) ? FALSE : TRUE;
+	    if (UnProtect)
+	    {
+		MemInfo.BaseAddress = lpBaseAddress;
+		MemInfo.RegionSize = Length;
+		if (MemInfo.Protect & (PAGE_EXECUTE|PAGE_EXECUTE_READ))
+		{
+		    MemInfo.Protect &= ~(PAGE_EXECUTE|PAGE_EXECUTE_READ);
+		    MemInfo.Protect |= PAGE_EXECUTE_READWRITE;
+		}
+		else 
+		{
+		    MemInfo.Protect &= ~(PAGE_READONLY|PAGE_NOACCESS);
+		    MemInfo.Protect |= PAGE_READWRITE;
+		}
+
+		ProtectStatus = NtProtectVirtualMemory(hProcess, 
+		                                       &MemInfo.BaseAddress, 
+						       &MemInfo.RegionSize,
+						       MemInfo.Protect,
+						       &MemInfo.Protect);
+		if (!NT_SUCCESS(ProtectStatus))
+		{
+		    SetLastErrorByStatus(ProtectStatus);
+		    return FALSE;
+		}
+		Length = MemInfo.RegionSize - ((ULONG_PTR)lpBaseAddress - (ULONG_PTR)MemInfo.BaseAddress);
+		if (Length > nSize)
+		{
+		    Length = nSize;
+		}
+	    }
+					    
+	    Status = NtWriteVirtualMemory(hProcess, 
+	                                  lpBaseAddress, 
+					  (LPVOID)lpBuffer, 
+					  Length,
+					  &Length);
+	    if (UnProtect)
+	    {
+		ProtectStatus = NtProtectVirtualMemory(hProcess, 
+		                                       &MemInfo.BaseAddress, 
+					               &MemInfo.RegionSize,
+					               MemInfo.Protect,
+					               &MemInfo.Protect);
+	    }
+	    if (!NT_SUCCESS(Status))
+     	    {
 		SetLastErrorByStatus (Status);
 		return FALSE;
-     	}
+     	    }
+	    if (UnProtect && !NT_SUCCESS(ProtectStatus))
+	    {
+		SetLastErrorByStatus (ProtectStatus);
+		return FALSE;
+	    }
+	    lpBaseAddress = (LPVOID)((ULONG_PTR)lpBaseAddress + Length);
+	    lpBuffer = (LPCVOID)((ULONG_PTR)lpBuffer + Length);
+	    nSize -= Length;
+	    if (lpNumberOfBytesWritten)
+	    {
+		*lpNumberOfBytesWritten += Length;
+	    }
+	}
 	return TRUE;
 }