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