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