xref: /reactos/win32ss/gdi/eng/mem.c (revision c2c66aff)
1 /*
2  * COPYRIGHT:         See COPYING in the top level directory
3  * PROJECT:           ReactOS kernel
4  * PURPOSE:           GDI Driver Memory Management Functions
5  * FILE:              win32ss/gdi/eng/mem.c
6  * PROGRAMER:         Jason Filby
7  */
8 
9 #include <win32k.h>
10 
11 #define NDEBUG
12 #include <debug.h>
13 
14 /*
15  * @implemented
16  */
17 _Must_inspect_result_
_When_(fl & FL_ZERO_MEMORY,_Ret_opt_bytecount_ (cjMemSize))18 _When_(fl & FL_ZERO_MEMORY, _Ret_opt_bytecount_(cjMemSize))
19 _When_(!(fl & FL_ZERO_MEMORY), _Ret_opt_bytecap_(cjMemSize))
20 __drv_allocatesMem(Mem)
21 ENGAPI
22 PVOID
23 APIENTRY
24 EngAllocMem(
25     _In_ ULONG fl,
26     _In_ ULONG cjMemSize,
27     _In_ ULONG ulTag)
28 {
29     PVOID pvBaseAddress;
30 
31     pvBaseAddress = ExAllocatePoolWithTag((fl & FL_NONPAGED_MEMORY) ?
32                                                     NonPagedPool : PagedPool,
33                                           cjMemSize,
34                                           ulTag);
35 
36     if (pvBaseAddress == NULL)
37         return NULL;
38 
39     if (fl & FL_ZERO_MEMORY)
40         RtlZeroMemory(pvBaseAddress, cjMemSize);
41 
42     return pvBaseAddress;
43 }
44 
45 /*
46  * @implemented
47  */
48 VOID
49 APIENTRY
EngFreeMem(PVOID pvBaseAddress)50 EngFreeMem(PVOID pvBaseAddress)
51 {
52     /* Windows allows to pass NULL */
53     if (pvBaseAddress)
54     {
55         /* Use 0 as tag, which equals a call to ExFreePool */
56         ExFreePoolWithTag(pvBaseAddress, 0);
57     }
58 }
59 
60 /*
61  * @implemented
62  */
63 _Must_inspect_result_
_Ret_opt_bytecount_(cjMemSize)64 _Ret_opt_bytecount_(cjMemSize)
65 __drv_allocatesMem(UserMem)
66 ENGAPI
67 PVOID
68 APIENTRY
69 EngAllocUserMem(
70     _In_ SIZE_T cjMemSize,
71     _In_ ULONG ulTag)
72 {
73     PVOID pvBaseAddress = NULL;
74     NTSTATUS Status;
75 
76     Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
77                                      &pvBaseAddress,
78                                      0,
79                                      &cjMemSize,
80                                      MEM_COMMIT | MEM_RESERVE,
81                                      PAGE_READWRITE);
82 
83     if (!NT_SUCCESS(Status))
84     {
85         return NULL;
86     }
87 
88     /* TODO: Add allocation info to AVL tree (stored inside W32PROCESS structure) */
89     //hSecure = EngSecureMem(pvBaseAddress, cj);
90 
91     return pvBaseAddress;
92 }
93 
94 /*
95  * @implemented
96  */
97 VOID
98 APIENTRY
EngFreeUserMem(PVOID pvBaseAddress)99 EngFreeUserMem(PVOID pvBaseAddress)
100 {
101     SIZE_T cjSize = 0;
102 
103     ZwFreeVirtualMemory(NtCurrentProcess(),
104                         &pvBaseAddress,
105                         &cjSize,
106                         MEM_RELEASE);
107 
108   /* TODO: Remove allocation info from AVL tree */
109 }
110 
111 PVOID
112 APIENTRY
HackSecureVirtualMemory(IN PVOID Address,IN SIZE_T Size,IN ULONG ProbeMode,OUT PVOID * SafeAddress)113 HackSecureVirtualMemory(
114     IN PVOID Address,
115     IN SIZE_T Size,
116     IN ULONG ProbeMode,
117     OUT PVOID *SafeAddress)
118 {
119     NTSTATUS Status = STATUS_SUCCESS;
120     PMDL pmdl;
121     LOCK_OPERATION Operation;
122 
123     if (ProbeMode == PAGE_READONLY) Operation = IoReadAccess;
124     else if (ProbeMode == PAGE_READWRITE) Operation = IoModifyAccess;
125     else return NULL;
126 
127     pmdl = IoAllocateMdl(Address, (ULONG)Size, FALSE, TRUE, NULL);
128     if (pmdl == NULL)
129     {
130         return NULL;
131     }
132 
133     _SEH2_TRY
134     {
135         MmProbeAndLockPages(pmdl, UserMode, Operation);
136     }
137     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
138     {
139         Status = _SEH2_GetExceptionCode();
140     }
141     _SEH2_END
142 
143     if (!NT_SUCCESS(Status))
144     {
145         IoFreeMdl(pmdl);
146         return NULL;
147     }
148 
149     *SafeAddress = MmGetSystemAddressForMdlSafe(pmdl, NormalPagePriority);
150 
151     if(!*SafeAddress)
152     {
153         MmUnlockPages(pmdl);
154         IoFreeMdl(pmdl);
155         return NULL;
156     }
157 
158     return pmdl;
159 }
160 
161 VOID
162 APIENTRY
HackUnsecureVirtualMemory(IN PVOID SecureHandle)163 HackUnsecureVirtualMemory(
164     IN PVOID  SecureHandle)
165 {
166     PMDL pmdl = (PMDL)SecureHandle;
167 
168     MmUnlockPages(pmdl);
169     IoFreeMdl(pmdl);
170 }
171 
172 /*
173  * @implemented
174  */
175 HANDLE
176 APIENTRY
EngSecureMem(PVOID Address,ULONG Length)177 EngSecureMem(PVOID Address, ULONG Length)
178 {
179     {// HACK!!!
180         _SEH2_TRY
181         {
182             ProbeForWrite(Address, Length, 1);
183         }
184         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
185         {
186             _SEH2_YIELD(return NULL);
187         }
188         _SEH2_END;
189         return (HANDLE)-1;
190     }
191     return MmSecureVirtualMemory(Address, Length, PAGE_READWRITE);
192 }
193 
194 HANDLE
195 APIENTRY
EngSecureMemForRead(PVOID Address,ULONG Length)196 EngSecureMemForRead(PVOID Address, ULONG Length)
197 {
198     {// HACK!!!
199         ULONG cPages;
200         volatile BYTE *pjProbe;
201 
202         _SEH2_TRY
203         {
204             ProbeForRead(Address, Length, 1);
205             cPages = ADDRESS_AND_SIZE_TO_SPAN_PAGES(Address, Length);
206             pjProbe = ALIGN_DOWN_POINTER_BY(Address, PAGE_SIZE);
207             while(cPages--)
208             {
209                 /* Do a read probe */
210                 (void)*pjProbe;
211                 pjProbe += PAGE_SIZE;
212             }
213         }
214         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
215         {
216             _SEH2_YIELD(return NULL);
217         }
218         _SEH2_END;
219         return (HANDLE)-1;
220     }
221     return MmSecureVirtualMemory(Address, Length, PAGE_READONLY);
222 }
223 
224 /*
225  * @implemented
226  */
227 VOID APIENTRY
EngUnsecureMem(HANDLE Mem)228 EngUnsecureMem(HANDLE Mem)
229 {
230     if (Mem == (HANDLE)-1) return;  // HACK!!!
231     MmUnsecureVirtualMemory((PVOID) Mem);
232 }
233 
234 /* EOF */
235