xref: /reactos/ntoskrnl/ex/sysinfo.c (revision ffb20d33)
1c2c66affSColin Finck /*
2c2c66affSColin Finck  * COPYRIGHT:       See COPYING in the top level directory
3c2c66affSColin Finck  * PROJECT:         ReactOS kernel
4c2c66affSColin Finck  * FILE:            ntoskrnl/ex/sysinfo.c
5c2c66affSColin Finck  * PURPOSE:         System information functions
6c2c66affSColin Finck  *
7c2c66affSColin Finck  * PROGRAMMERS:     David Welch (welch@mcmail.com)
8c2c66affSColin Finck  *                  Aleksey Bragin (aleksey@reactos.org)
9c2c66affSColin Finck  */
10c2c66affSColin Finck 
11c2c66affSColin Finck /* INCLUDES *****************************************************************/
12c2c66affSColin Finck 
13c2c66affSColin Finck #include <ntoskrnl.h>
14d033fe9bSStanislav Motylkov #include <wmidata.h>
15d033fe9bSStanislav Motylkov #include <wmistr.h>
16c2c66affSColin Finck #define NDEBUG
17c2c66affSColin Finck #include <debug.h>
18c2c66affSColin Finck 
19c2c66affSColin Finck /* The maximum size of an environment value (in bytes) */
20c2c66affSColin Finck #define MAX_ENVVAL_SIZE 1024
21c2c66affSColin Finck 
22d033fe9bSStanislav Motylkov #define SIG_ACPI 0x41435049
23d033fe9bSStanislav Motylkov #define SIG_FIRM 0x4649524D
24d033fe9bSStanislav Motylkov #define SIG_RSMB 0x52534D42
25d033fe9bSStanislav Motylkov 
26c2c66affSColin Finck extern LIST_ENTRY HandleTableListHead;
27c2c66affSColin Finck extern EX_PUSH_LOCK HandleTableListLock;
28c2c66affSColin Finck 
29c2c66affSColin Finck FAST_MUTEX ExpEnvironmentLock;
30c2c66affSColin Finck ERESOURCE ExpFirmwareTableResource;
31c2c66affSColin Finck LIST_ENTRY ExpFirmwareTableProviderListHead;
32c2c66affSColin Finck 
33c2c66affSColin Finck FORCEINLINE
34c2c66affSColin Finck NTSTATUS
ExpConvertLdrModuleToRtlModule(IN ULONG ModuleCount,IN PLDR_DATA_TABLE_ENTRY LdrEntry,OUT PRTL_PROCESS_MODULE_INFORMATION ModuleInfo)35c2c66affSColin Finck ExpConvertLdrModuleToRtlModule(IN ULONG ModuleCount,
36c2c66affSColin Finck                                IN PLDR_DATA_TABLE_ENTRY LdrEntry,
37c2c66affSColin Finck                                OUT PRTL_PROCESS_MODULE_INFORMATION ModuleInfo)
38c2c66affSColin Finck {
39c2c66affSColin Finck     PCHAR p;
40c2c66affSColin Finck     NTSTATUS Status;
41c2c66affSColin Finck     ANSI_STRING ModuleName;
42c2c66affSColin Finck 
43c2c66affSColin Finck     /* Fill it out */
44c2c66affSColin Finck     ModuleInfo->MappedBase = NULL;
45c2c66affSColin Finck     ModuleInfo->ImageBase = LdrEntry->DllBase;
46c2c66affSColin Finck     ModuleInfo->ImageSize = LdrEntry->SizeOfImage;
47c2c66affSColin Finck     ModuleInfo->Flags = LdrEntry->Flags;
48c2c66affSColin Finck     ModuleInfo->LoadCount = LdrEntry->LoadCount;
49c2c66affSColin Finck     ModuleInfo->LoadOrderIndex = (USHORT)ModuleCount;
50c2c66affSColin Finck     ModuleInfo->InitOrderIndex = 0;
51c2c66affSColin Finck 
52c2c66affSColin Finck     /* Setup name */
53c2c66affSColin Finck     RtlInitEmptyAnsiString(&ModuleName,
54c2c66affSColin Finck                            ModuleInfo->FullPathName,
55c2c66affSColin Finck                            sizeof(ModuleInfo->FullPathName));
56c2c66affSColin Finck 
57c2c66affSColin Finck     /* Convert it */
58c2c66affSColin Finck     Status = RtlUnicodeStringToAnsiString(&ModuleName,
59c2c66affSColin Finck                                           &LdrEntry->FullDllName,
60c2c66affSColin Finck                                           FALSE);
61c2c66affSColin Finck     if ((NT_SUCCESS(Status)) || (Status == STATUS_BUFFER_OVERFLOW))
62c2c66affSColin Finck     {
63c2c66affSColin Finck         /* Calculate offset to name */
64c2c66affSColin Finck         p = ModuleName.Buffer + ModuleName.Length;
65c2c66affSColin Finck         while ((p > ModuleName.Buffer) && (*--p))
66c2c66affSColin Finck         {
67c2c66affSColin Finck             /* Check if we found the separator */
68c2c66affSColin Finck             if (*p == OBJ_NAME_PATH_SEPARATOR)
69c2c66affSColin Finck             {
70c2c66affSColin Finck                 /* We did, break out */
71c2c66affSColin Finck                 p++;
72c2c66affSColin Finck                 break;
73c2c66affSColin Finck             }
74c2c66affSColin Finck         }
75c2c66affSColin Finck 
76c2c66affSColin Finck         /* Set the offset */
77c2c66affSColin Finck         ModuleInfo->OffsetToFileName = (USHORT)(p - ModuleName.Buffer);
78c2c66affSColin Finck     }
79c2c66affSColin Finck     else
80c2c66affSColin Finck     {
81c2c66affSColin Finck         /* Return empty name */
82c2c66affSColin Finck         ModuleInfo->FullPathName[0] = ANSI_NULL;
83c2c66affSColin Finck         ModuleInfo->OffsetToFileName = 0;
84c2c66affSColin Finck     }
85c2c66affSColin Finck 
86c2c66affSColin Finck     return Status;
87c2c66affSColin Finck }
88c2c66affSColin Finck 
89c2c66affSColin Finck NTSTATUS
90c2c66affSColin Finck NTAPI
ExpQueryModuleInformation(IN PLIST_ENTRY KernelModeList,IN PLIST_ENTRY UserModeList,OUT PRTL_PROCESS_MODULES Modules,IN ULONG Length,OUT PULONG ReturnLength)91c2c66affSColin Finck ExpQueryModuleInformation(IN PLIST_ENTRY KernelModeList,
92c2c66affSColin Finck                           IN PLIST_ENTRY UserModeList,
93c2c66affSColin Finck                           OUT PRTL_PROCESS_MODULES Modules,
94c2c66affSColin Finck                           IN ULONG Length,
95c2c66affSColin Finck                           OUT PULONG ReturnLength)
96c2c66affSColin Finck {
97c2c66affSColin Finck     NTSTATUS Status = STATUS_SUCCESS;
98c2c66affSColin Finck     ULONG RequiredLength;
99c2c66affSColin Finck     PRTL_PROCESS_MODULE_INFORMATION ModuleInfo;
100c2c66affSColin Finck     PLDR_DATA_TABLE_ENTRY LdrEntry;
101c2c66affSColin Finck     ULONG ModuleCount = 0;
102c2c66affSColin Finck     PLIST_ENTRY NextEntry;
103c2c66affSColin Finck 
104c2c66affSColin Finck     /* Setup defaults */
105c2c66affSColin Finck     RequiredLength = FIELD_OFFSET(RTL_PROCESS_MODULES, Modules);
106c2c66affSColin Finck     ModuleInfo = &Modules->Modules[0];
107c2c66affSColin Finck 
108c2c66affSColin Finck     /* Loop the kernel list */
109c2c66affSColin Finck     NextEntry = KernelModeList->Flink;
110c2c66affSColin Finck     while (NextEntry != KernelModeList)
111c2c66affSColin Finck     {
112c2c66affSColin Finck         /* Get the entry */
113c2c66affSColin Finck         LdrEntry = CONTAINING_RECORD(NextEntry,
114c2c66affSColin Finck                                      LDR_DATA_TABLE_ENTRY,
115c2c66affSColin Finck                                      InLoadOrderLinks);
116c2c66affSColin Finck 
117c2c66affSColin Finck         /* Update size and check if we can manage one more entry */
118c2c66affSColin Finck         RequiredLength += sizeof(RTL_PROCESS_MODULE_INFORMATION);
119c2c66affSColin Finck         if (Length >= RequiredLength)
120c2c66affSColin Finck         {
121c2c66affSColin Finck             Status = ExpConvertLdrModuleToRtlModule(ModuleCount,
122c2c66affSColin Finck                                                     LdrEntry,
123c2c66affSColin Finck                                                     ModuleInfo);
124c2c66affSColin Finck 
125c2c66affSColin Finck             /* Go to the next module */
126c2c66affSColin Finck             ModuleInfo++;
127c2c66affSColin Finck         }
128c2c66affSColin Finck         else
129c2c66affSColin Finck         {
130c2c66affSColin Finck             /* Set error code */
131c2c66affSColin Finck             Status = STATUS_INFO_LENGTH_MISMATCH;
132c2c66affSColin Finck         }
133c2c66affSColin Finck 
134c2c66affSColin Finck         /* Update count and move to next entry */
135c2c66affSColin Finck         ModuleCount++;
136c2c66affSColin Finck         NextEntry = NextEntry->Flink;
137c2c66affSColin Finck     }
138c2c66affSColin Finck 
139c2c66affSColin Finck     /* Check if caller also wanted user modules */
140c2c66affSColin Finck     if (UserModeList)
141c2c66affSColin Finck     {
142c2c66affSColin Finck         NextEntry = UserModeList->Flink;
143c2c66affSColin Finck         while (NextEntry != UserModeList)
144c2c66affSColin Finck         {
145c2c66affSColin Finck             /* Get the entry */
146c2c66affSColin Finck             LdrEntry = CONTAINING_RECORD(NextEntry,
147c2c66affSColin Finck                                          LDR_DATA_TABLE_ENTRY,
148c2c66affSColin Finck                                          InLoadOrderLinks);
149c2c66affSColin Finck 
150c2c66affSColin Finck             /* Update size and check if we can manage one more entry */
151c2c66affSColin Finck             RequiredLength += sizeof(RTL_PROCESS_MODULE_INFORMATION);
152c2c66affSColin Finck             if (Length >= RequiredLength)
153c2c66affSColin Finck             {
154c2c66affSColin Finck                 Status = ExpConvertLdrModuleToRtlModule(ModuleCount,
155c2c66affSColin Finck                                                         LdrEntry,
156c2c66affSColin Finck                                                         ModuleInfo);
157c2c66affSColin Finck 
158c2c66affSColin Finck                 /* Go to the next module */
159c2c66affSColin Finck                 ModuleInfo++;
160c2c66affSColin Finck             }
161c2c66affSColin Finck             else
162c2c66affSColin Finck             {
163c2c66affSColin Finck                 /* Set error code */
164c2c66affSColin Finck                 Status = STATUS_INFO_LENGTH_MISMATCH;
165c2c66affSColin Finck             }
166c2c66affSColin Finck 
167c2c66affSColin Finck             /* Update count and move to next entry */
168c2c66affSColin Finck             ModuleCount++;
169c2c66affSColin Finck             NextEntry = NextEntry->Flink;
170c2c66affSColin Finck         }
171c2c66affSColin Finck     }
172c2c66affSColin Finck 
173c2c66affSColin Finck     /* Update return length */
174c2c66affSColin Finck     if (ReturnLength) *ReturnLength = RequiredLength;
175c2c66affSColin Finck 
176c2c66affSColin Finck     /* Validate the length again */
177c2c66affSColin Finck     if (Length >= FIELD_OFFSET(RTL_PROCESS_MODULES, Modules))
178c2c66affSColin Finck     {
179c2c66affSColin Finck         /* Set the final count */
180c2c66affSColin Finck         Modules->NumberOfModules = ModuleCount;
181c2c66affSColin Finck     }
182c2c66affSColin Finck     else
183c2c66affSColin Finck     {
184c2c66affSColin Finck         /* Otherwise, we failed */
185c2c66affSColin Finck         Status = STATUS_INFO_LENGTH_MISMATCH;
186c2c66affSColin Finck     }
187c2c66affSColin Finck 
188c2c66affSColin Finck     /* Done */
189c2c66affSColin Finck     return Status;
190c2c66affSColin Finck }
191c2c66affSColin Finck 
192c2c66affSColin Finck VOID
193c2c66affSColin Finck NTAPI
ExUnlockUserBuffer(PMDL Mdl)194c2c66affSColin Finck ExUnlockUserBuffer(PMDL Mdl)
195c2c66affSColin Finck {
196c2c66affSColin Finck     MmUnlockPages(Mdl);
197c2c66affSColin Finck     ExFreePoolWithTag(Mdl, TAG_MDL);
198c2c66affSColin Finck }
199c2c66affSColin Finck 
200c2c66affSColin Finck NTSTATUS
201c2c66affSColin Finck NTAPI
ExLockUserBuffer(PVOID BaseAddress,ULONG Length,KPROCESSOR_MODE AccessMode,LOCK_OPERATION Operation,PVOID * MappedSystemVa,PMDL * OutMdl)202c2c66affSColin Finck ExLockUserBuffer(
203c2c66affSColin Finck     PVOID BaseAddress,
204c2c66affSColin Finck     ULONG Length,
205c2c66affSColin Finck     KPROCESSOR_MODE AccessMode,
206c2c66affSColin Finck     LOCK_OPERATION Operation,
207c2c66affSColin Finck     PVOID *MappedSystemVa,
208c2c66affSColin Finck     PMDL *OutMdl)
209c2c66affSColin Finck {
210c2c66affSColin Finck     PMDL Mdl;
211c2c66affSColin Finck     PAGED_CODE();
212c2c66affSColin Finck 
213c2c66affSColin Finck     *MappedSystemVa = NULL;
214c2c66affSColin Finck     *OutMdl = NULL;
215c2c66affSColin Finck 
216c2c66affSColin Finck     /* Allocate an MDL for the buffer */
217c2c66affSColin Finck     Mdl = IoAllocateMdl(BaseAddress, Length, FALSE, TRUE, NULL);
218c2c66affSColin Finck     if (Mdl == NULL)
219c2c66affSColin Finck     {
220c2c66affSColin Finck         return STATUS_INSUFFICIENT_RESOURCES;
221c2c66affSColin Finck     }
222c2c66affSColin Finck 
223c2c66affSColin Finck     /* Enter SEH for probing */
224c2c66affSColin Finck     _SEH2_TRY
225c2c66affSColin Finck     {
226c2c66affSColin Finck         MmProbeAndLockPages(Mdl, AccessMode, Operation);
227c2c66affSColin Finck     }
228c2c66affSColin Finck     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
229c2c66affSColin Finck     {
230c2c66affSColin Finck         ExFreePoolWithTag(Mdl, TAG_MDL);
231c2c66affSColin Finck         _SEH2_YIELD(return _SEH2_GetExceptionCode());
232c2c66affSColin Finck     }
233c2c66affSColin Finck     _SEH2_END;
234c2c66affSColin Finck 
235c2c66affSColin Finck     /* Return the safe kernel mode buffer */
236c2c66affSColin Finck     *MappedSystemVa = MmGetSystemAddressForMdlSafe(Mdl, NormalPagePriority);
237c2c66affSColin Finck     if (*MappedSystemVa == NULL)
238c2c66affSColin Finck     {
239c2c66affSColin Finck         ExUnlockUserBuffer(Mdl);
240c2c66affSColin Finck         return STATUS_INSUFFICIENT_RESOURCES;
241c2c66affSColin Finck     }
242c2c66affSColin Finck 
243c2c66affSColin Finck     /* Return the MDL */
244c2c66affSColin Finck     *OutMdl = Mdl;
245c2c66affSColin Finck     return STATUS_SUCCESS;
246c2c66affSColin Finck }
247c2c66affSColin Finck 
248d033fe9bSStanislav Motylkov NTSTATUS
249d033fe9bSStanislav Motylkov NTAPI
ExpGetRawSMBiosTable(_Out_opt_ PVOID Buffer,_Out_ ULONG * OutSize,_In_ ULONG BufferSize)250d033fe9bSStanislav Motylkov ExpGetRawSMBiosTable(
251d033fe9bSStanislav Motylkov     _Out_opt_ PVOID Buffer,
252d033fe9bSStanislav Motylkov     _Out_ ULONG * OutSize,
253d033fe9bSStanislav Motylkov     _In_ ULONG BufferSize)
254d033fe9bSStanislav Motylkov {
255d033fe9bSStanislav Motylkov     NTSTATUS Status;
256d033fe9bSStanislav Motylkov     PVOID DataBlockObject;
257d033fe9bSStanislav Motylkov     PWNODE_ALL_DATA AllData;
258d033fe9bSStanislav Motylkov     ULONG WMIBufSize;
259d033fe9bSStanislav Motylkov 
260d033fe9bSStanislav Motylkov     ASSERT(OutSize != NULL);
261d033fe9bSStanislav Motylkov     *OutSize = 0;
262d033fe9bSStanislav Motylkov 
263d033fe9bSStanislav Motylkov     /* Open the data block object for the SMBIOS table */
264d033fe9bSStanislav Motylkov     Status = IoWMIOpenBlock(&MSSmBios_RawSMBiosTables_GUID,
265d033fe9bSStanislav Motylkov                             WMIGUID_QUERY,
266d033fe9bSStanislav Motylkov                             &DataBlockObject);
267d033fe9bSStanislav Motylkov     if (!NT_SUCCESS(Status))
268d033fe9bSStanislav Motylkov     {
269d033fe9bSStanislav Motylkov         DPRINT1("IoWMIOpenBlock failed: 0x%08lx\n", Status);
270d033fe9bSStanislav Motylkov         return Status;
271d033fe9bSStanislav Motylkov     }
272d033fe9bSStanislav Motylkov 
273d033fe9bSStanislav Motylkov     /* Query the required buffer size */
274d033fe9bSStanislav Motylkov     WMIBufSize = 0;
275d033fe9bSStanislav Motylkov     Status = IoWMIQueryAllData(DataBlockObject, &WMIBufSize, NULL);
276d033fe9bSStanislav Motylkov     if (!NT_SUCCESS(Status))
277d033fe9bSStanislav Motylkov     {
278d033fe9bSStanislav Motylkov         DPRINT1("IoWMIOpenBlock failed: 0x%08lx\n", Status);
279d033fe9bSStanislav Motylkov         return Status;
280d033fe9bSStanislav Motylkov     }
281d033fe9bSStanislav Motylkov 
282d033fe9bSStanislav Motylkov     AllData = ExAllocatePoolWithTag(PagedPool, WMIBufSize, 'itfS');
283d033fe9bSStanislav Motylkov     if (AllData == NULL)
284d033fe9bSStanislav Motylkov     {
285d033fe9bSStanislav Motylkov         DPRINT1("Failed to allocate %lu bytes for SMBIOS tables\n", WMIBufSize);
286d033fe9bSStanislav Motylkov         return STATUS_INSUFFICIENT_RESOURCES;
287d033fe9bSStanislav Motylkov     }
288d033fe9bSStanislav Motylkov 
289d033fe9bSStanislav Motylkov     /* Query the buffer data */
290d033fe9bSStanislav Motylkov     Status = IoWMIQueryAllData(DataBlockObject, &WMIBufSize, AllData);
291d033fe9bSStanislav Motylkov     if (!NT_SUCCESS(Status))
292d033fe9bSStanislav Motylkov     {
293d033fe9bSStanislav Motylkov         DPRINT1("IoWMIOpenBlock failed: 0x%08lx\n", Status);
294d033fe9bSStanislav Motylkov         ExFreePoolWithTag(AllData, 'itfS');
295d033fe9bSStanislav Motylkov         return Status;
296d033fe9bSStanislav Motylkov     }
297d033fe9bSStanislav Motylkov 
298d033fe9bSStanislav Motylkov     Status = STATUS_SUCCESS;
299d033fe9bSStanislav Motylkov     *OutSize = AllData->FixedInstanceSize;
300d033fe9bSStanislav Motylkov     if (Buffer != NULL)
301d033fe9bSStanislav Motylkov     {
302d033fe9bSStanislav Motylkov         if (BufferSize >= *OutSize)
303d033fe9bSStanislav Motylkov         {
304d033fe9bSStanislav Motylkov             RtlMoveMemory(Buffer, AllData + 1, *OutSize);
305d033fe9bSStanislav Motylkov         }
306d033fe9bSStanislav Motylkov         else
307d033fe9bSStanislav Motylkov         {
308d033fe9bSStanislav Motylkov             Status = STATUS_BUFFER_TOO_SMALL;
309d033fe9bSStanislav Motylkov         }
310d033fe9bSStanislav Motylkov     }
311d033fe9bSStanislav Motylkov 
312d033fe9bSStanislav Motylkov     /* Free the buffer */
313d033fe9bSStanislav Motylkov     ExFreePoolWithTag(AllData, 'itfS');
314d033fe9bSStanislav Motylkov     return Status;
315d033fe9bSStanislav Motylkov }
316d033fe9bSStanislav Motylkov 
317c2c66affSColin Finck /* FUNCTIONS *****************************************************************/
318c2c66affSColin Finck 
319c2c66affSColin Finck /*
320c2c66affSColin Finck  * @implemented
321c2c66affSColin Finck  */
322c2c66affSColin Finck VOID
323c2c66affSColin Finck NTAPI
ExGetCurrentProcessorCpuUsage(PULONG CpuUsage)324c2c66affSColin Finck ExGetCurrentProcessorCpuUsage(PULONG CpuUsage)
325c2c66affSColin Finck {
326c2c66affSColin Finck     PKPRCB Prcb;
327c2c66affSColin Finck     ULONG TotalTime;
328c2c66affSColin Finck     ULONGLONG ScaledIdle;
329c2c66affSColin Finck 
330c2c66affSColin Finck     Prcb = KeGetCurrentPrcb();
331c2c66affSColin Finck 
332c2c66affSColin Finck     ScaledIdle = (ULONGLONG)Prcb->IdleThread->KernelTime * 100;
333c2c66affSColin Finck     TotalTime = Prcb->KernelTime + Prcb->UserTime;
334c2c66affSColin Finck     if (TotalTime != 0)
335c2c66affSColin Finck         *CpuUsage = (ULONG)(100 - (ScaledIdle / TotalTime));
336c2c66affSColin Finck     else
337c2c66affSColin Finck         *CpuUsage = 0;
338c2c66affSColin Finck }
339c2c66affSColin Finck 
340c2c66affSColin Finck /*
341c2c66affSColin Finck  * @implemented
342c2c66affSColin Finck  */
343c2c66affSColin Finck VOID
344c2c66affSColin Finck NTAPI
ExGetCurrentProcessorCounts(PULONG IdleTime,PULONG KernelAndUserTime,PULONG ProcessorNumber)3458e01dee2SEugen Podrug ExGetCurrentProcessorCounts(PULONG IdleTime,
3468e01dee2SEugen Podrug                             PULONG KernelAndUserTime,
347c2c66affSColin Finck                             PULONG ProcessorNumber)
348c2c66affSColin Finck {
349c2c66affSColin Finck     PKPRCB Prcb;
350c2c66affSColin Finck 
351c2c66affSColin Finck     Prcb = KeGetCurrentPrcb();
352c2c66affSColin Finck 
3538e01dee2SEugen Podrug     *IdleTime = Prcb->IdleThread->KernelTime;
3548e01dee2SEugen Podrug     *KernelAndUserTime = Prcb->KernelTime + Prcb->UserTime;
3558e01dee2SEugen Podrug     *ProcessorNumber = (ULONG)Prcb->Number;
356c2c66affSColin Finck }
357c2c66affSColin Finck 
358c2c66affSColin Finck /*
359c2c66affSColin Finck  * @implemented
360c2c66affSColin Finck  */
361c2c66affSColin Finck BOOLEAN
362c2c66affSColin Finck NTAPI
ExIsProcessorFeaturePresent(IN ULONG ProcessorFeature)363c2c66affSColin Finck ExIsProcessorFeaturePresent(IN ULONG ProcessorFeature)
364c2c66affSColin Finck {
365c2c66affSColin Finck     /* Quick check to see if it exists at all */
366c2c66affSColin Finck     if (ProcessorFeature >= PROCESSOR_FEATURE_MAX) return(FALSE);
367c2c66affSColin Finck 
368c2c66affSColin Finck     /* Return our support for it */
369c2c66affSColin Finck     return(SharedUserData->ProcessorFeatures[ProcessorFeature]);
370c2c66affSColin Finck }
371c2c66affSColin Finck 
372c2c66affSColin Finck /*
373c2c66affSColin Finck  * @implemented
374c2c66affSColin Finck  */
375c2c66affSColin Finck BOOLEAN
376c2c66affSColin Finck NTAPI
ExVerifySuite(SUITE_TYPE SuiteType)377c2c66affSColin Finck ExVerifySuite(SUITE_TYPE SuiteType)
378c2c66affSColin Finck {
379c2c66affSColin Finck     if (SuiteType == Personal) return TRUE;
380c2c66affSColin Finck     return FALSE;
381c2c66affSColin Finck }
382c2c66affSColin Finck 
383c2c66affSColin Finck NTSTATUS
384c2c66affSColin Finck NTAPI
NtQuerySystemEnvironmentValue(IN PUNICODE_STRING VariableName,OUT PWSTR ValueBuffer,IN ULONG ValueBufferLength,IN OUT PULONG ReturnLength OPTIONAL)385c2c66affSColin Finck NtQuerySystemEnvironmentValue(IN PUNICODE_STRING VariableName,
386c2c66affSColin Finck                               OUT PWSTR ValueBuffer,
387c2c66affSColin Finck                               IN ULONG ValueBufferLength,
388c2c66affSColin Finck                               IN OUT PULONG ReturnLength OPTIONAL)
389c2c66affSColin Finck {
390c2c66affSColin Finck     ANSI_STRING AName;
391c2c66affSColin Finck     UNICODE_STRING WName;
392c2c66affSColin Finck     ARC_STATUS Result;
393c2c66affSColin Finck     PCH AnsiValueBuffer;
394c2c66affSColin Finck     ANSI_STRING AValue;
395c2c66affSColin Finck     UNICODE_STRING WValue;
396c2c66affSColin Finck     KPROCESSOR_MODE PreviousMode;
397c2c66affSColin Finck     NTSTATUS Status;
398c2c66affSColin Finck     PAGED_CODE();
399c2c66affSColin Finck 
400c2c66affSColin Finck     /* Check if the call came from user mode */
401c2c66affSColin Finck     PreviousMode = ExGetPreviousMode();
402c2c66affSColin Finck     if (PreviousMode != KernelMode)
403c2c66affSColin Finck     {
404c2c66affSColin Finck         _SEH2_TRY
405c2c66affSColin Finck         {
406c2c66affSColin Finck             /* Probe the input and output buffers */
407c2c66affSColin Finck             ProbeForRead(VariableName, sizeof(UNICODE_STRING), sizeof(ULONG));
408c2c66affSColin Finck             ProbeForWrite(ValueBuffer, ValueBufferLength, sizeof(WCHAR));
409c2c66affSColin Finck             if (ReturnLength != NULL) ProbeForWriteUlong(ReturnLength);
410c2c66affSColin Finck         }
411c2c66affSColin Finck         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
412c2c66affSColin Finck         {
413c2c66affSColin Finck             /* Return the exception code */
414c2c66affSColin Finck             _SEH2_YIELD(return _SEH2_GetExceptionCode());
415c2c66affSColin Finck         }
416c2c66affSColin Finck         _SEH2_END;
417c2c66affSColin Finck     }
418c2c66affSColin Finck 
419c2c66affSColin Finck     /* According to NTInternals the SeSystemEnvironmentName privilege is required! */
420c2c66affSColin Finck     if (!SeSinglePrivilegeCheck(SeSystemEnvironmentPrivilege, PreviousMode))
421c2c66affSColin Finck     {
422c2c66affSColin Finck         DPRINT1("NtQuerySystemEnvironmentValue: Caller requires the SeSystemEnvironmentPrivilege privilege!\n");
423c2c66affSColin Finck         return STATUS_PRIVILEGE_NOT_HELD;
424c2c66affSColin Finck     }
425c2c66affSColin Finck 
426c2c66affSColin Finck     /* Copy the name to kernel space if necessary */
427c2c66affSColin Finck     Status = ProbeAndCaptureUnicodeString(&WName, PreviousMode, VariableName);
428c2c66affSColin Finck     if (!NT_SUCCESS(Status)) return Status;
429c2c66affSColin Finck 
430c2c66affSColin Finck     /* Convert the name to ANSI and release the captured UNICODE string */
431c2c66affSColin Finck     Status = RtlUnicodeStringToAnsiString(&AName, &WName, TRUE);
432c2c66affSColin Finck     ReleaseCapturedUnicodeString(&WName, PreviousMode);
433c2c66affSColin Finck     if (!NT_SUCCESS(Status)) return Status;
434c2c66affSColin Finck 
435c2c66affSColin Finck     /* Allocate a buffer for the ANSI environment variable */
436c2c66affSColin Finck     AnsiValueBuffer = ExAllocatePoolWithTag(NonPagedPool, MAX_ENVVAL_SIZE, 'rvnE');
437c2c66affSColin Finck     if (AnsiValueBuffer == NULL)
438c2c66affSColin Finck     {
439c2c66affSColin Finck         RtlFreeAnsiString(&AName);
440c2c66affSColin Finck         return STATUS_INSUFFICIENT_RESOURCES;
441c2c66affSColin Finck     }
442c2c66affSColin Finck 
443c2c66affSColin Finck     /* Get the environment variable and free the ANSI name */
444c2c66affSColin Finck     Result = HalGetEnvironmentVariable(AName.Buffer,
445c2c66affSColin Finck                                        MAX_ENVVAL_SIZE,
446c2c66affSColin Finck                                        AnsiValueBuffer);
447c2c66affSColin Finck     RtlFreeAnsiString(&AName);
448c2c66affSColin Finck 
449c2c66affSColin Finck     /* Check if we had success */
450c2c66affSColin Finck     if (Result == ESUCCESS)
451c2c66affSColin Finck     {
452c2c66affSColin Finck         /* Copy the result back to the caller. */
453c2c66affSColin Finck         _SEH2_TRY
454c2c66affSColin Finck         {
455c2c66affSColin Finck             /* Initialize ANSI string from the result */
456c2c66affSColin Finck             RtlInitAnsiString(&AValue, AnsiValueBuffer);
457c2c66affSColin Finck 
458c2c66affSColin Finck             /* Initialize a UNICODE string from the callers buffer */
459c2c66affSColin Finck             RtlInitEmptyUnicodeString(&WValue, ValueBuffer, (USHORT)ValueBufferLength);
460c2c66affSColin Finck 
461c2c66affSColin Finck             /* Convert the result to UNICODE */
462c2c66affSColin Finck             Status = RtlAnsiStringToUnicodeString(&WValue, &AValue, FALSE);
463c2c66affSColin Finck 
464c2c66affSColin Finck             if (ReturnLength != NULL)
465c2c66affSColin Finck                 *ReturnLength = WValue.Length;
466c2c66affSColin Finck         }
467c2c66affSColin Finck         _SEH2_EXCEPT(ExSystemExceptionFilter())
468c2c66affSColin Finck         {
469c2c66affSColin Finck             Status = _SEH2_GetExceptionCode();
470c2c66affSColin Finck         }
471c2c66affSColin Finck         _SEH2_END;
472c2c66affSColin Finck     }
473c2c66affSColin Finck     else
474c2c66affSColin Finck     {
475c2c66affSColin Finck         Status = STATUS_UNSUCCESSFUL;
476c2c66affSColin Finck     }
477c2c66affSColin Finck 
478c2c66affSColin Finck     /* Free the allocated ANSI value buffer */
479c2c66affSColin Finck     ExFreePoolWithTag(AnsiValueBuffer, 'rvnE');
480c2c66affSColin Finck 
481c2c66affSColin Finck     return Status;
482c2c66affSColin Finck }
483c2c66affSColin Finck 
484c2c66affSColin Finck 
485c2c66affSColin Finck NTSTATUS
486c2c66affSColin Finck NTAPI
NtSetSystemEnvironmentValue(IN PUNICODE_STRING VariableName,IN PUNICODE_STRING Value)487c2c66affSColin Finck NtSetSystemEnvironmentValue(IN PUNICODE_STRING VariableName,
488c2c66affSColin Finck                             IN PUNICODE_STRING Value)
489c2c66affSColin Finck {
490c2c66affSColin Finck     UNICODE_STRING CapturedName, CapturedValue;
491c2c66affSColin Finck     ANSI_STRING AName, AValue;
492c2c66affSColin Finck     KPROCESSOR_MODE PreviousMode;
493c2c66affSColin Finck     NTSTATUS Status;
494c2c66affSColin Finck 
495c2c66affSColin Finck     PAGED_CODE();
496c2c66affSColin Finck 
497c2c66affSColin Finck     PreviousMode = ExGetPreviousMode();
498c2c66affSColin Finck 
499c2c66affSColin Finck     /*
500c2c66affSColin Finck      * Copy the strings to kernel space if necessary
501c2c66affSColin Finck      */
502c2c66affSColin Finck     Status = ProbeAndCaptureUnicodeString(&CapturedName,
503c2c66affSColin Finck                                           PreviousMode,
504c2c66affSColin Finck                                           VariableName);
505c2c66affSColin Finck     if (NT_SUCCESS(Status))
506c2c66affSColin Finck     {
507c2c66affSColin Finck         Status = ProbeAndCaptureUnicodeString(&CapturedValue,
508c2c66affSColin Finck                                               PreviousMode,
509c2c66affSColin Finck                                               Value);
510c2c66affSColin Finck         if (NT_SUCCESS(Status))
511c2c66affSColin Finck         {
512c2c66affSColin Finck             /*
513c2c66affSColin Finck              * according to ntinternals the SeSystemEnvironmentName privilege is required!
514c2c66affSColin Finck              */
515c2c66affSColin Finck             if (SeSinglePrivilegeCheck(SeSystemEnvironmentPrivilege,
516c2c66affSColin Finck                                        PreviousMode))
517c2c66affSColin Finck             {
518c2c66affSColin Finck                 /*
519c2c66affSColin Finck                  * convert the strings to ANSI
520c2c66affSColin Finck                  */
521c2c66affSColin Finck                 Status = RtlUnicodeStringToAnsiString(&AName,
522c2c66affSColin Finck                                                       &CapturedName,
523c2c66affSColin Finck                                                       TRUE);
524c2c66affSColin Finck                 if (NT_SUCCESS(Status))
525c2c66affSColin Finck                 {
526c2c66affSColin Finck                     Status = RtlUnicodeStringToAnsiString(&AValue,
527c2c66affSColin Finck                                                           &CapturedValue,
528c2c66affSColin Finck                                                           TRUE);
529c2c66affSColin Finck                     if (NT_SUCCESS(Status))
530c2c66affSColin Finck                     {
531c2c66affSColin Finck                         ARC_STATUS Result = HalSetEnvironmentVariable(AName.Buffer,
532c2c66affSColin Finck                                                                       AValue.Buffer);
533c2c66affSColin Finck 
534c2c66affSColin Finck                         Status = (Result ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL);
535c2c66affSColin Finck                     }
536c2c66affSColin Finck                 }
537c2c66affSColin Finck             }
538c2c66affSColin Finck             else
539c2c66affSColin Finck             {
540c2c66affSColin Finck                 DPRINT1("NtSetSystemEnvironmentValue: Caller requires the SeSystemEnvironmentPrivilege privilege!\n");
541c2c66affSColin Finck                 Status = STATUS_PRIVILEGE_NOT_HELD;
542c2c66affSColin Finck             }
543c2c66affSColin Finck 
544c2c66affSColin Finck             ReleaseCapturedUnicodeString(&CapturedValue,
545c2c66affSColin Finck                                          PreviousMode);
546c2c66affSColin Finck         }
547c2c66affSColin Finck 
548c2c66affSColin Finck         ReleaseCapturedUnicodeString(&CapturedName,
549c2c66affSColin Finck                                      PreviousMode);
550c2c66affSColin Finck     }
551c2c66affSColin Finck 
552c2c66affSColin Finck     return Status;
553c2c66affSColin Finck }
554c2c66affSColin Finck 
555c2c66affSColin Finck NTSTATUS
556c2c66affSColin Finck NTAPI
NtEnumerateSystemEnvironmentValuesEx(IN ULONG InformationClass,IN PVOID Buffer,IN ULONG BufferLength)557c2c66affSColin Finck NtEnumerateSystemEnvironmentValuesEx(IN ULONG InformationClass,
558c2c66affSColin Finck                                      IN PVOID Buffer,
559c2c66affSColin Finck                                      IN ULONG BufferLength)
560c2c66affSColin Finck {
561c2c66affSColin Finck     UNIMPLEMENTED;
562c2c66affSColin Finck     return STATUS_NOT_IMPLEMENTED;
563c2c66affSColin Finck }
564c2c66affSColin Finck 
565c2c66affSColin Finck NTSTATUS
566c2c66affSColin Finck NTAPI
NtQuerySystemEnvironmentValueEx(_In_ PUNICODE_STRING VariableName,_In_ LPGUID VendorGuid,_Out_opt_ PVOID Value,_Inout_ PULONG ReturnLength,_Out_opt_ PULONG Attributes)5674c8a2a88SRatin Gao NtQuerySystemEnvironmentValueEx(
5684c8a2a88SRatin Gao     _In_ PUNICODE_STRING VariableName,
5694c8a2a88SRatin Gao     _In_ LPGUID VendorGuid,
5704c8a2a88SRatin Gao     _Out_opt_ PVOID Value,
5714c8a2a88SRatin Gao     _Inout_ PULONG ReturnLength,
5724c8a2a88SRatin Gao     _Out_opt_ PULONG Attributes)
573c2c66affSColin Finck {
574c2c66affSColin Finck     UNIMPLEMENTED;
575c2c66affSColin Finck     return STATUS_NOT_IMPLEMENTED;
576c2c66affSColin Finck }
577c2c66affSColin Finck 
578c2c66affSColin Finck NTSTATUS
579c2c66affSColin Finck NTAPI
NtSetSystemEnvironmentValueEx(_In_ PUNICODE_STRING VariableName,_In_ LPGUID VendorGuid,_In_reads_bytes_opt_ (ValueLength)PVOID Value,_In_ ULONG ValueLength,_In_ ULONG Attributes)5804c8a2a88SRatin Gao NtSetSystemEnvironmentValueEx(
5814c8a2a88SRatin Gao     _In_ PUNICODE_STRING VariableName,
5824c8a2a88SRatin Gao     _In_ LPGUID VendorGuid,
5834c8a2a88SRatin Gao     _In_reads_bytes_opt_(ValueLength) PVOID Value,
5844c8a2a88SRatin Gao     _In_ ULONG ValueLength,
5854c8a2a88SRatin Gao     _In_ ULONG Attributes)
586c2c66affSColin Finck {
587c2c66affSColin Finck     UNIMPLEMENTED;
588c2c66affSColin Finck     return STATUS_NOT_IMPLEMENTED;
589c2c66affSColin Finck }
590c2c66affSColin Finck 
591c2c66affSColin Finck /* --- Query/Set System Information --- */
592c2c66affSColin Finck 
593c2c66affSColin Finck /*
594c2c66affSColin Finck  * NOTE: QSI_DEF(n) and SSI_DEF(n) define _cdecl function symbols
595c2c66affSColin Finck  * so the stack is popped only in one place on x86 platform.
596c2c66affSColin Finck  */
597c2c66affSColin Finck #define QSI_USE(n) QSI##n
598c2c66affSColin Finck #define QSI_DEF(n) \
599c2c66affSColin Finck static NTSTATUS QSI_USE(n) (PVOID Buffer, ULONG Size, PULONG ReqSize)
600c2c66affSColin Finck 
601c2c66affSColin Finck #define SSI_USE(n) SSI##n
602c2c66affSColin Finck #define SSI_DEF(n) \
603c2c66affSColin Finck static NTSTATUS SSI_USE(n) (PVOID Buffer, ULONG Size)
604c2c66affSColin Finck 
605c2c66affSColin Finck VOID
606c2c66affSColin Finck NTAPI
607c2c66affSColin Finck ExQueryPoolUsage(OUT PULONG PagedPoolPages,
608c2c66affSColin Finck                  OUT PULONG NonPagedPoolPages,
609c2c66affSColin Finck                  OUT PULONG PagedPoolAllocs,
610c2c66affSColin Finck                  OUT PULONG PagedPoolFrees,
611c2c66affSColin Finck                  OUT PULONG PagedPoolLookasideHits,
612c2c66affSColin Finck                  OUT PULONG NonPagedPoolAllocs,
613c2c66affSColin Finck                  OUT PULONG NonPagedPoolFrees,
614c2c66affSColin Finck                  OUT PULONG NonPagedPoolLookasideHits);
615c2c66affSColin Finck 
616c2c66affSColin Finck /* Class 0 - Basic Information */
QSI_DEF(SystemBasicInformation)617c2c66affSColin Finck QSI_DEF(SystemBasicInformation)
618c2c66affSColin Finck {
619c2c66affSColin Finck     PSYSTEM_BASIC_INFORMATION Sbi
620c2c66affSColin Finck         = (PSYSTEM_BASIC_INFORMATION) Buffer;
621c2c66affSColin Finck 
622c2c66affSColin Finck     *ReqSize = sizeof(SYSTEM_BASIC_INFORMATION);
623c2c66affSColin Finck 
624c2c66affSColin Finck     /* Check user buffer's size */
625c2c66affSColin Finck     if (Size != sizeof(SYSTEM_BASIC_INFORMATION))
626c2c66affSColin Finck     {
627c2c66affSColin Finck         return STATUS_INFO_LENGTH_MISMATCH;
628c2c66affSColin Finck     }
629c2c66affSColin Finck 
630c2c66affSColin Finck     RtlZeroMemory(Sbi, Size);
631c2c66affSColin Finck     Sbi->Reserved = 0;
632c2c66affSColin Finck     Sbi->TimerResolution = KeMaximumIncrement;
633c2c66affSColin Finck     Sbi->PageSize = PAGE_SIZE;
634c2c66affSColin Finck     Sbi->NumberOfPhysicalPages = MmNumberOfPhysicalPages;
635c2c66affSColin Finck     Sbi->LowestPhysicalPageNumber = (ULONG)MmLowestPhysicalPage;
636c2c66affSColin Finck     Sbi->HighestPhysicalPageNumber = (ULONG)MmHighestPhysicalPage;
637c2c66affSColin Finck     Sbi->AllocationGranularity = MM_VIRTMEM_GRANULARITY; /* hard coded on Intel? */
638c2c66affSColin Finck     Sbi->MinimumUserModeAddress = 0x10000; /* Top of 64k */
639c2c66affSColin Finck     Sbi->MaximumUserModeAddress = (ULONG_PTR)MmHighestUserAddress;
640c2c66affSColin Finck     Sbi->ActiveProcessorsAffinityMask = KeActiveProcessors;
641c2c66affSColin Finck     Sbi->NumberOfProcessors = KeNumberProcessors;
642c2c66affSColin Finck 
643c2c66affSColin Finck     return STATUS_SUCCESS;
644c2c66affSColin Finck }
645c2c66affSColin Finck 
646c2c66affSColin Finck /* Class 1 - Processor Information */
QSI_DEF(SystemProcessorInformation)647c2c66affSColin Finck QSI_DEF(SystemProcessorInformation)
648c2c66affSColin Finck {
649c2c66affSColin Finck     PSYSTEM_PROCESSOR_INFORMATION Spi
650c2c66affSColin Finck         = (PSYSTEM_PROCESSOR_INFORMATION) Buffer;
651c2c66affSColin Finck 
652c2c66affSColin Finck     *ReqSize = sizeof(SYSTEM_PROCESSOR_INFORMATION);
653c2c66affSColin Finck 
654c2c66affSColin Finck     /* Check user buffer's size */
655c2c66affSColin Finck     if (Size < sizeof(SYSTEM_PROCESSOR_INFORMATION))
656c2c66affSColin Finck     {
657c2c66affSColin Finck         return STATUS_INFO_LENGTH_MISMATCH;
658c2c66affSColin Finck     }
659c2c66affSColin Finck     Spi->ProcessorArchitecture = KeProcessorArchitecture;
660c2c66affSColin Finck     Spi->ProcessorLevel = KeProcessorLevel;
661c2c66affSColin Finck     Spi->ProcessorRevision = KeProcessorRevision;
66235f30348SAlex Henrie #if (NTDDI_VERSION < NTDDI_WIN8)
663c2c66affSColin Finck     Spi->Reserved = 0;
66435f30348SAlex Henrie #else
66535f30348SAlex Henrie     Spi->MaximumProcessors = 0;
66635f30348SAlex Henrie #endif
667c2c66affSColin Finck     Spi->ProcessorFeatureBits = KeFeatureBits;
668c2c66affSColin Finck 
669c2c66affSColin Finck     DPRINT("Arch %u Level %u Rev 0x%x\n", Spi->ProcessorArchitecture,
670c2c66affSColin Finck         Spi->ProcessorLevel, Spi->ProcessorRevision);
671c2c66affSColin Finck 
672c2c66affSColin Finck     return STATUS_SUCCESS;
673c2c66affSColin Finck }
674c2c66affSColin Finck 
675c2c66affSColin Finck /* Class 2 - Performance Information */
QSI_DEF(SystemPerformanceInformation)676c2c66affSColin Finck QSI_DEF(SystemPerformanceInformation)
677c2c66affSColin Finck {
678e6323758SPierre Schweitzer     LONG i;
679c2c66affSColin Finck     ULONG IdleUser, IdleKernel;
680e6323758SPierre Schweitzer     PKPRCB Prcb;
681c2c66affSColin Finck     PSYSTEM_PERFORMANCE_INFORMATION Spi
682c2c66affSColin Finck         = (PSYSTEM_PERFORMANCE_INFORMATION) Buffer;
683c2c66affSColin Finck 
684c2c66affSColin Finck     PEPROCESS TheIdleProcess;
685c2c66affSColin Finck 
686c2c66affSColin Finck     *ReqSize = sizeof(SYSTEM_PERFORMANCE_INFORMATION);
687c2c66affSColin Finck 
688c2c66affSColin Finck     /* Check user buffer's size */
689c2c66affSColin Finck     if (Size < sizeof(SYSTEM_PERFORMANCE_INFORMATION))
690c2c66affSColin Finck     {
691c2c66affSColin Finck         return STATUS_INFO_LENGTH_MISMATCH;
692c2c66affSColin Finck     }
693c2c66affSColin Finck 
694c2c66affSColin Finck     TheIdleProcess = PsIdleProcess;
695c2c66affSColin Finck 
696c2c66affSColin Finck     IdleKernel = KeQueryRuntimeProcess(&TheIdleProcess->Pcb, &IdleUser);
697c2c66affSColin Finck     Spi->IdleProcessTime.QuadPart = UInt32x32To64(IdleKernel, KeMaximumIncrement);
698c2c66affSColin Finck     Spi->IoReadTransferCount = IoReadTransferCount;
699c2c66affSColin Finck     Spi->IoWriteTransferCount = IoWriteTransferCount;
700c2c66affSColin Finck     Spi->IoOtherTransferCount = IoOtherTransferCount;
701c2c66affSColin Finck     Spi->IoReadOperationCount = IoReadOperationCount;
702c2c66affSColin Finck     Spi->IoWriteOperationCount = IoWriteOperationCount;
703c2c66affSColin Finck     Spi->IoOtherOperationCount = IoOtherOperationCount;
70413d9d3ebSPierre Schweitzer     for (i = 0; i < KeNumberProcessors; i ++)
70513d9d3ebSPierre Schweitzer     {
70613d9d3ebSPierre Schweitzer         Prcb = KiProcessorBlock[i];
70713d9d3ebSPierre Schweitzer         if (Prcb)
70813d9d3ebSPierre Schweitzer         {
70913d9d3ebSPierre Schweitzer             Spi->IoReadTransferCount.QuadPart += Prcb->IoReadTransferCount.QuadPart;
71013d9d3ebSPierre Schweitzer             Spi->IoWriteTransferCount.QuadPart += Prcb->IoWriteTransferCount.QuadPart;
71113d9d3ebSPierre Schweitzer             Spi->IoOtherTransferCount.QuadPart += Prcb->IoOtherTransferCount.QuadPart;
71213d9d3ebSPierre Schweitzer             Spi->IoReadOperationCount += Prcb->IoReadOperationCount;
71313d9d3ebSPierre Schweitzer             Spi->IoWriteOperationCount += Prcb->IoWriteOperationCount;
71413d9d3ebSPierre Schweitzer             Spi->IoOtherOperationCount += Prcb->IoOtherOperationCount;
71513d9d3ebSPierre Schweitzer         }
71613d9d3ebSPierre Schweitzer     }
717c2c66affSColin Finck 
718c2c66affSColin Finck     Spi->AvailablePages = (ULONG)MmAvailablePages;
7193703bbd6SKyle Katarn 
7203703bbd6SKyle Katarn     Spi->CommittedPages = MmTotalCommittedPages;
721c2c66affSColin Finck     /*
722c2c66affSColin Finck      *  Add up the full system total + pagefile.
723c2c66affSColin Finck      *  All this make Taskmgr happy but not sure it is the right numbers.
724c2c66affSColin Finck      *  This too, fixes some of GlobalMemoryStatusEx numbers.
725c2c66affSColin Finck      */
726c2c66affSColin Finck     Spi->CommitLimit = MmNumberOfPhysicalPages + MiFreeSwapPages + MiUsedSwapPages;
727c2c66affSColin Finck 
7283703bbd6SKyle Katarn     Spi->PeakCommitment = MmPeakCommitment;
729c2c66affSColin Finck     Spi->PageFaultCount = 0; /* FIXME */
730c2c66affSColin Finck     Spi->CopyOnWriteCount = 0; /* FIXME */
731c2c66affSColin Finck     Spi->TransitionCount = 0; /* FIXME */
732c2c66affSColin Finck     Spi->CacheTransitionCount = 0; /* FIXME */
733c2c66affSColin Finck     Spi->DemandZeroCount = 0; /* FIXME */
734c2c66affSColin Finck     Spi->PageReadCount = 0; /* FIXME */
735c2c66affSColin Finck     Spi->PageReadIoCount = 0; /* FIXME */
736c2c66affSColin Finck     Spi->CacheReadCount = 0; /* FIXME */
737c2c66affSColin Finck     Spi->CacheIoCount = 0; /* FIXME */
738c2c66affSColin Finck     Spi->DirtyPagesWriteCount = 0; /* FIXME */
739c2c66affSColin Finck     Spi->DirtyWriteIoCount = 0; /* FIXME */
740c2c66affSColin Finck     Spi->MappedPagesWriteCount = 0; /* FIXME */
741c2c66affSColin Finck     Spi->MappedWriteIoCount = 0; /* FIXME */
742c2c66affSColin Finck 
743c2c66affSColin Finck     Spi->PagedPoolPages = 0;
744c2c66affSColin Finck     Spi->NonPagedPoolPages = 0;
745c2c66affSColin Finck     Spi->PagedPoolAllocs = 0;
746c2c66affSColin Finck     Spi->PagedPoolFrees = 0;
747c2c66affSColin Finck     Spi->PagedPoolLookasideHits = 0;
748c2c66affSColin Finck     Spi->NonPagedPoolAllocs = 0;
749c2c66affSColin Finck     Spi->NonPagedPoolFrees = 0;
750c2c66affSColin Finck     Spi->NonPagedPoolLookasideHits = 0;
751c2c66affSColin Finck     ExQueryPoolUsage(&Spi->PagedPoolPages,
752c2c66affSColin Finck                      &Spi->NonPagedPoolPages,
753c2c66affSColin Finck                      &Spi->PagedPoolAllocs,
754c2c66affSColin Finck                      &Spi->PagedPoolFrees,
755c2c66affSColin Finck                      &Spi->PagedPoolLookasideHits,
756c2c66affSColin Finck                      &Spi->NonPagedPoolAllocs,
757c2c66affSColin Finck                      &Spi->NonPagedPoolFrees,
758c2c66affSColin Finck                      &Spi->NonPagedPoolLookasideHits);
759c2c66affSColin Finck     Spi->FreeSystemPtes = 0; /* FIXME */
760c2c66affSColin Finck 
761c2c66affSColin Finck     Spi->ResidentSystemCodePage = 0; /* FIXME */
762c2c66affSColin Finck 
763c2c66affSColin Finck     Spi->TotalSystemDriverPages = 0; /* FIXME */
764c2c66affSColin Finck     Spi->Spare3Count = 0; /* FIXME */
765c2c66affSColin Finck 
7660699dcb5SJérôme Gardou     Spi->ResidentSystemCachePage = MiMemoryConsumers[MC_USER].PagesUsed; /* FIXME */
767c2c66affSColin Finck     Spi->ResidentPagedPoolPage = 0; /* FIXME */
768c2c66affSColin Finck 
769c2c66affSColin Finck     Spi->ResidentSystemDriverPage = 0; /* FIXME */
770c2c66affSColin Finck     Spi->CcFastReadNoWait = 0; /* FIXME */
771c2c66affSColin Finck     Spi->CcFastReadWait = 0; /* FIXME */
772c2c66affSColin Finck     Spi->CcFastReadResourceMiss = 0; /* FIXME */
773c2c66affSColin Finck     Spi->CcFastReadNotPossible = 0; /* FIXME */
774c2c66affSColin Finck 
775c2c66affSColin Finck     Spi->CcFastMdlReadNoWait = 0; /* FIXME */
776c2c66affSColin Finck     Spi->CcFastMdlReadWait = 0; /* FIXME */
777c2c66affSColin Finck     Spi->CcFastMdlReadResourceMiss = 0; /* FIXME */
778c2c66affSColin Finck     Spi->CcFastMdlReadNotPossible = 0; /* FIXME */
779c2c66affSColin Finck 
78045964099SPierre Schweitzer     Spi->CcMapDataNoWait = CcMapDataNoWait;
78145964099SPierre Schweitzer     Spi->CcMapDataWait = CcMapDataWait;
782c2c66affSColin Finck     Spi->CcMapDataNoWaitMiss = 0; /* FIXME */
783c2c66affSColin Finck     Spi->CcMapDataWaitMiss = 0; /* FIXME */
784c2c66affSColin Finck 
7853d13a464SPierre Schweitzer     Spi->CcPinMappedDataCount = CcPinMappedDataCount;
7860fbdf317SPierre Schweitzer     Spi->CcPinReadNoWait = CcPinReadNoWait;
7870fbdf317SPierre Schweitzer     Spi->CcPinReadWait = CcPinReadWait;
788c2c66affSColin Finck     Spi->CcPinReadNoWaitMiss = 0; /* FIXME */
789c2c66affSColin Finck     Spi->CcPinReadWaitMiss = 0; /* FIXME */
790c2c66affSColin Finck     Spi->CcCopyReadNoWait = 0; /* FIXME */
791c2c66affSColin Finck     Spi->CcCopyReadWait = 0; /* FIXME */
792c2c66affSColin Finck     Spi->CcCopyReadNoWaitMiss = 0; /* FIXME */
793c2c66affSColin Finck     Spi->CcCopyReadWaitMiss = 0; /* FIXME */
794c2c66affSColin Finck 
795c2c66affSColin Finck     Spi->CcMdlReadNoWait = 0; /* FIXME */
796c2c66affSColin Finck     Spi->CcMdlReadWait = 0; /* FIXME */
797c2c66affSColin Finck     Spi->CcMdlReadNoWaitMiss = 0; /* FIXME */
798c2c66affSColin Finck     Spi->CcMdlReadWaitMiss = 0; /* FIXME */
799c2c66affSColin Finck     Spi->CcReadAheadIos = 0; /* FIXME */
80045964099SPierre Schweitzer     Spi->CcLazyWriteIos = CcLazyWriteIos;
80145964099SPierre Schweitzer     Spi->CcLazyWritePages = CcLazyWritePages;
8029ac2e985SPierre Schweitzer     Spi->CcDataFlushes = CcDataFlushes;
8039ac2e985SPierre Schweitzer     Spi->CcDataPages = CcDataPages;
804e6323758SPierre Schweitzer 
805e6323758SPierre Schweitzer     Spi->ContextSwitches = 0;
806e6323758SPierre Schweitzer     Spi->FirstLevelTbFills = 0;
807e6323758SPierre Schweitzer     Spi->SecondLevelTbFills = 0;
808e6323758SPierre Schweitzer     Spi->SystemCalls = 0;
809e6323758SPierre Schweitzer     for (i = 0; i < KeNumberProcessors; i ++)
810e6323758SPierre Schweitzer     {
811e6323758SPierre Schweitzer         Prcb = KiProcessorBlock[i];
812e6323758SPierre Schweitzer         if (Prcb)
813e6323758SPierre Schweitzer         {
814e6323758SPierre Schweitzer             Spi->ContextSwitches += KeGetContextSwitches(Prcb);
815e6323758SPierre Schweitzer             Spi->FirstLevelTbFills += Prcb->KeFirstLevelTbFills;
816e6323758SPierre Schweitzer             Spi->SecondLevelTbFills += Prcb->KeSecondLevelTbFills;
817e6323758SPierre Schweitzer             Spi->SystemCalls += Prcb->KeSystemCalls;
818e6323758SPierre Schweitzer         }
819e6323758SPierre Schweitzer     }
820e6323758SPierre Schweitzer 
821c2c66affSColin Finck     return STATUS_SUCCESS;
822c2c66affSColin Finck }
823c2c66affSColin Finck 
824c2c66affSColin Finck /* Class 3 - Time Of Day Information */
QSI_DEF(SystemTimeOfDayInformation)825c2c66affSColin Finck QSI_DEF(SystemTimeOfDayInformation)
826c2c66affSColin Finck {
827c2c66affSColin Finck     SYSTEM_TIMEOFDAY_INFORMATION Sti;
828c2c66affSColin Finck     LARGE_INTEGER CurrentTime;
829c2c66affSColin Finck 
830c2c66affSColin Finck     /* Set amount of written information to 0 */
831c2c66affSColin Finck     *ReqSize = 0;
832c2c66affSColin Finck 
833c2c66affSColin Finck     /* Check user buffer's size */
834c2c66affSColin Finck     if (Size > sizeof(SYSTEM_TIMEOFDAY_INFORMATION))
835c2c66affSColin Finck     {
836c2c66affSColin Finck         return STATUS_INFO_LENGTH_MISMATCH;
837c2c66affSColin Finck     }
838c2c66affSColin Finck 
839c2c66affSColin Finck     /* Get current time */
840c2c66affSColin Finck     KeQuerySystemTime(&CurrentTime);
841c2c66affSColin Finck 
842c2c66affSColin Finck     /* Zero local buffer */
843c2c66affSColin Finck     RtlZeroMemory(&Sti, sizeof(SYSTEM_TIMEOFDAY_INFORMATION));
844c2c66affSColin Finck 
845c2c66affSColin Finck     /* Fill local time structure */
846c2c66affSColin Finck     Sti.BootTime= KeBootTime;
847c2c66affSColin Finck     Sti.CurrentTime = CurrentTime;
848c2c66affSColin Finck     Sti.TimeZoneBias.QuadPart = ExpTimeZoneBias.QuadPart;
849c2c66affSColin Finck     Sti.TimeZoneId = ExpTimeZoneId;
850c2c66affSColin Finck     Sti.Reserved = 0;
851c2c66affSColin Finck 
852c2c66affSColin Finck     /* Copy as much as requested by caller */
853c2c66affSColin Finck     RtlCopyMemory(Buffer, &Sti, Size);
854c2c66affSColin Finck 
855c2c66affSColin Finck     /* Set amount of information we copied */
856c2c66affSColin Finck     *ReqSize = Size;
857c2c66affSColin Finck 
858c2c66affSColin Finck     return STATUS_SUCCESS;
859c2c66affSColin Finck }
860c2c66affSColin Finck 
861712f4696SHermès Bélusca-Maïto /* Class 4 - Path Information (DEPRECATED) */
QSI_DEF(SystemPathInformation)862c2c66affSColin Finck QSI_DEF(SystemPathInformation)
863c2c66affSColin Finck {
864712f4696SHermès Bélusca-Maïto     /*
865712f4696SHermès Bélusca-Maïto      * Since NT 3.51, this information class is trivially implemented.
866712f4696SHermès Bélusca-Maïto      * The path to the NT directory is now stored in KUSER_SHARED_DATA
867712f4696SHermès Bélusca-Maïto      * as the NtSystemRoot member.
868712f4696SHermès Bélusca-Maïto      * Windows Checked builds show the following message and break to
869712f4696SHermès Bélusca-Maïto      * the debugger before failing the function as not implemented.
870712f4696SHermès Bélusca-Maïto      */
871712f4696SHermès Bélusca-Maïto #if DBG
872712f4696SHermès Bélusca-Maïto     DPRINT1("EX: SystemPathInformation now available via SharedUserData\n");
873712f4696SHermès Bélusca-Maïto     // DbgBreakPoint(); // Not needed in ReactOS.
874712f4696SHermès Bélusca-Maïto #endif
875712f4696SHermès Bélusca-Maïto     return STATUS_NOT_IMPLEMENTED;
876c2c66affSColin Finck }
877c2c66affSColin Finck 
878c2c66affSColin Finck /* Class 5 - Process Information */
QSI_DEF(SystemProcessInformation)879c2c66affSColin Finck QSI_DEF(SystemProcessInformation)
880c2c66affSColin Finck {
881c2c66affSColin Finck     PSYSTEM_PROCESS_INFORMATION SpiCurrent;
882c2c66affSColin Finck     PSYSTEM_THREAD_INFORMATION ThreadInfo;
883c2c66affSColin Finck     PEPROCESS Process = NULL, SystemProcess;
884c2c66affSColin Finck     PETHREAD CurrentThread;
885c2c66affSColin Finck     ANSI_STRING ImageName;
886c2c66affSColin Finck     ULONG CurrentSize;
887c2c66affSColin Finck     USHORT ImageNameMaximumLength; // image name length in bytes
888c2c66affSColin Finck     USHORT ImageNameLength;
889c2c66affSColin Finck     PLIST_ENTRY CurrentEntry;
890c2c66affSColin Finck     ULONG TotalSize = 0, ThreadsCount;
891c2c66affSColin Finck     ULONG TotalUser, TotalKernel;
892c2c66affSColin Finck     PUCHAR Current;
893c2c66affSColin Finck     NTSTATUS Status = STATUS_SUCCESS;
894c2c66affSColin Finck     PUNICODE_STRING TempProcessImageName;
895c2c66affSColin Finck     _SEH2_VOLATILE PUNICODE_STRING ProcessImageName = NULL;
896c2c66affSColin Finck     PWCHAR szSrc;
897c2c66affSColin Finck     BOOLEAN Overflow = FALSE;
898c2c66affSColin Finck 
899c2c66affSColin Finck     _SEH2_TRY
900c2c66affSColin Finck     {
901c2c66affSColin Finck         /* scan the process list */
902c2c66affSColin Finck 
903c2c66affSColin Finck         PSYSTEM_PROCESS_INFORMATION Spi
904c2c66affSColin Finck             = (PSYSTEM_PROCESS_INFORMATION) Buffer;
905c2c66affSColin Finck 
906c2c66affSColin Finck         *ReqSize = sizeof(SYSTEM_PROCESS_INFORMATION);
907c2c66affSColin Finck 
908c2c66affSColin Finck         /* Check for overflow */
909c2c66affSColin Finck         if (Size < sizeof(SYSTEM_PROCESS_INFORMATION))
910c2c66affSColin Finck         {
911c2c66affSColin Finck             Overflow = TRUE;
912c2c66affSColin Finck         }
913c2c66affSColin Finck 
914c2c66affSColin Finck         /* Zero user's buffer */
915c2c66affSColin Finck         if (!Overflow) RtlZeroMemory(Spi, Size);
916c2c66affSColin Finck 
917c2c66affSColin Finck         SystemProcess = PsIdleProcess;
918c2c66affSColin Finck         Process = SystemProcess;
919c2c66affSColin Finck         Current = (PUCHAR) Spi;
920c2c66affSColin Finck 
921c2c66affSColin Finck         do
922c2c66affSColin Finck         {
923c2c66affSColin Finck             SpiCurrent = (PSYSTEM_PROCESS_INFORMATION) Current;
924c2c66affSColin Finck 
925c2c66affSColin Finck             /* Lock the Process */
926c2c66affSColin Finck             KeEnterCriticalRegion();
927c2c66affSColin Finck             ExAcquirePushLockShared(&Process->ProcessLock);
928c2c66affSColin Finck 
929c2c66affSColin Finck             if ((Process->ProcessExiting) &&
930c2c66affSColin Finck                 (Process->Pcb.Header.SignalState) &&
931c2c66affSColin Finck                 !(Process->ActiveThreads) &&
932c2c66affSColin Finck                 (IsListEmpty(&Process->Pcb.ThreadListHead)))
933c2c66affSColin Finck             {
934c2c66affSColin Finck                 DPRINT1("Process %p (%s:%p) is a zombie\n",
935c2c66affSColin Finck                         Process, Process->ImageFileName, Process->UniqueProcessId);
936c2c66affSColin Finck                 CurrentSize = 0;
937c2c66affSColin Finck                 ImageNameMaximumLength = 0;
938c2c66affSColin Finck 
939c2c66affSColin Finck                 /* Unlock the Process */
940c2c66affSColin Finck                 ExReleasePushLockShared(&Process->ProcessLock);
941c2c66affSColin Finck                 KeLeaveCriticalRegion();
942c2c66affSColin Finck                 goto Skip;
943c2c66affSColin Finck             }
944c2c66affSColin Finck 
945c2c66affSColin Finck             ThreadsCount = 0;
946c2c66affSColin Finck             CurrentEntry = Process->Pcb.ThreadListHead.Flink;
947c2c66affSColin Finck             while (CurrentEntry != &Process->Pcb.ThreadListHead)
948c2c66affSColin Finck             {
949c2c66affSColin Finck                 ThreadsCount++;
950c2c66affSColin Finck                 CurrentEntry = CurrentEntry->Flink;
951c2c66affSColin Finck             }
952c2c66affSColin Finck 
953c2c66affSColin Finck             // size of the structure for every process
954c2c66affSColin Finck             CurrentSize = sizeof(SYSTEM_PROCESS_INFORMATION) + sizeof(SYSTEM_THREAD_INFORMATION) * ThreadsCount;
955c2c66affSColin Finck             ImageNameLength = 0;
956c2c66affSColin Finck             Status = SeLocateProcessImageName(Process, &TempProcessImageName);
957c2c66affSColin Finck             ProcessImageName = TempProcessImageName;
958c2c66affSColin Finck             szSrc = NULL;
959c2c66affSColin Finck             if (NT_SUCCESS(Status) && (ProcessImageName->Length > 0))
960c2c66affSColin Finck             {
961c2c66affSColin Finck               szSrc = (PWCHAR)((PCHAR)ProcessImageName->Buffer + ProcessImageName->Length);
962c2c66affSColin Finck               /* Loop the file name*/
963c2c66affSColin Finck               while (szSrc > ProcessImageName->Buffer)
964c2c66affSColin Finck               {
965c2c66affSColin Finck                 /* Make sure this isn't a backslash */
966c2c66affSColin Finck                 if (*--szSrc == OBJ_NAME_PATH_SEPARATOR)
967c2c66affSColin Finck                 {
968c2c66affSColin Finck                     szSrc++;
969c2c66affSColin Finck                     break;
970c2c66affSColin Finck                 }
971c2c66affSColin Finck                 else
972c2c66affSColin Finck                 {
973c2c66affSColin Finck                     ImageNameLength += sizeof(WCHAR);
974c2c66affSColin Finck                 }
975c2c66affSColin Finck               }
976c2c66affSColin Finck             }
977c2c66affSColin Finck             if (!ImageNameLength && Process != PsIdleProcess)
978c2c66affSColin Finck             {
979c2c66affSColin Finck               ImageNameLength = (USHORT)strlen(Process->ImageFileName) * sizeof(WCHAR);
980c2c66affSColin Finck             }
981c2c66affSColin Finck 
982c2c66affSColin Finck             /* Round up the image name length as NT does */
983c2c66affSColin Finck             if (ImageNameLength > 0)
984c2c66affSColin Finck                 ImageNameMaximumLength = ROUND_UP(ImageNameLength + sizeof(WCHAR), 8);
985c2c66affSColin Finck             else
986c2c66affSColin Finck                 ImageNameMaximumLength = 0;
987c2c66affSColin Finck 
988c2c66affSColin Finck             TotalSize += CurrentSize + ImageNameMaximumLength;
989c2c66affSColin Finck 
990c2c66affSColin Finck             /* Check for overflow */
991c2c66affSColin Finck             if (TotalSize > Size)
992c2c66affSColin Finck             {
993c2c66affSColin Finck                 Overflow = TRUE;
994c2c66affSColin Finck             }
995c2c66affSColin Finck 
996c2c66affSColin Finck             /* Fill system information */
997c2c66affSColin Finck             if (!Overflow)
998c2c66affSColin Finck             {
999c2c66affSColin Finck                 SpiCurrent->NextEntryOffset = CurrentSize + ImageNameMaximumLength; // relative offset to the beginning of the next structure
1000c2c66affSColin Finck                 SpiCurrent->NumberOfThreads = ThreadsCount;
1001c2c66affSColin Finck                 SpiCurrent->CreateTime = Process->CreateTime;
1002c2c66affSColin Finck                 SpiCurrent->ImageName.Length = ImageNameLength;
1003c2c66affSColin Finck                 SpiCurrent->ImageName.MaximumLength = ImageNameMaximumLength;
1004c2c66affSColin Finck                 SpiCurrent->ImageName.Buffer = (void*)(Current + CurrentSize);
1005c2c66affSColin Finck 
1006c2c66affSColin Finck                 /* Copy name to the end of the struct */
1007c2c66affSColin Finck                 if(Process != PsIdleProcess)
1008c2c66affSColin Finck                 {
1009c2c66affSColin Finck                     if (szSrc)
1010c2c66affSColin Finck                     {
1011c2c66affSColin Finck                         RtlCopyMemory(SpiCurrent->ImageName.Buffer, szSrc, SpiCurrent->ImageName.Length);
1012c2c66affSColin Finck                     }
1013c2c66affSColin Finck                     else
1014c2c66affSColin Finck                     {
1015c2c66affSColin Finck                         RtlInitAnsiString(&ImageName, Process->ImageFileName);
101693c0d324SJérôme Gardou                         Status = RtlAnsiStringToUnicodeString(&SpiCurrent->ImageName, &ImageName, FALSE);
101793c0d324SJérôme Gardou                         if (!NT_SUCCESS(Status))
101893c0d324SJérôme Gardou                         {
101993c0d324SJérôme Gardou                             SpiCurrent->ImageName.Length = 0;
102093c0d324SJérôme Gardou                         }
1021c2c66affSColin Finck                     }
1022c2c66affSColin Finck                 }
1023c2c66affSColin Finck                 else
1024c2c66affSColin Finck                 {
1025c2c66affSColin Finck                     RtlInitUnicodeString(&SpiCurrent->ImageName, NULL);
1026c2c66affSColin Finck                 }
1027c2c66affSColin Finck 
1028c2c66affSColin Finck                 SpiCurrent->BasePriority = Process->Pcb.BasePriority;
1029c2c66affSColin Finck                 SpiCurrent->UniqueProcessId = Process->UniqueProcessId;
1030c2c66affSColin Finck                 SpiCurrent->InheritedFromUniqueProcessId = Process->InheritedFromUniqueProcessId;
10317ed0284eSKyle Katarn 
10327ed0284eSKyle Katarn                 /* PsIdleProcess shares its handle table with PsInitialSystemProcess,
10337ed0284eSKyle Katarn                  * so return the handle count for System only, not Idle one. */
10347ed0284eSKyle Katarn                 SpiCurrent->HandleCount = (Process == PsIdleProcess) ? 0 : ObGetProcessHandleCount(Process);
10357ed0284eSKyle Katarn 
1036c2c66affSColin Finck                 SpiCurrent->PeakVirtualSize = Process->PeakVirtualSize;
1037c2c66affSColin Finck                 SpiCurrent->VirtualSize = Process->VirtualSize;
1038c2c66affSColin Finck                 SpiCurrent->PageFaultCount = Process->Vm.PageFaultCount;
1039c2c66affSColin Finck                 SpiCurrent->PeakWorkingSetSize = Process->Vm.PeakWorkingSetSize;
1040c2c66affSColin Finck                 SpiCurrent->WorkingSetSize = Process->Vm.WorkingSetSize;
10416170b574SGeorge Bișoc                 SpiCurrent->QuotaPeakPagedPoolUsage = Process->QuotaPeak[PsPagedPool];
10426170b574SGeorge Bișoc                 SpiCurrent->QuotaPagedPoolUsage = Process->QuotaUsage[PsPagedPool];
10436170b574SGeorge Bișoc                 SpiCurrent->QuotaPeakNonPagedPoolUsage = Process->QuotaPeak[PsNonPagedPool];
10446170b574SGeorge Bișoc                 SpiCurrent->QuotaNonPagedPoolUsage = Process->QuotaUsage[PsNonPagedPool];
10456170b574SGeorge Bișoc                 SpiCurrent->PagefileUsage = Process->QuotaUsage[PsPageFile];
10466170b574SGeorge Bișoc                 SpiCurrent->PeakPagefileUsage = Process->QuotaPeak[PsPageFile];
1047c2c66affSColin Finck                 SpiCurrent->PrivatePageCount = Process->CommitCharge;
1048c2c66affSColin Finck                 ThreadInfo = (PSYSTEM_THREAD_INFORMATION)(SpiCurrent + 1);
1049c2c66affSColin Finck 
1050c2c66affSColin Finck                 CurrentEntry = Process->Pcb.ThreadListHead.Flink;
1051c2c66affSColin Finck                 while (CurrentEntry != &Process->Pcb.ThreadListHead)
1052c2c66affSColin Finck                 {
1053c2c66affSColin Finck                     CurrentThread = CONTAINING_RECORD(CurrentEntry, ETHREAD, Tcb.ThreadListEntry);
1054c2c66affSColin Finck 
1055c2c66affSColin Finck                     ThreadInfo->KernelTime.QuadPart = UInt32x32To64(CurrentThread->Tcb.KernelTime, KeMaximumIncrement);
1056c2c66affSColin Finck                     ThreadInfo->UserTime.QuadPart = UInt32x32To64(CurrentThread->Tcb.UserTime, KeMaximumIncrement);
1057c2c66affSColin Finck                     ThreadInfo->CreateTime.QuadPart = CurrentThread->CreateTime.QuadPart;
1058c2c66affSColin Finck                     ThreadInfo->WaitTime = CurrentThread->Tcb.WaitTime;
1059c2c66affSColin Finck                     ThreadInfo->StartAddress = (PVOID) CurrentThread->StartAddress;
1060c2c66affSColin Finck                     ThreadInfo->ClientId = CurrentThread->Cid;
1061c2c66affSColin Finck                     ThreadInfo->Priority = CurrentThread->Tcb.Priority;
1062c2c66affSColin Finck                     ThreadInfo->BasePriority = CurrentThread->Tcb.BasePriority;
1063c2c66affSColin Finck                     ThreadInfo->ContextSwitches = CurrentThread->Tcb.ContextSwitches;
1064c2c66affSColin Finck                     ThreadInfo->ThreadState = CurrentThread->Tcb.State;
1065c2c66affSColin Finck                     ThreadInfo->WaitReason = CurrentThread->Tcb.WaitReason;
1066c2c66affSColin Finck 
1067c2c66affSColin Finck                     ThreadInfo++;
1068c2c66affSColin Finck                     CurrentEntry = CurrentEntry->Flink;
1069c2c66affSColin Finck                 }
1070c2c66affSColin Finck 
1071c2c66affSColin Finck                 /* Query total user/kernel times of a process */
1072c2c66affSColin Finck                 TotalKernel = KeQueryRuntimeProcess(&Process->Pcb, &TotalUser);
1073c2c66affSColin Finck                 SpiCurrent->UserTime.QuadPart = UInt32x32To64(TotalUser, KeMaximumIncrement);
1074c2c66affSColin Finck                 SpiCurrent->KernelTime.QuadPart = UInt32x32To64(TotalKernel, KeMaximumIncrement);
1075c2c66affSColin Finck             }
1076c2c66affSColin Finck 
1077c2c66affSColin Finck             if (ProcessImageName)
1078c2c66affSColin Finck             {
1079c2c66affSColin Finck                 /* Release the memory allocated by SeLocateProcessImageName */
1080c2c66affSColin Finck                 ExFreePoolWithTag(ProcessImageName, TAG_SEPA);
1081c2c66affSColin Finck                 ProcessImageName = NULL;
1082c2c66affSColin Finck             }
1083c2c66affSColin Finck 
1084c2c66affSColin Finck             /* Unlock the Process */
1085c2c66affSColin Finck             ExReleasePushLockShared(&Process->ProcessLock);
1086c2c66affSColin Finck             KeLeaveCriticalRegion();
1087c2c66affSColin Finck 
1088c2c66affSColin Finck             /* Handle idle process entry */
1089c2c66affSColin Finck Skip:
1090c2c66affSColin Finck             if (Process == PsIdleProcess) Process = NULL;
1091c2c66affSColin Finck 
1092c2c66affSColin Finck             Process = PsGetNextProcess(Process);
1093c2c66affSColin Finck             ThreadsCount = 0;
1094c2c66affSColin Finck             if ((Process == SystemProcess) || (Process == NULL))
1095c2c66affSColin Finck             {
1096c2c66affSColin Finck                 if (!Overflow)
1097c2c66affSColin Finck                     SpiCurrent->NextEntryOffset = 0;
1098c2c66affSColin Finck                 break;
1099c2c66affSColin Finck             }
1100c2c66affSColin Finck             else
1101c2c66affSColin Finck                 Current += CurrentSize + ImageNameMaximumLength;
1102c2c66affSColin Finck           }  while ((Process != SystemProcess) && (Process != NULL));
1103c2c66affSColin Finck 
1104c2c66affSColin Finck           if(Process != NULL)
1105c2c66affSColin Finck             ObDereferenceObject(Process);
1106c2c66affSColin Finck           Status = STATUS_SUCCESS;
1107c2c66affSColin Finck     }
1108c2c66affSColin Finck     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1109c2c66affSColin Finck     {
1110c2c66affSColin Finck         if(Process != NULL)
1111c2c66affSColin Finck             ObDereferenceObject(Process);
1112c2c66affSColin Finck         if (ProcessImageName)
1113c2c66affSColin Finck         {
1114c2c66affSColin Finck             /* Release the memory allocated by SeLocateProcessImageName */
1115c2c66affSColin Finck             ExFreePoolWithTag(ProcessImageName, TAG_SEPA);
1116c2c66affSColin Finck         }
1117c2c66affSColin Finck 
1118c2c66affSColin Finck         Status = _SEH2_GetExceptionCode();
1119c2c66affSColin Finck     }
1120c2c66affSColin Finck     _SEH2_END
1121c2c66affSColin Finck 
1122c2c66affSColin Finck     if (Overflow)
1123c2c66affSColin Finck         Status = STATUS_INFO_LENGTH_MISMATCH;
1124c2c66affSColin Finck 
1125c2c66affSColin Finck     *ReqSize = TotalSize;
1126c2c66affSColin Finck     return Status;
1127c2c66affSColin Finck }
1128c2c66affSColin Finck 
1129c2c66affSColin Finck /* Class 6 - Call Count Information */
QSI_DEF(SystemCallCountInformation)1130c2c66affSColin Finck QSI_DEF(SystemCallCountInformation)
1131c2c66affSColin Finck {
1132c2c66affSColin Finck     /* FIXME */
1133c2c66affSColin Finck     DPRINT1("NtQuerySystemInformation - SystemCallCountInformation not implemented\n");
1134c2c66affSColin Finck     return STATUS_NOT_IMPLEMENTED;
1135c2c66affSColin Finck }
1136c2c66affSColin Finck 
1137c2c66affSColin Finck /* Class 7 - Device Information */
QSI_DEF(SystemDeviceInformation)1138c2c66affSColin Finck QSI_DEF(SystemDeviceInformation)
1139c2c66affSColin Finck {
1140c2c66affSColin Finck     PSYSTEM_DEVICE_INFORMATION Sdi
1141c2c66affSColin Finck         = (PSYSTEM_DEVICE_INFORMATION) Buffer;
1142c2c66affSColin Finck     PCONFIGURATION_INFORMATION ConfigInfo;
1143c2c66affSColin Finck 
1144c2c66affSColin Finck     *ReqSize = sizeof(SYSTEM_DEVICE_INFORMATION);
1145c2c66affSColin Finck 
1146c2c66affSColin Finck     /* Check user buffer's size */
1147c2c66affSColin Finck     if (Size < sizeof(SYSTEM_DEVICE_INFORMATION))
1148c2c66affSColin Finck     {
1149c2c66affSColin Finck         return STATUS_INFO_LENGTH_MISMATCH;
1150c2c66affSColin Finck     }
1151c2c66affSColin Finck 
1152c2c66affSColin Finck     ConfigInfo = IoGetConfigurationInformation();
1153c2c66affSColin Finck 
1154c2c66affSColin Finck     Sdi->NumberOfDisks = ConfigInfo->DiskCount;
1155c2c66affSColin Finck     Sdi->NumberOfFloppies = ConfigInfo->FloppyCount;
1156c2c66affSColin Finck     Sdi->NumberOfCdRoms = ConfigInfo->CdRomCount;
1157c2c66affSColin Finck     Sdi->NumberOfTapes = ConfigInfo->TapeCount;
1158c2c66affSColin Finck     Sdi->NumberOfSerialPorts = ConfigInfo->SerialCount;
1159c2c66affSColin Finck     Sdi->NumberOfParallelPorts = ConfigInfo->ParallelCount;
1160c2c66affSColin Finck 
1161c2c66affSColin Finck     return STATUS_SUCCESS;
1162c2c66affSColin Finck }
1163c2c66affSColin Finck 
1164c2c66affSColin Finck /* Class 8 - Processor Performance Information */
QSI_DEF(SystemProcessorPerformanceInformation)1165c2c66affSColin Finck QSI_DEF(SystemProcessorPerformanceInformation)
1166c2c66affSColin Finck {
1167c2c66affSColin Finck     PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION Spi
1168c2c66affSColin Finck         = (PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) Buffer;
1169c2c66affSColin Finck 
1170c2c66affSColin Finck     LONG i;
1171c2c66affSColin Finck     ULONG TotalTime;
1172c2c66affSColin Finck     PKPRCB Prcb;
1173c2c66affSColin Finck 
1174c2c66affSColin Finck     *ReqSize = KeNumberProcessors * sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION);
1175c2c66affSColin Finck 
1176c2c66affSColin Finck     /* Check user buffer's size */
1177c2c66affSColin Finck     if (Size < *ReqSize)
1178c2c66affSColin Finck     {
1179c2c66affSColin Finck         return STATUS_INFO_LENGTH_MISMATCH;
1180c2c66affSColin Finck     }
1181c2c66affSColin Finck 
1182c2c66affSColin Finck     for (i = 0; i < KeNumberProcessors; i++)
1183c2c66affSColin Finck     {
1184c2c66affSColin Finck         /* Get the PRCB on this processor */
1185c2c66affSColin Finck         Prcb = KiProcessorBlock[i];
1186c2c66affSColin Finck 
1187c2c66affSColin Finck         /* Calculate total user and kernel times */
1188c2c66affSColin Finck         TotalTime = Prcb->IdleThread->KernelTime + Prcb->IdleThread->UserTime;
1189c2c66affSColin Finck         Spi->IdleTime.QuadPart = UInt32x32To64(TotalTime, KeMaximumIncrement);
1190c2c66affSColin Finck         Spi->KernelTime.QuadPart =  UInt32x32To64(Prcb->KernelTime, KeMaximumIncrement);
1191c2c66affSColin Finck         Spi->UserTime.QuadPart = UInt32x32To64(Prcb->UserTime, KeMaximumIncrement);
1192c2c66affSColin Finck         Spi->DpcTime.QuadPart = UInt32x32To64(Prcb->DpcTime, KeMaximumIncrement);
1193c2c66affSColin Finck         Spi->InterruptTime.QuadPart = UInt32x32To64(Prcb->InterruptTime, KeMaximumIncrement);
1194c2c66affSColin Finck         Spi->InterruptCount = Prcb->InterruptCount;
1195c2c66affSColin Finck         Spi++;
1196c2c66affSColin Finck     }
1197c2c66affSColin Finck 
1198c2c66affSColin Finck     return STATUS_SUCCESS;
1199c2c66affSColin Finck }
1200c2c66affSColin Finck 
1201c2c66affSColin Finck /* Class 9 - Flags Information */
QSI_DEF(SystemFlagsInformation)1202c2c66affSColin Finck QSI_DEF(SystemFlagsInformation)
1203c2c66affSColin Finck {
1204c2c66affSColin Finck #if (NTDDI_VERSION >= NTDDI_VISTA)
1205c2c66affSColin Finck     *ReqSize = sizeof(SYSTEM_FLAGS_INFORMATION);
1206c2c66affSColin Finck #endif
1207c2c66affSColin Finck 
1208c2c66affSColin Finck     if (sizeof(SYSTEM_FLAGS_INFORMATION) != Size)
1209c2c66affSColin Finck     {
1210c2c66affSColin Finck         return STATUS_INFO_LENGTH_MISMATCH;
1211c2c66affSColin Finck     }
1212c2c66affSColin Finck 
1213c2c66affSColin Finck     ((PSYSTEM_FLAGS_INFORMATION) Buffer)->Flags = NtGlobalFlag;
1214c2c66affSColin Finck #if (NTDDI_VERSION < NTDDI_VISTA)
1215c2c66affSColin Finck     *ReqSize = sizeof(SYSTEM_FLAGS_INFORMATION);
1216c2c66affSColin Finck #endif
1217c2c66affSColin Finck 
1218c2c66affSColin Finck     return STATUS_SUCCESS;
1219c2c66affSColin Finck }
1220c2c66affSColin Finck 
SSI_DEF(SystemFlagsInformation)1221c2c66affSColin Finck SSI_DEF(SystemFlagsInformation)
1222c2c66affSColin Finck {
1223c2c66affSColin Finck     if (sizeof(SYSTEM_FLAGS_INFORMATION) != Size)
1224c2c66affSColin Finck     {
1225c2c66affSColin Finck         return STATUS_INFO_LENGTH_MISMATCH;
1226c2c66affSColin Finck     }
1227c2c66affSColin Finck 
1228c2c66affSColin Finck     if (!SeSinglePrivilegeCheck(SeDebugPrivilege, ExGetPreviousMode()))
1229c2c66affSColin Finck     {
12303e5dcf79SEric Kohl #if (NTDDI_VERSION < NTDDI_WIN7)
12313e5dcf79SEric Kohl         return STATUS_ACCESS_VIOLATION;
12323e5dcf79SEric Kohl #else
1233c2c66affSColin Finck         return STATUS_ACCESS_DENIED;
12343e5dcf79SEric Kohl #endif
1235c2c66affSColin Finck     }
1236c2c66affSColin Finck 
1237c2c66affSColin Finck     NtGlobalFlag = ((PSYSTEM_FLAGS_INFORMATION) Buffer)->Flags;
1238c2c66affSColin Finck     return STATUS_SUCCESS;
1239c2c66affSColin Finck }
1240c2c66affSColin Finck 
1241c2c66affSColin Finck /* Class 10 - Call Time Information */
QSI_DEF(SystemCallTimeInformation)1242c2c66affSColin Finck QSI_DEF(SystemCallTimeInformation)
1243c2c66affSColin Finck {
1244c2c66affSColin Finck     /* FIXME */
1245c2c66affSColin Finck     DPRINT1("NtQuerySystemInformation - SystemCallTimeInformation not implemented\n");
1246c2c66affSColin Finck     return STATUS_NOT_IMPLEMENTED;
1247c2c66affSColin Finck }
1248c2c66affSColin Finck 
1249c2c66affSColin Finck /* Class 11 - Module Information */
QSI_DEF(SystemModuleInformation)1250c2c66affSColin Finck QSI_DEF(SystemModuleInformation)
1251c2c66affSColin Finck {
1252c2c66affSColin Finck     NTSTATUS Status;
1253c2c66affSColin Finck 
1254c2c66affSColin Finck     /* Acquire system module list lock */
1255c2c66affSColin Finck     KeEnterCriticalRegion();
1256c2c66affSColin Finck     ExAcquireResourceExclusiveLite(&PsLoadedModuleResource, TRUE);
1257c2c66affSColin Finck 
1258c2c66affSColin Finck     /* Call the generic handler with the system module list */
1259c2c66affSColin Finck     Status = ExpQueryModuleInformation(&PsLoadedModuleList,
1260c2c66affSColin Finck                                        &MmLoadedUserImageList,
1261c2c66affSColin Finck                                        (PRTL_PROCESS_MODULES)Buffer,
1262c2c66affSColin Finck                                        Size,
1263c2c66affSColin Finck                                        ReqSize);
1264c2c66affSColin Finck 
1265c2c66affSColin Finck     /* Release list lock and return status */
1266c2c66affSColin Finck     ExReleaseResourceLite(&PsLoadedModuleResource);
1267c2c66affSColin Finck     KeLeaveCriticalRegion();
1268c2c66affSColin Finck     return Status;
1269c2c66affSColin Finck }
1270c2c66affSColin Finck 
1271c2c66affSColin Finck /* Class 12 - Locks Information */
QSI_DEF(SystemLocksInformation)1272c2c66affSColin Finck QSI_DEF(SystemLocksInformation)
1273c2c66affSColin Finck {
1274c2c66affSColin Finck     /* FIXME */
1275c2c66affSColin Finck     DPRINT1("NtQuerySystemInformation - SystemLocksInformation not implemented\n");
1276c2c66affSColin Finck     return STATUS_NOT_IMPLEMENTED;
1277c2c66affSColin Finck }
1278c2c66affSColin Finck 
1279c2c66affSColin Finck /* Class 13 - Stack Trace Information */
QSI_DEF(SystemStackTraceInformation)1280c2c66affSColin Finck QSI_DEF(SystemStackTraceInformation)
1281c2c66affSColin Finck {
1282c2c66affSColin Finck     /* FIXME */
1283c2c66affSColin Finck     DPRINT1("NtQuerySystemInformation - SystemStackTraceInformation not implemented\n");
1284c2c66affSColin Finck     return STATUS_NOT_IMPLEMENTED;
1285c2c66affSColin Finck }
1286c2c66affSColin Finck 
1287c2c66affSColin Finck /* Class 14 - Paged Pool Information */
QSI_DEF(SystemPagedPoolInformation)1288c2c66affSColin Finck QSI_DEF(SystemPagedPoolInformation)
1289c2c66affSColin Finck {
1290c2c66affSColin Finck     /* FIXME */
1291c2c66affSColin Finck     DPRINT1("NtQuerySystemInformation - SystemPagedPoolInformation not implemented\n");
1292c2c66affSColin Finck     return STATUS_NOT_IMPLEMENTED;
1293c2c66affSColin Finck }
1294c2c66affSColin Finck 
1295c2c66affSColin Finck /* Class 15 - Non Paged Pool Information */
QSI_DEF(SystemNonPagedPoolInformation)1296c2c66affSColin Finck QSI_DEF(SystemNonPagedPoolInformation)
1297c2c66affSColin Finck {
1298c2c66affSColin Finck     /* FIXME */
1299c2c66affSColin Finck     DPRINT1("NtQuerySystemInformation - SystemNonPagedPoolInformation not implemented\n");
1300c2c66affSColin Finck     return STATUS_NOT_IMPLEMENTED;
1301c2c66affSColin Finck }
1302c2c66affSColin Finck 
1303c2c66affSColin Finck /* Class 16 - Handle Information */
QSI_DEF(SystemHandleInformation)1304c2c66affSColin Finck QSI_DEF(SystemHandleInformation)
1305c2c66affSColin Finck {
1306c2c66affSColin Finck     PSYSTEM_HANDLE_INFORMATION HandleInformation;
1307c2c66affSColin Finck     PLIST_ENTRY NextTableEntry;
1308c2c66affSColin Finck     PHANDLE_TABLE HandleTable;
1309c2c66affSColin Finck     PHANDLE_TABLE_ENTRY HandleTableEntry;
1310c2c66affSColin Finck     EXHANDLE Handle;
1311c2c66affSColin Finck     ULONG Index = 0;
1312c2c66affSColin Finck     NTSTATUS Status;
1313c2c66affSColin Finck     PMDL Mdl;
1314c2c66affSColin Finck     PAGED_CODE();
1315c2c66affSColin Finck 
1316c2c66affSColin Finck     DPRINT("NtQuerySystemInformation - SystemHandleInformation\n");
1317c2c66affSColin Finck 
1318c2c66affSColin Finck     /* Set initial required buffer size */
1319c2c66affSColin Finck     *ReqSize = FIELD_OFFSET(SYSTEM_HANDLE_INFORMATION, Handles);
1320c2c66affSColin Finck 
1321c2c66affSColin Finck     /* Check user's buffer size */
1322c2c66affSColin Finck     if (Size < *ReqSize)
1323c2c66affSColin Finck     {
1324c2c66affSColin Finck         return STATUS_INFO_LENGTH_MISMATCH;
1325c2c66affSColin Finck     }
1326c2c66affSColin Finck 
1327c2c66affSColin Finck     /* We need to lock down the memory */
1328c2c66affSColin Finck     Status = ExLockUserBuffer(Buffer,
1329c2c66affSColin Finck                               Size,
1330c2c66affSColin Finck                               ExGetPreviousMode(),
1331c2c66affSColin Finck                               IoWriteAccess,
1332c2c66affSColin Finck                               (PVOID*)&HandleInformation,
1333c2c66affSColin Finck                               &Mdl);
1334c2c66affSColin Finck     if (!NT_SUCCESS(Status))
1335c2c66affSColin Finck     {
1336c2c66affSColin Finck         DPRINT1("Failed to lock the user buffer: 0x%lx\n", Status);
1337c2c66affSColin Finck         return Status;
1338c2c66affSColin Finck     }
1339c2c66affSColin Finck 
1340c2c66affSColin Finck     /* Reset of count of handles */
1341c2c66affSColin Finck     HandleInformation->NumberOfHandles = 0;
1342c2c66affSColin Finck 
1343c2c66affSColin Finck     /* Enter a critical region */
1344c2c66affSColin Finck     KeEnterCriticalRegion();
1345c2c66affSColin Finck 
1346c2c66affSColin Finck     /* Acquire the handle table lock */
1347c2c66affSColin Finck     ExAcquirePushLockShared(&HandleTableListLock);
1348c2c66affSColin Finck 
1349c2c66affSColin Finck     /* Enumerate all system handles */
1350c2c66affSColin Finck     for (NextTableEntry = HandleTableListHead.Flink;
1351c2c66affSColin Finck          NextTableEntry != &HandleTableListHead;
1352c2c66affSColin Finck          NextTableEntry = NextTableEntry->Flink)
1353c2c66affSColin Finck     {
1354c2c66affSColin Finck         /* Get current handle table */
1355c2c66affSColin Finck         HandleTable = CONTAINING_RECORD(NextTableEntry, HANDLE_TABLE, HandleTableList);
1356c2c66affSColin Finck 
1357c2c66affSColin Finck         /* Set the initial value and loop the entries */
1358c2c66affSColin Finck         Handle.Value = 0;
1359c2c66affSColin Finck         while ((HandleTableEntry = ExpLookupHandleTableEntry(HandleTable, Handle)))
1360c2c66affSColin Finck         {
1361c2c66affSColin Finck             /* Validate the entry */
1362c2c66affSColin Finck             if ((HandleTableEntry->Object) &&
1363c2c66affSColin Finck                 (HandleTableEntry->NextFreeTableEntry != -2))
1364c2c66affSColin Finck             {
1365c2c66affSColin Finck                 /* Increase of count of handles */
1366c2c66affSColin Finck                 ++HandleInformation->NumberOfHandles;
1367c2c66affSColin Finck 
1368c2c66affSColin Finck                 /* Lock the entry */
1369c2c66affSColin Finck                 if (ExpLockHandleTableEntry(HandleTable, HandleTableEntry))
1370c2c66affSColin Finck                 {
1371c2c66affSColin Finck                     /* Increase required buffer size */
1372c2c66affSColin Finck                     *ReqSize += sizeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO);
1373c2c66affSColin Finck 
1374c2c66affSColin Finck                     /* Check user's buffer size */
1375c2c66affSColin Finck                     if (*ReqSize > Size)
1376c2c66affSColin Finck                     {
1377c2c66affSColin Finck                         Status = STATUS_INFO_LENGTH_MISMATCH;
1378c2c66affSColin Finck                     }
1379c2c66affSColin Finck                     else
1380c2c66affSColin Finck                     {
1381c2c66affSColin Finck                         POBJECT_HEADER ObjectHeader = ObpGetHandleObject(HandleTableEntry);
1382c2c66affSColin Finck 
1383c2c66affSColin Finck                         /* Filling handle information */
1384c2c66affSColin Finck                         HandleInformation->Handles[Index].UniqueProcessId =
1385c2c66affSColin Finck                             (USHORT)(ULONG_PTR) HandleTable->UniqueProcessId;
1386c2c66affSColin Finck 
1387c2c66affSColin Finck                         HandleInformation->Handles[Index].CreatorBackTraceIndex = 0;
1388c2c66affSColin Finck 
1389*ffb20d33SRatin Gao #if 0 /* FIXME!!! Type field corrupted */
1390c2c66affSColin Finck                         HandleInformation->Handles[Index].ObjectTypeIndex =
1391c2c66affSColin Finck                             (UCHAR) ObjectHeader->Type->Index;
1392c2c66affSColin Finck #else
1393c2c66affSColin Finck                         HandleInformation->Handles[Index].ObjectTypeIndex = 0;
1394c2c66affSColin Finck #endif
1395c2c66affSColin Finck 
1396c2c66affSColin Finck                         HandleInformation->Handles[Index].HandleAttributes =
1397c2c66affSColin Finck                             HandleTableEntry->ObAttributes & OBJ_HANDLE_ATTRIBUTES;
1398c2c66affSColin Finck 
1399c2c66affSColin Finck                         HandleInformation->Handles[Index].HandleValue =
1400c2c66affSColin Finck                             (USHORT)(ULONG_PTR) Handle.GenericHandleOverlay;
1401c2c66affSColin Finck 
1402c2c66affSColin Finck                         HandleInformation->Handles[Index].Object = &ObjectHeader->Body;
1403c2c66affSColin Finck 
1404c2c66affSColin Finck                         HandleInformation->Handles[Index].GrantedAccess =
1405c2c66affSColin Finck                             HandleTableEntry->GrantedAccess;
1406c2c66affSColin Finck 
1407c2c66affSColin Finck                         ++Index;
1408c2c66affSColin Finck                     }
1409c2c66affSColin Finck 
1410c2c66affSColin Finck                     /* Unlock it */
1411c2c66affSColin Finck                     ExUnlockHandleTableEntry(HandleTable, HandleTableEntry);
1412c2c66affSColin Finck                 }
1413c2c66affSColin Finck             }
1414c2c66affSColin Finck 
1415c2c66affSColin Finck             /* Go to the next entry */
1416c2c66affSColin Finck             Handle.Value += sizeof(HANDLE);
1417c2c66affSColin Finck         }
1418c2c66affSColin Finck     }
1419c2c66affSColin Finck 
1420c2c66affSColin Finck     /* Release the lock */
1421c2c66affSColin Finck     ExReleasePushLockShared(&HandleTableListLock);
1422c2c66affSColin Finck 
1423c2c66affSColin Finck     /* Leave the critical region */
1424c2c66affSColin Finck     KeLeaveCriticalRegion();
1425c2c66affSColin Finck 
1426c2c66affSColin Finck     /* Release the locked user buffer */
1427c2c66affSColin Finck     ExUnlockUserBuffer(Mdl);
1428c2c66affSColin Finck 
1429c2c66affSColin Finck     return Status;
1430c2c66affSColin Finck }
1431c2c66affSColin Finck 
1432c2c66affSColin Finck /* Class 17 -  Information */
QSI_DEF(SystemObjectInformation)1433c2c66affSColin Finck QSI_DEF(SystemObjectInformation)
1434c2c66affSColin Finck {
1435c2c66affSColin Finck     /* FIXME */
1436c2c66affSColin Finck     DPRINT1("NtQuerySystemInformation - SystemObjectInformation not implemented\n");
1437c2c66affSColin Finck     return STATUS_NOT_IMPLEMENTED;
1438c2c66affSColin Finck }
1439c2c66affSColin Finck 
1440c2c66affSColin Finck /* Class 18 -  Information */
QSI_DEF(SystemPageFileInformation)1441c2c66affSColin Finck QSI_DEF(SystemPageFileInformation)
1442c2c66affSColin Finck {
1443c2c66affSColin Finck     UNICODE_STRING FileName; /* FIXME */
1444c2c66affSColin Finck     SYSTEM_PAGEFILE_INFORMATION *Spfi = (SYSTEM_PAGEFILE_INFORMATION *) Buffer;
1445c2c66affSColin Finck 
1446c2c66affSColin Finck     if (Size < sizeof(SYSTEM_PAGEFILE_INFORMATION))
1447c2c66affSColin Finck     {
1448c2c66affSColin Finck         * ReqSize = sizeof(SYSTEM_PAGEFILE_INFORMATION);
1449c2c66affSColin Finck         return STATUS_INFO_LENGTH_MISMATCH;
1450c2c66affSColin Finck     }
1451c2c66affSColin Finck 
1452c2c66affSColin Finck     RtlInitUnicodeString(&FileName, NULL); /* FIXME */
1453c2c66affSColin Finck 
1454c2c66affSColin Finck     /* FIXME */
1455c2c66affSColin Finck     Spfi->NextEntryOffset = 0;
1456c2c66affSColin Finck 
1457c2c66affSColin Finck     Spfi->TotalSize = MiFreeSwapPages + MiUsedSwapPages;
1458c2c66affSColin Finck     Spfi->TotalInUse = MiUsedSwapPages;
1459c2c66affSColin Finck     Spfi->PeakUsage = MiUsedSwapPages; /* FIXME */
1460c2c66affSColin Finck     Spfi->PageFileName = FileName;
1461c2c66affSColin Finck     return STATUS_SUCCESS;
1462c2c66affSColin Finck }
1463c2c66affSColin Finck 
1464c2c66affSColin Finck /* Class 19 - Vdm Instemul Information */
QSI_DEF(SystemVdmInstemulInformation)1465c2c66affSColin Finck QSI_DEF(SystemVdmInstemulInformation)
1466c2c66affSColin Finck {
1467c2c66affSColin Finck     /* FIXME */
1468c2c66affSColin Finck     DPRINT1("NtQuerySystemInformation - SystemVdmInstemulInformation not implemented\n");
1469c2c66affSColin Finck     return STATUS_NOT_IMPLEMENTED;
1470c2c66affSColin Finck }
1471c2c66affSColin Finck 
1472c2c66affSColin Finck /* Class 20 - Vdm Bop Information */
QSI_DEF(SystemVdmBopInformation)1473c2c66affSColin Finck QSI_DEF(SystemVdmBopInformation)
1474c2c66affSColin Finck {
1475c2c66affSColin Finck     /* FIXME */
1476c2c66affSColin Finck     DPRINT1("NtQuerySystemInformation - SystemVdmBopInformation not implemented\n");
1477c2c66affSColin Finck     return STATUS_NOT_IMPLEMENTED;
1478c2c66affSColin Finck }
1479c2c66affSColin Finck 
1480c2c66affSColin Finck /* Class 21 - File Cache Information */
QSI_DEF(SystemFileCacheInformation)1481c2c66affSColin Finck QSI_DEF(SystemFileCacheInformation)
1482c2c66affSColin Finck {
1483c2c66affSColin Finck     SYSTEM_FILECACHE_INFORMATION *Sci = (SYSTEM_FILECACHE_INFORMATION *) Buffer;
1484c2c66affSColin Finck 
1485c2c66affSColin Finck     *ReqSize = sizeof(SYSTEM_FILECACHE_INFORMATION);
1486c2c66affSColin Finck 
1487c2c66affSColin Finck     if (Size < *ReqSize)
1488c2c66affSColin Finck     {
1489c2c66affSColin Finck         return STATUS_INFO_LENGTH_MISMATCH;
1490c2c66affSColin Finck     }
1491c2c66affSColin Finck 
1492c2c66affSColin Finck     RtlZeroMemory(Sci, sizeof(SYSTEM_FILECACHE_INFORMATION));
1493c2c66affSColin Finck 
1494c2c66affSColin Finck     /* Return the Byte size not the page size. */
14950699dcb5SJérôme Gardou     Sci->CurrentSize = MiMemoryConsumers[MC_USER].PagesUsed; /* FIXME */
14960699dcb5SJérôme Gardou     Sci->PeakSize = MiMemoryConsumers[MC_USER].PagesUsed; /* FIXME */
1497c2c66affSColin Finck     /* Taskmgr multiplies this one by page size right away */
14980699dcb5SJérôme Gardou     Sci->CurrentSizeIncludingTransitionInPages = MiMemoryConsumers[MC_USER].PagesUsed; /* FIXME: Should be */
1499c2c66affSColin Finck     /* system working set and standby pages. */
1500c2c66affSColin Finck     Sci->PageFaultCount = 0; /* FIXME */
1501c2c66affSColin Finck     Sci->MinimumWorkingSet = 0; /* FIXME */
1502c2c66affSColin Finck     Sci->MaximumWorkingSet = 0; /* FIXME */
1503c2c66affSColin Finck 
1504c2c66affSColin Finck     return STATUS_SUCCESS;
1505c2c66affSColin Finck }
1506c2c66affSColin Finck 
SSI_DEF(SystemFileCacheInformation)1507c2c66affSColin Finck SSI_DEF(SystemFileCacheInformation)
1508c2c66affSColin Finck {
1509c2c66affSColin Finck     if (Size < sizeof(SYSTEM_FILECACHE_INFORMATION))
1510c2c66affSColin Finck     {
1511c2c66affSColin Finck         return STATUS_INFO_LENGTH_MISMATCH;
1512c2c66affSColin Finck     }
1513c2c66affSColin Finck     /* FIXME */
1514c2c66affSColin Finck     DPRINT1("NtSetSystemInformation - SystemFileCacheInformation not implemented\n");
1515c2c66affSColin Finck     return STATUS_NOT_IMPLEMENTED;
1516c2c66affSColin Finck }
1517c2c66affSColin Finck 
1518c2c66affSColin Finck /* Class 22 - Pool Tag Information */
QSI_DEF(SystemPoolTagInformation)1519c2c66affSColin Finck QSI_DEF(SystemPoolTagInformation)
1520c2c66affSColin Finck {
1521c2c66affSColin Finck     if (Size < sizeof(SYSTEM_POOLTAG_INFORMATION)) return STATUS_INFO_LENGTH_MISMATCH;
1522c2c66affSColin Finck     return ExGetPoolTagInfo(Buffer, Size, ReqSize);
1523c2c66affSColin Finck }
1524c2c66affSColin Finck 
1525c2c66affSColin Finck /* Class 23 - Interrupt Information for all processors */
QSI_DEF(SystemInterruptInformation)1526c2c66affSColin Finck QSI_DEF(SystemInterruptInformation)
1527c2c66affSColin Finck {
1528c2c66affSColin Finck     PKPRCB Prcb;
1529c2c66affSColin Finck     LONG i;
1530c2c66affSColin Finck     ULONG ti;
1531c2c66affSColin Finck     PSYSTEM_INTERRUPT_INFORMATION sii = (PSYSTEM_INTERRUPT_INFORMATION)Buffer;
1532c2c66affSColin Finck 
1533c2c66affSColin Finck     if(Size < KeNumberProcessors * sizeof(SYSTEM_INTERRUPT_INFORMATION))
1534c2c66affSColin Finck     {
1535c2c66affSColin Finck         return STATUS_INFO_LENGTH_MISMATCH;
1536c2c66affSColin Finck     }
1537c2c66affSColin Finck 
1538c2c66affSColin Finck     ti = KeQueryTimeIncrement();
1539c2c66affSColin Finck 
1540c2c66affSColin Finck     for (i = 0; i < KeNumberProcessors; i++)
1541c2c66affSColin Finck     {
1542c2c66affSColin Finck         Prcb = KiProcessorBlock[i];
1543c2c66affSColin Finck         sii->ContextSwitches = KeGetContextSwitches(Prcb);
1544c2c66affSColin Finck         sii->DpcCount = Prcb->DpcData[0].DpcCount;
1545c2c66affSColin Finck         sii->DpcRate = Prcb->DpcRequestRate;
1546c2c66affSColin Finck         sii->TimeIncrement = ti;
1547c2c66affSColin Finck         sii->DpcBypassCount = 0;
1548c2c66affSColin Finck         sii->ApcBypassCount = 0;
1549c2c66affSColin Finck         sii++;
1550c2c66affSColin Finck     }
1551c2c66affSColin Finck 
1552c2c66affSColin Finck     return STATUS_SUCCESS;
1553c2c66affSColin Finck }
1554c2c66affSColin Finck 
1555c2c66affSColin Finck /* Class 24 - DPC Behaviour Information */
QSI_DEF(SystemDpcBehaviourInformation)1556c2c66affSColin Finck QSI_DEF(SystemDpcBehaviourInformation)
1557c2c66affSColin Finck {
1558962b2fd6SPierre Schweitzer     PSYSTEM_DPC_BEHAVIOR_INFORMATION sdbi = (PSYSTEM_DPC_BEHAVIOR_INFORMATION)Buffer;
1559962b2fd6SPierre Schweitzer 
1560962b2fd6SPierre Schweitzer     if (Size < sizeof(SYSTEM_DPC_BEHAVIOR_INFORMATION))
1561962b2fd6SPierre Schweitzer     {
1562962b2fd6SPierre Schweitzer         return STATUS_INFO_LENGTH_MISMATCH;
1563962b2fd6SPierre Schweitzer     }
1564962b2fd6SPierre Schweitzer 
1565962b2fd6SPierre Schweitzer     sdbi->DpcQueueDepth = KiMaximumDpcQueueDepth;
1566962b2fd6SPierre Schweitzer     sdbi->MinimumDpcRate = KiMinimumDpcRate;
1567962b2fd6SPierre Schweitzer     sdbi->AdjustDpcThreshold = KiAdjustDpcThreshold;
1568962b2fd6SPierre Schweitzer     sdbi->IdealDpcRate = KiIdealDpcRate;
1569962b2fd6SPierre Schweitzer 
1570962b2fd6SPierre Schweitzer     return STATUS_SUCCESS;
1571c2c66affSColin Finck }
1572c2c66affSColin Finck 
SSI_DEF(SystemDpcBehaviourInformation)1573c2c66affSColin Finck SSI_DEF(SystemDpcBehaviourInformation)
1574c2c66affSColin Finck {
1575c2c66affSColin Finck     /* FIXME */
1576c2c66affSColin Finck     DPRINT1("NtSetSystemInformation - SystemDpcBehaviourInformation not implemented\n");
1577c2c66affSColin Finck     return STATUS_NOT_IMPLEMENTED;
1578c2c66affSColin Finck }
1579c2c66affSColin Finck 
1580c2c66affSColin Finck /* Class 25 - Full Memory Information */
QSI_DEF(SystemFullMemoryInformation)1581c2c66affSColin Finck QSI_DEF(SystemFullMemoryInformation)
1582c2c66affSColin Finck {
1583c2c66affSColin Finck     PULONG Spi = (PULONG) Buffer;
1584c2c66affSColin Finck 
1585c2c66affSColin Finck     PEPROCESS TheIdleProcess;
1586c2c66affSColin Finck 
1587c2c66affSColin Finck     *ReqSize = sizeof(ULONG);
1588c2c66affSColin Finck 
1589c2c66affSColin Finck     if (sizeof(ULONG) != Size)
1590c2c66affSColin Finck     {
1591c2c66affSColin Finck         return STATUS_INFO_LENGTH_MISMATCH;
1592c2c66affSColin Finck     }
1593c2c66affSColin Finck 
1594c2c66affSColin Finck     DPRINT("SystemFullMemoryInformation\n");
1595c2c66affSColin Finck 
1596c2c66affSColin Finck     TheIdleProcess = PsIdleProcess;
1597c2c66affSColin Finck 
1598c2c66affSColin Finck     DPRINT("PID: %p, KernelTime: %u PFFree: %lu PFUsed: %lu\n",
1599c2c66affSColin Finck            TheIdleProcess->UniqueProcessId,
1600c2c66affSColin Finck            TheIdleProcess->Pcb.KernelTime,
1601c2c66affSColin Finck            MiFreeSwapPages,
1602c2c66affSColin Finck            MiUsedSwapPages);
1603c2c66affSColin Finck 
1604c2c66affSColin Finck     *Spi = MiMemoryConsumers[MC_USER].PagesUsed;
1605c2c66affSColin Finck 
1606c2c66affSColin Finck     return STATUS_SUCCESS;
1607c2c66affSColin Finck }
1608c2c66affSColin Finck 
1609c2c66affSColin Finck /* Class 26 - Load Image */
SSI_DEF(SystemLoadGdiDriverInformation)1610c2c66affSColin Finck SSI_DEF(SystemLoadGdiDriverInformation)
1611c2c66affSColin Finck {
1612c2c66affSColin Finck     PSYSTEM_GDI_DRIVER_INFORMATION DriverInfo = (PVOID)Buffer;
1613c2c66affSColin Finck     UNICODE_STRING ImageName;
1614c2c66affSColin Finck     PVOID ImageBase;
1615c2c66affSColin Finck     PVOID SectionPointer;
1616c2c66affSColin Finck     ULONG_PTR EntryPoint;
1617c2c66affSColin Finck     NTSTATUS Status;
1618c2c66affSColin Finck     ULONG DirSize;
1619c2c66affSColin Finck     PIMAGE_NT_HEADERS NtHeader;
1620c2c66affSColin Finck 
1621c2c66affSColin Finck     /* Validate size */
1622c2c66affSColin Finck     if (Size != sizeof(SYSTEM_GDI_DRIVER_INFORMATION))
1623c2c66affSColin Finck     {
1624c2c66affSColin Finck         /* Incorrect buffer length, fail */
1625c2c66affSColin Finck         return STATUS_INFO_LENGTH_MISMATCH;
1626c2c66affSColin Finck     }
1627c2c66affSColin Finck 
1628c2c66affSColin Finck     /* Only kernel mode can call this function */
1629c2c66affSColin Finck     if (ExGetPreviousMode() != KernelMode) return STATUS_PRIVILEGE_NOT_HELD;
1630c2c66affSColin Finck 
1631c2c66affSColin Finck     /* Load the driver */
1632c2c66affSColin Finck     ImageName = DriverInfo->DriverName;
1633c2c66affSColin Finck     Status = MmLoadSystemImage(&ImageName,
1634c2c66affSColin Finck                                NULL,
1635c2c66affSColin Finck                                NULL,
1636c2c66affSColin Finck                                0,
1637c2c66affSColin Finck                                &SectionPointer,
1638c2c66affSColin Finck                                &ImageBase);
1639c2c66affSColin Finck     if (!NT_SUCCESS(Status)) return Status;
1640c2c66affSColin Finck 
1641c2c66affSColin Finck     /* Return the export pointer */
1642c2c66affSColin Finck     DriverInfo->ExportSectionPointer =
1643c2c66affSColin Finck         RtlImageDirectoryEntryToData(ImageBase,
1644c2c66affSColin Finck                                      TRUE,
1645c2c66affSColin Finck                                      IMAGE_DIRECTORY_ENTRY_EXPORT,
1646c2c66affSColin Finck                                      &DirSize);
1647c2c66affSColin Finck 
1648c2c66affSColin Finck     /* Get the entrypoint */
1649c2c66affSColin Finck     NtHeader = RtlImageNtHeader(ImageBase);
1650c2c66affSColin Finck     EntryPoint = NtHeader->OptionalHeader.AddressOfEntryPoint;
1651c2c66affSColin Finck     EntryPoint += (ULONG_PTR)ImageBase;
1652c2c66affSColin Finck 
1653c2c66affSColin Finck     /* Save other data */
1654c2c66affSColin Finck     DriverInfo->ImageAddress = ImageBase;
1655c2c66affSColin Finck     DriverInfo->SectionPointer = SectionPointer;
1656c2c66affSColin Finck     DriverInfo->EntryPoint = (PVOID)EntryPoint;
1657c2c66affSColin Finck     DriverInfo->ImageLength = NtHeader->OptionalHeader.SizeOfImage;
1658c2c66affSColin Finck 
1659c2c66affSColin Finck     /* All is good */
1660c2c66affSColin Finck     return STATUS_SUCCESS;
1661c2c66affSColin Finck }
1662c2c66affSColin Finck 
1663c2c66affSColin Finck /* Class 27 - Unload Image */
SSI_DEF(SystemUnloadGdiDriverInformation)1664c2c66affSColin Finck SSI_DEF(SystemUnloadGdiDriverInformation)
1665c2c66affSColin Finck {
1666c2c66affSColin Finck     PVOID *SectionPointer = Buffer;
1667c2c66affSColin Finck 
1668c2c66affSColin Finck     /* Validate size */
1669c2c66affSColin Finck     if (Size != sizeof(PVOID))
1670c2c66affSColin Finck     {
1671c2c66affSColin Finck         /* Incorrect length, fail */
1672c2c66affSColin Finck         return STATUS_INFO_LENGTH_MISMATCH;
1673c2c66affSColin Finck     }
1674c2c66affSColin Finck 
1675c2c66affSColin Finck     /* Only kernel mode can call this function */
1676c2c66affSColin Finck     if (ExGetPreviousMode() != KernelMode) return STATUS_PRIVILEGE_NOT_HELD;
1677c2c66affSColin Finck 
1678c2c66affSColin Finck     /* Unload the image */
1679c2c66affSColin Finck     MmUnloadSystemImage(*SectionPointer);
1680c2c66affSColin Finck     return STATUS_SUCCESS;
1681c2c66affSColin Finck }
1682c2c66affSColin Finck 
1683c2c66affSColin Finck /* Class 28 - Time Adjustment Information */
QSI_DEF(SystemTimeAdjustmentInformation)1684c2c66affSColin Finck QSI_DEF(SystemTimeAdjustmentInformation)
1685c2c66affSColin Finck {
1686c2c66affSColin Finck     PSYSTEM_QUERY_TIME_ADJUST_INFORMATION TimeInfo =
1687c2c66affSColin Finck         (PSYSTEM_QUERY_TIME_ADJUST_INFORMATION)Buffer;
1688c2c66affSColin Finck 
1689c2c66affSColin Finck     /* Check if enough storage was provided */
1690c2c66affSColin Finck     if (sizeof(SYSTEM_QUERY_TIME_ADJUST_INFORMATION) > Size)
1691c2c66affSColin Finck     {
1692c2c66affSColin Finck         * ReqSize = sizeof(SYSTEM_QUERY_TIME_ADJUST_INFORMATION);
1693c2c66affSColin Finck         return STATUS_INFO_LENGTH_MISMATCH;
1694c2c66affSColin Finck     }
1695c2c66affSColin Finck 
1696c2c66affSColin Finck     /* Give time values to our caller */
1697c2c66affSColin Finck     TimeInfo->TimeIncrement = KeMaximumIncrement;
1698c2c66affSColin Finck     TimeInfo->TimeAdjustment = KeTimeAdjustment;
1699c2c66affSColin Finck     TimeInfo->Enable = !KiTimeAdjustmentEnabled;
1700c2c66affSColin Finck 
1701c2c66affSColin Finck     return STATUS_SUCCESS;
1702c2c66affSColin Finck }
1703c2c66affSColin Finck 
SSI_DEF(SystemTimeAdjustmentInformation)1704c2c66affSColin Finck SSI_DEF(SystemTimeAdjustmentInformation)
1705c2c66affSColin Finck {
1706c2c66affSColin Finck     KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
1707c2c66affSColin Finck     PSYSTEM_SET_TIME_ADJUST_INFORMATION TimeInfo =
1708c2c66affSColin Finck         (PSYSTEM_SET_TIME_ADJUST_INFORMATION)Buffer;
1709c2c66affSColin Finck 
1710c2c66affSColin Finck     /* Check size of a buffer, it must match our expectations */
1711c2c66affSColin Finck     if (sizeof(SYSTEM_SET_TIME_ADJUST_INFORMATION) != Size)
1712c2c66affSColin Finck         return STATUS_INFO_LENGTH_MISMATCH;
1713c2c66affSColin Finck 
1714c2c66affSColin Finck     /* Check who is calling */
1715c2c66affSColin Finck     if (PreviousMode != KernelMode)
1716c2c66affSColin Finck     {
1717c2c66affSColin Finck         /* Check access rights */
1718c2c66affSColin Finck         if (!SeSinglePrivilegeCheck(SeSystemtimePrivilege, PreviousMode))
1719c2c66affSColin Finck         {
1720c2c66affSColin Finck             return STATUS_PRIVILEGE_NOT_HELD;
1721c2c66affSColin Finck         }
1722c2c66affSColin Finck     }
1723c2c66affSColin Finck 
1724c2c66affSColin Finck     /* FIXME: behaviour suggests the member be named 'Disable' */
1725c2c66affSColin Finck     if (TimeInfo->Enable)
1726c2c66affSColin Finck     {
1727c2c66affSColin Finck         /* Disable time adjustment and set default value */
1728c2c66affSColin Finck         KiTimeAdjustmentEnabled = FALSE;
1729c2c66affSColin Finck         KeTimeAdjustment = KeMaximumIncrement;
1730c2c66affSColin Finck     }
1731c2c66affSColin Finck     else
1732c2c66affSColin Finck     {
1733c2c66affSColin Finck         /* Check if a valid time adjustment value is given */
1734c2c66affSColin Finck         if (TimeInfo->TimeAdjustment == 0) return STATUS_INVALID_PARAMETER_2;
1735c2c66affSColin Finck 
1736c2c66affSColin Finck         /* Enable time adjustment and set the adjustment value */
1737c2c66affSColin Finck         KiTimeAdjustmentEnabled = TRUE;
1738c2c66affSColin Finck         KeTimeAdjustment = TimeInfo->TimeAdjustment;
1739c2c66affSColin Finck     }
1740c2c66affSColin Finck 
1741c2c66affSColin Finck     return STATUS_SUCCESS;
1742c2c66affSColin Finck }
1743c2c66affSColin Finck 
1744c2c66affSColin Finck /* Class 29 - Summary Memory Information */
QSI_DEF(SystemSummaryMemoryInformation)1745c2c66affSColin Finck QSI_DEF(SystemSummaryMemoryInformation)
1746c2c66affSColin Finck {
1747c2c66affSColin Finck     /* FIXME */
1748c2c66affSColin Finck     DPRINT1("NtQuerySystemInformation - SystemSummaryMemoryInformation not implemented\n");
1749c2c66affSColin Finck     return STATUS_NOT_IMPLEMENTED;
1750c2c66affSColin Finck }
1751c2c66affSColin Finck 
1752c2c66affSColin Finck /* Class 30 - Next Event Id Information */
QSI_DEF(SystemNextEventIdInformation)1753c2c66affSColin Finck QSI_DEF(SystemNextEventIdInformation)
1754c2c66affSColin Finck {
1755c2c66affSColin Finck     /* FIXME */
1756c2c66affSColin Finck     DPRINT1("NtQuerySystemInformation - SystemNextEventIdInformation not implemented\n");
1757c2c66affSColin Finck     return STATUS_NOT_IMPLEMENTED;
1758c2c66affSColin Finck }
1759c2c66affSColin Finck 
1760c2c66affSColin Finck /* Class 31 */
QSI_DEF(SystemPerformanceTraceInformation)1761c2c66affSColin Finck QSI_DEF(SystemPerformanceTraceInformation)
1762c2c66affSColin Finck {
1763c2c66affSColin Finck     /* FIXME */
1764c2c66affSColin Finck     DPRINT1("NtQuerySystemInformation - SystemPerformanceTraceInformation not implemented\n");
1765c2c66affSColin Finck     return STATUS_NOT_IMPLEMENTED;
1766c2c66affSColin Finck }
1767c2c66affSColin Finck 
1768c2c66affSColin Finck /* Class 32 - Crash Dump Information */
QSI_DEF(SystemCrashDumpInformation)1769c2c66affSColin Finck QSI_DEF(SystemCrashDumpInformation)
1770c2c66affSColin Finck {
1771c2c66affSColin Finck     /* FIXME */
1772c2c66affSColin Finck     DPRINT1("NtQuerySystemInformation - SystemCrashDumpInformation not implemented\n");
1773c2c66affSColin Finck     return STATUS_NOT_IMPLEMENTED;
1774c2c66affSColin Finck }
1775c2c66affSColin Finck 
1776c2c66affSColin Finck /* Class 33 - Exception Information */
QSI_DEF(SystemExceptionInformation)1777c2c66affSColin Finck QSI_DEF(SystemExceptionInformation)
1778c2c66affSColin Finck {
1779c2c66affSColin Finck     PSYSTEM_EXCEPTION_INFORMATION ExceptionInformation =
1780c2c66affSColin Finck         (PSYSTEM_EXCEPTION_INFORMATION)Buffer;
1781c2c66affSColin Finck     PKPRCB Prcb;
1782c2c66affSColin Finck     ULONG AlignmentFixupCount = 0, ExceptionDispatchCount = 0;
1783c2c66affSColin Finck     ULONG FloatingEmulationCount = 0, ByteWordEmulationCount = 0;
1784c2c66affSColin Finck     CHAR i;
1785c2c66affSColin Finck 
1786c2c66affSColin Finck     /* Check size of a buffer, it must match our expectations */
1787c2c66affSColin Finck     if (sizeof(SYSTEM_EXCEPTION_INFORMATION) != Size)
1788c2c66affSColin Finck         return STATUS_INFO_LENGTH_MISMATCH;
1789c2c66affSColin Finck 
1790c2c66affSColin Finck     /* Sum up exception count information from all processors */
1791c2c66affSColin Finck     for (i = 0; i < KeNumberProcessors; i++)
1792c2c66affSColin Finck     {
1793c2c66affSColin Finck         Prcb = KiProcessorBlock[i];
1794c2c66affSColin Finck         if (Prcb)
1795c2c66affSColin Finck         {
1796c2c66affSColin Finck             AlignmentFixupCount += Prcb->KeAlignmentFixupCount;
1797c2c66affSColin Finck             ExceptionDispatchCount += Prcb->KeExceptionDispatchCount;
1798c2c66affSColin Finck #ifndef _M_ARM
1799c2c66affSColin Finck             FloatingEmulationCount += Prcb->KeFloatingEmulationCount;
1800c2c66affSColin Finck #endif // _M_ARM
1801c2c66affSColin Finck         }
1802c2c66affSColin Finck     }
1803c2c66affSColin Finck 
1804c2c66affSColin Finck     /* Save information in user's buffer */
1805c2c66affSColin Finck     ExceptionInformation->AlignmentFixupCount = AlignmentFixupCount;
1806c2c66affSColin Finck     ExceptionInformation->ExceptionDispatchCount = ExceptionDispatchCount;
1807c2c66affSColin Finck     ExceptionInformation->FloatingEmulationCount = FloatingEmulationCount;
1808c2c66affSColin Finck     ExceptionInformation->ByteWordEmulationCount = ByteWordEmulationCount;
1809c2c66affSColin Finck 
1810c2c66affSColin Finck     return STATUS_SUCCESS;
1811c2c66affSColin Finck }
1812c2c66affSColin Finck 
1813c2c66affSColin Finck /* Class 34 - Crash Dump State Information */
QSI_DEF(SystemCrashDumpStateInformation)1814c2c66affSColin Finck QSI_DEF(SystemCrashDumpStateInformation)
1815c2c66affSColin Finck {
1816c2c66affSColin Finck     /* FIXME */
1817c2c66affSColin Finck     DPRINT1("NtQuerySystemInformation - SystemCrashDumpStateInformation not implemented\n");
1818c2c66affSColin Finck     return STATUS_NOT_IMPLEMENTED;
1819c2c66affSColin Finck }
1820c2c66affSColin Finck 
1821c2c66affSColin Finck /* Class 35 - Kernel Debugger Information */
QSI_DEF(SystemKernelDebuggerInformation)1822c2c66affSColin Finck QSI_DEF(SystemKernelDebuggerInformation)
1823c2c66affSColin Finck {
1824c2c66affSColin Finck     PSYSTEM_KERNEL_DEBUGGER_INFORMATION skdi = (PSYSTEM_KERNEL_DEBUGGER_INFORMATION) Buffer;
1825c2c66affSColin Finck 
1826c2c66affSColin Finck #if (NTDDI_VERSION >= NTDDI_VISTA)
1827c2c66affSColin Finck     *ReqSize = sizeof(SYSTEM_KERNEL_DEBUGGER_INFORMATION);
1828c2c66affSColin Finck #endif
1829c2c66affSColin Finck 
1830c2c66affSColin Finck     if (Size < sizeof(SYSTEM_KERNEL_DEBUGGER_INFORMATION))
1831c2c66affSColin Finck     {
1832c2c66affSColin Finck         return STATUS_INFO_LENGTH_MISMATCH;
1833c2c66affSColin Finck     }
1834c2c66affSColin Finck 
1835c2c66affSColin Finck     skdi->KernelDebuggerEnabled = KD_DEBUGGER_ENABLED;
1836c2c66affSColin Finck     skdi->KernelDebuggerNotPresent = KD_DEBUGGER_NOT_PRESENT;
1837c2c66affSColin Finck 
1838c2c66affSColin Finck #if (NTDDI_VERSION < NTDDI_VISTA)
1839c2c66affSColin Finck     *ReqSize = sizeof(SYSTEM_KERNEL_DEBUGGER_INFORMATION);
1840c2c66affSColin Finck #endif
1841c2c66affSColin Finck 
1842c2c66affSColin Finck     return STATUS_SUCCESS;
1843c2c66affSColin Finck }
1844c2c66affSColin Finck 
1845c2c66affSColin Finck /* Class 36 - Context Switch Information */
QSI_DEF(SystemContextSwitchInformation)1846c2c66affSColin Finck QSI_DEF(SystemContextSwitchInformation)
1847c2c66affSColin Finck {
1848c2c66affSColin Finck     PSYSTEM_CONTEXT_SWITCH_INFORMATION ContextSwitchInformation =
1849c2c66affSColin Finck         (PSYSTEM_CONTEXT_SWITCH_INFORMATION)Buffer;
1850c2c66affSColin Finck     ULONG ContextSwitches;
1851c2c66affSColin Finck     PKPRCB Prcb;
1852c2c66affSColin Finck     CHAR i;
1853c2c66affSColin Finck 
1854c2c66affSColin Finck     /* Check size of a buffer, it must match our expectations */
1855c2c66affSColin Finck     if (sizeof(SYSTEM_CONTEXT_SWITCH_INFORMATION) != Size)
1856c2c66affSColin Finck         return STATUS_INFO_LENGTH_MISMATCH;
1857c2c66affSColin Finck 
1858c2c66affSColin Finck     /* Calculate total value of context switches across all processors */
1859c2c66affSColin Finck     ContextSwitches = 0;
1860c2c66affSColin Finck     for (i = 0; i < KeNumberProcessors; i ++)
1861c2c66affSColin Finck     {
1862c2c66affSColin Finck         Prcb = KiProcessorBlock[i];
1863c2c66affSColin Finck         if (Prcb)
1864c2c66affSColin Finck         {
1865c2c66affSColin Finck             ContextSwitches += KeGetContextSwitches(Prcb);
1866c2c66affSColin Finck         }
1867c2c66affSColin Finck     }
1868c2c66affSColin Finck 
1869c2c66affSColin Finck     ContextSwitchInformation->ContextSwitches = ContextSwitches;
1870c2c66affSColin Finck 
1871c2c66affSColin Finck     /* FIXME */
1872c2c66affSColin Finck     ContextSwitchInformation->FindAny = 0;
1873c2c66affSColin Finck     ContextSwitchInformation->FindLast = 0;
1874c2c66affSColin Finck     ContextSwitchInformation->FindIdeal = 0;
1875c2c66affSColin Finck     ContextSwitchInformation->IdleAny = 0;
1876c2c66affSColin Finck     ContextSwitchInformation->IdleCurrent = 0;
1877c2c66affSColin Finck     ContextSwitchInformation->IdleLast = 0;
1878c2c66affSColin Finck     ContextSwitchInformation->IdleIdeal = 0;
1879c2c66affSColin Finck     ContextSwitchInformation->PreemptAny = 0;
1880c2c66affSColin Finck     ContextSwitchInformation->PreemptCurrent = 0;
1881c2c66affSColin Finck     ContextSwitchInformation->PreemptLast = 0;
1882c2c66affSColin Finck     ContextSwitchInformation->SwitchToIdle = 0;
1883c2c66affSColin Finck 
1884c2c66affSColin Finck     return STATUS_SUCCESS;
1885c2c66affSColin Finck }
1886c2c66affSColin Finck 
1887c2c66affSColin Finck /* Class 37 - Registry Quota Information */
QSI_DEF(SystemRegistryQuotaInformation)1888c2c66affSColin Finck QSI_DEF(SystemRegistryQuotaInformation)
1889c2c66affSColin Finck {
1890c2c66affSColin Finck     PSYSTEM_REGISTRY_QUOTA_INFORMATION srqi = (PSYSTEM_REGISTRY_QUOTA_INFORMATION) Buffer;
1891c2c66affSColin Finck 
1892c2c66affSColin Finck     *ReqSize = sizeof(SYSTEM_REGISTRY_QUOTA_INFORMATION);
1893c2c66affSColin Finck     if (Size < sizeof(SYSTEM_REGISTRY_QUOTA_INFORMATION))
1894c2c66affSColin Finck     {
1895c2c66affSColin Finck         return STATUS_INFO_LENGTH_MISMATCH;
1896c2c66affSColin Finck     }
1897c2c66affSColin Finck 
1898c2c66affSColin Finck     DPRINT1("Faking max registry size of 32 MB\n");
1899c2c66affSColin Finck     srqi->RegistryQuotaAllowed = 0x2000000;
1900c2c66affSColin Finck     srqi->RegistryQuotaUsed = 0x200000;
1901c2c66affSColin Finck     srqi->PagedPoolSize = 0x200000;
1902c2c66affSColin Finck 
1903c2c66affSColin Finck     return STATUS_SUCCESS;
1904c2c66affSColin Finck }
1905c2c66affSColin Finck 
SSI_DEF(SystemRegistryQuotaInformation)1906c2c66affSColin Finck SSI_DEF(SystemRegistryQuotaInformation)
1907c2c66affSColin Finck {
1908c2c66affSColin Finck     /* FIXME */
1909c2c66affSColin Finck     DPRINT1("NtSetSystemInformation - SystemRegistryQuotaInformation not implemented\n");
1910c2c66affSColin Finck     return STATUS_NOT_IMPLEMENTED;
1911c2c66affSColin Finck }
1912c2c66affSColin Finck 
1913c2c66affSColin Finck /* Class 38 - Load And Call Image */
SSI_DEF(SystemExtendServiceTableInformation)1914c2c66affSColin Finck SSI_DEF(SystemExtendServiceTableInformation)
1915c2c66affSColin Finck {
1916c2c66affSColin Finck     UNICODE_STRING ImageName;
1917c2c66affSColin Finck     KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
1918c2c66affSColin Finck     PLDR_DATA_TABLE_ENTRY ModuleObject;
1919c2c66affSColin Finck     NTSTATUS Status;
1920c2c66affSColin Finck     PIMAGE_NT_HEADERS NtHeader;
1921c2c66affSColin Finck     DRIVER_OBJECT Win32k;
1922c2c66affSColin Finck     PDRIVER_INITIALIZE DriverInit;
1923c2c66affSColin Finck     PVOID ImageBase;
1924c2c66affSColin Finck     ULONG_PTR EntryPoint;
1925c2c66affSColin Finck 
1926c2c66affSColin Finck     /* Validate the size */
1927c2c66affSColin Finck     if (Size != sizeof(UNICODE_STRING)) return STATUS_INFO_LENGTH_MISMATCH;
1928c2c66affSColin Finck 
1929c2c66affSColin Finck     /* Check who is calling */
1930c2c66affSColin Finck     if (PreviousMode != KernelMode)
1931c2c66affSColin Finck     {
1932c2c66affSColin Finck         static const UNICODE_STRING Win32kName =
1933c2c66affSColin Finck             RTL_CONSTANT_STRING(L"\\SystemRoot\\System32\\win32k.sys");
1934c2c66affSColin Finck 
1935c2c66affSColin Finck         /* Make sure we can load drivers */
1936c2c66affSColin Finck         if (!SeSinglePrivilegeCheck(SeLoadDriverPrivilege, UserMode))
1937c2c66affSColin Finck         {
1938c2c66affSColin Finck             /* FIXME: We can't, fail */
1939c2c66affSColin Finck             return STATUS_PRIVILEGE_NOT_HELD;
1940c2c66affSColin Finck         }
1941c2c66affSColin Finck 
1942c2c66affSColin Finck         _SEH2_TRY
1943c2c66affSColin Finck         {
1944c2c66affSColin Finck             /* Probe and copy the unicode string */
1945c2c66affSColin Finck             ProbeForRead(Buffer, sizeof(ImageName), 1);
1946c2c66affSColin Finck             ImageName = *(PUNICODE_STRING)Buffer;
1947c2c66affSColin Finck 
1948c2c66affSColin Finck             /* Probe the string buffer */
1949c2c66affSColin Finck             ProbeForRead(ImageName.Buffer, ImageName.Length, sizeof(WCHAR));
1950c2c66affSColin Finck 
1951c2c66affSColin Finck             /* Check if we have the correct name (nothing else is allowed!) */
1952c2c66affSColin Finck             if (!RtlEqualUnicodeString(&ImageName, &Win32kName, FALSE))
1953c2c66affSColin Finck             {
1954c2c66affSColin Finck                 _SEH2_YIELD(return STATUS_PRIVILEGE_NOT_HELD);
1955c2c66affSColin Finck             }
1956c2c66affSColin Finck         }
1957c2c66affSColin Finck         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1958c2c66affSColin Finck         {
1959c2c66affSColin Finck             _SEH2_YIELD(return _SEH2_GetExceptionCode());
1960c2c66affSColin Finck         }
1961c2c66affSColin Finck         _SEH2_END;
1962c2c66affSColin Finck 
1963c2c66affSColin Finck         /* Recursively call the function, so that we are from kernel mode */
1964c2c66affSColin Finck         return ZwSetSystemInformation(SystemExtendServiceTableInformation,
1965c2c66affSColin Finck                                       (PVOID)&Win32kName,
1966c2c66affSColin Finck                                       sizeof(Win32kName));
1967c2c66affSColin Finck     }
1968c2c66affSColin Finck 
1969c2c66affSColin Finck     /* Load the image */
1970c2c66affSColin Finck     Status = MmLoadSystemImage((PUNICODE_STRING)Buffer,
1971c2c66affSColin Finck                                NULL,
1972c2c66affSColin Finck                                NULL,
1973c2c66affSColin Finck                                0,
1974c2c66affSColin Finck                                (PVOID)&ModuleObject,
1975c2c66affSColin Finck                                &ImageBase);
1976c2c66affSColin Finck 
1977c2c66affSColin Finck     if (!NT_SUCCESS(Status)) return Status;
1978c2c66affSColin Finck 
1979c2c66affSColin Finck     /* Get the headers */
1980c2c66affSColin Finck     NtHeader = RtlImageNtHeader(ImageBase);
1981c2c66affSColin Finck     if (!NtHeader)
1982c2c66affSColin Finck     {
1983c2c66affSColin Finck         /* Fail */
1984c2c66affSColin Finck         MmUnloadSystemImage(ModuleObject);
1985c2c66affSColin Finck         return STATUS_INVALID_IMAGE_FORMAT;
1986c2c66affSColin Finck     }
1987c2c66affSColin Finck 
1988c2c66affSColin Finck     /* Get the entrypoint */
1989c2c66affSColin Finck     EntryPoint = NtHeader->OptionalHeader.AddressOfEntryPoint;
1990c2c66affSColin Finck     EntryPoint += (ULONG_PTR)ImageBase;
1991c2c66affSColin Finck     DriverInit = (PDRIVER_INITIALIZE)EntryPoint;
1992c2c66affSColin Finck 
1993c2c66affSColin Finck     /* Create a dummy device */
1994c2c66affSColin Finck     RtlZeroMemory(&Win32k, sizeof(Win32k));
1995c2c66affSColin Finck     ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
1996c2c66affSColin Finck     Win32k.DriverStart = ImageBase;
1997c2c66affSColin Finck 
1998c2c66affSColin Finck     /* Call it */
1999c2c66affSColin Finck     Status = (DriverInit)(&Win32k, NULL);
2000c2c66affSColin Finck     ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
2001c2c66affSColin Finck 
2002c2c66affSColin Finck     /* Unload if we failed */
2003c2c66affSColin Finck     if (!NT_SUCCESS(Status)) MmUnloadSystemImage(ModuleObject);
2004c2c66affSColin Finck     return Status;
2005c2c66affSColin Finck }
2006c2c66affSColin Finck 
2007c2c66affSColin Finck /* Class 39 - Priority Separation */
SSI_DEF(SystemPrioritySeperation)2008c2c66affSColin Finck SSI_DEF(SystemPrioritySeperation)
2009c2c66affSColin Finck {
2010c2c66affSColin Finck     /* Check if the size is correct */
2011c2c66affSColin Finck     if (Size != sizeof(ULONG))
2012c2c66affSColin Finck     {
2013c2c66affSColin Finck         return STATUS_INFO_LENGTH_MISMATCH;
2014c2c66affSColin Finck     }
2015c2c66affSColin Finck 
2016c2c66affSColin Finck     /* We need the TCB privilege */
2017c2c66affSColin Finck     if (!SeSinglePrivilegeCheck(SeTcbPrivilege, ExGetPreviousMode()))
2018c2c66affSColin Finck     {
2019c2c66affSColin Finck         return STATUS_PRIVILEGE_NOT_HELD;
2020c2c66affSColin Finck     }
2021c2c66affSColin Finck 
2022c2c66affSColin Finck     /* Modify the quantum table */
2023c2c66affSColin Finck     PsChangeQuantumTable(TRUE, *(PULONG)Buffer);
2024c2c66affSColin Finck 
2025c2c66affSColin Finck     return STATUS_SUCCESS;
2026c2c66affSColin Finck }
2027c2c66affSColin Finck 
2028c2c66affSColin Finck /* Class 40 */
QSI_DEF(SystemVerifierAddDriverInformation)2029c2c66affSColin Finck QSI_DEF(SystemVerifierAddDriverInformation)
2030c2c66affSColin Finck {
2031c2c66affSColin Finck     /* FIXME */
2032c2c66affSColin Finck     DPRINT1("NtQuerySystemInformation - SystemVerifierAddDriverInformation not implemented\n");
2033c2c66affSColin Finck     return STATUS_NOT_IMPLEMENTED;
2034c2c66affSColin Finck }
2035c2c66affSColin Finck 
2036c2c66affSColin Finck /* Class 41 */
QSI_DEF(SystemVerifierRemoveDriverInformation)2037c2c66affSColin Finck QSI_DEF(SystemVerifierRemoveDriverInformation)
2038c2c66affSColin Finck {
2039c2c66affSColin Finck     /* FIXME */
2040c2c66affSColin Finck     DPRINT1("NtQuerySystemInformation - SystemVerifierRemoveDriverInformation not implemented\n");
2041c2c66affSColin Finck     return STATUS_NOT_IMPLEMENTED;
2042c2c66affSColin Finck }
2043c2c66affSColin Finck 
2044c2c66affSColin Finck /* Class 42 - Power Information */
QSI_DEF(SystemProcessorIdleInformation)2045c2c66affSColin Finck QSI_DEF(SystemProcessorIdleInformation)
2046c2c66affSColin Finck {
2047c2c66affSColin Finck     *ReqSize = sizeof(PROCESSOR_POWER_INFORMATION) * KeNumberProcessors;
2048c2c66affSColin Finck 
2049c2c66affSColin Finck     if (sizeof(PROCESSOR_POWER_INFORMATION) * KeNumberProcessors > Size)
2050c2c66affSColin Finck     {
2051c2c66affSColin Finck         return STATUS_INFO_LENGTH_MISMATCH;
2052c2c66affSColin Finck     }
2053c2c66affSColin Finck 
2054c2c66affSColin Finck     /* FIXME */
2055c2c66affSColin Finck     DPRINT1("NtQuerySystemInformation - SystemPowerInformation not implemented\n");
2056c2c66affSColin Finck     return STATUS_NOT_IMPLEMENTED;
2057c2c66affSColin Finck }
2058c2c66affSColin Finck 
2059c2c66affSColin Finck /* Class 43 */
QSI_DEF(SystemLegacyDriverInformation)2060c2c66affSColin Finck QSI_DEF(SystemLegacyDriverInformation)
2061c2c66affSColin Finck {
2062c2c66affSColin Finck     /* FIXME */
2063c2c66affSColin Finck     DPRINT1("NtQuerySystemInformation - SystemLegacyDriverInformation not implemented\n");
2064c2c66affSColin Finck     return STATUS_NOT_IMPLEMENTED;
2065c2c66affSColin Finck }
2066c2c66affSColin Finck 
2067c2c66affSColin Finck /* Class 44 - Current Time Zone Information */
QSI_DEF(SystemCurrentTimeZoneInformation)2068c2c66affSColin Finck QSI_DEF(SystemCurrentTimeZoneInformation)
2069c2c66affSColin Finck {
207049113829SEric Kohl     *ReqSize = sizeof(RTL_TIME_ZONE_INFORMATION);
2071c2c66affSColin Finck 
207249113829SEric Kohl     if (sizeof(RTL_TIME_ZONE_INFORMATION) != Size)
2073c2c66affSColin Finck     {
2074c2c66affSColin Finck         return STATUS_INFO_LENGTH_MISMATCH;
2075c2c66affSColin Finck     }
2076c2c66affSColin Finck 
2077c2c66affSColin Finck     /* Copy the time zone information struct */
2078c2c66affSColin Finck     memcpy(Buffer,
2079c2c66affSColin Finck            &ExpTimeZoneInfo,
208049113829SEric Kohl            sizeof(RTL_TIME_ZONE_INFORMATION));
2081c2c66affSColin Finck 
2082c2c66affSColin Finck     return STATUS_SUCCESS;
2083c2c66affSColin Finck }
2084c2c66affSColin Finck 
SSI_DEF(SystemCurrentTimeZoneInformation)2085c2c66affSColin Finck SSI_DEF(SystemCurrentTimeZoneInformation)
2086c2c66affSColin Finck {
2087c2c66affSColin Finck     /* Check user buffer's size */
208849113829SEric Kohl     if (Size < sizeof(RTL_TIME_ZONE_INFORMATION))
2089c2c66affSColin Finck     {
2090c2c66affSColin Finck         return STATUS_INFO_LENGTH_MISMATCH;
2091c2c66affSColin Finck     }
2092c2c66affSColin Finck 
209349113829SEric Kohl     return ExpSetTimeZoneInformation((PRTL_TIME_ZONE_INFORMATION)Buffer);
2094c2c66affSColin Finck }
2095c2c66affSColin Finck 
2096c2c66affSColin Finck static
2097c2c66affSColin Finck VOID
ExpCopyLookasideInformation(PSYSTEM_LOOKASIDE_INFORMATION * InfoPointer,PULONG RemainingPointer,PLIST_ENTRY ListHead,BOOLEAN ListUsesMisses)2098c2c66affSColin Finck ExpCopyLookasideInformation(
2099c2c66affSColin Finck     PSYSTEM_LOOKASIDE_INFORMATION *InfoPointer,
2100c2c66affSColin Finck     PULONG RemainingPointer,
2101c2c66affSColin Finck     PLIST_ENTRY ListHead,
2102c2c66affSColin Finck     BOOLEAN ListUsesMisses)
2103c2c66affSColin Finck 
2104c2c66affSColin Finck {
2105c2c66affSColin Finck     PSYSTEM_LOOKASIDE_INFORMATION Info;
2106c2c66affSColin Finck     PGENERAL_LOOKASIDE LookasideList;
2107c2c66affSColin Finck     PLIST_ENTRY ListEntry;
2108c2c66affSColin Finck     ULONG Remaining;
2109c2c66affSColin Finck 
2110c2c66affSColin Finck     /* Get info pointer and remaining count of free array element */
2111c2c66affSColin Finck     Info = *InfoPointer;
2112c2c66affSColin Finck     Remaining = *RemainingPointer;
2113c2c66affSColin Finck 
2114c2c66affSColin Finck     /* Loop as long as we have lookaside lists and free array elements */
2115c2c66affSColin Finck     for (ListEntry = ListHead->Flink;
2116c2c66affSColin Finck          (ListEntry != ListHead) && (Remaining > 0);
2117c2c66affSColin Finck          ListEntry = ListEntry->Flink, Remaining--)
2118c2c66affSColin Finck     {
2119c2c66affSColin Finck         LookasideList = CONTAINING_RECORD(ListEntry, GENERAL_LOOKASIDE, ListEntry);
2120c2c66affSColin Finck 
2121c2c66affSColin Finck         /* Fill the next array element */
2122c2c66affSColin Finck         Info->CurrentDepth = LookasideList->Depth;
2123c2c66affSColin Finck         Info->MaximumDepth = LookasideList->MaximumDepth;
2124c2c66affSColin Finck         Info->TotalAllocates = LookasideList->TotalAllocates;
2125c2c66affSColin Finck         Info->TotalFrees = LookasideList->TotalFrees;
2126c2c66affSColin Finck         Info->Type = LookasideList->Type;
2127c2c66affSColin Finck         Info->Tag = LookasideList->Tag;
2128c2c66affSColin Finck         Info->Size = LookasideList->Size;
2129c2c66affSColin Finck 
2130c2c66affSColin Finck         /* Check how the lists track misses/hits */
2131c2c66affSColin Finck         if (ListUsesMisses)
2132c2c66affSColin Finck         {
2133c2c66affSColin Finck             /* Copy misses */
2134c2c66affSColin Finck             Info->AllocateMisses = LookasideList->AllocateMisses;
2135c2c66affSColin Finck             Info->FreeMisses = LookasideList->FreeMisses;
2136c2c66affSColin Finck         }
2137c2c66affSColin Finck         else
2138c2c66affSColin Finck         {
2139c2c66affSColin Finck             /* Calculate misses */
2140c2c66affSColin Finck             Info->AllocateMisses = LookasideList->TotalAllocates
2141c2c66affSColin Finck                                    - LookasideList->AllocateHits;
2142c2c66affSColin Finck             Info->FreeMisses = LookasideList->TotalFrees
2143c2c66affSColin Finck                                - LookasideList->FreeHits;
2144c2c66affSColin Finck         }
2145c2c66affSColin Finck     }
2146c2c66affSColin Finck 
2147c2c66affSColin Finck     /* Return the updated pointer and remaining count */
2148c2c66affSColin Finck     *InfoPointer = Info;
2149c2c66affSColin Finck     *RemainingPointer = Remaining;
2150c2c66affSColin Finck }
2151c2c66affSColin Finck 
2152c2c66affSColin Finck /* Class 45 - Lookaside Information */
QSI_DEF(SystemLookasideInformation)2153c2c66affSColin Finck QSI_DEF(SystemLookasideInformation)
2154c2c66affSColin Finck {
2155c2c66affSColin Finck     KPROCESSOR_MODE PreviousMode;
2156c2c66affSColin Finck     PSYSTEM_LOOKASIDE_INFORMATION Info;
2157c2c66affSColin Finck     PMDL Mdl;
2158c2c66affSColin Finck     ULONG MaxCount, Remaining;
2159c2c66affSColin Finck     KIRQL OldIrql;
2160c2c66affSColin Finck     NTSTATUS Status;
2161c2c66affSColin Finck 
2162c2c66affSColin Finck     /* First we need to lock down the memory, since we are going to access it
2163c2c66affSColin Finck        at high IRQL */
2164c2c66affSColin Finck     PreviousMode = ExGetPreviousMode();
2165c2c66affSColin Finck     Status = ExLockUserBuffer(Buffer,
2166c2c66affSColin Finck                               Size,
2167c2c66affSColin Finck                               PreviousMode,
2168c2c66affSColin Finck                               IoWriteAccess,
2169c2c66affSColin Finck                               (PVOID*)&Info,
2170c2c66affSColin Finck                               &Mdl);
2171c2c66affSColin Finck     if (!NT_SUCCESS(Status))
2172c2c66affSColin Finck     {
2173c2c66affSColin Finck         DPRINT1("Failed to lock the user buffer: 0x%lx\n", Status);
2174c2c66affSColin Finck         return Status;
2175c2c66affSColin Finck     }
2176c2c66affSColin Finck 
2177c2c66affSColin Finck     /* Calculate how many items we can store */
2178c2c66affSColin Finck     Remaining = MaxCount = Size / sizeof(SYSTEM_LOOKASIDE_INFORMATION);
2179c2c66affSColin Finck     if (Remaining == 0)
2180c2c66affSColin Finck     {
2181c2c66affSColin Finck         goto Leave;
2182c2c66affSColin Finck     }
2183c2c66affSColin Finck 
2184c2c66affSColin Finck     /* Copy info from pool lookaside lists */
2185c2c66affSColin Finck     ExpCopyLookasideInformation(&Info,
2186c2c66affSColin Finck                                 &Remaining,
2187c2c66affSColin Finck                                 &ExPoolLookasideListHead,
2188c2c66affSColin Finck                                 FALSE);
2189c2c66affSColin Finck     if (Remaining == 0)
2190c2c66affSColin Finck     {
2191c2c66affSColin Finck         goto Leave;
2192c2c66affSColin Finck     }
2193c2c66affSColin Finck 
2194c2c66affSColin Finck     /* Copy info from system lookaside lists */
2195c2c66affSColin Finck     ExpCopyLookasideInformation(&Info,
2196c2c66affSColin Finck                                 &Remaining,
2197c2c66affSColin Finck                                 &ExSystemLookasideListHead,
2198c2c66affSColin Finck                                 TRUE);
2199c2c66affSColin Finck     if (Remaining == 0)
2200c2c66affSColin Finck     {
2201c2c66affSColin Finck         goto Leave;
2202c2c66affSColin Finck     }
2203c2c66affSColin Finck 
2204c2c66affSColin Finck     /* Acquire spinlock for ExpNonPagedLookasideListHead */
2205c2c66affSColin Finck     KeAcquireSpinLock(&ExpNonPagedLookasideListLock, &OldIrql);
2206c2c66affSColin Finck 
2207c2c66affSColin Finck     /* Copy info from non-paged lookaside lists */
2208c2c66affSColin Finck     ExpCopyLookasideInformation(&Info,
2209c2c66affSColin Finck                                 &Remaining,
2210c2c66affSColin Finck                                 &ExpNonPagedLookasideListHead,
2211c2c66affSColin Finck                                 TRUE);
2212c2c66affSColin Finck 
2213c2c66affSColin Finck     /* Release spinlock for ExpNonPagedLookasideListHead */
2214c2c66affSColin Finck     KeReleaseSpinLock(&ExpNonPagedLookasideListLock, OldIrql);
2215c2c66affSColin Finck 
2216c2c66affSColin Finck     if (Remaining == 0)
2217c2c66affSColin Finck     {
2218c2c66affSColin Finck         goto Leave;
2219c2c66affSColin Finck     }
2220c2c66affSColin Finck 
2221c2c66affSColin Finck     /* Acquire spinlock for ExpPagedLookasideListHead */
2222c2c66affSColin Finck     KeAcquireSpinLock(&ExpPagedLookasideListLock, &OldIrql);
2223c2c66affSColin Finck 
2224c2c66affSColin Finck     /* Copy info from paged lookaside lists */
2225c2c66affSColin Finck     ExpCopyLookasideInformation(&Info,
2226c2c66affSColin Finck                                 &Remaining,
2227c2c66affSColin Finck                                 &ExpPagedLookasideListHead,
2228c2c66affSColin Finck                                 TRUE);
2229c2c66affSColin Finck 
2230c2c66affSColin Finck     /* Release spinlock for ExpPagedLookasideListHead */
2231c2c66affSColin Finck     KeReleaseSpinLock(&ExpPagedLookasideListLock, OldIrql);
2232c2c66affSColin Finck 
2233c2c66affSColin Finck Leave:
2234c2c66affSColin Finck 
2235c2c66affSColin Finck     /* Release the locked user buffer */
2236c2c66affSColin Finck     ExUnlockUserBuffer(Mdl);
2237c2c66affSColin Finck 
2238c2c66affSColin Finck     /* Return the size of the actually written data */
2239c2c66affSColin Finck     *ReqSize = (MaxCount - Remaining) * sizeof(SYSTEM_LOOKASIDE_INFORMATION);
2240c2c66affSColin Finck     return STATUS_SUCCESS;
2241c2c66affSColin Finck }
2242c2c66affSColin Finck 
2243c2c66affSColin Finck /* Class 46 - Set time slip event */
SSI_DEF(SystemTimeSlipNotification)2244c2c66affSColin Finck SSI_DEF(SystemTimeSlipNotification)
2245c2c66affSColin Finck {
2246c2c66affSColin Finck     /* FIXME */
2247c2c66affSColin Finck     DPRINT1("NtSetSystemInformation - SystemTimeSlipNotification not implemented\n");
2248c2c66affSColin Finck     return STATUS_NOT_IMPLEMENTED;
2249c2c66affSColin Finck }
2250c2c66affSColin Finck 
2251c2c66affSColin Finck NTSTATUS
2252c2c66affSColin Finck NTAPI
2253c2c66affSColin Finck MmSessionCreate(OUT PULONG SessionId);
2254c2c66affSColin Finck 
2255c2c66affSColin Finck NTSTATUS
2256c2c66affSColin Finck NTAPI
2257c2c66affSColin Finck MmSessionDelete(IN ULONG SessionId);
2258c2c66affSColin Finck 
2259c2c66affSColin Finck /* Class 47 - Create a new session (TSE) */
SSI_DEF(SystemSessionCreate)2260c2c66affSColin Finck SSI_DEF(SystemSessionCreate)
2261c2c66affSColin Finck {
2262c2c66affSColin Finck     ULONG SessionId;
2263c2c66affSColin Finck     KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
2264c2c66affSColin Finck     NTSTATUS Status;
2265c2c66affSColin Finck 
2266c2c66affSColin Finck     if (Size != sizeof(ULONG)) return STATUS_INFO_LENGTH_MISMATCH;
2267c2c66affSColin Finck 
2268c2c66affSColin Finck     if (PreviousMode != KernelMode)
2269c2c66affSColin Finck     {
2270c2c66affSColin Finck         if (!SeSinglePrivilegeCheck(SeLoadDriverPrivilege, PreviousMode))
2271c2c66affSColin Finck         {
2272c2c66affSColin Finck             return STATUS_PRIVILEGE_NOT_HELD;
2273c2c66affSColin Finck         }
2274c2c66affSColin Finck 
2275c2c66affSColin Finck         ProbeForWriteUlong(Buffer);
2276c2c66affSColin Finck     }
2277c2c66affSColin Finck 
2278c2c66affSColin Finck     Status = MmSessionCreate(&SessionId);
2279c2c66affSColin Finck     if (NT_SUCCESS(Status)) *(PULONG)Buffer = SessionId;
2280c2c66affSColin Finck 
2281c2c66affSColin Finck     return Status;
2282c2c66affSColin Finck }
2283c2c66affSColin Finck 
2284c2c66affSColin Finck /* Class 48 - Delete an existing session (TSE) */
SSI_DEF(SystemSessionDetach)2285c2c66affSColin Finck SSI_DEF(SystemSessionDetach)
2286c2c66affSColin Finck {
2287c2c66affSColin Finck     ULONG SessionId;
2288c2c66affSColin Finck     KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
2289c2c66affSColin Finck 
2290c2c66affSColin Finck     if (Size != sizeof(ULONG)) return STATUS_INFO_LENGTH_MISMATCH;
2291c2c66affSColin Finck 
2292c2c66affSColin Finck     if (PreviousMode != KernelMode)
2293c2c66affSColin Finck     {
2294c2c66affSColin Finck         if (!SeSinglePrivilegeCheck(SeLoadDriverPrivilege, PreviousMode))
2295c2c66affSColin Finck         {
2296c2c66affSColin Finck             return STATUS_PRIVILEGE_NOT_HELD;
2297c2c66affSColin Finck         }
2298c2c66affSColin Finck     }
2299c2c66affSColin Finck 
2300c2c66affSColin Finck     SessionId = *(PULONG)Buffer;
2301c2c66affSColin Finck 
2302c2c66affSColin Finck     return MmSessionDelete(SessionId);
2303c2c66affSColin Finck }
2304c2c66affSColin Finck 
2305c2c66affSColin Finck /* Class 49 - UNKNOWN */
QSI_DEF(SystemSessionInformation)2306c2c66affSColin Finck QSI_DEF(SystemSessionInformation)
2307c2c66affSColin Finck {
2308c2c66affSColin Finck     /* FIXME */
2309c2c66affSColin Finck     DPRINT1("NtQuerySystemInformation - SystemSessionInformation not implemented\n");
2310c2c66affSColin Finck     return STATUS_NOT_IMPLEMENTED;
2311c2c66affSColin Finck }
2312c2c66affSColin Finck 
2313c2c66affSColin Finck /* Class 50 - System range start address */
QSI_DEF(SystemRangeStartInformation)2314c2c66affSColin Finck QSI_DEF(SystemRangeStartInformation)
2315c2c66affSColin Finck {
2316c2c66affSColin Finck     /* Check user buffer's size */
2317c2c66affSColin Finck     if (Size != sizeof(ULONG_PTR)) return STATUS_INFO_LENGTH_MISMATCH;
2318c2c66affSColin Finck 
2319c2c66affSColin Finck     *(PULONG_PTR)Buffer = (ULONG_PTR)MmSystemRangeStart;
2320c2c66affSColin Finck 
2321c2c66affSColin Finck     if (ReqSize) *ReqSize = sizeof(ULONG_PTR);
2322c2c66affSColin Finck 
2323c2c66affSColin Finck     return STATUS_SUCCESS;
2324c2c66affSColin Finck }
2325c2c66affSColin Finck 
2326c2c66affSColin Finck /* Class 51 - Driver verifier information */
QSI_DEF(SystemVerifierInformation)2327c2c66affSColin Finck QSI_DEF(SystemVerifierInformation)
2328c2c66affSColin Finck {
2329c2c66affSColin Finck     /* FIXME */
2330c2c66affSColin Finck     DPRINT1("NtQuerySystemInformation - SystemVerifierInformation not implemented\n");
2331c2c66affSColin Finck     return STATUS_NOT_IMPLEMENTED;
2332c2c66affSColin Finck }
2333c2c66affSColin Finck 
SSI_DEF(SystemVerifierInformation)2334c2c66affSColin Finck SSI_DEF(SystemVerifierInformation)
2335c2c66affSColin Finck {
2336c2c66affSColin Finck     /* FIXME */
2337c2c66affSColin Finck     DPRINT1("NtSetSystemInformation - SystemVerifierInformation not implemented\n");
2338c2c66affSColin Finck     return STATUS_NOT_IMPLEMENTED;
2339c2c66affSColin Finck }
2340c2c66affSColin Finck 
2341c2c66affSColin Finck /* Class 52 */
SSI_DEF(SystemVerifierThunkExtend)2342c2c66affSColin Finck SSI_DEF(SystemVerifierThunkExtend)
2343c2c66affSColin Finck {
2344c2c66affSColin Finck     /* FIXME */
2345c2c66affSColin Finck     DPRINT1("NtSetSystemInformation - SystemVerifierThunkExtend not implemented\n");
2346c2c66affSColin Finck     return STATUS_NOT_IMPLEMENTED;
2347c2c66affSColin Finck }
2348c2c66affSColin Finck 
2349c2c66affSColin Finck /* Class 53 - A session's processes */
QSI_DEF(SystemSessionProcessesInformation)2350c2c66affSColin Finck QSI_DEF(SystemSessionProcessesInformation)
2351c2c66affSColin Finck {
2352c2c66affSColin Finck     /* FIXME */
2353c2c66affSColin Finck     DPRINT1("NtQuerySystemInformation - SystemSessionProcessInformation not implemented\n");
2354c2c66affSColin Finck     return STATUS_NOT_IMPLEMENTED;
2355c2c66affSColin Finck }
2356c2c66affSColin Finck 
2357c2c66affSColin Finck /* Class 54 - Load & map in system space */
SSI_DEF(SystemLoadGdiDriverInSystemSpaceInformation)2358c2c66affSColin Finck SSI_DEF(SystemLoadGdiDriverInSystemSpaceInformation)
2359c2c66affSColin Finck {
2360c2c66affSColin Finck     /* FIXME */
2361c2c66affSColin Finck     DPRINT1("NtSetSystemInformation - SystemLoadGdiDriverInSystemSpaceInformation not implemented\n");
2362c2c66affSColin Finck     return STATUS_NOT_IMPLEMENTED;
2363c2c66affSColin Finck }
2364c2c66affSColin Finck 
2365c2c66affSColin Finck /* Class 55 - NUMA processor information */
QSI_DEF(SystemNumaProcessorMap)2366c2c66affSColin Finck QSI_DEF(SystemNumaProcessorMap)
2367c2c66affSColin Finck {
2368c2c66affSColin Finck     ULONG MaxEntries, Node;
2369c2c66affSColin Finck     PSYSTEM_NUMA_INFORMATION NumaInformation = (PSYSTEM_NUMA_INFORMATION)Buffer;
2370c2c66affSColin Finck 
2371c2c66affSColin Finck     /* Validate input size */
2372c2c66affSColin Finck     if (Size < sizeof(ULONG))
2373c2c66affSColin Finck     {
2374c2c66affSColin Finck         return STATUS_INFO_LENGTH_MISMATCH;
2375c2c66affSColin Finck     }
2376c2c66affSColin Finck 
2377c2c66affSColin Finck     /* Return highest node */
2378c2c66affSColin Finck     NumaInformation->HighestNodeNumber = KeNumberNodes - 1;
2379c2c66affSColin Finck 
2380c2c66affSColin Finck     /* Compute how much entries we will be able to put in output structure */
2381c2c66affSColin Finck     MaxEntries = (Size - FIELD_OFFSET(SYSTEM_NUMA_INFORMATION, ActiveProcessorsAffinityMask)) / sizeof(ULONGLONG);
2382c2c66affSColin Finck     /* Make sure we don't overflow KeNodeBlock */
2383c2c66affSColin Finck     if (MaxEntries > KeNumberNodes)
2384c2c66affSColin Finck     {
2385c2c66affSColin Finck         MaxEntries = KeNumberNodes;
2386c2c66affSColin Finck     }
2387c2c66affSColin Finck 
2388c2c66affSColin Finck     /* If we have entries to write, and room for it */
2389c2c66affSColin Finck     if (Size >= FIELD_OFFSET(SYSTEM_NUMA_INFORMATION, ActiveProcessorsAffinityMask) &&
2390c2c66affSColin Finck         MaxEntries != 0)
2391c2c66affSColin Finck     {
2392c2c66affSColin Finck         /* Already set size we return */
2393c2c66affSColin Finck         *ReqSize = FIELD_OFFSET(SYSTEM_NUMA_INFORMATION, ActiveProcessorsAffinityMask) +
2394c2c66affSColin Finck                    MaxEntries * sizeof(ULONGLONG);
2395c2c66affSColin Finck 
2396c2c66affSColin Finck         /* For each node, return processor mask */
2397c2c66affSColin Finck         for (Node = 0; Node < MaxEntries; ++Node)
2398c2c66affSColin Finck         {
2399c2c66affSColin Finck             NumaInformation->ActiveProcessorsAffinityMask[Node] = KeNodeBlock[Node]->ProcessorMask;
2400c2c66affSColin Finck         }
2401c2c66affSColin Finck     }
2402c2c66affSColin Finck     else
2403c2c66affSColin Finck     {
2404c2c66affSColin Finck         /* We only returned highest node number */
2405c2c66affSColin Finck         *ReqSize = sizeof(ULONG);
2406c2c66affSColin Finck     }
2407c2c66affSColin Finck 
2408c2c66affSColin Finck     return STATUS_SUCCESS;
2409c2c66affSColin Finck }
2410c2c66affSColin Finck 
2411c2c66affSColin Finck /* Class 56 - Prefetcher information */
QSI_DEF(SystemPrefetcherInformation)2412c2c66affSColin Finck QSI_DEF(SystemPrefetcherInformation)
2413c2c66affSColin Finck {
2414c2c66affSColin Finck     /* FIXME */
2415c2c66affSColin Finck     DPRINT1("NtQuerySystemInformation - SystemPrefetcherInformation not implemented\n");
2416c2c66affSColin Finck     return STATUS_NOT_IMPLEMENTED;
2417c2c66affSColin Finck }
2418c2c66affSColin Finck 
2419c2c66affSColin Finck /* Class 57 - Extended process information */
QSI_DEF(SystemExtendedProcessInformation)2420c2c66affSColin Finck QSI_DEF(SystemExtendedProcessInformation)
2421c2c66affSColin Finck {
2422c2c66affSColin Finck     /* FIXME */
2423c2c66affSColin Finck     DPRINT1("NtQuerySystemInformation - SystemExtendedProcessInformation not implemented\n");
2424c2c66affSColin Finck     return STATUS_NOT_IMPLEMENTED;
2425c2c66affSColin Finck }
2426c2c66affSColin Finck 
24277692a620SHermès Bélusca-Maïto /* Class 58 - Recommended shared data alignment */
QSI_DEF(SystemRecommendedSharedDataAlignment)2428c2c66affSColin Finck QSI_DEF(SystemRecommendedSharedDataAlignment)
2429c2c66affSColin Finck {
2430c2c66affSColin Finck     /* FIXME */
2431c2c66affSColin Finck     DPRINT1("NtQuerySystemInformation - SystemRecommendedSharedDataAlignment not implemented\n");
2432c2c66affSColin Finck     return STATUS_NOT_IMPLEMENTED;
2433c2c66affSColin Finck }
2434c2c66affSColin Finck 
2435c2c66affSColin Finck /* Class 60 - NUMA memory information */
QSI_DEF(SystemNumaAvailableMemory)2436c2c66affSColin Finck QSI_DEF(SystemNumaAvailableMemory)
2437c2c66affSColin Finck {
2438c2c66affSColin Finck     ULONG MaxEntries, Node;
2439c2c66affSColin Finck     PSYSTEM_NUMA_INFORMATION NumaInformation = (PSYSTEM_NUMA_INFORMATION)Buffer;
2440c2c66affSColin Finck 
2441c2c66affSColin Finck     /* Validate input size */
2442c2c66affSColin Finck     if (Size < sizeof(ULONG))
2443c2c66affSColin Finck     {
2444c2c66affSColin Finck         return STATUS_INFO_LENGTH_MISMATCH;
2445c2c66affSColin Finck     }
2446c2c66affSColin Finck 
2447c2c66affSColin Finck     /* Return highest node */
2448c2c66affSColin Finck     NumaInformation->HighestNodeNumber = KeNumberNodes - 1;
2449c2c66affSColin Finck 
2450c2c66affSColin Finck     /* Compute how much entries we will be able to put in output structure */
2451c2c66affSColin Finck     MaxEntries = (Size - FIELD_OFFSET(SYSTEM_NUMA_INFORMATION, AvailableMemory)) / sizeof(ULONGLONG);
2452c2c66affSColin Finck     /* Make sure we don't overflow KeNodeBlock */
2453c2c66affSColin Finck     if (MaxEntries > KeNumberNodes)
2454c2c66affSColin Finck     {
2455c2c66affSColin Finck         MaxEntries = KeNumberNodes;
2456c2c66affSColin Finck     }
2457c2c66affSColin Finck 
2458c2c66affSColin Finck     /* If we have entries to write, and room for it */
2459c2c66affSColin Finck     if (Size >= FIELD_OFFSET(SYSTEM_NUMA_INFORMATION, AvailableMemory) &&
2460c2c66affSColin Finck         MaxEntries != 0)
2461c2c66affSColin Finck     {
2462c2c66affSColin Finck         /* Already set size we return */
2463c2c66affSColin Finck         *ReqSize = FIELD_OFFSET(SYSTEM_NUMA_INFORMATION, AvailableMemory) +
2464c2c66affSColin Finck                    MaxEntries * sizeof(ULONGLONG);
2465c2c66affSColin Finck 
2466c2c66affSColin Finck         /* If we have a single entry (us), directly return MM information */
2467c2c66affSColin Finck         if (MaxEntries == 1)
2468c2c66affSColin Finck         {
2469c2c66affSColin Finck             NumaInformation->AvailableMemory[0] = MmAvailablePages << PAGE_SHIFT;
2470c2c66affSColin Finck         }
2471c2c66affSColin Finck         else
2472c2c66affSColin Finck         {
2473c2c66affSColin Finck             /* Otherwise, for each node, return available bytes */
2474c2c66affSColin Finck             for (Node = 0; Node < MaxEntries; ++Node)
2475c2c66affSColin Finck             {
2476c2c66affSColin Finck                 NumaInformation->AvailableMemory[Node] = (KeNodeBlock[Node]->FreeCount[0] + KeNodeBlock[Node]->FreeCount[1]) << PAGE_SHIFT;
2477c2c66affSColin Finck             }
2478c2c66affSColin Finck         }
2479c2c66affSColin Finck     }
2480c2c66affSColin Finck     else
2481c2c66affSColin Finck     {
2482c2c66affSColin Finck         /* We only returned highest node number */
2483c2c66affSColin Finck         *ReqSize = sizeof(ULONG);
2484c2c66affSColin Finck     }
2485c2c66affSColin Finck 
2486c2c66affSColin Finck     return STATUS_SUCCESS;
2487c2c66affSColin Finck }
2488c2c66affSColin Finck 
2489c2c66affSColin Finck /* Class 64 - Extended handle information */
QSI_DEF(SystemExtendedHandleInformation)2490c2c66affSColin Finck QSI_DEF(SystemExtendedHandleInformation)
2491c2c66affSColin Finck {
2492c2c66affSColin Finck     PSYSTEM_HANDLE_INFORMATION_EX HandleInformation;
2493c2c66affSColin Finck     PLIST_ENTRY NextTableEntry;
2494c2c66affSColin Finck     PHANDLE_TABLE HandleTable;
2495c2c66affSColin Finck     PHANDLE_TABLE_ENTRY HandleTableEntry;
2496c2c66affSColin Finck     EXHANDLE Handle;
2497c2c66affSColin Finck     ULONG Index = 0;
2498c2c66affSColin Finck     NTSTATUS Status;
2499c2c66affSColin Finck     PMDL Mdl;
2500c2c66affSColin Finck     PAGED_CODE();
2501c2c66affSColin Finck 
2502c2c66affSColin Finck     DPRINT("NtQuerySystemInformation - SystemExtendedHandleInformation\n");
2503c2c66affSColin Finck 
2504c2c66affSColin Finck     /* Set initial required buffer size */
2505c2c66affSColin Finck     *ReqSize = FIELD_OFFSET(SYSTEM_HANDLE_INFORMATION_EX, Handle);
2506c2c66affSColin Finck 
2507c2c66affSColin Finck     /* Check user's buffer size */
2508c2c66affSColin Finck     if (Size < *ReqSize)
2509c2c66affSColin Finck     {
2510c2c66affSColin Finck         return STATUS_INFO_LENGTH_MISMATCH;
2511c2c66affSColin Finck     }
2512c2c66affSColin Finck 
2513c2c66affSColin Finck     /* We need to lock down the memory */
2514c2c66affSColin Finck     Status = ExLockUserBuffer(Buffer,
2515c2c66affSColin Finck                               Size,
2516c2c66affSColin Finck                               ExGetPreviousMode(),
2517c2c66affSColin Finck                               IoWriteAccess,
2518c2c66affSColin Finck                               (PVOID*)&HandleInformation,
2519c2c66affSColin Finck                               &Mdl);
2520c2c66affSColin Finck     if (!NT_SUCCESS(Status))
2521c2c66affSColin Finck     {
2522c2c66affSColin Finck         DPRINT1("Failed to lock the user buffer: 0x%lx\n", Status);
2523c2c66affSColin Finck         return Status;
2524c2c66affSColin Finck     }
2525c2c66affSColin Finck 
2526c2c66affSColin Finck     /* Reset of count of handles */
2527c2c66affSColin Finck     HandleInformation->Count = 0;
2528c2c66affSColin Finck 
2529c2c66affSColin Finck     /* Enter a critical region */
2530c2c66affSColin Finck     KeEnterCriticalRegion();
2531c2c66affSColin Finck 
2532c2c66affSColin Finck     /* Acquire the handle table lock */
2533c2c66affSColin Finck     ExAcquirePushLockShared(&HandleTableListLock);
2534c2c66affSColin Finck 
2535c2c66affSColin Finck     /* Enumerate all system handles */
2536c2c66affSColin Finck     for (NextTableEntry = HandleTableListHead.Flink;
2537c2c66affSColin Finck          NextTableEntry != &HandleTableListHead;
2538c2c66affSColin Finck          NextTableEntry = NextTableEntry->Flink)
2539c2c66affSColin Finck     {
2540c2c66affSColin Finck         /* Get current handle table */
2541c2c66affSColin Finck         HandleTable = CONTAINING_RECORD(NextTableEntry, HANDLE_TABLE, HandleTableList);
2542c2c66affSColin Finck 
2543c2c66affSColin Finck         /* Set the initial value and loop the entries */
2544c2c66affSColin Finck         Handle.Value = 0;
2545c2c66affSColin Finck         while ((HandleTableEntry = ExpLookupHandleTableEntry(HandleTable, Handle)))
2546c2c66affSColin Finck         {
2547c2c66affSColin Finck             /* Validate the entry */
2548c2c66affSColin Finck             if ((HandleTableEntry->Object) &&
2549c2c66affSColin Finck                 (HandleTableEntry->NextFreeTableEntry != -2))
2550c2c66affSColin Finck             {
2551c2c66affSColin Finck                 /* Increase of count of handles */
2552c2c66affSColin Finck                 ++HandleInformation->Count;
2553c2c66affSColin Finck 
2554c2c66affSColin Finck                 /* Lock the entry */
2555c2c66affSColin Finck                 if (ExpLockHandleTableEntry(HandleTable, HandleTableEntry))
2556c2c66affSColin Finck                 {
2557c2c66affSColin Finck                     /* Increase required buffer size */
2558c2c66affSColin Finck                     *ReqSize += sizeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX);
2559c2c66affSColin Finck 
2560c2c66affSColin Finck                     /* Check user's buffer size */
2561c2c66affSColin Finck                     if (*ReqSize > Size)
2562c2c66affSColin Finck                     {
2563c2c66affSColin Finck                         Status = STATUS_INFO_LENGTH_MISMATCH;
2564c2c66affSColin Finck                     }
2565c2c66affSColin Finck                     else
2566c2c66affSColin Finck                     {
2567c2c66affSColin Finck                         POBJECT_HEADER ObjectHeader = ObpGetHandleObject(HandleTableEntry);
2568c2c66affSColin Finck 
2569c2c66affSColin Finck                         /* Filling handle information */
2570c2c66affSColin Finck                         HandleInformation->Handle[Index].UniqueProcessId =
2571c2c66affSColin Finck                             (USHORT)(ULONG_PTR) HandleTable->UniqueProcessId;
2572c2c66affSColin Finck 
2573c2c66affSColin Finck                         HandleInformation->Handle[Index].CreatorBackTraceIndex = 0;
2574c2c66affSColin Finck 
2575*ffb20d33SRatin Gao #if 0 /* FIXME!!! Type field corrupted */
2576c2c66affSColin Finck                         HandleInformation->Handles[Index].ObjectTypeIndex =
2577c2c66affSColin Finck                             (UCHAR) ObjectHeader->Type->Index;
2578c2c66affSColin Finck #else
2579c2c66affSColin Finck                         HandleInformation->Handle[Index].ObjectTypeIndex = 0;
2580c2c66affSColin Finck #endif
2581c2c66affSColin Finck 
2582c2c66affSColin Finck                         HandleInformation->Handle[Index].HandleAttributes =
2583c2c66affSColin Finck                             HandleTableEntry->ObAttributes & OBJ_HANDLE_ATTRIBUTES;
2584c2c66affSColin Finck 
2585c2c66affSColin Finck                         HandleInformation->Handle[Index].HandleValue =
2586c2c66affSColin Finck                             (USHORT)(ULONG_PTR) Handle.GenericHandleOverlay;
2587c2c66affSColin Finck 
2588c2c66affSColin Finck                         HandleInformation->Handle[Index].Object = &ObjectHeader->Body;
2589c2c66affSColin Finck 
2590c2c66affSColin Finck                         HandleInformation->Handle[Index].GrantedAccess =
2591c2c66affSColin Finck                             HandleTableEntry->GrantedAccess;
2592c2c66affSColin Finck 
2593c2c66affSColin Finck                         HandleInformation->Handle[Index].Reserved = 0;
2594c2c66affSColin Finck 
2595c2c66affSColin Finck                         ++Index;
2596c2c66affSColin Finck                     }
2597c2c66affSColin Finck 
2598c2c66affSColin Finck                     /* Unlock it */
2599c2c66affSColin Finck                     ExUnlockHandleTableEntry(HandleTable, HandleTableEntry);
2600c2c66affSColin Finck                 }
2601c2c66affSColin Finck             }
2602c2c66affSColin Finck 
2603c2c66affSColin Finck             /* Go to the next entry */
2604c2c66affSColin Finck             Handle.Value += sizeof(HANDLE);
2605c2c66affSColin Finck         }
2606c2c66affSColin Finck     }
2607c2c66affSColin Finck 
2608c2c66affSColin Finck     /* Release the lock */
2609c2c66affSColin Finck     ExReleasePushLockShared(&HandleTableListLock);
2610c2c66affSColin Finck 
2611c2c66affSColin Finck     /* Leave the critical region */
2612c2c66affSColin Finck     KeLeaveCriticalRegion();
2613c2c66affSColin Finck 
2614c2c66affSColin Finck     /* Release the locked user buffer */
2615c2c66affSColin Finck     ExUnlockUserBuffer(Mdl);
2616c2c66affSColin Finck 
2617c2c66affSColin Finck     return Status;
2618c2c66affSColin Finck }
2619c2c66affSColin Finck 
2620f821e174SPierre Schweitzer /* Class 70 - System object security mode information */
QSI_DEF(SystemObjectSecurityMode)2621f821e174SPierre Schweitzer QSI_DEF(SystemObjectSecurityMode)
2622f821e174SPierre Schweitzer {
2623f821e174SPierre Schweitzer     PULONG ObjectSecurityInfo = (PULONG)Buffer;
2624f821e174SPierre Schweitzer 
2625f821e174SPierre Schweitzer     /* Validate input size */
2626f821e174SPierre Schweitzer     if (Size != sizeof(ULONG))
2627f821e174SPierre Schweitzer     {
2628f821e174SPierre Schweitzer         return STATUS_INFO_LENGTH_MISMATCH;
2629f821e174SPierre Schweitzer     }
2630f821e174SPierre Schweitzer 
2631f821e174SPierre Schweitzer     *ObjectSecurityInfo = ObpObjectSecurityMode;
2632f821e174SPierre Schweitzer 
2633f821e174SPierre Schweitzer     return STATUS_SUCCESS;
2634f821e174SPierre Schweitzer }
2635f821e174SPierre Schweitzer 
263696ee4509SPierre Schweitzer /* Class 73 - Logical processor information */
QSI_DEF(SystemLogicalProcessorInformation)263796ee4509SPierre Schweitzer QSI_DEF(SystemLogicalProcessorInformation)
263896ee4509SPierre Schweitzer {
263996ee4509SPierre Schweitzer     LONG i;
264096ee4509SPierre Schweitzer     PKPRCB Prcb;
264196ee4509SPierre Schweitzer     KAFFINITY CurrentProc;
264296ee4509SPierre Schweitzer     NTSTATUS Status = STATUS_SUCCESS;
264396ee4509SPierre Schweitzer     ULONG DataSize = 0, ProcessorFlags;
264496ee4509SPierre Schweitzer     PSYSTEM_LOGICAL_PROCESSOR_INFORMATION CurrentInfo;
264596ee4509SPierre Schweitzer 
264696ee4509SPierre Schweitzer     /* First, browse active processors, thanks to the map */
264796ee4509SPierre Schweitzer     i = 0;
264896ee4509SPierre Schweitzer     CurrentInfo = Buffer;
264996ee4509SPierre Schweitzer     CurrentProc = KeActiveProcessors;
265096ee4509SPierre Schweitzer     do
265196ee4509SPierre Schweitzer     {
265296ee4509SPierre Schweitzer         /* If current processor is active and is main in case of HT/MC, return it */
265396ee4509SPierre Schweitzer         Prcb = KiProcessorBlock[i];
265496ee4509SPierre Schweitzer         if ((CurrentProc & 1) &&
265596ee4509SPierre Schweitzer             Prcb == Prcb->MultiThreadSetMaster)
265696ee4509SPierre Schweitzer         {
265796ee4509SPierre Schweitzer             /* Assume processor can do HT or multicore */
265896ee4509SPierre Schweitzer             ProcessorFlags = 1;
265996ee4509SPierre Schweitzer 
266096ee4509SPierre Schweitzer             /* If set is the same for PRCB and multithread, then
266196ee4509SPierre Schweitzer              * actually, the processor is single core
266296ee4509SPierre Schweitzer              */
266396ee4509SPierre Schweitzer             if (Prcb->SetMember == Prcb->MultiThreadProcessorSet)
266496ee4509SPierre Schweitzer             {
266596ee4509SPierre Schweitzer                 ProcessorFlags = 0;
266696ee4509SPierre Schweitzer             }
266796ee4509SPierre Schweitzer 
266896ee4509SPierre Schweitzer             /* Check we have enough room to return */
266996ee4509SPierre Schweitzer             DataSize += sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION);
267096ee4509SPierre Schweitzer             if (DataSize > Size)
267196ee4509SPierre Schweitzer             {
267296ee4509SPierre Schweitzer                 Status = STATUS_INFO_LENGTH_MISMATCH;
267396ee4509SPierre Schweitzer             }
267496ee4509SPierre Schweitzer             else
267596ee4509SPierre Schweitzer             {
267696ee4509SPierre Schweitzer                 /* Zero output and return */
267796ee4509SPierre Schweitzer                 RtlZeroMemory(CurrentInfo, sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION));
267896ee4509SPierre Schweitzer                 CurrentInfo->ProcessorMask = Prcb->MultiThreadProcessorSet;
267996ee4509SPierre Schweitzer 
268096ee4509SPierre Schweitzer                 /* Processor core needs 1 if HT/MC is supported */
268196ee4509SPierre Schweitzer                 CurrentInfo->Relationship = RelationProcessorCore;
268296ee4509SPierre Schweitzer                 CurrentInfo->ProcessorCore.Flags = ProcessorFlags;
268396ee4509SPierre Schweitzer                 ++CurrentInfo;
268496ee4509SPierre Schweitzer             }
268596ee4509SPierre Schweitzer         }
268696ee4509SPierre Schweitzer 
268796ee4509SPierre Schweitzer         /* Move to the next proc */
268896ee4509SPierre Schweitzer         CurrentProc >>= 1;
268996ee4509SPierre Schweitzer         ++i;
269096ee4509SPierre Schweitzer     /* Loop while there's someone in the bitmask */
269196ee4509SPierre Schweitzer     } while (CurrentProc != 0);
269296ee4509SPierre Schweitzer 
269396ee4509SPierre Schweitzer     /* Now, return the NUMA nodes */
269496ee4509SPierre Schweitzer     for (i = 0; i < KeNumberNodes; ++i)
269596ee4509SPierre Schweitzer     {
269696ee4509SPierre Schweitzer         /* Check we have enough room to return */
269796ee4509SPierre Schweitzer         DataSize += sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION);
269896ee4509SPierre Schweitzer         if (DataSize > Size)
269996ee4509SPierre Schweitzer         {
270096ee4509SPierre Schweitzer             Status = STATUS_INFO_LENGTH_MISMATCH;
270196ee4509SPierre Schweitzer         }
270296ee4509SPierre Schweitzer         else
270396ee4509SPierre Schweitzer         {
270496ee4509SPierre Schweitzer             /* Zero output and return */
270596ee4509SPierre Schweitzer             RtlZeroMemory(CurrentInfo, sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION));
270696ee4509SPierre Schweitzer             CurrentInfo->ProcessorMask = KeActiveProcessors;
270796ee4509SPierre Schweitzer 
270896ee4509SPierre Schweitzer             /* NUMA node needs its ID */
270996ee4509SPierre Schweitzer             CurrentInfo->Relationship = RelationNumaNode;
271096ee4509SPierre Schweitzer             CurrentInfo->NumaNode.NodeNumber = i;
271196ee4509SPierre Schweitzer             ++CurrentInfo;
271296ee4509SPierre Schweitzer         }
271396ee4509SPierre Schweitzer     }
271496ee4509SPierre Schweitzer 
271596ee4509SPierre Schweitzer     *ReqSize = DataSize;
271696ee4509SPierre Schweitzer 
271796ee4509SPierre Schweitzer     return Status;
271896ee4509SPierre Schweitzer }
271996ee4509SPierre Schweitzer 
2720d033fe9bSStanislav Motylkov /* Class 76 - System firmware table information */
QSI_DEF(SystemFirmwareTableInformation)2721d033fe9bSStanislav Motylkov QSI_DEF(SystemFirmwareTableInformation)
2722d033fe9bSStanislav Motylkov {
2723d033fe9bSStanislav Motylkov     PSYSTEM_FIRMWARE_TABLE_INFORMATION SysFirmwareInfo = (PSYSTEM_FIRMWARE_TABLE_INFORMATION)Buffer;
2724d033fe9bSStanislav Motylkov     NTSTATUS Status = STATUS_SUCCESS;
2725d033fe9bSStanislav Motylkov     ULONG InputBufSize;
2726d033fe9bSStanislav Motylkov     ULONG DataSize = 0;
2727d033fe9bSStanislav Motylkov     ULONG TableCount = 0;
2728d033fe9bSStanislav Motylkov 
2729d033fe9bSStanislav Motylkov     DPRINT("NtQuerySystemInformation - SystemFirmwareTableInformation\n");
2730d033fe9bSStanislav Motylkov 
2731d033fe9bSStanislav Motylkov     /* Set initial required buffer size */
2732d033fe9bSStanislav Motylkov     *ReqSize = FIELD_OFFSET(SYSTEM_FIRMWARE_TABLE_INFORMATION, TableBuffer);
2733d033fe9bSStanislav Motylkov 
2734d033fe9bSStanislav Motylkov     /* Check user's buffer size */
2735d033fe9bSStanislav Motylkov     if (Size < *ReqSize)
2736d033fe9bSStanislav Motylkov     {
2737d033fe9bSStanislav Motylkov         return STATUS_INFO_LENGTH_MISMATCH;
2738d033fe9bSStanislav Motylkov     }
2739d033fe9bSStanislav Motylkov 
2740d033fe9bSStanislav Motylkov     InputBufSize = SysFirmwareInfo->TableBufferLength;
2741d033fe9bSStanislav Motylkov     switch (SysFirmwareInfo->ProviderSignature)
2742d033fe9bSStanislav Motylkov     {
2743d033fe9bSStanislav Motylkov         /*
2744d033fe9bSStanislav Motylkov          * ExpFirmwareTableResource and ExpFirmwareTableProviderListHead
2745d033fe9bSStanislav Motylkov          * variables should be used there somehow...
2746d033fe9bSStanislav Motylkov          */
2747d033fe9bSStanislav Motylkov         case SIG_ACPI:
2748d033fe9bSStanislav Motylkov         {
2749d033fe9bSStanislav Motylkov             /* FIXME: Not implemented yet */
2750d033fe9bSStanislav Motylkov             DPRINT1("ACPI provider not implemented\n");
2751d033fe9bSStanislav Motylkov             Status = STATUS_NOT_IMPLEMENTED;
2752d033fe9bSStanislav Motylkov             break;
2753d033fe9bSStanislav Motylkov         }
2754d033fe9bSStanislav Motylkov         case SIG_FIRM:
2755d033fe9bSStanislav Motylkov         {
2756d033fe9bSStanislav Motylkov             /* FIXME: Not implemented yet */
2757d033fe9bSStanislav Motylkov             DPRINT1("FIRM provider not implemented\n");
2758d033fe9bSStanislav Motylkov             Status = STATUS_NOT_IMPLEMENTED;
2759d033fe9bSStanislav Motylkov             break;
2760d033fe9bSStanislav Motylkov         }
2761d033fe9bSStanislav Motylkov         case SIG_RSMB:
2762d033fe9bSStanislav Motylkov         {
2763d033fe9bSStanislav Motylkov             Status = ExpGetRawSMBiosTable(NULL, &DataSize, 0);
2764d033fe9bSStanislav Motylkov             if (DataSize > 0)
2765d033fe9bSStanislav Motylkov             {
2766d033fe9bSStanislav Motylkov                 TableCount = 1;
2767d033fe9bSStanislav Motylkov                 if (SysFirmwareInfo->Action == SystemFirmwareTable_Enumerate)
2768d033fe9bSStanislav Motylkov                 {
2769d033fe9bSStanislav Motylkov                     DataSize = TableCount * sizeof(ULONG);
2770d033fe9bSStanislav Motylkov                     if (DataSize <= InputBufSize)
2771d033fe9bSStanislav Motylkov                     {
2772d033fe9bSStanislav Motylkov                         *(ULONG *)SysFirmwareInfo->TableBuffer = 0;
2773d033fe9bSStanislav Motylkov                     }
2774d033fe9bSStanislav Motylkov                 }
2775d033fe9bSStanislav Motylkov                 else if (SysFirmwareInfo->Action == SystemFirmwareTable_Get
2776d033fe9bSStanislav Motylkov                          && DataSize <= InputBufSize)
2777d033fe9bSStanislav Motylkov                 {
2778d033fe9bSStanislav Motylkov                     Status = ExpGetRawSMBiosTable(SysFirmwareInfo->TableBuffer, &DataSize, InputBufSize);
2779d033fe9bSStanislav Motylkov                 }
2780d033fe9bSStanislav Motylkov                 SysFirmwareInfo->TableBufferLength = DataSize;
2781d033fe9bSStanislav Motylkov             }
2782d033fe9bSStanislav Motylkov             break;
2783d033fe9bSStanislav Motylkov         }
2784d033fe9bSStanislav Motylkov         default:
2785d033fe9bSStanislav Motylkov         {
2786d033fe9bSStanislav Motylkov             DPRINT1("SystemFirmwareTableInformation: Unsupported provider (0x%x)\n",
2787d033fe9bSStanislav Motylkov                     SysFirmwareInfo->ProviderSignature);
2788d033fe9bSStanislav Motylkov             Status = STATUS_ILLEGAL_FUNCTION;
2789d033fe9bSStanislav Motylkov         }
2790d033fe9bSStanislav Motylkov     }
2791d033fe9bSStanislav Motylkov 
2792d033fe9bSStanislav Motylkov     if (NT_SUCCESS(Status))
2793d033fe9bSStanislav Motylkov     {
2794d033fe9bSStanislav Motylkov         switch (SysFirmwareInfo->Action)
2795d033fe9bSStanislav Motylkov         {
2796d033fe9bSStanislav Motylkov             case SystemFirmwareTable_Enumerate:
2797d033fe9bSStanislav Motylkov             case SystemFirmwareTable_Get:
2798d033fe9bSStanislav Motylkov             {
2799d033fe9bSStanislav Motylkov                 if (SysFirmwareInfo->TableBufferLength > InputBufSize)
2800d033fe9bSStanislav Motylkov                 {
2801d033fe9bSStanislav Motylkov                     Status = STATUS_BUFFER_TOO_SMALL;
2802d033fe9bSStanislav Motylkov                 }
2803d033fe9bSStanislav Motylkov                 break;
2804d033fe9bSStanislav Motylkov             }
2805d033fe9bSStanislav Motylkov             default:
2806d033fe9bSStanislav Motylkov             {
2807d033fe9bSStanislav Motylkov                 DPRINT1("SystemFirmwareTableInformation: Unsupported action (0x%x)\n",
2808d033fe9bSStanislav Motylkov                         SysFirmwareInfo->Action);
2809d033fe9bSStanislav Motylkov                 Status = STATUS_ILLEGAL_FUNCTION;
2810d033fe9bSStanislav Motylkov             }
2811d033fe9bSStanislav Motylkov         }
2812d033fe9bSStanislav Motylkov     }
2813d033fe9bSStanislav Motylkov     else
2814d033fe9bSStanislav Motylkov     {
2815d033fe9bSStanislav Motylkov         SysFirmwareInfo->TableBufferLength = 0;
2816d033fe9bSStanislav Motylkov     }
2817d033fe9bSStanislav Motylkov     return Status;
2818d033fe9bSStanislav Motylkov }
2819d033fe9bSStanislav Motylkov 
2820c2c66affSColin Finck /* Query/Set Calls Table */
2821c2c66affSColin Finck typedef
2822c2c66affSColin Finck struct _QSSI_CALLS
2823c2c66affSColin Finck {
2824c2c66affSColin Finck     NTSTATUS (* Query) (PVOID,ULONG,PULONG);
2825c2c66affSColin Finck     NTSTATUS (* Set) (PVOID,ULONG);
2826c2c66affSColin Finck } QSSI_CALLS;
2827c2c66affSColin Finck 
2828c2c66affSColin Finck // QS    Query & Set
2829c2c66affSColin Finck // QX    Query
2830c2c66affSColin Finck // XS    Set
2831c2c66affSColin Finck // XX    unknown behaviour
2832c2c66affSColin Finck //
2833c2c66affSColin Finck #define SI_QS(n) {QSI_USE(n),SSI_USE(n)}
2834c2c66affSColin Finck #define SI_QX(n) {QSI_USE(n),NULL}
2835c2c66affSColin Finck #define SI_XS(n) {NULL,SSI_USE(n)}
2836c2c66affSColin Finck #define SI_XX(n) {NULL,NULL}
2837c2c66affSColin Finck 
2838c2c66affSColin Finck static
2839c2c66affSColin Finck QSSI_CALLS
2840c2c66affSColin Finck CallQS[] =
2841c2c66affSColin Finck {
2842c2c66affSColin Finck     SI_QX(SystemBasicInformation),
2843c2c66affSColin Finck     SI_QX(SystemProcessorInformation),
2844c2c66affSColin Finck     SI_QX(SystemPerformanceInformation),
2845c2c66affSColin Finck     SI_QX(SystemTimeOfDayInformation),
2846712f4696SHermès Bélusca-Maïto     SI_QX(SystemPathInformation),
2847c2c66affSColin Finck     SI_QX(SystemProcessInformation),
2848c2c66affSColin Finck     SI_QX(SystemCallCountInformation),
2849c2c66affSColin Finck     SI_QX(SystemDeviceInformation),
2850c2c66affSColin Finck     SI_QX(SystemProcessorPerformanceInformation),
2851c2c66affSColin Finck     SI_QS(SystemFlagsInformation),
2852c2c66affSColin Finck     SI_QX(SystemCallTimeInformation), /* should be SI_XX */
2853c2c66affSColin Finck     SI_QX(SystemModuleInformation),
2854c2c66affSColin Finck     SI_QX(SystemLocksInformation),
2855c2c66affSColin Finck     SI_QX(SystemStackTraceInformation), /* should be SI_XX */
2856c2c66affSColin Finck     SI_QX(SystemPagedPoolInformation), /* should be SI_XX */
2857c2c66affSColin Finck     SI_QX(SystemNonPagedPoolInformation), /* should be SI_XX */
2858c2c66affSColin Finck     SI_QX(SystemHandleInformation),
2859c2c66affSColin Finck     SI_QX(SystemObjectInformation),
2860c2c66affSColin Finck     SI_QX(SystemPageFileInformation),
2861c2c66affSColin Finck     SI_QX(SystemVdmInstemulInformation),
2862c2c66affSColin Finck     SI_QX(SystemVdmBopInformation), /* it should be SI_XX */
2863c2c66affSColin Finck     SI_QS(SystemFileCacheInformation),
2864c2c66affSColin Finck     SI_QX(SystemPoolTagInformation),
2865c2c66affSColin Finck     SI_QX(SystemInterruptInformation),
2866c2c66affSColin Finck     SI_QS(SystemDpcBehaviourInformation),
2867c2c66affSColin Finck     SI_QX(SystemFullMemoryInformation), /* it should be SI_XX */
2868c2c66affSColin Finck     SI_XS(SystemLoadGdiDriverInformation),
2869c2c66affSColin Finck     SI_XS(SystemUnloadGdiDriverInformation),
2870c2c66affSColin Finck     SI_QS(SystemTimeAdjustmentInformation),
2871c2c66affSColin Finck     SI_QX(SystemSummaryMemoryInformation), /* it should be SI_XX */
2872c2c66affSColin Finck     SI_QX(SystemNextEventIdInformation), /* it should be SI_XX */
2873c2c66affSColin Finck     SI_QX(SystemPerformanceTraceInformation), /* it should be SI_XX */
2874c2c66affSColin Finck     SI_QX(SystemCrashDumpInformation),
2875c2c66affSColin Finck     SI_QX(SystemExceptionInformation),
2876c2c66affSColin Finck     SI_QX(SystemCrashDumpStateInformation),
2877c2c66affSColin Finck     SI_QX(SystemKernelDebuggerInformation),
2878c2c66affSColin Finck     SI_QX(SystemContextSwitchInformation),
2879c2c66affSColin Finck     SI_QS(SystemRegistryQuotaInformation),
2880c2c66affSColin Finck     SI_XS(SystemExtendServiceTableInformation),
2881c2c66affSColin Finck     SI_XS(SystemPrioritySeperation),
2882c2c66affSColin Finck     SI_QX(SystemVerifierAddDriverInformation), /* it should be SI_XX */
2883c2c66affSColin Finck     SI_QX(SystemVerifierRemoveDriverInformation), /* it should be SI_XX */
2884c2c66affSColin Finck     SI_QX(SystemProcessorIdleInformation), /* it should be SI_XX */
2885c2c66affSColin Finck     SI_QX(SystemLegacyDriverInformation), /* it should be SI_XX */
2886c2c66affSColin Finck     SI_QS(SystemCurrentTimeZoneInformation), /* it should be SI_QX */
2887c2c66affSColin Finck     SI_QX(SystemLookasideInformation),
2888c2c66affSColin Finck     SI_XS(SystemTimeSlipNotification),
2889c2c66affSColin Finck     SI_XS(SystemSessionCreate),
2890c2c66affSColin Finck     SI_XS(SystemSessionDetach),
2891c2c66affSColin Finck     SI_QX(SystemSessionInformation), /* it should be SI_XX */
2892c2c66affSColin Finck     SI_QX(SystemRangeStartInformation),
2893c2c66affSColin Finck     SI_QS(SystemVerifierInformation),
2894c2c66affSColin Finck     SI_XS(SystemVerifierThunkExtend),
2895c2c66affSColin Finck     SI_QX(SystemSessionProcessesInformation),
2896c2c66affSColin Finck     SI_XS(SystemLoadGdiDriverInSystemSpaceInformation),
2897c2c66affSColin Finck     SI_QX(SystemNumaProcessorMap),
2898c2c66affSColin Finck     SI_QX(SystemPrefetcherInformation),
2899c2c66affSColin Finck     SI_QX(SystemExtendedProcessInformation),
2900c2c66affSColin Finck     SI_QX(SystemRecommendedSharedDataAlignment),
2901c2c66affSColin Finck     SI_XX(SystemComPlusPackage),
2902c2c66affSColin Finck     SI_QX(SystemNumaAvailableMemory),
2903c2c66affSColin Finck     SI_XX(SystemProcessorPowerInformation), /* FIXME: not implemented */
2904c2c66affSColin Finck     SI_XX(SystemEmulationBasicInformation), /* FIXME: not implemented */
2905c2c66affSColin Finck     SI_XX(SystemEmulationProcessorInformation), /* FIXME: not implemented */
2906c2c66affSColin Finck     SI_QX(SystemExtendedHandleInformation),
2907d033fe9bSStanislav Motylkov     SI_XX(SystemLostDelayedWriteInformation), /* FIXME: not implemented */
2908d033fe9bSStanislav Motylkov     SI_XX(SystemBigPoolInformation), /* FIXME: not implemented */
2909d033fe9bSStanislav Motylkov     SI_XX(SystemSessionPoolTagInformation), /* FIXME: not implemented */
2910d033fe9bSStanislav Motylkov     SI_XX(SystemSessionMappedViewInformation), /* FIXME: not implemented */
2911d033fe9bSStanislav Motylkov     SI_XX(SystemHotpatchInformation), /* FIXME: not implemented */
2912f821e174SPierre Schweitzer     SI_QX(SystemObjectSecurityMode),
2913d033fe9bSStanislav Motylkov     SI_XX(SystemWatchdogTimerHandler), /* FIXME: not implemented */
2914d033fe9bSStanislav Motylkov     SI_XX(SystemWatchdogTimerInformation), /* FIXME: not implemented */
291596ee4509SPierre Schweitzer     SI_QX(SystemLogicalProcessorInformation),
2916d033fe9bSStanislav Motylkov     SI_XX(SystemWow64SharedInformation), /* FIXME: not implemented */
2917d033fe9bSStanislav Motylkov     SI_XX(SystemRegisterFirmwareTableInformationHandler), /* FIXME: not implemented */
2918d033fe9bSStanislav Motylkov     SI_QX(SystemFirmwareTableInformation),
2919c2c66affSColin Finck };
2920c2c66affSColin Finck 
2921c2c66affSColin Finck C_ASSERT(SystemBasicInformation == 0);
2922c2c66affSColin Finck #define MIN_SYSTEM_INFO_CLASS (SystemBasicInformation)
29237692a620SHermès Bélusca-Maïto #define MAX_SYSTEM_INFO_CLASS RTL_NUMBER_OF(CallQS)
2924c2c66affSColin Finck 
2925c2c66affSColin Finck /*
2926c2c66affSColin Finck  * @implemented
2927c2c66affSColin Finck  */
2928c2c66affSColin Finck __kernel_entry
2929c2c66affSColin Finck NTSTATUS
2930c2c66affSColin Finck NTAPI
NtQuerySystemInformation(_In_ SYSTEM_INFORMATION_CLASS SystemInformationClass,_Out_writes_bytes_to_opt_ (SystemInformationLength,* ReturnLength)PVOID SystemInformation,_In_ ULONG SystemInformationLength,_Out_opt_ PULONG ReturnLength)2931c2c66affSColin Finck NtQuerySystemInformation(
2932c2c66affSColin Finck     _In_ SYSTEM_INFORMATION_CLASS SystemInformationClass,
2933c2c66affSColin Finck     _Out_writes_bytes_to_opt_(SystemInformationLength, *ReturnLength) PVOID SystemInformation,
29341200561fSHermès Bélusca-Maïto     _In_ ULONG SystemInformationLength,
29351200561fSHermès Bélusca-Maïto     _Out_opt_ PULONG ReturnLength)
2936c2c66affSColin Finck {
29371200561fSHermès Bélusca-Maïto     NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
29381200561fSHermès Bélusca-Maïto     ULONG CapturedResultLength = 0;
2939c2c66affSColin Finck     ULONG Alignment = TYPE_ALIGNMENT(ULONG);
29401200561fSHermès Bélusca-Maïto     KPROCESSOR_MODE PreviousMode;
2941c2c66affSColin Finck 
2942c2c66affSColin Finck     PAGED_CODE();
2943c2c66affSColin Finck 
2944c2c66affSColin Finck     PreviousMode = ExGetPreviousMode();
2945c2c66affSColin Finck 
2946c2c66affSColin Finck     _SEH2_TRY
2947c2c66affSColin Finck     {
2948c2c66affSColin Finck #if (NTDDI_VERSION >= NTDDI_VISTA)
2949c2c66affSColin Finck         /*
29507692a620SHermès Bélusca-Maïto          * Check whether the request is valid.
2951c2c66affSColin Finck          */
295263977328SThomas Faber         if (SystemInformationClass < MIN_SYSTEM_INFO_CLASS ||
295363977328SThomas Faber             SystemInformationClass >= MAX_SYSTEM_INFO_CLASS)
2954c2c66affSColin Finck         {
2955c2c66affSColin Finck             _SEH2_YIELD(return STATUS_INVALID_INFO_CLASS);
2956c2c66affSColin Finck         }
2957c2c66affSColin Finck #endif
2958c2c66affSColin Finck 
2959c2c66affSColin Finck         if (PreviousMode != KernelMode)
2960c2c66affSColin Finck         {
2961c2c66affSColin Finck             /* SystemKernelDebuggerInformation needs only BOOLEAN alignment */
2962c2c66affSColin Finck             if (SystemInformationClass == SystemKernelDebuggerInformation)
2963c2c66affSColin Finck                 Alignment = TYPE_ALIGNMENT(BOOLEAN);
2964c2c66affSColin Finck 
29651200561fSHermès Bélusca-Maïto             ProbeForWrite(SystemInformation, SystemInformationLength, Alignment);
29661200561fSHermès Bélusca-Maïto             if (ReturnLength != NULL)
29671200561fSHermès Bélusca-Maïto                 ProbeForWriteUlong(ReturnLength);
2968c2c66affSColin Finck         }
2969c2c66affSColin Finck 
29701200561fSHermès Bélusca-Maïto         if (ReturnLength)
29711200561fSHermès Bélusca-Maïto             *ReturnLength = 0;
2972c2c66affSColin Finck 
2973c2c66affSColin Finck #if (NTDDI_VERSION < NTDDI_VISTA)
2974c2c66affSColin Finck         /*
29757692a620SHermès Bélusca-Maïto          * Check whether the request is valid.
2976c2c66affSColin Finck          */
297763977328SThomas Faber         if (SystemInformationClass < MIN_SYSTEM_INFO_CLASS ||
297863977328SThomas Faber             SystemInformationClass >= MAX_SYSTEM_INFO_CLASS)
2979c2c66affSColin Finck         {
2980c2c66affSColin Finck             _SEH2_YIELD(return STATUS_INVALID_INFO_CLASS);
2981c2c66affSColin Finck         }
2982c2c66affSColin Finck #endif
2983c2c66affSColin Finck 
29847692a620SHermès Bélusca-Maïto         if (CallQS[SystemInformationClass].Query != NULL)
2985c2c66affSColin Finck         {
29867692a620SHermès Bélusca-Maïto             /* Hand the request to a subhandler */
29871200561fSHermès Bélusca-Maïto             Status = CallQS[SystemInformationClass].Query(SystemInformation,
29881200561fSHermès Bélusca-Maïto                                                           SystemInformationLength,
29891200561fSHermès Bélusca-Maïto                                                           &CapturedResultLength);
2990c2c66affSColin Finck 
2991c2c66affSColin Finck             /* Save the result length to the caller */
29921200561fSHermès Bélusca-Maïto             if (ReturnLength)
29931200561fSHermès Bélusca-Maïto                 *ReturnLength = CapturedResultLength;
2994c2c66affSColin Finck         }
2995c2c66affSColin Finck     }
2996c2c66affSColin Finck     _SEH2_EXCEPT(ExSystemExceptionFilter())
2997c2c66affSColin Finck     {
29981200561fSHermès Bélusca-Maïto         Status = _SEH2_GetExceptionCode();
2999c2c66affSColin Finck     }
3000c2c66affSColin Finck     _SEH2_END;
3001c2c66affSColin Finck 
30021200561fSHermès Bélusca-Maïto     return Status;
3003c2c66affSColin Finck }
3004c2c66affSColin Finck 
3005d484a68cSHermès Bélusca-Maïto __kernel_entry
3006c2c66affSColin Finck NTSTATUS
3007c2c66affSColin Finck NTAPI
NtSetSystemInformation(_In_ SYSTEM_INFORMATION_CLASS SystemInformationClass,_In_reads_bytes_ (SystemInformationLength)PVOID SystemInformation,_In_ ULONG SystemInformationLength)3008d484a68cSHermès Bélusca-Maïto NtSetSystemInformation(
3009d484a68cSHermès Bélusca-Maïto     _In_ SYSTEM_INFORMATION_CLASS SystemInformationClass,
3010d484a68cSHermès Bélusca-Maïto     _In_reads_bytes_(SystemInformationLength) PVOID SystemInformation,
3011d484a68cSHermès Bélusca-Maïto     _In_ ULONG SystemInformationLength)
3012c2c66affSColin Finck {
3013c2c66affSColin Finck     NTSTATUS Status = STATUS_INVALID_INFO_CLASS;
3014c2c66affSColin Finck     KPROCESSOR_MODE PreviousMode;
3015c2c66affSColin Finck 
3016c2c66affSColin Finck     PAGED_CODE();
3017c2c66affSColin Finck 
3018c2c66affSColin Finck     PreviousMode = ExGetPreviousMode();
3019c2c66affSColin Finck 
3020c2c66affSColin Finck     _SEH2_TRY
3021c2c66affSColin Finck     {
3022c2c66affSColin Finck         /*
30237692a620SHermès Bélusca-Maïto          * If called from user mode, check possible unsafe arguments.
3024c2c66affSColin Finck          */
3025c2c66affSColin Finck         if (PreviousMode != KernelMode)
3026c2c66affSColin Finck         {
3027c2c66affSColin Finck             ProbeForRead(SystemInformation, SystemInformationLength, sizeof(ULONG));
3028c2c66affSColin Finck         }
3029c2c66affSColin Finck 
3030c2c66affSColin Finck         /*
30317692a620SHermès Bélusca-Maïto          * Check whether the request is valid.
3032c2c66affSColin Finck          */
3033c2c66affSColin Finck         if ((SystemInformationClass >= MIN_SYSTEM_INFO_CLASS) &&
3034c2c66affSColin Finck             (SystemInformationClass < MAX_SYSTEM_INFO_CLASS))
3035c2c66affSColin Finck         {
30367692a620SHermès Bélusca-Maïto             if (CallQS[SystemInformationClass].Set != NULL)
3037c2c66affSColin Finck             {
30387692a620SHermès Bélusca-Maïto                 /* Hand the request to a subhandler */
3039c2c66affSColin Finck                 Status = CallQS[SystemInformationClass].Set(SystemInformation,
3040c2c66affSColin Finck                                                             SystemInformationLength);
3041c2c66affSColin Finck             }
3042c2c66affSColin Finck         }
3043c2c66affSColin Finck     }
3044c2c66affSColin Finck     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
3045c2c66affSColin Finck     {
3046c2c66affSColin Finck         Status = _SEH2_GetExceptionCode();
3047c2c66affSColin Finck     }
3048c2c66affSColin Finck     _SEH2_END;
3049c2c66affSColin Finck 
3050c2c66affSColin Finck     return Status;
3051c2c66affSColin Finck }
3052c2c66affSColin Finck 
3053c2c66affSColin Finck ULONG
3054c2c66affSColin Finck NTAPI
NtGetCurrentProcessorNumber(VOID)3055c2c66affSColin Finck NtGetCurrentProcessorNumber(VOID)
3056c2c66affSColin Finck {
3057c2c66affSColin Finck     /* Just use Ke */
3058c2c66affSColin Finck     return KeGetCurrentProcessorNumber();
3059c2c66affSColin Finck }
3060c2c66affSColin Finck 
3061c2c66affSColin Finck #undef ExGetPreviousMode
3062c2c66affSColin Finck KPROCESSOR_MODE
3063c2c66affSColin Finck NTAPI
ExGetPreviousMode(VOID)3064c2c66affSColin Finck ExGetPreviousMode(VOID)
3065c2c66affSColin Finck {
3066c2c66affSColin Finck     /* Just use Ke */
3067c2c66affSColin Finck     return KeGetPreviousMode();
3068c2c66affSColin Finck }
3069