Reputation: 704
How i can add new info to memory mapped file ? Using a pointer I can work with existing data, but only within their current size. Is it so ? For example:
void DemoFileMapping()
{
HANDLE hFile = CreateFile("1.txt", GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
DWORD d;
char * str = "ABCDEFG";
WriteFile(hFile, str, strlen(str), &d, 0);
HANDLE mapping = CreateFileMapping(hFile, 0, PAGE_READWRITE, 0, 0, 0);
if (mapping)
{
unsigned char * buf = (unsigned char *)MapViewOfFile(mapping, FILE_MAP_ALL_ACCESS, 0, 0, 0);
if (buf)
{
buf[2] = 'Z'; // it works!
UnmapViewOfFile(buf);
}
CloseHandle(mapping);
}
CloseHandle(hFile);
}
But how can I add new information to the current one? For example, extend the string to "ABCDEFGHIJK"? I would like to have solutions without a banal backup of a larger area than the file size.
Upvotes: 1
Views: 1357
Reputation: 33706
if I correct understand your question - you ask - are possible extend section (memory mapped file) after it was created. Yes. but for this need use ntdll api.
CreateFileMapping
this is restricted shell over ZwCreateSection
. if you look for it second parameter - DesiredAccess [in] - you can note next access flag:
SECTION_EXTEND_SIZE - Dynamically extend the size of the section.
Speaks for itself. but however MSDN not explain how extend the size of the section. for this exist next api - ZwExtendSection
but on current time it not documented at all (but it present and worked how minimum from win2000 up to latest win 10). what sense document flag SECTION_EXTEND_SIZE
without document ZwExtendSection
I don't understand. also in documentation from ZwCreateSection
- MaximumSize [in, optional] - the name of parameter is not correct. this is faster Initial section size, but not Maximum - because we can extend section.
also about ZwExtendSection
- it extend section to NewSectionSize (if it more then current section size - otherwise call will be have no effect) rounds this value up to the nearest multiple of PAGE_SIZE and if section based on file - it extend file too, and NewSectionSize will be new file size - exactly byte to byte. file size will be not rounded to PAGE_SIZE
but if section already mapped at some BaseAddress - are view of section will be also automatically extended ? this depended from how map view of section. if by call MapViewOfFile(mapping, FILE_MAP_ALL_ACCESS, 0, 0, 0);
no. so you will be need unmap and then map section again after extend.
but is you will be use ZwMapViewOfSection
with AllocationType [in] == MEM_RESERVE in this and only in this case ViewSize can be bigger than current section size (without MEM_RESERVE
flag you got error if ViewSize bigger than current section size) - in this case system reserves ViewSize of the process's virtual address space but commit only current section size (may be little more pages). and when you call NtExtendSection
- the committed view size will be extended up to NewSectionSize. this is similar when we first call VirtualAlloc
with big ViewSize and MEM_RESERVE
for reserve process's virtual address space without allocating any actual physical storage in memory and than again call VirtualAlloc
with NewSectionSize and MEM_COMMIT
flag. even not similar but exactly, only indirect.
before win8.1 no alternative for call ZwMapViewOfSection
if we want use MEM_RESERVE
flag, but from 8.1 we can use for this MapViewOfFile
too with flag FILE_MAP_RESERVE
. it declared in memoryapi.h
from SDK as
#define FILE_MAP_RESERVE 0x80000000
but by unknown reason not documented in MSDN. I check this flag - it worked (how I say from win 8.1 only)
demo/test program can be next:
void DemoFileMapping()
{
HANDLE hFile = CreateFile(L"1.txt", GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
if (hFile != INVALID_HANDLE_VALUE)
{
HANDLE hSection;
// set for demo intial size of section to 2 byte
// NtCreateSection rounds this value up to the nearest multiple of PAGE_SIZE.
// however this will be have effect for file size exactly, if current file size less than this value
LARGE_INTEGER InitialSize = { 2 };
NTSTATUS status = NtCreateSection(&hSection,
SECTION_MAP_WRITE|SECTION_MAP_READ|SECTION_EXTEND_SIZE, 0, &InitialSize,
PAGE_READWRITE, SEC_COMMIT, hFile);
//we can close file handle now
CloseHandle(hFile);
if (0 <= status)
{
PVOID BaseAddress = 0;
SIZE_T ViewSize = 0x1000000;//reserve 16 Mb memory for example
// BaseAddress = MapViewOfFile(hSection, FILE_MAP_RESERVE|FILE_MAP_READ|FILE_MAP_WRITE, 0, 0, ViewSize);
// note MEM_RESERVE
if (0 <= ZwMapViewOfSection(hSection, NtCurrentProcess(), &BaseAddress, 0, 0, 0,
&ViewSize, ViewUnmap, MEM_RESERVE, PAGE_READWRITE))
{
LARGE_INTEGER NewSize = { 0x20001 };// some random new size (128k+1 byte)
// this call extend file, section and view size
if (0 <= ZwExtendSection(hSection, &NewSize))
{
memset(BaseAddress, '*', NewSize.LowPart);
}
UnmapViewOfFile(BaseAddress);
}
CloseHandle(hSection);
}
}
}
Upvotes: 6