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