ReactOS 0.4.15-dev-7788-g1ad9096
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
28{
29 /* DebugObjectUnusedInformation */
30 IQS_SAME(ULONG, ULONG, 0),
31 /* DebugObjectKillProcessOnExitInformation */
33};
34
35/* PRIVATE FUNCTIONS *********************************************************/
36
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),
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 */
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,
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 */
196 }
197 }
198
199 /* Return status */
200 DBGKTRACE(DBGK_MESSAGE_DEBUG, "Status: %lx\n", Status);
201 return Status;
202}
203
205NTAPI
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
241NTAPI
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
274VOID
275NTAPI
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
316NTAPI
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)) ||
378 {
379 /* Fail */
380 return FALSE;
381 }
382
383 /* Otherwise, we're ok */
384 return TRUE;
385}
386
387VOID
388NTAPI
390{
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 */
417
418 /* Dereference process and thread and free the event */
422}
423
424VOID
425NTAPI
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
456NTAPI
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 */
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,
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
593NTAPI
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;
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 */
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
792NTAPI
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
843VOID
844NTAPI
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) */
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 */
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 */
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 */
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
960VOID
961NTAPI
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
994VOID
995NTAPI
999{
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,
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,
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,
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 */
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
1099VOID
1100NTAPI
1102{
1103 PAGED_CODE();
1104
1105 /* Sanity check */
1106 ASSERT(IsListEmpty(&((PDEBUG_OBJECT)DebugObject)->EventList));
1107}
1108
1109VOID
1110NTAPI
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 */
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
1200NTAPI
1202 IN PDEBUG_OBJECT DebugObject,
1203 IN NTSTATUS MsgStatus,
1205{
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 */
1237ThreadScan:
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 */
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
1409NTAPI
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
1495CODE_SEG("INIT")
1496VOID
1497NTAPI
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
1525NTAPI
1528 OUT HANDLE *DebugHandle)
1529{
1530 PDEBUG_OBJECT DebugObject;
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,
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 */
1570NTAPI
1574 IN ULONG Flags)
1575{
1577 PDEBUG_OBJECT DebugObject;
1578 HANDLE hDebug;
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 */
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,
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 */
1664NTAPI
1666 IN PCLIENT_ID AppClientId,
1667 IN NTSTATUS ContinueStatus)
1668{
1670 PDEBUG_OBJECT DebugObject;
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,
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,
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 */
1796NTAPI
1798 IN HANDLE DebugHandle)
1799{
1801 PDEBUG_OBJECT DebugObject;
1805 PAGED_CODE();
1806 DBGKTRACE(DBGK_PROCESS_DEBUG, "Process: %p Handle: %p\n",
1807 ProcessHandle, DebugHandle);
1808
1809 /* Reference the process */
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,
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 */
1872NTAPI
1874 IN HANDLE DebugHandle)
1875{
1877 PDEBUG_OBJECT DebugObject;
1880 PAGED_CODE();
1881 DBGKTRACE(DBGK_PROCESS_DEBUG, "Process: %p Handle: %p\n",
1882 ProcessHandle, DebugHandle);
1883
1884 /* Reference the process */
1889 (PVOID*)&Process,
1890 NULL);
1891 if (!NT_SUCCESS(Status)) return Status;
1892
1893 /* Reference the debug object */
1894 Status = ObReferenceObjectByHandle(DebugHandle,
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 */
1909
1910 /* Dereference the process and debug object and return status */
1912 ObDereferenceObject(DebugObject);
1913 return Status;
1914}
1915
1916/*
1917 * @implemented
1918 */
1920NTAPI
1922 IN DEBUGOBJECTINFOCLASS DebugObjectInformationClass,
1923 IN PVOID DebugInformation,
1924 IN ULONG DebugInformationLength,
1926{
1927 PDEBUG_OBJECT DebugObject;
1930 PDEBUG_OBJECT_KILL_PROCESS_ON_EXIT_INFORMATION DebugInfo = DebugInformation;
1931 PAGED_CODE();
1932
1933 /* Check buffers and parameters */
1934 Status = DefaultSetInfoBufferCheck(DebugObjectInformationClass,
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,
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 */
2000NTAPI
2004 OUT PDBGUI_WAIT_STATE_CHANGE StateChange)
2005{
2007 LARGE_INTEGER LocalTimeOut;
2011 BOOLEAN GotEvent;
2012 LARGE_INTEGER NewTime;
2013 PDEBUG_OBJECT DebugObject;
2014 DBGUI_WAIT_STATE_CHANGE WaitStateChange;
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,
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 {
2078 Executive,
2080 Alertable,
2081 Timeout);
2082 if (!NT_SUCCESS(Status) ||
2083 (Status == STATUS_TIMEOUT) ||
2084 (Status == STATUS_ALERTED) ||
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,
2111 EventList);
2112 DBGKTRACE(DBGK_PROCESS_DEBUG, "DebugEvent: %p Flags: %lx\n",
2113 DebugEvent, DebugEvent->Flags);
2114
2115 /* Check flags */
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,
2128 EventList);
2129
2130 /* Try to match process IDs */
2131 if (DebugEvent2->ClientId.UniqueProcess ==
2132 DebugEvent->ClientId.UniqueProcess)
2133 {
2134 /* Found it, break out */
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 PAGED_CODE()
static NTSTATUS StartThread(PTHREAD_DATA ThreadData, PLARGE_INTEGER Timeout, KIRQL Irql, BOOLEAN Try, BOOLEAN RetExpected)
Definition: ExFastMutex.c:205
WCHAR First[]
Definition: FormatMessage.c:11
unsigned char BOOLEAN
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:1280
ACPI_PHYSICAL_ADDRESS ACPI_SIZE BOOLEAN Warn UINT32 *TableIdx 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:732
struct NameRec_ * Name
Definition: cdprocs.h:460
LONG NTSTATUS
Definition: precomp.h:26
Definition: bufpool.h:45
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:36
#define DBGK_OBJECT_DEBUG
Definition: dbgk.h:19
#define DBGK_PROCESS_DEBUG
Definition: dbgk.h:18
#define DBGK_EXCEPTION_DEBUG
Definition: dbgk.h:21
#define DBGK_MESSAGE_DEBUG
Definition: dbgk.h:20
#define DBGKTRACE(x, fmt,...)
Definition: dbgk.h:46
#define DBGK_THREAD_DEBUG
Definition: dbgk.h:17
NTSTATUS NTAPI DbgkpSendApiMessageLpc(IN OUT PDBGKM_MSG Message, IN PVOID Port, IN BOOLEAN SuspendProcess)
Definition: dbgkobj.c:206
NTSTATUS NTAPI NtSetInformationDebugObject(IN HANDLE DebugHandle, IN DEBUGOBJECTINFOCLASS DebugObjectInformationClass, IN PVOID DebugInformation, IN ULONG DebugInformationLength, OUT PULONG ReturnLength OPTIONAL)
Definition: dbgkobj.c:1921
VOID NTAPI DbgkCopyProcessDebugPort(IN PEPROCESS Process, IN PEPROCESS Parent)
Definition: dbgkobj.c:276
VOID NTAPI DbgkpConvertKernelToUserStateChange(IN PDBGUI_WAIT_STATE_CHANGE WaitStateChange, IN PDEBUG_EVENT DebugEvent)
Definition: dbgkobj.c:845
NTSTATUS NTAPI NtDebugContinue(IN HANDLE DebugHandle, IN PCLIENT_ID AppClientId, IN NTSTATUS ContinueStatus)
Definition: dbgkobj.c:1665
VOID NTAPI DbgkpFreeDebugEvent(IN PDEBUG_EVENT DebugEvent)
Definition: dbgkobj.c:389
NTSTATUS NTAPI DbgkpSetProcessDebugObject(IN PEPROCESS Process, IN PDEBUG_OBJECT DebugObject, IN NTSTATUS MsgStatus, IN PETHREAD LastThread)
Definition: dbgkobj.c:1201
VOID NTAPI DbgkpDeleteObject(IN PVOID DebugObject)
Definition: dbgkobj.c:1101
VOID NTAPI DbgkpMarkProcessPeb(IN PEPROCESS Process)
Definition: dbgkobj.c:962
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
NTSTATUS NTAPI DbgkClearProcessDebugObject(IN PEPROCESS Process, IN PDEBUG_OBJECT SourceDebugObject OPTIONAL)
Definition: dbgkobj.c:1410
NTSTATUS NTAPI DbgkOpenProcessDebugPort(IN PEPROCESS Process, IN KPROCESSOR_MODE PreviousMode, OUT HANDLE *DebugHandle)
Definition: dbgkobj.c:1526
NTSTATUS NTAPI NtRemoveProcessDebug(IN HANDLE ProcessHandle, IN HANDLE DebugHandle)
Definition: dbgkobj.c:1873
NTSTATUS NTAPI DbgkpPostFakeProcessCreateMessages(IN PEPROCESS Process, IN PDEBUG_OBJECT DebugObject, OUT PETHREAD *LastThread)
Definition: dbgkobj.c:793
NTSTATUS NTAPI DbgkpPostFakeModuleMessages(IN PEPROCESS Process, IN PETHREAD Thread, IN PDEBUG_OBJECT DebugObject)
Definition: dbgkobj.c:457
ULONG DbgkpTraceLevel
Definition: dbgkobj.c:17
NTSTATUS NTAPI DbgkpPostFakeThreadMessages(IN PEPROCESS Process, IN PDEBUG_OBJECT DebugObject, IN PETHREAD StartThread, OUT PETHREAD *FirstThread, OUT PETHREAD *LastThread)
Definition: dbgkobj.c:594
NTSTATUS NTAPI NtCreateDebugObject(OUT PHANDLE DebugHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, IN ULONG Flags)
Definition: dbgkobj.c:1571
BOOLEAN NTAPI DbgkForwardException(IN PEXCEPTION_RECORD ExceptionRecord, IN BOOLEAN DebugPort, IN BOOLEAN SecondChance)
Definition: dbgkobj.c:317
FAST_MUTEX DbgkpProcessDebugPortMutex
Definition: dbgkobj.c:16
NTSTATUS NTAPI NtDebugActiveProcess(IN HANDLE ProcessHandle, IN HANDLE DebugHandle)
Definition: dbgkobj.c:1797
POBJECT_TYPE DbgkDebugObjectType
Definition: dbgkobj.c:15
static const INFORMATION_CLASS_INFO DbgkpDebugObjectInfoClass[]
Definition: dbgkobj.c:27
VOID NTAPI DbgkpCloseObject(IN PEPROCESS OwnerProcess OPTIONAL, IN PVOID ObjectBody, IN ACCESS_MASK GrantedAccess, IN ULONG HandleCount, IN ULONG SystemHandleCount)
Definition: dbgkobj.c:1111
VOID NTAPI DbgkpWakeTarget(IN PDEBUG_EVENT DebugEvent)
Definition: dbgkobj.c:426
NTSTATUS NTAPI NtWaitForDebugEvent(IN HANDLE DebugHandle, IN BOOLEAN Alertable, IN PLARGE_INTEGER Timeout OPTIONAL, OUT PDBGUI_WAIT_STATE_CHANGE StateChange)
Definition: dbgkobj.c:2001
VOID NTAPI DbgkpOpenHandles(IN PDBGUI_WAIT_STATE_CHANGE WaitStateChange, IN PEPROCESS Process, IN PETHREAD Thread)
Definition: dbgkobj.c:996
GENERIC_MAPPING DbgkDebugObjectMapping
Definition: dbgkobj.c:19
NTSTATUS NTAPI DbgkpSendApiMessage(IN OUT PDBGKM_MSG ApiMsg, IN BOOLEAN SuspendProcess)
Definition: dbgkobj.c:242
VOID NTAPI DbgkInitialize(VOID)
Definition: dbgkobj.c:1498
#define DEBUG_OBJECT_ALL_ACCESS
Definition: dbgktypes.h:34
#define DEBUG_OBJECT_WAIT_STATE_CHANGE
Definition: dbgktypes.h:31
#define DEBUG_EVENT_READ
Definition: dbgktypes.h:39
#define DEBUG_EVENT_NOWAIT
Definition: dbgktypes.h:40
enum _DEBUGOBJECTINFOCLASS DEBUGOBJECTINFOCLASS
#define DEBUG_EVENT_PROTECT_FAILED
Definition: dbgktypes.h:43
#define DEBUG_EVENT_SUSPEND
Definition: dbgktypes.h:44
#define DEBUG_EVENT_INACTIVE
Definition: dbgktypes.h:41
struct _DEBUG_OBJECT DEBUG_OBJECT
#define DBGK_KILL_PROCESS_ON_EXIT
Definition: dbgktypes.h:49
#define DEBUG_EVENT_RELEASE
Definition: dbgktypes.h:42
#define DEBUG_OBJECT_ADD_REMOVE_PROCESS
Definition: dbgktypes.h:32
struct _DBGKM_MSG DBGKM_MSG
@ DbgBreakpointStateChange
Definition: dbgktypes.h:120
@ DbgCreateProcessStateChange
Definition: dbgktypes.h:116
@ DbgCreateThreadStateChange
Definition: dbgktypes.h:115
@ DbgExitProcessStateChange
Definition: dbgktypes.h:118
@ DbgExceptionStateChange
Definition: dbgktypes.h:119
@ DbgUnloadDllStateChange
Definition: dbgktypes.h:123
@ DbgExitThreadStateChange
Definition: dbgktypes.h:117
@ DbgSingleStepStateChange
Definition: dbgktypes.h:121
@ DbgLoadDllStateChange
Definition: dbgktypes.h:122
#define DBGK_ALL_FLAGS
Definition: dbgktypes.h:50
@ DbgKmExceptionApi
Definition: dbgktypes.h:66
@ DbgKmCreateProcessApi
Definition: dbgktypes.h:68
@ DbgKmCreateThreadApi
Definition: dbgktypes.h:67
@ DbgKmExitProcessApi
Definition: dbgktypes.h:70
@ DbgKmUnloadDllApi
Definition: dbgktypes.h:72
@ DbgKmExitThreadApi
Definition: dbgktypes.h:69
@ DbgKmLoadDllApi
Definition: dbgktypes.h:71
HANDLE NTAPI DbgkpSectionToFileHandle(IN PVOID Section)
Definition: dbgkutil.c:19
VOID NTAPI DbgkpResumeProcess(VOID)
Definition: dbgkutil.c:77
BOOLEAN NTAPI DbgkpSuspendProcess(VOID)
Definition: dbgkutil.c:57
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define GENERIC_READ
Definition: compat.h:135
#define RtlImageNtHeader
Definition: compat.h:806
#define FILE_SHARE_READ
Definition: compat.h:136
PPEB Peb
Definition: dllmain.c:27
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:137
static const WCHAR Message[]
Definition: register.c:74
IN CINT OUT PVOID IN ULONG OUT PULONG ReturnLength
Definition: dumpinfo.c:43
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define InsertTailList(ListHead, Entry)
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
#define KeWaitForSingleObject(pEvt, foo, a, b, c)
Definition: env_spec_w32.h:478
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define KeSetEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:476
#define KeQuerySystemTime(t)
Definition: env_spec_w32.h:570
#define RemoveHeadList(ListHead)
Definition: env_spec_w32.h:964
#define NonPagedPool
Definition: env_spec_w32.h:307
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
VOID NTAPI KeClearEvent(IN PKEVENT Event)
Definition: eventobj.c:22
#define ExReleaseRundownProtection
Definition: ex.h:136
#define ExGetPreviousMode
Definition: ex.h:140
#define ExAcquireRundownProtection
Definition: ex.h:135
VOID NTAPI ProbeForRead(IN CONST VOID *Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:102
VOID NTAPI ProbeForWrite(IN PVOID Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:143
#define _SEH2_END
Definition: filesup.c:22
#define _SEH2_TRY
Definition: filesup.c:19
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
#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:223
ULONG Handle
Definition: gdb_input.c:15
Status
Definition: gdiplustypes.h:25
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
VOID FASTCALL ExAcquireFastMutex(IN PFAST_MUTEX FastMutex)
Definition: fmutex.c:23
VOID FASTCALL ExReleaseFastMutex(IN PFAST_MUTEX FastMutex)
Definition: fmutex.c:31
LONG NTAPI ExSystemExceptionFilter(VOID)
Definition: harderr.c:349
CPPORT Port[4]
Definition: headless.c:35
#define ICIF_SET
Definition: icif.h:19
#define IQS_SAME(Type, Alignment, Flags)
Definition: icif.h:37
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
#define PROCESS_SUSPEND_RESUME
Definition: pstypes.h:167
#define CT_SKIP_CREATION_MSG_BIT
Definition: pstypes.h:245
#define PSF_CREATE_REPORTED_BIT
Definition: pstypes.h:273
#define PSF_NO_DEBUG_INHERIT_BIT
Definition: pstypes.h:274
#define OBJ_KERNEL_HANDLE
Definition: winternl.h:231
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
#define OBJ_FORCE_ACCESS_CHECK
Definition: winternl.h:232
#define NOTHING
Definition: input_list.c:10
static CODE_SEG("PAGE")
Definition: isapnp.c:1482
_In_ PCWSTR FullDllName
Definition: ldrtypes.h:247
#define ASSERT(a)
Definition: mode.c:44
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
#define STATUS_DEBUGGER_INACTIVE
Definition: debugger.c:30
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
#define LPC_EXCEPTION
Definition: port.c:99
#define LPC_DEBUG_EVENT
Definition: port.c:100
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
#define KernelMode
Definition: asm.h:34
_In_ PVOID _In_ BOOLEAN Alertable
Definition: exfuncs.h:453
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)
NTSYSAPI NTSTATUS NTAPI ZwFlushInstructionCache(_In_ HANDLE ProcessHandle, _In_ PVOID BaseAddress, _In_ ULONG NumberOfBytesToFlush)
_In_ HANDLE ProcessHandle
Definition: mmfuncs.h:403
#define THREAD_ALL_ACCESS
Definition: nt_native.h:1339
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
#define SYNCHRONIZE
Definition: nt_native.h:61
ULONG ACCESS_MASK
Definition: nt_native.h:40
#define PROCESS_ALL_ACCESS
Definition: nt_native.h:1324
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define NtCurrentProcess()
Definition: nt_native.h:1657
#define FILE_SHARE_DELETE
Definition: nt_native.h:682
#define STANDARD_RIGHTS_READ
Definition: nt_native.h:65
#define STANDARD_RIGHTS_WRITE
Definition: nt_native.h:66
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
#define STANDARD_RIGHTS_EXECUTE
Definition: nt_native.h:67
#define MAXIMUM_ALLOWED
Definition: nt_native.h:83
@ NotificationEvent
@ SynchronizationEvent
_Out_ PKAPC_STATE ApcState
Definition: mm.h:1765
NTSTATUS NTAPI MmGetFileNameForAddress(IN PVOID Address, OUT PUNICODE_STRING ModuleName)
Definition: section.c:1885
static __inline NTSTATUS DefaultSetInfoBufferCheck(_In_ ULONG Class, _In_ const INFORMATION_CLASS_INFO *ClassList, _In_ ULONG ClassListEntries, _In_ PVOID Buffer, _In_ ULONG BufferLength, _In_ KPROCESSOR_MODE PreviousMode)
Probe helper that validates the provided parameters whenever a NtSet*** system call is invoked from u...
Definition: probe.h:70
NTSTATUS NTAPI LpcRequestWaitReplyPort(IN PVOID PortObject, IN PPORT_MESSAGE LpcRequest, OUT PPORT_MESSAGE LpcReply)
Definition: send.c:178
POBJECT_TYPE PsProcessType
Definition: process.c:20
POBJECT_TYPE PsThreadType
Definition: thread.c:20
PVOID *typedef PHANDLE
Definition: ntsecpkg.h:455
#define STATUS_TIMEOUT
Definition: ntstatus.h:81
#define STATUS_ALERTED
Definition: ntstatus.h:80
#define STATUS_USER_APC
Definition: ntstatus.h:78
#define DBG_TERMINATE_PROCESS
Definition: ntstatus.h:51
#define STATUS_PENDING
Definition: ntstatus.h:82
#define STATUS_SINGLE_STEP
Definition: ntstatus.h:185
#define STATUS_PROCESS_IS_TERMINATING
Definition: ntstatus.h:502
#define DBG_TERMINATE_THREAD
Definition: ntstatus.h:50
#define DBG_CONTINUE
Definition: ntstatus.h:47
#define STATUS_BREAKPOINT
Definition: ntstatus.h:184
#define DBG_EXCEPTION_NOT_HANDLED
Definition: ntstatus.h:57
#define STATUS_PORT_NOT_SET
Definition: ntstatus.h:894
#define STATUS_PORT_ALREADY_SET
Definition: ntstatus.h:308
#define DBG_EXCEPTION_HANDLED
Definition: ntstatus.h:46
#define L(x)
Definition: ntvdm.h:50
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:2204
NTSTATUS NTAPI ObCloseHandle(IN HANDLE Handle, IN KPROCESSOR_MODE AccessMode)
Definition: obhandle.c:3379
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:2935
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:2742
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:1039
NTSTATUS NTAPI ObCreateObjectType(IN PUNICODE_STRING TypeName, IN POBJECT_TYPE_INITIALIZER ObjectTypeInitializer, IN PVOID Reserved, OUT POBJECT_TYPE *ObjectType)
Definition: oblife.c:1136
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:494
static ULONG Timeout
Definition: ping.c:61
PETHREAD LastThread
Definition: pinsup.c:109
VOID NTAPI KeStackAttachProcess(IN PKPROCESS Process, OUT PRKAPC_STATE ApcState)
Definition: procobj.c:704
VOID NTAPI KeUnstackDetachProcess(IN PRKAPC_STATE ApcState)
Definition: procobj.c:756
NTSTATUS NTAPI PsSuspendThread(IN PETHREAD Thread, OUT PULONG PreviousCount OPTIONAL)
Definition: state.c:48
NTSTATUS NTAPI PsTerminateProcess(IN PEPROCESS Process, IN NTSTATUS ExitStatus)
Definition: kill.c:126
PETHREAD NTAPI PsGetNextProcessThread(IN PEPROCESS Process, IN PETHREAD Thread OPTIONAL)
Definition: process.c:75
NTSTATUS NTAPI PsResumeThread(IN PETHREAD Thread, OUT PULONG PreviousCount OPTIONAL)
Definition: state.c:32
PEPROCESS NTAPI PsGetNextProcess(IN PEPROCESS OldProcess OPTIONAL)
Definition: process.c:128
#define PspSetCrossThreadFlag(Thread, Flag)
Definition: ps_x.h:25
#define PspSetProcessFlag(Process, Flag)
Definition: ps_x.h:33
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:159
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:34
#define _SEH2_YIELD(__stmt)
Definition: pseh2_64.h:162
PEPROCESS PsInitialSystemProcess
Definition: psmgr.c:50
#define ProbeForWriteHandle(Ptr)
Definition: probe.h:43
#define ProbeForWriteUlong(Ptr)
Definition: probe.h:36
#define ProbeForReadLargeInteger(Ptr)
Definition: probe.h:75
#define STATUS_SUCCESS
Definition: shellext.h:65
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
EXCEPTION_RECORD ExceptionRecord
Definition: dbgktypes.h:131
HANDLE FileHandle
Definition: dbgktypes.h:163
PVOID NamePointer
Definition: dbgktypes.h:167
ULONG DebugInfoFileOffset
Definition: dbgktypes.h:165
ULONG DebugInfoSize
Definition: dbgktypes.h:166
PORT_MESSAGE h
Definition: dbgktypes.h:208
NTSTATUS ReturnedStatus
Definition: dbgktypes.h:210
DBGKM_CREATE_THREAD CreateThread
Definition: dbgktypes.h:214
DBGKM_CREATE_PROCESS CreateProcess
Definition: dbgktypes.h:215
DBGKM_EXCEPTION Exception
Definition: dbgktypes.h:213
DBGKM_LOAD_DLL LoadDll
Definition: dbgktypes.h:218
DBGKM_APINUMBER ApiNumber
Definition: dbgktypes.h:209
FAST_MUTEX Mutex
Definition: dbgktypes.h:93
UCHAR KillProcessOnExit
Definition: dbgktypes.h:101
KEVENT EventsPresent
Definition: dbgktypes.h:92
ULONG Flags
Definition: dbgktypes.h:97
LIST_ENTRY EventList
Definition: dbgktypes.h:94
UCHAR DebuggerInactive
Definition: dbgktypes.h:100
ULONG SkipTerminationMsg
Definition: pstypes.h:1186
EX_RUNDOWN_REF RundownProtect
Definition: pstypes.h:1159
CLIENT_ID Cid
Definition: pstypes.h:1128
ULONG SkipCreationMsg
Definition: pstypes.h:1185
ULONG SystemThread
Definition: pstypes.h:1182
DWORD NumberOfSymbols
Definition: ntddk_ex.h:126
IMAGE_FILE_HEADER FileHeader
Definition: ntddk_ex.h:183
Definition: btrfs_drv.h:1876
UNICODE_STRING FullDllName
Definition: btrfs_drv.h:1882
PVOID DllBase
Definition: btrfs_drv.h:1880
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
OB_CLOSE_METHOD CloseProcedure
Definition: obtypes.h:368
GENERIC_MAPPING GenericMapping
Definition: obtypes.h:358
OB_DELETE_METHOD DeleteProcedure
Definition: obtypes.h:369
ULONG DefaultNonPagedPoolCharge
Definition: obtypes.h:365
LIST_ENTRY InLoadOrderModuleList
Definition: ldrtypes.h:120
PPEB_LDR_DATA Ldr
Definition: btrfs_drv.h:1912
#define DebugEvent(tess)
Definition: sweep.c:59
static LARGE_INTEGER StartTime
Definition: sys_arch.c:13
#define TAG_DEBUG_EVENT
Definition: tag.h:34
uint32_t * PULONG
Definition: typedefs.h:59
#define NTAPI
Definition: typedefs.h:36
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define IN
Definition: typedefs.h:39
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
LONGLONG QuadPart
Definition: typedefs.h:114
_Must_inspect_result_ _In_ WDFDEVICE _In_ ULONG _In_ ACCESS_MASK DesiredAccess
Definition: wdfdevice.h:2658
#define CreateProcess
Definition: winbase.h:3693
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
FORCEINLINE VOID ExInitializeFastMutex(_Out_ PFAST_MUTEX FastMutex)
Definition: exfuncs.h:274
FAST_MUTEX
Definition: extypes.h:17
#define IO_NO_INCREMENT
Definition: iotypes.h:598
#define PORT_MAXIMUM_MESSAGE_LENGTH
Definition: iotypes.h:2029
_Out_ PCLIENT_ID ClientId
Definition: kefuncs.h:1151
@ Suspended
Definition: ketypes.h:420
@ Executive
Definition: ketypes.h:415
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7
KAPC_STATE
Definition: ketypes.h:1409
#define ObDereferenceObject
Definition: obfuncs.h:203
#define ObReferenceObject
Definition: obfuncs.h:204
#define DUPLICATE_SAME_ACCESS
#define PsGetCurrentProcess
Definition: psfuncs.h:17
_In_ KPROCESSOR_MODE PreviousMode
Definition: sefuncs.h:103
_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:20
unsigned char UCHAR
Definition: xmlstorage.h:181