2006-06-22 23:06:14 +00:00
|
|
|
/*
|
|
|
|
* PROJECT: ReactOS Win32 Base API
|
|
|
|
* LICENSE: GPL - See COPYING in the top level directory
|
2015-11-14 14:57:11 +00:00
|
|
|
* FILE: dll/win32/kernel32/client/file/filemap.c
|
2006-06-22 23:06:14 +00:00
|
|
|
* PURPOSE: Handles virtual memory APIs
|
|
|
|
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
1999-04-18 08:56:23 +00:00
|
|
|
*/
|
|
|
|
|
2011-11-07 15:43:37 +00:00
|
|
|
/* INCLUDES *******************************************************************/
|
1999-04-18 08:56:23 +00:00
|
|
|
|
2003-01-15 21:24:36 +00:00
|
|
|
#include <k32.h>
|
1999-04-18 08:56:23 +00:00
|
|
|
|
2003-01-15 21:24:36 +00:00
|
|
|
#define NDEBUG
|
2007-09-02 19:42:22 +00:00
|
|
|
#include <debug.h>
|
2001-02-17 17:42:46 +00:00
|
|
|
|
2011-11-07 15:43:37 +00:00
|
|
|
/* FUNCTIONS ******************************************************************/
|
1999-04-18 08:56:23 +00:00
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2006-06-22 23:06:14 +00:00
|
|
|
HANDLE
|
|
|
|
NTAPI
|
|
|
|
CreateFileMappingA(IN HANDLE hFile,
|
|
|
|
IN LPSECURITY_ATTRIBUTES lpFileMappingAttributes,
|
|
|
|
IN DWORD flProtect,
|
|
|
|
IN DWORD dwMaximumSizeHigh,
|
|
|
|
IN DWORD dwMaximumSizeLow,
|
|
|
|
IN LPCSTR lpName)
|
1999-04-18 08:56:23 +00:00
|
|
|
{
|
2011-07-22 08:59:27 +00:00
|
|
|
/* Call the W(ide) function */
|
|
|
|
ConvertWin32AnsiObjectApiToUnicodeApi(FileMapping,
|
|
|
|
lpName,
|
|
|
|
hFile,
|
|
|
|
lpFileMappingAttributes,
|
|
|
|
flProtect,
|
|
|
|
dwMaximumSizeHigh,
|
|
|
|
dwMaximumSizeLow);
|
1999-04-18 08:56:23 +00:00
|
|
|
}
|
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2006-06-22 23:06:14 +00:00
|
|
|
HANDLE
|
|
|
|
NTAPI
|
2001-02-17 17:42:46 +00:00
|
|
|
CreateFileMappingW(HANDLE hFile,
|
2006-06-22 23:06:14 +00:00
|
|
|
LPSECURITY_ATTRIBUTES lpFileMappingAttributes,
|
|
|
|
DWORD flProtect,
|
|
|
|
DWORD dwMaximumSizeHigh,
|
|
|
|
DWORD dwMaximumSizeLow,
|
|
|
|
LPCWSTR lpName)
|
1999-04-18 08:56:23 +00:00
|
|
|
{
|
2006-06-22 23:06:14 +00:00
|
|
|
NTSTATUS Status;
|
|
|
|
HANDLE SectionHandle;
|
|
|
|
OBJECT_ATTRIBUTES LocalAttributes;
|
|
|
|
POBJECT_ATTRIBUTES ObjectAttributes;
|
|
|
|
UNICODE_STRING SectionName;
|
|
|
|
ACCESS_MASK DesiredAccess;
|
|
|
|
LARGE_INTEGER LocalSize;
|
|
|
|
PLARGE_INTEGER SectionSize = NULL;
|
|
|
|
ULONG Attributes;
|
|
|
|
|
|
|
|
/* Set default access */
|
|
|
|
DesiredAccess = STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ;
|
|
|
|
|
|
|
|
/* Get the attributes for the actual allocation and cleanup flProtect */
|
2010-10-02 01:12:53 +00:00
|
|
|
Attributes = flProtect & (SEC_FILE | SEC_IMAGE | SEC_RESERVE | SEC_NOCACHE | SEC_COMMIT | SEC_LARGE_PAGES);
|
2006-06-22 23:06:14 +00:00
|
|
|
flProtect ^= Attributes;
|
|
|
|
|
|
|
|
/* If the caller didn't say anything, assume SEC_COMMIT */
|
|
|
|
if (!Attributes) Attributes = SEC_COMMIT;
|
|
|
|
|
|
|
|
/* Now check if the caller wanted write access */
|
|
|
|
if (flProtect == PAGE_READWRITE)
|
|
|
|
{
|
|
|
|
/* Give it */
|
2011-11-07 15:43:37 +00:00
|
|
|
DesiredAccess |= SECTION_MAP_WRITE;
|
|
|
|
}
|
|
|
|
else if (flProtect == PAGE_EXECUTE_READWRITE)
|
|
|
|
{
|
|
|
|
/* Give it */
|
|
|
|
DesiredAccess |= (SECTION_MAP_WRITE | SECTION_MAP_EXECUTE);
|
|
|
|
}
|
|
|
|
else if (flProtect == PAGE_EXECUTE_READ)
|
|
|
|
{
|
|
|
|
/* Give it */
|
|
|
|
DesiredAccess |= SECTION_MAP_EXECUTE;
|
|
|
|
}
|
2017-08-16 16:06:36 +00:00
|
|
|
else if ((flProtect == PAGE_EXECUTE_WRITECOPY) &&
|
|
|
|
(NtCurrentPeb()->OSMajorVersion >= 6))
|
|
|
|
{
|
|
|
|
/* Give it */
|
|
|
|
DesiredAccess |= (SECTION_MAP_WRITE | SECTION_MAP_EXECUTE);
|
|
|
|
}
|
2011-11-07 16:53:04 +00:00
|
|
|
else if ((flProtect != PAGE_READONLY) && (flProtect != PAGE_WRITECOPY))
|
2011-11-07 15:43:37 +00:00
|
|
|
{
|
|
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
|
|
return NULL;
|
2006-06-22 23:06:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Now check if we got a name */
|
|
|
|
if (lpName) RtlInitUnicodeString(&SectionName, lpName);
|
|
|
|
|
|
|
|
/* Now convert the object attributes */
|
2011-11-03 00:30:44 +00:00
|
|
|
ObjectAttributes = BaseFormatObjectAttributes(&LocalAttributes,
|
2006-06-22 23:06:14 +00:00
|
|
|
lpFileMappingAttributes,
|
|
|
|
lpName ? &SectionName : NULL);
|
|
|
|
|
|
|
|
/* Check if we got a size */
|
|
|
|
if (dwMaximumSizeLow || dwMaximumSizeHigh)
|
|
|
|
{
|
|
|
|
/* Use a LARGE_INTEGER and convert */
|
|
|
|
SectionSize = &LocalSize;
|
|
|
|
SectionSize->LowPart = dwMaximumSizeLow;
|
|
|
|
SectionSize->HighPart = dwMaximumSizeHigh;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Make sure the handle is valid */
|
|
|
|
if (hFile == INVALID_HANDLE_VALUE)
|
|
|
|
{
|
|
|
|
/* It's not, we'll only go on if we have a size */
|
|
|
|
hFile = NULL;
|
|
|
|
if (!SectionSize)
|
|
|
|
{
|
|
|
|
/* No size, so this isn't a valid non-mapped section */
|
|
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Now create the actual section */
|
|
|
|
Status = NtCreateSection(&SectionHandle,
|
|
|
|
DesiredAccess,
|
|
|
|
ObjectAttributes,
|
|
|
|
SectionSize,
|
|
|
|
flProtect,
|
|
|
|
Attributes,
|
|
|
|
hFile);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
/* We failed */
|
2011-07-23 18:54:29 +00:00
|
|
|
BaseSetLastNTError(Status);
|
2003-12-16 21:32:18 +00:00
|
|
|
return NULL;
|
2006-06-22 23:06:14 +00:00
|
|
|
}
|
2011-11-07 15:43:37 +00:00
|
|
|
else if (Status == STATUS_OBJECT_NAME_EXISTS)
|
|
|
|
{
|
|
|
|
SetLastError(ERROR_ALREADY_EXISTS);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
SetLastError(ERROR_SUCCESS);
|
|
|
|
}
|
1999-04-18 08:56:23 +00:00
|
|
|
|
2006-06-22 23:06:14 +00:00
|
|
|
/* Return the section */
|
|
|
|
return SectionHandle;
|
|
|
|
}
|
1999-10-03 23:19:15 +00:00
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2006-06-22 23:06:14 +00:00
|
|
|
LPVOID
|
|
|
|
NTAPI
|
2001-02-17 17:42:46 +00:00
|
|
|
MapViewOfFileEx(HANDLE hFileMappingObject,
|
2006-06-22 23:06:14 +00:00
|
|
|
DWORD dwDesiredAccess,
|
|
|
|
DWORD dwFileOffsetHigh,
|
|
|
|
DWORD dwFileOffsetLow,
|
2008-10-23 18:19:20 +00:00
|
|
|
SIZE_T dwNumberOfBytesToMap,
|
2006-06-22 23:06:14 +00:00
|
|
|
LPVOID lpBaseAddress)
|
1999-04-18 08:56:23 +00:00
|
|
|
{
|
2006-06-22 23:06:14 +00:00
|
|
|
NTSTATUS Status;
|
|
|
|
LARGE_INTEGER SectionOffset;
|
2008-10-23 18:19:20 +00:00
|
|
|
SIZE_T ViewSize;
|
2006-06-22 23:06:14 +00:00
|
|
|
ULONG Protect;
|
|
|
|
LPVOID ViewBase;
|
|
|
|
|
|
|
|
/* Convert the offset */
|
|
|
|
SectionOffset.LowPart = dwFileOffsetLow;
|
|
|
|
SectionOffset.HighPart = dwFileOffsetHigh;
|
|
|
|
|
|
|
|
/* Save the size and base */
|
|
|
|
ViewBase = lpBaseAddress;
|
|
|
|
ViewSize = dwNumberOfBytesToMap;
|
|
|
|
|
|
|
|
/* Convert flags to NT Protection Attributes */
|
2011-11-07 15:43:37 +00:00
|
|
|
if (dwDesiredAccess == FILE_MAP_COPY)
|
2006-06-22 23:06:14 +00:00
|
|
|
{
|
2011-11-07 15:43:37 +00:00
|
|
|
Protect = PAGE_WRITECOPY;
|
2006-06-22 23:06:14 +00:00
|
|
|
}
|
2011-11-07 15:43:37 +00:00
|
|
|
else if (dwDesiredAccess & FILE_MAP_WRITE)
|
2006-06-22 23:06:14 +00:00
|
|
|
{
|
2011-11-07 15:43:37 +00:00
|
|
|
Protect = (dwDesiredAccess & FILE_MAP_EXECUTE) ?
|
|
|
|
PAGE_EXECUTE_READWRITE : PAGE_READWRITE;
|
2006-06-22 23:06:14 +00:00
|
|
|
}
|
2011-11-07 15:43:37 +00:00
|
|
|
else if (dwDesiredAccess & FILE_MAP_READ)
|
2006-06-22 23:06:14 +00:00
|
|
|
{
|
2011-11-07 15:43:37 +00:00
|
|
|
Protect = (dwDesiredAccess & FILE_MAP_EXECUTE) ?
|
|
|
|
PAGE_EXECUTE_READ : PAGE_READONLY;
|
2006-06-22 23:06:14 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Protect = PAGE_NOACCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Map the section */
|
2012-04-25 10:17:29 +00:00
|
|
|
Status = NtMapViewOfSection(hFileMappingObject,
|
2006-06-22 23:06:14 +00:00
|
|
|
NtCurrentProcess(),
|
|
|
|
&ViewBase,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
&SectionOffset,
|
|
|
|
&ViewSize,
|
|
|
|
ViewShare,
|
|
|
|
0,
|
|
|
|
Protect);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
/* We failed */
|
2011-07-23 18:54:29 +00:00
|
|
|
BaseSetLastNTError(Status);
|
2006-06-22 23:06:14 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
1999-09-27 20:58:46 +00:00
|
|
|
|
2006-06-22 23:06:14 +00:00
|
|
|
/* Return the base */
|
|
|
|
return ViewBase;
|
|
|
|
}
|
2001-02-17 17:42:46 +00:00
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2006-06-22 23:06:14 +00:00
|
|
|
LPVOID
|
|
|
|
NTAPI
|
2001-02-17 17:42:46 +00:00
|
|
|
MapViewOfFile(HANDLE hFileMappingObject,
|
2006-06-22 23:06:14 +00:00
|
|
|
DWORD dwDesiredAccess,
|
|
|
|
DWORD dwFileOffsetHigh,
|
|
|
|
DWORD dwFileOffsetLow,
|
2008-10-23 18:19:20 +00:00
|
|
|
SIZE_T dwNumberOfBytesToMap)
|
1999-09-27 20:58:46 +00:00
|
|
|
{
|
2006-06-22 23:06:14 +00:00
|
|
|
/* Call the extended API */
|
|
|
|
return MapViewOfFileEx(hFileMappingObject,
|
|
|
|
dwDesiredAccess,
|
|
|
|
dwFileOffsetHigh,
|
|
|
|
dwFileOffsetLow,
|
|
|
|
dwNumberOfBytesToMap,
|
|
|
|
NULL);
|
1999-09-27 20:58:46 +00:00
|
|
|
}
|
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2006-06-22 23:06:14 +00:00
|
|
|
BOOL
|
|
|
|
NTAPI
|
2008-08-02 09:29:16 +00:00
|
|
|
UnmapViewOfFile(LPCVOID lpBaseAddress)
|
1999-09-27 20:58:46 +00:00
|
|
|
{
|
2006-06-22 23:06:14 +00:00
|
|
|
NTSTATUS Status;
|
|
|
|
|
|
|
|
/* Unmap the section */
|
2008-08-02 09:29:16 +00:00
|
|
|
Status = NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)lpBaseAddress);
|
2006-06-22 23:06:14 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
2011-11-07 15:43:37 +00:00
|
|
|
/* Check if the pages were protected */
|
|
|
|
if (Status == STATUS_INVALID_PAGE_PROTECTION)
|
|
|
|
{
|
|
|
|
/* Flush the region if it was a "secure memory cache" */
|
|
|
|
if (RtlFlushSecureMemoryCache((PVOID)lpBaseAddress, 0))
|
|
|
|
{
|
|
|
|
/* Now try to unmap again */
|
|
|
|
Status = NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)lpBaseAddress);
|
|
|
|
if (NT_SUCCESS(Status)) return TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-06-22 23:06:14 +00:00
|
|
|
/* We failed */
|
2011-07-23 18:54:29 +00:00
|
|
|
BaseSetLastNTError(Status);
|
2006-06-22 23:06:14 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2016-11-12 21:53:33 +00:00
|
|
|
/* Otherwise, return success */
|
2006-06-22 23:06:14 +00:00
|
|
|
return TRUE;
|
1999-09-27 20:58:46 +00:00
|
|
|
}
|
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2006-06-22 23:06:14 +00:00
|
|
|
HANDLE
|
|
|
|
NTAPI
|
2011-11-07 15:43:37 +00:00
|
|
|
OpenFileMappingA(IN DWORD dwDesiredAccess,
|
|
|
|
IN BOOL bInheritHandle,
|
|
|
|
IN LPCSTR lpName)
|
1999-09-27 20:58:46 +00:00
|
|
|
{
|
2011-11-07 15:43:37 +00:00
|
|
|
ConvertOpenWin32AnsiObjectApiToUnicodeApi(FileMapping, dwDesiredAccess, bInheritHandle, lpName);
|
2006-06-22 23:06:14 +00:00
|
|
|
}
|
1999-10-03 23:19:15 +00:00
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2011-11-03 00:30:44 +00:00
|
|
|
/* FIXME: Convert to the new macros */
|
2006-06-22 23:06:14 +00:00
|
|
|
HANDLE
|
|
|
|
NTAPI
|
2011-11-07 15:43:37 +00:00
|
|
|
OpenFileMappingW(IN DWORD dwDesiredAccess,
|
|
|
|
IN BOOL bInheritHandle,
|
|
|
|
IN LPCWSTR lpName)
|
1999-09-27 20:58:46 +00:00
|
|
|
{
|
2006-06-22 23:06:14 +00:00
|
|
|
NTSTATUS Status;
|
|
|
|
HANDLE SectionHandle;
|
|
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
|
|
UNICODE_STRING UnicodeName;
|
|
|
|
|
|
|
|
/* We need a name */
|
|
|
|
if (!lpName)
|
|
|
|
{
|
|
|
|
/* Otherwise, fail */
|
2004-10-24 12:55:19 +00:00
|
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
|
|
return NULL;
|
2006-06-22 23:06:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Convert attributes */
|
|
|
|
RtlInitUnicodeString(&UnicodeName, lpName);
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
|
|
&UnicodeName,
|
|
|
|
(bInheritHandle ? OBJ_INHERIT : 0),
|
2011-11-03 07:00:48 +00:00
|
|
|
BaseGetNamedObjectDirectory(),
|
2006-06-22 23:06:14 +00:00
|
|
|
NULL);
|
|
|
|
|
|
|
|
/* Convert COPY to READ */
|
2011-11-07 17:49:10 +00:00
|
|
|
if (dwDesiredAccess == FILE_MAP_COPY)
|
|
|
|
{
|
|
|
|
/* Fixup copy */
|
|
|
|
dwDesiredAccess = SECTION_MAP_READ;
|
|
|
|
}
|
|
|
|
else if (dwDesiredAccess & FILE_MAP_EXECUTE)
|
2011-11-07 15:43:37 +00:00
|
|
|
{
|
2011-11-07 17:49:10 +00:00
|
|
|
/* Fixup execute */
|
2011-11-07 15:43:37 +00:00
|
|
|
dwDesiredAccess = (dwDesiredAccess & ~FILE_MAP_EXECUTE) | SECTION_MAP_EXECUTE;
|
|
|
|
}
|
2006-06-22 23:06:14 +00:00
|
|
|
|
|
|
|
/* Open the section */
|
2012-04-25 10:17:29 +00:00
|
|
|
Status = NtOpenSection(&SectionHandle, dwDesiredAccess, &ObjectAttributes);
|
2006-06-22 23:06:14 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
/* We failed */
|
2011-07-23 18:54:29 +00:00
|
|
|
BaseSetLastNTError(Status);
|
2006-06-22 23:06:14 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
1999-09-27 20:58:46 +00:00
|
|
|
|
2006-06-22 23:06:14 +00:00
|
|
|
/* Otherwise, return the handle */
|
|
|
|
return SectionHandle;
|
|
|
|
}
|
2001-02-17 17:42:46 +00:00
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2006-06-22 23:06:14 +00:00
|
|
|
BOOL
|
|
|
|
NTAPI
|
2011-11-07 15:43:37 +00:00
|
|
|
FlushViewOfFile(IN LPCVOID lpBaseAddress,
|
|
|
|
IN SIZE_T dwNumberOfBytesToFlush)
|
1999-11-17 21:20:15 +00:00
|
|
|
{
|
2006-06-22 23:06:14 +00:00
|
|
|
NTSTATUS Status;
|
2013-08-22 18:25:02 +00:00
|
|
|
PVOID BaseAddress = (PVOID)lpBaseAddress;
|
|
|
|
SIZE_T NumberOfBytesToFlush = dwNumberOfBytesToFlush;
|
2008-05-21 16:10:00 +00:00
|
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
|
|
|
2006-06-22 23:06:14 +00:00
|
|
|
/* Flush the view */
|
|
|
|
Status = NtFlushVirtualMemory(NtCurrentProcess(),
|
2013-08-22 18:25:02 +00:00
|
|
|
&BaseAddress,
|
2008-05-21 16:10:00 +00:00
|
|
|
&NumberOfBytesToFlush,
|
|
|
|
&IoStatusBlock);
|
2011-11-07 15:43:37 +00:00
|
|
|
if (!NT_SUCCESS(Status) && (Status != STATUS_NOT_MAPPED_DATA))
|
2006-06-22 23:06:14 +00:00
|
|
|
{
|
|
|
|
/* We failed */
|
2011-07-23 18:54:29 +00:00
|
|
|
BaseSetLastNTError(Status);
|
2006-06-22 23:06:14 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Return success */
|
|
|
|
return TRUE;
|
1999-11-17 21:20:15 +00:00
|
|
|
}
|
|
|
|
|
1999-10-03 23:19:15 +00:00
|
|
|
/* EOF */
|