Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/dbgeng/dbgeng.c | 23 +++++++++++++++++++++-- dlls/dbgeng/tests/dbgeng.c | 27 ++++++++++++++++++++++++--- 2 files changed, 45 insertions(+), 5 deletions(-)
diff --git a/dlls/dbgeng/dbgeng.c b/dlls/dbgeng/dbgeng.c index 1acfe0b318..d7f8191858 100644 --- a/dlls/dbgeng/dbgeng.c +++ b/dlls/dbgeng/dbgeng.c @@ -725,9 +725,28 @@ static ULONG STDMETHODCALLTYPE debugdataspaces_Release(IDebugDataSpaces *iface) static HRESULT STDMETHODCALLTYPE debugdataspaces_ReadVirtual(IDebugDataSpaces *iface, ULONG64 offset, void *buffer, ULONG buffer_size, ULONG *read_len) { - FIXME("%p, %s, %p, %u, %p stub.\n", iface, wine_dbgstr_longlong(offset), buffer, buffer_size, read_len); + struct debug_client *debug_client = impl_from_IDebugDataSpaces(iface); + static struct target_process *target; + HRESULT hr = S_OK; + SIZE_T length;
- return E_NOTIMPL; + TRACE("%p, %s, %p, %u, %p.\n", iface, wine_dbgstr_longlong(offset), buffer, buffer_size, read_len); + + if (!(target = debug_client_get_target(debug_client))) + return E_UNEXPECTED; + + if (ReadProcessMemory(target->handle, (const void *)(ULONG_PTR)offset, buffer, buffer_size, &length)) + { + if (read_len) + *read_len = length; + } + else + { + hr = HRESULT_FROM_WIN32(GetLastError()); + WARN("Failed to read process memory %#x.\n", hr); + } + + return hr; }
static HRESULT STDMETHODCALLTYPE debugdataspaces_WriteVirtual(IDebugDataSpaces *iface, ULONG64 offset, void *buffer, diff --git a/dlls/dbgeng/tests/dbgeng.c b/dlls/dbgeng/tests/dbgeng.c index 2a2dd3ad06..c8906c9048 100644 --- a/dlls/dbgeng/tests/dbgeng.c +++ b/dlls/dbgeng/tests/dbgeng.c @@ -322,14 +322,15 @@ todo_wine static void test_module_information(void) { static const char *event_name = "dbgeng_test_event"; - unsigned int loaded, unloaded, index; + unsigned int loaded, unloaded, index, length; DEBUG_MODULE_PARAMETERS params[2]; + IDebugDataSpaces *dataspaces; PROCESS_INFORMATION info; IDebugSymbols *symbols; IDebugControl *control; + ULONG64 bases[2], base; IDebugClient *client; - ULONG64 bases[2]; - ULONG64 base; + char buffer[64]; HANDLE event; HRESULT hr; BOOL ret; @@ -343,6 +344,9 @@ static void test_module_information(void) hr = client->lpVtbl->QueryInterface(client, &IID_IDebugSymbols, (void **)&symbols); ok(hr == S_OK, "Failed to get interface pointer, hr %#x.\n", hr);
+ hr = client->lpVtbl->QueryInterface(client, &IID_IDebugDataSpaces, (void **)&dataspaces); + ok(hr == S_OK, "Failed to get interface pointer, hr %#x.\n", hr); + event = CreateEventA(NULL, FALSE, FALSE, event_name); ok(event != NULL, "Failed to create event.\n");
@@ -419,6 +423,22 @@ static void test_module_information(void) hr = symbols->lpVtbl->GetModuleParameters(symbols, 1, NULL, loaded, params); ok(FAILED(hr), "Unexpected hr %#x.\n", hr);
+ /* Read memory. */ + base = 0; + hr = symbols->lpVtbl->GetModuleByIndex(symbols, 0, &base); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(!!base, "Unexpected module base.\n"); + + hr = dataspaces->lpVtbl->ReadVirtual(dataspaces, base, buffer, sizeof(buffer), &length); + ok(hr == S_OK, "Failed to read process memory, hr %#x.\n", hr); + ok(length == sizeof(buffer), "Unexpected length %u.\n", length); + ok(buffer[0] == 'M' && buffer[1] == 'Z', "Unexpected contents.\n"); + + memset(buffer, 0, sizeof(buffer)); + hr = dataspaces->lpVtbl->ReadVirtual(dataspaces, base, buffer, sizeof(buffer), NULL); + ok(hr == S_OK, "Failed to read process memory, hr %#x.\n", hr); + ok(buffer[0] == 'M' && buffer[1] == 'Z', "Unexpected contents.\n"); + hr = client->lpVtbl->DetachProcesses(client); ok(hr == S_OK, "Failed to detach, hr %#x.\n", hr);
@@ -431,6 +451,7 @@ static void test_module_information(void) client->lpVtbl->Release(client); control->lpVtbl->Release(control); symbols->lpVtbl->Release(symbols); + dataspaces->lpVtbl->Release(dataspaces); }
static void target_proc(const char *event_name, const char *event_ready_name)
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/dbgeng/dbgeng.c | 48 ++++++++++++++++++++++++++++++++++++-- dlls/dbgeng/tests/dbgeng.c | 9 +++++++ 2 files changed, 55 insertions(+), 2 deletions(-)
diff --git a/dlls/dbgeng/dbgeng.c b/dlls/dbgeng/dbgeng.c index d7f8191858..5352d3cc53 100644 --- a/dlls/dbgeng/dbgeng.c +++ b/dlls/dbgeng/dbgeng.c @@ -57,6 +57,7 @@ struct target_process unsigned int unloaded; BOOL initialized; } modules; + ULONG cpu_type; };
struct debug_client @@ -79,6 +80,21 @@ static struct target_process *debug_client_get_target(struct debug_client *debug return LIST_ENTRY(list_head(&debug_client->targets), struct target_process, entry); }
+static WORD debug_target_get_module_machine(struct target_process *target, HMODULE module) +{ + IMAGE_DOS_HEADER dos = { 0 }; + WORD machine = 0; + + ReadProcessMemory(target->handle, module, &dos, sizeof(dos), NULL); + if (dos.e_magic == IMAGE_DOS_SIGNATURE) + { + ReadProcessMemory(target->handle, (const char *)module + dos.e_lfanew + 4 /* signature */, &machine, + sizeof(machine), NULL); + } + + return machine; +} + static HRESULT debug_target_init_modules_info(struct target_process *target) { unsigned int i, count; @@ -123,6 +139,8 @@ static HRESULT debug_target_init_modules_info(struct target_process *target) } }
+ target->cpu_type = debug_target_get_module_machine(target, modules[0]); + heap_free(modules);
target->modules.loaded = count; @@ -2465,9 +2483,35 @@ static HRESULT STDMETHODCALLTYPE debugcontrol_GetPageSize(IDebugControl2 *iface,
static HRESULT STDMETHODCALLTYPE debugcontrol_IsPointer64Bit(IDebugControl2 *iface) { - FIXME("%p stub.\n", iface); + struct debug_client *debug_client = impl_from_IDebugControl2(iface); + static struct target_process *target; + HRESULT hr;
- return E_NOTIMPL; + TRACE("%p.\n", iface); + + if (!(target = debug_client_get_target(debug_client))) + return E_UNEXPECTED; + + if (FAILED(hr = debug_target_init_modules_info(target))) + return hr; + + switch (target->cpu_type) + { + case IMAGE_FILE_MACHINE_I386: + case IMAGE_FILE_MACHINE_ARM: + hr = S_FALSE; + break; + case IMAGE_FILE_MACHINE_IA64: + case IMAGE_FILE_MACHINE_AMD64: + case IMAGE_FILE_MACHINE_ARM64: + hr = S_OK; + break; + default: + FIXME("Unexpected cpu type %#x.\n", target->cpu_type); + hr = E_UNEXPECTED; + } + + return hr; }
static HRESULT STDMETHODCALLTYPE debugcontrol_ReadBugCheckData(IDebugControl2 *iface, ULONG *code, ULONG64 *arg1, diff --git a/dlls/dbgeng/tests/dbgeng.c b/dlls/dbgeng/tests/dbgeng.c index c8906c9048..32f90015d6 100644 --- a/dlls/dbgeng/tests/dbgeng.c +++ b/dlls/dbgeng/tests/dbgeng.c @@ -347,6 +347,9 @@ static void test_module_information(void) hr = client->lpVtbl->QueryInterface(client, &IID_IDebugDataSpaces, (void **)&dataspaces); ok(hr == S_OK, "Failed to get interface pointer, hr %#x.\n", hr);
+ hr = control->lpVtbl->IsPointer64Bit(control); + ok(hr == E_UNEXPECTED, "Unexpected hr %#x.\n", hr); + event = CreateEventA(NULL, FALSE, FALSE, event_name); ok(event != NULL, "Failed to create event.\n");
@@ -359,9 +362,15 @@ static void test_module_information(void) hr = client->lpVtbl->AttachProcess(client, 0, info.dwProcessId, DEBUG_ATTACH_NONINVASIVE); ok(hr == S_OK, "Failed to attach to process, hr %#x.\n", hr);
+ hr = control->lpVtbl->IsPointer64Bit(control); + ok(hr == E_UNEXPECTED, "Unexpected hr %#x.\n", hr); + hr = control->lpVtbl->WaitForEvent(control, 0, INFINITE); ok(hr == S_OK, "Waiting for event failed, hr %#x.\n", hr);
+ hr = control->lpVtbl->IsPointer64Bit(control); + ok(SUCCEEDED(hr), "Failed to get pointer length, hr %#x.\n", hr); + /* Number of modules. */ hr = symbols->lpVtbl->GetNumberModules(symbols, &loaded, &unloaded); ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/dbgeng/dbgeng.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-)
diff --git a/dlls/dbgeng/dbgeng.c b/dlls/dbgeng/dbgeng.c index 5352d3cc53..a62c05272a 100644 --- a/dlls/dbgeng/dbgeng.c +++ b/dlls/dbgeng/dbgeng.c @@ -2436,9 +2436,21 @@ static HRESULT STDMETHODCALLTYPE debugcontrol_GetActualProcessorType(IDebugContr
static HRESULT STDMETHODCALLTYPE debugcontrol_GetExecutingProcessorType(IDebugControl2 *iface, ULONG *type) { - FIXME("%p, %p stub.\n", iface, type); + struct debug_client *debug_client = impl_from_IDebugControl2(iface); + static struct target_process *target; + HRESULT hr;
- return E_NOTIMPL; + TRACE("%p, %p.\n", iface, type); + + if (!(target = debug_client_get_target(debug_client))) + return E_UNEXPECTED; + + if (FAILED(hr = debug_target_init_modules_info(target))) + return hr; + + *type = target->cpu_type; + + return S_OK; }
static HRESULT STDMETHODCALLTYPE debugcontrol_GetNumberPossibleExecutingProcessorTypes(IDebugControl2 *iface,
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/dbgeng/dbgeng.c | 62 ++++++++++++++++++++++++++++++++++++-- dlls/dbgeng/tests/dbgeng.c | 27 +++++++++++++++-- include/dbgeng.h | 8 +++++ 3 files changed, 92 insertions(+), 5 deletions(-)
diff --git a/dlls/dbgeng/dbgeng.c b/dlls/dbgeng/dbgeng.c index a62c05272a..704084c3a1 100644 --- a/dlls/dbgeng/dbgeng.c +++ b/dlls/dbgeng/dbgeng.c @@ -42,6 +42,7 @@ extern NTSTATUS WINAPI NtResumeProcess(HANDLE handle); struct module_info { DEBUG_MODULE_PARAMETERS params; + char image_name[MAX_PATH]; };
struct target_process @@ -136,6 +137,9 @@ static HRESULT debug_target_init_modules_info(struct target_process *target)
target->modules.info[i].params.Base = (ULONG_PTR)info.lpBaseOfDll; target->modules.info[i].params.Size = info.SizeOfImage; + + GetModuleFileNameExA(target->handle, modules[i], target->modules.info[i].image_name, + ARRAY_SIZE(target->modules.info[i].image_name)); } }
@@ -1448,13 +1452,67 @@ static HRESULT STDMETHODCALLTYPE debugsymbols_GetModuleVersionInformation(IDebug return E_NOTIMPL; }
+static HRESULT debug_target_return_string(const char *str, char *buffer, unsigned int buffer_size, + unsigned int *size) +{ + unsigned int len = strlen(str), dst_len; + + if (size) + *size = len + 1; + + if (buffer && buffer_size) + { + dst_len = min(len, buffer_size - 1); + if (dst_len) + memcpy(buffer, str, dst_len); + buffer[dst_len] = 0; + } + + return len < buffer_size ? S_OK : S_FALSE; +} + static HRESULT STDMETHODCALLTYPE debugsymbols_GetModuleNameString(IDebugSymbols3 *iface, ULONG which, ULONG index, ULONG64 base, char *buffer, ULONG buffer_size, ULONG *name_size) { - FIXME("%p, %u, %u, %s, %p, %u, %p stub.\n", iface, which, index, wine_dbgstr_longlong(base), buffer, buffer_size, + struct debug_client *debug_client = impl_from_IDebugSymbols3(iface); + const struct module_info *info; + struct target_process *target; + HRESULT hr; + + TRACE("%p, %u, %u, %s, %p, %u, %p.\n", iface, which, index, wine_dbgstr_longlong(base), buffer, buffer_size, name_size);
- return E_NOTIMPL; + if (!(target = debug_client_get_target(debug_client))) + return E_UNEXPECTED; + + if (index == DEBUG_ANY_ID) + info = debug_target_get_module_info_by_base(target, base); + else + info = debug_target_get_module_info(target, index); + + if (!info) + { + WARN("Was unable to locate module.\n"); + return E_INVALIDARG; + } + + switch (which) + { + case DEBUG_MODNAME_IMAGE: + hr = debug_target_return_string(info->image_name, buffer, buffer_size, name_size); + break; + case DEBUG_MODNAME_MODULE: + case DEBUG_MODNAME_LOADED_IMAGE: + case DEBUG_MODNAME_SYMBOL_FILE: + case DEBUG_MODNAME_MAPPED_IMAGE: + FIXME("Unsupported name info %d.\n", which); + return E_NOTIMPL; + default: + WARN("Unknown name info %d.\n", which); + return E_INVALIDARG; + } + + return hr; }
static HRESULT STDMETHODCALLTYPE debugsymbols_GetConstantName(IDebugSymbols3 *iface, ULONG64 module, ULONG type_id, diff --git a/dlls/dbgeng/tests/dbgeng.c b/dlls/dbgeng/tests/dbgeng.c index 32f90015d6..715649b7c3 100644 --- a/dlls/dbgeng/tests/dbgeng.c +++ b/dlls/dbgeng/tests/dbgeng.c @@ -326,11 +326,11 @@ static void test_module_information(void) DEBUG_MODULE_PARAMETERS params[2]; IDebugDataSpaces *dataspaces; PROCESS_INFORMATION info; - IDebugSymbols *symbols; + IDebugSymbols2 *symbols; IDebugControl *control; ULONG64 bases[2], base; + char buffer[MAX_PATH]; IDebugClient *client; - char buffer[64]; HANDLE event; HRESULT hr; BOOL ret; @@ -341,7 +341,7 @@ static void test_module_information(void) hr = client->lpVtbl->QueryInterface(client, &IID_IDebugControl, (void **)&control); ok(hr == S_OK, "Failed to get interface pointer, hr %#x.\n", hr);
- hr = client->lpVtbl->QueryInterface(client, &IID_IDebugSymbols, (void **)&symbols); + hr = client->lpVtbl->QueryInterface(client, &IID_IDebugSymbols2, (void **)&symbols); ok(hr == S_OK, "Failed to get interface pointer, hr %#x.\n", hr);
hr = client->lpVtbl->QueryInterface(client, &IID_IDebugDataSpaces, (void **)&dataspaces); @@ -432,6 +432,27 @@ static void test_module_information(void) hr = symbols->lpVtbl->GetModuleParameters(symbols, 1, NULL, loaded, params); ok(FAILED(hr), "Unexpected hr %#x.\n", hr);
+ /* Image name. */ + hr = symbols->lpVtbl->GetModuleNameString(symbols, DEBUG_MODNAME_IMAGE, 0, 0, buffer, sizeof(buffer), &length); + ok(hr == S_OK, "Failed to get image name, hr %#x.\n", hr); + ok(strlen(buffer) + 1 == length, "Unexpected length.\n"); + + hr = symbols->lpVtbl->GetModuleNameString(symbols, DEBUG_MODNAME_IMAGE, 0, 0, NULL, sizeof(buffer), &length); + ok(hr == S_OK, "Failed to get image name, hr %#x.\n", hr); + ok(length > 0, "Unexpected length.\n"); + + hr = symbols->lpVtbl->GetModuleNameString(symbols, DEBUG_MODNAME_IMAGE, DEBUG_ANY_ID, base, buffer, sizeof(buffer), + &length); + ok(hr == S_OK, "Failed to get image name, hr %#x.\n", hr); + ok(strlen(buffer) + 1 == length, "Unexpected length.\n"); + + hr = symbols->lpVtbl->GetModuleNameString(symbols, DEBUG_MODNAME_IMAGE, 0, 0, buffer, length - 1, &length); + ok(hr == S_FALSE, "Failed to get image name, hr %#x.\n", hr); + ok(strlen(buffer) + 2 == length, "Unexpected length %u, %u.\n", length, strlen(buffer)); + + hr = symbols->lpVtbl->GetModuleNameString(symbols, DEBUG_MODNAME_IMAGE, 0, 0, NULL, length - 1, NULL); + ok(hr == S_FALSE, "Failed to get image name, hr %#x.\n", hr); + /* Read memory. */ base = 0; hr = symbols->lpVtbl->GetModuleByIndex(symbols, 0, &base); diff --git a/include/dbgeng.h b/include/dbgeng.h index f50a1ca21d..3017edac55 100644 --- a/include/dbgeng.h +++ b/include/dbgeng.h @@ -162,7 +162,15 @@ DEFINE_GUID(IID_IDebugSystemObjects3, 0xe9676e2f, 0xe286, 0x4ea3, 0xb0, 0xf9 #define DEBUG_CDS_REFRESH_INLINESTEP 16 #define DEBUG_CDS_REFRESH_INLINESTEP_PSEUDO 17
+/* GetModuleNameString() indices */ +#define DEBUG_MODNAME_IMAGE 0 +#define DEBUG_MODNAME_MODULE 1 +#define DEBUG_MODNAME_LOADED_IMAGE 2 +#define DEBUG_MODNAME_SYMBOL_FILE 3 +#define DEBUG_MODNAME_MAPPED_IMAGE 4 + #define DEBUG_INVALID_OFFSET ((ULONG64)-1) +#define DEBUG_ANY_ID 0xffffffff
typedef struct _DEBUG_MODULE_PARAMETERS {
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/dbgeng/Makefile.in | 1 + dlls/dbgeng/dbgeng.c | 77 +++++++++++++++++++++++++++++++++-------- 2 files changed, 63 insertions(+), 15 deletions(-)
diff --git a/dlls/dbgeng/Makefile.in b/dlls/dbgeng/Makefile.in index 3a16e2e6db..c2639c5d22 100644 --- a/dlls/dbgeng/Makefile.in +++ b/dlls/dbgeng/Makefile.in @@ -1,4 +1,5 @@ MODULE = dbgeng.dll IMPORTLIB = dbgeng +DELAYIMPORTS = version
C_SRCS = dbgeng.c diff --git a/dlls/dbgeng/dbgeng.c b/dlls/dbgeng/dbgeng.c index 704084c3a1..287e0d84f7 100644 --- a/dlls/dbgeng/dbgeng.c +++ b/dlls/dbgeng/dbgeng.c @@ -81,6 +81,25 @@ static struct target_process *debug_client_get_target(struct debug_client *debug return LIST_ENTRY(list_head(&debug_client->targets), struct target_process, entry); }
+static HRESULT debug_target_return_string(const char *str, char *buffer, unsigned int buffer_size, + unsigned int *size) +{ + unsigned int len = strlen(str), dst_len; + + if (size) + *size = len + 1; + + if (buffer && buffer_size) + { + dst_len = min(len, buffer_size - 1); + if (dst_len) + memcpy(buffer, str, dst_len); + buffer[dst_len] = 0; + } + + return len < buffer_size ? S_OK : S_FALSE; +} + static WORD debug_target_get_module_machine(struct target_process *target, HMODULE module) { IMAGE_DOS_HEADER dos = { 0 }; @@ -1446,29 +1465,57 @@ static HRESULT STDMETHODCALLTYPE debugsymbols_GetSourceFileLineOffsets(IDebugSym static HRESULT STDMETHODCALLTYPE debugsymbols_GetModuleVersionInformation(IDebugSymbols3 *iface, ULONG index, ULONG64 base, const char *item, void *buffer, ULONG buffer_size, ULONG *info_size) { - FIXME("%p, %u, %s, %s, %p, %u, %p stub.\n", iface, index, wine_dbgstr_longlong(base), debugstr_a(item), buffer, + struct debug_client *debug_client = impl_from_IDebugSymbols3(iface); + const struct module_info *info; + struct target_process *target; + void *version_info, *ptr; + HRESULT hr = E_FAIL; + DWORD handle, size; + + TRACE("%p, %u, %s, %s, %p, %u, %p.\n", iface, index, wine_dbgstr_longlong(base), debugstr_a(item), buffer, buffer_size, info_size);
- return E_NOTIMPL; -} + if (!(target = debug_client_get_target(debug_client))) + return E_UNEXPECTED;
-static HRESULT debug_target_return_string(const char *str, char *buffer, unsigned int buffer_size, - unsigned int *size) -{ - unsigned int len = strlen(str), dst_len; + if (index == DEBUG_ANY_ID) + info = debug_target_get_module_info_by_base(target, base); + else + info = debug_target_get_module_info(target, index);
- if (size) - *size = len + 1; + if (!info) + { + WARN("Was unable to locate module.\n"); + return E_INVALIDARG; + }
- if (buffer && buffer_size) + if (!(size = GetFileVersionInfoSizeA(info->image_name, &handle))) + return E_FAIL; + + if (!(version_info = heap_alloc(size))) + return E_OUTOFMEMORY; + + if (GetFileVersionInfoA(info->image_name, handle, size, version_info)) { - dst_len = min(len, buffer_size - 1); - if (dst_len) - memcpy(buffer, str, dst_len); - buffer[dst_len] = 0; + if (VerQueryValueA(version_info, item, &ptr, &size)) + { + if (info_size) + *info_size = size; + + if (buffer && buffer_size) + { + unsigned int dst_len = min(size, buffer_size); + if (dst_len) + memcpy(buffer, ptr, dst_len); + } + + hr = buffer && buffer_size < size ? S_FALSE : S_OK; + } }
- return len < buffer_size ? S_OK : S_FALSE; + heap_free(version_info); + + return hr; }
static HRESULT STDMETHODCALLTYPE debugsymbols_GetModuleNameString(IDebugSymbols3 *iface, ULONG which, ULONG index,