ReactOS  0.4.14-dev-77-gd9e7c48
dbgkobj.c
Go to the documentation of this file.
1 /*
2  * PROJECT: ReactOS Kernel
3  * LICENSE: GPL - See COPYING in the top level directory
4  * FILE: ntoskrnl/dbgk/dbgkobj.c
5  * PURPOSE: User-Mode Debugging Support, Debug Object Management.
6  * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
7  */
8 
9 /* INCLUDES ******************************************************************/
10 
11 #include <ntoskrnl.h>
12 #define NDEBUG
13 #include <debug.h>
14 
18 
20 {
25 };
26 
27 static const INFORMATION_CLASS_INFO DbgkpDebugObjectInfoClass[] =
28 {
29  /* DebugObjectUnusedInformation */
30  ICI_SQ_SAME(sizeof(ULONG), sizeof(ULONG), 0),
31  /* DebugObjectKillProcessOnExitInformation */
32  ICI_SQ_SAME(sizeof(DEBUG_OBJECT_KILL_PROCESS_ON_EXIT_INFORMATION), sizeof(ULONG), ICIF_SET),
33 };
34 
35 /* PRIVATE FUNCTIONS *********************************************************/
36 
38 NTAPI
42  IN ULONG Flags,
43  IN PDEBUG_OBJECT TargetObject OPTIONAL)
44 {
46  DEBUG_EVENT LocalDebugEvent;
47  PDEBUG_OBJECT DebugObject;
49  BOOLEAN NewEvent;
50  PAGED_CODE();
52  "Process: %p Thread: %p Message: %p Flags: %lx\n",
54 
55  /* Check if we have to allocate a debug event */
56  NewEvent = (Flags & DEBUG_EVENT_NOWAIT) ? TRUE : FALSE;
57  if (NewEvent)
58  {
59  /* Allocate it */
61  sizeof(DEBUG_EVENT),
62  'EgbD');
64 
65  /* Set flags */
67 
68  /* Reference the thread and process */
71 
72  /* Set the current thread */
73  DebugEvent->BackoutThread = PsGetCurrentThread();
74 
75  /* Set the debug object */
76  DebugObject = TargetObject;
77  }
78  else
79  {
80  /* Use the debug event on the stack */
81  DebugEvent = &LocalDebugEvent;
82  DebugEvent->Flags = Flags;
83 
84  /* Acquire the port lock */
86 
87  /* Get the debug object */
88  DebugObject = Process->DebugPort;
89 
90  /* Check what kind of API message this is */
91  switch (Message->ApiNumber)
92  {
93  /* Process or thread creation */
96 
97  /* Make sure we're not skipping creation messages */
98  if (Thread->SkipCreationMsg) DebugObject = NULL;
99  break;
100 
101  /* Process or thread exit */
102  case DbgKmExitThreadApi:
103  case DbgKmExitProcessApi:
104 
105  /* Make sure we're not skipping exit messages */
106  if (Thread->SkipTerminationMsg) DebugObject = NULL;
107 
108  /* No special handling for other messages */
109  default:
110  break;
111  }
112  }
113 
114  /* Setup the Debug Event */
116  DebugEvent->Process = Process;
117  DebugEvent->Thread = Thread;
118  DebugEvent->ApiMsg = *Message;
119  DebugEvent->ClientId = Thread->Cid;
120 
121  /* Check if we have a port object */
122  if (!DebugObject)
123  {
124  /* Fail */
126  }
127  else
128  {
129  /* Acquire the debug object mutex */
130  ExAcquireFastMutex(&DebugObject->Mutex);
131 
132  /* Check if a debugger is active */
133  if (!DebugObject->DebuggerInactive)
134  {
135  /* Add the event into the object's list */
136  DBGKTRACE(DBGK_MESSAGE_DEBUG, "Inserting: %p %d\n",
137  DebugEvent, Message->ApiNumber);
138  InsertTailList(&DebugObject->EventList, &DebugEvent->EventList);
139 
140  /* Check if we have to signal it */
141  if (!NewEvent)
142  {
143  /* Signal it */
144  KeSetEvent(&DebugObject->EventsPresent,
146  FALSE);
147  }
148 
149  /* Set success */
151  }
152  else
153  {
154  /* No debugger */
156  }
157 
158  /* Release the object lock */
159  ExReleaseFastMutex(&DebugObject->Mutex);
160  }
161 
162  /* Check if we had acquired the port lock */
163  if (!NewEvent)
164  {
165  /* Release it */
167 
168  /* Check if we got here through success */
169  if (NT_SUCCESS(Status))
170  {
171  /* Wait on the continue event */
172  KeWaitForSingleObject(&DebugEvent->ContinueEvent,
173  Executive,
174  KernelMode,
175  FALSE,
176  NULL);
177 
178  /* Copy API Message back */
179  *Message = DebugEvent->ApiMsg;
180 
181  /* Set return status */
182  Status = DebugEvent->Status;
183  }
184  }
185  else
186  {
187  /* Check if we failed */
188  if (!NT_SUCCESS(Status))
189  {
190  /* Dereference the process and thread */
193 
194  /* Free the debug event */
195  ExFreePoolWithTag(DebugEvent, 'EgbD');
196  }
197  }
198 
199  /* Return status */
200  DBGKTRACE(DBGK_MESSAGE_DEBUG, "Status: %lx\n", Status);
201  return Status;
202 }
203 
204 NTSTATUS
205 NTAPI
207  IN PVOID Port,
208  IN BOOLEAN SuspendProcess)
209 {
213  PAGED_CODE();
214 
215  /* Suspend process if required */
216  if (SuspendProcess) Suspended = DbgkpSuspendProcess();
217 
218  /* Set return status */
219  Message->ReturnedStatus = STATUS_PENDING;
220 
221  /* Set create process reported state */
223 
224  /* Send the LPC command */
227  (PPORT_MESSAGE)&Buffer[0]);
228 
229  /* Flush the instruction cache */
231 
232  /* Copy the buffer back */
234 
235  /* Resume the process if it was suspended */
237  return Status;
238 }
239 
240 NTSTATUS
241 NTAPI
243  IN BOOLEAN SuspendProcess)
244 {
247  PAGED_CODE();
248  DBGKTRACE(DBGK_MESSAGE_DEBUG, "ApiMsg: %p SuspendProcess: %lx\n", ApiMsg, SuspendProcess);
249 
250  /* Suspend process if required */
251  if (SuspendProcess) Suspended = DbgkpSuspendProcess();
252 
253  /* Set return status */
254  ApiMsg->ReturnedStatus = STATUS_PENDING;
255 
256  /* Set create process reported state */
258 
259  /* Send the LPC command */
262  ApiMsg,
263  0,
264  NULL);
265 
266  /* Flush the instruction cache */
268 
269  /* Resume the process if it was suspended */
271  return Status;
272 }
273 
274 VOID
275 NTAPI
278 {
279  PDEBUG_OBJECT DebugObject;
280  PAGED_CODE();
281  DBGKTRACE(DBGK_PROCESS_DEBUG, "Process: %p Parent: %p\n", Process, Parent);
282 
283  /* Clear this process's port */
284  Process->DebugPort = NULL;
285 
286  /* Check if the parent has one */
287  if (!Parent->DebugPort) return;
288 
289  /* It does, acquire the mutex */
291 
292  /* Make sure it still has one, and that we should inherit */
293  DebugObject = Parent->DebugPort;
294  if ((DebugObject) && !(Process->NoDebugInherit))
295  {
296  /* Acquire the debug object's lock */
297  ExAcquireFastMutex(&DebugObject->Mutex);
298 
299  /* Make sure the debugger is active */
300  if (!DebugObject->DebuggerInactive)
301  {
302  /* Reference the object and set it */
303  ObReferenceObject(DebugObject);
304  Process->DebugPort = DebugObject;
305  }
306 
307  /* Release the debug object */
308  ExReleaseFastMutex(&DebugObject->Mutex);
309  }
310 
311  /* Release the port mutex */
313 }
314 
315 BOOLEAN
316 NTAPI
318  IN BOOLEAN DebugPort,
319  IN BOOLEAN SecondChance)
320 {
321  DBGKM_MSG ApiMessage;
322  PDBGKM_EXCEPTION DbgKmException = &ApiMessage.Exception;
325  PVOID Port;
326  BOOLEAN UseLpc = FALSE;
327  PAGED_CODE();
329  "ExceptionRecord: %p Port: %u\n", ExceptionRecord, DebugPort);
330 
331  /* Setup the API Message */
332  ApiMessage.h.u1.Length = sizeof(DBGKM_MSG) << 16 |
333  (8 + sizeof(DBGKM_EXCEPTION));
334  ApiMessage.h.u2.ZeroInit = 0;
335  ApiMessage.h.u2.s2.Type = LPC_DEBUG_EVENT;
336  ApiMessage.ApiNumber = DbgKmExceptionApi;
337 
338  /* Check if this is to be sent on the debug port */
339  if (DebugPort)
340  {
341  /* Use the debug port, unless the thread is being hidden */
342  Port = PsGetCurrentThread()->HideFromDebugger ?
343  NULL : Process->DebugPort;
344  }
345  else
346  {
347  /* Otherwise, use the exception port */
348  Port = Process->ExceptionPort;
349  ApiMessage.h.u2.ZeroInit = 0;
350  ApiMessage.h.u2.s2.Type = LPC_EXCEPTION;
351  UseLpc = TRUE;
352  }
353 
354  /* Break out if there's no port */
355  if (!Port) return FALSE;
356 
357  /* Fill out the exception information */
358  DbgKmException->ExceptionRecord = *ExceptionRecord;
359  DbgKmException->FirstChance = !SecondChance;
360 
361  /* Check if we should use LPC */
362  if (UseLpc)
363  {
364  /* Send the message on the LPC Port */
365  Status = DbgkpSendApiMessageLpc(&ApiMessage, Port, DebugPort);
366  }
367  else
368  {
369  /* Use native debug object */
370  Status = DbgkpSendApiMessage(&ApiMessage, DebugPort);
371  }
372 
373  /* Check if we failed, and for a debug port, also check the return status */
374  if (!(NT_SUCCESS(Status)) ||
375  ((DebugPort) &&
376  (!(NT_SUCCESS(ApiMessage.ReturnedStatus)) ||
377  (ApiMessage.ReturnedStatus == DBG_EXCEPTION_NOT_HANDLED))))
378  {
379  /* Fail */
380  return FALSE;
381  }
382 
383  /* Otherwise, we're ok */
384  return TRUE;
385 }
386 
387 VOID
388 NTAPI
390 {
391  PHANDLE Handle = NULL;
392  PAGED_CODE();
393  DBGKTRACE(DBGK_OBJECT_DEBUG, "DebugEvent: %p\n", DebugEvent);
394 
395  /* Check if this event had a file handle */
396  switch (DebugEvent->ApiMsg.ApiNumber)
397  {
398  /* Create process has a handle */
400 
401  /* Get the pointer */
402  Handle = &DebugEvent->ApiMsg.CreateProcess.FileHandle;
403  break;
404 
405  /* As does DLL load */
406  case DbgKmLoadDllApi:
407 
408  /* Get the pointer */
409  Handle = &DebugEvent->ApiMsg.LoadDll.FileHandle;
410 
411  default:
412  break;
413  }
414 
415  /* Close the handle if it exsts */
416  if ((Handle) && (*Handle)) ObCloseHandle(*Handle, KernelMode);
417 
418  /* Dereference process and thread and free the event */
421  ExFreePoolWithTag(DebugEvent, 'EgbD');
422 }
423 
424 VOID
425 NTAPI
427 {
428  PETHREAD Thread = DebugEvent->Thread;
429  PAGED_CODE();
430  DBGKTRACE(DBGK_OBJECT_DEBUG, "DebugEvent: %p\n", DebugEvent);
431 
432  /* Check if we have to wake the thread */
434 
435  /* Check if we had locked the thread */
436  if (DebugEvent->Flags & DEBUG_EVENT_RELEASE)
437  {
438  /* Unlock it */
440  }
441 
442  /* Check if we have to wake up the event */
443  if (DebugEvent->Flags & DEBUG_EVENT_NOWAIT)
444  {
445  /* Otherwise, free the debug event */
447  }
448  else
449  {
450  /* Signal the continue event */
451  KeSetEvent(&DebugEvent->ContinueEvent, IO_NO_INCREMENT, FALSE);
452  }
453 }
454 
455 NTSTATUS
456 NTAPI
459  IN PDEBUG_OBJECT DebugObject)
460 {
461  PPEB Peb = Process->Peb;
462  PPEB_LDR_DATA LdrData;
463  PLDR_DATA_TABLE_ENTRY LdrEntry;
464  PLIST_ENTRY ListHead, NextEntry;
465  DBGKM_MSG ApiMessage;
466  PDBGKM_LOAD_DLL LoadDll = &ApiMessage.LoadDll;
467  ULONG i;
468  PIMAGE_NT_HEADERS NtHeader;
474  PAGED_CODE();
475  DBGKTRACE(DBGK_PROCESS_DEBUG, "Process: %p Thread: %p DebugObject: %p\n",
476  Process, Thread, DebugObject);
477 
478  /* Quit if there's no PEB */
479  if (!Peb) return STATUS_SUCCESS;
480 
481  /* Accessing user memory, need SEH */
482  _SEH2_TRY
483  {
484  /* Get the Loader Data List */
485  ProbeForRead(Peb, sizeof(*Peb), 1);
486  LdrData = Peb->Ldr;
487  ProbeForRead(LdrData, sizeof(*LdrData), 1);
488  ListHead = &LdrData->InLoadOrderModuleList;
489  ProbeForRead(ListHead, sizeof(*ListHead), 1);
490  NextEntry = ListHead->Flink;
491 
492  /* Loop the modules */
493  i = 0;
494  while ((NextEntry != ListHead) && (i < 500))
495  {
496  ProbeForRead(NextEntry, sizeof(*NextEntry), 1);
497  /* Skip the first entry */
498  if (!i)
499  {
500  /* Go to the next module */
501  NextEntry = NextEntry->Flink;
502  i++;
503  continue;
504  }
505 
506  /* Get the entry */
507  LdrEntry = CONTAINING_RECORD(NextEntry,
509  InLoadOrderLinks);
510  ProbeForRead(LdrEntry, sizeof(*LdrEntry), 1);
511 
512  /* Setup the API Message */
513  RtlZeroMemory(&ApiMessage, sizeof(DBGKM_MSG));
514  ApiMessage.ApiNumber = DbgKmLoadDllApi;
515 
516  /* Set base and clear the name */
517  LoadDll->BaseOfDll = LdrEntry->DllBase;
518  LoadDll->NamePointer = NULL;
519 
520  /* Get the NT Headers */
521  NtHeader = RtlImageNtHeader(LoadDll->BaseOfDll);
522  if (NtHeader)
523  {
524  /* Save debug data */
525  LoadDll->DebugInfoFileOffset = NtHeader->FileHeader.
526  PointerToSymbolTable;
527  LoadDll->DebugInfoSize = NtHeader->FileHeader.NumberOfSymbols;
528  }
529 
530  /* Trace */
531  FullDllName = LdrEntry->FullDllName;
532  ProbeForRead(FullDllName.Buffer, FullDllName.MaximumLength, 1);
533  DBGKTRACE(DBGK_PROCESS_DEBUG, "Name: %wZ. Base: %p\n",
534  &FullDllName, LdrEntry->DllBase);
535 
536  /* Get the name of the DLL */
538  if (NT_SUCCESS(Status))
539  {
540  /* Setup the object attributes */
542  &ModuleName,
546  NULL,
547  NULL);
548 
549  /* Open the file to get a handle to it */
550  Status = ZwOpenFile(&LoadDll->FileHandle,
553  &IoStatusBlock,
558  if (!NT_SUCCESS(Status)) LoadDll->FileHandle = NULL;
559 
560  /* Free the name now */
562  }
563 
564  /* Send the fake module load message */
566  Thread,
567  &ApiMessage,
569  DebugObject);
570  if (!NT_SUCCESS(Status))
571  {
572  /* Message send failed, close the file handle if we had one */
573  if (LoadDll->FileHandle) ObCloseHandle(LoadDll->FileHandle,
574  KernelMode);
575  }
576 
577  /* Go to the next module */
578  NextEntry = NextEntry->Flink;
579  i++;
580  }
581  }
583  {
584  NOTHING;
585  }
586  _SEH2_END;
587 
588  /* Return success */
589  return STATUS_SUCCESS;
590 }
591 
592 NTSTATUS
593 NTAPI
595  IN PDEBUG_OBJECT DebugObject,
597  OUT PETHREAD *FirstThread,
599 {
600  PETHREAD pFirstThread = NULL, ThisThread, OldThread = NULL, pLastThread;
602  BOOLEAN IsFirstThread;
603  ULONG Flags;
604  DBGKM_MSG ApiMessage;
607  BOOLEAN First;
608  PIMAGE_NT_HEADERS NtHeader;
609  PAGED_CODE();
610  DBGKTRACE(DBGK_THREAD_DEBUG, "Process: %p StartThread: %p Object: %p\n",
611  Process, StartThread, DebugObject);
612 
613  /* Check if we have a start thread */
614  if (StartThread)
615  {
616  /* Then the one we'll find won't be the first one */
617  IsFirstThread = FALSE;
618  pFirstThread = StartThread;
619  ThisThread = StartThread;
620 
621  /* Reference it */
623  }
624  else
625  {
626  /* Get the first thread ourselves */
627  ThisThread = PsGetNextProcessThread(Process, NULL);
628  IsFirstThread = TRUE;
629  }
630 
631  /* Start thread loop */
632  do
633  {
634  /* Dereference the previous thread if we had one */
635  if (OldThread) ObDereferenceObject(OldThread);
636 
637  /* Set this as the last thread and lock it */
638  pLastThread = ThisThread;
639  ObReferenceObject(ThisThread);
640  if (ExAcquireRundownProtection(&ThisThread->RundownProtect))
641  {
642  /* Acquire worked, set flags */
644 
645  /* Check if this is a user thread */
646  if (!ThisThread->SystemThread)
647  {
648  /* Suspend it */
649  if (NT_SUCCESS(PsSuspendThread(ThisThread, NULL)))
650  {
651  /* Remember this */
653  }
654  }
655  }
656  else
657  {
658  /* Couldn't acquire rundown */
660  }
661 
662  /* Clear the API Message */
663  RtlZeroMemory(&ApiMessage, sizeof(ApiMessage));
664 
665  /* Check if this is the first thread */
666  if ((IsFirstThread) &&
668  !(ThisThread->SystemThread) &&
669  (ThisThread->GrantedAccess))
670  {
671  /* It is, save the flag */
672  First = TRUE;
673  }
674  else
675  {
676  /* It isn't, save the flag */
677  First = FALSE;
678  }
679 
680  /* Check if this is the first */
681  if (First)
682  {
683  /* So we'll start with the create process message */
684  ApiMessage.ApiNumber = DbgKmCreateProcessApi;
685 
686  /* Get the file handle */
687  if (Process->SectionObject)
688  {
689  /* Use the section object */
690  CreateProcess->FileHandle =
691  DbgkpSectionToFileHandle(Process->SectionObject);
692  }
693  else
694  {
695  /* Don't return any handle */
696  CreateProcess->FileHandle = NULL;
697  }
698 
699  /* Set the base address */
700  CreateProcess->BaseOfImage = Process->SectionBaseAddress;
701 
702  /* Get the NT Header */
703  NtHeader = RtlImageNtHeader(Process->SectionBaseAddress);
704  if (NtHeader)
705  {
706  /* Fill out data from the header */
707  CreateProcess->DebugInfoFileOffset = NtHeader->FileHeader.
708  PointerToSymbolTable;
709  CreateProcess->DebugInfoSize = NtHeader->FileHeader.
710  NumberOfSymbols;
711  }
712  }
713  else
714  {
715  /* Otherwise it's a thread message */
716  ApiMessage.ApiNumber = DbgKmCreateThreadApi;
717  CreateThread->StartAddress = ThisThread->StartAddress;
718  }
719 
720  /* Trace */
721  DBGKTRACE(DBGK_THREAD_DEBUG, "Thread: %p. First: %lx, OldThread: %p\n",
722  ThisThread, First, OldThread);
723  DBGKTRACE(DBGK_THREAD_DEBUG, "Start Address: %p\n",
724  ThisThread->StartAddress);
725 
726  /* Queue the message */
728  ThisThread,
729  &ApiMessage,
730  Flags,
731  DebugObject);
732  if (!NT_SUCCESS(Status))
733  {
734  /* Resume the thread if it was suspended */
735  if (Flags & DEBUG_EVENT_SUSPEND) PsResumeThread(ThisThread, NULL);
736 
737  /* Check if we acquired rundown */
739  {
740  /* Release it */
741  ExReleaseRundownProtection(&ThisThread->RundownProtect);
742  }
743 
744  /* If this was a process create, check if we got a handle */
745  if ((ApiMessage.ApiNumber == DbgKmCreateProcessApi) &&
746  (CreateProcess->FileHandle))
747  {
748  /* Close it */
749  ObCloseHandle(CreateProcess->FileHandle, KernelMode);
750  }
751 
752  /* Release our reference and break out */
753  ObDereferenceObject(ThisThread);
754  break;
755  }
756 
757  /* Check if this was the first message */
758  if (First)
759  {
760  /* It isn't the first thread anymore */
761  IsFirstThread = FALSE;
762 
763  /* Reference this thread and set it as first */
764  ObReferenceObject(ThisThread);
765  pFirstThread = ThisThread;
766  }
767 
768  /* Get the next thread */
769  ThisThread = PsGetNextProcessThread(Process, ThisThread);
770  OldThread = pLastThread;
771  } while (ThisThread);
772 
773  /* Check the API status */
774  if (!NT_SUCCESS(Status))
775  {
776  /* Dereference and fail */
777  if (pFirstThread) ObDereferenceObject(pFirstThread);
778  ObDereferenceObject(pLastThread);
779  return Status;
780  }
781 
782  /* Make sure we have a first thread */
783  if (!pFirstThread) return STATUS_UNSUCCESSFUL;
784 
785  /* Return thread pointers */
786  *FirstThread = pFirstThread;
787  *LastThread = pLastThread;
788  return Status;
789 }
790 
791 NTSTATUS
792 NTAPI
794  IN PDEBUG_OBJECT DebugObject,
796 {
798  PETHREAD FirstThread, FinalThread;
799  PETHREAD ReturnThread = NULL;
801  PAGED_CODE();
802  DBGKTRACE(DBGK_PROCESS_DEBUG, "Process: %p DebugObject: %p\n",
803  Process, DebugObject);
804 
805  /* Attach to the process */
807 
808  /* Post the fake thread messages */
810  DebugObject,
811  NULL,
812  &FirstThread,
813  &FinalThread);
814  if (NT_SUCCESS(Status))
815  {
816  /* Send the fake module messages too */
818  FirstThread,
819  DebugObject);
820  if (!NT_SUCCESS(Status))
821  {
822  /* We failed, dereference the final thread */
823  ObDereferenceObject(FinalThread);
824  }
825  else
826  {
827  /* Set the final thread */
828  ReturnThread = FinalThread;
829  }
830 
831  /* Dereference the first thread */
832  ObDereferenceObject(FirstThread);
833  }
834 
835  /* Detach from the process */
837 
838  /* Return the last thread */
839  *LastThread = ReturnThread;
840  return Status;
841 }
842 
843 VOID
844 NTAPI
847 {
848  DBGKTRACE(DBGK_OBJECT_DEBUG, "DebugEvent: %p\n", DebugEvent);
849 
850  /* Start by copying the client ID */
851  WaitStateChange->AppClientId = DebugEvent->ClientId;
852 
853  /* Now check which kind of event this was */
854  switch (DebugEvent->ApiMsg.ApiNumber)
855  {
856  /* New process */
858 
859  /* Set the right native code */
860  WaitStateChange->NewState = DbgCreateProcessStateChange;
861 
862  /* Copy the information */
863  WaitStateChange->StateInfo.CreateProcessInfo.NewProcess =
864  DebugEvent->ApiMsg.CreateProcess;
865 
866  /* Clear the file handle for us */
867  DebugEvent->ApiMsg.CreateProcess.FileHandle = NULL;
868  break;
869 
870  /* New thread */
872 
873  /* Set the right native code */
874  WaitStateChange->NewState = DbgCreateThreadStateChange;
875 
876  /* Copy information */
877  WaitStateChange->StateInfo.CreateThread.NewThread.StartAddress =
878  DebugEvent->ApiMsg.CreateThread.StartAddress;
879  WaitStateChange->StateInfo.CreateThread.NewThread.SubSystemKey =
880  DebugEvent->ApiMsg.CreateThread.SubSystemKey;
881  break;
882 
883  /* Exception (or breakpoint/step) */
884  case DbgKmExceptionApi:
885 
886  /* Look at the exception code */
887  if ((NTSTATUS)DebugEvent->ApiMsg.Exception.ExceptionRecord.ExceptionCode ==
889  {
890  /* Update this as a breakpoint exception */
891  WaitStateChange->NewState = DbgBreakpointStateChange;
892  }
893  else if ((NTSTATUS)DebugEvent->ApiMsg.Exception.ExceptionRecord.ExceptionCode ==
895  {
896  /* Update this as a single step exception */
897  WaitStateChange->NewState = DbgSingleStepStateChange;
898  }
899  else
900  {
901  /* Otherwise, set default exception */
902  WaitStateChange->NewState = DbgExceptionStateChange;
903  }
904 
905  /* Copy the exception record */
906  WaitStateChange->StateInfo.Exception.ExceptionRecord =
907  DebugEvent->ApiMsg.Exception.ExceptionRecord;
908  /* Copy FirstChance flag */
909  WaitStateChange->StateInfo.Exception.FirstChance =
910  DebugEvent->ApiMsg.Exception.FirstChance;
911  break;
912 
913  /* Process exited */
914  case DbgKmExitProcessApi:
915 
916  /* Set the right native code and copy the exit code */
917  WaitStateChange->NewState = DbgExitProcessStateChange;
918  WaitStateChange->StateInfo.ExitProcess.ExitStatus =
919  DebugEvent->ApiMsg.ExitProcess.ExitStatus;
920  break;
921 
922  /* Thread exited */
923  case DbgKmExitThreadApi:
924 
925  /* Set the right native code */
926  WaitStateChange->NewState = DbgExitThreadStateChange;
927  WaitStateChange->StateInfo.ExitThread.ExitStatus =
928  DebugEvent->ApiMsg.ExitThread.ExitStatus;
929  break;
930 
931  /* DLL Load */
932  case DbgKmLoadDllApi:
933 
934  /* Set the native code */
935  WaitStateChange->NewState = DbgLoadDllStateChange;
936 
937  /* Copy the data */
938  WaitStateChange->StateInfo.LoadDll = DebugEvent->ApiMsg.LoadDll;
939 
940  /* Clear the file handle for us */
941  DebugEvent->ApiMsg.LoadDll.FileHandle = NULL;
942  break;
943 
944  /* DLL Unload */
945  case DbgKmUnloadDllApi:
946 
947  /* Set the native code and copy the address */
948  WaitStateChange->NewState = DbgUnloadDllStateChange;
949  WaitStateChange->StateInfo.UnloadDll.BaseAddress =
950  DebugEvent->ApiMsg.UnloadDll.BaseAddress;
951  break;
952 
953  default:
954 
955  /* Shouldn't happen */
956  ASSERT(FALSE);
957  }
958 }
959 
960 VOID
961 NTAPI
963 {
965  PAGED_CODE();
966  DBGKTRACE(DBGK_PROCESS_DEBUG, "Process: %p\n", Process);
967 
968  /* Acquire process rundown */
969  if (!ExAcquireRundownProtection(&Process->RundownProtect)) return;
970 
971  /* Make sure we have a PEB */
972  if (Process->Peb)
973  {
974  /* Attach to the process */
976 
977  /* Acquire the debug port mutex */
979 
980  /* Set the IsBeingDebugged member of the PEB */
981  Process->Peb->BeingDebugged = (Process->DebugPort) ? TRUE: FALSE;
982 
983  /* Release lock */
985 
986  /* Detach from the process */
988  }
989 
990  /* Release rundown protection */
991  ExReleaseRundownProtection(&Process->RundownProtect);
992 }
993 
994 VOID
995 NTAPI
999 {
1000  NTSTATUS Status;
1001  HANDLE Handle;
1002  PHANDLE DupHandle;
1003  PAGED_CODE();
1004  DBGKTRACE(DBGK_OBJECT_DEBUG, "Process: %p Thread: %p State: %lx\n",
1005  Process, Thread, WaitStateChange->NewState);
1006 
1007  /* Check which state this is */
1008  switch (WaitStateChange->NewState)
1009  {
1010  /* New thread */
1012 
1013  /* Get handle to thread */
1015  0,
1016  NULL,
1018  PsThreadType,
1019  KernelMode,
1020  &Handle);
1021  if (NT_SUCCESS(Status))
1022  {
1023  /* Save the thread handle */
1024  WaitStateChange->
1025  StateInfo.CreateThread.HandleToThread = Handle;
1026  }
1027  return;
1028 
1029  /* New process */
1031 
1032  /* Get handle to thread */
1034  0,
1035  NULL,
1037  PsThreadType,
1038  KernelMode,
1039  &Handle);
1040  if (NT_SUCCESS(Status))
1041  {
1042  /* Save the thread handle */
1043  WaitStateChange->
1044  StateInfo.CreateProcessInfo.HandleToThread = Handle;
1045  }
1046 
1047  /* Get handle to process */
1049  0,
1050  NULL,
1052  PsProcessType,
1053  KernelMode,
1054  &Handle);
1055  if (NT_SUCCESS(Status))
1056  {
1057  /* Save the process handle */
1058  WaitStateChange->
1059  StateInfo.CreateProcessInfo.HandleToProcess = Handle;
1060  }
1061 
1062  /* Fall through to duplicate file handle */
1063  DupHandle = &WaitStateChange->
1064  StateInfo.CreateProcessInfo.NewProcess.FileHandle;
1065  break;
1066 
1067  /* DLL Load */
1068  case DbgLoadDllStateChange:
1069 
1070  /* Fall through to duplicate file handle */
1071  DupHandle = &WaitStateChange->StateInfo.LoadDll.FileHandle;
1072  break;
1073 
1074  /* Anything else has no handles */
1075  default:
1076  return;
1077  }
1078 
1079  /* If we got here, then we have to duplicate a handle, possibly */
1080  Handle = *DupHandle;
1081  if (Handle)
1082  {
1083  /* Duplicate it */
1085  Handle,
1087  DupHandle,
1088  0,
1089  0,
1091  KernelMode);
1092  if (!NT_SUCCESS(Status)) *DupHandle = NULL;
1093 
1094  /* Close the original handle */
1096  }
1097 }
1098 
1099 VOID
1100 NTAPI
1102 {
1103  PAGED_CODE();
1104 
1105  /* Sanity check */
1106  ASSERT(IsListEmpty(&((PDEBUG_OBJECT)DebugObject)->EventList));
1107 }
1108 
1109 VOID
1110 NTAPI
1112  IN PVOID ObjectBody,
1114  IN ULONG HandleCount,
1115  IN ULONG SystemHandleCount)
1116 {
1117  PDEBUG_OBJECT DebugObject = ObjectBody;
1119  BOOLEAN DebugPortCleared = FALSE;
1120  PLIST_ENTRY DebugEventList;
1122  PAGED_CODE();
1123  DBGKTRACE(DBGK_OBJECT_DEBUG, "OwnerProcess: %p DebugObject: %p\n",
1124  OwnerProcess, DebugObject);
1125 
1126  /* If this isn't the last handle, do nothing */
1127  if (SystemHandleCount > 1) return;
1128 
1129  /* Otherwise, lock the debug object */
1130  ExAcquireFastMutex(&DebugObject->Mutex);
1131 
1132  /* Set it as inactive */
1133  DebugObject->DebuggerInactive = TRUE;
1134 
1135  /* Remove it from the debug event list */
1136  DebugEventList = DebugObject->EventList.Flink;
1137  InitializeListHead(&DebugObject->EventList);
1138 
1139  /* Release the lock */
1140  ExReleaseFastMutex(&DebugObject->Mutex);
1141 
1142  /* Signal the wait event */
1143  KeSetEvent(&DebugObject->EventsPresent, IO_NO_INCREMENT, FALSE);
1144 
1145  /* Start looping each process */
1146  while ((Process = PsGetNextProcess(Process)))
1147  {
1148  /* Check if the process has us as their debug port */
1149  if (Process->DebugPort == DebugObject)
1150  {
1151  /* Acquire the process debug port lock */
1153 
1154  /* Check if it's still us */
1155  if (Process->DebugPort == DebugObject)
1156  {
1157  /* Clear it and remember */
1158  Process->DebugPort = NULL;
1159  DebugPortCleared = TRUE;
1160  }
1161 
1162  /* Release the port lock */
1164 
1165  /* Check if we cleared the debug port */
1166  if (DebugPortCleared)
1167  {
1168  /* Mark this in the PEB */
1170 
1171  /* Check if we terminate on exit */
1172  if (DebugObject->KillProcessOnExit)
1173  {
1174  /* Terminate the process */
1176  }
1177 
1178  /* Dereference the debug object */
1179  ObDereferenceObject(DebugObject);
1180  }
1181  }
1182  }
1183 
1184  /* Loop debug events */
1185  while (DebugEventList != &DebugObject->EventList)
1186  {
1187  /* Get the debug event */
1188  DebugEvent = CONTAINING_RECORD(DebugEventList, DEBUG_EVENT, EventList);
1189 
1190  /* Go to the next entry */
1191  DebugEventList = DebugEventList->Flink;
1192 
1193  /* Wake it up */
1196  }
1197 }
1198 
1199 NTSTATUS
1200 NTAPI
1202  IN PDEBUG_OBJECT DebugObject,
1203  IN NTSTATUS MsgStatus,
1205 {
1206  NTSTATUS Status;
1207  LIST_ENTRY TempList;
1208  BOOLEAN GlobalHeld = FALSE, DoSetEvent = TRUE;
1209  PETHREAD ThisThread, FirstThread;
1210  PLIST_ENTRY NextEntry;
1212  PETHREAD EventThread;
1213  PAGED_CODE();
1214  DBGKTRACE(DBGK_PROCESS_DEBUG, "Process: %p DebugObject: %p\n",
1215  Process, DebugObject);
1216 
1217  /* Initialize the temporary list */
1218  InitializeListHead(&TempList);
1219 
1220  /* Check if we have a success message */
1221  if (NT_SUCCESS(MsgStatus))
1222  {
1223  /* Then default to STATUS_SUCCESS */
1225  }
1226  else
1227  {
1228  /* No last thread, and set the failure code */
1229  LastThread = NULL;
1230  Status = MsgStatus;
1231  }
1232 
1233  /* Now check what status we have here */
1234  if (NT_SUCCESS(Status))
1235  {
1236  /* Acquire the global lock */
1237 ThreadScan:
1238  GlobalHeld = TRUE;
1240 
1241  /* Check if we already have a port */
1242  if (Process->DebugPort)
1243  {
1244  /* Set failure */
1246  }
1247  else
1248  {
1249  /* Otherwise, set the port and reference the thread */
1250  Process->DebugPort = DebugObject;
1252 
1253  /* Get the next thread */
1254  ThisThread = PsGetNextProcessThread(Process, LastThread);
1255  if (ThisThread)
1256  {
1257  /* Clear the debug port and release the lock */
1258  Process->DebugPort = NULL;
1260  GlobalHeld = FALSE;
1261 
1262  /* Dereference the thread */
1264 
1265  /* Post fake messages */
1267  DebugObject,
1268  ThisThread,
1269  &FirstThread,
1270  &LastThread);
1271  if (!NT_SUCCESS(Status))
1272  {
1273  /* Clear the last thread */
1274  LastThread = NULL;
1275  }
1276  else
1277  {
1278  /* Dereference the first thread and re-acquire the lock */
1279  ObDereferenceObject(FirstThread);
1280  goto ThreadScan;
1281  }
1282  }
1283  }
1284  }
1285 
1286  /* Acquire the debug object's lock */
1287  ExAcquireFastMutex(&DebugObject->Mutex);
1288 
1289  /* Check our status here */
1290  if (NT_SUCCESS(Status))
1291  {
1292  /* Check if we're disconnected */
1293  if (DebugObject->DebuggerInactive)
1294  {
1295  /* Set status */
1296  Process->DebugPort = NULL;
1298  }
1299  else
1300  {
1301  /* Set the process flags */
1305 
1306  /* Reference the debug object */
1307  ObReferenceObject(DebugObject);
1308  }
1309  }
1310 
1311  /* Loop the events list */
1312  NextEntry = DebugObject->EventList.Flink;
1313  while (NextEntry != &DebugObject->EventList)
1314  {
1315  /* Get the debug event and go to the next entry */
1316  DebugEvent = CONTAINING_RECORD(NextEntry, DEBUG_EVENT, EventList);
1317  NextEntry = NextEntry->Flink;
1318  DBGKTRACE(DBGK_PROCESS_DEBUG, "DebugEvent: %p Flags: %lx TH: %p/%p\n",
1319  DebugEvent, DebugEvent->Flags,
1320  DebugEvent->BackoutThread, PsGetCurrentThread());
1321 
1322  /* Check for if the debug event queue needs flushing */
1323  if ((DebugEvent->Flags & DEBUG_EVENT_INACTIVE) &&
1324  (DebugEvent->BackoutThread == PsGetCurrentThread()))
1325  {
1326  /* Get the event's thread */
1327  EventThread = DebugEvent->Thread;
1328  DBGKTRACE(DBGK_PROCESS_DEBUG, "EventThread: %p MsgStatus: %lx\n",
1329  EventThread, MsgStatus);
1330 
1331  /* Check if the status is success */
1332  if ((MsgStatus == STATUS_SUCCESS) &&
1333  (EventThread->GrantedAccess) &&
1334  (!EventThread->SystemThread))
1335  {
1336  /* Check if we couldn't acquire rundown for it */
1338  {
1339  /* Set the skip termination flag */
1341 
1342  /* Insert it into the temp list */
1343  RemoveEntryList(&DebugEvent->EventList);
1344  InsertTailList(&TempList, &DebugEvent->EventList);
1345  }
1346  else
1347  {
1348  /* Do we need to signal the event */
1349  if (DoSetEvent)
1350  {
1351  /* Do it */
1352  DebugEvent->Flags &= ~DEBUG_EVENT_INACTIVE;
1353  KeSetEvent(&DebugObject->EventsPresent,
1355  FALSE);
1356  DoSetEvent = FALSE;
1357  }
1358 
1359  /* Clear the backout thread */
1360  DebugEvent->BackoutThread = NULL;
1361 
1362  /* Set skip flag */
1364  }
1365  }
1366  else
1367  {
1368  /* Insert it into the temp list */
1369  RemoveEntryList(&DebugEvent->EventList);
1370  InsertTailList(&TempList, &DebugEvent->EventList);
1371  }
1372 
1373  /* Check if the lock is held */
1374  if (DebugEvent->Flags & DEBUG_EVENT_RELEASE)
1375  {
1376  /* Release it */
1377  DebugEvent->Flags &= ~DEBUG_EVENT_RELEASE;
1379  }
1380  }
1381  }
1382 
1383  /* Release the debug object */
1384  ExReleaseFastMutex(&DebugObject->Mutex);
1385 
1386  /* Release the global lock if acquired */
1388 
1389  /* Check if there's a thread to dereference */
1391 
1392  /* Loop our temporary list */
1393  while (!IsListEmpty(&TempList))
1394  {
1395  /* Remove the event */
1396  NextEntry = RemoveHeadList(&TempList);
1397  DebugEvent = CONTAINING_RECORD(NextEntry, DEBUG_EVENT, EventList);
1398 
1399  /* Wake it */
1401  }
1402 
1403  /* Check if we got here through success and mark the PEB, then return */
1405  return Status;
1406 }
1407 
1408 NTSTATUS
1409 NTAPI
1411  IN PDEBUG_OBJECT SourceDebugObject OPTIONAL)
1412 {
1413  PDEBUG_OBJECT DebugObject;
1415  LIST_ENTRY TempList;
1416  PLIST_ENTRY NextEntry;
1417  PAGED_CODE();
1418  DBGKTRACE(DBGK_OBJECT_DEBUG, "Process: %p DebugObject: %p\n",
1419  Process, SourceDebugObject);
1420 
1421  /* Acquire the port lock */
1423 
1424  /* Get the Process Debug Object */
1425  DebugObject = Process->DebugPort;
1426 
1427  /*
1428  * Check if the process had an object and it matches,
1429  * or if the process had an object but none was specified
1430  * (in which we are called from NtTerminateProcess)
1431  */
1432  if ((DebugObject) &&
1433  ((DebugObject == SourceDebugObject) ||
1434  (SourceDebugObject == NULL)))
1435  {
1436  /* Clear the debug port */
1437  Process->DebugPort = NULL;
1438 
1439  /* Release the port lock and remove the PEB flag */
1442  }
1443  else
1444  {
1445  /* Release the port lock and fail */
1447  return STATUS_PORT_NOT_SET;
1448  }
1449 
1450  /* Initialize the temporary list */
1451  InitializeListHead(&TempList);
1452 
1453  /* Acquire the Object */
1454  ExAcquireFastMutex(&DebugObject->Mutex);
1455 
1456  /* Loop the events */
1457  NextEntry = DebugObject->EventList.Flink;
1458  while (NextEntry != &DebugObject->EventList)
1459  {
1460  /* Get the Event and go to the next entry */
1461  DebugEvent = CONTAINING_RECORD(NextEntry, DEBUG_EVENT, EventList);
1462  NextEntry = NextEntry->Flink;
1463 
1464  /* Check that it belongs to the specified process */
1465  if (DebugEvent->Process == Process)
1466  {
1467  /* Insert it into the temporary list */
1468  RemoveEntryList(&DebugEvent->EventList);
1469  InsertTailList(&TempList, &DebugEvent->EventList);
1470  }
1471  }
1472 
1473  /* Release the Object */
1474  ExReleaseFastMutex(&DebugObject->Mutex);
1475 
1476  /* Release the initial reference */
1477  ObDereferenceObject(DebugObject);
1478 
1479  /* Loop our temporary list */
1480  while (!IsListEmpty(&TempList))
1481  {
1482  /* Remove the event */
1483  NextEntry = RemoveHeadList(&TempList);
1484  DebugEvent = CONTAINING_RECORD(NextEntry, DEBUG_EVENT, EventList);
1485 
1486  /* Wake it up */
1489  }
1490 
1491  /* Return Success */
1492  return STATUS_SUCCESS;
1493 }
1494 
1495 VOID
1496 INIT_FUNCTION
1497 NTAPI
1499 {
1500  OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
1502  PAGED_CODE();
1503 
1504  /* Initialize the process debug port mutex */
1506 
1507  /* Create the Debug Object Type */
1508  RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
1509  RtlInitUnicodeString(&Name, L"DebugObject");
1510  ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
1511  ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(DEBUG_OBJECT);
1512  ObjectTypeInitializer.GenericMapping = DbgkDebugObjectMapping;
1513  ObjectTypeInitializer.PoolType = NonPagedPool;
1514  ObjectTypeInitializer.ValidAccessMask = DEBUG_OBJECT_ALL_ACCESS;
1515  ObjectTypeInitializer.SecurityRequired = TRUE;
1516  ObjectTypeInitializer.CloseProcedure = DbgkpCloseObject;
1517  ObjectTypeInitializer.DeleteProcedure = DbgkpDeleteObject;
1519  &ObjectTypeInitializer,
1520  NULL,
1522 }
1523 
1524 NTSTATUS
1525 NTAPI
1528  OUT HANDLE *DebugHandle)
1529 {
1530  PDEBUG_OBJECT DebugObject;
1531  NTSTATUS Status;
1532  PAGED_CODE();
1533 
1534  /* If there's no debug port, just exit */
1535  if (!Process->DebugPort) return STATUS_PORT_NOT_SET;
1536 
1537  /* Otherwise, acquire the lock while we grab the port */
1539 
1540  /* Grab it and reference it if it exists */
1541  DebugObject = Process->DebugPort;
1542  if (DebugObject) ObReferenceObject(DebugObject);
1543 
1544  /* Release the lock now */
1546 
1547  /* Bail out if it doesn't exist */
1548  if (!DebugObject) return STATUS_PORT_NOT_SET;
1549 
1550  /* Now get a handle to it */
1551  Status = ObOpenObjectByPointer(DebugObject,
1552  0,
1553  NULL,
1556  PreviousMode,
1557  DebugHandle);
1558  if (!NT_SUCCESS(Status)) ObDereferenceObject(DebugObject);
1559 
1560  /* Return status */
1561  return Status;
1562 }
1563 
1564 /* PUBLIC FUNCTIONS **********************************************************/
1565 
1566 /*
1567  * @implemented
1568  */
1569 NTSTATUS
1570 NTAPI
1574  IN ULONG Flags)
1575 {
1577  PDEBUG_OBJECT DebugObject;
1578  HANDLE hDebug;
1579  NTSTATUS Status;
1580  PAGED_CODE();
1581 
1582  /* Check if we were called from user mode*/
1583  if (PreviousMode != KernelMode)
1584  {
1585  /* Enter SEH for probing */
1586  _SEH2_TRY
1587  {
1588  /* Probe the handle */
1589  ProbeForWriteHandle(DebugHandle);
1590  }
1592  {
1593  /* Return the exception code */
1595  } _SEH2_END;
1596  }
1597 
1598  /* Check for invalid flags */
1600 
1601  /* Create the Object */
1605  PreviousMode,
1606  NULL,
1607  sizeof(DEBUG_OBJECT),
1608  0,
1609  0,
1610  (PVOID*)&DebugObject);
1611  if (NT_SUCCESS(Status))
1612  {
1613  /* Initialize the Debug Object's Fast Mutex */
1614  ExInitializeFastMutex(&DebugObject->Mutex);
1615 
1616  /* Initialize the State Event List */
1617  InitializeListHead(&DebugObject->EventList);
1618 
1619  /* Initialize the Debug Object's Wait Event */
1620  KeInitializeEvent(&DebugObject->EventsPresent,
1622  FALSE);
1623 
1624  /* Set the Flags */
1625  DebugObject->Flags = 0;
1627  {
1628  DebugObject->KillProcessOnExit = TRUE;
1629  }
1630 
1631  /* Insert it */
1632  Status = ObInsertObject((PVOID)DebugObject,
1633  NULL,
1634  DesiredAccess,
1635  0,
1636  NULL,
1637  &hDebug);
1638  if (NT_SUCCESS(Status))
1639  {
1640  /* Enter SEH to protect the write */
1641  _SEH2_TRY
1642  {
1643  /* Return the handle */
1644  *DebugHandle = hDebug;
1645  }
1647  {
1648  /* Get the exception code */
1650  } _SEH2_END;
1651  }
1652  }
1653 
1654  /* Return Status */
1655  DBGKTRACE(DBGK_OBJECT_DEBUG, "Handle: %p DebugObject: %p\n",
1656  hDebug, DebugObject);
1657  return Status;
1658 }
1659 
1660 /*
1661  * @implemented
1662  */
1663 NTSTATUS
1664 NTAPI
1666  IN PCLIENT_ID AppClientId,
1667  IN NTSTATUS ContinueStatus)
1668 {
1670  PDEBUG_OBJECT DebugObject;
1671  NTSTATUS Status;
1672  PDEBUG_EVENT DebugEvent = NULL, DebugEventToWake = NULL;
1673  PLIST_ENTRY ListHead, NextEntry;
1674  BOOLEAN NeedsWake = FALSE;
1676  PAGED_CODE();
1677  DBGKTRACE(DBGK_OBJECT_DEBUG, "Handle: %p Status: %d\n",
1678  DebugHandle, ContinueStatus);
1679 
1680  /* Check if we were called from user mode*/
1681  if (PreviousMode != KernelMode)
1682  {
1683  /* Enter SEH for probing */
1684  _SEH2_TRY
1685  {
1686  /* Probe the handle */
1687  ProbeForRead(AppClientId, sizeof(CLIENT_ID), sizeof(ULONG));
1688  ClientId = *AppClientId;
1689  AppClientId = &ClientId;
1690  }
1692  {
1693  /* Return the exception code */
1695  } _SEH2_END;
1696  }
1697 
1698  /* Make sure that the status is valid */
1699  if ((ContinueStatus != DBG_CONTINUE) &&
1700  (ContinueStatus != DBG_EXCEPTION_HANDLED) &&
1701  (ContinueStatus != DBG_EXCEPTION_NOT_HANDLED) &&
1702  (ContinueStatus != DBG_TERMINATE_THREAD) &&
1703  (ContinueStatus != DBG_TERMINATE_PROCESS))
1704  {
1705  /* Invalid status */
1707  }
1708  else
1709  {
1710  /* Get the debug object */
1711  Status = ObReferenceObjectByHandle(DebugHandle,
1714  PreviousMode,
1715  (PVOID*)&DebugObject,
1716  NULL);
1717  if (NT_SUCCESS(Status))
1718  {
1719  /* Acquire the mutex */
1720  ExAcquireFastMutex(&DebugObject->Mutex);
1721 
1722  /* Loop the state list */
1723  ListHead = &DebugObject->EventList;
1724  NextEntry = ListHead->Flink;
1725  while (ListHead != NextEntry)
1726  {
1727  /* Get the current debug event */
1728  DebugEvent = CONTAINING_RECORD(NextEntry,
1729  DEBUG_EVENT,
1730  EventList);
1731 
1732  /* Compare process ID */
1733  if (DebugEvent->ClientId.UniqueProcess ==
1734  AppClientId->UniqueProcess)
1735  {
1736  /* Check if we already found a match */
1737  if (NeedsWake)
1738  {
1739  /* Wake it up and break out */
1740  DebugEvent->Flags &= ~DEBUG_EVENT_INACTIVE;
1741  KeSetEvent(&DebugObject->EventsPresent,
1743  FALSE);
1744  break;
1745  }
1746 
1747  /* Compare thread ID and flag */
1748  if ((DebugEvent->ClientId.UniqueThread ==
1749  AppClientId->UniqueThread) && (DebugEvent->Flags & DEBUG_EVENT_READ))
1750  {
1751  /* Remove the event from the list */
1752  RemoveEntryList(NextEntry);
1753 
1754  /* Remember who to wake */
1755  NeedsWake = TRUE;
1756  DebugEventToWake = DebugEvent;
1757  }
1758  }
1759 
1760  /* Go to the next entry */
1761  NextEntry = NextEntry->Flink;
1762  }
1763 
1764  /* Release the mutex */
1765  ExReleaseFastMutex(&DebugObject->Mutex);
1766 
1767  /* Dereference the object */
1768  ObDereferenceObject(DebugObject);
1769 
1770  /* Check if need a wait */
1771  if (NeedsWake)
1772  {
1773  /* Set the continue status */
1774  DebugEventToWake->ApiMsg.ReturnedStatus = ContinueStatus;
1775  DebugEventToWake->Status = STATUS_SUCCESS;
1776 
1777  /* Wake the target */
1778  DbgkpWakeTarget(DebugEventToWake);
1779  }
1780  else
1781  {
1782  /* Fail */
1784  }
1785  }
1786  }
1787 
1788  /* Return status */
1789  return Status;
1790 }
1791 
1792 /*
1793  * @implemented
1794  */
1795 NTSTATUS
1796 NTAPI
1798  IN HANDLE DebugHandle)
1799 {
1801  PDEBUG_OBJECT DebugObject;
1804  NTSTATUS Status;
1805  PAGED_CODE();
1806  DBGKTRACE(DBGK_PROCESS_DEBUG, "Process: %p Handle: %p\n",
1807  ProcessHandle, DebugHandle);
1808 
1809  /* Reference the process */
1812  PsProcessType,
1813  PreviousMode,
1814  (PVOID*)&Process,
1815  NULL);
1816  if (!NT_SUCCESS(Status)) return Status;
1817 
1818  /* Don't allow debugging the current process or the system process */
1819  if ((Process == PsGetCurrentProcess()) ||
1821  {
1822  /* Dereference and fail */
1824  return STATUS_ACCESS_DENIED;
1825  }
1826 
1827  /* Reference the debug object */
1828  Status = ObReferenceObjectByHandle(DebugHandle,
1831  PreviousMode,
1832  (PVOID*)&DebugObject,
1833  NULL);
1834  if (!NT_SUCCESS(Status))
1835  {
1836  /* Dereference the process and exit */
1838  return Status;
1839  }
1840 
1841  /* Acquire process rundown protection */
1842  if (!ExAcquireRundownProtection(&Process->RundownProtect))
1843  {
1844  /* Dereference the process and debug object and exit */
1846  ObDereferenceObject(DebugObject);
1848  }
1849 
1850  /* Send fake create messages for debuggers to have a consistent state */
1852  DebugObject,
1853  &LastThread);
1855  DebugObject,
1856  Status,
1857  LastThread);
1858 
1859  /* Release rundown protection */
1860  ExReleaseRundownProtection(&Process->RundownProtect);
1861 
1862  /* Dereference the process and debug object and return status */
1864  ObDereferenceObject(DebugObject);
1865  return Status;
1866 }
1867 
1868 /*
1869  * @implemented
1870  */
1871 NTSTATUS
1872 NTAPI
1874  IN HANDLE DebugHandle)
1875 {
1877  PDEBUG_OBJECT DebugObject;
1879  NTSTATUS Status;
1880  PAGED_CODE();
1881  DBGKTRACE(DBGK_PROCESS_DEBUG, "Process: %p Handle: %p\n",
1882  ProcessHandle, DebugHandle);
1883 
1884  /* Reference the process */
1887  PsProcessType,
1888  PreviousMode,
1889  (PVOID*)&Process,
1890  NULL);
1891  if (!NT_SUCCESS(Status)) return Status;
1892 
1893  /* Reference the debug object */
1894  Status = ObReferenceObjectByHandle(DebugHandle,
1897  PreviousMode,
1898  (PVOID*)&DebugObject,
1899  NULL);
1900  if (!NT_SUCCESS(Status))
1901  {
1902  /* Dereference the process and exit */
1904  return Status;
1905  }
1906 
1907  /* Remove the debug object */
1908  Status = DbgkClearProcessDebugObject(Process, DebugObject);
1909 
1910  /* Dereference the process and debug object and return status */
1912  ObDereferenceObject(DebugObject);
1913  return Status;
1914 }
1915 
1916 /*
1917  * @implemented
1918  */
1919 NTSTATUS
1920 NTAPI
1922  IN DEBUGOBJECTINFOCLASS DebugObjectInformationClass,
1923  IN PVOID DebugInformation,
1924  IN ULONG DebugInformationLength,
1926 {
1927  PDEBUG_OBJECT DebugObject;
1929  NTSTATUS Status;
1930  PDEBUG_OBJECT_KILL_PROCESS_ON_EXIT_INFORMATION DebugInfo = DebugInformation;
1931  PAGED_CODE();
1932 
1933  /* Check buffers and parameters */
1934  Status = DefaultSetInfoBufferCheck(DebugObjectInformationClass,
1936  sizeof(DbgkpDebugObjectInfoClass) /
1937  sizeof(DbgkpDebugObjectInfoClass[0]),
1938  DebugInformation,
1939  DebugInformationLength,
1940  PreviousMode);
1941  if (!NT_SUCCESS(Status)) return Status;
1942 
1943  /* Check if the caller wanted the return length */
1944  if (ReturnLength)
1945  {
1946  /* Enter SEH for probe */
1947  _SEH2_TRY
1948  {
1949  /* Return required length to user-mode */
1951  *ReturnLength = sizeof(*DebugInfo);
1952  }
1954  {
1955  /* Return the exception code */
1957  }
1958  _SEH2_END;
1959  }
1960 
1961  /* Open the Object */
1962  Status = ObReferenceObjectByHandle(DebugHandle,
1965  PreviousMode,
1966  (PVOID*)&DebugObject,
1967  NULL);
1968  if (NT_SUCCESS(Status))
1969  {
1970  /* Acquire the object */
1971  ExAcquireFastMutex(&DebugObject->Mutex);
1972 
1973  /* Set the proper flag */
1974  if (DebugInfo->KillProcessOnExit)
1975  {
1976  /* Enable killing the process */
1977  DebugObject->KillProcessOnExit = TRUE;
1978  }
1979  else
1980  {
1981  /* Disable */
1982  DebugObject->KillProcessOnExit = FALSE;
1983  }
1984 
1985  /* Release the mutex */
1986  ExReleaseFastMutex(&DebugObject->Mutex);
1987 
1988  /* Release the Object */
1989  ObDereferenceObject(DebugObject);
1990  }
1991 
1992  /* Return Status */
1993  return Status;
1994 }
1995 
1996 /*
1997  * @implemented
1998  */
1999 NTSTATUS
2000 NTAPI
2004  OUT PDBGUI_WAIT_STATE_CHANGE StateChange)
2005 {
2007  LARGE_INTEGER LocalTimeOut;
2010  PETHREAD Thread;
2011  BOOLEAN GotEvent;
2012  LARGE_INTEGER NewTime;
2013  PDEBUG_OBJECT DebugObject;
2014  DBGUI_WAIT_STATE_CHANGE WaitStateChange;
2015  NTSTATUS Status;
2016  PDEBUG_EVENT DebugEvent = NULL, DebugEvent2;
2017  PLIST_ENTRY ListHead, NextEntry, NextEntry2;
2018  PAGED_CODE();
2019  DBGKTRACE(DBGK_OBJECT_DEBUG, "Handle: %p\n", DebugHandle);
2020 
2021  /* Clear the initial wait state change structure and the timeout */
2022  RtlZeroMemory(&WaitStateChange, sizeof(WaitStateChange));
2023  LocalTimeOut.QuadPart = 0;
2024 
2025  /* Check if we were called from user mode */
2026  if (PreviousMode != KernelMode)
2027  {
2028  /* Protect probe in SEH */
2029  _SEH2_TRY
2030  {
2031  /* Check if we came with a timeout */
2032  if (Timeout)
2033  {
2034  /* Probe it */
2036 
2037  /* Make a local copy */
2038  LocalTimeOut = *Timeout;
2039  Timeout = &LocalTimeOut;
2040  }
2041 
2042  /* Probe the state change structure */
2043  ProbeForWrite(StateChange, sizeof(*StateChange), sizeof(ULONG));
2044  }
2046  {
2047  /* Return the exception code */
2049  }
2050  _SEH2_END;
2051  }
2052  else
2053  {
2054  /* Copy directly */
2055  if (Timeout) LocalTimeOut = *Timeout;
2056  }
2057 
2058  /* If we were passed a timeout, query the current time */
2060 
2061  /* Get the debug object */
2062  Status = ObReferenceObjectByHandle(DebugHandle,
2065  PreviousMode,
2066  (PVOID*)&DebugObject,
2067  NULL);
2068  if (!NT_SUCCESS(Status)) return Status;
2069 
2070  /* Clear process and thread */
2071  Process = NULL;
2072  Thread = NULL;
2073 
2074  /* Wait on the debug object given to us */
2075  while (TRUE)
2076  {
2077  Status = KeWaitForSingleObject(&DebugObject->EventsPresent,
2078  Executive,
2079  PreviousMode,
2080  Alertable,
2081  Timeout);
2082  if (!NT_SUCCESS(Status) ||
2083  (Status == STATUS_TIMEOUT) ||
2084  (Status == STATUS_ALERTED) ||
2085  (Status == STATUS_USER_APC))
2086  {
2087  /* Break out the wait */
2088  break;
2089  }
2090 
2091  /* Lock the object */
2092  GotEvent = FALSE;
2093  ExAcquireFastMutex(&DebugObject->Mutex);
2094 
2095  /* Check if a debugger is connected */
2096  if (DebugObject->DebuggerInactive)
2097  {
2098  /* Not connected */
2100  }
2101  else
2102  {
2103  /* Loop the events */
2104  ListHead = &DebugObject->EventList;
2105  NextEntry = ListHead->Flink;
2106  while (ListHead != NextEntry)
2107  {
2108  /* Get the debug event */
2109  DebugEvent = CONTAINING_RECORD(NextEntry,
2110  DEBUG_EVENT,
2111  EventList);
2112  DBGKTRACE(DBGK_PROCESS_DEBUG, "DebugEvent: %p Flags: %lx\n",
2113  DebugEvent, DebugEvent->Flags);
2114 
2115  /* Check flags */
2116  if (!(DebugEvent->Flags & (DEBUG_EVENT_INACTIVE | DEBUG_EVENT_READ)))
2117  {
2118  /* We got an event */
2119  GotEvent = TRUE;
2120 
2121  /* Loop the list internally */
2122  NextEntry2 = DebugObject->EventList.Flink;
2123  while (NextEntry2 != NextEntry)
2124  {
2125  /* Get the debug event */
2126  DebugEvent2 = CONTAINING_RECORD(NextEntry2,
2127  DEBUG_EVENT,
2128  EventList);
2129 
2130  /* Try to match process IDs */
2131  if (DebugEvent2->ClientId.UniqueProcess ==
2132  DebugEvent->ClientId.UniqueProcess)
2133  {
2134  /* Found it, break out */
2135  DebugEvent->Flags |= DEBUG_EVENT_INACTIVE;
2136  DebugEvent->BackoutThread = NULL;
2137  GotEvent = FALSE;
2138  break;
2139  }
2140 
2141  /* Move to the next entry */
2142  NextEntry2 = NextEntry2->Flink;
2143  }
2144 
2145  /* Check if we still have a valid event */
2146  if (GotEvent) break;
2147  }
2148 
2149  /* Move to the next entry */
2150  NextEntry = NextEntry->Flink;
2151  }
2152 
2153  /* Check if we have an event */
2154  if (GotEvent)
2155  {
2156  /* Save and reference the process and thread */
2157  Process = DebugEvent->Process;
2158  Thread = DebugEvent->Thread;
2161 
2162  /* Convert to user-mode structure */
2163  DbgkpConvertKernelToUserStateChange(&WaitStateChange,
2164  DebugEvent);
2165 
2166  /* Set flag */
2167  DebugEvent->Flags |= DEBUG_EVENT_READ;
2168  }
2169  else
2170  {
2171  /* Unsignal the event */
2172  KeClearEvent(&DebugObject->EventsPresent);
2173  }
2174 
2175  /* Set success */
2177  }
2178 
2179  /* Release the mutex */
2180  ExReleaseFastMutex(&DebugObject->Mutex);
2181  if (!NT_SUCCESS(Status)) break;
2182 
2183  /* Check if we got an event */
2184  if (!GotEvent)
2185  {
2186  /* Check if we can wait again */
2187  if (LocalTimeOut.QuadPart < 0)
2188  {
2189  /* Query the new time */
2190  KeQuerySystemTime(&NewTime);
2191 
2192  /* Substract times */
2193  LocalTimeOut.QuadPart += (NewTime.QuadPart - StartTime.QuadPart);
2194  StartTime = NewTime;
2195 
2196  /* Check if we've timed out */
2197  if (LocalTimeOut.QuadPart >= 0)
2198  {
2199  /* We have, break out of the loop */
2201  break;
2202  }
2203  }
2204  }
2205  else
2206  {
2207  /* Open the handles and dereference the objects */
2208  DbgkpOpenHandles(&WaitStateChange, Process, Thread);
2211  break;
2212  }
2213  }
2214 
2215  /* We're done, dereference the object */
2216  ObDereferenceObject(DebugObject);
2217 
2218  /* Protect write with SEH */
2219  _SEH2_TRY
2220  {
2221  /* Return our wait state change structure */
2222  *StateChange = WaitStateChange;
2223  }
2225  {
2226  /* Get SEH Exception code */
2228  }
2229  _SEH2_END;
2230 
2231  /* Return status */
2232  return Status;
2233 }
#define ProbeForWriteUlong(Ptr)
Definition: probe.h:36
#define KeQuerySystemTime(t)
Definition: env_spec_w32.h:570
ULONG DebugInfoSize
Definition: dbgktypes.h:166
#define MAXIMUM_ALLOWED
Definition: nt_native.h:83
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:35
static NTSTATUS StartThread(PTHREAD_DATA ThreadData, PLARGE_INTEGER Timeout, KIRQL Irql, BOOLEAN Try, BOOLEAN RetExpected)
Definition: ExFastMutex.c:205
_In_ PVOID _In_ BOOLEAN Alertable
Definition: exfuncs.h:452
IN CINT OUT PVOID IN ULONG OUT PULONG ReturnLength
Definition: dumpinfo.c:39
CPPORT Port[4]
Definition: headless.c:34
#define IN
Definition: typedefs.h:38
NTSYSAPI NTSTATUS NTAPI ZwFlushInstructionCache(_In_ HANDLE ProcessHandle, _In_ PVOID BaseAddress, _In_ ULONG NumberOfBytesToFlush)
NTSTATUS NTAPI ObCreateObjectType(IN PUNICODE_STRING TypeName, IN POBJECT_TYPE_INITIALIZER ObjectTypeInitializer, IN PVOID Reserved, OUT POBJECT_TYPE *ObjectType)
Definition: oblife.c:1048
#define THREAD_ALL_ACCESS
Definition: nt_native.h:1339
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
KAPC_STATE
Definition: ketypes.h:1273
#define DBG_TERMINATE_PROCESS
Definition: ntstatus.h:51
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define STATUS_PORT_NOT_SET
Definition: ntstatus.h:880
PPEB Peb
Definition: dllmain.c:27
#define DEBUG_EVENT_INACTIVE
Definition: dbgktypes.h:41
ULONG SkipTerminationMsg
Definition: pstypes.h:1117
VOID NTAPI DbgkpConvertKernelToUserStateChange(IN PDBGUI_WAIT_STATE_CHANGE WaitStateChange, IN PDEBUG_EVENT DebugEvent)
Definition: dbgkobj.c:845
#define PROCESS_ALL_ACCESS
Definition: nt_native.h:1324
NTSTATUS NTAPI DbgkpPostFakeModuleMessages(IN PEPROCESS Process, IN PETHREAD Thread, IN PDEBUG_OBJECT DebugObject)
Definition: dbgkobj.c:457
#define STANDARD_RIGHTS_WRITE
Definition: nt_native.h:66
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
HANDLE FileHandle
Definition: dbgktypes.h:163
LIST_ENTRY InLoadOrderModuleList
Definition: ldrtypes.h:120
NTKERNELAPI VOID FASTCALL ExReleaseRundownProtection(_Inout_ PEX_RUNDOWN_REF RunRef)
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
NTSTATUS ReturnedStatus
Definition: dbgktypes.h:210
struct _DEBUG_OBJECT DEBUG_OBJECT
#define PSF_CREATE_REPORTED_BIT
Definition: pstypes.h:257
UCHAR DebuggerInactive
Definition: dbgktypes.h:100
LONG NTSTATUS
Definition: precomp.h:26
EX_RUNDOWN_REF RundownProtect
Definition: pstypes.h:1090
#define STATUS_SINGLE_STEP
Definition: ntstatus.h:173
#define ExAcquireRundownProtection
Definition: ex.h:130
#define DBGK_KILL_PROCESS_ON_EXIT
Definition: dbgktypes.h:49
NTSTATUS NTAPI NtRemoveProcessDebug(IN HANDLE ProcessHandle, IN HANDLE DebugHandle)
Definition: dbgkobj.c:1873
NTSTATUS NTAPI NtDebugActiveProcess(IN HANDLE ProcessHandle, IN HANDLE DebugHandle)
Definition: dbgkobj.c:1797
#define DebugEvent(tess)
Definition: sweep.c:59
KPROCESSOR_MODE NTAPI ExGetPreviousMode(VOID)
Definition: sysinfo.c:3066
FAST_MUTEX Mutex
Definition: dbgktypes.h:93
VOID NTAPI ObDereferenceObject(IN PVOID Object)
Definition: obref.c:375
ACPI_BUFFER *RetBuffer ACPI_BUFFER *RetBuffer char ACPI_WALK_RESOURCE_CALLBACK void *Context ACPI_BUFFER *RetBuffer UINT16 ACPI_RESOURCE **ResourcePtr ACPI_GENERIC_ADDRESS *Reg UINT32 *ReturnValue UINT8 UINT8 *Slp_TypB ACPI_PHYSICAL_ADDRESS PhysicalAddress64 UINT32 UINT32 *TimeElapsed UINT32 ACPI_STATUS const char UINT32 ACPI_STATUS const char UINT32 const char const char * ModuleName
Definition: acpixf.h:1264
ACPI_PHYSICAL_ADDRESS ACPI_SIZE BOOLEAN Warn BOOLEAN Physical UINT32 ACPI_TABLE_HEADER *OutTableHeader ACPI_TABLE_HEADER **OutTable ACPI_HANDLE UINT32 ACPI_WALK_CALLBACK ACPI_WALK_CALLBACK void void **ReturnValue UINT32 ACPI_BUFFER *RetPathPtr ACPI_OBJECT_HANDLER void *Data ACPI_OBJECT_HANDLER void **Data ACPI_STRING ACPI_OBJECT_LIST ACPI_BUFFER *ReturnObjectBuffer ACPI_DEVICE_INFO **ReturnBuffer ACPI_HANDLE Parent
Definition: acpixf.h:722
NTSTATUS NTAPI MmGetFileNameForAddress(IN PVOID Address, OUT PUNICODE_STRING ModuleName)
Definition: section.c:1831
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
#define InsertTailList(ListHead, Entry)
#define STANDARD_RIGHTS_EXECUTE
Definition: nt_native.h:67
#define PROCESS_SUSPEND_RESUME
Definition: pstypes.h:159
NTSTATUS NTAPI ObOpenObjectByPointer(IN PVOID Object, IN ULONG HandleAttributes, IN PACCESS_STATE PassedAccessState, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, OUT PHANDLE Handle)
Definition: obhandle.c:2739
#define DBGK_THREAD_DEBUG
Definition: dbgk.h:17
#define STATUS_ALERTED
Definition: ntstatus.h:80
DBGKM_CREATE_PROCESS CreateProcess
Definition: dbgktypes.h:215
NTSTATUS NTAPI NtCreateDebugObject(OUT PHANDLE DebugHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, IN ULONG Flags)
Definition: dbgkobj.c:1571
LONG NTAPI KeSetEvent(IN PKEVENT Event, IN KPRIORITY Increment, IN BOOLEAN Wait)
Definition: eventobj.c:159
HANDLE NTAPI DbgkpSectionToFileHandle(IN PVOID Section)
Definition: dbgkutil.c:19
static LARGE_INTEGER StartTime
Definition: sys_arch.c:18
NTSTATUS NTAPI KeWaitForSingleObject(IN PVOID Object, IN KWAIT_REASON WaitReason, IN KPROCESSOR_MODE WaitMode, IN BOOLEAN Alertable, IN PLARGE_INTEGER Timeout OPTIONAL)
Definition: wait.c:416
#define DEBUG_EVENT_PROTECT_FAILED
Definition: dbgktypes.h:43
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
static __inline NTSTATUS DefaultSetInfoBufferCheck(ULONG Class, const INFORMATION_CLASS_INFO *ClassList, ULONG ClassListEntries, PVOID Buffer, ULONG BufferLength, KPROCESSOR_MODE PreviousMode)
Definition: probe.h:8
VOID NTAPI DbgkpDeleteObject(IN PVOID DebugObject)
Definition: dbgkobj.c:1101
VOID FASTCALL ExReleaseFastMutex(IN PFAST_MUTEX FastMutex)
Definition: fmutex.c:31
VOID NTAPI ProbeForWrite(IN PVOID Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:143
NTSTATUS NTAPI LpcRequestWaitReplyPort(IN PVOID PortObject, IN PPORT_MESSAGE LpcRequest, OUT PPORT_MESSAGE LpcReply)
Definition: send.c:178
#define DBG_CONTINUE
Definition: ntstatus.h:47
#define PAGED_CODE()
Definition: video.h:57
#define FILE_SHARE_READ
Definition: compat.h:125
_SEH2_TRY
Definition: create.c:4250
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
PVOID DllBase
Definition: btrfs_drv.h:1784
#define STATUS_TIMEOUT
Definition: ntstatus.h:81
WCHAR First[]
Definition: FormatMessage.c:11
VOID NTAPI DbgkpFreeDebugEvent(IN PDEBUG_EVENT DebugEvent)
Definition: dbgkobj.c:389
#define DEBUG_EVENT_SUSPEND
Definition: dbgktypes.h:44
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define DEBUG_OBJECT_WAIT_STATE_CHANGE
Definition: dbgktypes.h:31
#define OBJ_FORCE_ACCESS_CHECK
Definition: winternl.h:232
#define DBGK_OBJECT_DEBUG
Definition: dbgk.h:19
NTSTATUS NTAPI NtWaitForDebugEvent(IN HANDLE DebugHandle, IN BOOLEAN Alertable, IN PLARGE_INTEGER Timeout OPTIONAL, OUT PDBGUI_WAIT_STATE_CHANGE StateChange)
Definition: dbgkobj.c:2001
NTSTATUS NTAPI ObReferenceObjectByHandle(IN HANDLE Handle, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, OUT PVOID *Object, OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL)
Definition: obref.c:496
#define DUPLICATE_SAME_ACCESS
DBGKM_LOAD_DLL LoadDll
Definition: dbgktypes.h:218
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
PEPROCESS PsInitialSystemProcess
Definition: psmgr.c:50
VOID NTAPI KeStackAttachProcess(IN PKPROCESS Process, OUT PRKAPC_STATE ApcState)
Definition: procobj.c:701
#define DBG_EXCEPTION_HANDLED
Definition: ntstatus.h:46
PORT_MESSAGE h
Definition: dbgktypes.h:208
struct NameRec_ * Name
Definition: cdprocs.h:464
#define PsGetCurrentProcess
Definition: psfuncs.h:17
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
VOID INIT_FUNCTION NTAPI DbgkInitialize(VOID)
Definition: dbgkobj.c:1498
unsigned char BOOLEAN
HANDLE WINAPI DECLSPEC_HOTPATCH CreateThread(IN LPSECURITY_ATTRIBUTES lpThreadAttributes, IN DWORD dwStackSize, IN LPTHREAD_START_ROUTINE lpStartAddress, IN LPVOID lpParameter, IN DWORD dwCreationFlags, OUT LPDWORD lpThreadId)
Definition: thread.c:136
GENERIC_MAPPING DbgkDebugObjectMapping
Definition: dbgkobj.c:19
smooth NULL
Definition: ftsmooth.c:416
#define STATUS_BREAKPOINT
Definition: ntstatus.h:172
FORCEINLINE PLIST_ENTRY RemoveHeadList(_Inout_ PLIST_ENTRY ListHead)
Definition: rtlfuncs.h:128
NTSTATUS NTAPI DbgkOpenProcessDebugPort(IN PEPROCESS Process, IN KPROCESSOR_MODE PreviousMode, OUT HANDLE *DebugHandle)
Definition: dbgkobj.c:1526
Definition: bufpool.h:45
_In_ PCWSTR FullDllName
Definition: ldrtypes.h:247
OB_CLOSE_METHOD CloseProcedure
Definition: obtypes.h:368
IMAGE_FILE_HEADER FileHeader
Definition: ntddk_ex.h:183
NTSTATUS NTAPI NtDebugContinue(IN HANDLE DebugHandle, IN PCLIENT_ID AppClientId, IN NTSTATUS ContinueStatus)
Definition: dbgkobj.c:1665
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
NTSTATUS NTAPI ObCreateObject(IN KPROCESSOR_MODE ProbeMode OPTIONAL, IN POBJECT_TYPE Type, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN KPROCESSOR_MODE AccessMode, IN OUT PVOID ParseContext OPTIONAL, IN ULONG ObjectSize, IN ULONG PagedPoolCharge OPTIONAL, IN ULONG NonPagedPoolCharge OPTIONAL, OUT PVOID *Object)
Definition: oblife.c:952
#define NtCurrentProcess()
Definition: nt_native.h:1657
BOOLEAN NTAPI DbgkpSuspendProcess(VOID)
Definition: dbgkutil.c:57
ULONG DbgkpTraceLevel
Definition: dbgkobj.c:17
FAST_MUTEX
Definition: extypes.h:17
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
_In_ HANDLE Handle
Definition: extypes.h:390
_In_ KPROCESSOR_MODE PreviousMode
Definition: sefuncs.h:103
enum _DEBUGOBJECTINFOCLASS DEBUGOBJECTINFOCLASS
#define DEBUG_EVENT_READ
Definition: dbgktypes.h:39
_Out_ PCLIENT_ID ClientId
Definition: kefuncs.h:1176
NTSTATUS NTAPI DbgkpPostFakeProcessCreateMessages(IN PEPROCESS Process, IN PDEBUG_OBJECT DebugObject, OUT PETHREAD *LastThread)
Definition: dbgkobj.c:793
NTSTATUS NTAPI PsSuspendThread(IN PETHREAD Thread, OUT PULONG PreviousCount OPTIONAL)
Definition: state.c:48
VOID NTAPI DbgkpOpenHandles(IN PDBGUI_WAIT_STATE_CHANGE WaitStateChange, IN PEPROCESS Process, IN PETHREAD Thread)
Definition: dbgkobj.c:996
DWORD NumberOfSymbols
Definition: ntddk_ex.h:126
#define _SEH2_YIELD(STMT_)
Definition: pseh2_64.h:8
VOID NTAPI DbgkCopyProcessDebugPort(IN PEPROCESS Process, IN PEPROCESS Parent)
Definition: dbgkobj.c:276
BOOLEAN NTAPI DbgkForwardException(IN PEXCEPTION_RECORD ExceptionRecord, IN BOOLEAN DebugPort, IN BOOLEAN SecondChance)
Definition: dbgkobj.c:317
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define STATUS_PENDING
Definition: ntstatus.h:82
NTSTATUS NTAPI PsTerminateProcess(IN PEPROCESS Process, IN NTSTATUS ExitStatus)
Definition: kill.c:129
#define PSF_NO_DEBUG_INHERIT_BIT
Definition: pstypes.h:258
CLIENT_ID Cid
Definition: pstypes.h:1059
FORCEINLINE VOID ExInitializeFastMutex(_Out_ PFAST_MUTEX FastMutex)
Definition: exfuncs.h:274
#define STATUS_PROCESS_IS_TERMINATING
Definition: ntstatus.h:488
ULONG SkipCreationMsg
Definition: pstypes.h:1116
#define DBGK_ALL_FLAGS
Definition: dbgktypes.h:50
#define ProbeForWriteHandle(Ptr)
Definition: probe.h:43
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
#define DBGK_EXCEPTION_DEBUG
Definition: dbgk.h:21
VOID NTAPI DbgkpResumeProcess(VOID)
Definition: dbgkutil.c:77
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
#define ProbeForReadLargeInteger(Ptr)
Definition: probe.h:75
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
CHAR Message[80]
Definition: alive.c:5
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
PETHREAD NTAPI PsGetNextProcessThread(IN PEPROCESS Process, IN PETHREAD Thread OPTIONAL)
Definition: process.c:75
NTSYSAPI NTSTATUS NTAPI ZwOpenFile(_Out_ PHANDLE FileHandle, _In_ ACCESS_MASK DesiredAccess, _In_ POBJECT_ATTRIBUTES ObjectAttributes, _Out_ PIO_STATUS_BLOCK IoStatusBlock, _In_ ULONG ShareAccess, _In_ ULONG OpenOptions)
#define DBG_EXCEPTION_NOT_HANDLED
Definition: ntstatus.h:57
unsigned char UCHAR
Definition: xmlstorage.h:181
POBJECT_TYPE DbgkDebugObjectType
Definition: dbgkobj.c:15
NTSTATUS NTAPI ObCloseHandle(IN HANDLE Handle, IN KPROCESSOR_MODE AccessMode)
Definition: obhandle.c:3376
POBJECT_TYPE PsThreadType
Definition: thread.c:20
#define FILE_SHARE_DELETE
Definition: nt_native.h:682
VOID NTAPI ProbeForRead(IN CONST VOID *Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:102
static const WCHAR L[]
Definition: oid.c:1250
NTSTATUS NTAPI DbgkpSetProcessDebugObject(IN PEPROCESS Process, IN PDEBUG_OBJECT DebugObject, IN NTSTATUS MsgStatus, IN PETHREAD LastThread)
Definition: dbgkobj.c:1201
NTSTATUS NTAPI DbgkClearProcessDebugObject(IN PEPROCESS Process, IN PDEBUG_OBJECT SourceDebugObject OPTIONAL)
Definition: dbgkobj.c:1410
#define PspSetCrossThreadFlag(Thread, Flag)
Definition: ps_x.h:25
NTSTATUS NTAPI DbgkpSendApiMessage(IN OUT PDBGKM_MSG ApiMsg, IN BOOLEAN SuspendProcess)
Definition: dbgkobj.c:242
PVOID NamePointer
Definition: dbgktypes.h:167
PVOID *typedef PHANDLE
Definition: ntsecpkg.h:414
Definition: btrfs_drv.h:1780
#define STATUS_DEBUGGER_INACTIVE
Definition: debugger.c:30
PEPROCESS NTAPI PsGetNextProcess(IN PEPROCESS OldProcess OPTIONAL)
Definition: process.c:128
#define NOTHING
Definition: env_spec_w32.h:461
#define GENERIC_READ
Definition: compat.h:124
Definition: typedefs.h:117
NTSTATUS NTAPI DbgkpPostFakeThreadMessages(IN PEPROCESS Process, IN PDEBUG_OBJECT DebugObject, IN PETHREAD StartThread, OUT PETHREAD *FirstThread, OUT PETHREAD *LastThread)
Definition: dbgkobj.c:594
#define STANDARD_RIGHTS_READ
Definition: nt_native.h:65
#define SYNCHRONIZE
Definition: nt_native.h:61
#define CreateProcess
Definition: winbase.h:3575
ULONG SystemThread
Definition: pstypes.h:1113
static const INFORMATION_CLASS_INFO DbgkpDebugObjectInfoClass[]
Definition: dbgkobj.c:27
#define DBG_TERMINATE_THREAD
Definition: ntstatus.h:50
LIST_ENTRY EventList
Definition: dbgktypes.h:94
Status
Definition: gdiplustypes.h:24
PETHREAD LastThread
Definition: pinsup.c:109
#define STATUS_USER_APC
Definition: ntstatus.h:78
VOID NTAPI DbgkpWakeTarget(IN PDEBUG_EVENT DebugEvent)
Definition: dbgkobj.c:426
#define DEBUG_EVENT_NOWAIT
Definition: dbgktypes.h:40
_SEH2_END
Definition: create.c:4424
NTSTATUS NTAPI ObInsertObject(IN PVOID Object, IN PACCESS_STATE AccessState OPTIONAL, IN ACCESS_MASK DesiredAccess, IN ULONG ObjectPointerBias, OUT PVOID *NewObject OPTIONAL, OUT PHANDLE Handle)
Definition: obhandle.c:2932
static ULONG Timeout
Definition: ping.c:61
LONG NTAPI ExSystemExceptionFilter(VOID)
Definition: harderr.c:351
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
GENERIC_MAPPING GenericMapping
Definition: obtypes.h:358
VOID FASTCALL ExAcquireFastMutex(IN PFAST_MUTEX FastMutex)
Definition: fmutex.c:23
PPEB_LDR_DATA Ldr
Definition: btrfs_drv.h:1816
VOID NTAPI KeUnstackDetachProcess(IN PRKAPC_STATE ApcState)
Definition: procobj.c:753
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
_In_ PIO_STACK_LOCATION _Inout_ PFILE_OBJECT _Inout_ PVCB _Outptr_result_maybenull_ PDCB _In_ PDCB _In_ PDIRENT _In_ ULONG _In_ ULONG _In_ PUNICODE_STRING _In_ PACCESS_MASK DesiredAccess
Definition: create.c:4157
#define PORT_MAXIMUM_MESSAGE_LENGTH
Definition: iotypes.h:1986
DBGKM_APINUMBER ApiNumber
Definition: dbgktypes.h:209
_Out_ PKAPC_STATE ApcState
Definition: mm.h:1492
UNICODE_STRING FullDllName
Definition: btrfs_drv.h:1786
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
NTSTATUS NTAPI DbgkpQueueMessage(IN PEPROCESS Process, IN PETHREAD Thread, IN PDBGKM_MSG Message, IN ULONG Flags, IN PDEBUG_OBJECT TargetObject OPTIONAL)
Definition: dbgkobj.c:39
unsigned int * PULONG
Definition: retypes.h:1
struct _DBGKM_MSG DBGKM_MSG
#define DBGK_PROCESS_DEBUG
Definition: dbgk.h:18
#define CT_SKIP_CREATION_MSG_BIT
Definition: pstypes.h:229
NTSTATUS NTAPI NtSetInformationDebugObject(IN HANDLE DebugHandle, IN DEBUGOBJECTINFOCLASS DebugObjectInformationClass, IN PVOID DebugInformation, IN ULONG DebugInformationLength, OUT PULONG ReturnLength OPTIONAL)
Definition: dbgkobj.c:1921
#define DBGKTRACE(x, fmt,...)
Definition: dbgk.h:46
#define RtlImageNtHeader
Definition: compat.h:457
NTSTATUS NTAPI DbgkpSendApiMessageLpc(IN OUT PDBGKM_MSG Message, IN PVOID Port, IN BOOLEAN SuspendProcess)
Definition: dbgkobj.c:206
#define FILE_SYNCHRONOUS_IO_NONALERT
Definition: from_kernel.h:31
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:219
#define DEBUG_OBJECT_ADD_REMOVE_PROCESS
Definition: dbgktypes.h:32
NTSTATUS NTAPI PsResumeThread(IN PETHREAD Thread, OUT PULONG PreviousCount OPTIONAL)
Definition: state.c:32
#define OUT
Definition: typedefs.h:39
#define DBGK_MESSAGE_DEBUG
Definition: dbgk.h:20
#define ObReferenceObject
Definition: obfuncs.h:204
#define PspSetProcessFlag(Process, Flag)
Definition: ps_x.h:33
ULONG DebugInfoFileOffset
Definition: dbgktypes.h:165
#define DEBUG_EVENT_RELEASE
Definition: dbgktypes.h:42
unsigned int ULONG
Definition: retypes.h:1
#define IO_NO_INCREMENT
Definition: iotypes.h:566
#define DEBUG_OBJECT_ALL_ACCESS
Definition: dbgktypes.h:34
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
NTSTATUS NTAPI ObDuplicateObject(IN PEPROCESS SourceProcess, IN HANDLE SourceHandle, IN PEPROCESS TargetProcess OPTIONAL, IN PHANDLE TargetHandle OPTIONAL, IN ACCESS_MASK DesiredAccess, IN ULONG HandleAttributes, IN ULONG Options, IN KPROCESSOR_MODE PreviousMode)
Definition: obhandle.c:2201
EXCEPTION_RECORD ExceptionRecord
Definition: dbgktypes.h:131
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:12
VOID NTAPI KeClearEvent(IN PKEVENT Event)
Definition: eventobj.c:22
_In_ PSECURITY_SUBJECT_CONTEXT _In_ BOOLEAN _In_ ACCESS_MASK _In_ ACCESS_MASK _Outptr_opt_ PPRIVILEGE_SET _In_ PGENERIC_MAPPING _In_ KPROCESSOR_MODE _Out_ PACCESS_MASK GrantedAccess
Definition: sefuncs.h:13
_In_ HANDLE ProcessHandle
Definition: mmfuncs.h:403
return STATUS_SUCCESS
Definition: btrfs.c:2966
OB_DELETE_METHOD DeleteProcedure
Definition: obtypes.h:369
VOID NTAPI DbgkpMarkProcessPeb(IN PEPROCESS Process)
Definition: dbgkobj.c:962
#define OBJ_KERNEL_HANDLE
Definition: winternl.h:231
UCHAR KillProcessOnExit
Definition: dbgktypes.h:101
POBJECT_TYPE PsProcessType
Definition: process.c:20
ULONG DefaultNonPagedPoolCharge
Definition: obtypes.h:365
ULONG ACCESS_MASK
Definition: nt_native.h:40
DBGKM_CREATE_THREAD CreateThread
Definition: dbgktypes.h:214
DBGKM_EXCEPTION Exception
Definition: dbgktypes.h:213
FAST_MUTEX DbgkpProcessDebugPortMutex
Definition: dbgkobj.c:16
VOID NTAPI DbgkpCloseObject(IN PEPROCESS OwnerProcess OPTIONAL, IN PVOID ObjectBody, IN ACCESS_MASK GrantedAccess, IN ULONG HandleCount, IN ULONG SystemHandleCount)
Definition: dbgkobj.c:1111
LONGLONG QuadPart
Definition: typedefs.h:112
#define STATUS_PORT_ALREADY_SET
Definition: ntstatus.h:294
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
KEVENT EventsPresent
Definition: dbgktypes.h:92