1c2c66affSColin Finck /*
2c2c66affSColin Finck * PROJECT: ReactOS Win32 Base API
3c2c66affSColin Finck * LICENSE: GPL - See COPYING in the top level directory
4c2c66affSColin Finck * FILE: dll/win32/kernel32/client/virtmem.c
5c2c66affSColin Finck * PURPOSE: Handles virtual memory APIs
6c2c66affSColin Finck * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
7c2c66affSColin Finck */
8c2c66affSColin Finck
9c2c66affSColin Finck /* INCLUDES *******************************************************************/
10c2c66affSColin Finck
11c2c66affSColin Finck #include <k32.h>
12c2c66affSColin Finck
13c2c66affSColin Finck #define NDEBUG
14c2c66affSColin Finck #include <debug.h>
15c2c66affSColin Finck
16c2c66affSColin Finck /* FUNCTIONS ******************************************************************/
17c2c66affSColin Finck
18c2c66affSColin Finck /*
19c2c66affSColin Finck * @implemented
20c2c66affSColin Finck */
21c2c66affSColin Finck LPVOID
22c2c66affSColin Finck NTAPI
VirtualAllocEx(IN HANDLE hProcess,IN LPVOID lpAddress,IN SIZE_T dwSize,IN DWORD flAllocationType,IN DWORD flProtect)23c2c66affSColin Finck VirtualAllocEx(IN HANDLE hProcess,
24c2c66affSColin Finck IN LPVOID lpAddress,
25c2c66affSColin Finck IN SIZE_T dwSize,
26c2c66affSColin Finck IN DWORD flAllocationType,
27c2c66affSColin Finck IN DWORD flProtect)
28c2c66affSColin Finck {
29c2c66affSColin Finck NTSTATUS Status;
30c2c66affSColin Finck
31c2c66affSColin Finck /* Make sure the address is within the granularity of the system (64K) */
32*4f0a158aSTimo Kreuzer if ((lpAddress != NULL) &&
33*4f0a158aSTimo Kreuzer (lpAddress < UlongToPtr(BaseStaticServerData->SysInfo.AllocationGranularity)))
34c2c66affSColin Finck {
35c2c66affSColin Finck /* Fail the call */
36c2c66affSColin Finck SetLastError(ERROR_INVALID_PARAMETER);
37c2c66affSColin Finck return NULL;
38c2c66affSColin Finck }
39c2c66affSColin Finck
40c2c66affSColin Finck /* Allocate the memory */
41c2c66affSColin Finck Status = NtAllocateVirtualMemory(hProcess,
42c2c66affSColin Finck &lpAddress,
43c2c66affSColin Finck 0,
44c2c66affSColin Finck &dwSize,
45c2c66affSColin Finck flAllocationType,
46c2c66affSColin Finck flProtect);
47c2c66affSColin Finck
48c2c66affSColin Finck /* Check for status */
49c2c66affSColin Finck if (!NT_SUCCESS(Status))
50c2c66affSColin Finck {
51c2c66affSColin Finck /* We failed */
52c2c66affSColin Finck BaseSetLastNTError(Status);
53c2c66affSColin Finck return NULL;
54c2c66affSColin Finck }
55c2c66affSColin Finck
56c2c66affSColin Finck /* Return the allocated address */
57c2c66affSColin Finck return lpAddress;
58c2c66affSColin Finck }
59c2c66affSColin Finck
60c2c66affSColin Finck /*
61c2c66affSColin Finck * @implemented
62c2c66affSColin Finck */
63c2c66affSColin Finck LPVOID
64c2c66affSColin Finck NTAPI
VirtualAlloc(IN LPVOID lpAddress,IN SIZE_T dwSize,IN DWORD flAllocationType,IN DWORD flProtect)65c2c66affSColin Finck VirtualAlloc(IN LPVOID lpAddress,
66c2c66affSColin Finck IN SIZE_T dwSize,
67c2c66affSColin Finck IN DWORD flAllocationType,
68c2c66affSColin Finck IN DWORD flProtect)
69c2c66affSColin Finck {
70c2c66affSColin Finck /* Call the extended API */
71c2c66affSColin Finck return VirtualAllocEx(GetCurrentProcess(),
72c2c66affSColin Finck lpAddress,
73c2c66affSColin Finck dwSize,
74c2c66affSColin Finck flAllocationType,
75c2c66affSColin Finck flProtect);
76c2c66affSColin Finck }
77c2c66affSColin Finck
78c2c66affSColin Finck /*
79c2c66affSColin Finck * @implemented
80c2c66affSColin Finck */
81c2c66affSColin Finck BOOL
82c2c66affSColin Finck NTAPI
VirtualFreeEx(IN HANDLE hProcess,IN LPVOID lpAddress,IN SIZE_T dwSize,IN DWORD dwFreeType)83c2c66affSColin Finck VirtualFreeEx(IN HANDLE hProcess,
84c2c66affSColin Finck IN LPVOID lpAddress,
85c2c66affSColin Finck IN SIZE_T dwSize,
86c2c66affSColin Finck IN DWORD dwFreeType)
87c2c66affSColin Finck {
88c2c66affSColin Finck NTSTATUS Status;
89c2c66affSColin Finck
90c2c66affSColin Finck /* Validate size and flags */
91c2c66affSColin Finck if (!(dwSize) || !(dwFreeType & MEM_RELEASE))
92c2c66affSColin Finck {
93c2c66affSColin Finck /* Free the memory */
94c2c66affSColin Finck Status = NtFreeVirtualMemory(hProcess,
95c2c66affSColin Finck &lpAddress,
96c2c66affSColin Finck &dwSize,
97c2c66affSColin Finck dwFreeType);
98c2c66affSColin Finck if (!NT_SUCCESS(Status))
99c2c66affSColin Finck {
100c2c66affSColin Finck /* We failed */
101c2c66affSColin Finck BaseSetLastNTError(Status);
102c2c66affSColin Finck return FALSE;
103c2c66affSColin Finck }
104c2c66affSColin Finck
105c2c66affSColin Finck /* Return success */
106c2c66affSColin Finck return TRUE;
107c2c66affSColin Finck }
108c2c66affSColin Finck
109c2c66affSColin Finck /* Invalid combo */
110c2c66affSColin Finck BaseSetLastNTError(STATUS_INVALID_PARAMETER);
111c2c66affSColin Finck return FALSE;
112c2c66affSColin Finck }
113c2c66affSColin Finck
114c2c66affSColin Finck /*
115c2c66affSColin Finck * @implemented
116c2c66affSColin Finck */
117c2c66affSColin Finck BOOL
118c2c66affSColin Finck NTAPI
VirtualFree(IN LPVOID lpAddress,IN SIZE_T dwSize,IN DWORD dwFreeType)119c2c66affSColin Finck VirtualFree(IN LPVOID lpAddress,
120c2c66affSColin Finck IN SIZE_T dwSize,
121c2c66affSColin Finck IN DWORD dwFreeType)
122c2c66affSColin Finck {
123c2c66affSColin Finck /* Call the extended API */
124c2c66affSColin Finck return VirtualFreeEx(GetCurrentProcess(),
125c2c66affSColin Finck lpAddress,
126c2c66affSColin Finck dwSize,
127c2c66affSColin Finck dwFreeType);
128c2c66affSColin Finck }
129c2c66affSColin Finck
130c2c66affSColin Finck /*
131c2c66affSColin Finck * @implemented
132c2c66affSColin Finck */
133c2c66affSColin Finck BOOL
134c2c66affSColin Finck NTAPI
VirtualProtect(IN LPVOID lpAddress,IN SIZE_T dwSize,IN DWORD flNewProtect,OUT PDWORD lpflOldProtect)135c2c66affSColin Finck VirtualProtect(IN LPVOID lpAddress,
136c2c66affSColin Finck IN SIZE_T dwSize,
137c2c66affSColin Finck IN DWORD flNewProtect,
138c2c66affSColin Finck OUT PDWORD lpflOldProtect)
139c2c66affSColin Finck {
140c2c66affSColin Finck /* Call the extended API */
141c2c66affSColin Finck return VirtualProtectEx(GetCurrentProcess(),
142c2c66affSColin Finck lpAddress,
143c2c66affSColin Finck dwSize,
144c2c66affSColin Finck flNewProtect,
145c2c66affSColin Finck lpflOldProtect);
146c2c66affSColin Finck }
147c2c66affSColin Finck
148c2c66affSColin Finck /*
149c2c66affSColin Finck * @implemented
150c2c66affSColin Finck */
151c2c66affSColin Finck BOOL
152c2c66affSColin Finck NTAPI
VirtualProtectEx(IN HANDLE hProcess,IN LPVOID lpAddress,IN SIZE_T dwSize,IN DWORD flNewProtect,OUT PDWORD lpflOldProtect)153c2c66affSColin Finck VirtualProtectEx(IN HANDLE hProcess,
154c2c66affSColin Finck IN LPVOID lpAddress,
155c2c66affSColin Finck IN SIZE_T dwSize,
156c2c66affSColin Finck IN DWORD flNewProtect,
157c2c66affSColin Finck OUT PDWORD lpflOldProtect)
158c2c66affSColin Finck {
159c2c66affSColin Finck NTSTATUS Status;
160c2c66affSColin Finck
161c2c66affSColin Finck /* Change the protection */
162c2c66affSColin Finck Status = NtProtectVirtualMemory(hProcess,
163c2c66affSColin Finck &lpAddress,
164c2c66affSColin Finck &dwSize,
165c2c66affSColin Finck flNewProtect,
166c2c66affSColin Finck (PULONG)lpflOldProtect);
167c2c66affSColin Finck if (!NT_SUCCESS(Status))
168c2c66affSColin Finck {
169c2c66affSColin Finck /* We failed */
170c2c66affSColin Finck BaseSetLastNTError(Status);
171c2c66affSColin Finck return FALSE;
172c2c66affSColin Finck }
173c2c66affSColin Finck
174c2c66affSColin Finck /* Return success */
175c2c66affSColin Finck return TRUE;
176c2c66affSColin Finck }
177c2c66affSColin Finck
178c2c66affSColin Finck /*
179c2c66affSColin Finck * @implemented
180c2c66affSColin Finck */
181c2c66affSColin Finck BOOL
182c2c66affSColin Finck NTAPI
VirtualLock(IN LPVOID lpAddress,IN SIZE_T dwSize)183c2c66affSColin Finck VirtualLock(IN LPVOID lpAddress,
184c2c66affSColin Finck IN SIZE_T dwSize)
185c2c66affSColin Finck {
186c2c66affSColin Finck NTSTATUS Status;
187c2c66affSColin Finck SIZE_T RegionSize = dwSize;
188c2c66affSColin Finck PVOID BaseAddress = lpAddress;
189c2c66affSColin Finck
190c2c66affSColin Finck /* Lock the memory */
191c2c66affSColin Finck Status = NtLockVirtualMemory(NtCurrentProcess(),
192c2c66affSColin Finck &BaseAddress,
193c2c66affSColin Finck &RegionSize,
194c2c66affSColin Finck MAP_PROCESS);
195c2c66affSColin Finck if (!NT_SUCCESS(Status))
196c2c66affSColin Finck {
197c2c66affSColin Finck /* We failed */
198c2c66affSColin Finck BaseSetLastNTError(Status);
199c2c66affSColin Finck return FALSE;
200c2c66affSColin Finck }
201c2c66affSColin Finck
202c2c66affSColin Finck /* Return success */
203c2c66affSColin Finck return TRUE;
204c2c66affSColin Finck }
205c2c66affSColin Finck
206c2c66affSColin Finck /*
207c2c66affSColin Finck * @implemented
208c2c66affSColin Finck */
209c2c66affSColin Finck SIZE_T
210c2c66affSColin Finck NTAPI
VirtualQuery(IN LPCVOID lpAddress,OUT PMEMORY_BASIC_INFORMATION lpBuffer,IN SIZE_T dwLength)211c2c66affSColin Finck VirtualQuery(IN LPCVOID lpAddress,
212c2c66affSColin Finck OUT PMEMORY_BASIC_INFORMATION lpBuffer,
213c2c66affSColin Finck IN SIZE_T dwLength)
214c2c66affSColin Finck {
215c2c66affSColin Finck /* Call the extended API */
216c2c66affSColin Finck return VirtualQueryEx(NtCurrentProcess(),
217c2c66affSColin Finck lpAddress,
218c2c66affSColin Finck lpBuffer,
219c2c66affSColin Finck dwLength);
220c2c66affSColin Finck }
221c2c66affSColin Finck
222c2c66affSColin Finck /*
223c2c66affSColin Finck * @implemented
224c2c66affSColin Finck */
225c2c66affSColin Finck SIZE_T
226c2c66affSColin Finck NTAPI
VirtualQueryEx(IN HANDLE hProcess,IN LPCVOID lpAddress,OUT PMEMORY_BASIC_INFORMATION lpBuffer,IN SIZE_T dwLength)227c2c66affSColin Finck VirtualQueryEx(IN HANDLE hProcess,
228c2c66affSColin Finck IN LPCVOID lpAddress,
229c2c66affSColin Finck OUT PMEMORY_BASIC_INFORMATION lpBuffer,
230c2c66affSColin Finck IN SIZE_T dwLength)
231c2c66affSColin Finck {
232c2c66affSColin Finck NTSTATUS Status;
233c2c66affSColin Finck SIZE_T ResultLength;
234c2c66affSColin Finck
235c2c66affSColin Finck /* Query basic information */
236c2c66affSColin Finck Status = NtQueryVirtualMemory(hProcess,
237c2c66affSColin Finck (LPVOID)lpAddress,
238c2c66affSColin Finck MemoryBasicInformation,
239c2c66affSColin Finck lpBuffer,
240c2c66affSColin Finck dwLength,
241c2c66affSColin Finck &ResultLength);
242c2c66affSColin Finck if (!NT_SUCCESS(Status))
243c2c66affSColin Finck {
244c2c66affSColin Finck /* We failed */
245c2c66affSColin Finck BaseSetLastNTError(Status);
246c2c66affSColin Finck return 0;
247c2c66affSColin Finck }
248c2c66affSColin Finck
249c2c66affSColin Finck /* Return the length returned */
250c2c66affSColin Finck return ResultLength;
251c2c66affSColin Finck }
252c2c66affSColin Finck
253c2c66affSColin Finck /*
254c2c66affSColin Finck * @implemented
255c2c66affSColin Finck */
256c2c66affSColin Finck BOOL
257c2c66affSColin Finck NTAPI
VirtualUnlock(IN LPVOID lpAddress,IN SIZE_T dwSize)258c2c66affSColin Finck VirtualUnlock(IN LPVOID lpAddress,
259c2c66affSColin Finck IN SIZE_T dwSize)
260c2c66affSColin Finck {
261c2c66affSColin Finck NTSTATUS Status;
262c2c66affSColin Finck SIZE_T RegionSize = dwSize;
263c2c66affSColin Finck PVOID BaseAddress = lpAddress;
264c2c66affSColin Finck
265c2c66affSColin Finck /* Lock the memory */
266c2c66affSColin Finck Status = NtUnlockVirtualMemory(NtCurrentProcess(),
267c2c66affSColin Finck &BaseAddress,
268c2c66affSColin Finck &RegionSize,
269c2c66affSColin Finck MAP_PROCESS);
270c2c66affSColin Finck if (!NT_SUCCESS(Status))
271c2c66affSColin Finck {
272c2c66affSColin Finck /* We failed */
273c2c66affSColin Finck BaseSetLastNTError(Status);
274c2c66affSColin Finck return FALSE;
275c2c66affSColin Finck }
276c2c66affSColin Finck
277c2c66affSColin Finck /* Return success */
278c2c66affSColin Finck return TRUE;
279c2c66affSColin Finck }
280c2c66affSColin Finck
281c2c66affSColin Finck /*
282c2c66affSColin Finck * @implemented
283c2c66affSColin Finck */
284c2c66affSColin Finck UINT
285c2c66affSColin Finck WINAPI
GetWriteWatch(IN DWORD dwFlags,IN PVOID lpBaseAddress,IN SIZE_T dwRegionSize,IN PVOID * lpAddresses,OUT PULONG_PTR lpdwCount,OUT PULONG lpdwGranularity)286c2c66affSColin Finck GetWriteWatch(IN DWORD dwFlags,
287c2c66affSColin Finck IN PVOID lpBaseAddress,
288c2c66affSColin Finck IN SIZE_T dwRegionSize,
289c2c66affSColin Finck IN PVOID *lpAddresses,
290c2c66affSColin Finck OUT PULONG_PTR lpdwCount,
291c2c66affSColin Finck OUT PULONG lpdwGranularity)
292c2c66affSColin Finck {
293c2c66affSColin Finck NTSTATUS Status;
294c2c66affSColin Finck
295c2c66affSColin Finck Status = NtGetWriteWatch(GetCurrentProcess(),
296c2c66affSColin Finck dwFlags,
297c2c66affSColin Finck lpBaseAddress,
298c2c66affSColin Finck dwRegionSize,
299c2c66affSColin Finck lpAddresses,
300c2c66affSColin Finck lpdwCount,
301c2c66affSColin Finck lpdwGranularity);
302c2c66affSColin Finck if (!NT_SUCCESS(Status))
303c2c66affSColin Finck {
304c2c66affSColin Finck BaseSetLastNTError(Status);
305c2c66affSColin Finck return -1;
306c2c66affSColin Finck }
307c2c66affSColin Finck
308c2c66affSColin Finck return 0;
309c2c66affSColin Finck }
310c2c66affSColin Finck
311c2c66affSColin Finck /*
312c2c66affSColin Finck * @implemented
313c2c66affSColin Finck */
314c2c66affSColin Finck UINT
315c2c66affSColin Finck WINAPI
ResetWriteWatch(IN LPVOID lpBaseAddress,IN SIZE_T dwRegionSize)316c2c66affSColin Finck ResetWriteWatch(IN LPVOID lpBaseAddress,
317c2c66affSColin Finck IN SIZE_T dwRegionSize)
318c2c66affSColin Finck {
319c2c66affSColin Finck NTSTATUS Status;
320c2c66affSColin Finck
321c2c66affSColin Finck Status = NtResetWriteWatch(NtCurrentProcess(),
322c2c66affSColin Finck lpBaseAddress,
323c2c66affSColin Finck dwRegionSize);
324c2c66affSColin Finck if (!NT_SUCCESS(Status))
325c2c66affSColin Finck {
326c2c66affSColin Finck BaseSetLastNTError(Status);
327c2c66affSColin Finck return -1;
328c2c66affSColin Finck }
329c2c66affSColin Finck
330c2c66affSColin Finck return 0;
331c2c66affSColin Finck }
332c2c66affSColin Finck
333c2c66affSColin Finck /*
334c2c66affSColin Finck * @implemented
335c2c66affSColin Finck */
336c2c66affSColin Finck BOOL
337c2c66affSColin Finck WINAPI
AllocateUserPhysicalPages(IN HANDLE hProcess,IN PULONG_PTR NumberOfPages,OUT PULONG_PTR UserPfnArray)338c2c66affSColin Finck AllocateUserPhysicalPages(IN HANDLE hProcess,
339c2c66affSColin Finck IN PULONG_PTR NumberOfPages,
340c2c66affSColin Finck OUT PULONG_PTR UserPfnArray)
341c2c66affSColin Finck {
342c2c66affSColin Finck NTSTATUS Status;
343c2c66affSColin Finck
344c2c66affSColin Finck Status = NtAllocateUserPhysicalPages(hProcess, NumberOfPages, UserPfnArray);
345c2c66affSColin Finck if (!NT_SUCCESS(Status))
346c2c66affSColin Finck {
347c2c66affSColin Finck BaseSetLastNTError(Status);
348c2c66affSColin Finck return FALSE;
349c2c66affSColin Finck }
350c2c66affSColin Finck
351c2c66affSColin Finck return TRUE;
352c2c66affSColin Finck }
353c2c66affSColin Finck
354c2c66affSColin Finck /*
355c2c66affSColin Finck * @implemented
356c2c66affSColin Finck */
357c2c66affSColin Finck BOOL
358c2c66affSColin Finck WINAPI
FreeUserPhysicalPages(IN HANDLE hProcess,IN PULONG_PTR NumberOfPages,IN PULONG_PTR PageArray)359c2c66affSColin Finck FreeUserPhysicalPages(IN HANDLE hProcess,
360c2c66affSColin Finck IN PULONG_PTR NumberOfPages,
361c2c66affSColin Finck IN PULONG_PTR PageArray)
362c2c66affSColin Finck {
363c2c66affSColin Finck NTSTATUS Status;
364c2c66affSColin Finck
365c2c66affSColin Finck Status = NtFreeUserPhysicalPages(hProcess, NumberOfPages, PageArray);
366c2c66affSColin Finck if (!NT_SUCCESS(Status))
367c2c66affSColin Finck {
368c2c66affSColin Finck BaseSetLastNTError(Status);
369c2c66affSColin Finck return FALSE;
370c2c66affSColin Finck }
371c2c66affSColin Finck
372c2c66affSColin Finck return TRUE;
373c2c66affSColin Finck }
374c2c66affSColin Finck
375c2c66affSColin Finck /*
376c2c66affSColin Finck * @implemented
377c2c66affSColin Finck */
378c2c66affSColin Finck BOOL
379c2c66affSColin Finck WINAPI
MapUserPhysicalPages(IN PVOID VirtualAddress,IN ULONG_PTR NumberOfPages,OUT PULONG_PTR PageArray OPTIONAL)380c2c66affSColin Finck MapUserPhysicalPages(IN PVOID VirtualAddress,
381c2c66affSColin Finck IN ULONG_PTR NumberOfPages,
382c2c66affSColin Finck OUT PULONG_PTR PageArray OPTIONAL)
383c2c66affSColin Finck {
384c2c66affSColin Finck NTSTATUS Status;
385c2c66affSColin Finck
386c2c66affSColin Finck Status = NtMapUserPhysicalPages(VirtualAddress, NumberOfPages, PageArray);
387c2c66affSColin Finck if (!NT_SUCCESS(Status))
388c2c66affSColin Finck {
389c2c66affSColin Finck BaseSetLastNTError(Status);
390c2c66affSColin Finck return FALSE;
391c2c66affSColin Finck }
392c2c66affSColin Finck
393c2c66affSColin Finck return TRUE;
394c2c66affSColin Finck }
395c2c66affSColin Finck
396c2c66affSColin Finck /*
397c2c66affSColin Finck * @implemented
398c2c66affSColin Finck */
399c2c66affSColin Finck BOOL
400c2c66affSColin Finck WINAPI
MapUserPhysicalPagesScatter(IN PVOID * VirtualAddresses,IN ULONG_PTR NumberOfPages,OUT PULONG_PTR PageArray OPTIONAL)401c2c66affSColin Finck MapUserPhysicalPagesScatter(IN PVOID *VirtualAddresses,
402c2c66affSColin Finck IN ULONG_PTR NumberOfPages,
403c2c66affSColin Finck OUT PULONG_PTR PageArray OPTIONAL)
404c2c66affSColin Finck {
405c2c66affSColin Finck NTSTATUS Status;
406c2c66affSColin Finck
407c2c66affSColin Finck Status = NtMapUserPhysicalPagesScatter(VirtualAddresses,
408c2c66affSColin Finck NumberOfPages,
409c2c66affSColin Finck PageArray);
410c2c66affSColin Finck if (!NT_SUCCESS(Status))
411c2c66affSColin Finck {
412c2c66affSColin Finck BaseSetLastNTError(Status);
413c2c66affSColin Finck return FALSE;
414c2c66affSColin Finck }
415c2c66affSColin Finck
416c2c66affSColin Finck return TRUE;
417c2c66affSColin Finck }
418c2c66affSColin Finck
419c2c66affSColin Finck /* EOF */
420