Решение зависит от того, поддерживается ли объект сопоставления файлов файлом подкачки операционной системы (параметр hFile INVALID_HANDLE_VALUE
) или каким-либо файлом на диске.
В этом случае вы используетеобъект сопоставления файлов поддерживается файлом подкачки операционной системы, необходимо использовать флаг SEC_RESERVE
:
указывает, что при просмотре файлаотображается в адресное пространство процесса, весь диапазон страниц зарезервирован для последующего использования процессом, а не зафиксирован.Зарезервированные страницы могут быть зафиксированы для последующих вызовов функции VirtualAlloc .После фиксации страниц они не могут быть освобождены или распакованы с помощью функции VirtualFree .
Код может выглядеть следующим образом:
#define MAX_FILE_SIZE 0x10000000
void ExtendInMemorySection()
{
if (HANDLE hSection = CreateFileMapping(INVALID_HANDLE_VALUE, 0,
PAGE_READWRITE|SEC_RESERVE, 0, MAX_FILE_SIZE, NULL))
{
PVOID pv = MapViewOfFile(hSection, FILE_MAP_WRITE, 0, 0, 0);
CloseHandle(hSection);
if (pv)
{
SYSTEM_INFO info;
GetSystemInfo(&info);
PBYTE pb = (PBYTE)pv;
int n = MAX_FILE_SIZE / info.dwPageSize;
do
{
if (!VirtualAlloc(pb, info.dwPageSize, MEM_COMMIT, PAGE_READWRITE))
{
break;
}
pb += info.dwPageSize;
} while (--n);
UnmapViewOfFile(pv);
}
}
}
Но из SEC_RESERVE
Этот атрибут не влияет на объекты сопоставления файлов, которые поддерживаются исполняемыми файлами изображений или файлами данных (параметр hfile является дескриптором файла).
Для этого (и только для этого) случая существует недокументированный API:
NTSYSCALLAPI
NTSTATUS
NTAPI
NtExtendSection(
_In_ HANDLE SectionHandle,
_Inout_ PLARGE_INTEGER NewSectionSize
);
Этот API позволяет увеличить размер раздела (и файла резервной копии).Кроме того, SectionHandle
должно иметь право доступа SECTION_EXTEND_SIZE
в этом случае, но CreateFileMapping
создает дескриптор раздела без этого доступа.Поэтому нам нужно использовать только NtCreateSection
здесь, тогда нам нужно использовать ZwMapViewOfSection
API с AllocationType = MEM_RESERVE
и ViewSize = MAX_FILE_SIZE
- это резервный ViewSize
регион памяти, но не коммитэто, но после вызова NtExtendSection
действительные данные (страницы фиксации) будут автоматически расширены.До win 8.1, MapViewOfFile
не такой функционал для типа размещения pass MEM_RESERVE
для ZwMapViewOfSection
, но начиная с win 8 (или 8.1) существует недокументированный флаг FILE_MAP_RESERVE
, который позволяет это делать.
В общем случае демонстрационный код может выглядеть следующим образом:
#define MAX_FILE_SIZE 0x10000000
void ExtendFileSection()
{
HANDLE hFile = CreateFile(L"d:/ee.tmp", GENERIC_ALL, 0, 0, CREATE_ALWAYS, 0, 0);
if (hFile != INVALID_HANDLE_VALUE)
{
HANDLE hSection;
SYSTEM_INFO info;
GetSystemInfo(&info);
// initially only 1 page in the file
LARGE_INTEGER SectionSize = { info.dwPageSize };
NTSTATUS status = NtCreateSection(&hSection,
SECTION_EXTEND_SIZE|SECTION_MAP_READ|SECTION_MAP_WRITE, 0,
&SectionSize, PAGE_READWRITE, SEC_COMMIT, hFile);
CloseHandle(hFile);
if (0 <= status)
{
PVOID BaseAddress = 0;
SIZE_T ViewSize = MAX_FILE_SIZE;
//MapViewOfFile(hSection, FILE_MAP_WRITE|FILE_MAP_RESERVE, 0, 0, MAX_FILE_SIZE);
status = ZwMapViewOfSection(hSection, NtCurrentProcess(), &BaseAddress, 0, 0, 0,
&ViewSize, ViewUnmap, MEM_RESERVE, PAGE_READWRITE);
if (0 <= status)
{
SIZE_T n = MAX_FILE_SIZE / info.dwPageSize - 1;
do
{
SectionSize.QuadPart += info.dwPageSize;
if (0 > NtExtendSection(hSection, &SectionSize))
{
break;
}
} while (--n);
UnmapViewOfFile(BaseAddress);
}
CloseHandle(hSection);
}
}
}