Automatic Copyright Year update after running gdb/copyright.py
[deliverable/binutils-gdb.git] / gdb / nat / windows-nat.c
1 /* Internal interfaces for the Windows code
2 Copyright (C) 1995-2022 Free Software Foundation, Inc.
3
4 This file is part of GDB.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>. */
18
19 #include "gdbsupport/common-defs.h"
20 #include "nat/windows-nat.h"
21 #include "gdbsupport/common-debug.h"
22
23 namespace windows_nat
24 {
25
26 HANDLE current_process_handle;
27 DWORD current_process_id;
28 DWORD main_thread_id;
29 enum gdb_signal last_sig = GDB_SIGNAL_0;
30 DEBUG_EVENT current_event;
31
32 /* The most recent event from WaitForDebugEvent. Unlike
33 current_event, this is guaranteed never to come from a pending
34 stop. This is important because only data from the most recent
35 event from WaitForDebugEvent can be used when calling
36 ContinueDebugEvent. */
37 static DEBUG_EVENT last_wait_event;
38
39 DWORD desired_stop_thread_id = -1;
40 std::vector<pending_stop> pending_stops;
41 EXCEPTION_RECORD siginfo_er;
42
43 #ifdef __x86_64__
44 bool wow64_process = false;
45 bool ignore_first_breakpoint = false;
46 #endif
47
48 AdjustTokenPrivileges_ftype *AdjustTokenPrivileges;
49 DebugActiveProcessStop_ftype *DebugActiveProcessStop;
50 DebugBreakProcess_ftype *DebugBreakProcess;
51 DebugSetProcessKillOnExit_ftype *DebugSetProcessKillOnExit;
52 EnumProcessModules_ftype *EnumProcessModules;
53 #ifdef __x86_64__
54 EnumProcessModulesEx_ftype *EnumProcessModulesEx;
55 #endif
56 GetModuleInformation_ftype *GetModuleInformation;
57 GetModuleFileNameExA_ftype *GetModuleFileNameExA;
58 GetModuleFileNameExW_ftype *GetModuleFileNameExW;
59 LookupPrivilegeValueA_ftype *LookupPrivilegeValueA;
60 OpenProcessToken_ftype *OpenProcessToken;
61 GetCurrentConsoleFont_ftype *GetCurrentConsoleFont;
62 GetConsoleFontSize_ftype *GetConsoleFontSize;
63 #ifdef __x86_64__
64 Wow64SuspendThread_ftype *Wow64SuspendThread;
65 Wow64GetThreadContext_ftype *Wow64GetThreadContext;
66 Wow64SetThreadContext_ftype *Wow64SetThreadContext;
67 Wow64GetThreadSelectorEntry_ftype *Wow64GetThreadSelectorEntry;
68 #endif
69 GenerateConsoleCtrlEvent_ftype *GenerateConsoleCtrlEvent;
70
71 /* Note that 'debug_events' must be locally defined in the relevant
72 functions. */
73 #define DEBUG_EVENTS(fmt, ...) \
74 debug_prefixed_printf_cond (debug_events, "windows events", fmt, \
75 ## __VA_ARGS__)
76
77 windows_thread_info::~windows_thread_info ()
78 {
79 }
80
81 void
82 windows_thread_info::suspend ()
83 {
84 if (suspended != 0)
85 return;
86
87 if (SuspendThread (h) == (DWORD) -1)
88 {
89 DWORD err = GetLastError ();
90
91 /* We get Access Denied (5) when trying to suspend
92 threads that Windows started on behalf of the
93 debuggee, usually when those threads are just
94 about to exit.
95 We can get Invalid Handle (6) if the main thread
96 has exited. */
97 if (err != ERROR_INVALID_HANDLE && err != ERROR_ACCESS_DENIED)
98 warning (_("SuspendThread (tid=0x%x) failed. (winerr %u)"),
99 (unsigned) tid, (unsigned) err);
100 suspended = -1;
101 }
102 else
103 suspended = 1;
104 }
105
106 void
107 windows_thread_info::resume ()
108 {
109 if (suspended > 0)
110 {
111 stopped_at_software_breakpoint = false;
112
113 if (ResumeThread (h) == (DWORD) -1)
114 {
115 DWORD err = GetLastError ();
116 warning (_("warning: ResumeThread (tid=0x%x) failed. (winerr %u)"),
117 (unsigned) tid, (unsigned) err);
118 }
119 }
120 suspended = 0;
121 }
122
123 /* Return the name of the DLL referenced by H at ADDRESS. UNICODE
124 determines what sort of string is read from the inferior. Returns
125 the name of the DLL, or NULL on error. If a name is returned, it
126 is stored in a static buffer which is valid until the next call to
127 get_image_name. */
128
129 static const char *
130 get_image_name (HANDLE h, void *address, int unicode)
131 {
132 #ifdef __CYGWIN__
133 static char buf[MAX_PATH];
134 #else
135 static char buf[(2 * MAX_PATH) + 1];
136 #endif
137 DWORD size = unicode ? sizeof (WCHAR) : sizeof (char);
138 char *address_ptr;
139 int len = 0;
140 char b[2];
141 SIZE_T done;
142
143 /* Attempt to read the name of the dll that was detected.
144 This is documented to work only when actively debugging
145 a program. It will not work for attached processes. */
146 if (address == NULL)
147 return NULL;
148
149 /* See if we could read the address of a string, and that the
150 address isn't null. */
151 if (!ReadProcessMemory (h, address, &address_ptr,
152 sizeof (address_ptr), &done)
153 || done != sizeof (address_ptr)
154 || !address_ptr)
155 return NULL;
156
157 /* Find the length of the string. */
158 while (ReadProcessMemory (h, address_ptr + len++ * size, &b, size, &done)
159 && (b[0] != 0 || b[size - 1] != 0) && done == size)
160 continue;
161
162 if (!unicode)
163 ReadProcessMemory (h, address_ptr, buf, len, &done);
164 else
165 {
166 WCHAR *unicode_address = (WCHAR *) alloca (len * sizeof (WCHAR));
167 ReadProcessMemory (h, address_ptr, unicode_address, len * sizeof (WCHAR),
168 &done);
169 #ifdef __CYGWIN__
170 wcstombs (buf, unicode_address, MAX_PATH);
171 #else
172 WideCharToMultiByte (CP_ACP, 0, unicode_address, len, buf, sizeof buf,
173 0, 0);
174 #endif
175 }
176
177 return buf;
178 }
179
180 /* The exception thrown by a program to tell the debugger the name of
181 a thread. The exception record contains an ID of a thread and a
182 name to give it. This exception has no documented name, but MSDN
183 dubs it "MS_VC_EXCEPTION" in one code example. */
184 #define MS_VC_EXCEPTION 0x406d1388
185
186 handle_exception_result
187 handle_exception (struct target_waitstatus *ourstatus, bool debug_exceptions)
188 {
189 #define DEBUG_EXCEPTION_SIMPLE(x) if (debug_exceptions) \
190 debug_printf ("gdb: Target exception %s at %s\n", x, \
191 host_address_to_string (\
192 current_event.u.Exception.ExceptionRecord.ExceptionAddress))
193
194 EXCEPTION_RECORD *rec = &current_event.u.Exception.ExceptionRecord;
195 DWORD code = rec->ExceptionCode;
196 handle_exception_result result = HANDLE_EXCEPTION_HANDLED;
197
198 memcpy (&siginfo_er, rec, sizeof siginfo_er);
199
200 ourstatus->kind = TARGET_WAITKIND_STOPPED;
201
202 /* Record the context of the current thread. */
203 thread_rec (ptid_t (current_event.dwProcessId, current_event.dwThreadId, 0),
204 DONT_SUSPEND);
205
206 switch (code)
207 {
208 case EXCEPTION_ACCESS_VIOLATION:
209 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_ACCESS_VIOLATION");
210 ourstatus->value.sig = GDB_SIGNAL_SEGV;
211 if (handle_access_violation (rec))
212 return HANDLE_EXCEPTION_UNHANDLED;
213 break;
214 case STATUS_STACK_OVERFLOW:
215 DEBUG_EXCEPTION_SIMPLE ("STATUS_STACK_OVERFLOW");
216 ourstatus->value.sig = GDB_SIGNAL_SEGV;
217 break;
218 case STATUS_FLOAT_DENORMAL_OPERAND:
219 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_DENORMAL_OPERAND");
220 ourstatus->value.sig = GDB_SIGNAL_FPE;
221 break;
222 case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
223 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_ARRAY_BOUNDS_EXCEEDED");
224 ourstatus->value.sig = GDB_SIGNAL_FPE;
225 break;
226 case STATUS_FLOAT_INEXACT_RESULT:
227 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_INEXACT_RESULT");
228 ourstatus->value.sig = GDB_SIGNAL_FPE;
229 break;
230 case STATUS_FLOAT_INVALID_OPERATION:
231 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_INVALID_OPERATION");
232 ourstatus->value.sig = GDB_SIGNAL_FPE;
233 break;
234 case STATUS_FLOAT_OVERFLOW:
235 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_OVERFLOW");
236 ourstatus->value.sig = GDB_SIGNAL_FPE;
237 break;
238 case STATUS_FLOAT_STACK_CHECK:
239 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_STACK_CHECK");
240 ourstatus->value.sig = GDB_SIGNAL_FPE;
241 break;
242 case STATUS_FLOAT_UNDERFLOW:
243 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_UNDERFLOW");
244 ourstatus->value.sig = GDB_SIGNAL_FPE;
245 break;
246 case STATUS_FLOAT_DIVIDE_BY_ZERO:
247 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_DIVIDE_BY_ZERO");
248 ourstatus->value.sig = GDB_SIGNAL_FPE;
249 break;
250 case STATUS_INTEGER_DIVIDE_BY_ZERO:
251 DEBUG_EXCEPTION_SIMPLE ("STATUS_INTEGER_DIVIDE_BY_ZERO");
252 ourstatus->value.sig = GDB_SIGNAL_FPE;
253 break;
254 case STATUS_INTEGER_OVERFLOW:
255 DEBUG_EXCEPTION_SIMPLE ("STATUS_INTEGER_OVERFLOW");
256 ourstatus->value.sig = GDB_SIGNAL_FPE;
257 break;
258 case EXCEPTION_BREAKPOINT:
259 #ifdef __x86_64__
260 if (ignore_first_breakpoint)
261 {
262 /* For WOW64 processes, there are always 2 breakpoint exceptions
263 on startup, first a BREAKPOINT for the 64bit ntdll.dll,
264 then a WX86_BREAKPOINT for the 32bit ntdll.dll.
265 Here we only care about the WX86_BREAKPOINT's. */
266 ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
267 ignore_first_breakpoint = false;
268 }
269 else if (wow64_process)
270 {
271 /* This breakpoint exception is triggered for WOW64 processes when
272 reaching an int3 instruction in 64bit code.
273 gdb checks for int3 in case of SIGTRAP, this fails because
274 Wow64GetThreadContext can only report the pc of 32bit code, and
275 gdb lets the target process continue.
276 So handle it as SIGINT instead, then the target is stopped
277 unconditionally. */
278 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_BREAKPOINT");
279 rec->ExceptionCode = DBG_CONTROL_C;
280 ourstatus->value.sig = GDB_SIGNAL_INT;
281 break;
282 }
283 #endif
284 /* FALLTHROUGH */
285 case STATUS_WX86_BREAKPOINT:
286 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_BREAKPOINT");
287 ourstatus->value.sig = GDB_SIGNAL_TRAP;
288 break;
289 case DBG_CONTROL_C:
290 DEBUG_EXCEPTION_SIMPLE ("DBG_CONTROL_C");
291 ourstatus->value.sig = GDB_SIGNAL_INT;
292 break;
293 case DBG_CONTROL_BREAK:
294 DEBUG_EXCEPTION_SIMPLE ("DBG_CONTROL_BREAK");
295 ourstatus->value.sig = GDB_SIGNAL_INT;
296 break;
297 case EXCEPTION_SINGLE_STEP:
298 case STATUS_WX86_SINGLE_STEP:
299 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_SINGLE_STEP");
300 ourstatus->value.sig = GDB_SIGNAL_TRAP;
301 break;
302 case EXCEPTION_ILLEGAL_INSTRUCTION:
303 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_ILLEGAL_INSTRUCTION");
304 ourstatus->value.sig = GDB_SIGNAL_ILL;
305 break;
306 case EXCEPTION_PRIV_INSTRUCTION:
307 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_PRIV_INSTRUCTION");
308 ourstatus->value.sig = GDB_SIGNAL_ILL;
309 break;
310 case EXCEPTION_NONCONTINUABLE_EXCEPTION:
311 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_NONCONTINUABLE_EXCEPTION");
312 ourstatus->value.sig = GDB_SIGNAL_ILL;
313 break;
314 case MS_VC_EXCEPTION:
315 DEBUG_EXCEPTION_SIMPLE ("MS_VC_EXCEPTION");
316 if (handle_ms_vc_exception (rec))
317 {
318 ourstatus->value.sig = GDB_SIGNAL_TRAP;
319 result = HANDLE_EXCEPTION_IGNORED;
320 break;
321 }
322 /* treat improperly formed exception as unknown */
323 /* FALLTHROUGH */
324 default:
325 /* Treat unhandled first chance exceptions specially. */
326 if (current_event.u.Exception.dwFirstChance)
327 return HANDLE_EXCEPTION_UNHANDLED;
328 debug_printf ("gdb: unknown target exception 0x%08x at %s\n",
329 (unsigned) current_event.u.Exception.ExceptionRecord.ExceptionCode,
330 host_address_to_string (
331 current_event.u.Exception.ExceptionRecord.ExceptionAddress));
332 ourstatus->value.sig = GDB_SIGNAL_UNKNOWN;
333 break;
334 }
335
336 last_sig = ourstatus->value.sig;
337 return result;
338
339 #undef DEBUG_EXCEPTION_SIMPLE
340 }
341
342 /* Iterate over all DLLs currently mapped by our inferior, looking for
343 a DLL which is loaded at LOAD_ADDR. If found, add the DLL to our
344 list of solibs; otherwise do nothing. LOAD_ADDR NULL means add all
345 DLLs to the list of solibs; this is used when the inferior finishes
346 its initialization, and all the DLLs it statically depends on are
347 presumed loaded. */
348
349 static void
350 windows_add_dll (LPVOID load_addr)
351 {
352 HMODULE dummy_hmodule;
353 DWORD cb_needed;
354 HMODULE *hmodules;
355 int i;
356
357 #ifdef __x86_64__
358 if (wow64_process)
359 {
360 if (EnumProcessModulesEx (current_process_handle, &dummy_hmodule,
361 sizeof (HMODULE), &cb_needed,
362 LIST_MODULES_32BIT) == 0)
363 return;
364 }
365 else
366 #endif
367 {
368 if (EnumProcessModules (current_process_handle, &dummy_hmodule,
369 sizeof (HMODULE), &cb_needed) == 0)
370 return;
371 }
372
373 if (cb_needed < 1)
374 return;
375
376 hmodules = (HMODULE *) alloca (cb_needed);
377 #ifdef __x86_64__
378 if (wow64_process)
379 {
380 if (EnumProcessModulesEx (current_process_handle, hmodules,
381 cb_needed, &cb_needed,
382 LIST_MODULES_32BIT) == 0)
383 return;
384 }
385 else
386 #endif
387 {
388 if (EnumProcessModules (current_process_handle, hmodules,
389 cb_needed, &cb_needed) == 0)
390 return;
391 }
392
393 char system_dir[MAX_PATH];
394 char syswow_dir[MAX_PATH];
395 size_t system_dir_len = 0;
396 bool convert_syswow_dir = false;
397 #ifdef __x86_64__
398 if (wow64_process)
399 #endif
400 {
401 /* This fails on 32bit Windows because it has no SysWOW64 directory,
402 and in this case a path conversion isn't necessary. */
403 UINT len = GetSystemWow64DirectoryA (syswow_dir, sizeof (syswow_dir));
404 if (len > 0)
405 {
406 /* Check that we have passed a large enough buffer. */
407 gdb_assert (len < sizeof (syswow_dir));
408
409 len = GetSystemDirectoryA (system_dir, sizeof (system_dir));
410 /* Error check. */
411 gdb_assert (len != 0);
412 /* Check that we have passed a large enough buffer. */
413 gdb_assert (len < sizeof (system_dir));
414
415 strcat (system_dir, "\\");
416 strcat (syswow_dir, "\\");
417 system_dir_len = strlen (system_dir);
418
419 convert_syswow_dir = true;
420 }
421
422 }
423 for (i = 1; i < (int) (cb_needed / sizeof (HMODULE)); i++)
424 {
425 MODULEINFO mi;
426 #ifdef __USEWIDE
427 wchar_t dll_name[MAX_PATH];
428 char dll_name_mb[MAX_PATH];
429 #else
430 char dll_name[MAX_PATH];
431 #endif
432 const char *name;
433 if (GetModuleInformation (current_process_handle, hmodules[i],
434 &mi, sizeof (mi)) == 0)
435 continue;
436
437 if (GetModuleFileNameEx (current_process_handle, hmodules[i],
438 dll_name, sizeof (dll_name)) == 0)
439 continue;
440 #ifdef __USEWIDE
441 wcstombs (dll_name_mb, dll_name, MAX_PATH);
442 name = dll_name_mb;
443 #else
444 name = dll_name;
445 #endif
446 /* Convert the DLL path of 32bit processes returned by
447 GetModuleFileNameEx from the 64bit system directory to the
448 32bit syswow64 directory if necessary. */
449 std::string syswow_dll_path;
450 if (convert_syswow_dir
451 && strncasecmp (name, system_dir, system_dir_len) == 0
452 && strchr (name + system_dir_len, '\\') == nullptr)
453 {
454 syswow_dll_path = syswow_dir;
455 syswow_dll_path += name + system_dir_len;
456 name = syswow_dll_path.c_str();
457 }
458
459 /* Record the DLL if either LOAD_ADDR is NULL or the address
460 at which the DLL was loaded is equal to LOAD_ADDR. */
461 if (!(load_addr != nullptr && mi.lpBaseOfDll != load_addr))
462 {
463 handle_load_dll (name, mi.lpBaseOfDll);
464 if (load_addr != nullptr)
465 return;
466 }
467 }
468 }
469
470 /* See nat/windows-nat.h. */
471
472 void
473 dll_loaded_event ()
474 {
475 gdb_assert (current_event.dwDebugEventCode == LOAD_DLL_DEBUG_EVENT);
476
477 LOAD_DLL_DEBUG_INFO *event = &current_event.u.LoadDll;
478 const char *dll_name;
479
480 /* Try getting the DLL name via the lpImageName field of the event.
481 Note that Microsoft documents this fields as strictly optional,
482 in the sense that it might be NULL. And the first DLL event in
483 particular is explicitly documented as "likely not pass[ed]"
484 (source: MSDN LOAD_DLL_DEBUG_INFO structure). */
485 dll_name = get_image_name (current_process_handle,
486 event->lpImageName, event->fUnicode);
487 /* If the DLL name could not be gleaned via lpImageName, try harder
488 by enumerating all the DLLs loaded into the inferior, looking for
489 one that is loaded at base address = lpBaseOfDll. */
490 if (dll_name != nullptr)
491 handle_load_dll (dll_name, event->lpBaseOfDll);
492 else if (event->lpBaseOfDll != nullptr)
493 windows_add_dll (event->lpBaseOfDll);
494 }
495
496 /* See nat/windows-nat.h. */
497
498 void
499 windows_add_all_dlls ()
500 {
501 windows_add_dll (nullptr);
502 }
503
504 /* See nat/windows-nat.h. */
505
506 bool
507 matching_pending_stop (bool debug_events)
508 {
509 /* If there are pending stops, and we might plausibly hit one of
510 them, we don't want to actually continue the inferior -- we just
511 want to report the stop. In this case, we just pretend to
512 continue. See the comment by the definition of "pending_stops"
513 for details on why this is needed. */
514 for (const auto &item : pending_stops)
515 {
516 if (desired_stop_thread_id == -1
517 || desired_stop_thread_id == item.thread_id)
518 {
519 DEBUG_EVENTS ("pending stop anticipated, desired=0x%x, item=0x%x",
520 desired_stop_thread_id, item.thread_id);
521 return true;
522 }
523 }
524
525 return false;
526 }
527
528 /* See nat/windows-nat.h. */
529
530 gdb::optional<pending_stop>
531 fetch_pending_stop (bool debug_events)
532 {
533 gdb::optional<pending_stop> result;
534 for (auto iter = pending_stops.begin ();
535 iter != pending_stops.end ();
536 ++iter)
537 {
538 if (desired_stop_thread_id == -1
539 || desired_stop_thread_id == iter->thread_id)
540 {
541 result = *iter;
542 current_event = iter->event;
543
544 DEBUG_EVENTS ("pending stop found in 0x%x (desired=0x%x)",
545 iter->thread_id, desired_stop_thread_id);
546
547 pending_stops.erase (iter);
548 break;
549 }
550 }
551
552 return result;
553 }
554
555 /* See nat/windows-nat.h. */
556
557 BOOL
558 continue_last_debug_event (DWORD continue_status, bool debug_events)
559 {
560 DEBUG_EVENTS ("ContinueDebugEvent (cpid=%d, ctid=0x%x, %s)",
561 (unsigned) last_wait_event.dwProcessId,
562 (unsigned) last_wait_event.dwThreadId,
563 continue_status == DBG_CONTINUE ?
564 "DBG_CONTINUE" : "DBG_EXCEPTION_NOT_HANDLED");
565
566 return ContinueDebugEvent (last_wait_event.dwProcessId,
567 last_wait_event.dwThreadId,
568 continue_status);
569 }
570
571 /* See nat/windows-nat.h. */
572
573 BOOL
574 wait_for_debug_event (DEBUG_EVENT *event, DWORD timeout)
575 {
576 BOOL result = WaitForDebugEvent (event, timeout);
577 if (result)
578 last_wait_event = *event;
579 return result;
580 }
581
582 /* Define dummy functions which always return error for the rare cases where
583 these functions could not be found. */
584 template<typename... T>
585 BOOL WINAPI
586 bad (T... args)
587 {
588 return FALSE;
589 }
590
591 template<typename... T>
592 DWORD WINAPI
593 bad (T... args)
594 {
595 return 0;
596 }
597
598 static BOOL WINAPI
599 bad_GetCurrentConsoleFont (HANDLE w, BOOL bMaxWindow, CONSOLE_FONT_INFO *f)
600 {
601 f->nFont = 0;
602 return 1;
603 }
604
605 static COORD WINAPI
606 bad_GetConsoleFontSize (HANDLE w, DWORD nFont)
607 {
608 COORD size;
609 size.X = 8;
610 size.Y = 12;
611 return size;
612 }
613
614 /* See windows-nat.h. */
615
616 bool
617 initialize_loadable ()
618 {
619 bool result = true;
620 HMODULE hm = NULL;
621
622 #define GPA(m, func) \
623 func = (func ## _ftype *) GetProcAddress (m, #func)
624
625 hm = LoadLibrary (TEXT ("kernel32.dll"));
626 if (hm)
627 {
628 GPA (hm, DebugActiveProcessStop);
629 GPA (hm, DebugBreakProcess);
630 GPA (hm, DebugSetProcessKillOnExit);
631 GPA (hm, GetConsoleFontSize);
632 GPA (hm, DebugActiveProcessStop);
633 GPA (hm, GetCurrentConsoleFont);
634 #ifdef __x86_64__
635 GPA (hm, Wow64SuspendThread);
636 GPA (hm, Wow64GetThreadContext);
637 GPA (hm, Wow64SetThreadContext);
638 GPA (hm, Wow64GetThreadSelectorEntry);
639 #endif
640 GPA (hm, GenerateConsoleCtrlEvent);
641 }
642
643 /* Set variables to dummy versions of these processes if the function
644 wasn't found in kernel32.dll. */
645 if (!DebugBreakProcess)
646 DebugBreakProcess = bad;
647 if (!DebugActiveProcessStop || !DebugSetProcessKillOnExit)
648 {
649 DebugActiveProcessStop = bad;
650 DebugSetProcessKillOnExit = bad;
651 }
652 if (!GetConsoleFontSize)
653 GetConsoleFontSize = bad_GetConsoleFontSize;
654 if (!GetCurrentConsoleFont)
655 GetCurrentConsoleFont = bad_GetCurrentConsoleFont;
656
657 /* Load optional functions used for retrieving filename information
658 associated with the currently debugged process or its dlls. */
659 hm = LoadLibrary (TEXT ("psapi.dll"));
660 if (hm)
661 {
662 GPA (hm, EnumProcessModules);
663 #ifdef __x86_64__
664 GPA (hm, EnumProcessModulesEx);
665 #endif
666 GPA (hm, GetModuleInformation);
667 GPA (hm, GetModuleFileNameExA);
668 GPA (hm, GetModuleFileNameExW);
669 }
670
671 if (!EnumProcessModules || !GetModuleInformation
672 || !GetModuleFileNameExA || !GetModuleFileNameExW)
673 {
674 /* Set variables to dummy versions of these processes if the function
675 wasn't found in psapi.dll. */
676 EnumProcessModules = bad;
677 GetModuleInformation = bad;
678 GetModuleFileNameExA = bad;
679 GetModuleFileNameExW = bad;
680
681 result = false;
682 }
683
684 hm = LoadLibrary (TEXT ("advapi32.dll"));
685 if (hm)
686 {
687 GPA (hm, OpenProcessToken);
688 GPA (hm, LookupPrivilegeValueA);
689 GPA (hm, AdjustTokenPrivileges);
690 /* Only need to set one of these since if OpenProcessToken fails nothing
691 else is needed. */
692 if (!OpenProcessToken || !LookupPrivilegeValueA
693 || !AdjustTokenPrivileges)
694 OpenProcessToken = bad;
695 }
696
697 #undef GPA
698
699 return result;
700 }
701
702 }
This page took 0.042925 seconds and 4 git commands to generate.