ntdll: Implementation of inter-process NtMapViewOfSection and NtUnmapViewOfSection.
This commit is contained in:
parent
8025f79ce1
commit
02e2fa7798
|
@ -403,7 +403,66 @@ static void test_MapViewOfFile(void)
|
|||
GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %d\n", GetLastError() );
|
||||
|
||||
CloseHandle( file );
|
||||
DeleteFileA( testfile );
|
||||
}
|
||||
|
||||
static DWORD (WINAPI *pNtMapViewOfSection)( HANDLE handle, HANDLE process, PVOID *addr_ptr,
|
||||
ULONG zero_bits, SIZE_T commit_size,
|
||||
const LARGE_INTEGER *offset_ptr, SIZE_T *size_ptr,
|
||||
ULONG inherit, ULONG alloc_type, ULONG protect );
|
||||
static DWORD (WINAPI *pNtUnmapViewOfSection)( HANDLE process, PVOID addr );
|
||||
|
||||
static void test_NtMapViewOfSection(void)
|
||||
{
|
||||
HANDLE hProcess;
|
||||
|
||||
static const char testfile[] = "testfile.xxx";
|
||||
static const char data[] = "test data for NtMapViewOfSection";
|
||||
char buffer[sizeof(data)];
|
||||
HANDLE file, mapping;
|
||||
void *ptr;
|
||||
BOOL ret;
|
||||
DWORD status, written;
|
||||
SIZE_T size, result;
|
||||
LARGE_INTEGER offset;
|
||||
|
||||
pNtMapViewOfSection = (void *)GetProcAddress( GetModuleHandle("ntdll.dll"), "NtMapViewOfSection" );
|
||||
pNtUnmapViewOfSection = (void *)GetProcAddress( GetModuleHandle("ntdll.dll"), "NtUnmapViewOfSection" );
|
||||
if (!pNtMapViewOfSection || !pNtUnmapViewOfSection)
|
||||
{
|
||||
skip( "NtMapViewOfSection not found\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
file = CreateFileA( testfile, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0 );
|
||||
ok( file != INVALID_HANDLE_VALUE, "Failed to create test file\n" );
|
||||
WriteFile( file, data, sizeof(data), &written, NULL );
|
||||
SetFilePointer( file, 4096, NULL, FILE_BEGIN );
|
||||
SetEndOfFile( file );
|
||||
|
||||
/* read/write mapping */
|
||||
|
||||
mapping = CreateFileMappingA( file, NULL, PAGE_READWRITE, 0, 4096, NULL );
|
||||
ok( mapping != 0, "CreateFileMapping failed\n" );
|
||||
|
||||
hProcess = create_target_process("sleep");
|
||||
ok(hProcess != NULL, "Can't start process\n");
|
||||
|
||||
ptr = NULL;
|
||||
size = 0;
|
||||
offset.QuadPart = 0;
|
||||
status = pNtMapViewOfSection( mapping, hProcess, &ptr, 0, 0, &offset, &size, 1, 0, PAGE_READWRITE );
|
||||
ok( !status, "NtMapViewOfSection failed status %x\n", status );
|
||||
|
||||
ret = ReadProcessMemory( hProcess, ptr, buffer, sizeof(buffer), &result );
|
||||
ok( ret, "ReadProcessMemory failed\n" );
|
||||
ok( result == sizeof(buffer), "ReadProcessMemory didn't read all data (%lx)\n", result );
|
||||
ok( !memcmp( buffer, data, sizeof(buffer) ), "Wrong data read\n" );
|
||||
|
||||
status = pNtUnmapViewOfSection( hProcess, ptr );
|
||||
ok( !status, "NtUnmapViewOfSection failed status %x\n", status );
|
||||
|
||||
CloseHandle( mapping );
|
||||
CloseHandle( file );
|
||||
DeleteFileA( testfile );
|
||||
}
|
||||
|
@ -439,4 +498,5 @@ START_TEST(virtual)
|
|||
test_VirtualAllocEx();
|
||||
test_VirtualAlloc();
|
||||
test_MapViewOfFile();
|
||||
test_NtMapViewOfSection();
|
||||
}
|
||||
|
|
|
@ -780,6 +780,26 @@ static BOOL call_apcs( BOOL alertable )
|
|||
&result.virtual_unlock.addr,
|
||||
&result.virtual_unlock.size, 0 );
|
||||
break;
|
||||
case APC_MAP_VIEW:
|
||||
{
|
||||
LARGE_INTEGER offset;
|
||||
result.type = call.type;
|
||||
result.map_view.addr = call.map_view.addr;
|
||||
result.map_view.size = call.map_view.size;
|
||||
offset.u.LowPart = call.map_view.offset_low;
|
||||
offset.u.HighPart = call.map_view.offset_high;
|
||||
result.map_view.status = NtMapViewOfSection( call.map_view.handle, NtCurrentProcess(),
|
||||
&result.map_view.addr, call.map_view.zero_bits,
|
||||
0, &offset, &result.map_view.size, ViewShare,
|
||||
call.map_view.alloc_type, call.map_view.prot );
|
||||
NtClose( call.map_view.handle );
|
||||
break;
|
||||
}
|
||||
case APC_UNMAP_VIEW:
|
||||
result.type = call.type;
|
||||
result.unmap_view.status = NtUnmapViewOfSection( NtCurrentProcess(),
|
||||
call.unmap_view.addr );
|
||||
break;
|
||||
case APC_CREATE_THREAD:
|
||||
{
|
||||
CLIENT_ID id;
|
||||
|
|
|
@ -1960,17 +1960,36 @@ NTSTATUS WINAPI NtMapViewOfSection( HANDLE handle, HANDLE process, PVOID *addr_p
|
|||
TRACE("handle=%p process=%p addr=%p off=%x%08x size=%lx access=%x\n",
|
||||
handle, process, *addr_ptr, offset.u.HighPart, offset.u.LowPart, size, protect );
|
||||
|
||||
if (!is_current_process( process ))
|
||||
{
|
||||
ERR("Unsupported on other process\n");
|
||||
return STATUS_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
/* Check parameters */
|
||||
|
||||
if ((offset.u.LowPart & mask) || (*addr_ptr && ((UINT_PTR)*addr_ptr & mask)))
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
if (process != NtCurrentProcess())
|
||||
{
|
||||
apc_call_t call;
|
||||
apc_result_t result;
|
||||
|
||||
call.map_view.type = APC_MAP_VIEW;
|
||||
call.map_view.handle = handle;
|
||||
call.map_view.addr = *addr_ptr;
|
||||
call.map_view.size = *size_ptr;
|
||||
call.map_view.offset_low = offset.u.LowPart;
|
||||
call.map_view.offset_high = offset.u.HighPart;
|
||||
call.map_view.zero_bits = zero_bits;
|
||||
call.map_view.alloc_type = alloc_type;
|
||||
call.map_view.prot = protect;
|
||||
res = NTDLL_queue_process_apc( process, &call, &result );
|
||||
if (res != STATUS_SUCCESS) return res;
|
||||
|
||||
if (result.map_view.status == STATUS_SUCCESS)
|
||||
{
|
||||
*addr_ptr = result.map_view.addr;
|
||||
*size_ptr = result.map_view.size;
|
||||
}
|
||||
return result.map_view.status;
|
||||
}
|
||||
|
||||
SERVER_START_REQ( get_mapping_info )
|
||||
{
|
||||
req->handle = handle;
|
||||
|
@ -2107,11 +2126,18 @@ NTSTATUS WINAPI NtUnmapViewOfSection( HANDLE process, PVOID addr )
|
|||
sigset_t sigset;
|
||||
void *base = ROUND_ADDR( addr, page_mask );
|
||||
|
||||
if (!is_current_process( process ))
|
||||
if (process != NtCurrentProcess())
|
||||
{
|
||||
ERR("Unsupported on other process\n");
|
||||
return STATUS_ACCESS_DENIED;
|
||||
apc_call_t call;
|
||||
apc_result_t result;
|
||||
|
||||
call.unmap_view.type = APC_UNMAP_VIEW;
|
||||
call.unmap_view.addr = addr;
|
||||
status = NTDLL_queue_process_apc( process, &call, &result );
|
||||
if (status == STATUS_SUCCESS) status = result.unmap_view.status;
|
||||
return status;
|
||||
}
|
||||
|
||||
server_enter_uninterrupted_section( &csVirtual, &sigset );
|
||||
if ((view = VIRTUAL_FindView( base )) && (base == view->base))
|
||||
{
|
||||
|
|
|
@ -222,6 +222,8 @@ enum apc_type
|
|||
APC_VIRTUAL_FLUSH,
|
||||
APC_VIRTUAL_LOCK,
|
||||
APC_VIRTUAL_UNLOCK,
|
||||
APC_MAP_VIEW,
|
||||
APC_UNMAP_VIEW,
|
||||
APC_CREATE_THREAD
|
||||
};
|
||||
|
||||
|
@ -296,6 +298,23 @@ typedef union
|
|||
unsigned long size;
|
||||
} virtual_unlock;
|
||||
struct
|
||||
{
|
||||
enum apc_type type;
|
||||
obj_handle_t handle;
|
||||
void *addr;
|
||||
unsigned long size;
|
||||
unsigned int offset_low;
|
||||
unsigned int offset_high;
|
||||
unsigned int zero_bits;
|
||||
unsigned int alloc_type;
|
||||
unsigned int prot;
|
||||
} map_view;
|
||||
struct
|
||||
{
|
||||
enum apc_type type;
|
||||
void *addr;
|
||||
} unmap_view;
|
||||
struct
|
||||
{
|
||||
enum apc_type type;
|
||||
void (__stdcall *func)(void*);
|
||||
|
@ -365,6 +384,18 @@ typedef union
|
|||
unsigned long size;
|
||||
} virtual_unlock;
|
||||
struct
|
||||
{
|
||||
enum apc_type type;
|
||||
unsigned int status;
|
||||
void *addr;
|
||||
unsigned long size;
|
||||
} map_view;
|
||||
struct
|
||||
{
|
||||
enum apc_type type;
|
||||
unsigned int status;
|
||||
} unmap_view;
|
||||
struct
|
||||
{
|
||||
enum apc_type type;
|
||||
unsigned int status;
|
||||
|
@ -4593,6 +4624,6 @@ union generic_reply
|
|||
struct query_symlink_reply query_symlink_reply;
|
||||
};
|
||||
|
||||
#define SERVER_PROTOCOL_VERSION 272
|
||||
#define SERVER_PROTOCOL_VERSION 273
|
||||
|
||||
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
|
||||
|
|
|
@ -238,6 +238,8 @@ enum apc_type
|
|||
APC_VIRTUAL_FLUSH,
|
||||
APC_VIRTUAL_LOCK,
|
||||
APC_VIRTUAL_UNLOCK,
|
||||
APC_MAP_VIEW,
|
||||
APC_UNMAP_VIEW,
|
||||
APC_CREATE_THREAD
|
||||
};
|
||||
|
||||
|
@ -312,6 +314,23 @@ typedef union
|
|||
unsigned long size; /* requested address */
|
||||
} virtual_unlock;
|
||||
struct
|
||||
{
|
||||
enum apc_type type; /* APC_MAP_VIEW */
|
||||
obj_handle_t handle; /* mapping handle */
|
||||
void *addr; /* requested address */
|
||||
unsigned long size; /* allocation size */
|
||||
unsigned int offset_low;/* file offset */
|
||||
unsigned int offset_high;
|
||||
unsigned int zero_bits; /* allocation alignment */
|
||||
unsigned int alloc_type;/* allocation type */
|
||||
unsigned int prot; /* memory protection flags */
|
||||
} map_view;
|
||||
struct
|
||||
{
|
||||
enum apc_type type; /* APC_UNMAP_VIEW */
|
||||
void *addr; /* view address */
|
||||
} unmap_view;
|
||||
struct
|
||||
{
|
||||
enum apc_type type; /* APC_CREATE_THREAD */
|
||||
void (__stdcall *func)(void*); /* start function */
|
||||
|
@ -381,6 +400,18 @@ typedef union
|
|||
unsigned long size; /* resulting size */
|
||||
} virtual_unlock;
|
||||
struct
|
||||
{
|
||||
enum apc_type type; /* APC_MAP_VIEW */
|
||||
unsigned int status; /* status returned by call */
|
||||
void *addr; /* resulting address */
|
||||
unsigned long size; /* resulting size */
|
||||
} map_view;
|
||||
struct
|
||||
{
|
||||
enum apc_type type; /* APC_MAP_VIEW */
|
||||
unsigned int status; /* status returned by call */
|
||||
} unmap_view;
|
||||
struct
|
||||
{
|
||||
enum apc_type type; /* APC_CREATE_THREAD */
|
||||
unsigned int status; /* status returned by call */
|
||||
|
|
|
@ -1164,11 +1164,27 @@ DECL_HANDLER(queue_apc)
|
|||
case APC_VIRTUAL_FLUSH:
|
||||
case APC_VIRTUAL_LOCK:
|
||||
case APC_VIRTUAL_UNLOCK:
|
||||
case APC_UNMAP_VIEW:
|
||||
process = get_process_from_handle( req->process, PROCESS_VM_OPERATION );
|
||||
break;
|
||||
case APC_VIRTUAL_QUERY:
|
||||
process = get_process_from_handle( req->process, PROCESS_QUERY_INFORMATION );
|
||||
break;
|
||||
case APC_MAP_VIEW:
|
||||
process = get_process_from_handle( req->process, PROCESS_VM_OPERATION );
|
||||
if (process)
|
||||
{
|
||||
/* duplicate the handle into the target process */
|
||||
obj_handle_t handle = duplicate_handle( current->process, apc->call.map_view.handle,
|
||||
process, 0, 0, DUP_HANDLE_SAME_ACCESS );
|
||||
if (handle) apc->call.map_view.handle = handle;
|
||||
else
|
||||
{
|
||||
release_object( process );
|
||||
process = NULL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case APC_CREATE_THREAD:
|
||||
process = get_process_from_handle( req->process, PROCESS_CREATE_THREAD );
|
||||
break;
|
||||
|
|
|
@ -150,6 +150,15 @@ static void dump_apc_call( const apc_call_t *call )
|
|||
fprintf( stderr, "APC_VIRTUAL_UNLOCK,addr=%p,size=%lu",
|
||||
call->virtual_unlock.addr, call->virtual_unlock.size );
|
||||
break;
|
||||
case APC_MAP_VIEW:
|
||||
fprintf( stderr, "APC_MAP_VIEW,handle=%p,addr=%p,size=%lu,offset=%x%08x,zero_bits=%u,alloc_type=%x,prot=%x",
|
||||
call->map_view.handle, call->map_view.addr, call->map_view.size,
|
||||
call->map_view.offset_high, call->map_view.offset_low, call->map_view.zero_bits,
|
||||
call->map_view.alloc_type, call->map_view.prot );
|
||||
break;
|
||||
case APC_UNMAP_VIEW:
|
||||
fprintf( stderr, "APC_UNMAP_VIEW,addr=%p", call->unmap_view.addr );
|
||||
break;
|
||||
case APC_CREATE_THREAD:
|
||||
fprintf( stderr, "APC_CREATE_THREAD,func=%p,arg=%p,reserve=%lx,commit=%lx,suspend=%u",
|
||||
call->create_thread.func, call->create_thread.arg,
|
||||
|
@ -209,6 +218,15 @@ static void dump_apc_result( const apc_result_t *result )
|
|||
get_status_name( result->virtual_unlock.status ),
|
||||
result->virtual_unlock.addr, result->virtual_unlock.size );
|
||||
break;
|
||||
case APC_MAP_VIEW:
|
||||
fprintf( stderr, "APC_MAP_VIEW,status=%s,addr=%p,size=%lu",
|
||||
get_status_name( result->map_view.status ),
|
||||
result->map_view.addr, result->map_view.size );
|
||||
break;
|
||||
case APC_UNMAP_VIEW:
|
||||
fprintf( stderr, "APC_UNMAP_VIEW,status=%s",
|
||||
get_status_name( result->unmap_view.status ) );
|
||||
break;
|
||||
case APC_CREATE_THREAD:
|
||||
fprintf( stderr, "APC_CREATE_THREAD,status=%s,tid=%04x,handle=%p",
|
||||
get_status_name( result->create_thread.status ),
|
||||
|
|
Loading…
Reference in New Issue