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