d3d11: Use wined3d_device_context_draw().
[wine.git] / dlls / dbgeng / tests / dbgeng.c
blob627971751938c3dc97b6f5926a1eff18a78051a8
1 /*
2 * Copyright 2019 Nikolay Sivov for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #include <stdarg.h>
20 #include <stdio.h>
21 #include <string.h>
23 #include "windef.h"
24 #include "winbase.h"
26 #include "initguid.h"
27 #include "dbgeng.h"
29 #include "wine/test.h"
31 static void test_engine_options(void)
33 IDebugControl *control;
34 ULONG options;
35 HRESULT hr;
37 hr = DebugCreate(&IID_IDebugControl, (void **)&control);
38 ok(hr == S_OK, "Failed to create engine object, hr %#x.\n", hr);
40 options = 0xf;
41 hr = control->lpVtbl->GetEngineOptions(control, &options);
42 ok(hr == S_OK, "Failed to get engine options, hr %#x.\n", hr);
43 ok(options == 0, "Unexpected options %#x.\n", options);
45 hr = control->lpVtbl->AddEngineOptions(control, DEBUG_ENGOPT_INITIAL_BREAK);
46 ok(hr == S_OK, "Failed to add engine options, hr %#x.\n", hr);
48 options = 0;
49 hr = control->lpVtbl->GetEngineOptions(control, &options);
50 ok(hr == S_OK, "Failed to get engine options, hr %#x.\n", hr);
51 ok(options == DEBUG_ENGOPT_INITIAL_BREAK, "Unexpected options %#x.\n", options);
53 hr = control->lpVtbl->AddEngineOptions(control, 0x01000000);
54 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
56 options = 0;
57 hr = control->lpVtbl->GetEngineOptions(control, &options);
58 ok(hr == S_OK, "Failed to get engine options, hr %#x.\n", hr);
59 ok(options == DEBUG_ENGOPT_INITIAL_BREAK, "Unexpected options %#x.\n", options);
61 hr = control->lpVtbl->RemoveEngineOptions(control, 0x01000000);
62 ok(hr == S_OK, "Failed to remove options, hr %#x.\n", hr);
64 hr = control->lpVtbl->AddEngineOptions(control, DEBUG_ENGOPT_IGNORE_DBGHELP_VERSION);
65 ok(hr == S_OK, "Failed to add engine options, hr %#x.\n", hr);
67 options = 0;
68 hr = control->lpVtbl->GetEngineOptions(control, &options);
69 ok(hr == S_OK, "Failed to get engine options, hr %#x.\n", hr);
70 ok(options == (DEBUG_ENGOPT_INITIAL_BREAK | DEBUG_ENGOPT_IGNORE_DBGHELP_VERSION),
71 "Unexpected options %#x.\n", options);
73 hr = control->lpVtbl->RemoveEngineOptions(control, DEBUG_ENGOPT_INITIAL_BREAK);
74 ok(hr == S_OK, "Failed to remove options, hr %#x.\n", hr);
76 options = 0;
77 hr = control->lpVtbl->GetEngineOptions(control, &options);
78 ok(hr == S_OK, "Failed to get engine options, hr %#x.\n", hr);
79 ok(options == DEBUG_ENGOPT_IGNORE_DBGHELP_VERSION, "Unexpected options %#x.\n", options);
81 hr = control->lpVtbl->SetEngineOptions(control, DEBUG_ENGOPT_INITIAL_BREAK);
82 ok(hr == S_OK, "Failed to set options, hr %#x.\n", hr);
84 options = 0;
85 hr = control->lpVtbl->GetEngineOptions(control, &options);
86 ok(hr == S_OK, "Failed to get engine options, hr %#x.\n", hr);
87 ok(options == DEBUG_ENGOPT_INITIAL_BREAK, "Unexpected options %#x.\n", options);
89 hr = control->lpVtbl->SetEngineOptions(control, 0x01000000);
90 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
92 hr = control->lpVtbl->SetEngineOptions(control, 0x01000000 | DEBUG_ENGOPT_IGNORE_DBGHELP_VERSION);
93 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
95 options = 0;
96 hr = control->lpVtbl->GetEngineOptions(control, &options);
97 ok(hr == S_OK, "Failed to get engine options, hr %#x.\n", hr);
98 ok(options == DEBUG_ENGOPT_INITIAL_BREAK, "Unexpected options %#x.\n", options);
100 control->lpVtbl->Release(control);
103 static HRESULT WINAPI event_callbacks_QueryInterface(IDebugEventCallbacks *iface, REFIID riid, void **out)
105 if (IsEqualIID(riid, &IID_IDebugEventCallbacks) ||
106 IsEqualIID(riid, &IID_IUnknown))
108 *out = iface;
109 iface->lpVtbl->AddRef(iface);
110 return S_OK;
113 *out = NULL;
114 return E_NOINTERFACE;
117 static ULONG WINAPI event_callbacks_AddRef(IDebugEventCallbacks *iface)
119 return 2;
122 static ULONG WINAPI event_callbacks_Release(IDebugEventCallbacks *iface)
124 return 1;
127 static HRESULT WINAPI event_callbacks_GetInterestMask(IDebugEventCallbacks *iface, ULONG *mask)
129 *mask = ~0u;
130 return S_OK;
133 static HRESULT WINAPI event_callbacks_Breakpoint(IDebugEventCallbacks *iface, PDEBUG_BREAKPOINT breakpoint)
135 return E_NOTIMPL;
138 static HRESULT WINAPI event_callbacks_Exception(IDebugEventCallbacks *iface, EXCEPTION_RECORD64 *exception,
139 ULONG first_chance)
141 return E_NOTIMPL;
144 static HRESULT WINAPI event_callbacks_CreateThread(IDebugEventCallbacks *iface, ULONG64 handle, ULONG64 data_offset,
145 ULONG64 start_offset)
147 return E_NOTIMPL;
150 static HRESULT WINAPI event_callbacks_ExitThread(IDebugEventCallbacks *iface, ULONG exit_code)
152 return E_NOTIMPL;
155 static HRESULT WINAPI event_callbacks_CreateProcess(IDebugEventCallbacks *iface, ULONG64 image_handle, ULONG64 handle,
156 ULONG64 base_offset, ULONG module_size, const char *module_name, const char *image_name, ULONG checksum,
157 ULONG timedatestamp, ULONG64 initial_thread_handle, ULONG64 thread_data_offset, ULONG64 start_offset)
159 return E_NOTIMPL;
162 static HRESULT WINAPI event_callbacks_ExitProcess(IDebugEventCallbacks *iface, ULONG exit_code)
164 return E_NOTIMPL;
167 static HRESULT WINAPI event_callbacks_LoadModule(IDebugEventCallbacks *iface, ULONG64 image_handle,
168 ULONG64 base_offset, ULONG module_size, const char *module_name, const char *image_name, ULONG checksum,
169 ULONG timedatestamp)
171 return E_NOTIMPL;
174 static HRESULT WINAPI event_callbacks_UnloadModule(IDebugEventCallbacks *iface, const char *image_basename,
175 ULONG64 base_offset)
177 return E_NOTIMPL;
180 static HRESULT WINAPI event_callbacks_SystemError(IDebugEventCallbacks *iface, ULONG error, ULONG level)
182 return E_NOTIMPL;
185 static HRESULT WINAPI event_callbacks_SessionStatus(IDebugEventCallbacks *iface, ULONG status)
187 return E_NOTIMPL;
190 static HRESULT WINAPI event_callbacks_ChangeDebuggeeState(IDebugEventCallbacks *iface, ULONG flags, ULONG64 argument)
192 return E_NOTIMPL;
195 static HRESULT WINAPI event_callbacks_ChangeEngineState(IDebugEventCallbacks *iface, ULONG flags, ULONG64 argument)
197 return E_NOTIMPL;
200 static HRESULT WINAPI event_callbacks_ChangeSymbolState(IDebugEventCallbacks *iface, ULONG flags, ULONG64 argument)
203 return E_NOTIMPL;
206 static const IDebugEventCallbacksVtbl event_callbacks_vtbl =
208 event_callbacks_QueryInterface,
209 event_callbacks_AddRef,
210 event_callbacks_Release,
211 event_callbacks_GetInterestMask,
212 event_callbacks_Breakpoint,
213 event_callbacks_Exception,
214 event_callbacks_CreateThread,
215 event_callbacks_ExitThread,
216 event_callbacks_CreateProcess,
217 event_callbacks_ExitProcess,
218 event_callbacks_LoadModule,
219 event_callbacks_UnloadModule,
220 event_callbacks_SystemError,
221 event_callbacks_SessionStatus,
222 event_callbacks_ChangeDebuggeeState,
223 event_callbacks_ChangeEngineState,
224 event_callbacks_ChangeSymbolState,
227 static BOOL create_target_process(const char *event_name, PROCESS_INFORMATION *info)
229 static const char *event_target_ready_name = "dbgeng_test_target_ready_event";
230 char path_name[MAX_PATH];
231 STARTUPINFOA startup;
232 HANDLE ready_event;
233 char **argv;
234 BOOL ret;
236 ready_event = CreateEventA(NULL, FALSE, FALSE, event_target_ready_name);
237 ok(ready_event != NULL, "Failed to create event.\n");
239 winetest_get_mainargs(&argv);
240 memset(&startup, 0, sizeof(startup));
241 startup.cb = sizeof(startup);
242 sprintf(path_name, "%s dbgeng target %s %s", argv[0], event_name, event_target_ready_name);
243 ret = CreateProcessA(NULL, path_name, NULL, NULL, FALSE, 0, NULL, NULL, &startup, info);
244 if (ret)
246 WaitForSingleObject(ready_event, INFINITE);
249 CloseHandle(ready_event);
251 return ret;
254 static void test_attach(void)
256 static const char *event_name = "dbgeng_test_event";
257 IDebugEventCallbacks event_callbacks = { &event_callbacks_vtbl };
258 PROCESS_INFORMATION info;
259 IDebugControl *control;
260 IDebugClient *client;
261 BOOL is_debugged;
262 HANDLE event;
263 HRESULT hr;
264 BOOL ret;
266 hr = DebugCreate(&IID_IDebugClient, (void **)&client);
267 ok(hr == S_OK, "Failed to create engine object, hr %#x.\n", hr);
269 hr = client->lpVtbl->QueryInterface(client, &IID_IDebugControl, (void **)&control);
270 ok(hr == S_OK, "Failed to get interface pointer, hr %#x.\n", hr);
272 hr = client->lpVtbl->SetEventCallbacks(client, &event_callbacks);
273 ok(hr == S_OK, "Failed to set event callbacks, hr %#x.\n", hr);
275 event = CreateEventA(NULL, FALSE, FALSE, event_name);
276 ok(event != NULL, "Failed to create event.\n");
278 ret = create_target_process(event_name, &info);
279 ok(ret, "Failed to create target process.\n");
281 is_debugged = TRUE;
282 CheckRemoteDebuggerPresent(info.hProcess, &is_debugged);
283 ok(!is_debugged, "Unexpected mode.\n");
285 /* Non-invasive mode. */
286 hr = client->lpVtbl->AttachProcess(client, 0, info.dwProcessId, DEBUG_ATTACH_NONINVASIVE);
287 ok(hr == S_OK, "Failed to attach to process, hr %#x.\n", hr);
289 is_debugged = TRUE;
290 ret = CheckRemoteDebuggerPresent(info.hProcess, &is_debugged);
291 ok(ret, "Failed to check target status.\n");
292 ok(!is_debugged, "Unexpected mode.\n");
294 hr = control->lpVtbl->WaitForEvent(control, 0, INFINITE);
295 ok(hr == S_OK, "Waiting for event failed, hr %#x.\n", hr);
297 is_debugged = TRUE;
298 ret = CheckRemoteDebuggerPresent(info.hProcess, &is_debugged);
299 ok(ret, "Failed to check target status.\n");
300 ok(!is_debugged, "Unexpected mode.\n");
302 hr = client->lpVtbl->DetachProcesses(client);
303 ok(hr == S_OK, "Failed to detach, hr %#x.\n", hr);
305 hr = client->lpVtbl->EndSession(client, DEBUG_END_ACTIVE_DETACH);
306 todo_wine
307 ok(hr == S_OK, "Failed to end session, hr %#x.\n", hr);
309 SetEvent(event);
311 wait_child_process(info.hProcess);
313 CloseHandle(info.hProcess);
314 CloseHandle(info.hThread);
316 CloseHandle(event);
318 client->lpVtbl->Release(client);
319 control->lpVtbl->Release(control);
322 static void test_module_information(void)
324 static const char *event_name = "dbgeng_test_event";
325 unsigned int loaded, unloaded, index, length;
326 DEBUG_MODULE_PARAMETERS params[2];
327 IDebugDataSpaces *dataspaces;
328 PROCESS_INFORMATION info;
329 IDebugSymbols2 *symbols;
330 IDebugControl *control;
331 ULONG64 bases[2], base;
332 char buffer[MAX_PATH];
333 IDebugClient *client;
334 HANDLE event;
335 HRESULT hr;
336 BOOL ret;
338 hr = DebugCreate(&IID_IDebugClient, (void **)&client);
339 ok(hr == S_OK, "Failed to create engine object, hr %#x.\n", hr);
341 hr = client->lpVtbl->QueryInterface(client, &IID_IDebugControl, (void **)&control);
342 ok(hr == S_OK, "Failed to get interface pointer, hr %#x.\n", hr);
344 hr = client->lpVtbl->QueryInterface(client, &IID_IDebugSymbols2, (void **)&symbols);
345 ok(hr == S_OK, "Failed to get interface pointer, hr %#x.\n", hr);
347 hr = client->lpVtbl->QueryInterface(client, &IID_IDebugDataSpaces, (void **)&dataspaces);
348 ok(hr == S_OK, "Failed to get interface pointer, hr %#x.\n", hr);
350 hr = control->lpVtbl->IsPointer64Bit(control);
351 ok(hr == E_UNEXPECTED, "Unexpected hr %#x.\n", hr);
353 event = CreateEventA(NULL, FALSE, FALSE, event_name);
354 ok(event != NULL, "Failed to create event.\n");
356 ret = create_target_process(event_name, &info);
357 ok(ret, "Failed to create target process.\n");
359 hr = control->lpVtbl->SetEngineOptions(control, DEBUG_ENGOPT_INITIAL_BREAK);
360 ok(hr == S_OK, "Failed to set engine options, hr %#x.\n", hr);
362 hr = client->lpVtbl->AttachProcess(client, 0, info.dwProcessId, DEBUG_ATTACH_NONINVASIVE);
363 ok(hr == S_OK, "Failed to attach to process, hr %#x.\n", hr);
365 hr = control->lpVtbl->IsPointer64Bit(control);
366 ok(hr == E_UNEXPECTED, "Unexpected hr %#x.\n", hr);
368 hr = control->lpVtbl->WaitForEvent(control, 0, INFINITE);
369 ok(hr == S_OK, "Waiting for event failed, hr %#x.\n", hr);
371 hr = control->lpVtbl->IsPointer64Bit(control);
372 ok(SUCCEEDED(hr), "Failed to get pointer length, hr %#x.\n", hr);
374 /* Number of modules. */
375 hr = symbols->lpVtbl->GetNumberModules(symbols, &loaded, &unloaded);
376 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
377 ok(loaded > 0, "Unexpected module count %u.\n", loaded);
379 /* Module base. */
380 hr = symbols->lpVtbl->GetModuleByIndex(symbols, loaded, &base);
381 ok(FAILED(hr), "Unexpected hr %#x.\n", hr);
383 base = 0;
384 hr = symbols->lpVtbl->GetModuleByIndex(symbols, 0, &base);
385 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
386 ok(!!base, "Unexpected module base.\n");
388 hr = symbols->lpVtbl->GetModuleByOffset(symbols, 0, 0, &index, &base);
389 ok(FAILED(hr), "Unexpected hr %#x.\n", hr);
391 hr = symbols->lpVtbl->GetModuleByOffset(symbols, base, 0, &index, &base);
392 ok(hr == S_OK, "Failed to get module, hr %#x.\n", hr);
394 hr = symbols->lpVtbl->GetModuleByOffset(symbols, base, 0, NULL, NULL);
395 ok(hr == S_OK, "Failed to get module, hr %#x.\n", hr);
397 hr = symbols->lpVtbl->GetModuleByOffset(symbols, base + 1, 0, NULL, NULL);
398 ok(hr == S_OK, "Failed to get module, hr %#x.\n", hr);
400 hr = symbols->lpVtbl->GetModuleByOffset(symbols, base, loaded, NULL, NULL);
401 ok(FAILED(hr), "Unexpected hr %#x.\n", hr);
403 /* Parameters. */
404 base = 0;
405 hr = symbols->lpVtbl->GetModuleByIndex(symbols, 0, &base);
406 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
407 ok(!!base, "Unexpected module base.\n");
409 hr = symbols->lpVtbl->GetModuleParameters(symbols, 1, NULL, 0, params);
410 ok(hr == S_OK, "Failed to get module parameters, hr %#x.\n", hr);
411 ok(params[0].Base == base, "Unexpected module base.\n");
413 hr = symbols->lpVtbl->GetModuleParameters(symbols, 1, &base, 100, params);
414 ok(hr == S_OK, "Failed to get module parameters, hr %#x.\n", hr);
415 ok(params[0].Base == base, "Unexpected module base.\n");
417 bases[0] = base + 1;
418 bases[1] = base;
419 hr = symbols->lpVtbl->GetModuleParameters(symbols, 2, bases, 0, params);
420 ok(hr == S_OK || broken(hr == E_NOINTERFACE) /* XP */, "Failed to get module parameters, hr %#x.\n", hr);
421 ok(params[0].Base == DEBUG_INVALID_OFFSET, "Unexpected module base.\n");
422 ok(params[0].Size == 0, "Unexpected module size.\n");
423 ok(params[1].Base == base, "Unexpected module base.\n");
424 ok(params[1].Size != 0, "Unexpected module size.\n");
426 hr = symbols->lpVtbl->GetModuleParameters(symbols, 1, bases, 0, params);
427 ok(hr == S_OK || broken(hr == E_NOINTERFACE) /* XP */, "Failed to get module parameters, hr %#x.\n", hr);
429 hr = symbols->lpVtbl->GetModuleParameters(symbols, 1, bases, loaded, params);
430 ok(hr == S_OK || broken(hr == E_NOINTERFACE) /* XP */, "Failed to get module parameters, hr %#x.\n", hr);
432 hr = symbols->lpVtbl->GetModuleParameters(symbols, 1, NULL, loaded, params);
433 ok(FAILED(hr), "Unexpected hr %#x.\n", hr);
435 /* Image name. */
436 hr = symbols->lpVtbl->GetModuleNameString(symbols, DEBUG_MODNAME_IMAGE, 0, 0, buffer, sizeof(buffer), &length);
437 ok(hr == S_OK, "Failed to get image name, hr %#x.\n", hr);
438 ok(strlen(buffer) + 1 == length, "Unexpected length.\n");
440 hr = symbols->lpVtbl->GetModuleNameString(symbols, DEBUG_MODNAME_IMAGE, 0, 0, NULL, sizeof(buffer), &length);
441 ok(hr == S_OK, "Failed to get image name, hr %#x.\n", hr);
442 ok(length > 0, "Unexpected length.\n");
444 hr = symbols->lpVtbl->GetModuleNameString(symbols, DEBUG_MODNAME_IMAGE, DEBUG_ANY_ID, base, buffer, sizeof(buffer),
445 &length);
446 ok(hr == S_OK, "Failed to get image name, hr %#x.\n", hr);
447 ok(strlen(buffer) + 1 == length, "Unexpected length.\n");
449 hr = symbols->lpVtbl->GetModuleNameString(symbols, DEBUG_MODNAME_IMAGE, 0, 0, buffer, length - 1, &length);
450 ok(hr == S_FALSE, "Failed to get image name, hr %#x.\n", hr);
451 ok(strlen(buffer) + 2 == length, "Unexpected length %u.\n", length);
453 hr = symbols->lpVtbl->GetModuleNameString(symbols, DEBUG_MODNAME_IMAGE, 0, 0, NULL, length - 1, NULL);
454 ok(hr == S_FALSE, "Failed to get image name, hr %#x.\n", hr);
456 /* Read memory. */
457 base = 0;
458 hr = symbols->lpVtbl->GetModuleByIndex(symbols, 0, &base);
459 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
460 ok(!!base, "Unexpected module base.\n");
462 hr = dataspaces->lpVtbl->ReadVirtual(dataspaces, base, buffer, sizeof(buffer), &length);
463 ok(hr == S_OK, "Failed to read process memory, hr %#x.\n", hr);
464 ok(length == sizeof(buffer), "Unexpected length %u.\n", length);
465 ok(buffer[0] == 'M' && buffer[1] == 'Z', "Unexpected contents.\n");
467 memset(buffer, 0, sizeof(buffer));
468 hr = dataspaces->lpVtbl->ReadVirtual(dataspaces, base, buffer, sizeof(buffer), NULL);
469 ok(hr == S_OK, "Failed to read process memory, hr %#x.\n", hr);
470 ok(buffer[0] == 'M' && buffer[1] == 'Z', "Unexpected contents.\n");
472 hr = client->lpVtbl->DetachProcesses(client);
473 ok(hr == S_OK, "Failed to detach, hr %#x.\n", hr);
475 SetEvent(event);
476 wait_child_process(info.hProcess);
478 CloseHandle(info.hProcess);
479 CloseHandle(info.hThread);
480 CloseHandle(event);
482 client->lpVtbl->Release(client);
483 control->lpVtbl->Release(control);
484 symbols->lpVtbl->Release(symbols);
485 dataspaces->lpVtbl->Release(dataspaces);
488 static void target_proc(const char *event_name, const char *event_ready_name)
490 HANDLE terminate_event, ready_event;
492 terminate_event = OpenEventA(SYNCHRONIZE, FALSE, event_name);
493 ok(terminate_event != NULL, "Failed to open event handle.\n");
495 ready_event = OpenEventA(EVENT_MODIFY_STATE, FALSE, event_ready_name);
496 ok(ready_event != NULL, "Failed to open event handle.\n");
498 SetEvent(ready_event);
500 for (;;)
502 if (WaitForSingleObject(terminate_event, 100) == WAIT_OBJECT_0)
503 break;
506 CloseHandle(terminate_event);
507 CloseHandle(ready_event);
510 START_TEST(dbgeng)
512 char **argv;
513 int argc;
515 argc = winetest_get_mainargs(&argv);
517 if (argc > 4 && !strcmp(argv[2], "target"))
519 target_proc(argv[3], argv[4]);
520 return;
523 test_engine_options();
524 test_attach();
525 test_module_information();