ntdll: Implementation of inter-process NtMapViewOfSection and NtUnmapViewOfSection.

This commit is contained in:
Alexandre Julliard 2007-01-18 15:17:51 +01:00
parent 8025f79ce1
commit 02e2fa7798
7 changed files with 212 additions and 10 deletions

View File

@ -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();
}

View File

@ -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;

View File

@ -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))
{

View File

@ -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 */

View File

@ -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 */

View File

@ -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;

View File

@ -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 ),