From: Eric Pouech eric.pouech@gmail.com
Code is duplicated in ntdll.dll (for 32bit only and old Wow configuration) and wow64.dll for new Wow64 configurations.
Signed-off-by: Eric Pouech eric.pouech@gmail.com --- dlls/ntdll/unix/sync.c | 54 +++++++++++++++++++++++++++++++++- dlls/wow64/sync.c | 66 +++++++++++++++++++++++++++++++++++++++++- server/mapping.c | 3 -- 3 files changed, 118 insertions(+), 5 deletions(-)
diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c index 22a3555ba3f..831c16130b9 100644 --- a/dlls/ntdll/unix/sync.c +++ b/dlls/ntdll/unix/sync.c @@ -1008,15 +1008,48 @@ static NTSTATUS event_data_to_state_change( const debug_event_t *data, DBGUI_WAI info->DebugInfoFileOffset = data->load_dll.dbg_offset; info->DebugInfoSize = data->load_dll.dbg_size; info->NamePointer = wine_server_get_ptr( data->load_dll.name ); + if ((DWORD_PTR)data->load_dll.base != data->load_dll.base) + return STATUS_PARTIAL_COPY; return STATUS_SUCCESS; } case DbgUnloadDllStateChange: state->StateInfo.UnloadDll.BaseAddress = wine_server_get_ptr( data->unload_dll.base ); + if ((DWORD_PTR)data->unload_dll.base != data->unload_dll.base) + return STATUS_PARTIAL_COPY; return STATUS_SUCCESS; } return STATUS_INTERNAL_ERROR; }
+#ifndef _WIN64 +/* helper to NtWaitForDebugEvent; retrive machine from PE image */ +static NTSTATUS get_image_machine( HANDLE handle, USHORT *machine ) +{ + IMAGE_DOS_HEADER dos_hdr; + IMAGE_NT_HEADERS nt_hdr; + IO_STATUS_BLOCK iosb; + LARGE_INTEGER offset; + FILE_POSITION_INFORMATION pos_info; + NTSTATUS status; + + offset.QuadPart = 0; + status = NtReadFile( handle, NULL, NULL, NULL, + &iosb, &dos_hdr, sizeof(dos_hdr), &offset, NULL ); + if (!status) + { + offset.QuadPart = dos_hdr.e_lfanew; + status = NtReadFile( handle, NULL, NULL, NULL, &iosb, + &nt_hdr, FIELD_OFFSET(IMAGE_NT_HEADERS, OptionalHeader), &offset, NULL ); + if (!status) + *machine = nt_hdr.FileHeader.Machine; + /* Reset file pos at beginning of file */ + pos_info.CurrentByteOffset.QuadPart = 0; + NtSetInformationFile( handle, &iosb, &pos_info, sizeof(pos_info), FilePositionInformation ); + } + return status; +} +#endif + /********************************************************************** * NtWaitForDebugEvent (NTDLL.@) */ @@ -1034,8 +1067,9 @@ NTSTATUS WINAPI NtWaitForDebugEvent( HANDLE handle, BOOLEAN alertable, LARGE_INT req->debug = wine_server_obj_handle( handle ); wine_server_set_reply( req, &data, sizeof(data) ); ret = wine_server_call( req ); - if (!ret && !(ret = event_data_to_state_change( &data, state ))) + if (!ret) { + ret = event_data_to_state_change( &data, state ); state->NewState = data.code; state->AppClientId.UniqueProcess = ULongToHandle( reply->pid ); state->AppClientId.UniqueThread = ULongToHandle( reply->tid ); @@ -1043,6 +1077,24 @@ NTSTATUS WINAPI NtWaitForDebugEvent( HANDLE handle, BOOLEAN alertable, LARGE_INT } SERVER_END_REQ;
+#ifndef _WIN64 + /* don't pass 64bit load events to 32bit callers */ + if (!ret && state->NewState == DbgLoadDllStateChange) + { + USHORT machine; + if (!get_image_machine( state->StateInfo.LoadDll.FileHandle, &machine ) && + machine != current_machine) + ret = STATUS_PARTIAL_COPY; + } + if (ret == STATUS_PARTIAL_COPY) + { + if (state->NewState == DbgLoadDllStateChange) + NtClose( state->StateInfo.LoadDll.FileHandle ); + NtDebugContinue( handle, &state->AppClientId, DBG_CONTINUE ); + wait = TRUE; + continue; + } +#endif if (ret != STATUS_PENDING) return ret; if (!wait) return STATUS_TIMEOUT; wait = FALSE; diff --git a/dlls/wow64/sync.c b/dlls/wow64/sync.c index bf42f43b7e6..385477ef5fa 100644 --- a/dlls/wow64/sync.c +++ b/dlls/wow64/sync.c @@ -1490,6 +1490,65 @@ NTSTATUS WINAPI wow64_NtWaitForAlertByThreadId( UINT *args ) }
+/* helper to wow64_NtWaitForDebugEvent; retrive machine from PE image */ +static NTSTATUS get_image_machine( HANDLE handle, USHORT *machine ) +{ + IMAGE_DOS_HEADER dos_hdr; + IMAGE_NT_HEADERS nt_hdr; + IO_STATUS_BLOCK iosb; + LARGE_INTEGER offset; + FILE_POSITION_INFORMATION pos_info; + NTSTATUS status; + + offset.QuadPart = 0; + status = NtReadFile( handle, NULL, NULL, NULL, + &iosb, &dos_hdr, sizeof(dos_hdr), &offset, NULL ); + if (!status) + { + offset.QuadPart = dos_hdr.e_lfanew; + status = NtReadFile( handle, NULL, NULL, NULL, &iosb, + &nt_hdr, FIELD_OFFSET(IMAGE_NT_HEADERS, OptionalHeader), &offset, NULL ); + if (!status) + *machine = nt_hdr.FileHeader.Machine; + /* Reset file pos at beginning of file */ + pos_info.CurrentByteOffset.QuadPart = 0; + NtSetInformationFile( handle, &iosb, &pos_info, sizeof(pos_info), FilePositionInformation ); + } + return status; +} + +/* helper to wow64_NtWaitForDebugEvent; only pass debug events for current machine */ +static BOOL filter_out_state_change( HANDLE handle, DBGUI_WAIT_STATE_CHANGE *state ) +{ + BOOL filter_out; + + switch (state->NewState) + { + case DbgLoadDllStateChange: + filter_out = ((ULONG64)state->StateInfo.LoadDll.BaseOfDll >> 32) != 0; + if (!filter_out) + { + USHORT machine; + filter_out = !get_image_machine( state->StateInfo.LoadDll.FileHandle, &machine) && machine != current_machine; + } + break; + case DbgUnloadDllStateChange: + filter_out = ((ULONG_PTR)state->StateInfo.UnloadDll.BaseAddress >> 32) != 0; + break; + default: + filter_out = FALSE; + break; + } + if (filter_out) + { + if (state->NewState == DbgLoadDllStateChange) + NtClose( state->StateInfo.LoadDll.FileHandle ); + NtDebugContinue( handle, &state->AppClientId, DBG_CONTINUE ); + } + return filter_out; +} + + /********************************************************************** * wow64_NtWaitForDebugEvent */ @@ -1502,7 +1561,12 @@ NTSTATUS WINAPI wow64_NtWaitForDebugEvent( UINT *args )
ULONG i; DBGUI_WAIT_STATE_CHANGE state; - NTSTATUS status = NtWaitForDebugEvent( handle, alertable, timeout, &state ); + NTSTATUS status; + + do + { + status = NtWaitForDebugEvent( handle, alertable, timeout, &state ); + } while (!status && filter_out_state_change( handle, &state ));
if (!status) { diff --git a/server/mapping.c b/server/mapping.c index f14ee11cc62..8c436623600 100644 --- a/server/mapping.c +++ b/server/mapping.c @@ -378,10 +378,7 @@ static void set_process_machine( struct process *process, struct memory_view *vi
static int generate_dll_event( struct thread *thread, int code, struct memory_view *view ) { - unsigned short process_machine = thread->process->machine; - if (!(view->flags & SEC_IMAGE)) return 0; - if (process_machine != native_machine && process_machine != view->image.machine) return 0; generate_debug_event( thread, code, view ); return 1; }