- Change the protection in WriteProcessMemory if it is necessary.
authorHartmut Birr <osexpert@googlemail.com>
Mon, 24 Oct 2005 17:23:42 +0000 (17:23 +0000)
committerHartmut Birr <osexpert@googlemail.com>
Mon, 24 Oct 2005 17:23:42 +0000 (17:23 +0000)
svn path=/trunk/; revision=18744

reactos/lib/kernel32/mem/procmem.c

index 925370c..40fc3b5 100644 (file)
@@ -58,17 +58,99 @@ WriteProcessMemory (
        SIZE_T *lpNumberOfBytesWritten
        )
 {
        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;
                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;
 }
 
        return TRUE;
 }