本文整理汇总了C++中NtAllocateVirtualMemory函数的典型用法代码示例。如果您正苦于以下问题:C++ NtAllocateVirtualMemory函数的具体用法?C++ NtAllocateVirtualMemory怎么用?C++ NtAllocateVirtualMemory使用的例子?那么恭喜您, 这里精选的函数代码示例或许可以为您提供帮助。
在下文中一共展示了NtAllocateVirtualMemory函数的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: AllocateGuarded
static
PVOID
AllocateGuarded(
_In_ SIZE_T SizeRequested)
{
NTSTATUS Status;
SIZE_T Size = PAGE_ROUND_UP(SizeRequested + PAGE_SIZE);
PVOID VirtualMemory = NULL;
PCHAR StartOfBuffer;
Status = NtAllocateVirtualMemory(NtCurrentProcess(), &VirtualMemory, 0, &Size, MEM_RESERVE, PAGE_NOACCESS);
if (!NT_SUCCESS(Status))
return NULL;
Size -= PAGE_SIZE;
if (Size)
{
Status = NtAllocateVirtualMemory(NtCurrentProcess(), &VirtualMemory, 0, &Size, MEM_COMMIT, PAGE_READWRITE);
if (!NT_SUCCESS(Status))
{
Size = 0;
Status = NtFreeVirtualMemory(NtCurrentProcess(), &VirtualMemory, &Size, MEM_RELEASE);
ok(Status == STATUS_SUCCESS, "Status = %lx\n", Status);
return NULL;
}
}
StartOfBuffer = VirtualMemory;
StartOfBuffer += Size - SizeRequested;
return StartOfBuffer;
}
示例2: test_commit_in_the_middle
// What happens if we commit an area in the middle of a reserved block?
// Does that affect how we can free it?
void test_commit_in_the_middle(void)
{
VOID *address, *a;
ULONG size;
NTSTATUS r;
HANDLE handle = (HANDLE) ~0;
// allocate 32 pages
address = NULL;
size = 0x30000;
r = NtAllocateVirtualMemory( handle, &address, 0, &size, MEM_RESERVE, PAGE_NOACCESS );
ok(r == STATUS_SUCCESS, "wrong return code\n");
ok(address != NULL, "address wrong\n");
ok(size == 0x30000, "size wrong\n");
a = address;
// split it into three bits
address = a + 0x10000;
size = 0x10000;
r = NtAllocateVirtualMemory( handle, &address, 0, &size, MEM_COMMIT, PAGE_READONLY );
ok(r == STATUS_SUCCESS, "wrong return code\n");
// now try free everything
address = a;
size = 0x30000;
r = NtFreeVirtualMemory( handle, &address, &size, MEM_RELEASE );
ok(r == STATUS_SUCCESS, "wrong return code\n");
}
示例3: test_separate_alloc_single_free
// What happens if we try to free two blocks
// that were allocated separately at the same time?
void test_separate_alloc_single_free(void)
{
VOID *address, *a;
ULONG size;
NTSTATUS r;
HANDLE handle = (HANDLE) ~0;
// allocate 32 pages
address = NULL;
size = 0x20000;
r = NtAllocateVirtualMemory( handle, &address, 0, &size, MEM_RESERVE, PAGE_NOACCESS );
ok(r == STATUS_SUCCESS, "wrong return code\n");
ok(address != NULL, "address wrong\n");
ok(size == 0x20000, "size wrong\n");
a = address;
// free all the memory again
address = a;
size = 0x20000;
r = NtFreeVirtualMemory( handle, &address, &size, MEM_RELEASE );
ok(r == STATUS_SUCCESS, "wrong return code\n");
// allocate again at the same address, but in two chunks
address = a;
size = 0x10000;
r = NtAllocateVirtualMemory( handle, &address, 0, &size, MEM_RESERVE, PAGE_NOACCESS );
ok(r == STATUS_SUCCESS, "wrong return code\n");
ok(address != NULL, "address wrong\n");
ok(size == 0x10000, "size wrong\n");
// allocate again at the same address, but in two chunks
address = a + 0x10000;
size = 0x10000;
r = NtAllocateVirtualMemory( handle, &address, 0, &size, MEM_RESERVE, PAGE_NOACCESS );
ok(r == STATUS_SUCCESS, "wrong return code\n");
ok(address != NULL, "address wrong\n");
ok(size == 0x10000, "size wrong\n");
// try free two separately allocated chunks in one go
address = a;
size = 0x20000;
r = NtFreeVirtualMemory( handle, &address, &size, MEM_RELEASE );
ok(r == STATUS_UNABLE_TO_FREE_VM, "wrong return code\n");
// that doesn't work... free it properly in two goes
address = a;
size = 0x10000;
r = NtFreeVirtualMemory( handle, &address, &size, MEM_RELEASE );
ok(r == STATUS_SUCCESS, "wrong return code\n");
address = a + 0x10000;
size = 0x10000;
r = NtFreeVirtualMemory( handle, &address, &size, MEM_RELEASE );
ok(r == STATUS_SUCCESS, "wrong return code\n");
}
示例4: test_split_and_join
// What happens if we split an area by freeing a piece of virtual memory in the middle of it?
// Does it rejoin itself when we reallocate the area in the middle?
void test_split_and_join(void)
{
VOID *address, *a;
ULONG size;
NTSTATUS r;
HANDLE handle = (HANDLE) ~0;
// allocate 32 pages
address = NULL;
size = 0x30000;
r = NtAllocateVirtualMemory( handle, &address, 0, &size, MEM_RESERVE, PAGE_NOACCESS );
ok(r == STATUS_SUCCESS, "wrong return code\n");
ok(address != NULL, "address wrong\n");
ok(size == 0x30000, "size wrong\n");
a = address;
// split it into three bits
address = a + 0x10000;
size = 0x10000;
r = NtFreeVirtualMemory( handle, &address, &size, MEM_RELEASE );
ok(r == STATUS_SUCCESS, "wrong return code\n");
// reallocate the bits we just removed
address = a + 0x10000;
size = 0x10000;
r = NtAllocateVirtualMemory( handle, &address, 0, &size, MEM_RESERVE, PAGE_NOACCESS );
ok(r == STATUS_SUCCESS, "wrong return code\n");
ok(address != NULL, "address wrong\n");
ok(size == 0x10000, "size wrong\n");
// now try free everything
address = a;
size = 0x30000;
r = NtFreeVirtualMemory( handle, &address, &size, MEM_RELEASE );
ok(r == STATUS_UNABLE_TO_FREE_VM, "wrong return code\n");
// now really free it
address = a;
size = 0x10000;
r = NtFreeVirtualMemory( handle, &address, &size, MEM_RELEASE );
ok(r == STATUS_SUCCESS, "wrong return code\n");
address = a + 0x10000;
size = 0x10000;
r = NtFreeVirtualMemory( handle, &address, &size, MEM_RELEASE );
ok(r == STATUS_SUCCESS, "wrong return code\n");
address = a + 0x20000;
size = 0x10000;
r = NtFreeVirtualMemory( handle, &address, &size, MEM_RELEASE );
ok(r == STATUS_SUCCESS, "wrong return code\n");
}
示例5: test_chunksize
// The granulatiry of memory allocations on NT seems to be 0x10000 or 16 x 4k pages.
// The size is rounded to multiples of pages size.
// So what happens when we try to allocate memory at an address that is not
// a multiple of 0x10000? What happens if a chunk of memory in that set of 16 pages
// is already allocated? What happens if it's not already allocated?
void test_chunksize( void )
{
VOID *address[2];
ULONG size;
NTSTATUS r;
HANDLE handle = (HANDLE) ~0;
address[0] = NULL;
size = 0x1000;
r = NtAllocateVirtualMemory( handle, &address[0], 0, &size, MEM_RESERVE, PAGE_NOACCESS );
ok(r == STATUS_SUCCESS, "wrong return code\n");
ok(address[0] != NULL, "address wrong\n");
ok(size == 0x1000, "size wrong\n");
// try allocate memory one page after the previous allocation.
address[1] = address[0] + 0x1000;
size = 0x1000;
r = NtAllocateVirtualMemory( handle, &address[1], 0, &size, MEM_RESERVE, PAGE_NOACCESS );
ok(r == STATUS_CONFLICTING_ADDRESSES, "wrong return code (%08lx)\n", r);
ok(address[1] == address[0] + 0x1000, "address wrong\n");
ok(size == 0x1000, "size wrong\n");
// free the memory... assume nobody else grabs it (ie. there's no other threads)
r = NtFreeVirtualMemory( handle, &address[0], &size, MEM_RELEASE );
ok(r == STATUS_SUCCESS, "wrong return code\n");
ok(size == 0x1000, "size wrong\n");
// try allocate memory one page after the previous (free'd) allocation
r = NtAllocateVirtualMemory( handle, &address[1], 0, &size, MEM_RESERVE, PAGE_NOACCESS );
ok(r == STATUS_SUCCESS, "wrong return code (%08lx)\n", r);
ok(address[1] == address[0], "address wrong\n");
ok(size == 0x2000, "size wrong\n");
// free what we allocated
address[1] = address[0] + 0x1000;
size = 0x1000;
r = NtFreeVirtualMemory( handle, &address[1], &size, MEM_RELEASE );
ok(r == STATUS_SUCCESS, "wrong return code\n");
ok(address[1] == address[0] + 0x1000, "address wrong\n");
ok(size == 0x1000, "size wrong\n");
// free what we didn't allocate...
address[1] = address[0];
size = 0x1000;
r = NtFreeVirtualMemory( handle, &address[1], &size, MEM_RELEASE );
ok(r == STATUS_SUCCESS, "wrong return code\n");
ok(address[1] == address[0], "address wrong\n");
ok(size == 0x1000, "size wrong\n");
}
示例6: NtQueryVirtualMemory
UINT_PTR SectionRelayBuffer::RegisterSection(UINT_PTR section)
{
UINT_PTR i;
UINT_PTR base=(UINT_PTR)(section)>>31;
for (i=0;i<section_count;i++)
if (record[i].section_register==base) break;
if (i<section_count)
{
record[i].section_referenced++;
return record[i].section_relay_buffer;
}
UINT_PTR addr=(base<<31)+0x40000000;
UINT_PTR size=0x1000,len;
LPVOID allocate;
MEMORY_BASIC_INFORMATION info;
allocate=(LPVOID)addr;
for (;;)
{
allocate=(LPVOID)addr;
NtQueryVirtualMemory(NtCurrentProcess(),allocate,
MemoryBasicInformation,&info,sizeof(info),&len);
if ((info.State&MEM_FREE))
if ((UINT_PTR)info.BaseAddress+info.RegionSize-addr>=0x1000)
break;
addr=(UINT_PTR)info.BaseAddress-0x1000;
}
NtAllocateVirtualMemory(NtCurrentProcess(),&allocate,
0,&size,MEM_COMMIT|MEM_RESERVE,PAGE_EXECUTE_READWRITE);
addr=(UINT_PTR)allocate;
record[section_count].section_register=section>>31;
record[section_count].section_relay_buffer=addr;
record[section_count].section_referenced=1;
section_count++;
return addr;
}
示例7: test_open_process_param_size
void test_open_process_param_size( void )
{
NTSTATUS r;
PVOID p = 0;
PCLIENT_ID id;
ULONG sz = 0x1000;
OBJECT_ATTRIBUTES oa;
HANDLE handle = 0, dummy = (void*) 1;
r = NtAllocateVirtualMemory(NtCurrentProcess(), &p, 0, &sz, MEM_COMMIT, PAGE_READWRITE);
ok( r == STATUS_SUCCESS, "wrong return %08lx\n", r );
memset( &oa, 0, sizeof oa );
id = (p + sz - 4);
id->UniqueProcess = dummy;
r = NtOpenProcess( &handle, 0, &oa, id );
ok( r == STATUS_ACCESS_VIOLATION, "wrong return %08lx\n", r );
id = (p + sz - 8);
id->UniqueProcess = dummy;
id->UniqueThread = dummy;
r = NtOpenProcess( &handle, 0, &oa, id );
ok( r == STATUS_INVALID_CID, "wrong return %08lx\n", r );
r = NtFreeVirtualMemory(NtCurrentProcess(), &p, &sz, MEM_RELEASE );
ok( r == STATUS_SUCCESS, "wrong return %08lx\n", r );
}
示例8: AcquireLMCredentials
NTSTATUS
AcquireLMCredentials (
VOID
)
{
UNICODE_STRING Ntlm;
PUCHAR AllocateMemory = NULL;
ULONG AllocateLength = 8;
NTSTATUS status;
TimeStamp Expiry;
status = NtAllocateVirtualMemory(
NtCurrentProcess(),
&AllocateMemory,
0,
&AllocateLength,
MEM_COMMIT,
PAGE_READWRITE
);
if ( !NT_SUCCESS(status) ) {
return status;
}
Ntlm.Length = Ntlm.MaximumLength = 8;
Ntlm.Buffer = (LPWSTR)AllocateMemory,
RtlCopyMemory( Ntlm.Buffer, L"NTLM", 8 );
status = AcquireCredentialsHandle(
NULL, // Default principal
(PSECURITY_STRING) &Ntlm,
SECPKG_CRED_INBOUND, // Need to define this
NULL, // No LUID
NULL, // No AuthData
NULL, // No GetKeyFn
NULL, // No GetKeyArg
&SrvLmLsaHandle,
&Expiry
);
(VOID)NtFreeVirtualMemory(
NtCurrentProcess(),
&AllocateMemory,
&AllocateLength,
MEM_DECOMMIT
);
if ( !NT_SUCCESS(status) ) {
status = MapSecurityError(status);
return status;
}
SrvHaveCreds |= HAVENTLM;
return status;
} // AcquireLMCredentials
示例9: misc_AllocBuffer
// alloc buffer ...
LPVOID misc_AllocBuffer(DWORD dwSize)
{
LPVOID lpBuffer=NULL;
DWORD dwLen=dwSize;
if (NT_SUCCESS(NtAllocateVirtualMemory(NtCurrentProcess(),&lpBuffer,0,&dwLen,MEM_COMMIT|MEM_TOP_DOWN,PAGE_READWRITE)))
return lpBuffer;
return NULL;
}
示例10: test_free_mem
void test_free_mem( void )
{
VOID *address, *a;
ULONG size;
NTSTATUS r;
HANDLE handle = (HANDLE) ~0;
// allocate 16 pages
address = NULL;
size = 0x10000;
r = NtAllocateVirtualMemory( handle, &address, 0, &size, MEM_RESERVE, PAGE_NOACCESS );
ok(r == STATUS_SUCCESS, "wrong return code\n");
ok(address != NULL, "address wrong\n");
ok(size == 0x10000, "size wrong\n");
a = address;
// free half of the memory we committed
address = a;
size = 0x8000;
r = NtFreeVirtualMemory( handle, &address, &size, MEM_RELEASE );
ok(r == STATUS_SUCCESS, "wrong return code\n");
ok(size == 0x8000, "size wrong\n");
// try free memory across a block boundary
address = a + 0xc000;
size = 0x10000;
r = NtFreeVirtualMemory( handle, &address, &size, MEM_RELEASE );
ok(r == STATUS_UNABLE_TO_FREE_VM, "wrong return code (%08lx)\n", r);
ok(size == 0x10000, "size wrong\n");
// try free all the memory again
address = a;
size = 0x10000;
r = NtFreeVirtualMemory( handle, &address, &size, MEM_RELEASE );
ok(r == STATUS_MEMORY_NOT_ALLOCATED, "wrong return code\n");
// free the last 4 pages
address = a + 0xc000;
size = 0x4000;
r = NtFreeVirtualMemory( handle, &address, &size, MEM_RELEASE );
ok(r == STATUS_SUCCESS, "wrong return code\n");
// free the last 4 pages again... should fail
address = a + 0xc000;
size = 0x4000;
r = NtFreeVirtualMemory( handle, &address, &size, MEM_RELEASE );
ok(r == STATUS_MEMORY_NOT_ALLOCATED, "wrong return code\n");
ok(size == 0x4000, "size wrong\n");
// free the rest
address = a + 0x8000;
size = 0x4000;
r = NtFreeVirtualMemory( handle, &address, &size, MEM_RELEASE );
ok(r == STATUS_SUCCESS, "wrong return code\n");
}
示例11: GetProcAddr
LPVOID GetProcAddr(HANDLE hProc)
{
AcquireLock();
DWORD pid,addr,len;
if (hProc==NtCurrentProcess()) pid=current_process_id;
else
{
PROCESS_BASIC_INFORMATION info;
NtQueryInformationProcess(hProc,ProcessBasicInformation,&info,sizeof(info),&len);
pid=info.uUniqueProcessId;
}
pid>>=2;
for (UINT_PTR i=0;i<count;i++)
{
if ((proc_record[i]&0xFFF)==pid)
{
addr=proc_record[i]&~0xFFF;
ReleaseLock();
return (LPVOID)addr;
}
}
len=0x1000;
NtAllocateVirtualMemory(hProc,(PVOID*)(proc_record+count),0,&len,
MEM_COMMIT,PAGE_EXECUTE_READWRITE);
DWORD base = proc_record[count];
proc_record[count] |= pid;
union
{
LPVOID buffer;
DWORD b;
};
b = base;
LPVOID fun_table[3];
*(DWORD*)(normal_routine + ADDR0) += base;
NtWriteVirtualMemory(hProc, buffer, normal_routine, 0x14, 0);
*(DWORD*)(normal_routine + ADDR0) -= base;
b += 0x14;
fun_table[0] = NtTerminateThread;
fun_table[1] = NtQueryVirtualMemory;
fun_table[2] = MessageBoxW;
NtWriteVirtualMemory(hProc, buffer, fun_table, 0xC, 0);
b += 0xC;
*(DWORD*)(except_routine + ADDR1) += base;
*(DWORD*)(except_routine + ADDR2) += base;
*(DWORD*)(except_routine + ADDR3) += base;
NtWriteVirtualMemory(hProc, buffer, except_routine, 0xE0, 0);
*(DWORD*)(except_routine + ADDR1) -= base;
*(DWORD*)(except_routine + ADDR2) -= base;
*(DWORD*)(except_routine + ADDR3) -= base;
count++;
ReleaseLock();
return (LPVOID)base;
}
示例12: Inject
DWORD Inject(HANDLE hProc, LPWSTR engine)
{
LPVOID lpvAllocAddr = 0;
DWORD dwWrite = 0x1000, len = 0;
HANDLE hTH;
WCHAR path[MAX_PATH];
LPWSTR p;
if (!IthCheckFile(DllName)) return -1;
p = GetMainModulePath();
len = wcslen(p);
memcpy(path, p, len << 1);
memset(path + len, 0, (MAX_PATH - len) << 1);
for (p = path + len; *p != L'\\'; p--); //Always a \ after drive letter.
p++;
wcscpy(p, DllName);
NtAllocateVirtualMemory(hProc, &lpvAllocAddr, 0, &dwWrite, MEM_COMMIT, PAGE_READWRITE);
if (lpvAllocAddr == 0) return -1;
CheckThreadStart();
//Copy module path into address space of target process.
NtWriteVirtualMemory(hProc, lpvAllocAddr, path, MAX_PATH << 1, &dwWrite);
hTH = IthCreateThread(LoadLibrary, (DWORD)lpvAllocAddr, hProc);
if (hTH == 0 || hTH == INVALID_HANDLE_VALUE)
{
ConsoleOutput(ErrorRemoteThread);
return -1;
}
NtWaitForSingleObject(hTH, 0, 0);
THREAD_BASIC_INFORMATION info;
NtQueryInformationThread(hTH, ThreadBasicInformation, &info, sizeof(info), &dwWrite);
NtClose(hTH);
if (info.ExitStatus != 0)
{
wcscpy(p, engine);
NtWriteVirtualMemory(hProc, lpvAllocAddr, path, MAX_PATH << 1, &dwWrite);
hTH = IthCreateThread(LoadLibrary, (DWORD)lpvAllocAddr, hProc);
if (hTH == 0 || hTH == INVALID_HANDLE_VALUE)
{
ConsoleOutput(ErrorRemoteThread);
return -1;
}
NtWaitForSingleObject(hTH, 0, 0);
NtClose(hTH);
}
dwWrite = 0;
NtFreeVirtualMemory(hProc, &lpvAllocAddr, &dwWrite, MEM_RELEASE);
return info.ExitStatus;
}
示例13: VirtualAllocEx
/***********************************************************************
* VirtualAllocEx ([email protected])
*
* Seems to be just as VirtualAlloc, but with process handle.
*
* PARAMS
* hProcess [I] Handle to process to do mem operation.
* addr [I] Address of region to reserve or commit.
* size [I] Size of region.
* type [I] Type of allocation.
* protect [I] Type of access protection.
*
*
* RETURNS
* Success: Base address of allocated region of pages.
* Failure: NULL.
*/
LPVOID WINAPI VirtualAllocEx( HANDLE hProcess, LPVOID addr, SIZE_T size,
DWORD type, DWORD protect )
{
LPVOID ret = addr;
NTSTATUS status;
if ((status = NtAllocateVirtualMemory( hProcess, &ret, 0, &size, type, protect )))
{
SetLastError( RtlNtStatusToDosError(status) );
ret = NULL;
}
return ret;
}
示例14: read_file
/* return 1 on success, 0 on nonexistent file, -1 on other error */
static int read_file( const char *name, void **data, SIZE_T *size )
{
struct stat st;
int fd, ret = -1;
size_t header_size;
IMAGE_DOS_HEADER *dos;
IMAGE_NT_HEADERS *nt;
const size_t min_size = sizeof(*dos) + sizeof(fakedll_signature) +
FIELD_OFFSET( IMAGE_NT_HEADERS, OptionalHeader.MajorLinkerVersion );
if ((fd = open( name, O_RDONLY | O_BINARY )) == -1) return 0;
if (fstat( fd, &st ) == -1) goto done;
*size = st.st_size;
if (!file_buffer || st.st_size > file_buffer_size)
{
VirtualFree( file_buffer, 0, MEM_RELEASE );
file_buffer = NULL;
file_buffer_size = st.st_size;
if (NtAllocateVirtualMemory( GetCurrentProcess(), &file_buffer, 0, &file_buffer_size,
MEM_COMMIT, PAGE_READWRITE )) goto done;
}
/* check for valid fake dll file */
if (st.st_size < min_size) goto done;
header_size = min( st.st_size, 4096 );
if (pread( fd, file_buffer, header_size, 0 ) != header_size) goto done;
dos = file_buffer;
if (dos->e_magic != IMAGE_DOS_SIGNATURE) goto done;
if (dos->e_lfanew < sizeof(fakedll_signature)) goto done;
if (memcmp( dos + 1, fakedll_signature, sizeof(fakedll_signature) )) goto done;
if (dos->e_lfanew + FIELD_OFFSET(IMAGE_NT_HEADERS,OptionalHeader.MajorLinkerVersion) > header_size)
goto done;
nt = (IMAGE_NT_HEADERS *)((char *)file_buffer + dos->e_lfanew);
if (nt->Signature == IMAGE_NT_SIGNATURE && nt->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR_MAGIC)
{
/* wrong 32/64 type, pretend it doesn't exist */
ret = 0;
goto done;
}
if (st.st_size == header_size ||
pread( fd, (char *)file_buffer + header_size,
st.st_size - header_size, header_size ) == st.st_size - header_size)
{
*data = file_buffer;
ret = 1;
}
done:
close( fd );
return ret;
}
示例15: RtlCreateEnvironment
/******************************************************************************
* RtlCreateEnvironment [[email protected]]
*/
NTSTATUS WINAPI RtlCreateEnvironment(BOOLEAN inherit, PWSTR* env)
{
NTSTATUS nts;
TRACE("(%u,%p)!\n", inherit, env);
if (inherit)
{
MEMORY_BASIC_INFORMATION mbi;
RtlAcquirePebLock();
nts = NtQueryVirtualMemory(NtCurrentProcess(),
NtCurrentTeb()->Peb->ProcessParameters->Environment,
0, &mbi, sizeof(mbi), NULL);
if (nts == STATUS_SUCCESS)
{
*env = NULL;
nts = NtAllocateVirtualMemory(NtCurrentProcess(), (void**)env, 0, &mbi.RegionSize,
MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
if (nts == STATUS_SUCCESS)
memcpy(*env, NtCurrentTeb()->Peb->ProcessParameters->Environment, mbi.RegionSize);
else *env = NULL;
}
RtlReleasePebLock();
}
else
{
SIZE_T size = 1;
PVOID addr = NULL;
nts = NtAllocateVirtualMemory(NtCurrentProcess(), &addr, 0, &size,
MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
if (nts == STATUS_SUCCESS) *env = addr;
}
return nts;
}