[INTRIN]
[reactos.git] / reactos / dll / win32 / kernel32 / client / file / filemap.c
1 /*
2 * PROJECT: ReactOS Win32 Base API
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: dll/win32/kernel32/mem/section.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 HANDLE
22 NTAPI
23 CreateFileMappingA(IN HANDLE hFile,
24 IN LPSECURITY_ATTRIBUTES lpFileMappingAttributes,
25 IN DWORD flProtect,
26 IN DWORD dwMaximumSizeHigh,
27 IN DWORD dwMaximumSizeLow,
28 IN LPCSTR lpName)
29 {
30 /* Call the W(ide) function */
31 ConvertWin32AnsiObjectApiToUnicodeApi(FileMapping,
32 lpName,
33 hFile,
34 lpFileMappingAttributes,
35 flProtect,
36 dwMaximumSizeHigh,
37 dwMaximumSizeLow);
38 }
39
40 /*
41 * @implemented
42 */
43 HANDLE
44 NTAPI
45 CreateFileMappingW(HANDLE hFile,
46 LPSECURITY_ATTRIBUTES lpFileMappingAttributes,
47 DWORD flProtect,
48 DWORD dwMaximumSizeHigh,
49 DWORD dwMaximumSizeLow,
50 LPCWSTR lpName)
51 {
52 NTSTATUS Status;
53 HANDLE SectionHandle;
54 OBJECT_ATTRIBUTES LocalAttributes;
55 POBJECT_ATTRIBUTES ObjectAttributes;
56 UNICODE_STRING SectionName;
57 ACCESS_MASK DesiredAccess;
58 LARGE_INTEGER LocalSize;
59 PLARGE_INTEGER SectionSize = NULL;
60 ULONG Attributes;
61
62 /* Set default access */
63 DesiredAccess = STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ;
64
65 /* Get the attributes for the actual allocation and cleanup flProtect */
66 Attributes = flProtect & (SEC_FILE | SEC_IMAGE | SEC_RESERVE | SEC_NOCACHE | SEC_COMMIT | SEC_LARGE_PAGES);
67 flProtect ^= Attributes;
68
69 /* If the caller didn't say anything, assume SEC_COMMIT */
70 if (!Attributes) Attributes = SEC_COMMIT;
71
72 /* Now check if the caller wanted write access */
73 if (flProtect == PAGE_READWRITE)
74 {
75 /* Give it */
76 DesiredAccess |= SECTION_MAP_WRITE;
77 }
78 else if (flProtect == PAGE_EXECUTE_READWRITE)
79 {
80 /* Give it */
81 DesiredAccess |= (SECTION_MAP_WRITE | SECTION_MAP_EXECUTE);
82 }
83 else if (flProtect == PAGE_EXECUTE_READ)
84 {
85 /* Give it */
86 DesiredAccess |= SECTION_MAP_EXECUTE;
87 }
88 else if ((flProtect != PAGE_READONLY) && (flProtect != PAGE_WRITECOPY))
89 {
90 SetLastError(ERROR_INVALID_PARAMETER);
91 return NULL;
92 }
93
94 /* Now check if we got a name */
95 if (lpName) RtlInitUnicodeString(&SectionName, lpName);
96
97 /* Now convert the object attributes */
98 ObjectAttributes = BaseFormatObjectAttributes(&LocalAttributes,
99 lpFileMappingAttributes,
100 lpName ? &SectionName : NULL);
101
102 /* Check if we got a size */
103 if (dwMaximumSizeLow || dwMaximumSizeHigh)
104 {
105 /* Use a LARGE_INTEGER and convert */
106 SectionSize = &LocalSize;
107 SectionSize->LowPart = dwMaximumSizeLow;
108 SectionSize->HighPart = dwMaximumSizeHigh;
109 }
110
111 /* Make sure the handle is valid */
112 if (hFile == INVALID_HANDLE_VALUE)
113 {
114 /* It's not, we'll only go on if we have a size */
115 hFile = NULL;
116 if (!SectionSize)
117 {
118 /* No size, so this isn't a valid non-mapped section */
119 SetLastError(ERROR_INVALID_PARAMETER);
120 return NULL;
121 }
122 }
123
124 /* Now create the actual section */
125 Status = NtCreateSection(&SectionHandle,
126 DesiredAccess,
127 ObjectAttributes,
128 SectionSize,
129 flProtect,
130 Attributes,
131 hFile);
132 if (!NT_SUCCESS(Status))
133 {
134 /* We failed */
135 BaseSetLastNTError(Status);
136 return NULL;
137 }
138 else if (Status == STATUS_OBJECT_NAME_EXISTS)
139 {
140 SetLastError(ERROR_ALREADY_EXISTS);
141 }
142 else
143 {
144 SetLastError(ERROR_SUCCESS);
145 }
146
147 /* Return the section */
148 return SectionHandle;
149 }
150
151 /*
152 * @implemented
153 */
154 LPVOID
155 NTAPI
156 MapViewOfFileEx(HANDLE hFileMappingObject,
157 DWORD dwDesiredAccess,
158 DWORD dwFileOffsetHigh,
159 DWORD dwFileOffsetLow,
160 SIZE_T dwNumberOfBytesToMap,
161 LPVOID lpBaseAddress)
162 {
163 NTSTATUS Status;
164 LARGE_INTEGER SectionOffset;
165 SIZE_T ViewSize;
166 ULONG Protect;
167 LPVOID ViewBase;
168
169 /* Convert the offset */
170 SectionOffset.LowPart = dwFileOffsetLow;
171 SectionOffset.HighPart = dwFileOffsetHigh;
172
173 /* Save the size and base */
174 ViewBase = lpBaseAddress;
175 ViewSize = dwNumberOfBytesToMap;
176
177 /* Convert flags to NT Protection Attributes */
178 if (dwDesiredAccess == FILE_MAP_COPY)
179 {
180 Protect = PAGE_WRITECOPY;
181 }
182 else if (dwDesiredAccess & FILE_MAP_WRITE)
183 {
184 Protect = (dwDesiredAccess & FILE_MAP_EXECUTE) ?
185 PAGE_EXECUTE_READWRITE : PAGE_READWRITE;
186 }
187 else if (dwDesiredAccess & FILE_MAP_READ)
188 {
189 Protect = (dwDesiredAccess & FILE_MAP_EXECUTE) ?
190 PAGE_EXECUTE_READ : PAGE_READONLY;
191 }
192 else
193 {
194 Protect = PAGE_NOACCESS;
195 }
196
197 /* Map the section */
198 Status = NtMapViewOfSection(hFileMappingObject,
199 NtCurrentProcess(),
200 &ViewBase,
201 0,
202 0,
203 &SectionOffset,
204 &ViewSize,
205 ViewShare,
206 0,
207 Protect);
208 if (!NT_SUCCESS(Status))
209 {
210 /* We failed */
211 BaseSetLastNTError(Status);
212 return NULL;
213 }
214
215 /* Return the base */
216 return ViewBase;
217 }
218
219 /*
220 * @implemented
221 */
222 LPVOID
223 NTAPI
224 MapViewOfFile(HANDLE hFileMappingObject,
225 DWORD dwDesiredAccess,
226 DWORD dwFileOffsetHigh,
227 DWORD dwFileOffsetLow,
228 SIZE_T dwNumberOfBytesToMap)
229 {
230 /* Call the extended API */
231 return MapViewOfFileEx(hFileMappingObject,
232 dwDesiredAccess,
233 dwFileOffsetHigh,
234 dwFileOffsetLow,
235 dwNumberOfBytesToMap,
236 NULL);
237 }
238
239 /*
240 * @implemented
241 */
242 BOOL
243 NTAPI
244 UnmapViewOfFile(LPCVOID lpBaseAddress)
245 {
246 NTSTATUS Status;
247
248 /* Unmap the section */
249 Status = NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)lpBaseAddress);
250 if (!NT_SUCCESS(Status))
251 {
252 /* Check if the pages were protected */
253 if (Status == STATUS_INVALID_PAGE_PROTECTION)
254 {
255 /* Flush the region if it was a "secure memory cache" */
256 if (RtlFlushSecureMemoryCache((PVOID)lpBaseAddress, 0))
257 {
258 /* Now try to unmap again */
259 Status = NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)lpBaseAddress);
260 if (NT_SUCCESS(Status)) return TRUE;
261 }
262 }
263
264 /* We failed */
265 BaseSetLastNTError(Status);
266 return FALSE;
267 }
268
269 /* Otherwise, return sucess */
270 return TRUE;
271 }
272
273 /*
274 * @implemented
275 */
276 HANDLE
277 NTAPI
278 OpenFileMappingA(IN DWORD dwDesiredAccess,
279 IN BOOL bInheritHandle,
280 IN LPCSTR lpName)
281 {
282 ConvertOpenWin32AnsiObjectApiToUnicodeApi(FileMapping, dwDesiredAccess, bInheritHandle, lpName);
283 }
284
285 /*
286 * @implemented
287 */
288 /* FIXME: Convert to the new macros */
289 HANDLE
290 NTAPI
291 OpenFileMappingW(IN DWORD dwDesiredAccess,
292 IN BOOL bInheritHandle,
293 IN LPCWSTR lpName)
294 {
295 NTSTATUS Status;
296 HANDLE SectionHandle;
297 OBJECT_ATTRIBUTES ObjectAttributes;
298 UNICODE_STRING UnicodeName;
299
300 /* We need a name */
301 if (!lpName)
302 {
303 /* Otherwise, fail */
304 SetLastError(ERROR_INVALID_PARAMETER);
305 return NULL;
306 }
307
308 /* Convert attributes */
309 RtlInitUnicodeString(&UnicodeName, lpName);
310 InitializeObjectAttributes(&ObjectAttributes,
311 &UnicodeName,
312 (bInheritHandle ? OBJ_INHERIT : 0),
313 BaseGetNamedObjectDirectory(),
314 NULL);
315
316 /* Convert COPY to READ */
317 if (dwDesiredAccess == FILE_MAP_COPY)
318 {
319 /* Fixup copy */
320 dwDesiredAccess = SECTION_MAP_READ;
321 }
322 else if (dwDesiredAccess & FILE_MAP_EXECUTE)
323 {
324 /* Fixup execute */
325 dwDesiredAccess = (dwDesiredAccess & ~FILE_MAP_EXECUTE) | SECTION_MAP_EXECUTE;
326 }
327
328 /* Open the section */
329 Status = NtOpenSection(&SectionHandle, dwDesiredAccess, &ObjectAttributes);
330 if (!NT_SUCCESS(Status))
331 {
332 /* We failed */
333 BaseSetLastNTError(Status);
334 return NULL;
335 }
336
337 /* Otherwise, return the handle */
338 return SectionHandle;
339 }
340
341 /*
342 * @implemented
343 */
344 BOOL
345 NTAPI
346 FlushViewOfFile(IN LPCVOID lpBaseAddress,
347 IN SIZE_T dwNumberOfBytesToFlush)
348 {
349 NTSTATUS Status;
350 PVOID BaseAddress = (PVOID)lpBaseAddress;
351 SIZE_T NumberOfBytesToFlush = dwNumberOfBytesToFlush;
352 IO_STATUS_BLOCK IoStatusBlock;
353
354 /* Flush the view */
355 Status = NtFlushVirtualMemory(NtCurrentProcess(),
356 &BaseAddress,
357 &NumberOfBytesToFlush,
358 &IoStatusBlock);
359 if (!NT_SUCCESS(Status) && (Status != STATUS_NOT_MAPPED_DATA))
360 {
361 /* We failed */
362 BaseSetLastNTError(Status);
363 return FALSE;
364 }
365
366 /* Return success */
367 return TRUE;
368 }
369
370 /* EOF */