[HAL]
[reactos.git] / reactos / dll / win32 / kernel32 / mem / procmem.c
1 /*
2 * PROJECT: ReactOS Win32 Base API
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: dll/win32/kernel32/mem/procmem.c
5 * PURPOSE: Handles virtual memory APIs
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
7 */
8
9 /* INCLUDES ******************************************************************/
10
11 #include <k32.h>
12
13 #define NDEBUG
14 #include <debug.h>
15
16 /* FUNCTIONS *****************************************************************/
17
18 /*
19 * @implemented
20 */
21 BOOL
22 NTAPI
23 ReadProcessMemory(IN HANDLE hProcess,
24 IN LPCVOID lpBaseAddress,
25 IN LPVOID lpBuffer,
26 IN DWORD nSize,
27 OUT LPDWORD lpNumberOfBytesRead)
28 {
29 NTSTATUS Status;
30
31 /* Do the read */
32 Status = NtReadVirtualMemory(hProcess,
33 (PVOID)lpBaseAddress,
34 lpBuffer,
35 nSize,
36 lpNumberOfBytesRead);
37 if (!NT_SUCCESS(Status))
38 {
39 /* We failed */
40 SetLastErrorByStatus (Status);
41 return FALSE;
42 }
43
44 /* Return success */
45 return TRUE;
46 }
47
48 /*
49 * @implemented
50 */
51 BOOL
52 NTAPI
53 WriteProcessMemory(IN HANDLE hProcess,
54 IN LPVOID lpBaseAddress,
55 IN LPCVOID lpBuffer,
56 IN SIZE_T nSize,
57 OUT SIZE_T *lpNumberOfBytesWritten)
58 {
59 NTSTATUS Status;
60 ULONG OldValue;
61 SIZE_T RegionSize;
62 PVOID Base;
63 BOOLEAN UnProtect;
64
65 /* Set parameters for protect call */
66 RegionSize = nSize;
67 Base = lpBaseAddress;
68
69 /* Check the current status */
70 Status = NtProtectVirtualMemory(hProcess,
71 &Base,
72 &RegionSize,
73 PAGE_EXECUTE_READWRITE,
74 &OldValue);
75 if (NT_SUCCESS(Status))
76 {
77 /* Check if we are unprotecting */
78 UnProtect = OldValue & (PAGE_READWRITE |
79 PAGE_WRITECOPY |
80 PAGE_EXECUTE_READWRITE |
81 PAGE_EXECUTE_WRITECOPY) ? FALSE : TRUE;
82 if (!UnProtect)
83 {
84 /* Set the new protection */
85 Status = NtProtectVirtualMemory(hProcess,
86 &Base,
87 &RegionSize,
88 OldValue,
89 &OldValue);
90
91 /* Write the memory */
92 Status = NtWriteVirtualMemory(hProcess,
93 lpBaseAddress,
94 (LPVOID)lpBuffer,
95 nSize,
96 lpNumberOfBytesWritten);
97 if (!NT_SUCCESS(Status))
98 {
99 /* We failed */
100 SetLastErrorByStatus(Status);
101 return FALSE;
102 }
103
104 /* Flush the ITLB */
105 NtFlushInstructionCache(hProcess, lpBaseAddress, nSize);
106 return TRUE;
107 }
108 else
109 {
110 /* Check if we were read only */
111 if ((OldValue & PAGE_NOACCESS) || (OldValue & PAGE_READONLY))
112 {
113 /* Restore protection and fail */
114 NtProtectVirtualMemory(hProcess,
115 &Base,
116 &RegionSize,
117 OldValue,
118 &OldValue);
119 SetLastErrorByStatus(STATUS_ACCESS_VIOLATION);
120 return FALSE;
121 }
122
123 /* Otherwise, do the write */
124 Status = NtWriteVirtualMemory(hProcess,
125 lpBaseAddress,
126 (LPVOID)lpBuffer,
127 nSize,
128 lpNumberOfBytesWritten);
129
130 /* And restore the protection */
131 NtProtectVirtualMemory(hProcess,
132 &Base,
133 &RegionSize,
134 OldValue,
135 &OldValue);
136 if (!NT_SUCCESS(Status))
137 {
138 /* We failed */
139 SetLastErrorByStatus(STATUS_ACCESS_VIOLATION);
140 return FALSE;
141 }
142
143 /* Flush the ITLB */
144 NtFlushInstructionCache(hProcess, lpBaseAddress, nSize);
145 return TRUE;
146 }
147 }
148 else
149 {
150 /* We failed */
151 SetLastErrorByStatus(Status);
152 return FALSE;
153 }
154 }
155
156 /* EOF */