ReactOS  0.4.14-dev-323-g6fe6a88
debugger.c
Go to the documentation of this file.
1 /*
2  * PROJECT: ReactOS Win32 Base API
3  * LICENSE: GPL - See COPYING in the top level directory
4  * FILE: dll/win32/kernel32/client/debugger.c
5  * PURPOSE: Wrappers for the NT Debug Implementation
6  * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
7  */
8 
9 /* INCLUDES *****************************************************************/
10 
11 #include <k32.h>
12 
13 #include <ndk/dbgkfuncs.h>
14 
15 #define NDEBUG
16 #include <debug.h>
17 
18 typedef struct _DBGSS_THREAD_DATA
19 {
27 
28 #define DbgSsSetThreadData(d) \
29  NtCurrentTeb()->DbgSsReserved[0] = d
30 
31 #define DbgSsGetThreadData() \
32  ((PDBGSS_THREAD_DATA)NtCurrentTeb()->DbgSsReserved[0])
33 
34 /* PRIVATE FUNCTIONS *********************************************************/
35 
36 static
37 HANDLE
39 {
42  HANDLE hMutex;
43 
44  /* SIDs to be used in the DACL */
45  PSID psidSystem = NULL;
46  PSID psidAdministrators = NULL;
47  PSID psidEveryone = NULL;
48 
49  /* buffer for the DACL */
50  PVOID pDaclBuf = NULL;
51 
52  /* minimum size of the DACL: an ACL descriptor and three ACCESS_ALLOWED_ACE
53  headers. We'll add the size of SIDs when we'll know it
54  */
55  SIZE_T nDaclBufSize =
56  sizeof(ACL) + (sizeof(ACCESS_ALLOWED_ACE) -
57  sizeof(((ACCESS_ALLOWED_ACE*)0)->SidStart)) * 3;
58 
59  /* security descriptor of the mutex */
60  SECURITY_DESCRIPTOR sdMutexSecurity;
61 
62  /* attributes of the mutex object we'll create */
63  SECURITY_ATTRIBUTES saMutexAttribs = {sizeof(saMutexAttribs),
64  &sdMutexSecurity,
65  TRUE};
66 
67  NTSTATUS nErrCode;
68 
69  /* first, try to open the mutex */
71  TRUE,
72  L"DBWinMutex");
73 
74  if (hMutex != NULL)
75  {
76  /* success */
77  return hMutex;
78  }
79  /* error other than the mutex not being found */
80  else if (GetLastError() != ERROR_FILE_NOT_FOUND)
81  {
82  /* failure */
83  return NULL;
84  }
85 
86  /* if the mutex doesn't exist, create it */
87 
88  /* first, set up the mutex security */
89  /* allocate the NT AUTHORITY\SYSTEM SID */
90  nErrCode = RtlAllocateAndInitializeSid(&siaNTAuth,
91  1,
93  0,
94  0,
95  0,
96  0,
97  0,
98  0,
99  0,
100  &psidSystem);
101 
102  /* failure */
103  if (!NT_SUCCESS(nErrCode)) goto l_Cleanup;
104 
105  /* allocate the BUILTIN\Administrators SID */
106  nErrCode = RtlAllocateAndInitializeSid(&siaNTAuth,
107  2,
110  0,
111  0,
112  0,
113  0,
114  0,
115  0,
116  &psidAdministrators);
117 
118  /* failure */
119  if (!NT_SUCCESS(nErrCode)) goto l_Cleanup;
120 
121  /* allocate the Everyone SID */
122  nErrCode = RtlAllocateAndInitializeSid(&siaWorldAuth,
123  1,
124  0,
125  0,
126  0,
127  0,
128  0,
129  0,
130  0,
131  0,
132  &psidEveryone);
133 
134  /* failure */
135  if (!NT_SUCCESS(nErrCode)) goto l_Cleanup;
136 
137  /* allocate space for the SIDs too */
138  nDaclBufSize += RtlLengthSid(psidSystem);
139  nDaclBufSize += RtlLengthSid(psidAdministrators);
140  nDaclBufSize += RtlLengthSid(psidEveryone);
141 
142  /* allocate the buffer for the DACL */
143  pDaclBuf = GlobalAlloc(GMEM_FIXED, nDaclBufSize);
144 
145  /* failure */
146  if (pDaclBuf == NULL) goto l_Cleanup;
147 
148  /* create the DACL */
149  nErrCode = RtlCreateAcl(pDaclBuf, nDaclBufSize, ACL_REVISION);
150 
151  /* failure */
152  if (!NT_SUCCESS(nErrCode)) goto l_Cleanup;
153 
154  /* grant the minimum required access to Everyone */
155  nErrCode = RtlAddAccessAllowedAce(pDaclBuf,
156  ACL_REVISION,
157  SYNCHRONIZE |
158  READ_CONTROL |
160  psidEveryone);
161 
162  /* failure */
163  if (!NT_SUCCESS(nErrCode)) goto l_Cleanup;
164 
165  /* grant full access to BUILTIN\Administrators */
166  nErrCode = RtlAddAccessAllowedAce(pDaclBuf,
167  ACL_REVISION,
169  psidAdministrators);
170 
171  /* failure */
172  if (!NT_SUCCESS(nErrCode)) goto l_Cleanup;
173 
174  /* grant full access to NT AUTHORITY\SYSTEM */
175  nErrCode = RtlAddAccessAllowedAce(pDaclBuf,
176  ACL_REVISION,
178  psidSystem);
179 
180  /* failure */
181  if (!NT_SUCCESS(nErrCode)) goto l_Cleanup;
182 
183  /* create the security descriptor */
184  nErrCode = RtlCreateSecurityDescriptor(&sdMutexSecurity,
186 
187  /* failure */
188  if (!NT_SUCCESS(nErrCode)) goto l_Cleanup;
189 
190  /* set the descriptor's DACL to the ACL we created */
191  nErrCode = RtlSetDaclSecurityDescriptor(&sdMutexSecurity,
192  TRUE,
193  pDaclBuf,
194  FALSE);
195 
196  /* failure */
197  if (!NT_SUCCESS(nErrCode)) goto l_Cleanup;
198 
199  /* create the mutex */
200  hMutex = CreateMutexW(&saMutexAttribs, FALSE, L"DBWinMutex");
201 
202 l_Cleanup:
203  /* free the buffers */
204  if (pDaclBuf) GlobalFree(pDaclBuf);
205  if (psidEveryone) RtlFreeSid(psidEveryone);
206  if (psidAdministrators) RtlFreeSid(psidAdministrators);
207  if (psidSystem) RtlFreeSid(psidSystem);
208 
209  return hMutex;
210 }
211 
212 VOID
213 WINAPI
216  IN HANDLE hThread)
217 {
219 
220  /* Allocate a thread structure */
221  ThreadData = RtlAllocateHeap(RtlGetProcessHeap(),
222  0,
223  sizeof(DBGSS_THREAD_DATA));
224  if (!ThreadData) return;
225 
226  /* Fill it out */
227  ThreadData->ThreadHandle = hThread;
228  ThreadData->ProcessId = dwProcessId;
229  ThreadData->ThreadId = dwThreadId;
230  ThreadData->ProcessHandle = NULL;
231  ThreadData->HandleMarked = FALSE;
232 
233  /* Link it */
234  ThreadData->Next = DbgSsGetThreadData();
236 }
237 
238 VOID
239 WINAPI
242 {
244 
245  /* Allocate a thread structure */
246  ThreadData = RtlAllocateHeap(RtlGetProcessHeap(),
247  0,
248  sizeof(DBGSS_THREAD_DATA));
249  if (!ThreadData) return;
250 
251  /* Fill it out */
252  ThreadData->ProcessHandle = hProcess;
253  ThreadData->ProcessId = dwProcessId;
254  ThreadData->ThreadId = 0;
255  ThreadData->ThreadHandle = NULL;
256  ThreadData->HandleMarked = FALSE;
257 
258  /* Link it */
259  ThreadData->Next = DbgSsGetThreadData();
261 }
262 
263 VOID
264 WINAPI
266 {
268 
269  /* Loop all thread data events */
271  {
272  /* Check if this one matches */
273  if (ThreadData->ThreadId == dwThreadId)
274  {
275  /* Mark the structure and break out */
276  ThreadData->HandleMarked = TRUE;
277  break;
278  }
279  }
280 }
281 
282 VOID
283 WINAPI
285 {
287 
288  /* Loop all thread data events */
290  {
291  /* Check if this one matches */
292  if ((ThreadData->ProcessId == dwProcessId) && !(ThreadData->ThreadId))
293  {
294  /* Mark the structure and break out */
295  ThreadData->HandleMarked = TRUE;
296  break;
297  }
298  }
299 }
300 
301 VOID
302 WINAPI
303 RemoveHandles(IN DWORD dwProcessId,
305 {
307  PDBGSS_THREAD_DATA ThisData;
308 
309  /* Loop all thread data events */
310  ThreadData = (PDBGSS_THREAD_DATA*)NtCurrentTeb()->DbgSsReserved;
311  ThisData = *ThreadData;
312  while(ThisData)
313  {
314  /* Check if this one matches */
315  if ((ThisData->HandleMarked) &&
316  ((ThisData->ProcessId == dwProcessId) || (ThisData->ThreadId == dwThreadId)))
317  {
318  /* Close open handles */
319  if (ThisData->ThreadHandle) CloseHandle(ThisData->ThreadHandle);
320  if (ThisData->ProcessHandle) CloseHandle(ThisData->ProcessHandle);
321 
322  /* Unlink the thread data */
323  *ThreadData = ThisData->Next;
324 
325  /* Free it*/
326  RtlFreeHeap(RtlGetProcessHeap(), 0, ThisData);
327  }
328  else
329  {
330  /* Move to the next one */
331  ThreadData = &ThisData->Next;
332  }
333  ThisData = *ThreadData;
334  }
335 }
336 
337 VOID
338 WINAPI
340 {
342  PDBGSS_THREAD_DATA ThisData;
343 
344  /* Loop all thread data events */
345  ThreadData = (PDBGSS_THREAD_DATA*)NtCurrentTeb()->DbgSsReserved;
346  ThisData = *ThreadData;
347  while(ThisData)
348  {
349  /* Check if this one matches */
350  if (ThisData->ProcessId == dwProcessId)
351  {
352  /* Close open handles */
353  if (ThisData->ThreadHandle) CloseHandle(ThisData->ThreadHandle);
354  if (ThisData->ProcessHandle) CloseHandle(ThisData->ProcessHandle);
355 
356  /* Unlink the thread data */
357  *ThreadData = ThisData->Next;
358 
359  /* Free it*/
360  RtlFreeHeap(RtlGetProcessHeap(), 0, ThisData);
361  }
362  else
363  {
364  /* Move to the next one */
365  ThreadData = &ThisData->Next;
366  }
367  ThisData = *ThreadData;
368  }
369 }
370 
371 HANDLE
372 WINAPI
374 {
377  HANDLE Handle;
379 
380  /* If we don't have a PID, look it up */
381  if (dwProcessId == MAXDWORD) dwProcessId = (DWORD_PTR)CsrGetProcessId();
382 
383  /* Open a handle to the process */
385  ClientId.UniqueProcess = UlongToHandle(dwProcessId);
392  &ClientId);
393  if (!NT_SUCCESS(Status))
394  {
395  /* Fail */
397  return 0;
398  }
399 
400  /* Return the handle */
401  return Handle;
402 }
403 
404 /* PUBLIC FUNCTIONS **********************************************************/
405 
406 /*
407  * @implemented
408  */
409 BOOL
410 WINAPI
412  OUT PBOOL pbDebuggerPresent)
413 {
414  HANDLE DebugPort;
416 
417  /* Make sure we have an output and process*/
418  if (!(pbDebuggerPresent) || !(hProcess))
419  {
420  /* Fail */
422  return FALSE;
423  }
424 
425  /* Check if the process has a debug object/port */
428  &DebugPort,
429  sizeof(DebugPort),
430  NULL);
431  if (NT_SUCCESS(Status))
432  {
433  /* Return the current state */
434  *pbDebuggerPresent = DebugPort != NULL;
435  return TRUE;
436  }
437 
438  /* Otherwise, fail */
440  return FALSE;
441 }
442 
443 /*
444  * @implemented
445  */
446 BOOL
447 WINAPI
450  IN DWORD dwContinueStatus)
451 {
454 
455  /* Set the Client ID */
456  ClientId.UniqueProcess = UlongToHandle(dwProcessId);
458 
459  /* Continue debugging */
460  Status = DbgUiContinue(&ClientId, dwContinueStatus);
461  if (!NT_SUCCESS(Status))
462  {
463  /* Fail */
465  return FALSE;
466  }
467 
468  /* Remove the process/thread handles */
469  RemoveHandles(dwProcessId, dwThreadId);
470 
471  /* Success */
472  return TRUE;
473 }
474 
475 /*
476  * @implemented
477  */
478 BOOL
479 WINAPI
481 {
482  NTSTATUS Status, Status1;
483  HANDLE Handle;
484 
485  /* Connect to the debugger */
487  if (!NT_SUCCESS(Status))
488  {
490  return FALSE;
491  }
492 
493  /* Get the process handle */
494  Handle = ProcessIdToHandle(dwProcessId);
495  if (!Handle) return FALSE;
496 
497  /* Now debug the process */
499 
500  /* Close the handle since we're done */
501  Status1 = NtClose(Handle);
502  ASSERT(NT_SUCCESS(Status1));
503 
504  /* Check if debugging worked */
505  if (!NT_SUCCESS(Status))
506  {
507  /* Fail */
509  return FALSE;
510  }
511 
512  /* Success */
513  return TRUE;
514 }
515 
516 /*
517  * @implemented
518  */
519 BOOL
520 WINAPI
522 {
523  NTSTATUS Status, Status1;
524  HANDLE Handle;
525 
526  /* Get the process handle */
527  Handle = ProcessIdToHandle(dwProcessId);
528  if (!Handle) return FALSE;
529 
530  /* Close all the process handles */
531  CloseAllProcessHandles(dwProcessId);
532 
533  /* Now stop debugging the process */
535  Status1 = NtClose(Handle);
536  ASSERT(NT_SUCCESS(Status1));
537 
538  /* Check for failure */
539  if (!NT_SUCCESS(Status))
540  {
541  /* Fail */
543  return FALSE;
544  }
545 
546  /* Success */
547  return TRUE;
548 }
549 
550 /*
551  * @implemented
552  */
553 BOOL
554 WINAPI
556 {
558 
559  /* Send the breakin request */
561  if (!NT_SUCCESS(Status))
562  {
563  /* Failure */
565  return FALSE;
566  }
567 
568  /* Success */
569  return TRUE;
570 }
571 
572 /*
573  * @implemented
574  */
575 BOOL
576 WINAPI
578 {
579  HANDLE Handle;
581  ULONG State;
582 
583  /* Get the debug object */
585  if (!Handle)
586  {
587  /* Fail */
589  return FALSE;
590  }
591 
592  /* Now set the kill-on-exit state */
593  State = KillOnExit != 0;
596  &State,
597  sizeof(State),
598  NULL);
599  if (!NT_SUCCESS(Status))
600  {
601  /* Fail */
603  return FALSE;
604  }
605 
606  /* Success */
607  return TRUE;
608 }
609 
610 /*
611  * @implemented
612  */
613 BOOL
614 WINAPI
616 {
617  return (BOOL)NtCurrentPeb()->BeingDebugged;
618 }
619 
620 /*
621  * @implemented
622  */
623 BOOL
624 WINAPI
626  IN DWORD dwMilliseconds)
627 {
628  LARGE_INTEGER WaitTime;
630  DBGUI_WAIT_STATE_CHANGE WaitStateChange;
632 
633  /* Convert to NT Timeout */
634  Timeout = BaseFormatTimeOut(&WaitTime, dwMilliseconds);
635 
636  /* Loop while we keep getting interrupted */
637  do
638  {
639  /* Call the native API */
640  Status = DbgUiWaitStateChange(&WaitStateChange, Timeout);
641  } while ((Status == STATUS_ALERTED) || (Status == STATUS_USER_APC));
642 
643  /* Check if the wait failed */
645  {
646  /* Set the error code and quit */
648  return FALSE;
649  }
650 
651  /* Check if we timed out */
652  if (Status == STATUS_TIMEOUT)
653  {
654  /* Fail with a timeout error */
656  return FALSE;
657  }
658 
659  /* Convert the structure */
660  Status = DbgUiConvertStateChangeStructure(&WaitStateChange, lpDebugEvent);
661  if (!NT_SUCCESS(Status))
662  {
663  /* Set the error code and quit */
665  return FALSE;
666  }
667 
668  /* Check what kind of event this was */
669  switch (lpDebugEvent->dwDebugEventCode)
670  {
671  /* New thread was created */
673 
674  /* Setup the thread data */
675  SaveThreadHandle(lpDebugEvent->dwProcessId,
676  lpDebugEvent->dwThreadId,
677  lpDebugEvent->u.CreateThread.hThread);
678  break;
679 
680  /* New process was created */
682 
683  /* Setup the process data */
684  SaveProcessHandle(lpDebugEvent->dwProcessId,
685  lpDebugEvent->u.CreateProcessInfo.hProcess);
686 
687  /* Setup the thread data */
688  SaveThreadHandle(lpDebugEvent->dwProcessId,
689  lpDebugEvent->dwThreadId,
690  lpDebugEvent->u.CreateProcessInfo.hThread);
691  break;
692 
693  /* Process was exited */
695 
696  /* Mark the thread data as such and fall through */
697  MarkProcessHandle(lpDebugEvent->dwProcessId);
698 
699  /* Thread was exited */
701 
702  /* Mark the thread data */
703  MarkThreadHandle(lpDebugEvent->dwThreadId);
704  break;
705 
706  /* Nothing to do */
711  case RIP_EVENT:
712  break;
713 
714  /* Fail anything else */
715  default:
716  return FALSE;
717  }
718 
719  /* Return success */
720  return TRUE;
721 }
722 
723 /*
724  * @implemented
725  */
726 VOID
727 WINAPI
729 {
730  _SEH2_TRY
731  {
732  ULONG_PTR a_nArgs[2];
733 
734  a_nArgs[0] = (ULONG_PTR)(strlen(_OutputString) + 1);
735  a_nArgs[1] = (ULONG_PTR)_OutputString;
736 
737  /* send the string to the user-mode debugger */
738  RaiseException(DBG_PRINTEXCEPTION_C, 0, 2, a_nArgs);
739  }
741  {
742  /* no user-mode debugger: try the systemwide debug message monitor, or the
743  kernel debugger as a last resort */
744 
745  /* mutex used to synchronize invocations of OutputDebugString */
746  static HANDLE s_hDBMonMutex = NULL;
747  /* true if we already attempted to open/create the mutex */
748  static BOOL s_bDBMonMutexTriedOpen = FALSE;
749 
750  /* local copy of the mutex handle */
751  volatile HANDLE hDBMonMutex = s_hDBMonMutex;
752  /* handle to the Section of the shared buffer */
753  volatile HANDLE hDBMonBuffer = NULL;
754 
755  /* pointer to the mapped view of the shared buffer. It consist of the current
756  process id followed by the message string */
757  struct { DWORD ProcessId; CHAR Buffer[1]; } * pDBMonBuffer = NULL;
758 
759  /* event: signaled by the debug message monitor when OutputDebugString can write
760  to the shared buffer */
761  volatile HANDLE hDBMonBufferReady = NULL;
762 
763  /* event: to be signaled by OutputDebugString when it's done writing to the
764  shared buffer */
765  volatile HANDLE hDBMonDataReady = NULL;
766 
767  /* mutex not opened, and no previous attempts to open/create it */
768  if (hDBMonMutex == NULL && !s_bDBMonMutexTriedOpen)
769  {
770  /* open/create the mutex */
771  hDBMonMutex = K32CreateDBMonMutex();
772  /* store the handle */
773  s_hDBMonMutex = hDBMonMutex;
774  }
775 
776  _SEH2_TRY
777  {
778  volatile PCHAR a_cBuffer = NULL;
779 
780  /* opening the mutex failed */
781  if (hDBMonMutex == NULL)
782  {
783  /* remember next time */
784  s_bDBMonMutexTriedOpen = TRUE;
785  }
786  /* opening the mutex succeeded */
787  else
788  {
789  do
790  {
791  /* synchronize with other invocations of OutputDebugString */
792  WaitForSingleObject(hDBMonMutex, INFINITE);
793 
794  /* buffer of the system-wide debug message monitor */
795  hDBMonBuffer = OpenFileMappingW(SECTION_MAP_WRITE, FALSE, L"DBWIN_BUFFER");
796 
797  /* couldn't open the buffer: send the string to the kernel debugger */
798  if (hDBMonBuffer == NULL) break;
799 
800  /* map the buffer */
801  pDBMonBuffer = MapViewOfFile(hDBMonBuffer,
803  0,
804  0,
805  0);
806 
807  /* couldn't map the buffer: send the string to the kernel debugger */
808  if (pDBMonBuffer == NULL) break;
809 
810  /* open the event signaling that the buffer can be accessed */
811  hDBMonBufferReady = OpenEventW(SYNCHRONIZE, FALSE, L"DBWIN_BUFFER_READY");
812 
813  /* couldn't open the event: send the string to the kernel debugger */
814  if (hDBMonBufferReady == NULL) break;
815 
816  /* open the event to be signaled when the buffer has been filled */
817  hDBMonDataReady = OpenEventW(EVENT_MODIFY_STATE, FALSE, L"DBWIN_DATA_READY");
818  }
819  while(0);
820 
821  /* we couldn't connect to the system-wide debug message monitor: send the
822  string to the kernel debugger */
823  if (hDBMonDataReady == NULL) ReleaseMutex(hDBMonMutex);
824  }
825 
826  _SEH2_TRY
827  {
828  /* size of the current output block */
829  volatile SIZE_T nRoundLen;
830 
831  /* size of the remainder of the string */
832  volatile SIZE_T nOutputStringLen;
833 
834  /* output the whole string */
835  nOutputStringLen = strlen(_OutputString);
836 
837  do
838  {
839  /* we're connected to the debug monitor:
840  write the current block to the shared buffer */
841  if (hDBMonDataReady)
842  {
843  /* wait a maximum of 10 seconds for the debug monitor
844  to finish processing the shared buffer */
845  if (WaitForSingleObject(hDBMonBufferReady, 10000) != WAIT_OBJECT_0)
846  {
847  /* timeout or failure: give up */
848  break;
849  }
850 
851  /* write the process id into the buffer */
852  pDBMonBuffer->ProcessId = GetCurrentProcessId();
853 
854  /* write only as many bytes as they fit in the buffer */
855  if (nOutputStringLen > (PAGE_SIZE - sizeof(DWORD) - 1))
856  nRoundLen = PAGE_SIZE - sizeof(DWORD) - 1;
857  else
858  nRoundLen = nOutputStringLen;
859 
860  /* copy the current block into the buffer */
861  memcpy(pDBMonBuffer->Buffer, _OutputString, nRoundLen);
862 
863  /* null-terminate the current block */
864  pDBMonBuffer->Buffer[nRoundLen] = 0;
865 
866  /* signal that the data contains meaningful data and can be read */
867  SetEvent(hDBMonDataReady);
868  }
869  /* else, send the current block to the kernel debugger */
870  else
871  {
872  /* output in blocks of 512 characters */
873  a_cBuffer = (CHAR*)HeapAlloc(GetProcessHeap(), 0, 512);
874 
875  if (!a_cBuffer)
876  {
877  DbgPrint("OutputDebugStringA: Failed\n");
878  break;
879  }
880 
881  /* write a maximum of 511 bytes */
882  if (nOutputStringLen > 510)
883  nRoundLen = 510;
884  else
885  nRoundLen = nOutputStringLen;
886 
887  /* copy the current block */
888  memcpy(a_cBuffer, _OutputString, nRoundLen);
889 
890  /* null-terminate the current block */
891  a_cBuffer[nRoundLen] = 0;
892 
893  /* send the current block to the kernel debugger */
894  DbgPrint("%s", a_cBuffer);
895 
896  if (a_cBuffer)
897  {
898  HeapFree(GetProcessHeap(), 0, a_cBuffer);
899  a_cBuffer = NULL;
900  }
901  }
902 
903  /* move to the next block */
904  _OutputString += nRoundLen;
905  nOutputStringLen -= nRoundLen;
906  }
907  /* repeat until the string has been fully output */
908  while (nOutputStringLen > 0);
909  }
910  /* ignore access violations and let other exceptions fall through */
912  {
913  if (a_cBuffer)
914  HeapFree(GetProcessHeap(), 0, a_cBuffer);
915 
916  /* string copied verbatim from Microsoft's kernel32.dll */
917  DbgPrint("\nOutputDebugString faulted during output\n");
918  }
919  _SEH2_END;
920  }
922  {
923  /* close all the still open resources */
924  if (hDBMonBufferReady) CloseHandle(hDBMonBufferReady);
925  if (pDBMonBuffer) UnmapViewOfFile(pDBMonBuffer);
926  if (hDBMonBuffer) CloseHandle(hDBMonBuffer);
927  if (hDBMonDataReady) CloseHandle(hDBMonDataReady);
928 
929  /* leave the critical section */
930  if (hDBMonDataReady != NULL)
931  ReleaseMutex(hDBMonMutex);
932  }
933  _SEH2_END;
934  }
935  _SEH2_END;
936 }
937 
938 /*
939  * @implemented
940  */
941 VOID
942 WINAPI
944 {
948 
949  /* convert the string in ANSI */
950  RtlInitUnicodeString(&UnicodeString, OutputString);
952 
953  /* OutputDebugStringW always prints something, even if conversion fails */
954  if (!NT_SUCCESS(Status)) AnsiString.Buffer = "";
955 
956  /* Output the converted string */
958 
959  /* free the converted string */
961 }
962 
963 /* EOF */
HANDLE NTAPI DbgUiGetThreadDebugObject(VOID)
Definition: dbgui.c:333
signed char * PCHAR
Definition: retypes.h:7
#define ERROR_INVALID_PARAMETER
Definition: compat.h:91
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:35
HANDLE WINAPI ProcessIdToHandle(IN DWORD dwProcessId)
Definition: debugger.c:373
NTSTATUS NTAPI DbgUiConnectToDbg(VOID)
Definition: dbgui.c:25
#define IN
Definition: typedefs.h:38
#define SECURITY_LOCAL_SYSTEM_RID
Definition: setypes.h:546
#define TRUE
Definition: types.h:120
HGLOBAL NTAPI GlobalAlloc(UINT uFlags, SIZE_T dwBytes)
Definition: heapmem.c:368
#define CloseHandle
Definition: compat.h:398
*BytesInUnicodeString PWCH UnicodeString
Definition: rtlfuncs.h:1980
#define MapViewOfFile
Definition: compat.h:402
#define DWORD_PTR
Definition: treelist.c:76
VOID WINAPI OutputDebugStringA(IN LPCSTR _OutputString)
Definition: debugger.c:728
VOID WINAPI MarkProcessHandle(IN DWORD dwProcessId)
Definition: debugger.c:284
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
#define PROCESS_QUERY_INFORMATION
Definition: pstypes.h:158
#define DbgPrint
Definition: loader.c:25
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
BOOL WINAPI IsDebuggerPresent(VOID)
Definition: debugger.c:615
NTSTATUS NTAPI DbgUiStopDebugging(IN HANDLE Process)
Definition: dbgui.c:381
NTSYSAPI PVOID NTAPI RtlFreeSid(_In_ _Post_invalid_ PSID Sid)
#define DbgSsSetThreadData(d)
Definition: debugger.c:28
char CHAR
Definition: xmlstorage.h:175
LONG NTSTATUS
Definition: precomp.h:26
BOOL WINAPI ContinueDebugEvent(IN DWORD dwProcessId, IN DWORD dwThreadId, IN DWORD dwContinueStatus)
Definition: debugger.c:448
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:606
NTSTATUS NTAPI NtQueryInformationProcess(IN HANDLE ProcessHandle, IN PROCESSINFOCLASS ProcessInformationClass, OUT PVOID ProcessInformation, IN ULONG ProcessInformationLength, OUT PULONG ReturnLength OPTIONAL)
Definition: query.c:59
BOOL WINAPI DECLSPEC_HOTPATCH SetEvent(IN HANDLE hEvent)
Definition: synch.c:733
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
_In_ BOOL _In_ HANDLE hProcess
Definition: mapping.h:70
BOOLEAN HandleMarked
Definition: debugger.c:25
NTSYSAPI NTSTATUS NTAPI RtlCreateSecurityDescriptor(_Out_ PSECURITY_DESCRIPTOR SecurityDescriptor, _In_ ULONG Revision)
#define LOAD_DLL_DEBUG_EVENT
Definition: winbase.h:107
#define PROCESS_SUSPEND_RESUME
Definition: pstypes.h:159
HANDLE UniqueProcess
Definition: compat.h:474
struct _DBGSS_THREAD_DATA * PDBGSS_THREAD_DATA
#define STATUS_ALERTED
Definition: ntstatus.h:80
NTSYSAPI NTSTATUS NTAPI RtlAllocateAndInitializeSid(IN PSID_IDENTIFIER_AUTHORITY IdentifierAuthority, IN UCHAR SubAuthorityCount, IN ULONG SubAuthority0, IN ULONG SubAuthority1, IN ULONG SubAuthority2, IN ULONG SubAuthority3, IN ULONG SubAuthority4, IN ULONG SubAuthority5, IN ULONG SubAuthority6, IN ULONG SubAuthority7, OUT PSID *Sid)
Definition: sid.c:290
NTSTATUS NTAPI NtOpenProcess(OUT PHANDLE ProcessHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, IN PCLIENT_ID ClientId)
Definition: process.c:1440
#define DWORD
Definition: nt_native.h:44
NTSYSAPI NTSTATUS WINAPI RtlAddAccessAllowedAce(PACL, DWORD, DWORD, PSID)
BOOL WINAPI DebugSetProcessKillOnExit(IN BOOL KillOnExit)
Definition: debugger.c:577
PLARGE_INTEGER WINAPI BaseFormatTimeOut(OUT PLARGE_INTEGER Timeout, IN DWORD dwMilliseconds)
Definition: utils.c:288
#define STATUS_INVALID_HANDLE
Definition: ntstatus.h:231
#define PROCESS_CREATE_THREAD
Definition: pstypes.h:150
_SEH2_TRY
Definition: create.c:4250
HANDLE WINAPI DECLSPEC_HOTPATCH OpenEventW(IN DWORD dwDesiredAccess, IN BOOL bInheritHandle, IN LPCWSTR lpName)
Definition: synch.c:682
NTSYSAPI NTSTATUS NTAPI RtlCreateAcl(PACL Acl, ULONG AclSize, ULONG AclRevision)
static HANDLE K32CreateDBMonMutex(void)
Definition: debugger.c:38
uint32_t ULONG_PTR
Definition: typedefs.h:63
#define SECURITY_DESCRIPTOR_REVISION
Definition: setypes.h:58
#define STATUS_TIMEOUT
Definition: ntstatus.h:81
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
#define EXCEPTION_CONTINUE_SEARCH
Definition: excpt.h:86
VOID WINAPI CloseAllProcessHandles(IN DWORD dwProcessId)
Definition: debugger.c:339
#define ERROR_ACCESS_DENIED
Definition: compat.h:87
unsigned int BOOL
Definition: ntddk_ex.h:94
#define MUTANT_ALL_ACCESS
Definition: extypes.h:110
VOID WINAPI MarkThreadHandle(IN DWORD dwThreadId)
Definition: debugger.c:265
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
HANDLE WINAPI DECLSPEC_HOTPATCH OpenMutexW(IN DWORD dwDesiredAccess, IN BOOL bInheritHandle, IN LPCWSTR lpName)
Definition: synch.c:605
unsigned char BOOLEAN
struct _ACL ACL
smooth NULL
Definition: ftsmooth.c:416
#define UNLOAD_DLL_DEBUG_EVENT
Definition: winbase.h:108
NTSYSAPI NTSTATUS WINAPI RtlSetDaclSecurityDescriptor(PSECURITY_DESCRIPTOR, BOOLEAN, PACL, BOOLEAN)
SIZE_T LPDEBUG_EVENT
Definition: cordebug.idl:83
#define MAXDWORD
Definition: bufpool.h:45
NTSYSAPI ULONG NTAPI RtlLengthSid(IN PSID Sid)
Definition: sid.c:150
DWORD BaseSetLastNTError(IN NTSTATUS Status)
Definition: reactos.cpp:166
NTSYSAPI NTSTATUS NTAPI RtlUnicodeStringToAnsiString(PANSI_STRING DestinationString, PUNICODE_STRING SourceString, BOOLEAN AllocateDestinationString)
const char * LPCSTR
Definition: xmlstorage.h:183
HANDLE hMutex
Definition: mutex.c:11
BOOL * PBOOL
Definition: windef.h:161
NTSTATUS NTAPI DbgUiContinue(IN PCLIENT_ID ClientId, IN NTSTATUS ContinueStatus)
Definition: dbgui.c:47
#define ERROR_FILE_NOT_FOUND
Definition: disk.h:79
#define SECURITY_NT_AUTHORITY
Definition: setypes.h:526
NTSTATUS NTAPI DbgUiDebugActiveProcess(IN HANDLE Process)
Definition: dbgui.c:355
#define SECTION_MAP_WRITE
Definition: nt_native.h:1288
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:588
HANDLE ProcessHandle
Definition: debugger.c:22
_In_ HANDLE Handle
Definition: extypes.h:390
#define EXIT_PROCESS_DEBUG_EVENT
Definition: winbase.h:106
#define WAIT_OBJECT_0
Definition: winbase.h:387
_Out_ PCLIENT_ID ClientId
Definition: kefuncs.h:1176
#define PROCESS_VM_WRITE
Definition: pstypes.h:154
#define GetProcessHeap()
Definition: compat.h:395
BOOL WINAPI DebugActiveProcessStop(IN DWORD dwProcessId)
Definition: debugger.c:521
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
#define SECURITY_BUILTIN_DOMAIN_RID
Definition: setypes.h:553
#define CREATE_THREAD_DEBUG_EVENT
Definition: winbase.h:103
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define SECURITY_WORLD_SID_AUTHORITY
Definition: setypes.h:499
#define UlongToHandle(ul)
Definition: basetsd.h:97
VOID WINAPI OutputDebugStringW(IN LPCWSTR OutputString)
Definition: debugger.c:943
BOOL WINAPI DebugBreakProcess(IN HANDLE Process)
Definition: debugger.c:555
#define WINAPI
Definition: msvc.h:8
NTSYSAPI VOID NTAPI RtlFreeAnsiString(PANSI_STRING AnsiString)
unsigned long DWORD
Definition: ntddk_ex.h:95
#define DBG_UNABLE_TO_PROVIDE_HANDLE
Definition: ntstatus.h:49
HGLOBAL NTAPI GlobalFree(HGLOBAL hMem)
Definition: heapmem.c:611
#define SetLastError(x)
Definition: compat.h:409
NTSTATUS NTAPI DbgUiConvertStateChangeStructure(IN PDBGUI_WAIT_STATE_CHANGE WaitStateChange, OUT PVOID Win32DebugEvent)
Definition: dbgui.c:61
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3399
NTSTATUS NTAPI DbgUiWaitStateChange(OUT PDBGUI_WAIT_STATE_CHANGE WaitStateChange, IN PLARGE_INTEGER TimeOut OPTIONAL)
Definition: dbgui.c:274
HANDLE UniqueThread
Definition: compat.h:475
#define READ_CONTROL
Definition: nt_native.h:58
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
BOOL WINAPI DECLSPEC_HOTPATCH ReleaseMutex(IN HANDLE hMutex)
Definition: synch.c:618
BOOL WINAPI WaitForDebugEvent(IN LPDEBUG_EVENT lpDebugEvent, IN DWORD dwMilliseconds)
Definition: debugger.c:625
DWORD dwThreadId
Definition: fdebug.c:31
NTSTATUS NTAPI DbgUiIssueRemoteBreakin(IN HANDLE Process)
Definition: dbgui.c:303
static const WCHAR L[]
Definition: oid.c:1250
#define GMEM_FIXED
Definition: winbase.h:290
#define SECTION_MAP_READ
Definition: compat.h:128
#define DbgSsGetThreadData()
Definition: debugger.c:31
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define PAGE_SIZE
Definition: env_spec_w32.h:49
#define DBG_PRINTEXCEPTION_C
Definition: ntstatus.h:53
#define SYNCHRONIZE
Definition: nt_native.h:61
HANDLE NTAPI OpenFileMappingW(IN DWORD dwDesiredAccess, IN BOOL bInheritHandle, IN LPCWSTR lpName)
Definition: filemap.c:297
BOOL WINAPI CheckRemoteDebuggerPresent(IN HANDLE hProcess, OUT PBOOL pbDebuggerPresent)
Definition: debugger.c:411
VOID WINAPI SaveProcessHandle(IN DWORD dwProcessId, IN HANDLE hProcess)
Definition: debugger.c:240
Status
Definition: gdiplustypes.h:24
#define STATUS_USER_APC
Definition: ntstatus.h:78
VOID WINAPI RemoveHandles(IN DWORD dwProcessId, IN DWORD dwThreadId)
Definition: debugger.c:303
ULONG_PTR SIZE_T
Definition: typedefs.h:78
HANDLE NTAPI CsrGetProcessId(VOID)
Definition: connect.c:501
enum State_ State
Definition: pofuncs.h:54
_SEH2_END
Definition: create.c:4424
static ULONG Timeout
Definition: ping.c:61
struct _DBGSS_THREAD_DATA DBGSS_THREAD_DATA
FORCEINLINE struct _TEB * NtCurrentTeb(VOID)
Definition: psfuncs.h:420
VOID WINAPI RaiseException(IN DWORD dwExceptionCode, IN DWORD dwExceptionFlags, IN DWORD nNumberOfArguments, IN CONST ULONG_PTR *lpArguments OPTIONAL)
Definition: except.c:693
#define NtCurrentPeb()
Definition: FLS.c:20
#define STATUS_ACCESS_VIOLATION
Definition: ntstatus.h:228
VOID WINAPI SaveThreadHandle(IN DWORD dwProcessId, IN DWORD dwThreadId, IN HANDLE hThread)
Definition: debugger.c:214
#define EXCEPTION_DEBUG_EVENT
Definition: winbase.h:102
HANDLE WINAPI DECLSPEC_HOTPATCH CreateMutexW(IN LPSECURITY_ATTRIBUTES lpMutexAttributes OPTIONAL, IN BOOL bInitialOwner, IN LPCWSTR lpName OPTIONAL)
Definition: synch.c:576
_SEH2_FINALLY
Definition: create.c:4395
#define ERROR_SEM_TIMEOUT
Definition: winerror.h:193
NTSTATUS NTAPI NtSetInformationDebugObject(IN HANDLE DebugHandle, IN DEBUGOBJECTINFOCLASS DebugObjectInformationClass, IN PVOID DebugInformation, IN ULONG DebugInformationLength, OUT PULONG ReturnLength OPTIONAL)
Definition: dbgkobj.c:1921
HANDLE hThread
Definition: wizard.c:27
#define EXIT_THREAD_DEBUG_EVENT
Definition: winbase.h:105
#define ACL_REVISION
Definition: setypes.h:39
#define PROCESS_VM_READ
Definition: pstypes.h:153
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:219
#define OUT
Definition: typedefs.h:39
unsigned int ULONG
Definition: retypes.h:1
#define OUTPUT_DEBUG_STRING_EVENT
Definition: winbase.h:109
#define EVENT_MODIFY_STATE
Definition: winbase.h:163
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define ULONG_PTR
Definition: config.h:101
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
#define PROCESS_VM_OPERATION
Definition: pstypes.h:152
#define CREATE_PROCESS_DEBUG_EVENT
Definition: winbase.h:104
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
BOOL WINAPI DebugActiveProcess(IN DWORD dwProcessId)
Definition: debugger.c:480
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:12
HANDLE ThreadHandle
Definition: debugger.c:21
#define INFINITE
Definition: serial.h:102
#define UnmapViewOfFile
Definition: compat.h:403
#define MUTANT_QUERY_STATE
Definition: extypes.h:109
#define DOMAIN_ALIAS_RID_ADMINS
Definition: setypes.h:624
struct _DBGSS_THREAD_DATA * Next
Definition: debugger.c:20
#define HeapFree(x, y, z)
Definition: compat.h:394
#define RIP_EVENT
Definition: winbase.h:110
DWORD WINAPI GetCurrentProcessId(VOID)
Definition: proc.c:1158