ReactOS  0.4.15-dev-3326-ga91f5e8
query.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/ps/query.c
5  * PURPOSE: Process Manager: Thread/Process Query/Set Information
6  * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
7  * Thomas Weidenmueller (w3seek@reactos.org)
8  * Eric Kohl
9  */
10 
11 /* INCLUDES ******************************************************************/
12 
13 #include <ntoskrnl.h>
14 #define NDEBUG
15 #include <debug.h>
16 
17 /* Debugging Level */
19 
20 /* PRIVATE FUNCTIONS *********************************************************/
21 
23 NTAPI
26 {
27  PSECTION Section;
28  PAGED_CODE();
29 
30  /* Lock the process */
31  if (!ExAcquireRundownProtection(&Process->RundownProtect))
32  {
34  }
35 
36  /* Get the section */
37  Section = Process->SectionObject;
38  if (Section)
39  {
40  /* Get the file object and reference it */
43  }
44 
45  /* Release the protection */
46  ExReleaseRundownProtection(&Process->RundownProtect);
47 
48  /* Return status */
49  return Section ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
50 }
51 
52 /* PUBLIC FUNCTIONS **********************************************************/
53 
54 /*
55  * @implemented
56  */
58 NTAPI
61  _In_ PROCESSINFOCLASS ProcessInformationClass,
62  _Out_ PVOID ProcessInformation,
63  _In_ ULONG ProcessInformationLength,
65 {
69  ULONG Length = 0;
70  HANDLE DebugPort = 0;
71  PPROCESS_BASIC_INFORMATION ProcessBasicInfo =
72  (PPROCESS_BASIC_INFORMATION)ProcessInformation;
73  PKERNEL_USER_TIMES ProcessTime = (PKERNEL_USER_TIMES)ProcessInformation;
74  ULONG UserTime, KernelTime;
75  PPROCESS_PRIORITY_CLASS PsPriorityClass = (PPROCESS_PRIORITY_CLASS)ProcessInformation;
76  ULONG HandleCount;
78  (PPROCESS_SESSION_INFORMATION)ProcessInformation;
79  PVM_COUNTERS VmCounters = (PVM_COUNTERS)ProcessInformation;
80  PIO_COUNTERS IoCounters = (PIO_COUNTERS)ProcessInformation;
81  PQUOTA_LIMITS QuotaLimits = (PQUOTA_LIMITS)ProcessInformation;
83  ULONG Cookie, ExecuteOptions = 0;
84  ULONG_PTR Wow64 = 0;
85  PROCESS_VALUES ProcessValues;
86  ULONG Flags;
87  PAGED_CODE();
88 
89  /* Verify Information Class validity */
90  Status = DefaultQueryInfoBufferCheck(ProcessInformationClass,
93  ProcessInformation,
94  ProcessInformationLength,
96  NULL,
98  FALSE);
99  if (!NT_SUCCESS(Status))
100  {
101  DPRINT1("NtQueryInformationProcess(): Information verification class failed! (Status -> 0x%lx, ProcessInformationClass -> %lx)\n", Status, ProcessInformationClass);
102  return Status;
103  }
104 
105  if (((ProcessInformationClass == ProcessCookie) ||
106  (ProcessInformationClass == ProcessImageInformation)) &&
108  {
109  /*
110  * Retrieving the process cookie is only allowed for the calling process
111  * itself! XP only allows NtCurrentProcess() as process handles even if
112  * a real handle actually represents the current process.
113  */
115  }
116 
117  /* Check the information class */
118  switch (ProcessInformationClass)
119  {
120  /* Basic process information */
122 
123  if (ProcessInformationLength != sizeof(PROCESS_BASIC_INFORMATION))
124  {
126  break;
127  }
128 
129  /* Set return length */
131 
132  /* Reference the process */
136  PreviousMode,
137  (PVOID*)&Process,
138  NULL);
139  if (!NT_SUCCESS(Status)) break;
140 
141  /* Protect writes with SEH */
142  _SEH2_TRY
143  {
144  /* Write all the information from the EPROCESS/KPROCESS */
145  ProcessBasicInfo->ExitStatus = Process->ExitStatus;
146  ProcessBasicInfo->PebBaseAddress = Process->Peb;
147  ProcessBasicInfo->AffinityMask = Process->Pcb.Affinity;
148  ProcessBasicInfo->UniqueProcessId = (ULONG_PTR)Process->
149  UniqueProcessId;
150  ProcessBasicInfo->InheritedFromUniqueProcessId =
151  (ULONG_PTR)Process->InheritedFromUniqueProcessId;
152  ProcessBasicInfo->BasePriority = Process->Pcb.BasePriority;
153 
154  }
156  {
157  /* Get exception code */
159  }
160  _SEH2_END;
161 
162  /* Dereference the process */
164  break;
165 
166  /* Process quota limits */
167  case ProcessQuotaLimits:
168 
169  if (ProcessInformationLength != sizeof(QUOTA_LIMITS))
170  {
172  break;
173  }
174 
175  Length = sizeof(QUOTA_LIMITS);
176 
177  /* Reference the process */
181  PreviousMode,
182  (PVOID*)&Process,
183  NULL);
184  if (!NT_SUCCESS(Status)) break;
185 
186  /* Indicate success */
188 
189  _SEH2_TRY
190  {
191  /* Set max/min working set sizes */
192  QuotaLimits->MaximumWorkingSetSize =
193  Process->Vm.MaximumWorkingSetSize << PAGE_SHIFT;
194  QuotaLimits->MinimumWorkingSetSize =
195  Process->Vm.MinimumWorkingSetSize << PAGE_SHIFT;
196 
197  /* Set default time limits */
198  QuotaLimits->TimeLimit.LowPart = MAXULONG;
199  QuotaLimits->TimeLimit.HighPart = MAXULONG;
200 
201  /* Is quota block a default one? */
202  if (Process->QuotaBlock == &PspDefaultQuotaBlock)
203  {
204  /* Set default pools and pagefile limits */
205  QuotaLimits->PagedPoolLimit = (SIZE_T)-1;
206  QuotaLimits->NonPagedPoolLimit = (SIZE_T)-1;
207  QuotaLimits->PagefileLimit = (SIZE_T)-1;
208  }
209  else
210  {
211  /* Get limits from non-default quota block */
212  QuotaLimits->PagedPoolLimit =
213  Process->QuotaBlock->QuotaEntry[PagedPool].Limit;
214  QuotaLimits->NonPagedPoolLimit =
215  Process->QuotaBlock->QuotaEntry[NonPagedPool].Limit;
216  QuotaLimits->PagefileLimit =
217  Process->QuotaBlock->QuotaEntry[2].Limit;
218  }
219  }
221  {
222  /* Get exception code */
224  }
225  _SEH2_END;
226 
227  /* Dereference the process */
229  break;
230 
231  case ProcessIoCounters:
232 
233  if (ProcessInformationLength != sizeof(IO_COUNTERS))
234  {
236  break;
237  }
238 
239  Length = sizeof(IO_COUNTERS);
240 
241  /* Reference the process */
245  PreviousMode,
246  (PVOID*)&Process,
247  NULL);
248  if (!NT_SUCCESS(Status)) break;
249 
250  /* Query IO counters from the process */
251  KeQueryValuesProcess(&Process->Pcb, &ProcessValues);
252 
253  _SEH2_TRY
254  {
255  RtlCopyMemory(IoCounters, &ProcessValues.IoInfo, sizeof(IO_COUNTERS));
256  }
258  {
259  /* Ignore exception */
260  }
261  _SEH2_END;
262 
263  /* Set status to success in any case */
265 
266  /* Dereference the process */
268  break;
269 
270  /* Timing */
271  case ProcessTimes:
272 
273  /* Set the return length */
274  if (ProcessInformationLength != sizeof(KERNEL_USER_TIMES))
275  {
277  break;
278  }
279 
280  Length = sizeof(KERNEL_USER_TIMES);
281 
282  /* Reference the process */
286  PreviousMode,
287  (PVOID*)&Process,
288  NULL);
289  if (!NT_SUCCESS(Status)) break;
290 
291  /* Protect writes with SEH */
292  _SEH2_TRY
293  {
294  /* Copy time information from EPROCESS/KPROCESS */
295  KernelTime = KeQueryRuntimeProcess(&Process->Pcb, &UserTime);
296  ProcessTime->CreateTime = Process->CreateTime;
298  ProcessTime->KernelTime.QuadPart = (LONGLONG)KernelTime * KeMaximumIncrement;
299  ProcessTime->ExitTime = Process->ExitTime;
300  }
302  {
303  /* Get exception code */
305  }
306  _SEH2_END;
307 
308  /* Dereference the process */
310  break;
311 
312  /* Process Debug Port */
313  case ProcessDebugPort:
314 
315  if (ProcessInformationLength != sizeof(HANDLE))
316  {
318  break;
319  }
320 
321  /* Set return length */
322  Length = sizeof(HANDLE);
323 
324  /* Reference the process */
328  PreviousMode,
329  (PVOID*)&Process,
330  NULL);
331  if (!NT_SUCCESS(Status)) break;
332 
333  /* Protect write with SEH */
334  _SEH2_TRY
335  {
336  /* Return whether or not we have a debug port */
337  *(PHANDLE)ProcessInformation = (Process->DebugPort ?
338  (HANDLE)-1 : NULL);
339  }
341  {
342  /* Get exception code */
344  }
345  _SEH2_END;
346 
347  /* Dereference the process */
349  break;
350 
351  case ProcessHandleCount:
352 
353  if (ProcessInformationLength != sizeof(ULONG))
354  {
356  break;
357  }
358 
359  /* Set the return length*/
360  Length = sizeof(ULONG);
361 
362  /* Reference the process */
366  PreviousMode,
367  (PVOID*)&Process,
368  NULL);
369  if (!NT_SUCCESS(Status)) break;
370 
371  /* Count the number of handles this process has */
372  HandleCount = ObGetProcessHandleCount(Process);
373 
374  /* Protect write in SEH */
375  _SEH2_TRY
376  {
377  /* Return the count of handles */
378  *(PULONG)ProcessInformation = HandleCount;
379  }
381  {
382  /* Get the exception code */
384  }
385  _SEH2_END;
386 
387  /* Dereference the process */
389  break;
390 
391  /* Session ID for the process */
393 
394  if (ProcessInformationLength != sizeof(PROCESS_SESSION_INFORMATION))
395  {
397  break;
398  }
399 
400  /* Set the return length*/
402 
403  /* Reference the process */
407  PreviousMode,
408  (PVOID*)&Process,
409  NULL);
410  if (!NT_SUCCESS(Status)) break;
411 
412  /* Enter SEH for write safety */
413  _SEH2_TRY
414  {
415  /* Write back the Session ID */
417  }
419  {
420  /* Get the exception code */
422  }
423  _SEH2_END;
424 
425  /* Dereference the process */
427  break;
428 
429  /* Virtual Memory Statistics */
430  case ProcessVmCounters:
431 
432  /* Validate the input length */
433  if ((ProcessInformationLength != sizeof(VM_COUNTERS)) &&
434  (ProcessInformationLength != sizeof(VM_COUNTERS_EX)))
435  {
437  break;
438  }
439 
440  /* Reference the process */
444  PreviousMode,
445  (PVOID*)&Process,
446  NULL);
447  if (!NT_SUCCESS(Status)) break;
448 
449  /* Enter SEH for write safety */
450  _SEH2_TRY
451  {
452  /* Return data from EPROCESS */
453  VmCounters->PeakVirtualSize = Process->PeakVirtualSize;
454  VmCounters->VirtualSize = Process->VirtualSize;
455  VmCounters->PageFaultCount = Process->Vm.PageFaultCount;
456  VmCounters->PeakWorkingSetSize = Process->Vm.PeakWorkingSetSize;
457  VmCounters->WorkingSetSize = Process->Vm.WorkingSetSize;
458  VmCounters->QuotaPeakPagedPoolUsage = Process->QuotaPeak[PsPagedPool];
459  VmCounters->QuotaPagedPoolUsage = Process->QuotaUsage[PsPagedPool];
460  VmCounters->QuotaPeakNonPagedPoolUsage = Process->QuotaPeak[PsNonPagedPool];
461  VmCounters->QuotaNonPagedPoolUsage = Process->QuotaUsage[PsNonPagedPool];
462  VmCounters->PagefileUsage = Process->QuotaUsage[PsPageFile] << PAGE_SHIFT;
463  VmCounters->PeakPagefileUsage = Process->QuotaPeak[PsPageFile] << PAGE_SHIFT;
464  //VmCounters->PrivateUsage = Process->CommitCharge << PAGE_SHIFT;
465  //
466 
467  /* Set the return length */
468  Length = ProcessInformationLength;
469  }
471  {
472  /* Get the exception code */
474  }
475  _SEH2_END;
476 
477  /* Dereference the process */
479  break;
480 
481  /* Hard Error Processing Mode */
483 
484  if (ProcessInformationLength != sizeof(ULONG))
485  {
487  break;
488  }
489 
490  /* Set the return length*/
491  Length = sizeof(ULONG);
492 
493  /* Reference the process */
497  PreviousMode,
498  (PVOID*)&Process,
499  NULL);
500  if (!NT_SUCCESS(Status)) break;
501 
502  /* Enter SEH for writing back data */
503  _SEH2_TRY
504  {
505  /* Write the current processing mode */
506  *(PULONG)ProcessInformation = Process->
507  DefaultHardErrorProcessing;
508  }
510  {
511  /* Get the exception code */
513  }
514  _SEH2_END;
515 
516  /* Dereference the process */
518  break;
519 
520  /* Priority Boosting status */
522 
523  if (ProcessInformationLength != sizeof(ULONG))
524  {
526  break;
527  }
528 
529  /* Set the return length */
530  Length = sizeof(ULONG);
531 
532  /* Reference the process */
536  PreviousMode,
537  (PVOID*)&Process,
538  NULL);
539  if (!NT_SUCCESS(Status)) break;
540 
541  /* Enter SEH for writing back data */
542  _SEH2_TRY
543  {
544  /* Return boost status */
545  *(PULONG)ProcessInformation = Process->Pcb.DisableBoost ?
546  TRUE : FALSE;
547  }
549  {
550  /* Get the exception code */
552  }
553  _SEH2_END;
554 
555  /* Dereference the process */
557  break;
558 
559  /* DOS Device Map */
560  case ProcessDeviceMap:
561 
562  if (ProcessInformationLength == sizeof(PROCESS_DEVICEMAP_INFORMATION_EX))
563  {
564  /* Protect read in SEH */
565  _SEH2_TRY
566  {
567  PPROCESS_DEVICEMAP_INFORMATION_EX DeviceMapEx = ProcessInformation;
568 
569  Flags = DeviceMapEx->Flags;
570  }
572  {
573  /* Get the exception code */
575  _SEH2_YIELD(break);
576  }
577  _SEH2_END;
578 
579  /* Only one flag is supported and it needs LUID mappings */
580  if ((Flags & ~PROCESS_LUID_DOSDEVICES_ONLY) != 0 ||
582  {
584  break;
585  }
586  }
587  else
588  {
589  /* This has to be the size of the Query union field for x64 compatibility! */
590  if (ProcessInformationLength != RTL_FIELD_SIZE(PROCESS_DEVICEMAP_INFORMATION, Query))
591  {
593  break;
594  }
595 
596  /* No flags for standard call */
597  Flags = 0;
598  }
599 
600  /* Set the return length */
601  Length = ProcessInformationLength;
602 
603  /* Reference the process */
607  PreviousMode,
608  (PVOID*)&Process,
609  NULL);
610  if (!NT_SUCCESS(Status)) break;
611 
612  /* Query the device map information */
614  ProcessInformation,
615  Flags);
616 
617  /* Dereference the process */
619  break;
620 
621  /* Priority class */
623 
624  if (ProcessInformationLength != sizeof(PROCESS_PRIORITY_CLASS))
625  {
627  break;
628  }
629 
630  /* Set the return length*/
631  Length = sizeof(PROCESS_PRIORITY_CLASS);
632 
633  /* Reference the process */
637  PreviousMode,
638  (PVOID*)&Process,
639  NULL);
640  if (!NT_SUCCESS(Status)) break;
641 
642  /* Enter SEH for writing back data */
643  _SEH2_TRY
644  {
645  /* Return current priority class */
646  PsPriorityClass->PriorityClass = Process->PriorityClass;
647  PsPriorityClass->Foreground = FALSE;
648  }
650  {
651  /* Get the exception code */
653  }
654  _SEH2_END;
655 
656  /* Dereference the process */
658  break;
659 
661 
662  /* Reference the process */
666  PreviousMode,
667  (PVOID*)&Process,
668  NULL);
669  if (!NT_SUCCESS(Status)) break;
670 
671  /* Get the image path */
673  if (NT_SUCCESS(Status))
674  {
675  /* Set return length */
676  Length = ImageName->MaximumLength +
677  sizeof(OBJECT_NAME_INFORMATION);
678 
679  /* Make sure it's large enough */
680  if (Length <= ProcessInformationLength)
681  {
682  /* Enter SEH to protect write */
683  _SEH2_TRY
684  {
685  /* Copy it */
686  RtlCopyMemory(ProcessInformation,
687  ImageName,
688  Length);
689 
690  /* Update pointer */
691  ((PUNICODE_STRING)ProcessInformation)->Buffer =
692  (PWSTR)((PUNICODE_STRING)ProcessInformation + 1);
693  }
695  {
696  /* Get the exception code */
698  }
699  _SEH2_END;
700  }
701  else
702  {
703  /* Buffer too small */
705  }
706 
707  /* Free the image path */
709  }
710  /* Dereference the process */
712  break;
713 
714  case ProcessDebugFlags:
715 
716  if (ProcessInformationLength != sizeof(ULONG))
717  {
719  break;
720  }
721 
722  /* Set the return length*/
723  Length = sizeof(ULONG);
724 
725  /* Reference the process */
729  PreviousMode,
730  (PVOID*)&Process,
731  NULL);
732  if (!NT_SUCCESS(Status)) break;
733 
734  /* Enter SEH for writing back data */
735  _SEH2_TRY
736  {
737  /* Return the debug flag state */
738  *(PULONG)ProcessInformation = Process->NoDebugInherit ? 0 : 1;
739  }
741  {
742  /* Get the exception code */
744  }
745  _SEH2_END;
746 
747  /* Dereference the process */
749  break;
750 
752 
753  if (ProcessInformationLength != sizeof(ULONG))
754  {
756  break;
757  }
758 
759  /* Set the return length */
760  Length = sizeof(ULONG);
761 
762  /* Reference the process */
766  PreviousMode,
767  (PVOID*)&Process,
768  NULL);
769  if (!NT_SUCCESS(Status)) break;
770 
771  /* Enter SEH for writing back data */
772  _SEH2_TRY
773  {
774  /* Return the BreakOnTermination state */
775  *(PULONG)ProcessInformation = Process->BreakOnTermination;
776  }
778  {
779  /* Get the exception code */
781  }
782  _SEH2_END;
783 
784  /* Dereference the process */
786  break;
787 
788  /* Per-process security cookie */
789  case ProcessCookie:
790 
791  if (ProcessInformationLength != sizeof(ULONG))
792  {
793  /* Length size wrong, bail out */
795  break;
796  }
797 
798  /* Get the current process and cookie */
800  Cookie = Process->Cookie;
801  if (!Cookie)
802  {
803  LARGE_INTEGER SystemTime;
804  ULONG NewCookie;
805  PKPRCB Prcb;
806 
807  /* Generate a new cookie */
808  KeQuerySystemTime(&SystemTime);
809  Prcb = KeGetCurrentPrcb();
810  NewCookie = Prcb->KeSystemCalls ^ Prcb->InterruptTime ^
811  SystemTime.u.LowPart ^ SystemTime.u.HighPart;
812 
813  /* Set the new cookie or return the current one */
815  NewCookie,
816  Cookie);
817  if (!Cookie) Cookie = NewCookie;
818 
819  /* Set return length */
820  Length = sizeof(ULONG);
821  }
822 
823  /* Indicate success */
825 
826  /* Enter SEH to protect write */
827  _SEH2_TRY
828  {
829  /* Write back the cookie */
830  *(PULONG)ProcessInformation = Cookie;
831  }
833  {
834  /* Get the exception code */
836  }
837  _SEH2_END;
838  break;
839 
841 
842  if (ProcessInformationLength != sizeof(SECTION_IMAGE_INFORMATION))
843  {
844  /* Break out */
846  break;
847  }
848 
849  /* Set the length required and validate it */
851 
852  /* Enter SEH to protect write */
853  _SEH2_TRY
854  {
856  }
858  {
859  /* Get the exception code */
861  }
862  _SEH2_END;
863 
864  /* Indicate success */
866  break;
867 
869 
870  if (ProcessInformationLength != sizeof(HANDLE))
871  {
873  break;
874  }
875 
876  /* Set the return length */
877  Length = sizeof(HANDLE);
878 
879  /* Reference the process */
883  PreviousMode,
884  (PVOID*)&Process,
885  NULL);
886  if (!NT_SUCCESS(Status)) break;
887 
888  /* Get the debug port */
890 
891  /* Let go of the process */
893 
894  /* Protect write in SEH */
895  _SEH2_TRY
896  {
897  /* Return debug port's handle */
898  *(PHANDLE)ProcessInformation = DebugPort;
899  }
901  {
902  /* Get the exception code */
904  }
905  _SEH2_END;
906  break;
907 
909  DPRINT1("Handle tracing Not implemented: %lx\n", ProcessInformationClass);
911  break;
912 
914 
915  if (ProcessInformationLength != sizeof(ULONG))
916  {
918  break;
919  }
920 
921  /* Set the return length */
922  Length = sizeof(ULONG);
923 
924  /* Indicate success */
926 
927  /* Protect write in SEH */
928  _SEH2_TRY
929  {
930  /* Query Ob */
931  *(PULONG)ProcessInformation = ObIsLUIDDeviceMapsEnabled();
932  }
934  {
935  /* Get the exception code */
937  }
938  _SEH2_END;
939  break;
940 
942 
943  if (ProcessInformationLength != sizeof(ULONG))
944  {
946  break;
947  }
948 
949  /* Set the return length */
950  Length = sizeof(ULONG);
951 
952  /* Reference the process */
956  PreviousMode,
957  (PVOID*)&Process,
958  NULL);
959  if (!NT_SUCCESS(Status)) break;
960 
961  /* Protect write in SEH */
962  _SEH2_TRY
963  {
964  /* Return if the flag is set */
965  *(PULONG)ProcessInformation = (ULONG)Process->VdmAllowed;
966  }
968  {
969  /* Get the exception code */
971  }
972  _SEH2_END;
973 
974  /* Dereference the process */
976  break;
977 
979 
980  if (ProcessInformationLength != sizeof(ULONG_PTR))
981  {
983  break;
984  }
985 
986  /* Set return length */
987  Length = sizeof(ULONG_PTR);
988 
989  /* Reference the process */
993  PreviousMode,
994  (PVOID*)&Process,
995  NULL);
996  if (!NT_SUCCESS(Status)) break;
997 
998  /* Make sure the process isn't dying */
999  if (ExAcquireRundownProtection(&Process->RundownProtect))
1000  {
1001  /* Get the WOW64 process structure */
1002 #ifdef _WIN64
1003  Wow64 = (ULONG_PTR)Process->Wow64Process;
1004 #else
1005  Wow64 = 0;
1006 #endif
1007  /* Release the lock */
1008  ExReleaseRundownProtection(&Process->RundownProtect);
1009  }
1010 
1011  /* Protect write with SEH */
1012  _SEH2_TRY
1013  {
1014  /* Return whether or not we have a debug port */
1015  *(PULONG_PTR)ProcessInformation = Wow64;
1016  }
1018  {
1019  /* Get exception code */
1021  }
1022  _SEH2_END;
1023 
1024  /* Dereference the process */
1026  break;
1027 
1028  case ProcessExecuteFlags:
1029 
1030  if (ProcessInformationLength != sizeof(ULONG))
1031  {
1033  break;
1034  }
1035 
1036  /* Set return length */
1037  Length = sizeof(ULONG);
1038 
1040  {
1041  return STATUS_INVALID_PARAMETER;
1042  }
1043 
1044  /* Get the options */
1045  Status = MmGetExecuteOptions(&ExecuteOptions);
1046  if (NT_SUCCESS(Status))
1047  {
1048  /* Protect write with SEH */
1049  _SEH2_TRY
1050  {
1051  /* Return them */
1052  *(PULONG)ProcessInformation = ExecuteOptions;
1053  }
1055  {
1056  /* Get exception code */
1058  }
1059  _SEH2_END;
1060  }
1061  break;
1062 
1063  case ProcessLdtInformation:
1064  DPRINT1("VDM/16-bit not implemented: %lx\n", ProcessInformationClass);
1066  break;
1067 
1069  DPRINT1("WS Watch Not implemented: %lx\n", ProcessInformationClass);
1071  break;
1072 
1074  DPRINT1("Pool limits Not implemented: %lx\n", ProcessInformationClass);
1076  break;
1077 
1078  /* Not supported by Server 2003 */
1079  default:
1080  DPRINT1("Unsupported info class: %lx\n", ProcessInformationClass);
1082  }
1083 
1084  /* Protect write with SEH */
1085  _SEH2_TRY
1086  {
1087  /* Check if caller wanted return length */
1088  if ((ReturnLength) && (Length)) *ReturnLength = Length;
1089  }
1091  {
1092  /* Get exception code */
1094  }
1095  _SEH2_END;
1096 
1097  return Status;
1098 }
1099 
1100 /*
1101  * @implemented
1102  */
1103 NTSTATUS
1104 NTAPI
1106  IN PROCESSINFOCLASS ProcessInformationClass,
1107  IN PVOID ProcessInformation,
1108  IN ULONG ProcessInformationLength)
1109 {
1112  ACCESS_MASK Access;
1113  NTSTATUS Status;
1114  HANDLE PortHandle = NULL;
1118  PROCESS_PRIORITY_CLASS PriorityClass = {0};
1119  PROCESS_FOREGROUND_BACKGROUND Foreground = {0};
1120  PVOID ExceptionPort;
1121  ULONG Break;
1122  KAFFINITY ValidAffinity, Affinity = 0;
1123  KPRIORITY BasePriority = 0;
1124  UCHAR MemoryPriority = 0;
1125  BOOLEAN DisableBoost = 0;
1126  ULONG DefaultHardErrorMode = 0;
1127  ULONG DebugFlags = 0, EnableFixup = 0, Boost = 0;
1128  ULONG NoExecute = 0, VdmPower = 0;
1130  PLIST_ENTRY Next;
1131  PETHREAD Thread;
1132  PAGED_CODE();
1133 
1134  /* Verify Information Class validity */
1135  Status = DefaultSetInfoBufferCheck(ProcessInformationClass,
1138  ProcessInformation,
1139  ProcessInformationLength,
1140  PreviousMode);
1141  if (!NT_SUCCESS(Status))
1142  {
1143  DPRINT1("NtSetInformationProcess(): Information verification class failed! (Status -> 0x%lx, ProcessInformationClass -> %lx)\n", Status, ProcessInformationClass);
1144  return Status;
1145  }
1146 
1147  /* Check what class this is */
1148  Access = PROCESS_SET_INFORMATION;
1149  if (ProcessInformationClass == ProcessSessionInformation)
1150  {
1151  /* Setting the Session ID needs a special mask */
1152  Access |= PROCESS_SET_SESSIONID;
1153  }
1154  else if (ProcessInformationClass == ProcessExceptionPort)
1155  {
1156  /* Setting the exception port needs a special mask */
1157  Access |= PROCESS_SUSPEND_RESUME;
1158  }
1159 
1160  /* Reference the process */
1162  Access,
1163  PsProcessType,
1164  PreviousMode,
1165  (PVOID*)&Process,
1166  NULL);
1167  if (!NT_SUCCESS(Status)) return Status;
1168 
1169  /* Check what kind of information class this is */
1170  switch (ProcessInformationClass)
1171  {
1173 
1174  /* Check buffer length */
1175  if (ProcessInformationLength != sizeof(ULONG))
1176  {
1178  break;
1179  }
1180 
1181  /* Use SEH for capture */
1182  _SEH2_TRY
1183  {
1184  /* Capture the boolean */
1185  VdmPower = *(PULONG)ProcessInformation;
1186  }
1188  {
1189  /* Get the exception code */
1191  _SEH2_YIELD(break);
1192  }
1193  _SEH2_END;
1194 
1195  /* Getting VDM powers requires the SeTcbPrivilege */
1197  {
1198  /* We don't hold the privilege, bail out */
1200  DPRINT1("Need TCB privilege\n");
1201  break;
1202  }
1203 
1204  /* Set or clear the flag */
1205  if (VdmPower)
1206  {
1208  }
1209  else
1210  {
1212  }
1213  break;
1214 
1215  /* Error/Exception Port */
1216  case ProcessExceptionPort:
1217 
1218  /* Check buffer length */
1219  if (ProcessInformationLength != sizeof(HANDLE))
1220  {
1222  break;
1223  }
1224 
1225  /* Use SEH for capture */
1226  _SEH2_TRY
1227  {
1228  /* Capture the handle */
1229  PortHandle = *(PHANDLE)ProcessInformation;
1230  }
1232  {
1233  /* Get the exception code */
1235  _SEH2_YIELD(break);
1236  }
1237  _SEH2_END;
1238 
1239  /* Setting the error port requires the SeTcbPrivilege */
1241  {
1242  /* We don't hold the privilege, bail out */
1244  break;
1245  }
1246 
1247  /* Get the LPC Port */
1248  Status = ObReferenceObjectByHandle(PortHandle,
1249  0,
1251  PreviousMode,
1252  (PVOID)&ExceptionPort,
1253  NULL);
1254  if (!NT_SUCCESS(Status)) break;
1255 
1256  /* Change the pointer */
1257  if (InterlockedCompareExchangePointer(&Process->ExceptionPort,
1258  ExceptionPort,
1259  NULL))
1260  {
1261  /* We already had one, fail */
1262  ObDereferenceObject(ExceptionPort);
1264  }
1265  break;
1266 
1267  /* Security Token */
1268  case ProcessAccessToken:
1269 
1270  /* Check buffer length */
1271  if (ProcessInformationLength != sizeof(PROCESS_ACCESS_TOKEN))
1272  {
1274  break;
1275  }
1276 
1277  /* Use SEH for capture */
1278  _SEH2_TRY
1279  {
1280  /* Save the token handle */
1281  TokenHandle = ((PPROCESS_ACCESS_TOKEN)ProcessInformation)->
1282  Token;
1283  }
1285  {
1286  /* Get the exception code */
1288  _SEH2_YIELD(break);
1289  }
1290  _SEH2_END;
1291 
1292  /* Assign the actual token */
1294  break;
1295 
1296  /* Hard error processing */
1298 
1299  /* Check buffer length */
1300  if (ProcessInformationLength != sizeof(ULONG))
1301  {
1303  break;
1304  }
1305 
1306  /* Enter SEH for direct buffer read */
1307  _SEH2_TRY
1308  {
1309  DefaultHardErrorMode = *(PULONG)ProcessInformation;
1310  }
1312  {
1313  /* Get exception code */
1315  _SEH2_YIELD(break);
1316  }
1317  _SEH2_END;
1318 
1319  /* Set the mode */
1320  Process->DefaultHardErrorProcessing = DefaultHardErrorMode;
1321 
1322  /* Call Ke for the update */
1323  if (DefaultHardErrorMode & SEM_NOALIGNMENTFAULTEXCEPT)
1324  {
1326  }
1327  else
1328  {
1330  }
1332  break;
1333 
1334  /* Session ID */
1336 
1337  /* Check buffer length */
1338  if (ProcessInformationLength != sizeof(PROCESS_SESSION_INFORMATION))
1339  {
1341  break;
1342  }
1343 
1344  /* Enter SEH for capture */
1345  _SEH2_TRY
1346  {
1347  /* Capture the caller's buffer */
1348  SessionInfo = *(PPROCESS_SESSION_INFORMATION)ProcessInformation;
1349  }
1351  {
1352  /* Get the exception code */
1354  _SEH2_YIELD(break);
1355  }
1356  _SEH2_END;
1357 
1358  /* Setting the session id requires the SeTcbPrivilege */
1360  {
1361  /* We don't hold the privilege, bail out */
1363  break;
1364  }
1365 
1366 #if 0 // OLD AND DEPRECATED CODE!!!!
1367 
1368  /* FIXME - update the session id for the process token */
1369  //Status = PsLockProcess(Process, FALSE);
1370  if (!NT_SUCCESS(Status)) break;
1371 
1372  /* Write the session ID in the EPROCESS */
1373  Process->Session = UlongToPtr(SessionInfo.SessionId); // HACK!!!
1374 
1375  /* Check if the process also has a PEB */
1376  if (Process->Peb)
1377  {
1378  /*
1379  * Attach to the process to make sure we're in the right
1380  * context to access the PEB structure
1381  */
1382  KeAttachProcess(&Process->Pcb);
1383 
1384  /* Enter SEH for write to user-mode PEB */
1385  _SEH2_TRY
1386  {
1387  /* Write the session ID */
1388  Process->Peb->SessionId = SessionInfo.SessionId;
1389  }
1391  {
1392  /* Get exception code */
1394  }
1395  _SEH2_END;
1396 
1397  /* Detach from the process */
1398  KeDetachProcess();
1399  }
1400 
1401  /* Unlock the process */
1402  //PsUnlockProcess(Process);
1403 
1404 #endif
1405 
1406  /*
1407  * Since we cannot change the session ID of the given
1408  * process anymore because it is set once and for all
1409  * at process creation time and because it is stored
1410  * inside the Process->Session structure managed by MM,
1411  * we fake changing it: we just return success if the
1412  * user-defined value is the same as the session ID of
1413  * the process, and otherwise we fail.
1414  */
1415  if (SessionInfo.SessionId == PsGetProcessSessionId(Process))
1416  {
1418  }
1419  else
1420  {
1422  }
1423 
1424  break;
1425 
1426  case ProcessPriorityClass:
1427 
1428  /* Check buffer length */
1429  if (ProcessInformationLength != sizeof(PROCESS_PRIORITY_CLASS))
1430  {
1432  break;
1433  }
1434 
1435  /* Enter SEH for capture */
1436  _SEH2_TRY
1437  {
1438  /* Capture the caller's buffer */
1439  PriorityClass = *(PPROCESS_PRIORITY_CLASS)ProcessInformation;
1440  }
1442  {
1443  /* Return the exception code */
1445  _SEH2_YIELD(break);
1446  }
1447  _SEH2_END;
1448 
1449  /* Check for invalid PriorityClass value */
1451  {
1453  break;
1454  }
1455 
1456  if ((PriorityClass.PriorityClass != Process->PriorityClass) &&
1458  {
1459  /* Check the privilege */
1461  ProcessHandle,
1463  PreviousMode);
1464  if (!HasPrivilege)
1465  {
1467  DPRINT1("Privilege to change priority to realtime lacking\n");
1469  }
1470  }
1471 
1472  /* Check if we have a job */
1473  if (Process->Job)
1474  {
1475  DPRINT1("Jobs not yet supported\n");
1476  }
1477 
1478  /* Set process priority class */
1479  Process->PriorityClass = PriorityClass.PriorityClass;
1480 
1481  /* Set process priority mode (foreground or background) */
1483  PriorityClass.Foreground ?
1487  break;
1488 
1490 
1491  /* Check buffer length */
1492  if (ProcessInformationLength != sizeof(PROCESS_FOREGROUND_BACKGROUND))
1493  {
1495  break;
1496  }
1497 
1498  /* Enter SEH for capture */
1499  _SEH2_TRY
1500  {
1501  /* Capture the caller's buffer */
1502  Foreground = *(PPROCESS_FOREGROUND_BACKGROUND)ProcessInformation;
1503  }
1505  {
1506  /* Return the exception code */
1508  _SEH2_YIELD(break);
1509  }
1510  _SEH2_END;
1511 
1512  /* Set process priority mode (foreground or background) */
1514  Foreground.Foreground ?
1518  break;
1519 
1520  case ProcessBasePriority:
1521 
1522  /* Validate input length */
1523  if (ProcessInformationLength != sizeof(KPRIORITY))
1524  {
1526  break;
1527  }
1528 
1529  /* Enter SEH for direct buffer read */
1530  _SEH2_TRY
1531  {
1532  BasePriority = *(KPRIORITY*)ProcessInformation;
1533  }
1535  {
1536  /* Get exception code */
1537  Break = 0;
1539  _SEH2_YIELD(break);
1540  }
1541  _SEH2_END;
1542 
1543  /* Extract the memory priority out of there */
1544  if (BasePriority & 0x80000000)
1545  {
1546  MemoryPriority = MEMORY_PRIORITY_FOREGROUND;
1547  BasePriority &= ~0x80000000;
1548  }
1549  else
1550  {
1551  MemoryPriority = MEMORY_PRIORITY_BACKGROUND;
1552  }
1553 
1554  /* Validate the number */
1555  if ((BasePriority > HIGH_PRIORITY) || (BasePriority <= LOW_PRIORITY))
1556  {
1558  return STATUS_INVALID_PARAMETER;
1559  }
1560 
1561  /* Check if the new base is higher */
1562  if (BasePriority > Process->Pcb.BasePriority)
1563  {
1565  ProcessHandle,
1567  PreviousMode);
1568  if (!HasPrivilege)
1569  {
1571  DPRINT1("Privilege to change priority from %lx to %lx lacking\n", BasePriority, Process->Pcb.BasePriority);
1573  }
1574  }
1575 
1576  /* Call Ke */
1577  KeSetPriorityAndQuantumProcess(&Process->Pcb, BasePriority, 0);
1578 
1579  /* Now set the memory priority */
1580  MmSetMemoryPriorityProcess(Process, MemoryPriority);
1582  break;
1583 
1584  case ProcessRaisePriority:
1585 
1586  /* Validate input length */
1587  if (ProcessInformationLength != sizeof(ULONG))
1588  {
1590  break;
1591  }
1592 
1593  /* Enter SEH for direct buffer read */
1594  _SEH2_TRY
1595  {
1596  Boost = *(PULONG)ProcessInformation;
1597  }
1599  {
1600  /* Get exception code */
1601  Break = 0;
1603  _SEH2_YIELD(break);
1604  }
1605  _SEH2_END;
1606 
1607  /* Make sure the process isn't dying */
1608  if (ExAcquireRundownProtection(&Process->RundownProtect))
1609  {
1610  /* Lock it */
1612  ExAcquirePushLockShared(&Process->ProcessLock);
1613 
1614  /* Loop the threads */
1615  for (Next = Process->ThreadListHead.Flink;
1616  Next != &Process->ThreadListHead;
1617  Next = Next->Flink)
1618  {
1619  /* Call Ke for the thread */
1620  Thread = CONTAINING_RECORD(Next, ETHREAD, ThreadListEntry);
1621  KeBoostPriorityThread(&Thread->Tcb, Boost);
1622  }
1623 
1624  /* Release the lock and rundown */
1625  ExReleasePushLockShared(&Process->ProcessLock);
1627  ExReleaseRundownProtection(&Process->RundownProtect);
1628 
1629  /* Set success code */
1631  }
1632  else
1633  {
1634  /* Avoid race conditions */
1636  }
1637  break;
1638 
1640 
1641  /* Check buffer length */
1642  if (ProcessInformationLength != sizeof(ULONG))
1643  {
1645  break;
1646  }
1647 
1648  /* Enter SEH for direct buffer read */
1649  _SEH2_TRY
1650  {
1651  Break = *(PULONG)ProcessInformation;
1652  }
1654  {
1655  /* Get exception code */
1656  Break = 0;
1658  _SEH2_YIELD(break);
1659  }
1660  _SEH2_END;
1661 
1662  /* Setting 'break on termination' requires the SeDebugPrivilege */
1664  {
1665  /* We don't hold the privilege, bail out */
1667  break;
1668  }
1669 
1670  /* Set or clear the flag */
1671  if (Break)
1672  {
1674  }
1675  else
1676  {
1678  }
1679 
1680  break;
1681 
1682  case ProcessAffinityMask:
1683 
1684  /* Check buffer length */
1685  if (ProcessInformationLength != sizeof(KAFFINITY))
1686  {
1688  break;
1689  }
1690 
1691  /* Enter SEH for direct buffer read */
1692  _SEH2_TRY
1693  {
1694  Affinity = *(PKAFFINITY)ProcessInformation;
1695  }
1697  {
1698  /* Get exception code */
1699  Break = 0;
1701  _SEH2_YIELD(break);
1702  }
1703  _SEH2_END;
1704 
1705  /* Make sure it's valid for the CPUs present */
1706  ValidAffinity = Affinity & KeActiveProcessors;
1707  if (!Affinity || (ValidAffinity != Affinity))
1708  {
1710  break;
1711  }
1712 
1713  /* Check if it's within job affinity limits */
1714  if (Process->Job)
1715  {
1716  /* Not yet implemented */
1717  UNIMPLEMENTED;
1719  break;
1720  }
1721 
1722  /* Make sure the process isn't dying */
1723  if (ExAcquireRundownProtection(&Process->RundownProtect))
1724  {
1725  /* Lock it */
1727  ExAcquirePushLockShared(&Process->ProcessLock);
1728 
1729  /* Call Ke to do the work */
1730  KeSetAffinityProcess(&Process->Pcb, ValidAffinity);
1731 
1732  /* Release the lock and rundown */
1733  ExReleasePushLockShared(&Process->ProcessLock);
1735  ExReleaseRundownProtection(&Process->RundownProtect);
1736 
1737  /* Set success code */
1739  }
1740  else
1741  {
1742  /* Avoid race conditions */
1744  }
1745  break;
1746 
1747  /* Priority Boosting status */
1748  case ProcessPriorityBoost:
1749 
1750  /* Validate input length */
1751  if (ProcessInformationLength != sizeof(ULONG))
1752  {
1754  break;
1755  }
1756 
1757  /* Enter SEH for direct buffer read */
1758  _SEH2_TRY
1759  {
1760  DisableBoost = *(PBOOLEAN)ProcessInformation;
1761  }
1763  {
1764  /* Get exception code */
1765  Break = 0;
1767  _SEH2_YIELD(break);
1768  }
1769  _SEH2_END;
1770 
1771  /* Make sure the process isn't dying */
1772  if (ExAcquireRundownProtection(&Process->RundownProtect))
1773  {
1774  /* Lock it */
1776  ExAcquirePushLockShared(&Process->ProcessLock);
1777 
1778  /* Call Ke to do the work */
1779  KeSetDisableBoostProcess(&Process->Pcb, DisableBoost);
1780 
1781  /* Loop the threads too */
1782  for (Next = Process->ThreadListHead.Flink;
1783  Next != &Process->ThreadListHead;
1784  Next = Next->Flink)
1785  {
1786  /* Call Ke for the thread */
1787  Thread = CONTAINING_RECORD(Next, ETHREAD, ThreadListEntry);
1788  KeSetDisableBoostThread(&Thread->Tcb, DisableBoost);
1789  }
1790 
1791  /* Release the lock and rundown */
1792  ExReleasePushLockShared(&Process->ProcessLock);
1794  ExReleaseRundownProtection(&Process->RundownProtect);
1795 
1796  /* Set success code */
1798  }
1799  else
1800  {
1801  /* Avoid race conditions */
1803  }
1804  break;
1805 
1806  case ProcessDebugFlags:
1807 
1808  /* Check buffer length */
1809  if (ProcessInformationLength != sizeof(ULONG))
1810  {
1812  break;
1813  }
1814 
1815  /* Enter SEH for direct buffer read */
1816  _SEH2_TRY
1817  {
1818  DebugFlags = *(PULONG)ProcessInformation;
1819  }
1821  {
1822  /* Get exception code */
1824  _SEH2_YIELD(break);
1825  }
1826  _SEH2_END;
1827 
1828  /* Set the mode */
1829  if (DebugFlags & ~1)
1830  {
1832  }
1833  else
1834  {
1835  if (DebugFlags & 1)
1836  {
1838  }
1839  else
1840  {
1842  }
1843  }
1844 
1845  /* Done */
1847  break;
1848 
1850 
1851  /* Check buffer length */
1852  if (ProcessInformationLength != sizeof(BOOLEAN))
1853  {
1855  break;
1856  }
1857 
1858  /* Enter SEH for direct buffer read */
1859  _SEH2_TRY
1860  {
1861  EnableFixup = *(PULONG)ProcessInformation;
1862  }
1864  {
1865  /* Get exception code */
1867  _SEH2_YIELD(break);
1868  }
1869  _SEH2_END;
1870 
1871  /* Set the mode */
1872  if (EnableFixup)
1873  {
1874  Process->DefaultHardErrorProcessing |= SEM_NOALIGNMENTFAULTEXCEPT;
1875  }
1876  else
1877  {
1878  Process->DefaultHardErrorProcessing &= ~SEM_NOALIGNMENTFAULTEXCEPT;
1879  }
1880 
1881  /* Call Ke for the update */
1884  break;
1885 
1886  case ProcessUserModeIOPL:
1887 
1888  /* Only TCB can do this */
1890  {
1891  /* We don't hold the privilege, bail out */
1892  DPRINT1("Need TCB to set IOPL\n");
1894  break;
1895  }
1896 
1897  /* Only supported on x86 */
1898 #if defined (_X86_)
1899  Ke386SetIOPL();
1900 #elif defined(_M_AMD64)
1901  /* On x64 this function isn't implemented.
1902  On Windows 2003 it returns success.
1903  On Vista+ it returns STATUS_NOT_IMPLEMENTED. */
1904  if ((ExGetPreviousMode() != KernelMode) &&
1905  (RtlRosGetAppcompatVersion() > _WIN32_WINNT_WS03))
1906  {
1908  }
1909 #else
1911 #endif
1912  /* Done */
1913  break;
1914 
1915  case ProcessExecuteFlags:
1916 
1917  /* Check buffer length */
1918  if (ProcessInformationLength != sizeof(ULONG))
1919  {
1921  break;
1922  }
1923 
1925  {
1927  break;
1928  }
1929 
1930  /* Enter SEH for direct buffer read */
1931  _SEH2_TRY
1932  {
1933  NoExecute = *(PULONG)ProcessInformation;
1934  }
1936  {
1937  /* Get exception code */
1939  _SEH2_YIELD(break);
1940  }
1941  _SEH2_END;
1942 
1943  /* Call Mm for the update */
1944  Status = MmSetExecuteOptions(NoExecute);
1945  break;
1946 
1947  case ProcessDeviceMap:
1948 
1949  /* Check buffer length */
1950  if (ProcessInformationLength != sizeof(HANDLE))
1951  {
1953  break;
1954  }
1955 
1956  /* Use SEH for capture */
1957  _SEH2_TRY
1958  {
1959  /* Capture the handle */
1960  DirectoryHandle = *(PHANDLE)ProcessInformation;
1961  }
1963  {
1964  /* Get the exception code */
1966  _SEH2_YIELD(break);
1967  }
1968  _SEH2_END;
1969 
1970  /* Call Ob to set the device map */
1972  break;
1973 
1974 
1975  /* We currently don't implement any of these */
1976  case ProcessLdtInformation:
1977  case ProcessLdtSize:
1978  case ProcessIoPortHandlers:
1979  DPRINT1("VDM/16-bit Request not implemented: %lx\n", ProcessInformationClass);
1981  break;
1982 
1983  case ProcessQuotaLimits:
1984 
1986  1,
1987  ProcessInformation,
1988  ProcessInformationLength,
1989  PreviousMode);
1990  break;
1991 
1993  DPRINT1("WS watch not implemented\n");
1995  break;
1996 
1997  case ProcessHandleTracing:
1998  DPRINT1("Handle tracing not implemented\n");
2000  break;
2001 
2002  /* Anything else is invalid */
2003  default:
2004  DPRINT1("Invalid Server 2003 Info Class: %lx\n", ProcessInformationClass);
2006  }
2007 
2008  /* Dereference and return status */
2010  return Status;
2011 }
2012 
2013 /*
2014  * @implemented
2015  */
2016 NTSTATUS
2017 NTAPI
2020  IN PVOID ThreadInformation,
2022 {
2023  PETHREAD Thread;
2025  NTSTATUS Status;
2027  KPRIORITY Priority = 0;
2028  KAFFINITY Affinity = 0, CombinedAffinity;
2029  PVOID Address = NULL;
2031  ULONG_PTR DisableBoost = 0;
2032  ULONG_PTR IdealProcessor = 0;
2033  ULONG_PTR Break = 0;
2034  PTEB Teb;
2035  ULONG_PTR TlsIndex = 0;
2036  PVOID *ExpansionSlots;
2037  PETHREAD ProcThread;
2039  PAGED_CODE();
2040 
2041  /* Verify Information Class validity */
2045  ThreadInformation,
2047  PreviousMode);
2048  if (!NT_SUCCESS(Status))
2049  {
2050  DPRINT1("NtSetInformationThread(): Information verification class failed! (Status -> 0x%lx, ThreadInformationClass -> %lx)\n", Status, ThreadInformationClass);
2051  return Status;
2052  }
2053 
2054  /* Check what kind of information class this is */
2055  switch (ThreadInformationClass)
2056  {
2057  /* Thread priority */
2058  case ThreadPriority:
2059 
2060  /* Check buffer length */
2061  if (ThreadInformationLength != sizeof(KPRIORITY))
2062  {
2064  break;
2065  }
2066 
2067  /* Use SEH for capture */
2068  _SEH2_TRY
2069  {
2070  /* Get the priority */
2071  Priority = *(PLONG)ThreadInformation;
2072  }
2074  {
2075  /* Get the exception code */
2077  _SEH2_YIELD(break);
2078  }
2079  _SEH2_END;
2080 
2081  /* Validate it */
2082  if ((Priority > HIGH_PRIORITY) ||
2083  (Priority <= LOW_PRIORITY))
2084  {
2085  /* Fail */
2087  break;
2088  }
2089 
2090  /* Check for the required privilege */
2092  {
2094  ThreadHandle,
2096  PreviousMode);
2097  if (!HasPrivilege)
2098  {
2099  DPRINT1("Privilege to change priority to %lx lacking\n", Priority);
2101  }
2102  }
2103 
2104  /* Reference the thread */
2105  Status = ObReferenceObjectByHandle(ThreadHandle,
2107  PsThreadType,
2108  PreviousMode,
2109  (PVOID*)&Thread,
2110  NULL);
2111  if (!NT_SUCCESS(Status))
2112  break;
2113 
2114  /* Set the priority */
2116 
2117  /* Dereference the thread */
2119  break;
2120 
2121  case ThreadBasePriority:
2122 
2123  /* Check buffer length */
2124  if (ThreadInformationLength != sizeof(LONG))
2125  {
2127  break;
2128  }
2129 
2130  /* Use SEH for capture */
2131  _SEH2_TRY
2132  {
2133  /* Get the priority */
2134  Priority = *(PLONG)ThreadInformation;
2135  }
2137  {
2138  /* Get the exception code */
2140  _SEH2_YIELD(break);
2141  }
2142  _SEH2_END;
2143 
2144  /* Validate it */
2147  {
2148  /* These ones are OK */
2149  if ((Priority != THREAD_BASE_PRIORITY_LOWRT + 1) &&
2151  {
2152  /* Check if the process is real time */
2153  if (PsGetCurrentProcess()->PriorityClass !=
2155  {
2156  /* It isn't, fail */
2158  break;
2159  }
2160  }
2161  }
2162 
2163  /* Reference the thread */
2164  Status = ObReferenceObjectByHandle(ThreadHandle,
2166  PsThreadType,
2167  PreviousMode,
2168  (PVOID*)&Thread,
2169  NULL);
2170  if (!NT_SUCCESS(Status))
2171  break;
2172 
2173  /* Set the base priority */
2175 
2176  /* Dereference the thread */
2178  break;
2179 
2180  case ThreadAffinityMask:
2181 
2182  /* Check buffer length */
2183  if (ThreadInformationLength != sizeof(ULONG_PTR))
2184  {
2186  break;
2187  }
2188 
2189  /* Use SEH for capture */
2190  _SEH2_TRY
2191  {
2192  /* Get the priority */
2193  Affinity = *(PULONG_PTR)ThreadInformation;
2194  }
2196  {
2197  /* Get the exception code */
2199  _SEH2_YIELD(break);
2200  }
2201  _SEH2_END;
2202 
2203  /* Validate it */
2204  if (!Affinity)
2205  {
2206  /* Fail */
2208  break;
2209  }
2210 
2211  /* Reference the thread */
2212  Status = ObReferenceObjectByHandle(ThreadHandle,
2214  PsThreadType,
2215  PreviousMode,
2216  (PVOID*)&Thread,
2217  NULL);
2218  if (!NT_SUCCESS(Status))
2219  break;
2220 
2221  /* Get the process */
2222  Process = Thread->ThreadsProcess;
2223 
2224  /* Try to acquire rundown */
2225  if (ExAcquireRundownProtection(&Process->RundownProtect))
2226  {
2227  /* Lock it */
2229  ExAcquirePushLockShared(&Process->ProcessLock);
2230 
2231  /* Combine masks */
2232  CombinedAffinity = Affinity & Process->Pcb.Affinity;
2233  if (CombinedAffinity != Affinity)
2234  {
2235  /* Fail */
2237  }
2238  else
2239  {
2240  /* Set the affinity */
2241  KeSetAffinityThread(&Thread->Tcb, CombinedAffinity);
2242  }
2243 
2244  /* Release the lock and rundown */
2245  ExReleasePushLockShared(&Process->ProcessLock);
2247  ExReleaseRundownProtection(&Process->RundownProtect);
2248  }
2249  else
2250  {
2251  /* Too late */
2253  }
2254 
2255  /* Dereference the thread */
2257  break;
2258 
2260 
2261  /* Check buffer length */
2262  if (ThreadInformationLength != sizeof(HANDLE))
2263  {
2265  break;
2266  }
2267 
2268  /* Use SEH for capture */
2269  _SEH2_TRY
2270  {
2271  /* Save the token handle */
2272  TokenHandle = *(PHANDLE)ThreadInformation;
2273  }
2275  {
2276  /* Get the exception code */
2278  _SEH2_YIELD(break);
2279  }
2280  _SEH2_END;
2281 
2282  /* Reference the thread */
2283  Status = ObReferenceObjectByHandle(ThreadHandle,
2285  PsThreadType,
2286  PreviousMode,
2287  (PVOID*)&Thread,
2288  NULL);
2289  if (!NT_SUCCESS(Status))
2290  break;
2291 
2292  /* Assign the actual token */
2294 
2295  /* Dereference the thread */
2297  break;
2298 
2300 
2301  /* Check buffer length */
2302  if (ThreadInformationLength != sizeof(ULONG_PTR))
2303  {
2305  break;
2306  }
2307 
2308  /* Use SEH for capture */
2309  _SEH2_TRY
2310  {
2311  /* Get the priority */
2312  Address = *(PVOID*)ThreadInformation;
2313  }
2315  {
2316  /* Get the exception code */
2318  _SEH2_YIELD(break);
2319  }
2320  _SEH2_END;
2321 
2322  /* Reference the thread */
2323  Status = ObReferenceObjectByHandle(ThreadHandle,
2325  PsThreadType,
2326  PreviousMode,
2327  (PVOID*)&Thread,
2328  NULL);
2329  if (!NT_SUCCESS(Status))
2330  break;
2331 
2332  /* Set the address */
2334 
2335  /* Dereference the thread */
2337  break;
2338 
2339  case ThreadIdealProcessor:
2340 
2341  /* Check buffer length */
2342  if (ThreadInformationLength != sizeof(ULONG_PTR))
2343  {
2345  break;
2346  }
2347 
2348  /* Use SEH for capture */
2349  _SEH2_TRY
2350  {
2351  /* Get the priority */
2352  IdealProcessor = *(PULONG_PTR)ThreadInformation;
2353  }
2355  {
2356  /* Get the exception code */
2358  _SEH2_YIELD(break);
2359  }
2360  _SEH2_END;
2361 
2362  /* Validate it */
2363  if (IdealProcessor > MAXIMUM_PROCESSORS)
2364  {
2365  /* Fail */
2367  break;
2368  }
2369 
2370  /* Reference the thread */
2371  Status = ObReferenceObjectByHandle(ThreadHandle,
2373  PsThreadType,
2374  PreviousMode,
2375  (PVOID*)&Thread,
2376  NULL);
2377  if (!NT_SUCCESS(Status))
2378  break;
2379 
2380  /* Set the ideal */
2382  (CCHAR)IdealProcessor);
2383 
2384  /* Get the TEB and protect the thread */
2385  Teb = Thread->Tcb.Teb;
2387  {
2388  /* Save the ideal processor */
2389  Teb->IdealProcessor = Thread->Tcb.IdealProcessor;
2390 
2391  /* Release rundown protection */
2393  }
2394 
2395  /* Dereference the thread */
2397  break;
2398 
2399  case ThreadPriorityBoost:
2400 
2401  /* Check buffer length */
2402  if (ThreadInformationLength != sizeof(ULONG_PTR))
2403  {
2405  break;
2406  }
2407 
2408  /* Use SEH for capture */
2409  _SEH2_TRY
2410  {
2411  /* Get the priority */
2412  DisableBoost = *(PULONG_PTR)ThreadInformation;
2413  }
2415  {
2416  /* Get the exception code */
2418  _SEH2_YIELD(break);
2419  }
2420  _SEH2_END;
2421 
2422  /* Reference the thread */
2423  Status = ObReferenceObjectByHandle(ThreadHandle,
2425  PsThreadType,
2426  PreviousMode,
2427  (PVOID*)&Thread,
2428  NULL);
2429  if (!NT_SUCCESS(Status))
2430  break;
2431 
2432  /* Call the kernel */
2433  KeSetDisableBoostThread(&Thread->Tcb, (BOOLEAN)DisableBoost);
2434 
2435  /* Dereference the thread */
2437  break;
2438 
2439  case ThreadZeroTlsCell:
2440 
2441  /* Check buffer length */
2442  if (ThreadInformationLength != sizeof(ULONG))
2443  {
2445  break;
2446  }
2447 
2448  /* Use SEH for capture */
2449  _SEH2_TRY
2450  {
2451  /* Get the priority */
2452  TlsIndex = *(PULONG)ThreadInformation;
2453  }
2455  {
2456  /* Get the exception code */
2458  _SEH2_YIELD(break);
2459  }
2460  _SEH2_END;
2461 
2462  /* Reference the thread */
2463  Status = ObReferenceObjectByHandle(ThreadHandle,
2465  PsThreadType,
2466  PreviousMode,
2467  (PVOID*)&Thread,
2468  NULL);
2469  if (!NT_SUCCESS(Status))
2470  break;
2471 
2472  /* This is only valid for the current thread */
2473  if (Thread != PsGetCurrentThread())
2474  {
2475  /* Fail */
2478  break;
2479  }
2480 
2481  /* Get the process */
2482  Process = Thread->ThreadsProcess;
2483 
2484  /* Loop the threads */
2485  ProcThread = PsGetNextProcessThread(Process, NULL);
2486  while (ProcThread)
2487  {
2488  /* Acquire rundown */
2489  if (ExAcquireRundownProtection(&ProcThread->RundownProtect))
2490  {
2491  /* Get the TEB */
2492  Teb = ProcThread->Tcb.Teb;
2493  if (Teb)
2494  {
2495  /* Check if we're in the expansion range */
2496  if (TlsIndex > TLS_MINIMUM_AVAILABLE - 1)
2497  {
2499  TLS_EXPANSION_SLOTS) - 1)
2500  {
2501  /* Check if we have expansion slots */
2502  ExpansionSlots = Teb->TlsExpansionSlots;
2503  if (ExpansionSlots)
2504  {
2505  /* Clear the index */
2506  ExpansionSlots[TlsIndex - TLS_MINIMUM_AVAILABLE] = 0;
2507  }
2508  }
2509  }
2510  else
2511  {
2512  /* Clear the index */
2513  Teb->TlsSlots[TlsIndex] = NULL;
2514  }
2515  }
2516 
2517  /* Release rundown */
2519  }
2520 
2521  /* Go to the next thread */
2522  ProcThread = PsGetNextProcessThread(Process, ProcThread);
2523  }
2524 
2525  /* Dereference the thread */
2527  break;
2528 
2530 
2531  /* Check buffer length */
2532  if (ThreadInformationLength != sizeof(ULONG))
2533  {
2535  break;
2536  }
2537 
2538  /* Enter SEH for direct buffer read */
2539  _SEH2_TRY
2540  {
2541  Break = *(PULONG)ThreadInformation;
2542  }
2544  {
2545  /* Get exception code */
2546  Break = 0;
2548  _SEH2_YIELD(break);
2549  }
2550  _SEH2_END;
2551 
2552  /* Setting 'break on termination' requires the SeDebugPrivilege */
2554  {
2555  /* We don't hold the privilege, bail out */
2557  break;
2558  }
2559 
2560  /* Reference the thread */
2561  Status = ObReferenceObjectByHandle(ThreadHandle,
2563  PsThreadType,
2564  PreviousMode,
2565  (PVOID*)&Thread,
2566  NULL);
2567  if (!NT_SUCCESS(Status))
2568  break;
2569 
2570  /* Set or clear the flag */
2571  if (Break)
2572  {
2574  }
2575  else
2576  {
2578  }
2579 
2580  /* Dereference the thread */
2582  break;
2583 
2585 
2586  /* Check buffer length */
2587  if (ThreadInformationLength != 0)
2588  {
2590  break;
2591  }
2592 
2593  /* Reference the thread */
2594  Status = ObReferenceObjectByHandle(ThreadHandle,
2596  PsThreadType,
2597  PreviousMode,
2598  (PVOID*)&Thread,
2599  NULL);
2600  if (!NT_SUCCESS(Status))
2601  break;
2602 
2603  /* Set the flag */
2605 
2606  /* Dereference the thread */
2608  break;
2609 
2610  default:
2611  /* We don't implement it yet */
2612  DPRINT1("Not implemented: %d\n", ThreadInformationClass);
2614  }
2615 
2616  return Status;
2617 }
2618 
2619 /*
2620  * @implemented
2621  */
2622 NTSTATUS
2623 NTAPI
2626  OUT PVOID ThreadInformation,
2629 {
2630  PETHREAD Thread;
2632  NTSTATUS Status;
2633  ULONG Access;
2634  ULONG Length = 0;
2635  PTHREAD_BASIC_INFORMATION ThreadBasicInfo =
2636  (PTHREAD_BASIC_INFORMATION)ThreadInformation;
2637  PKERNEL_USER_TIMES ThreadTime = (PKERNEL_USER_TIMES)ThreadInformation;
2638  KIRQL OldIrql;
2639  ULONG ThreadTerminated;
2640  PAGED_CODE();
2641 
2642  /* Verify Information Class validity */
2646  ThreadInformation,
2648  ReturnLength,
2649  NULL,
2650  PreviousMode,
2651  FALSE);
2652  if (!NT_SUCCESS(Status))
2653  {
2654  DPRINT1("NtQueryInformationThread(): Information verification class failed! (Status -> 0x%lx , ThreadInformationClass -> %lx)\n", Status, ThreadInformationClass);
2655  return Status;
2656  }
2657 
2658  /* Check what class this is */
2659  Access = THREAD_QUERY_INFORMATION;
2660 
2661  /* Check what kind of information class this is */
2662  switch (ThreadInformationClass)
2663  {
2664  /* Basic thread information */
2666 
2667  /* Set return length */
2668  Length = sizeof(THREAD_BASIC_INFORMATION);
2669 
2671  {
2673  break;
2674  }
2675 
2676  /* Reference the process */
2677  Status = ObReferenceObjectByHandle(ThreadHandle,
2678  Access,
2679  PsThreadType,
2680  PreviousMode,
2681  (PVOID*)&Thread,
2682  NULL);
2683  if (!NT_SUCCESS(Status))
2684  break;
2685 
2686  /* Protect writes with SEH */
2687  _SEH2_TRY
2688  {
2689  /* Write all the information from the ETHREAD/KTHREAD */
2690  ThreadBasicInfo->ExitStatus = Thread->ExitStatus;
2691  ThreadBasicInfo->TebBaseAddress = (PVOID)Thread->Tcb.Teb;
2692  ThreadBasicInfo->ClientId = Thread->Cid;
2693  ThreadBasicInfo->AffinityMask = Thread->Tcb.Affinity;
2694  ThreadBasicInfo->Priority = Thread->Tcb.Priority;
2695  ThreadBasicInfo->BasePriority = KeQueryBasePriorityThread(&Thread->Tcb);
2696  }
2698  {
2699  /* Get exception code */
2701  }
2702  _SEH2_END;
2703 
2704  /* Dereference the thread */
2706  break;
2707 
2708  /* Thread time information */
2709  case ThreadTimes:
2710 
2711  /* Set the return length */
2712  Length = sizeof(KERNEL_USER_TIMES);
2713 
2715  {
2717  break;
2718  }
2719 
2720  /* Reference the process */
2721  Status = ObReferenceObjectByHandle(ThreadHandle,
2722  Access,
2723  PsThreadType,
2724  PreviousMode,
2725  (PVOID*)&Thread,
2726  NULL);
2727  if (!NT_SUCCESS(Status))
2728  break;
2729 
2730  /* Protect writes with SEH */
2731  _SEH2_TRY
2732  {
2733  /* Copy time information from ETHREAD/KTHREAD */
2736  ThreadTime->CreateTime = Thread->CreateTime;
2737 
2738  /* Exit time is in a union and only valid on actual exit! */
2739  if (KeReadStateThread(&Thread->Tcb))
2740  {
2741  ThreadTime->ExitTime = Thread->ExitTime;
2742  }
2743  else
2744  {
2745  ThreadTime->ExitTime.QuadPart = 0;
2746  }
2747  }
2749  {
2750  /* Get exception code */
2752  }
2753  _SEH2_END;
2754 
2755  /* Dereference the thread */
2757  break;
2758 
2760 
2761  /* Set the return length*/
2762  Length = sizeof(PVOID);
2763 
2765  {
2767  break;
2768  }
2769 
2770  /* Reference the process */
2771  Status = ObReferenceObjectByHandle(ThreadHandle,
2772  Access,
2773  PsThreadType,
2774  PreviousMode,
2775  (PVOID*)&Thread,
2776  NULL);
2777  if (!NT_SUCCESS(Status))
2778  break;
2779 
2780  /* Protect write with SEH */
2781  _SEH2_TRY
2782  {
2783  /* Return the Win32 Start Address */
2784  *(PVOID*)ThreadInformation = Thread->Win32StartAddress;
2785  }
2787  {
2788  /* Get exception code */
2790  }
2791  _SEH2_END;
2792 
2793  /* Dereference the thread */
2795  break;
2796 
2798 
2799  /* Set the return length*/
2800  Length = sizeof(LARGE_INTEGER);
2801 
2803  {
2805  break;
2806  }
2807 
2808  /* Reference the process */
2809  Status = ObReferenceObjectByHandle(ThreadHandle,
2810  Access,
2811  PsThreadType,
2812  PreviousMode,
2813  (PVOID*)&Thread,
2814  NULL);
2815  if (!NT_SUCCESS(Status))
2816  break;
2817 
2818  /* Protect write with SEH */
2819  _SEH2_TRY
2820  {
2821  /* FIXME */
2822  (*(PLARGE_INTEGER)ThreadInformation).QuadPart = 0;
2823  }
2825  {
2826  /* Get exception code */
2828  }
2829  _SEH2_END;
2830 
2831  /* Dereference the thread */
2833  break;
2834 
2835  case ThreadAmILastThread:
2836 
2837  /* Set the return length*/
2838  Length = sizeof(ULONG);
2839 
2841  {
2843  break;
2844  }
2845 
2846  /* Reference the process */
2847  Status = ObReferenceObjectByHandle(ThreadHandle,
2848  Access,
2849  PsThreadType,
2850  PreviousMode,
2851  (PVOID*)&Thread,
2852  NULL);
2853  if (!NT_SUCCESS(Status))
2854  break;
2855 
2856  /* Protect write with SEH */
2857  _SEH2_TRY
2858  {
2859  /* Return whether or not we are the last thread */
2860  *(PULONG)ThreadInformation = ((Thread->ThreadsProcess->
2861  ThreadListHead.Flink->Flink ==
2862  &Thread->ThreadsProcess->
2863  ThreadListHead) ?
2864  TRUE : FALSE);
2865  }
2867  {
2868  /* Get exception code */
2870  }
2871  _SEH2_END;
2872 
2873  /* Dereference the thread */
2875  break;
2876 
2877  case ThreadIsIoPending:
2878 
2879  /* Set the return length*/
2880  Length = sizeof(ULONG);
2881 
2883  {
2885  break;
2886  }
2887 
2888  /* Reference the process */
2889  Status = ObReferenceObjectByHandle(ThreadHandle,
2890  Access,
2891  PsThreadType,
2892  PreviousMode,
2893  (PVOID*)&Thread,
2894  NULL);
2895  if (!NT_SUCCESS(Status))
2896  break;
2897 
2898  /* Raise the IRQL to protect the IRP list */
2900 
2901  /* Protect write with SEH */
2902  _SEH2_TRY
2903  {
2904  /* Check if the IRP list is empty or not */
2905  *(PULONG)ThreadInformation = !IsListEmpty(&Thread->IrpList);
2906  }
2908  {
2909  /* Get exception code */
2911  }
2912  _SEH2_END;
2913 
2914  /* Lower IRQL back */
2916 
2917  /* Dereference the thread */
2919  break;
2920 
2921  /* LDT and GDT information */
2923 
2924 #if defined(_X86_)
2925  /* Reference the process */
2926  Status = ObReferenceObjectByHandle(ThreadHandle,
2927  Access,
2928  PsThreadType,
2929  PreviousMode,
2930  (PVOID*)&Thread,
2931  NULL);
2932  if (!NT_SUCCESS(Status))
2933  break;
2934 
2935  /* Call the worker routine */
2937  ThreadInformation,
2939  ReturnLength);
2940 
2941  /* Dereference the thread */
2943 #else
2944  /* Only implemented on x86 */
2946 #endif
2947  break;
2948 
2949  case ThreadPriorityBoost:
2950 
2951  /* Set the return length*/
2952  Length = sizeof(ULONG);
2953 
2955  {
2957  break;
2958  }
2959 
2960  /* Reference the process */
2961  Status = ObReferenceObjectByHandle(ThreadHandle,
2962  Access,
2963  PsThreadType,
2964  PreviousMode,
2965  (PVOID*)&Thread,
2966  NULL);
2967  if (!NT_SUCCESS(Status))
2968  break;
2969 
2970  _SEH2_TRY
2971  {
2972  *(PULONG)ThreadInformation = Thread->Tcb.DisableBoost ? 1 : 0;
2973  }
2975  {
2977  }
2978  _SEH2_END;
2979 
2980  /* Dereference the thread */
2982  break;
2983 
2984  case ThreadIsTerminated:
2985 
2986  /* Set the return length*/
2987  Length = sizeof(ThreadTerminated);
2988 
2990  {
2992  break;
2993  }
2994 
2995  /* Reference the process */
2996  Status = ObReferenceObjectByHandle(ThreadHandle,
2997  Access,
2998  PsThreadType,
2999  PreviousMode,
3000  (PVOID*)&Thread,
3001  NULL);
3002  if (!NT_SUCCESS(Status))
3003  break;
3004 
3005  ThreadTerminated = PsIsThreadTerminating(Thread);
3006 
3007  _SEH2_TRY
3008  {
3009  *(PULONG)ThreadInformation = ThreadTerminated ? 1 : 0;
3010  }
3012  {
3014  }
3015  _SEH2_END;
3016 
3017  /* Dereference the thread */
3019  break;
3020 
3021  /* Anything else */
3022  default:
3023 
3024  /* Not yet implemented */
3025  DPRINT1("Not implemented: %lx\n", ThreadInformationClass);
3027  }
3028 
3029  /* Protect write with SEH */
3030  _SEH2_TRY
3031  {
3032  /* Check if caller wanted return length */
3034  }
3036  {
3037  /* Get exception code */
3039  }
3040  _SEH2_END;
3041 
3042  return Status;
3043 }
3044 
3045 /* EOF */
LARGE_INTEGER TimeLimit
Definition: lsa.idl:292
#define KeQuerySystemTime(t)
Definition: env_spec_w32.h:570
struct _THREAD_BASIC_INFORMATION THREAD_BASIC_INFORMATION
#define MAXIMUM_PROCESSORS
Definition: rwlock.h:5
BOOLEAN NTAPI KeSetDisableBoostThread(IN OUT PKTHREAD Thread, IN BOOLEAN Disable)
Definition: thrdobj.c:95
#define LOW_PRIORITY
ULONG KeMaximumIncrement
Definition: clock.c:20
#define RTL_FIELD_SIZE(type, field)
Definition: kdb_expr.c:84
IN CINT OUT PVOID IN ULONG OUT PULONG ReturnLength
Definition: dumpinfo.c:39
PFILE_OBJECT NTAPI MmGetFileObjectForSection(IN PVOID Section)
Definition: section.c:1734
SIZE_T PeakVirtualSize
Definition: winternl.h:1605
INT64 NonPagedPoolLimit
Definition: lsa.idl:288
#define PAGE_SHIFT
Definition: env_spec_w32.h:45
#define IN
Definition: typedefs.h:39
#define PspClearProcessFlag(Process, Flag)
Definition: ps_x.h:35
NTSTATUS NTAPI SeLocateProcessImageName(_In_ PEPROCESS Process, _Out_ PUNICODE_STRING *ProcessImageName)
Finds the process image name of a specific process.
Definition: audit.c:199
struct _VM_COUNTERS_ * PVM_COUNTERS
#define STATUS_PRIVILEGE_NOT_HELD
Definition: DriverTester.h:9
#define PSF_BREAK_ON_TERMINATION_BIT
Definition: pstypes.h:285
LARGE_INTEGER ExitTime
Definition: pstypes.h:1107
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
KAFFINITY NTAPI KeSetAffinityProcess(IN PKPROCESS Process, IN KAFFINITY Affinity)
Definition: procobj.c:265
INT64 PagefileLimit
Definition: lsa.idl:291
#define STATUS_INFO_LENGTH_MISMATCH
Definition: udferr_usr.h:133
ULONG InterruptTime
Definition: ketypes.h:740
KAFFINITY AffinityMask
Definition: compat.h:789
SIZE_T PeakPagefileUsage
Definition: winternl.h:1615
#define _WIN32_WINNT_WS03
Definition: sdkddkver.h:23
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
BOOLEAN NTAPI KeSetAutoAlignmentProcess(IN PKPROCESS Process, IN BOOLEAN Enable)
Definition: procobj.c:313
#define PspClearCrossThreadFlag(Thread, Flag)
Definition: ps_x.h:27
KAFFINITY NTAPI KeSetAffinityThread(IN PKTHREAD Thread, IN KAFFINITY Affinity)
Definition: thrdobj.c:1303
#define PROCESS_QUERY_INFORMATION
Definition: pstypes.h:166
NTSTATUS NTAPI ObQueryDeviceMapInformation(_In_opt_ PEPROCESS Process, _Out_ PPROCESS_DEVICEMAP_INFORMATION DeviceMapInfo, _In_ ULONG Flags)
Definition: devicemap.c:539
#define _Out_
Definition: ms_sal.h:345
const LUID SeDebugPrivilege
Definition: priv.c:39
#define SEM_NOALIGNMENTFAULTEXCEPT
Definition: rtltypes.h:71
NTKERNELAPI VOID FASTCALL ExReleaseRundownProtection(_Inout_ PEX_RUNDOWN_REF RunRef)
#define TRUE
Definition: types.h:120
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
BOOLEAN NTAPI KeSetDisableBoostProcess(IN PKPROCESS Process, IN BOOLEAN Disable)
Definition: procobj.c:331
#define TLS_EXPANSION_SLOTS
Definition: pstypes.h:310
uint16_t * PWSTR
Definition: typedefs.h:56
SIZE_T QuotaPagedPoolUsage
Definition: winternl.h:1611
LARGE_INTEGER CreateTime
Definition: pstypes.h:1104
#define THREAD_SET_INFORMATION
Definition: nt_native.h:1337
#define THREAD_BASE_PRIORITY_MAX
Definition: pstypes.h:183
struct _KERNEL_USER_TIMES KERNEL_USER_TIMES
LONG NTSTATUS
Definition: precomp.h:26
struct _PROCESS_ACCESS_TOKEN * PPROCESS_ACCESS_TOKEN
LARGE_INTEGER UserTime
Definition: winternl.h:1063
EX_RUNDOWN_REF RundownProtect
Definition: pstypes.h:1159
NTSTATUS NTAPI ObSetDeviceMap(IN PEPROCESS Process, IN HANDLE DirectoryHandle)
Definition: devicemap.c:24
_IRQL_requires_same_ _In_ PLSA_STRING _In_ SECURITY_LOGON_TYPE _In_ ULONG _In_ ULONG _In_opt_ PTOKEN_GROUPS _In_ PTOKEN_SOURCE _Out_ PVOID _Out_ PULONG _Inout_ PLUID _Out_ PHANDLE Token
KTHREAD Tcb
Definition: pstypes.h:1103
FORCEINLINE struct _KPRCB * KeGetCurrentPrcb(VOID)
Definition: ketypes.h:1079
#define ExAcquireRundownProtection
Definition: ex.h:133
SCHAR Priority
Definition: ketypes.h:1714
VOID NTAPI Ke386SetIOPL(VOID)
Definition: v86vdm.c:581
static HANDLE DirectoryHandle
Definition: ObType.c:48
SIZE_T PagefileUsage
Definition: winternl.h:1614
SIZE_T QuotaPeakPagedPoolUsage
Definition: winternl.h:1610
#define InterlockedCompareExchange
Definition: interlocked.h:104
#define LOW_REALTIME_PRIORITY
KPROCESSOR_MODE NTAPI ExGetPreviousMode(VOID)
Definition: sysinfo.c:3070
LONG NTAPI KeSetBasePriorityThread(IN PKTHREAD Thread, IN LONG Increment)
Definition: thrdobj.c:1184
SIZE_T VirtualSize
Definition: winternl.h:1606
IO_COUNTERS IoInfo
Definition: ke.h:48
#define PROCESS_SUSPEND_RESUME
Definition: pstypes.h:167
_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
#define THREAD_SET_THREAD_TOKEN
Definition: pstypes.h:150
LONG KPRIORITY
Definition: compat.h:662
static __inline NTSTATUS DefaultQueryInfoBufferCheck(ULONG Class, const INFORMATION_CLASS_INFO *ClassList, ULONG ClassListEntries, PVOID Buffer, ULONG BufferLength, PULONG ReturnLength, PULONG_PTR ReturnLengthPtr, KPROCESSOR_MODE PreviousMode, BOOLEAN CompleteProbing)
Definition: probe.h:59
KPRIORITY BasePriority
Definition: compat.h:791
_SEH2_TRY
Definition: create.c:4226
SIZE_T QuotaPeakNonPagedPoolUsage
Definition: winternl.h:1612
uint32_t ULONG_PTR
Definition: typedefs.h:65
ULONG PspTraceLevel
Definition: query.c:18
LARGE_INTEGER ExitTime
Definition: winternl.h:1061
NTSTATUS NTAPI PspQueryDescriptorThread(IN PETHREAD Thread, IN PVOID ThreadInformation, IN ULONG ThreadInformationLength, OUT PULONG ReturnLength OPTIONAL)
Definition: psldt.c:43
NTSTATUS NTAPI PspSetQuotaLimits(_In_ PEPROCESS Process, _In_ ULONG Unused, _In_ PVOID QuotaLimits, _In_ ULONG QuotaLimitsLength, _In_ KPROCESSOR_MODE PreviousMode)
Definition: quota.c:300
UCHAR KIRQL
Definition: env_spec_w32.h:591
ULONG PageFaultCount
Definition: winternl.h:1607
VOID NTAPI KeBoostPriorityThread(IN PKTHREAD Thread, IN KPRIORITY Increment)
Definition: thrdobj.c:229
struct _QUOTA_LIMITS QUOTA_LIMITS
return STATUS_NOT_IMPLEMENTED
enum _PROCESSINFOCLASS PROCESSINFOCLASS
Definition: loader.c:63
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
BOOLEAN NTAPI SeCheckPrivilegedObject(_In_ LUID PrivilegeValue, _In_ HANDLE ObjectHandle, _In_ ACCESS_MASK DesiredAccess, _In_ KPROCESSOR_MODE PreviousMode)
Checks a privileged object if such object has the specific privilege submitted by the caller.
Definition: priv.c:803
VOID NTAPI MmGetImageInformation(OUT PSECTION_IMAGE_INFORMATION ImageInformation)
Definition: section.c:1808
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
#define FALSE
Definition: types.h:117
long LONG
Definition: pedump.c:60
EPROCESS_QUOTA_BLOCK PspDefaultQuotaBlock
Definition: quota.c:17
INT64 PagedPoolLimit
Definition: lsa.idl:287
ULONG NTAPI ObGetProcessHandleCount(IN PEPROCESS Process)
Definition: obhandle.c:58
PVOID Win32StartAddress
Definition: pstypes.h:1152
#define InterlockedCompareExchangePointer
Definition: interlocked.h:129
_In_ THREADINFOCLASS ThreadInformationClass
Definition: psfuncs.h:832
struct _QUOTA_LIMITS * PQUOTA_LIMITS
BOOLEAN NTAPI KeReadStateThread(IN PKTHREAD Thread)
Definition: thrdobj.c:51
#define PsGetCurrentProcess
Definition: psfuncs.h:17
struct _PROCESS_PRIORITY_CLASS PROCESS_PRIORITY_CLASS
NTSTATUS NTAPI MmGetExecuteOptions(IN PULONG ExecuteOptions)
Definition: pagfault.c:2579
KAFFINITY * PKAFFINITY
Definition: basetsd.h:197
NTSTATUS NTAPI PspSetPrimaryToken(IN PEPROCESS Process, IN HANDLE TokenHandle OPTIONAL, IN PACCESS_TOKEN Token OPTIONAL)
Definition: security.c:215
unsigned char BOOLEAN
struct _OBJECT_NAME_INFORMATION OBJECT_NAME_INFORMATION
SIZE_T QuotaNonPagedPoolUsage
Definition: winternl.h:1613
struct _KERNEL_USER_TIMES * PKERNEL_USER_TIMES
static WCHAR Address[46]
Definition: ping.c:68
#define _In_
Definition: ms_sal.h:308
_In_ ACCESS_MASK _In_ ULONG _Out_ PHANDLE TokenHandle
Definition: psfuncs.h:715
NTSTATUS NTAPI DbgkOpenProcessDebugPort(IN PEPROCESS Process, IN KPROCESSOR_MODE PreviousMode, OUT HANDLE *DebugHandle)
Definition: dbgkobj.c:1526
#define CT_HIDE_FROM_DEBUGGER_BIT
Definition: pstypes.h:240
NTSTATUS NTAPI NtSetInformationThread(IN HANDLE ThreadHandle, IN THREADINFOCLASS ThreadInformationClass, IN PVOID ThreadInformation, IN ULONG ThreadInformationLength)
Definition: query.c:2018
void * PVOID
Definition: retypes.h:9
#define CT_BREAK_ON_TERMINATION_BIT
Definition: pstypes.h:244
#define HIGH_PRIORITY
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
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:547
#define UlongToPtr(u)
Definition: config.h:106
struct _THREAD_BASIC_INFORMATION * PTHREAD_BASIC_INFORMATION
ULONG_PTR InheritedFromUniqueProcessId
Definition: pstypes.h:340
#define NtCurrentProcess()
Definition: nt_native.h:1657
KIRQL OldIrql
Definition: mm.h:1502
_Out_ PULONG UserTime
Definition: kefuncs.h:771
POBJECT_TYPE LpcPortObjectType
Definition: port.c:17
ULONG DisableBoost
Definition: ketypes.h:1657
#define PROCESS_PRIORITY_CLASS_ABOVE_NORMAL
Definition: pstypes.h:112
Status
Definition: gdiplustypes.h:24
int64_t LONGLONG
Definition: typedefs.h:68
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
_In_ KPROCESSOR_MODE PreviousMode
Definition: sefuncs.h:103
struct _PROCESS_SESSION_INFORMATION * PPROCESS_SESSION_INFORMATION
#define THREAD_BASE_PRIORITY_LOWRT
Definition: pstypes.h:182
ULONG KernelTime
Definition: ketypes.h:1919
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
#define PROCESS_PRIORITY_CLASS_REALTIME
Definition: pstypes.h:110
struct _PROCESS_FOREGROUND_BACKGROUND * PPROCESS_FOREGROUND_BACKGROUND
VOID NTAPI KeQueryValuesProcess(IN PKPROCESS Process, PPROCESS_VALUES Values)
Definition: procobj.c:525
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
char CCHAR
Definition: typedefs.h:51
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
LARGE_INTEGER CreateTime
Definition: winternl.h:1060
#define PSF_NO_DEBUG_INHERIT_BIT
Definition: pstypes.h:274
CLIENT_ID Cid
Definition: pstypes.h:1128
#define THREAD_BASE_PRIORITY_IDLE
Definition: pstypes.h:185
_In_opt_ PVOID _Out_ PLARGE_INTEGER Cookie
Definition: cmfuncs.h:13
#define STATUS_PROCESS_IS_TERMINATING
Definition: ntstatus.h:502
#define ObDereferenceObject
Definition: obfuncs.h:203
_In_ ULONG _In_ ULONG _In_ ULONG _Out_ PKIRQL _Out_ PKAFFINITY Affinity
Definition: halfuncs.h:170
PVOID HANDLE
Definition: typedefs.h:73
#define MEMORY_PRIORITY_BACKGROUND
Definition: pstypes.h:124
ULONG KeSystemCalls
Definition: ketypes.h:651
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2652
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
BOOL Query(LPCTSTR *ServiceArgs, DWORD ArgCount, BOOL bExtended)
Definition: query.c:292
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7
NTSTATUS NTAPI PsReferenceProcessFilePointer(IN PEPROCESS Process, OUT PFILE_OBJECT *FileObject)
Definition: query.c:24
* PFILE_OBJECT
Definition: iotypes.h:1998
NTSTATUS NTAPI NtQueryInformationThread(IN HANDLE ThreadHandle, IN THREADINFOCLASS ThreadInformationClass, OUT PVOID ThreadInformation, IN ULONG ThreadInformationLength, OUT PULONG ReturnLength OPTIONAL)
Definition: query.c:2624
struct _SECTION_IMAGE_INFORMATION SECTION_IMAGE_INFORMATION
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
struct _PROCESS_BASIC_INFORMATION * PPROCESS_BASIC_INFORMATION
PETHREAD NTAPI PsGetNextProcessThread(IN PEPROCESS Process, IN PETHREAD Thread OPTIONAL)
Definition: process.c:75
VOID NTAPI KeDetachProcess(VOID)
Definition: procobj.c:621
struct _PROCESS_PRIORITY_CLASS * PPROCESS_PRIORITY_CLASS
_In_ WDFINTERRUPT _In_ WDF_INTERRUPT_POLICY _In_ WDF_INTERRUPT_PRIORITY Priority
Definition: wdfinterrupt.h:651
unsigned char UCHAR
Definition: xmlstorage.h:181
static const char * ImageName
Definition: image.c:34
char * PBOOLEAN
Definition: retypes.h:11
union _LARGE_INTEGER LARGE_INTEGER
POBJECT_TYPE PsThreadType
Definition: thread.c:20
NTSTATUS NTAPI MmSetExecuteOptions(IN ULONG ExecuteOptions)
Definition: pagfault.c:2621
#define STATUS_INVALID_INFO_CLASS
Definition: ntstatus.h:240
#define PROCESS_LUID_DOSDEVICES_ONLY
Definition: pstypes.h:228
#define PspSetCrossThreadFlag(Thread, Flag)
Definition: ps_x.h:25
#define PSF_VDM_ALLOWED_BIT
Definition: pstypes.h:296
PVOID *typedef PHANDLE
Definition: ntsecpkg.h:454
#define KeEnterCriticalRegion()
Definition: ke_x.h:88
ULONG IdealProcessor
Definition: ketypes.h:1876
ULONG LowPart
Definition: typedefs.h:106
NTSTATUS NTAPI PsAssignImpersonationToken(IN PETHREAD Thread, IN HANDLE TokenHandle)
Definition: security.c:502
KPRIORITY NTAPI KeSetPriorityAndQuantumProcess(IN PKPROCESS Process, IN KPRIORITY Priority, IN UCHAR Quantum OPTIONAL)
Definition: procobj.c:349
Definition: typedefs.h:119
#define TlsIndex
Definition: ws2_32p.h:277
INT64 MinimumWorkingSetSize
Definition: lsa.idl:289
KAFFINITY KeActiveProcessors
Definition: krnlinit.c:23
VOID NTAPI PsSetProcessPriorityByClass(IN PEPROCESS Process, IN PSPROCESSPRIORITYMODE Type)
Definition: process.c:1325
const LUID SeIncreaseBasePriorityPrivilege
Definition: priv.c:33
BOOLEAN HasPrivilege(IN PPRIVILEGE_SET Privilege)
Definition: shutdown.c:92
#define MEMORY_PRIORITY_FOREGROUND
Definition: pstypes.h:126
const LUID SeTcbPrivilege
Definition: priv.c:26
#define MAXULONG
Definition: typedefs.h:251
FORCEINLINE VOID ExAcquirePushLockShared(PEX_PUSH_LOCK PushLock)
Definition: ex.h:1103
ULONG_PTR SIZE_T
Definition: typedefs.h:80
SIZE_T WorkingSetSize
Definition: winternl.h:1609
Definition: compat.h:694
_SEH2_END
Definition: create.c:4400
NTSTATUS ExitStatus
Definition: pstypes.h:1113
#define KeLeaveCriticalRegion()
Definition: ke_x.h:119
#define THREAD_BASE_PRIORITY_MIN
Definition: pstypes.h:184
NTSTATUS NTAPI NtSetInformationProcess(IN HANDLE ProcessHandle, IN PROCESSINFOCLASS ProcessInformationClass, IN PVOID ProcessInformation, IN ULONG ProcessInformationLength)
Definition: query.c:1105
enum _THREADINFOCLASS THREADINFOCLASS
Definition: thread.c:101
struct _PROCESS_SESSION_INFORMATION PROCESS_SESSION_INFORMATION
KPRIORITY NTAPI KeSetPriorityThread(IN PKTHREAD Thread, IN KPRIORITY Priority)
Definition: thrdobj.c:1327
_In_ THREADINFOCLASS _In_ ULONG ThreadInformationLength
Definition: psfuncs.h:835
#define RTL_NUMBER_OF(x)
Definition: RtlRegistry.c:12
ULONG_PTR KAFFINITY
Definition: compat.h:85
VOID NTAPI KeAttachProcess(IN PKPROCESS Process)
Definition: procobj.c:582
ULONG NTAPI KeQueryRuntimeProcess(IN PKPROCESS Process, OUT PULONG UserTime)
Definition: procobj.c:860
NTSTATUS NTAPI MmSetMemoryPriorityProcess(IN PEPROCESS Process, IN UCHAR MemoryPriority)
Definition: procsup.c:468
#define _Out_opt_
Definition: ms_sal.h:346
unsigned int * PULONG
Definition: retypes.h:1
#define NULL
Definition: types.h:112
VOID NTAPI KeRaiseIrql(KIRQL NewIrql, PKIRQL OldIrql)
Definition: spinlock.c:27
INT64 MaximumWorkingSetSize
Definition: lsa.idl:290
UNICODE_STRING * PUNICODE_STRING
Definition: env_spec_w32.h:373
struct _IO_COUNTERS IO_COUNTERS
PVOID Teb
Definition: ketypes.h:1739
#define DPRINT1
Definition: precomp.h:8
ULONG UserTime
Definition: ketypes.h:1935
BOOLEAN NTAPI SeSinglePrivilegeCheck(_In_ LUID PrivilegeValue, _In_ KPROCESSOR_MODE PreviousMode)
Checks if a single privilege is present in the context of the calling thread.
Definition: priv.c:744
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:219
#define PROCESS_SET_SESSIONID
Definition: pstypes.h:159
#define OUT
Definition: typedefs.h:40
#define ObReferenceObject
Definition: obfuncs.h:204
FORCEINLINE VOID ExReleasePushLockShared(PEX_PUSH_LOCK PushLock)
Definition: ex.h:1211
#define PspSetProcessFlag(Process, Flag)
Definition: ps_x.h:33
static LIST_ENTRY ThreadListHead
Definition: sys_arch.c:11
#define THREAD_QUERY_INFORMATION
Definition: pstypes.h:149
struct _LARGE_INTEGER::@2240 u
GROUP_AFFINITY Affinity
Definition: ketypes.h:1870
unsigned int ULONG
Definition: retypes.h:1
ULONG NTAPI PsGetProcessSessionId(IN PEPROCESS Process)
Definition: process.c:1163
#define UNIMPLEMENTED
Definition: debug.h:115
#define ULONG_PTR
Definition: config.h:101
uint32_t * PULONG_PTR
Definition: typedefs.h:65
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define PROCESS_SET_INFORMATION
Definition: pstypes.h:165
PVOID TlsSlots[64]
Definition: compat.h:738
PVOID * TlsExpansionSlots
Definition: compat.h:753
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:40
#define TAG_SEPA
Definition: tag.h:179
#define STATUS_SUCCESS
Definition: shellext.h:65
SIZE_T PeakWorkingSetSize
Definition: winternl.h:1608
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:165
#define _SEH2_YIELD(__stmt)
Definition: pseh2_64.h:168
struct _PROCESS_BASIC_INFORMATION PROCESS_BASIC_INFORMATION
UCHAR NTAPI KeSetIdealProcessorThread(IN PKTHREAD Thread, IN UCHAR Processor)
Definition: thrdobj.c:1075
VOID NTAPI KeLowerIrql(KIRQL NewIrql)
Definition: spinlock.c:39
BOOLEAN NTAPI PsIsThreadTerminating(IN PETHREAD Thread)
Definition: thread.c:868
_In_ HANDLE ProcessHandle
Definition: mmfuncs.h:403
static const INFORMATION_CLASS_INFO PsThreadInfoClass[]
Definition: ps_i.h:360
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
signed int * PLONG
Definition: retypes.h:5
ULONG NTAPI ObIsLUIDDeviceMapsEnabled(VOID)
Definition: devicemap.c:662
LARGE_INTEGER KernelTime
Definition: winternl.h:1062
LONG NTAPI KeQueryBasePriorityThread(IN PKTHREAD Thread)
Definition: thrdobj.c:61
LIST_ENTRY IrpList
Definition: pstypes.h:1144
#define APC_LEVEL
Definition: env_spec_w32.h:695
POBJECT_TYPE PsProcessType
Definition: process.c:20
ULONG ACCESS_MASK
Definition: nt_native.h:40
union _LARGE_INTEGER * PLARGE_INTEGER
Definition: file.c:85
NTSTATUS NTAPI NtQueryInformationProcess(_In_ HANDLE ProcessHandle, _In_ PROCESSINFOCLASS ProcessInformationClass, _Out_ PVOID ProcessInformation, _In_ ULONG ProcessInformationLength, _Out_opt_ PULONG ReturnLength)
Definition: query.c:59
static const INFORMATION_CLASS_INFO PsProcessInfoClass[]
Definition: ps_i.h:15
LONGLONG QuadPart
Definition: typedefs.h:114
#define TLS_MINIMUM_AVAILABLE
Definition: ntddk_ex.h:236
#define PAGED_CODE()
struct _IO_COUNTERS * PIO_COUNTERS
#define STATUS_PORT_ALREADY_SET
Definition: ntstatus.h:308
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68