Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

5947 lines
198 KiB

  1. /*++
  2. Copyright (c) 1989-2001 Microsoft Corporation
  3. Module Name:
  4. sysinfo.c
  5. Abstract:
  6. This module implements the NT set and query system information services.
  7. Author:
  8. Steve Wood (stevewo) 21-Aug-1989
  9. Environment:
  10. Kernel mode only.
  11. Revision History:
  12. --*/
  13. #include "exp.h"
  14. #pragma hdrstop
  15. #include "stdlib.h"
  16. #include "string.h"
  17. #include "vdmntos.h"
  18. #include <nturtl.h>
  19. #include "pool.h"
  20. #include "stktrace.h"
  21. #include "align.h"
  22. #if defined(_WIN64)
  23. #include <wow64t.h>
  24. #endif
  25. extern ULONG MmAvailablePages;
  26. extern ULONG MmSystemCodePage;
  27. extern ULONG MmSystemCachePage;
  28. extern ULONG MmPagedPoolPage;
  29. extern ULONG MmSystemDriverPage;
  30. extern ULONG MmTotalSystemCodePages;
  31. extern ULONG MmTotalSystemDriverPages;
  32. extern ULONG MmStandbyRePurposed;
  33. extern RTL_TIME_ZONE_INFORMATION ExpTimeZoneInformation;
  34. //
  35. // For SystemDpcBehaviorInformation
  36. //
  37. extern ULONG KiMaximumDpcQueueDepth;
  38. extern ULONG KiMinimumDpcRate;
  39. extern ULONG KiAdjustDpcThreshold;
  40. extern ULONG KiIdealDpcRate;
  41. extern LIST_ENTRY MmLoadedUserImageList;
  42. extern MMSUPPORT MmSystemCacheWs;
  43. extern PFN_NUMBER MmTransitionSharedPages;
  44. extern PFN_NUMBER MmTransitionSharedPagesPeak;
  45. #define ROUND_UP(VALUE,ROUND) ((ULONG)(((ULONG)VALUE + \
  46. ((ULONG)ROUND - 1L)) & (~((ULONG)ROUND - 1L))))
  47. //
  48. // For referencing a user-supplied event handle
  49. //
  50. extern POBJECT_TYPE ExEventObjectType;
  51. //
  52. // Watchdog Handler
  53. //
  54. PWD_HANDLER ExpWdHandler = NULL;
  55. PVOID ExpWdHandlerContext = NULL;
  56. //
  57. // COM+ Package Install Status
  58. //
  59. const static UNICODE_STRING KeyName = RTL_CONSTANT_STRING (COMPLUS_PACKAGE_KEYPATH);
  60. static UNICODE_STRING KeyValueName = RTL_CONSTANT_STRING (COMPLUS_PACKAGE_ENABLE64BIT);
  61. NTSTATUS
  62. ExpValidateLocale(
  63. IN LCID LocaleId
  64. );
  65. BOOLEAN
  66. ExpIsValidUILanguage(
  67. IN WCHAR *pLangId
  68. );
  69. NTSTATUS
  70. ExpGetCurrentUserUILanguage(
  71. IN WCHAR *ValueName,
  72. OUT LANGID *CurrentUserUILanguageId,
  73. IN BOOLEAN bCheckGP
  74. );
  75. NTSTATUS
  76. ExpSetCurrentUserUILanguage(
  77. IN WCHAR *ValueName,
  78. IN LANGID DefaultUILanguageId
  79. );
  80. NTSTATUS
  81. ExpGetUILanguagePolicy(
  82. IN HANDLE CurrentUserKey,
  83. OUT LANGID *PolicyUILanguageId
  84. );
  85. NTSTATUS
  86. ExpGetProcessInformation (
  87. OUT PVOID SystemInformation,
  88. IN ULONG SystemInformationLength,
  89. OUT PULONG Length,
  90. IN PULONG SessionId OPTIONAL,
  91. IN BOOLEAN ExtendedInformation
  92. );
  93. NTSTATUS
  94. ExGetSessionPoolTagInformation (
  95. OUT PVOID SystemInformation,
  96. IN ULONG SystemInformationLength,
  97. OUT PULONG Length,
  98. IN PULONG SessionId
  99. );
  100. VOID
  101. ExpGetProcessorIdleInformation (
  102. OUT PVOID SystemInformation,
  103. IN ULONG SystemInformationLength,
  104. OUT PULONG Length
  105. );
  106. VOID
  107. ExpGetProcessorPowerInformation (
  108. OUT PVOID SystemInformation,
  109. IN ULONG SystemInformationLength,
  110. OUT PULONG Length
  111. );
  112. VOID
  113. ExpCopyProcessInfo (
  114. IN PSYSTEM_PROCESS_INFORMATION ProcessInfo,
  115. IN PEPROCESS Process,
  116. IN BOOLEAN ExtendedInformation
  117. );
  118. VOID
  119. ExpCopyThreadInfo (
  120. IN PVOID ThreadInfoBuffer,
  121. IN PETHREAD Thread,
  122. IN BOOLEAN ExtendedInformation
  123. );
  124. #if i386
  125. NTSTATUS
  126. ExpGetStackTraceInformation (
  127. OUT PVOID SystemInformation,
  128. IN ULONG SystemInformationLength,
  129. OUT PULONG Length
  130. );
  131. #endif // i386
  132. NTSTATUS
  133. ExpGetLockInformation (
  134. OUT PVOID SystemInformation,
  135. IN ULONG SystemInformationLength,
  136. OUT PULONG Length
  137. );
  138. NTSTATUS
  139. ExpGetLookasideInformation (
  140. OUT PVOID Buffer,
  141. IN ULONG BufferLength,
  142. OUT PULONG Length
  143. );
  144. NTSTATUS
  145. ExpGetHandleInformation(
  146. OUT PVOID SystemInformation,
  147. IN ULONG SystemInformationLength,
  148. OUT PULONG Length
  149. );
  150. NTSTATUS
  151. ExpGetHandleInformationEx(
  152. OUT PVOID SystemInformation,
  153. IN ULONG SystemInformationLength,
  154. OUT PULONG Length
  155. );
  156. NTSTATUS
  157. ExpGetObjectInformation(
  158. OUT PVOID SystemInformation,
  159. IN ULONG SystemInformationLength,
  160. OUT PULONG Length
  161. );
  162. NTSTATUS
  163. ExpGetInstemulInformation(
  164. OUT PSYSTEM_VDM_INSTEMUL_INFO Info
  165. );
  166. NTSTATUS
  167. ExGetPoolTagInfo (
  168. IN PVOID SystemInformation,
  169. IN ULONG SystemInformationLength,
  170. IN OUT PULONG ReturnLength OPTIONAL
  171. );
  172. NTSTATUS
  173. ExGetSessionPoolTagInfo (
  174. IN PVOID SystemInformation,
  175. IN ULONG SystemInformationLength,
  176. IN OUT PULONG ReturnedEntries,
  177. IN OUT PULONG ActualEntries
  178. );
  179. NTSTATUS
  180. ExGetBigPoolInfo (
  181. IN PVOID SystemInformation,
  182. IN ULONG SystemInformationLength,
  183. IN OUT PULONG ReturnLength OPTIONAL
  184. );
  185. NTSTATUS
  186. ExpQueryModuleInformation(
  187. IN PLIST_ENTRY LoadOrderListHead,
  188. IN PLIST_ENTRY UserModeLoadOrderListHead,
  189. OUT PRTL_PROCESS_MODULES ModuleInformation,
  190. IN ULONG ModuleInformationLength,
  191. OUT PULONG ReturnLength OPTIONAL
  192. );
  193. NTSTATUS
  194. ExpQueryLegacyDriverInformation(
  195. IN PSYSTEM_LEGACY_DRIVER_INFORMATION LegacyInfo,
  196. IN PULONG Length
  197. );
  198. NTSTATUS
  199. ExpQueryNumaProcessorMap(
  200. OUT PVOID SystemInformation,
  201. IN ULONG SystemInformationLength,
  202. OUT PULONG ReturnedLength
  203. );
  204. NTSTATUS
  205. ExpQueryNumaAvailableMemory(
  206. OUT PVOID SystemInformation,
  207. IN ULONG SystemInformationLength,
  208. OUT PULONG ReturnedLength
  209. );
  210. #if defined(ALLOC_PRAGMA)
  211. #pragma alloc_text(PAGE, NtQueryDefaultLocale)
  212. #pragma alloc_text(PAGE, NtSetDefaultLocale)
  213. #pragma alloc_text(PAGE, NtQueryInstallUILanguage)
  214. #pragma alloc_text(PAGE, NtQueryDefaultUILanguage)
  215. #pragma alloc_text(PAGE, ExpGetCurrentUserUILanguage)
  216. #pragma alloc_text(PAGE, NtSetDefaultUILanguage)
  217. #pragma alloc_text(PAGE, ExpSetCurrentUserUILanguage)
  218. #pragma alloc_text(PAGE, ExpValidateLocale)
  219. #pragma alloc_text(PAGE, ExpGetUILanguagePolicy)
  220. #pragma alloc_text(PAGE, NtQuerySystemInformation)
  221. #pragma alloc_text(PAGE, NtSetSystemInformation)
  222. #pragma alloc_text(PAGE, ExpGetHandleInformation)
  223. #pragma alloc_text(PAGE, ExpGetHandleInformationEx)
  224. #pragma alloc_text(PAGE, ExpGetObjectInformation)
  225. #pragma alloc_text(PAGE, ExpQueryModuleInformation)
  226. #pragma alloc_text(PAGE, ExpCopyProcessInfo)
  227. #pragma alloc_text(PAGE, ExpQueryLegacyDriverInformation)
  228. #pragma alloc_text(PAGE, ExLockUserBuffer)
  229. #pragma alloc_text(PAGE, ExpQueryNumaAvailableMemory)
  230. #pragma alloc_text(PAGE, ExpQueryNumaProcessorMap)
  231. #pragma alloc_text(PAGE, ExpReadComPlusPackage)
  232. #pragma alloc_text(PAGE, ExpUpdateComPlusPackage)
  233. #pragma alloc_text(PAGE, ExGetSessionPoolTagInformation)
  234. #pragma alloc_text(PAGELK, ExpGetLockInformation)
  235. #pragma alloc_text(PAGELK, ExpGetProcessorPowerInformation)
  236. #pragma alloc_text(PAGELK, ExpGetProcessorIdleInformation)
  237. #pragma alloc_text(PAGE, ExpIsValidUILanguage)
  238. #endif
  239. NTSTATUS
  240. ExpReadComPlusPackage(
  241. VOID
  242. )
  243. /*++
  244. Routine Description:
  245. This function reads the status of the 64-bit COM+ package from the registry
  246. and stick it inside the shared page.
  247. Arguments:
  248. None.
  249. Return Value:
  250. NTSTATUS.
  251. --*/
  252. {
  253. NTSTATUS Status;
  254. static OBJECT_ATTRIBUTES ObjectAttributes = RTL_CONSTANT_OBJECT_ATTRIBUTES (&KeyName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE);
  255. CHAR KeyValueBuffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(ULONG)];
  256. PKEY_VALUE_PARTIAL_INFORMATION KeyValueInformation;
  257. ULONG ResultLength;
  258. HANDLE Key;
  259. Status = ZwOpenKey (&Key,
  260. GENERIC_READ,
  261. &ObjectAttributes);
  262. if (NT_SUCCESS (Status)) {
  263. KeyValueInformation = (PKEY_VALUE_PARTIAL_INFORMATION)KeyValueBuffer;
  264. Status = ZwQueryValueKey (Key,
  265. &KeyValueName,
  266. KeyValuePartialInformation,
  267. KeyValueInformation,
  268. sizeof (KeyValueBuffer),
  269. &ResultLength);
  270. if (NT_SUCCESS (Status)) {
  271. if ((KeyValueInformation->Type == REG_DWORD) &&
  272. (KeyValueInformation->DataLength == sizeof(ULONG))) {
  273. SharedUserData->ComPlusPackage = *(PULONG)KeyValueInformation->Data;
  274. }
  275. }
  276. ZwClose (Key);
  277. }
  278. return Status;
  279. }
  280. NTSTATUS
  281. ExpUpdateComPlusPackage(
  282. IN ULONG ComPlusPackageStatus
  283. )
  284. /*++
  285. Routine Description:
  286. This function updates the COM+ runtime package status on the system.
  287. The package status indicates whether the 64-bit or the 32-bit runtime
  288. should be used when executing IL_ONLY COM+ images.
  289. Arguments:
  290. ComPlusPackageStatus - COM+ Runtime package status on the system
  291. Return Value:
  292. NTSTATUS
  293. --*/
  294. {
  295. NTSTATUS Status;
  296. static OBJECT_ATTRIBUTES ObjectAttributes = RTL_CONSTANT_OBJECT_ATTRIBUTES (&KeyName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE | OBJ_FORCE_ACCESS_CHECK);
  297. ULONG Disposition;
  298. HANDLE Key;
  299. Status = ZwOpenKey (&Key,
  300. GENERIC_WRITE,
  301. &ObjectAttributes
  302. );
  303. if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
  304. {
  305. Status = ZwCreateKey (&Key,
  306. GENERIC_WRITE,
  307. &ObjectAttributes,
  308. 0,
  309. NULL,
  310. REG_OPTION_NON_VOLATILE,
  311. &Disposition
  312. );
  313. }
  314. if (NT_SUCCESS (Status)) {
  315. Status = ZwSetValueKey (Key,
  316. &KeyValueName,
  317. 0,
  318. REG_DWORD,
  319. &ComPlusPackageStatus,
  320. sizeof(ULONG));
  321. ZwClose (Key);
  322. }
  323. return Status;
  324. }
  325. NTSTATUS
  326. NtQueryDefaultLocale (
  327. IN BOOLEAN UserProfile,
  328. OUT PLCID DefaultLocaleId
  329. )
  330. {
  331. KPROCESSOR_MODE PreviousMode;
  332. NTSTATUS Status;
  333. PAGED_CODE();
  334. Status = STATUS_SUCCESS;
  335. try {
  336. //
  337. // Get previous processor mode and probe output argument if necessary.
  338. //
  339. PreviousMode = KeGetPreviousMode();
  340. if (PreviousMode != KernelMode) {
  341. ProbeForWriteUlong ((PULONG)DefaultLocaleId);
  342. }
  343. if (UserProfile) {
  344. *DefaultLocaleId = MmGetSessionLocaleId ();
  345. }
  346. else {
  347. *DefaultLocaleId = PsDefaultSystemLocaleId;
  348. }
  349. }
  350. except (EXCEPTION_EXECUTE_HANDLER) {
  351. Status = GetExceptionCode();
  352. }
  353. return Status;
  354. }
  355. NTSTATUS
  356. NtSetDefaultLocale (
  357. IN BOOLEAN UserProfile,
  358. IN LCID DefaultLocaleId
  359. )
  360. {
  361. NTSTATUS Status;
  362. OBJECT_ATTRIBUTES ObjectAttributes;
  363. UNICODE_STRING KeyPath, KeyValueName;
  364. HANDLE CurrentUserKey, Key;
  365. WCHAR KeyValueBuffer[ 128 ];
  366. PKEY_VALUE_PARTIAL_INFORMATION KeyValueInformation;
  367. ULONG ResultLength;
  368. PWSTR s;
  369. ULONG n, i, Digit;
  370. WCHAR c;
  371. ULONG Flags;
  372. PAGED_CODE();
  373. if (DefaultLocaleId & 0xFFFF0000) {
  374. return STATUS_INVALID_PARAMETER;
  375. }
  376. KeyValueInformation = (PKEY_VALUE_PARTIAL_INFORMATION)KeyValueBuffer;
  377. if (UserProfile) {
  378. Status = RtlOpenCurrentUser( KEY_ENUMERATE_SUB_KEYS, &CurrentUserKey );
  379. if (!NT_SUCCESS( Status )) {
  380. return Status;
  381. }
  382. RtlInitUnicodeString( &KeyValueName, L"Locale" );
  383. RtlInitUnicodeString( &KeyPath, L"Control Panel\\International" );
  384. Flags = OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE | OBJ_FORCE_ACCESS_CHECK;
  385. }
  386. else {
  387. RtlInitUnicodeString( &KeyValueName, L"Default" );
  388. RtlInitUnicodeString( &KeyPath, L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Nls\\Language" );
  389. CurrentUserKey = NULL;
  390. Flags = OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE;
  391. }
  392. InitializeObjectAttributes (&ObjectAttributes,
  393. &KeyPath,
  394. Flags,
  395. CurrentUserKey,
  396. NULL);
  397. if (DefaultLocaleId == 0) {
  398. Status = ZwOpenKey (&Key, GENERIC_READ, &ObjectAttributes);
  399. if (NT_SUCCESS( Status )) {
  400. Status = ZwQueryValueKey( Key,
  401. &KeyValueName,
  402. KeyValuePartialInformation,
  403. KeyValueInformation,
  404. sizeof( KeyValueBuffer ),
  405. &ResultLength
  406. );
  407. if (NT_SUCCESS( Status )) {
  408. if (KeyValueInformation->Type == REG_SZ) {
  409. s = (PWSTR)KeyValueInformation->Data;
  410. for (i=0; i<KeyValueInformation->DataLength; i += sizeof( WCHAR )) {
  411. c = *s++;
  412. if (c >= L'0' && c <= L'9') {
  413. Digit = c - L'0';
  414. }
  415. else if (c >= L'A' && c <= L'F') {
  416. Digit = c - L'A' + 10;
  417. }
  418. else if (c >= L'a' && c <= L'f') {
  419. Digit = c - L'a' + 10;
  420. }
  421. else {
  422. break;
  423. }
  424. if (Digit >= 16) {
  425. break;
  426. }
  427. DefaultLocaleId = (DefaultLocaleId << 4) | Digit;
  428. }
  429. }
  430. else {
  431. if (KeyValueInformation->Type == REG_DWORD &&
  432. KeyValueInformation->DataLength == sizeof( ULONG )) {
  433. DefaultLocaleId = *(PLCID)KeyValueInformation->Data;
  434. }
  435. else {
  436. Status = STATUS_UNSUCCESSFUL;
  437. }
  438. }
  439. }
  440. ZwClose( Key );
  441. }
  442. }
  443. else {
  444. Status = ExpValidateLocale( DefaultLocaleId );
  445. if (NT_SUCCESS(Status)) {
  446. Status = ZwOpenKey( &Key,
  447. GENERIC_WRITE,
  448. &ObjectAttributes
  449. );
  450. if (NT_SUCCESS( Status )) {
  451. if (UserProfile) {
  452. n = 8;
  453. }
  454. else {
  455. n = 4;
  456. }
  457. s = &KeyValueBuffer[ n ];
  458. *s-- = UNICODE_NULL;
  459. i = (ULONG)DefaultLocaleId;
  460. while (s >= KeyValueBuffer) {
  461. Digit = i & 0x0000000F;
  462. if (Digit <= 9) {
  463. *s-- = (WCHAR)(Digit + L'0');
  464. }
  465. else {
  466. *s-- = (WCHAR)((Digit - 10) + L'A');
  467. }
  468. i = i >> 4;
  469. }
  470. Status = ZwSetValueKey( Key,
  471. &KeyValueName,
  472. 0,
  473. REG_SZ,
  474. KeyValueBuffer,
  475. (n+1) * sizeof( WCHAR )
  476. );
  477. ZwClose( Key );
  478. }
  479. }
  480. }
  481. ZwClose( CurrentUserKey );
  482. if (NT_SUCCESS( Status )) {
  483. if (UserProfile) {
  484. MmSetSessionLocaleId (DefaultLocaleId);
  485. }
  486. else {
  487. PsDefaultSystemLocaleId = DefaultLocaleId;
  488. }
  489. }
  490. return Status;
  491. }
  492. NTSTATUS
  493. NtQueryInstallUILanguage(
  494. OUT LANGID *InstallUILanguageId
  495. )
  496. {
  497. KPROCESSOR_MODE PreviousMode;
  498. NTSTATUS Status;
  499. PAGED_CODE();
  500. Status = STATUS_SUCCESS;
  501. try {
  502. //
  503. // Get previous processor mode and probe output argument if necessary.
  504. //
  505. PreviousMode = KeGetPreviousMode();
  506. if (PreviousMode != KernelMode) {
  507. ProbeForWriteUshort( (USHORT *)InstallUILanguageId );
  508. }
  509. *InstallUILanguageId = PsInstallUILanguageId;
  510. }
  511. except (EXCEPTION_EXECUTE_HANDLER) {
  512. Status = GetExceptionCode();
  513. }
  514. return Status;
  515. }
  516. NTSTATUS
  517. NtQueryDefaultUILanguage(
  518. OUT LANGID *DefaultUILanguageId
  519. )
  520. {
  521. KPROCESSOR_MODE PreviousMode;
  522. NTSTATUS Status;
  523. PAGED_CODE();
  524. Status = STATUS_SUCCESS;
  525. try {
  526. //
  527. // Get previous processor mode and probe output argument if necessary.
  528. //
  529. PreviousMode = KeGetPreviousMode();
  530. if (PreviousMode != KernelMode) {
  531. ProbeForWriteUshort( (USHORT *)DefaultUILanguageId );
  532. }
  533. //
  534. // Read the UI language from the current security context.
  535. //
  536. if (!NT_SUCCESS(ExpGetCurrentUserUILanguage( L"MultiUILanguageId",
  537. DefaultUILanguageId,
  538. TRUE))) {
  539. *DefaultUILanguageId = PsInstallUILanguageId;
  540. }
  541. }
  542. except (EXCEPTION_EXECUTE_HANDLER) {
  543. Status = GetExceptionCode();
  544. }
  545. return Status;
  546. }
  547. NTSTATUS
  548. ExpGetUILanguagePolicy(
  549. IN HANDLE CurrentUserKey,
  550. OUT LANGID *PolicyUILanguageId
  551. )
  552. {
  553. NTSTATUS Status;
  554. OBJECT_ATTRIBUTES ObjectAttributes;
  555. UNICODE_STRING KeyPath, KeyValueName;
  556. HANDLE Key;
  557. WCHAR KeyValueBuffer[ 128 ];
  558. PKEY_VALUE_PARTIAL_INFORMATION KeyValueInformation;
  559. ULONG ResultLength;
  560. ULONG Language;
  561. PAGED_CODE();
  562. KeyValueInformation = (PKEY_VALUE_PARTIAL_INFORMATION)KeyValueBuffer;
  563. RtlInitUnicodeString( &KeyValueName, L"MultiUILanguageId" );
  564. RtlInitUnicodeString( &KeyPath, L"Software\\Policies\\Microsoft\\Control Panel\\Desktop" );
  565. InitializeObjectAttributes( &ObjectAttributes,
  566. &KeyPath,
  567. (OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE),
  568. CurrentUserKey,
  569. NULL
  570. );
  571. //
  572. // Check if there is a Policy key
  573. //
  574. Status = ZwOpenKey( &Key,
  575. GENERIC_READ,
  576. &ObjectAttributes
  577. );
  578. if (NT_SUCCESS( Status )) {
  579. Status = ZwQueryValueKey( Key,
  580. &KeyValueName,
  581. KeyValuePartialInformation,
  582. KeyValueInformation,
  583. sizeof( KeyValueBuffer ),
  584. &ResultLength
  585. );
  586. if (NT_SUCCESS( Status )) {
  587. if ((KeyValueInformation->DataLength > 2) &&
  588. (KeyValueInformation->Type == REG_SZ) &&
  589. ExpIsValidUILanguage((PWSTR) KeyValueInformation->Data)) {
  590. RtlInitUnicodeString( &KeyValueName, (PWSTR) KeyValueInformation->Data );
  591. Status = RtlUnicodeStringToInteger( &KeyValueName,
  592. (ULONG)16,
  593. &Language
  594. );
  595. //
  596. // Final check to make sure this is an MUI system
  597. //
  598. if (NT_SUCCESS( Status )) {
  599. *PolicyUILanguageId = (LANGID)Language;
  600. }
  601. }
  602. else {
  603. Status = STATUS_UNSUCCESSFUL;
  604. }
  605. }
  606. ZwClose( Key );
  607. }
  608. return Status;
  609. }
  610. NTSTATUS
  611. ExpSetCurrentUserUILanguage(
  612. IN WCHAR *ValueName,
  613. IN LANGID CurrentUserUILanguage
  614. )
  615. {
  616. NTSTATUS Status;
  617. OBJECT_ATTRIBUTES ObjectAttributes;
  618. UNICODE_STRING KeyPath, KeyValueName;
  619. HANDLE CurrentUserKey, Key;
  620. WCHAR KeyValueBuffer[ 128 ];
  621. PKEY_VALUE_PARTIAL_INFORMATION KeyValueInformation;
  622. PWSTR s;
  623. ULONG i, Digit;
  624. PAGED_CODE();
  625. if (CurrentUserUILanguage & 0xFFFF0000) {
  626. return STATUS_INVALID_PARAMETER;
  627. }
  628. KeyValueInformation = (PKEY_VALUE_PARTIAL_INFORMATION)KeyValueBuffer;
  629. Status = RtlOpenCurrentUser( KEY_ENUMERATE_SUB_KEYS, &CurrentUserKey );
  630. if (!NT_SUCCESS( Status )) {
  631. return Status;
  632. }
  633. RtlInitUnicodeString( &KeyValueName, ValueName );
  634. RtlInitUnicodeString( &KeyPath, L"Control Panel\\Desktop" );
  635. InitializeObjectAttributes( &ObjectAttributes,
  636. &KeyPath,
  637. (OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE | OBJ_FORCE_ACCESS_CHECK),
  638. CurrentUserKey,
  639. NULL
  640. );
  641. Status = ExpValidateLocale( MAKELCID( CurrentUserUILanguage, SORT_DEFAULT ) );
  642. if (NT_SUCCESS(Status)) {
  643. Status = ZwOpenKey( &Key,
  644. GENERIC_WRITE,
  645. &ObjectAttributes
  646. );
  647. if (NT_SUCCESS( Status )) {
  648. s = &KeyValueBuffer[ 8 ];
  649. *s-- = UNICODE_NULL;
  650. i = (ULONG)CurrentUserUILanguage;
  651. while (s >= KeyValueBuffer) {
  652. Digit = i & 0x0000000F;
  653. if (Digit <= 9) {
  654. *s-- = (WCHAR)(Digit + L'0');
  655. }
  656. else {
  657. *s-- = (WCHAR)((Digit - 10) + L'A');
  658. }
  659. i = i >> 4;
  660. }
  661. Status = ZwSetValueKey( Key,
  662. &KeyValueName,
  663. 0,
  664. REG_SZ,
  665. KeyValueBuffer,
  666. 9 * sizeof( WCHAR )
  667. );
  668. ZwClose( Key );
  669. }
  670. }
  671. ZwClose( CurrentUserKey );
  672. return Status;
  673. }
  674. NTSTATUS
  675. ExpGetCurrentUserUILanguage(
  676. IN WCHAR *ValueName,
  677. OUT LANGID *CurrentUserUILanguageId,
  678. IN BOOLEAN bCheckGP
  679. )
  680. {
  681. NTSTATUS Status;
  682. OBJECT_ATTRIBUTES ObjectAttributes;
  683. UNICODE_STRING KeyPath, KeyValueName, UILanguage;
  684. HANDLE CurrentUserKey, Key;
  685. WCHAR KeyValueBuffer[ 128 ];
  686. PKEY_VALUE_PARTIAL_INFORMATION KeyValueInformation;
  687. ULONG ResultLength;
  688. ULONG Digit;
  689. PAGED_CODE();
  690. KeyValueInformation = (PKEY_VALUE_PARTIAL_INFORMATION)KeyValueBuffer;
  691. Status = RtlOpenCurrentUser( KEY_ENUMERATE_SUB_KEYS, &CurrentUserKey );
  692. if (!NT_SUCCESS( Status )) {
  693. return Status;
  694. }
  695. RtlInitUnicodeString( &KeyValueName, ValueName );
  696. RtlInitUnicodeString( &KeyPath, L"Control Panel\\Desktop" );
  697. InitializeObjectAttributes( &ObjectAttributes,
  698. &KeyPath,
  699. (OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE | OBJ_FORCE_ACCESS_CHECK),
  700. CurrentUserKey,
  701. NULL
  702. );
  703. //
  704. // Let's check if there is a policy installed for the UI language,
  705. // and if so, let's use it.
  706. //
  707. if (!bCheckGP || !NT_SUCCESS( ExpGetUILanguagePolicy( CurrentUserKey, CurrentUserUILanguageId ))) {
  708. Status = ZwOpenKey( &Key,
  709. GENERIC_READ,
  710. &ObjectAttributes
  711. );
  712. if (NT_SUCCESS( Status )) {
  713. Status = ZwQueryValueKey( Key,
  714. &KeyValueName,
  715. KeyValuePartialInformation,
  716. KeyValueInformation,
  717. sizeof( KeyValueBuffer ),
  718. &ResultLength
  719. );
  720. if (NT_SUCCESS( Status )) {
  721. if (KeyValueInformation->Type == REG_SZ &&
  722. ExpIsValidUILanguage((PWSTR) KeyValueInformation->Data)) {
  723. RtlInitUnicodeString( &UILanguage, (PWSTR) KeyValueInformation->Data);
  724. Status = RtlUnicodeStringToInteger( &UILanguage,
  725. (ULONG) 16,
  726. &Digit
  727. );
  728. if (NT_SUCCESS( Status )) {
  729. *CurrentUserUILanguageId = (LANGID) Digit;
  730. }
  731. }
  732. else {
  733. Status = STATUS_UNSUCCESSFUL;
  734. }
  735. }
  736. ZwClose( Key );
  737. }
  738. }
  739. ZwClose( CurrentUserKey );
  740. return Status;
  741. }
  742. NTSTATUS
  743. NtSetDefaultUILanguage(
  744. IN LANGID DefaultUILanguageId
  745. )
  746. {
  747. NTSTATUS Status;
  748. LANGID LangId;
  749. //
  750. // if this is called during user logon, then we need to update the user's registry.
  751. //
  752. if (DefaultUILanguageId == 0) {
  753. Status = ExpGetCurrentUserUILanguage( L"MUILanguagePending" ,
  754. &LangId,
  755. FALSE
  756. );
  757. if (NT_SUCCESS( Status )) {
  758. Status = ExpSetCurrentUserUILanguage( L"MultiUILanguageId" ,
  759. LangId
  760. );
  761. }
  762. return Status;
  763. }
  764. return ExpSetCurrentUserUILanguage( L"MUILanguagePending", DefaultUILanguageId );
  765. }
  766. NTSTATUS
  767. ExpValidateLocale(
  768. IN LCID LocaleId
  769. )
  770. {
  771. NTSTATUS Status = STATUS_INVALID_PARAMETER, ReturnStatus;
  772. UNICODE_STRING LocaleName, KeyValueName;
  773. UNICODE_STRING NlsLocaleKeyPath, NlsSortKeyPath, NlsLangGroupKeyPath;
  774. WCHAR LocaleNameBuffer[ 32 ];
  775. WCHAR KeyValueNameBuffer[ 32 ];
  776. WCHAR KeyValueBuffer[ 128 ];
  777. WCHAR *Ptr;
  778. HANDLE LocaleKey, SortKey, LangGroupKey;
  779. OBJECT_ATTRIBUTES NlsLocaleObjA, NlsSortObjA, NlsLangGroupObjA;
  780. PKEY_VALUE_PARTIAL_INFORMATION KeyValueInformation;
  781. ULONG i, ResultLength;
  782. //
  783. // Convert the LCID to the form %08x (e.g. 00000409)
  784. //
  785. LocaleName.Length = sizeof( LocaleNameBuffer ) / sizeof( WCHAR );
  786. LocaleName.MaximumLength = LocaleName.Length;
  787. LocaleName.Buffer = LocaleNameBuffer;
  788. //
  789. // Convert LCID to a string
  790. //
  791. ReturnStatus = RtlIntegerToUnicodeString( LocaleId, 16, &LocaleName );
  792. if (!NT_SUCCESS(ReturnStatus))
  793. goto Failed1;
  794. Ptr = KeyValueNameBuffer;
  795. for (i = ((LocaleName.Length)/sizeof(WCHAR));
  796. i < 8;
  797. i++, Ptr++) {
  798. *Ptr = L'0';
  799. }
  800. *Ptr = UNICODE_NULL;
  801. RtlInitUnicodeString(&KeyValueName, KeyValueNameBuffer);
  802. KeyValueName.MaximumLength = sizeof( KeyValueNameBuffer ) / sizeof( WCHAR );
  803. RtlAppendUnicodeToString(&KeyValueName, LocaleName.Buffer);
  804. //
  805. // Open Registry Keys : Locale, Sort and LanguageGroup
  806. //
  807. RtlInitUnicodeString(&NlsLocaleKeyPath,
  808. L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Nls\\Locale");
  809. InitializeObjectAttributes( &NlsLocaleObjA,
  810. &NlsLocaleKeyPath,
  811. (OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE),
  812. NULL,
  813. NULL
  814. );
  815. ReturnStatus = ZwOpenKey( &LocaleKey,
  816. GENERIC_READ,
  817. &NlsLocaleObjA
  818. );
  819. if (!NT_SUCCESS(ReturnStatus))
  820. goto Failed1;
  821. RtlInitUnicodeString(&NlsSortKeyPath,
  822. L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Nls\\Locale\\Alternate Sorts");
  823. InitializeObjectAttributes( &NlsSortObjA,
  824. &NlsSortKeyPath,
  825. (OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE),
  826. NULL,
  827. NULL
  828. );
  829. ReturnStatus = ZwOpenKey( &SortKey,
  830. GENERIC_READ,
  831. &NlsSortObjA
  832. );
  833. if (!NT_SUCCESS(ReturnStatus))
  834. goto Failed2;
  835. RtlInitUnicodeString(&NlsLangGroupKeyPath,
  836. L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Nls\\Language Groups");
  837. InitializeObjectAttributes( &NlsLangGroupObjA,
  838. &NlsLangGroupKeyPath,
  839. (OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE),
  840. NULL,
  841. NULL
  842. );
  843. ReturnStatus = ZwOpenKey( &LangGroupKey,
  844. GENERIC_READ,
  845. &NlsLangGroupObjA
  846. );
  847. if (!NT_SUCCESS(ReturnStatus))
  848. goto Failed3;
  849. //
  850. // Validate Locale : Lookup the Locale's Language group, and make sure it is there.
  851. //
  852. KeyValueInformation = (PKEY_VALUE_PARTIAL_INFORMATION) KeyValueBuffer;
  853. ReturnStatus = ZwQueryValueKey( LocaleKey,
  854. &KeyValueName,
  855. KeyValuePartialInformation,
  856. KeyValueInformation,
  857. sizeof( KeyValueBuffer ),
  858. &ResultLength
  859. );
  860. if (!NT_SUCCESS(ReturnStatus)) {
  861. ReturnStatus = ZwQueryValueKey( SortKey,
  862. &KeyValueName,
  863. KeyValuePartialInformation,
  864. KeyValueInformation,
  865. sizeof( KeyValueBuffer ),
  866. &ResultLength
  867. );
  868. }
  869. if ((NT_SUCCESS(ReturnStatus)) &&
  870. (KeyValueInformation->DataLength > 2)
  871. ) {
  872. RtlInitUnicodeString( &KeyValueName, (PWSTR) KeyValueInformation->Data );
  873. ReturnStatus = ZwQueryValueKey( LangGroupKey,
  874. &KeyValueName,
  875. KeyValuePartialInformation,
  876. KeyValueInformation,
  877. sizeof( KeyValueBuffer ),
  878. &ResultLength
  879. );
  880. if ((NT_SUCCESS(ReturnStatus)) &&
  881. (KeyValueInformation->Type == REG_SZ) &&
  882. (KeyValueInformation->DataLength > 2)
  883. ) {
  884. Ptr = (PWSTR) KeyValueInformation->Data;
  885. if (Ptr[0] == L'1' && Ptr[1] == UNICODE_NULL) {
  886. Status = STATUS_SUCCESS;
  887. }
  888. }
  889. }
  890. //
  891. // Close opened keys
  892. //
  893. ZwClose( LangGroupKey );
  894. Failed3:
  895. ZwClose( SortKey );
  896. Failed2:
  897. ZwClose( LocaleKey );
  898. Failed1:
  899. //
  900. // If an error happens, let's record it.
  901. //
  902. if (!NT_SUCCESS(ReturnStatus)) {
  903. Status = ReturnStatus;
  904. }
  905. return Status;
  906. }
  907. NTSTATUS
  908. ExpQueryNumaProcessorMap(
  909. OUT PVOID SystemInformation,
  910. IN ULONG SystemInformationLength,
  911. OUT PULONG ReturnedLength
  912. )
  913. {
  914. PSYSTEM_NUMA_INFORMATION Map;
  915. ULONG Length;
  916. ULONG ReturnCount;
  917. #if !defined(NT_UP)
  918. ULONG i;
  919. #endif
  920. Map = (PSYSTEM_NUMA_INFORMATION)SystemInformation;
  921. //
  922. // Must be able to return at least the number of nodes.
  923. //
  924. if (SystemInformationLength < sizeof(Map->HighestNodeNumber)) {
  925. return STATUS_INFO_LENGTH_MISMATCH;
  926. }
  927. Map->HighestNodeNumber = KeNumberNodes - 1;
  928. //
  929. // Return as many node masks as possible in the SystemInformation
  930. // buffer.
  931. //
  932. Length = FIELD_OFFSET(SYSTEM_NUMA_INFORMATION,
  933. ActiveProcessorsAffinityMask);
  934. ReturnCount = (SystemInformationLength - Length) /
  935. sizeof(Map->ActiveProcessorsAffinityMask[0]);
  936. if (ReturnCount > KeNumberNodes) {
  937. ReturnCount = KeNumberNodes;
  938. }
  939. if ((Length > SystemInformationLength) ||
  940. (ReturnCount == 0)) {
  941. *ReturnedLength = sizeof(Map->HighestNodeNumber);
  942. return STATUS_SUCCESS;
  943. }
  944. *ReturnedLength = FIELD_OFFSET(SYSTEM_NUMA_INFORMATION,
  945. ActiveProcessorsAffinityMask[ReturnCount]);
  946. #if !defined(NT_UP)
  947. for (i = 0; i < ReturnCount; i++) {
  948. Map->ActiveProcessorsAffinityMask[i] = KeNodeBlock[i]->ProcessorMask;
  949. }
  950. #else
  951. if (ReturnCount) {
  952. Map->ActiveProcessorsAffinityMask[0] = 1;
  953. }
  954. #endif
  955. return STATUS_SUCCESS;
  956. }
  957. NTSTATUS
  958. ExpQueryNumaAvailableMemory(
  959. OUT PVOID SystemInformation,
  960. IN ULONG SystemInformationLength,
  961. OUT PULONG ReturnedLength
  962. )
  963. {
  964. PSYSTEM_NUMA_INFORMATION Map;
  965. ULONG Length;
  966. ULONG ReturnCount;
  967. Map = (PSYSTEM_NUMA_INFORMATION)SystemInformation;
  968. //
  969. // Must be able to return at least the number of nodes.
  970. //
  971. if (SystemInformationLength < sizeof(Map->HighestNodeNumber)) {
  972. return STATUS_INFO_LENGTH_MISMATCH;
  973. }
  974. Map->HighestNodeNumber = KeNumberNodes - 1;
  975. //
  976. // Return as many node masks as possible in the SystemInformation
  977. // buffer.
  978. //
  979. Length = FIELD_OFFSET(SYSTEM_NUMA_INFORMATION,
  980. AvailableMemory);
  981. ReturnCount = (SystemInformationLength - Length) /
  982. sizeof(Map->AvailableMemory[0]);
  983. if (ReturnCount > KeNumberNodes) {
  984. ReturnCount = KeNumberNodes;
  985. }
  986. if ((Length > SystemInformationLength) ||
  987. (ReturnCount == 0)) {
  988. *ReturnedLength = sizeof(Map->HighestNodeNumber);
  989. return STATUS_SUCCESS;
  990. }
  991. *ReturnedLength = FIELD_OFFSET(SYSTEM_NUMA_INFORMATION,
  992. AvailableMemory[ReturnCount]);
  993. //
  994. // Return the aproximate number of free bytes at this time.
  995. // (It's aproximate because no lock is taken and with respect
  996. // to any user mode application its only a sample.
  997. //
  998. #if !defined(NT_UP)
  999. if (KeNumberNodes > 1) {
  1000. ULONG i;
  1001. for (i = 0; i < ReturnCount; i++) {
  1002. Map->AvailableMemory[i] =
  1003. ((ULONGLONG)KeNodeBlock[i]->FreeCount[ZeroedPageList] +
  1004. (ULONGLONG)KeNodeBlock[i]->FreeCount[FreePageList])
  1005. << PAGE_SHIFT;
  1006. }
  1007. } else
  1008. #endif
  1009. if (ReturnCount) {
  1010. Map->AvailableMemory[0] = ((ULONGLONG)MmAvailablePages) << PAGE_SHIFT;
  1011. }
  1012. return STATUS_SUCCESS;
  1013. }
  1014. NTSTATUS
  1015. ExpGetSystemBasicInformation (
  1016. OUT PSYSTEM_BASIC_INFORMATION BasicInfo
  1017. )
  1018. {
  1019. NTSTATUS NtStatus = STATUS_SUCCESS;
  1020. try {
  1021. BasicInfo->NumberOfProcessors = KeNumberProcessors;
  1022. BasicInfo->ActiveProcessorsAffinityMask = (ULONG_PTR)KeActiveProcessors;
  1023. BasicInfo->Reserved = 0;
  1024. BasicInfo->TimerResolution = KeMaximumIncrement;
  1025. BasicInfo->NumberOfPhysicalPages = MmNumberOfPhysicalPages;
  1026. BasicInfo->LowestPhysicalPageNumber = (SYSINF_PAGE_COUNT)MmLowestPhysicalPage;
  1027. BasicInfo->HighestPhysicalPageNumber = (SYSINF_PAGE_COUNT)MmHighestPhysicalPage;
  1028. BasicInfo->PageSize = PAGE_SIZE;
  1029. BasicInfo->AllocationGranularity = MM_ALLOCATION_GRANULARITY;
  1030. BasicInfo->MinimumUserModeAddress = (ULONG_PTR)MM_LOWEST_USER_ADDRESS;
  1031. BasicInfo->MaximumUserModeAddress = (ULONG_PTR)MM_HIGHEST_USER_ADDRESS;
  1032. }
  1033. except (EXCEPTION_EXECUTE_HANDLER) {
  1034. NtStatus = GetExceptionCode();
  1035. }
  1036. return NtStatus;
  1037. }
  1038. NTSTATUS
  1039. ExpGetSystemProcessorInformation (
  1040. OUT PSYSTEM_PROCESSOR_INFORMATION ProcessorInformation
  1041. )
  1042. {
  1043. NTSTATUS NtStatus = STATUS_SUCCESS;
  1044. try {
  1045. ProcessorInformation->ProcessorArchitecture = KeProcessorArchitecture;
  1046. ProcessorInformation->ProcessorLevel = KeProcessorLevel;
  1047. ProcessorInformation->ProcessorRevision = KeProcessorRevision;
  1048. ProcessorInformation->Reserved = 0;
  1049. ProcessorInformation->ProcessorFeatureBits = KeFeatureBits;
  1050. }
  1051. except (EXCEPTION_EXECUTE_HANDLER) {
  1052. NtStatus = GetExceptionCode();
  1053. }
  1054. return NtStatus;
  1055. }
  1056. #if defined(_WIN64)
  1057. NTSTATUS
  1058. ExpGetSystemEmulationBasicInformation (
  1059. OUT PSYSTEM_BASIC_INFORMATION BasicInfo
  1060. )
  1061. {
  1062. NTSTATUS NtStatus = STATUS_SUCCESS;
  1063. try {
  1064. BasicInfo->NumberOfProcessors = min(32, KeNumberProcessors);
  1065. BasicInfo->ActiveProcessorsAffinityMask = (ULONG_PTR)
  1066. ((KeActiveProcessors & 0xFFFFFFFF) | ((KeActiveProcessors & (0xFFFFFFFF << 32) ) >> 32));
  1067. BasicInfo->Reserved = 0;
  1068. BasicInfo->TimerResolution = KeMaximumIncrement;
  1069. BasicInfo->NumberOfPhysicalPages = (MmNumberOfPhysicalPages * (PAGE_SIZE >> PAGE_SHIFT_X86NT));
  1070. BasicInfo->LowestPhysicalPageNumber = (SYSINF_PAGE_COUNT)MmLowestPhysicalPage;
  1071. BasicInfo->HighestPhysicalPageNumber = (SYSINF_PAGE_COUNT)MmHighestPhysicalPage;
  1072. BasicInfo->PageSize = PAGE_SIZE_X86NT;
  1073. BasicInfo->AllocationGranularity = MM_ALLOCATION_GRANULARITY;
  1074. BasicInfo->MinimumUserModeAddress = 0x00000000000010000UI64;
  1075. //
  1076. // NOTE: MmGetMaxWowAddress return the highest usermode address boundary,
  1077. // thus we are subtracting one to get the maximum accessible usermode address
  1078. //
  1079. BasicInfo->MaximumUserModeAddress = ((ULONG_PTR)MmGetMaxWowAddress () - 1);
  1080. }
  1081. except (EXCEPTION_EXECUTE_HANDLER) {
  1082. NtStatus = GetExceptionCode();
  1083. }
  1084. return NtStatus;
  1085. }
  1086. #endif
  1087. NTSTATUS
  1088. NtQuerySystemInformation (
  1089. IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
  1090. OUT PVOID SystemInformation,
  1091. IN ULONG SystemInformationLength,
  1092. OUT PULONG ReturnLength OPTIONAL
  1093. )
  1094. /*++
  1095. Routine Description:
  1096. This function queries information about the system.
  1097. Arguments:
  1098. SystemInformationClass - The system information class about which
  1099. to retrieve information.
  1100. SystemInformation - A pointer to a buffer which receives the specified
  1101. information. The format and content of the buffer depend on the
  1102. specified system information class.
  1103. SystemInformation Format by Information Class:
  1104. SystemBasicInformation - Data type is SYSTEM_BASIC_INFORMATION
  1105. SYSTEM_BASIC_INFORMATION Structure
  1106. ULONG Reserved - Always zero.
  1107. ULONG TimerResolutionInMicroSeconds - The resolution of
  1108. the hardware time. All time values in NT are
  1109. specified as 64-bit LARGE_INTEGER values in units of
  1110. 100 nanoseconds. This field allows an application to
  1111. understand how many of the low order bits of a system
  1112. time value are insignificant.
  1113. ULONG PageSize - The physical page size for virtual memory
  1114. objects. Physical memory is committed in PageSize
  1115. chunks.
  1116. ULONG AllocationGranularity - The logical page size for
  1117. virtual memory objects. Allocating 1 byte of virtual
  1118. memory will actually allocate AllocationGranularity
  1119. bytes of virtual memory. Storing into that byte will
  1120. commit the first physical page of the virtual memory.
  1121. ULONG MinimumUserModeAddress - The smallest valid user mode
  1122. address. The first AllocationGranularity bytes of
  1123. the virtual address space are reserved. This forces
  1124. access violations for code the dereferences a zero
  1125. pointer.
  1126. ULONG MaximumUserModeAddress - The largest valid user mode
  1127. address. The next AllocationGranularity bytes of
  1128. the virtual address space are reserved. This allows
  1129. system service routines to validate user mode pointer
  1130. parameters quickly.
  1131. KAFFINITY ActiveProcessorsAffinityMask - The affinity mask
  1132. for the current hardware configuration.
  1133. CCHAR NumberOfProcessors - The number of processors
  1134. in the current hardware configuration.
  1135. SystemProcessorInformation - Data type is SYSTEM_PROCESSOR_INFORMATION
  1136. SYSTEM_PROCESSOR_INFORMATION Structure
  1137. USHORT ProcessorArchitecture - The processor architecture:
  1138. PROCESSOR_ARCHITECTURE_INTEL
  1139. PROCESSOR_ARCHITECTURE_IA64
  1140. PROCESSOR_ARCHITECTURE_MIPS
  1141. PROCESSOR_ARCHITECTURE_ALPHA
  1142. PROCESSOR_ARCHITECTURE_PPC
  1143. USHORT ProcessorLevel - architecture dependent processor level.
  1144. This is the least common denominator for an MP system:
  1145. For PROCESSOR_ARCHITECTURE_INTEL:
  1146. 3 - 386
  1147. 4 - 486
  1148. 5 - 586 or Pentium
  1149. For PROCESSOR_ARCHITECTURE_IA64:
  1150. 7 - Itanium
  1151. 31 - Itanium 2
  1152. For PROCESSOR_ARCHITECTURE_MIPS:
  1153. 00xx - where xx is 8-bit implementation number (bits 8-15 of
  1154. PRId register.
  1155. 0004 - R4000
  1156. For PROCESSOR_ARCHITECTURE_ALPHA:
  1157. xxxx - where xxxx is 16-bit processor version number (low
  1158. order 16 bits of processor version number from firmware)
  1159. 21064 - 21064
  1160. 21066 - 21066
  1161. 21164 - 21164
  1162. For PROCESSOR_ARCHITECTURE_PPC:
  1163. xxxx - where xxxx is 16-bit processor version number (high
  1164. order 16 bits of Processor Version Register).
  1165. 1 - 601
  1166. 3 - 603
  1167. 4 - 604
  1168. 6 - 603+
  1169. 9 - 604+
  1170. 20 - 620
  1171. USHORT ProcessorRevision - architecture dependent processor revision.
  1172. This is the least common denominator for an MP system:
  1173. For PROCESSOR_ARCHITECTURE_INTEL:
  1174. For Old Intel 386 or 486:
  1175. FFxx - where xx is displayed as a hexadecimal CPU stepping
  1176. (e.g. FFD0 is D0 stepping)
  1177. For Intel Pentium or Cyrix/NexGen 486
  1178. xxyy - where xx is model number and yy is stepping, so
  1179. 0201 is Model 2, Stepping 1
  1180. For PROCESSOR_ARCHITECTURE_IA64:
  1181. xxyy - where xx is model number and yy is stepping, so
  1182. 0201 is Model 2, Stepping 1
  1183. For PROCESSOR_ARCHITECTURE_MIPS:
  1184. 00xx is 8-bit revision number of processor (low order 8 bits
  1185. of PRId Register
  1186. For PROCESSOR_ARCHITECTURE_ALPHA:
  1187. xxyy - where xxyy is 16-bit processor revision number (low
  1188. order 16 bits of processor revision number from firmware).
  1189. Displayed as Model 'A'+xx, Pass yy
  1190. For PROCESSOR_ARCHITECTURE_PPC:
  1191. xxyy - where xxyy is 16-bit processor revision number (low
  1192. order 16 bits of Processor Version Register). Displayed
  1193. as a fixed point number xx.yy
  1194. USHORT Reserved - Always zero.
  1195. ULONG ProcessorFeatureBits - architecture dependent processor feature bits.
  1196. This is the least common denominator for an MP system.
  1197. SystemPerformanceInformation - Data type is SYSTEM_PERFORMANCE_INFORMATION
  1198. SYSTEM_PERFORMANCE_INFORMATION Structure
  1199. LARGE_INTEGER IdleProcessTime - Returns the kernel time of the idle
  1200. process.
  1201. LARGE_INTEGER IoReadTransferCount;
  1202. LARGE_INTEGER IoWriteTransferCount;
  1203. LARGE_INTEGER IoOtherTransferCount;
  1204. LARGE_INTEGER KernelTime;
  1205. LARGE_INTEGER UserTime;
  1206. ULONG IoReadOperationCount;
  1207. ULONG IoWriteOperationCount;
  1208. ULONG IoOtherOperationCount;
  1209. ULONG AvailablePages;
  1210. ULONG CommittedPages;
  1211. ULONG PageFaultCount;
  1212. ULONG CopyOnWriteCount;
  1213. ULONG TransitionCount;
  1214. ULONG CacheTransitionCount;
  1215. ULONG DemandZeroCount;
  1216. ULONG PageReadCount;
  1217. ULONG PageReadIoCount;
  1218. ULONG CacheReadCount;
  1219. ULONG CacheIoCount;
  1220. ULONG DirtyPagesWriteCount;
  1221. ULONG DirtyWriteIoCount;
  1222. ULONG MappedPagesWriteCount;
  1223. ULONG MappedWriteIoCount;
  1224. ULONG PagedPoolPages;
  1225. ULONG NonPagedPoolPages;
  1226. ULONG PagedPoolAllocs;
  1227. ULONG PagedPoolFrees;
  1228. ULONG NonPagedPoolAllocs;
  1229. ULONG NonPagedPoolFrees;
  1230. ULONG LpcThreadsWaitingInReceive;
  1231. ULONG LpcThreadsWaitingForReply;
  1232. SystemProcessInformation - Data type is SYSTEM_PROCESS_INFORMATION
  1233. SYSTEM_PROCESS_INFORMATION Structure
  1234. SystemDockInformation - Data type is SYSTEM_DOCK_INFORMATION
  1235. SYSTEM_DOCK_INFORMATION Structure
  1236. SYSTEM_DOCKED_STATE DockState - Ordinal specifying the current docking state. Possible values:
  1237. SystemDockStateUnknown - The docking state of the system could not be determined.
  1238. SystemUndocked - The system is undocked.
  1239. SystemDocked - The system is docked.
  1240. ULONG DockIdLength - Specifies the length in characters of the Dock ID string
  1241. (not including terminating NULL).
  1242. ULONG SerialNumberOffset - Specifies the character offset of the Serial Number within
  1243. the DockId buffer.
  1244. ULONG SerialNumberLength - Specifies the length in characters of the Serial Number
  1245. string (not including terminating NULL).
  1246. WCHAR DockId - Character buffer containing two null-terminated strings. The first
  1247. string is a character representation of the dock ID number, starting
  1248. at the beginning of the buffer. The second string is a character
  1249. representation of the machine's serial number, starting at character
  1250. offset SerialNumberOffset in the buffer.
  1251. SystemPowerSettings - Data type is SYSTEM_POWER_SETTINGS
  1252. SYSTEM_POWER_INFORMATION Structure
  1253. BOOLEAN SystemSuspendSupported - Supplies a BOOLEAN as to
  1254. whether the system suspend is enabled or not.
  1255. BOOLEAN SystemHibernateSupported - Supplies a BOOLEAN as to
  1256. whether the system hibernate is enabled or not.
  1257. BOOLEAN ResumeTimerSupportsSuspend - Supplies a BOOLEAN as to
  1258. whether the resuming from an external programmed timer
  1259. from within a system suspend is enabled or not.
  1260. BOOLEAN ResumeTimerSupportsHibernate - Supplies a BOOLEAN as to
  1261. whether or resuming from an external programmed timer
  1262. from within a system hibernate is enabled or not.
  1263. BOOLEAN LidSupported - Supplies a BOOLEAN as to whether or not
  1264. the suspending and resuming by Lid are enabled or not.
  1265. BOOLEAN TurboSettingSupported - Supplies a BOOLEAN as to whether
  1266. or not the system supports a turbo mode setting.
  1267. BOOLEAN TurboMode - Supplies a BOOLEAN as to whether or not
  1268. the system is in turbo mode.
  1269. BOOLEAN SystemAcOrDc - Supplies a BOOLEAN as to whether or not
  1270. the system is in AC mode.
  1271. BOOLEAN DisablePowerDown - If TRUE, signifies that all requests to
  1272. PoRequestPowerChange for a SET_POWER-PowerDown irp are to
  1273. be ignored.
  1274. LARGE_INTEGER SpindownDrives - If non-zero, signifies to the
  1275. cache manager (or the IO subsystem) to optimize drive
  1276. accesses based upon power saves, are that drives are to
  1277. be spun down as appropriate. The value represents to user's
  1278. requested disk spin down timeout.
  1279. SystemProcessorSpeedInformation - Data type is SYSTEM_PROCESSOR_SPEED_INFORMATION
  1280. SYSTEM_PROCESSOR_SPEED_INFORMATION Structure (same as HalProcessorSpeedInformation)
  1281. ULONG MaximumProcessorSpeed - The maximum hertz the processor is
  1282. capable of. This information is used by the UI to draw the
  1283. appropriate scale. This field is read-only and cannot be
  1284. set.
  1285. ULONG CurrentAvailableSpeed - The hertz for which the processor
  1286. runs at when not idle. This field is read-only and cannot
  1287. be set.
  1288. ULONG ConfiguredSpeedLimit - The hertz for which the processor
  1289. is limited to due to the current configuration.
  1290. UCHAR PowerState
  1291. 0 - Normal
  1292. 1 - The processor speed is being limited due to available
  1293. power restrictions. This field id read-only by the system.
  1294. UCHAR ThermalState
  1295. 0 - Normal
  1296. 1 - The processors speed is being limited due to thermal
  1297. restrictions. This field is read-only by the system.
  1298. UCHAR TurboState
  1299. 0 - Normal
  1300. 1 - The processors speed is being limited by the fact that
  1301. the system turbo mode is currently disabled which is
  1302. requested to obtain more processor speed.
  1303. SystemInformationLength - Specifies the length in bytes of the system
  1304. information buffer.
  1305. ReturnLength - An optional pointer which, if specified, receives the
  1306. number of bytes placed in the system information buffer.
  1307. Return Value:
  1308. Returns one of the following status codes:
  1309. STATUS_SUCCESS - normal, successful completion.
  1310. STATUS_INVALID_INFO_CLASS - The SystemInformationClass parameter
  1311. did not specify a valid value.
  1312. STATUS_INFO_LENGTH_MISMATCH - The value of the SystemInformationLength
  1313. parameter did not match the length required for the information
  1314. class requested by the SystemInformationClass parameter.
  1315. STATUS_ACCESS_VIOLATION - Either the SystemInformation buffer pointer
  1316. or the ReturnLength pointer value specified an invalid address.
  1317. STATUS_WORKING_SET_QUOTA - The process does not have sufficient
  1318. working set to lock the specified output structure in memory.
  1319. STATUS_INSUFFICIENT_RESOURCES - Insufficient system resources exist
  1320. for this request to complete.
  1321. --*/
  1322. {
  1323. KPROCESSOR_MODE PreviousMode;
  1324. SYSTEM_TIMEOFDAY_INFORMATION LocalTimeOfDayInfo;
  1325. SYSTEM_PERFORMANCE_INFORMATION LocalPerformanceInfo;
  1326. PSYSTEM_PERFORMANCE_INFORMATION PerformanceInfo;
  1327. PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION ProcessorPerformanceInfo;
  1328. PSYSTEM_CALL_COUNT_INFORMATION CallCountInformation;
  1329. PSYSTEM_DEVICE_INFORMATION DeviceInformation;
  1330. PCONFIGURATION_INFORMATION ConfigInfo;
  1331. PSYSTEM_EXCEPTION_INFORMATION ExceptionInformation;
  1332. PSYSTEM_FILECACHE_INFORMATION FileCache;
  1333. PSYSTEM_QUERY_TIME_ADJUST_INFORMATION TimeAdjustmentInformation;
  1334. PSYSTEM_KERNEL_DEBUGGER_INFORMATION KernelDebuggerInformation;
  1335. PSYSTEM_CONTEXT_SWITCH_INFORMATION ContextSwitchInformation;
  1336. PSYSTEM_INTERRUPT_INFORMATION InterruptInformation;
  1337. PSYSTEM_SESSION_PROCESS_INFORMATION SessionProcessInformation;
  1338. PVOID ProcessInformation;
  1339. ULONG ProcessInformationLength;
  1340. PSYSTEM_SESSION_POOLTAG_INFORMATION SessionPoolTagInformation;
  1341. PSYSTEM_SESSION_MAPPED_VIEW_INFORMATION SessionMappedViewInformation;
  1342. ULONG SessionPoolTagInformationLength;
  1343. NTSTATUS Status;
  1344. PKPRCB Prcb;
  1345. ULONG Length = 0;
  1346. ULONG i;
  1347. ULONG ContextSwitches;
  1348. PULONG TableLimit, TableCounts;
  1349. PKSERVICE_TABLE_DESCRIPTOR Table;
  1350. ULONG SessionId;
  1351. ULONG Alignment;
  1352. PAGED_CODE();
  1353. //
  1354. // Assume successful completion.
  1355. //
  1356. Status = STATUS_SUCCESS;
  1357. try {
  1358. //
  1359. // Get previous processor mode and probe output argument if necessary.
  1360. //
  1361. PreviousMode = KeGetPreviousMode();
  1362. if (PreviousMode != KernelMode) {
  1363. Alignment = sizeof(ULONG);
  1364. if (SystemInformationClass == SystemKernelDebuggerInformation) {
  1365. Alignment = sizeof(BOOLEAN);
  1366. } else if (SystemInformationClass == SystemLocksInformation) {
  1367. Alignment = sizeof(PVOID);
  1368. }
  1369. ProbeForWrite(SystemInformation,
  1370. SystemInformationLength,
  1371. Alignment);
  1372. if (ARGUMENT_PRESENT(ReturnLength)) {
  1373. ProbeForWriteUlong(ReturnLength);
  1374. }
  1375. }
  1376. if (ARGUMENT_PRESENT(ReturnLength)) {
  1377. *ReturnLength = 0;
  1378. }
  1379. switch (SystemInformationClass) {
  1380. case SystemBasicInformation:
  1381. if (SystemInformationLength != sizeof( SYSTEM_BASIC_INFORMATION )) {
  1382. return STATUS_INFO_LENGTH_MISMATCH;
  1383. }
  1384. Status = ExpGetSystemBasicInformation ((PSYSTEM_BASIC_INFORMATION)SystemInformation);
  1385. if (NT_SUCCESS (Status) && ARGUMENT_PRESENT( ReturnLength )) {
  1386. *ReturnLength = sizeof( SYSTEM_BASIC_INFORMATION );
  1387. }
  1388. break;
  1389. case SystemEmulationBasicInformation:
  1390. if (SystemInformationLength != sizeof( SYSTEM_BASIC_INFORMATION )) {
  1391. return STATUS_INFO_LENGTH_MISMATCH;
  1392. }
  1393. #if defined(_WIN64)
  1394. Status = ExpGetSystemEmulationBasicInformation ((PSYSTEM_BASIC_INFORMATION)SystemInformation);
  1395. #else
  1396. Status = ExpGetSystemBasicInformation ((PSYSTEM_BASIC_INFORMATION)SystemInformation);
  1397. #endif
  1398. if (NT_SUCCESS (Status) && ARGUMENT_PRESENT( ReturnLength )) {
  1399. *ReturnLength = sizeof( SYSTEM_BASIC_INFORMATION );
  1400. }
  1401. break;
  1402. case SystemProcessorInformation:
  1403. if (SystemInformationLength < sizeof( SYSTEM_PROCESSOR_INFORMATION )) {
  1404. return STATUS_INFO_LENGTH_MISMATCH;
  1405. }
  1406. Status = ExpGetSystemProcessorInformation ((PSYSTEM_PROCESSOR_INFORMATION)SystemInformation);
  1407. if (NT_SUCCESS (Status) && ARGUMENT_PRESENT( ReturnLength )) {
  1408. *ReturnLength = sizeof( SYSTEM_PROCESSOR_INFORMATION );
  1409. }
  1410. break;
  1411. case SystemEmulationProcessorInformation:
  1412. if (SystemInformationLength < sizeof( SYSTEM_PROCESSOR_INFORMATION )) {
  1413. return STATUS_INFO_LENGTH_MISMATCH;
  1414. }
  1415. #if defined(_WIN64)
  1416. Status = ExpGetSystemEmulationProcessorInformation ((PSYSTEM_PROCESSOR_INFORMATION)SystemInformation);
  1417. #else
  1418. Status = ExpGetSystemProcessorInformation ((PSYSTEM_PROCESSOR_INFORMATION)SystemInformation);
  1419. #endif
  1420. if (NT_SUCCESS (Status) && ARGUMENT_PRESENT( ReturnLength )) {
  1421. *ReturnLength = sizeof( SYSTEM_PROCESSOR_INFORMATION );
  1422. }
  1423. break;
  1424. case SystemPerformanceInformation:
  1425. if (SystemInformationLength < sizeof( SYSTEM_PERFORMANCE_INFORMATION )) {
  1426. return STATUS_INFO_LENGTH_MISMATCH;
  1427. }
  1428. PerformanceInfo = (PSYSTEM_PERFORMANCE_INFORMATION)SystemInformation;
  1429. //
  1430. // Io information.
  1431. //
  1432. LocalPerformanceInfo.IoReadTransferCount = IoReadTransferCount;
  1433. LocalPerformanceInfo.IoWriteTransferCount = IoWriteTransferCount;
  1434. LocalPerformanceInfo.IoOtherTransferCount = IoOtherTransferCount;
  1435. LocalPerformanceInfo.IoReadOperationCount = IoReadOperationCount;
  1436. LocalPerformanceInfo.IoWriteOperationCount = IoWriteOperationCount;
  1437. LocalPerformanceInfo.IoOtherOperationCount = IoOtherOperationCount;
  1438. //
  1439. // Ke information.
  1440. //
  1441. // These counters are kept on a per processor basis and must
  1442. // be totaled.
  1443. //
  1444. {
  1445. ULONG FirstLevelTbFills = 0;
  1446. ULONG SecondLevelTbFills = 0;
  1447. ULONG SystemCalls = 0;
  1448. // ULONG InterruptCount = 0;
  1449. ContextSwitches = 0;
  1450. for (i = 0; i < (ULONG)KeNumberProcessors; i += 1) {
  1451. Prcb = KiProcessorBlock[i];
  1452. if (Prcb != NULL) {
  1453. ContextSwitches += KeGetContextSwitches(Prcb);
  1454. FirstLevelTbFills += Prcb->KeFirstLevelTbFills;
  1455. // InterruptCount += Prcb->KeInterruptCount;
  1456. SecondLevelTbFills += Prcb->KeSecondLevelTbFills;
  1457. SystemCalls += Prcb->KeSystemCalls;
  1458. }
  1459. }
  1460. LocalPerformanceInfo.ContextSwitches = ContextSwitches;
  1461. LocalPerformanceInfo.FirstLevelTbFills = FirstLevelTbFills;
  1462. // LocalPerformanceInfo.InterruptCount = KeInterruptCount;
  1463. LocalPerformanceInfo.SecondLevelTbFills = SecondLevelTbFills;
  1464. LocalPerformanceInfo.SystemCalls = SystemCalls;
  1465. }
  1466. //
  1467. // Mm information.
  1468. //
  1469. LocalPerformanceInfo.AvailablePages = MmAvailablePages;
  1470. LocalPerformanceInfo.CommittedPages = (SYSINF_PAGE_COUNT)MmTotalCommittedPages;
  1471. LocalPerformanceInfo.CommitLimit = (SYSINF_PAGE_COUNT)MmTotalCommitLimit;
  1472. LocalPerformanceInfo.PeakCommitment = (SYSINF_PAGE_COUNT)MmPeakCommitment;
  1473. LocalPerformanceInfo.PageFaultCount = MmInfoCounters.PageFaultCount;
  1474. LocalPerformanceInfo.CopyOnWriteCount = MmInfoCounters.CopyOnWriteCount;
  1475. LocalPerformanceInfo.TransitionCount = MmInfoCounters.TransitionCount;
  1476. LocalPerformanceInfo.CacheTransitionCount = MmInfoCounters.CacheTransitionCount;
  1477. LocalPerformanceInfo.DemandZeroCount = MmInfoCounters.DemandZeroCount;
  1478. LocalPerformanceInfo.PageReadCount = MmInfoCounters.PageReadCount;
  1479. LocalPerformanceInfo.PageReadIoCount = MmInfoCounters.PageReadIoCount;
  1480. LocalPerformanceInfo.CacheReadCount = MmInfoCounters.CacheReadCount;
  1481. LocalPerformanceInfo.CacheIoCount = MmInfoCounters.CacheIoCount;
  1482. LocalPerformanceInfo.DirtyPagesWriteCount = MmInfoCounters.DirtyPagesWriteCount;
  1483. LocalPerformanceInfo.DirtyWriteIoCount = MmInfoCounters.DirtyWriteIoCount;
  1484. LocalPerformanceInfo.MappedPagesWriteCount = MmInfoCounters.MappedPagesWriteCount;
  1485. LocalPerformanceInfo.MappedWriteIoCount = MmInfoCounters.MappedWriteIoCount;
  1486. LocalPerformanceInfo.FreeSystemPtes = MmTotalFreeSystemPtes[0];
  1487. LocalPerformanceInfo.ResidentSystemCodePage = MmSystemCodePage;
  1488. LocalPerformanceInfo.ResidentSystemCachePage = MmSystemCachePage;
  1489. LocalPerformanceInfo.ResidentPagedPoolPage = MmPagedPoolPage;
  1490. LocalPerformanceInfo.ResidentSystemDriverPage = MmSystemDriverPage;
  1491. LocalPerformanceInfo.TotalSystemCodePages = MmTotalSystemCodePages;
  1492. LocalPerformanceInfo.TotalSystemDriverPages = MmTotalSystemDriverPages;
  1493. LocalPerformanceInfo.AvailablePagedPoolPages = (ULONG)MmAvailablePoolInPages (PagedPool);
  1494. //
  1495. // Process information.
  1496. //
  1497. LocalPerformanceInfo.IdleProcessTime.QuadPart =
  1498. UInt32x32To64(PsIdleProcess->Pcb.KernelTime,
  1499. KeMaximumIncrement);
  1500. //
  1501. // Pool information.
  1502. //
  1503. LocalPerformanceInfo.PagedPoolPages = 0;
  1504. LocalPerformanceInfo.NonPagedPoolPages = 0;
  1505. LocalPerformanceInfo.PagedPoolAllocs = 0;
  1506. LocalPerformanceInfo.PagedPoolFrees = 0;
  1507. LocalPerformanceInfo.PagedPoolLookasideHits = 0;
  1508. LocalPerformanceInfo.NonPagedPoolAllocs = 0;
  1509. LocalPerformanceInfo.NonPagedPoolFrees = 0;
  1510. LocalPerformanceInfo.NonPagedPoolLookasideHits = 0;
  1511. ExQueryPoolUsage( &LocalPerformanceInfo.PagedPoolPages,
  1512. &LocalPerformanceInfo.NonPagedPoolPages,
  1513. &LocalPerformanceInfo.PagedPoolAllocs,
  1514. &LocalPerformanceInfo.PagedPoolFrees,
  1515. &LocalPerformanceInfo.PagedPoolLookasideHits,
  1516. &LocalPerformanceInfo.NonPagedPoolAllocs,
  1517. &LocalPerformanceInfo.NonPagedPoolFrees,
  1518. &LocalPerformanceInfo.NonPagedPoolLookasideHits
  1519. );
  1520. //
  1521. // Cache Manager information.
  1522. //
  1523. LocalPerformanceInfo.CcFastReadNoWait = CcFastReadNoWait;
  1524. LocalPerformanceInfo.CcFastReadWait = CcFastReadWait;
  1525. LocalPerformanceInfo.CcFastReadResourceMiss = CcFastReadResourceMiss;
  1526. LocalPerformanceInfo.CcFastReadNotPossible = CcFastReadNotPossible;
  1527. LocalPerformanceInfo.CcFastMdlReadNoWait = CcFastMdlReadNoWait;
  1528. LocalPerformanceInfo.CcFastMdlReadWait = CcFastMdlReadWait;
  1529. LocalPerformanceInfo.CcFastMdlReadResourceMiss = CcFastMdlReadResourceMiss;
  1530. LocalPerformanceInfo.CcFastMdlReadNotPossible = CcFastMdlReadNotPossible;
  1531. LocalPerformanceInfo.CcMapDataNoWait = CcMapDataNoWait;
  1532. LocalPerformanceInfo.CcMapDataWait = CcMapDataWait;
  1533. LocalPerformanceInfo.CcMapDataNoWaitMiss = CcMapDataNoWaitMiss;
  1534. LocalPerformanceInfo.CcMapDataWaitMiss = CcMapDataWaitMiss;
  1535. LocalPerformanceInfo.CcPinMappedDataCount = CcPinMappedDataCount;
  1536. LocalPerformanceInfo.CcPinReadNoWait = CcPinReadNoWait;
  1537. LocalPerformanceInfo.CcPinReadWait = CcPinReadWait;
  1538. LocalPerformanceInfo.CcPinReadNoWaitMiss = CcPinReadNoWaitMiss;
  1539. LocalPerformanceInfo.CcPinReadWaitMiss = CcPinReadWaitMiss;
  1540. LocalPerformanceInfo.CcCopyReadNoWait = CcCopyReadNoWait;
  1541. LocalPerformanceInfo.CcCopyReadWait = CcCopyReadWait;
  1542. LocalPerformanceInfo.CcCopyReadNoWaitMiss = CcCopyReadNoWaitMiss;
  1543. LocalPerformanceInfo.CcCopyReadWaitMiss = CcCopyReadWaitMiss;
  1544. LocalPerformanceInfo.CcMdlReadNoWait = CcMdlReadNoWait;
  1545. LocalPerformanceInfo.CcMdlReadWait = CcMdlReadWait;
  1546. LocalPerformanceInfo.CcMdlReadNoWaitMiss = CcMdlReadNoWaitMiss;
  1547. LocalPerformanceInfo.CcMdlReadWaitMiss = CcMdlReadWaitMiss;
  1548. LocalPerformanceInfo.CcReadAheadIos = CcReadAheadIos;
  1549. LocalPerformanceInfo.CcLazyWriteIos = CcLazyWriteIos;
  1550. LocalPerformanceInfo.CcLazyWritePages = CcLazyWritePages;
  1551. LocalPerformanceInfo.CcDataFlushes = CcDataFlushes;
  1552. LocalPerformanceInfo.CcDataPages = CcDataPages;
  1553. #if !defined(NT_UP)
  1554. //
  1555. // On an MP machines go sum up some other 'hot' cache manager
  1556. // statistics.
  1557. //
  1558. for (i = 0; i < (ULONG)KeNumberProcessors; i++) {
  1559. Prcb = KiProcessorBlock[i];
  1560. LocalPerformanceInfo.CcFastReadNoWait += Prcb->CcFastReadNoWait;
  1561. LocalPerformanceInfo.CcFastReadWait += Prcb->CcFastReadWait;
  1562. LocalPerformanceInfo.CcFastReadNotPossible += Prcb->CcFastReadNotPossible;
  1563. LocalPerformanceInfo.CcCopyReadNoWait += Prcb->CcCopyReadNoWait;
  1564. LocalPerformanceInfo.CcCopyReadWait += Prcb->CcCopyReadWait;
  1565. LocalPerformanceInfo.CcCopyReadNoWaitMiss += Prcb->CcCopyReadNoWaitMiss;
  1566. }
  1567. #endif
  1568. *PerformanceInfo = LocalPerformanceInfo;
  1569. if (ARGUMENT_PRESENT( ReturnLength )) {
  1570. *ReturnLength = sizeof(LocalPerformanceInfo);
  1571. }
  1572. break;
  1573. case SystemProcessorPerformanceInformation:
  1574. if (SystemInformationLength <
  1575. sizeof( SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION )) {
  1576. return STATUS_INFO_LENGTH_MISMATCH;
  1577. }
  1578. ProcessorPerformanceInfo =
  1579. (PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) SystemInformation;
  1580. Length = 0;
  1581. for (i = 0; i < (ULONG)KeNumberProcessors; i++) {
  1582. Prcb = KiProcessorBlock[i];
  1583. if (Prcb != NULL) {
  1584. if (SystemInformationLength < Length + sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION))
  1585. break;
  1586. Length += sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION);
  1587. ProcessorPerformanceInfo->UserTime.QuadPart =
  1588. UInt32x32To64(Prcb->UserTime,
  1589. KeMaximumIncrement);
  1590. ProcessorPerformanceInfo->KernelTime.QuadPart =
  1591. UInt32x32To64(Prcb->KernelTime,
  1592. KeMaximumIncrement);
  1593. ProcessorPerformanceInfo->DpcTime.QuadPart =
  1594. UInt32x32To64(Prcb->DpcTime,
  1595. KeMaximumIncrement);
  1596. ProcessorPerformanceInfo->InterruptTime.QuadPart =
  1597. UInt32x32To64(Prcb->InterruptTime,
  1598. KeMaximumIncrement);
  1599. ProcessorPerformanceInfo->IdleTime.QuadPart =
  1600. UInt32x32To64(Prcb->IdleThread->KernelTime,
  1601. KeMaximumIncrement);
  1602. ProcessorPerformanceInfo->InterruptCount = Prcb->InterruptCount;
  1603. ProcessorPerformanceInfo++;
  1604. }
  1605. }
  1606. if (ARGUMENT_PRESENT( ReturnLength )) {
  1607. *ReturnLength = Length;
  1608. }
  1609. break;
  1610. case SystemProcessorPowerInformation:
  1611. if (SystemInformationLength < sizeof( SYSTEM_PROCESSOR_POWER_INFORMATION )) {
  1612. return STATUS_INFO_LENGTH_MISMATCH;
  1613. }
  1614. ExpGetProcessorPowerInformation(
  1615. SystemInformation,
  1616. SystemInformationLength,
  1617. &Length
  1618. );
  1619. if (ARGUMENT_PRESENT( ReturnLength )) {
  1620. *ReturnLength = Length;
  1621. }
  1622. break;
  1623. case SystemProcessorIdleInformation:
  1624. if (SystemInformationLength < sizeof( SYSTEM_PROCESSOR_IDLE_INFORMATION )) {
  1625. return STATUS_INFO_LENGTH_MISMATCH;
  1626. }
  1627. ExpGetProcessorIdleInformation(
  1628. SystemInformation,
  1629. SystemInformationLength,
  1630. &Length
  1631. );
  1632. if (ARGUMENT_PRESENT( ReturnLength )) {
  1633. *ReturnLength = Length;
  1634. }
  1635. break;
  1636. case SystemTimeOfDayInformation:
  1637. if (SystemInformationLength > sizeof (SYSTEM_TIMEOFDAY_INFORMATION)) {
  1638. return STATUS_INFO_LENGTH_MISMATCH;
  1639. }
  1640. RtlZeroMemory (&LocalTimeOfDayInfo, sizeof(LocalTimeOfDayInfo));
  1641. KeQuerySystemTime(&LocalTimeOfDayInfo.CurrentTime);
  1642. LocalTimeOfDayInfo.BootTime = KeBootTime;
  1643. LocalTimeOfDayInfo.TimeZoneBias = ExpTimeZoneBias;
  1644. LocalTimeOfDayInfo.TimeZoneId = ExpCurrentTimeZoneId;
  1645. LocalTimeOfDayInfo.BootTimeBias = KeBootTimeBias;
  1646. LocalTimeOfDayInfo.SleepTimeBias = KeInterruptTimeBias;
  1647. try {
  1648. RtlCopyMemory (
  1649. SystemInformation,
  1650. &LocalTimeOfDayInfo,
  1651. SystemInformationLength
  1652. );
  1653. if (ARGUMENT_PRESENT(ReturnLength) ) {
  1654. *ReturnLength = SystemInformationLength;
  1655. }
  1656. } except(EXCEPTION_EXECUTE_HANDLER) {
  1657. return GetExceptionCode ();
  1658. }
  1659. break;
  1660. //
  1661. // Query system time adjustment information.
  1662. //
  1663. case SystemTimeAdjustmentInformation:
  1664. if (SystemInformationLength != sizeof( SYSTEM_QUERY_TIME_ADJUST_INFORMATION )) {
  1665. return STATUS_INFO_LENGTH_MISMATCH;
  1666. }
  1667. TimeAdjustmentInformation =
  1668. (PSYSTEM_QUERY_TIME_ADJUST_INFORMATION)SystemInformation;
  1669. TimeAdjustmentInformation->TimeAdjustment = KeTimeAdjustment;
  1670. TimeAdjustmentInformation->TimeIncrement = KeMaximumIncrement;
  1671. TimeAdjustmentInformation->Enable = KeTimeSynchronization;
  1672. break;
  1673. case SystemSummaryMemoryInformation:
  1674. case SystemFullMemoryInformation:
  1675. if (SystemInformationLength < sizeof( SYSTEM_MEMORY_INFORMATION )) {
  1676. return STATUS_INFO_LENGTH_MISMATCH;
  1677. }
  1678. Status = MmMemoryUsage (SystemInformation,
  1679. SystemInformationLength,
  1680. (SystemInformationClass == SystemFullMemoryInformation) ? 0 : 1,
  1681. &Length);
  1682. if (NT_SUCCESS(Status) && ARGUMENT_PRESENT( ReturnLength )) {
  1683. *ReturnLength = Length;
  1684. }
  1685. break;
  1686. case SystemPathInformation:
  1687. #if DBG
  1688. DbgPrint( "EX: SystemPathInformation now available via SharedUserData\n" );
  1689. DbgBreakPoint();
  1690. #endif
  1691. return STATUS_NOT_IMPLEMENTED;
  1692. break;
  1693. case SystemProcessInformation:
  1694. case SystemExtendedProcessInformation:
  1695. {
  1696. BOOLEAN ExtendedInformation;
  1697. if (SystemInformationClass == SystemProcessInformation ) {
  1698. ExtendedInformation = FALSE;
  1699. } else {
  1700. ExtendedInformation = TRUE;
  1701. }
  1702. Status = ExpGetProcessInformation (SystemInformation,
  1703. SystemInformationLength,
  1704. &Length,
  1705. NULL,
  1706. ExtendedInformation);
  1707. if (ARGUMENT_PRESENT( ReturnLength )) {
  1708. *ReturnLength = Length;
  1709. }
  1710. }
  1711. break;
  1712. case SystemSessionProcessInformation:
  1713. SessionProcessInformation =
  1714. (PSYSTEM_SESSION_PROCESS_INFORMATION)SystemInformation;
  1715. if (SystemInformationLength < sizeof( SYSTEM_SESSION_PROCESS_INFORMATION)) {
  1716. return STATUS_INFO_LENGTH_MISMATCH;
  1717. }
  1718. //
  1719. // The lower level locks the buffer specified below into memory using MmProbeAndLockPages.
  1720. // We don't need to probe the buffers here.
  1721. //
  1722. SessionId = SessionProcessInformation->SessionId;
  1723. ProcessInformation = SessionProcessInformation->Buffer;
  1724. ProcessInformationLength = SessionProcessInformation->SizeOfBuf;
  1725. if (!POINTER_IS_ALIGNED (ProcessInformation, sizeof (ULONG))) {
  1726. return STATUS_DATATYPE_MISALIGNMENT;
  1727. }
  1728. Status = ExpGetProcessInformation (ProcessInformation,
  1729. ProcessInformationLength,
  1730. &Length,
  1731. &SessionId,
  1732. FALSE);
  1733. if (ARGUMENT_PRESENT( ReturnLength )) {
  1734. *ReturnLength = Length;
  1735. }
  1736. break;
  1737. case SystemCallCountInformation:
  1738. Length = sizeof(SYSTEM_CALL_COUNT_INFORMATION) +
  1739. (NUMBER_SERVICE_TABLES * sizeof(ULONG));
  1740. Table = KeServiceDescriptorTableShadow;
  1741. for (i = 0; i < NUMBER_SERVICE_TABLES; i += 1) {
  1742. if ((Table->Limit != 0) && (Table->Count != NULL)) {
  1743. Length += Table->Limit * sizeof(ULONG);
  1744. }
  1745. Table += 1;
  1746. }
  1747. if (ARGUMENT_PRESENT( ReturnLength )) {
  1748. *ReturnLength = Length;
  1749. }
  1750. if (SystemInformationLength < Length) {
  1751. return STATUS_INFO_LENGTH_MISMATCH;
  1752. }
  1753. CallCountInformation = (PSYSTEM_CALL_COUNT_INFORMATION)SystemInformation;
  1754. CallCountInformation->Length = Length;
  1755. CallCountInformation->NumberOfTables = NUMBER_SERVICE_TABLES;
  1756. TableLimit = (PULONG)(CallCountInformation + 1);
  1757. TableCounts = TableLimit + NUMBER_SERVICE_TABLES;
  1758. Table = KeServiceDescriptorTableShadow;
  1759. for (i = 0; i < NUMBER_SERVICE_TABLES; i += 1) {
  1760. if ((Table->Limit == 0) || (Table->Count == NULL)) {
  1761. *TableLimit++ = 0;
  1762. } else {
  1763. *TableLimit++ = Table->Limit;
  1764. RtlCopyMemory((PVOID)TableCounts,
  1765. (PVOID)Table->Count,
  1766. Table->Limit * sizeof(ULONG));
  1767. TableCounts += Table->Limit;
  1768. }
  1769. Table += 1;
  1770. }
  1771. break;
  1772. case SystemDeviceInformation:
  1773. if (SystemInformationLength != sizeof( SYSTEM_DEVICE_INFORMATION )) {
  1774. return STATUS_INFO_LENGTH_MISMATCH;
  1775. }
  1776. ConfigInfo = IoGetConfigurationInformation();
  1777. DeviceInformation = (PSYSTEM_DEVICE_INFORMATION)SystemInformation;
  1778. DeviceInformation->NumberOfDisks = ConfigInfo->DiskCount;
  1779. DeviceInformation->NumberOfFloppies = ConfigInfo->FloppyCount;
  1780. DeviceInformation->NumberOfCdRoms = ConfigInfo->CdRomCount;
  1781. DeviceInformation->NumberOfTapes = ConfigInfo->TapeCount;
  1782. DeviceInformation->NumberOfSerialPorts = ConfigInfo->SerialCount;
  1783. DeviceInformation->NumberOfParallelPorts = ConfigInfo->ParallelCount;
  1784. if (ARGUMENT_PRESENT( ReturnLength )) {
  1785. *ReturnLength = sizeof( SYSTEM_DEVICE_INFORMATION );
  1786. }
  1787. break;
  1788. case SystemFlagsInformation:
  1789. if (SystemInformationLength != sizeof( SYSTEM_FLAGS_INFORMATION )) {
  1790. return STATUS_INFO_LENGTH_MISMATCH;
  1791. }
  1792. ((PSYSTEM_FLAGS_INFORMATION)SystemInformation)->Flags = NtGlobalFlag;
  1793. if (ARGUMENT_PRESENT( ReturnLength )) {
  1794. *ReturnLength = sizeof( SYSTEM_FLAGS_INFORMATION );
  1795. }
  1796. break;
  1797. case SystemCallTimeInformation:
  1798. return STATUS_NOT_IMPLEMENTED;
  1799. case SystemModuleInformation:
  1800. KeEnterCriticalRegion();
  1801. ExAcquireResourceExclusiveLite( &PsLoadedModuleResource, TRUE );
  1802. try {
  1803. Status = ExpQueryModuleInformation( &PsLoadedModuleList,
  1804. &MmLoadedUserImageList,
  1805. (PRTL_PROCESS_MODULES)SystemInformation,
  1806. SystemInformationLength,
  1807. ReturnLength
  1808. );
  1809. } except(EXCEPTION_EXECUTE_HANDLER) {
  1810. Status = GetExceptionCode();
  1811. }
  1812. ExReleaseResourceLite (&PsLoadedModuleResource);
  1813. KeLeaveCriticalRegion();
  1814. break;
  1815. case SystemLocksInformation:
  1816. if (SystemInformationLength < sizeof( RTL_PROCESS_LOCKS )) {
  1817. return STATUS_INFO_LENGTH_MISMATCH;
  1818. }
  1819. Status = ExpGetLockInformation (SystemInformation,
  1820. SystemInformationLength,
  1821. &Length);
  1822. if (ARGUMENT_PRESENT( ReturnLength )) {
  1823. *ReturnLength = Length;
  1824. }
  1825. break;
  1826. case SystemStackTraceInformation:
  1827. if (SystemInformationLength < sizeof( RTL_PROCESS_BACKTRACES )) {
  1828. return STATUS_INFO_LENGTH_MISMATCH;
  1829. }
  1830. #if i386
  1831. Status = ExpGetStackTraceInformation (SystemInformation,
  1832. SystemInformationLength,
  1833. &Length);
  1834. #else
  1835. Status = STATUS_NOT_IMPLEMENTED;
  1836. #endif // i386
  1837. if (ARGUMENT_PRESENT( ReturnLength )) {
  1838. *ReturnLength = Length;
  1839. }
  1840. break;
  1841. case SystemPagedPoolInformation:
  1842. Status = STATUS_NOT_IMPLEMENTED;
  1843. if (ARGUMENT_PRESENT( ReturnLength )) {
  1844. *ReturnLength = 0;
  1845. }
  1846. break;
  1847. case SystemNonPagedPoolInformation:
  1848. Status = STATUS_NOT_IMPLEMENTED;
  1849. if (ARGUMENT_PRESENT( ReturnLength )) {
  1850. *ReturnLength = 0;
  1851. }
  1852. break;
  1853. case SystemHandleInformation:
  1854. if (SystemInformationLength < sizeof( SYSTEM_HANDLE_INFORMATION )) {
  1855. return STATUS_INFO_LENGTH_MISMATCH;
  1856. }
  1857. if (!POINTER_IS_ALIGNED (SystemInformation, TYPE_ALIGNMENT (SYSTEM_HANDLE_INFORMATION))) {
  1858. return STATUS_DATATYPE_MISALIGNMENT;
  1859. }
  1860. Status = ExpGetHandleInformation( SystemInformation,
  1861. SystemInformationLength,
  1862. &Length
  1863. );
  1864. if (ARGUMENT_PRESENT( ReturnLength )) {
  1865. *ReturnLength = Length;
  1866. }
  1867. break;
  1868. case SystemExtendedHandleInformation:
  1869. if (SystemInformationLength < sizeof( SYSTEM_HANDLE_INFORMATION_EX )) {
  1870. return STATUS_INFO_LENGTH_MISMATCH;
  1871. }
  1872. if (!POINTER_IS_ALIGNED (SystemInformation, TYPE_ALIGNMENT (SYSTEM_HANDLE_INFORMATION_EX))) {
  1873. return STATUS_DATATYPE_MISALIGNMENT;
  1874. }
  1875. Status = ExpGetHandleInformationEx( SystemInformation,
  1876. SystemInformationLength,
  1877. &Length
  1878. );
  1879. if (ARGUMENT_PRESENT( ReturnLength )) {
  1880. *ReturnLength = Length;
  1881. }
  1882. break;
  1883. case SystemObjectInformation:
  1884. if (SystemInformationLength < sizeof( SYSTEM_OBJECTTYPE_INFORMATION )) {
  1885. return STATUS_INFO_LENGTH_MISMATCH;
  1886. }
  1887. Status = ExpGetObjectInformation( SystemInformation,
  1888. SystemInformationLength,
  1889. &Length
  1890. );
  1891. if (ARGUMENT_PRESENT( ReturnLength )) {
  1892. *ReturnLength = Length;
  1893. }
  1894. break;
  1895. case SystemPageFileInformation:
  1896. if (SystemInformationLength < sizeof( SYSTEM_PAGEFILE_INFORMATION )) {
  1897. return STATUS_INFO_LENGTH_MISMATCH;
  1898. }
  1899. Status = MmGetPageFileInformation( SystemInformation,
  1900. SystemInformationLength,
  1901. &Length
  1902. );
  1903. if (ARGUMENT_PRESENT( ReturnLength )) {
  1904. *ReturnLength = Length;
  1905. }
  1906. break;
  1907. case SystemFileCacheInformation:
  1908. //
  1909. // This structure was extended in NT 4.0 from 12 bytes.
  1910. // Use the previous size of 12 bytes for versioning info.
  1911. //
  1912. if (SystemInformationLength < 12) {
  1913. return STATUS_INFO_LENGTH_MISMATCH;
  1914. }
  1915. FileCache = (PSYSTEM_FILECACHE_INFORMATION)SystemInformation;
  1916. FileCache->CurrentSize = ((SIZE_T)MmSystemCacheWs.WorkingSetSize) << PAGE_SHIFT;
  1917. FileCache->PeakSize = ((SIZE_T)MmSystemCacheWs.PeakWorkingSetSize) << PAGE_SHIFT;
  1918. FileCache->PageFaultCount = MmSystemCacheWs.PageFaultCount;
  1919. i = 12;
  1920. if (SystemInformationLength >= sizeof( SYSTEM_FILECACHE_INFORMATION )) {
  1921. i = sizeof (SYSTEM_FILECACHE_INFORMATION);
  1922. FileCache->MinimumWorkingSet =
  1923. MmSystemCacheWs.MinimumWorkingSetSize;
  1924. FileCache->MaximumWorkingSet =
  1925. MmSystemCacheWs.MaximumWorkingSetSize;
  1926. FileCache->CurrentSizeIncludingTransitionInPages = MmSystemCacheWs.WorkingSetSize + MmTransitionSharedPages;
  1927. FileCache->PeakSizeIncludingTransitionInPages = MmTransitionSharedPagesPeak;
  1928. FileCache->TransitionRePurposeCount = MmStandbyRePurposed;
  1929. }
  1930. if (ARGUMENT_PRESENT( ReturnLength )) {
  1931. *ReturnLength = i;
  1932. }
  1933. break;
  1934. case SystemSessionPoolTagInformation:
  1935. SessionProcessInformation =
  1936. (PSYSTEM_SESSION_PROCESS_INFORMATION)SystemInformation;
  1937. if (SystemInformationLength < sizeof( SYSTEM_SESSION_PROCESS_INFORMATION)) {
  1938. return STATUS_INFO_LENGTH_MISMATCH;
  1939. }
  1940. //
  1941. // The lower level locks the buffer specified below into
  1942. // memory using MmProbeAndLockPages.
  1943. // We don't need to probe the buffers here.
  1944. //
  1945. SessionId = SessionProcessInformation->SessionId;
  1946. SessionPoolTagInformation = SessionProcessInformation->Buffer;
  1947. SessionPoolTagInformationLength = SessionProcessInformation->SizeOfBuf;
  1948. if (!POINTER_IS_ALIGNED (SessionPoolTagInformation, sizeof (ULONGLONG))) {
  1949. return STATUS_DATATYPE_MISALIGNMENT;
  1950. }
  1951. Status = ExGetSessionPoolTagInformation (
  1952. SessionPoolTagInformation,
  1953. SessionPoolTagInformationLength,
  1954. &Length,
  1955. &SessionId);
  1956. if (ARGUMENT_PRESENT( ReturnLength )) {
  1957. *ReturnLength = Length;
  1958. }
  1959. break;
  1960. case SystemPoolTagInformation:
  1961. if (SystemInformationLength < sizeof( SYSTEM_POOLTAG_INFORMATION )) {
  1962. return STATUS_INFO_LENGTH_MISMATCH;
  1963. }
  1964. Status = ExGetPoolTagInfo (SystemInformation,
  1965. SystemInformationLength,
  1966. ReturnLength);
  1967. break;
  1968. case SystemBigPoolInformation:
  1969. if (SystemInformationLength < sizeof( SYSTEM_BIGPOOL_INFORMATION )) {
  1970. return STATUS_INFO_LENGTH_MISMATCH;
  1971. }
  1972. Status = ExGetBigPoolInfo (SystemInformation,
  1973. SystemInformationLength,
  1974. ReturnLength);
  1975. break;
  1976. case SystemSessionMappedViewInformation:
  1977. SessionMappedViewInformation =
  1978. (PSYSTEM_SESSION_MAPPED_VIEW_INFORMATION)SystemInformation;
  1979. if (SystemInformationLength < sizeof( SYSTEM_SESSION_MAPPED_VIEW_INFORMATION)) {
  1980. return STATUS_INFO_LENGTH_MISMATCH;
  1981. }
  1982. //
  1983. // The lower level locks the buffer specified below into
  1984. // memory using MmProbeAndLockPages.
  1985. // We don't need to probe the buffers here.
  1986. //
  1987. SessionId = SessionMappedViewInformation->SessionId;
  1988. if (!POINTER_IS_ALIGNED (SessionMappedViewInformation, sizeof (ULONGLONG))) {
  1989. return STATUS_DATATYPE_MISALIGNMENT;
  1990. }
  1991. Status = MmGetSessionMappedViewInformation (
  1992. SessionMappedViewInformation,
  1993. SystemInformationLength,
  1994. &Length,
  1995. &SessionId);
  1996. if (ARGUMENT_PRESENT( ReturnLength )) {
  1997. *ReturnLength = Length;
  1998. }
  1999. break;
  2000. case SystemVdmInstemulInformation:
  2001. #ifdef i386
  2002. if (SystemInformationLength < sizeof( SYSTEM_VDM_INSTEMUL_INFO )) {
  2003. return STATUS_INFO_LENGTH_MISMATCH;
  2004. }
  2005. Status = ExpGetInstemulInformation(
  2006. (PSYSTEM_VDM_INSTEMUL_INFO)SystemInformation
  2007. );
  2008. if (ARGUMENT_PRESENT( ReturnLength )) {
  2009. *ReturnLength = sizeof(SYSTEM_VDM_INSTEMUL_INFO);
  2010. }
  2011. #else
  2012. Status = STATUS_NOT_IMPLEMENTED;
  2013. #endif
  2014. break;
  2015. //
  2016. // Get system exception information which includes the number
  2017. // of exceptions that have dispatched, the number of alignment
  2018. // fixups, and the number of floating emulations that have been
  2019. // performed.
  2020. //
  2021. case SystemExceptionInformation:
  2022. if (SystemInformationLength < sizeof( SYSTEM_EXCEPTION_INFORMATION)) {
  2023. return STATUS_INFO_LENGTH_MISMATCH;
  2024. }
  2025. if (ARGUMENT_PRESENT( ReturnLength )) {
  2026. *ReturnLength = sizeof(SYSTEM_EXCEPTION_INFORMATION);
  2027. }
  2028. ExceptionInformation = (PSYSTEM_EXCEPTION_INFORMATION)SystemInformation;
  2029. //
  2030. // Ke information.
  2031. //
  2032. // These counters are kept on a per processor basis and must
  2033. // be totaled.
  2034. //
  2035. {
  2036. ULONG AlignmentFixupCount = 0;
  2037. ULONG ExceptionDispatchCount = 0;
  2038. ULONG FloatingEmulationCount = 0;
  2039. ULONG ByteWordEmulationCount = 0;
  2040. for (i = 0; i < (ULONG)KeNumberProcessors; i += 1) {
  2041. Prcb = KiProcessorBlock[i];
  2042. if (Prcb != NULL) {
  2043. AlignmentFixupCount += Prcb->KeAlignmentFixupCount;
  2044. ExceptionDispatchCount += Prcb->KeExceptionDispatchCount;
  2045. FloatingEmulationCount += Prcb->KeFloatingEmulationCount;
  2046. }
  2047. }
  2048. ExceptionInformation->AlignmentFixupCount = AlignmentFixupCount;
  2049. ExceptionInformation->ExceptionDispatchCount = ExceptionDispatchCount;
  2050. ExceptionInformation->FloatingEmulationCount = FloatingEmulationCount;
  2051. ExceptionInformation->ByteWordEmulationCount = ByteWordEmulationCount;
  2052. }
  2053. break;
  2054. case SystemKernelDebuggerInformation:
  2055. if (SystemInformationLength < sizeof( SYSTEM_KERNEL_DEBUGGER_INFORMATION)) {
  2056. return STATUS_INFO_LENGTH_MISMATCH;
  2057. }
  2058. KernelDebuggerInformation =
  2059. (PSYSTEM_KERNEL_DEBUGGER_INFORMATION)SystemInformation;
  2060. KernelDebuggerInformation->KernelDebuggerEnabled = KdDebuggerEnabled;
  2061. KernelDebuggerInformation->KernelDebuggerNotPresent = KdDebuggerNotPresent;
  2062. if (ARGUMENT_PRESENT( ReturnLength )) {
  2063. *ReturnLength = sizeof(SYSTEM_KERNEL_DEBUGGER_INFORMATION);
  2064. }
  2065. break;
  2066. case SystemContextSwitchInformation:
  2067. if (SystemInformationLength < sizeof( SYSTEM_CONTEXT_SWITCH_INFORMATION)) {
  2068. return STATUS_INFO_LENGTH_MISMATCH;
  2069. }
  2070. ContextSwitchInformation =
  2071. (PSYSTEM_CONTEXT_SWITCH_INFORMATION)SystemInformation;
  2072. //
  2073. // Compute the total number of context switches and fill in the
  2074. // remainder of the context switch information.
  2075. //
  2076. ContextSwitches = 0;
  2077. for (i = 0; i < (ULONG)KeNumberProcessors; i += 1) {
  2078. Prcb = KiProcessorBlock[i];
  2079. if (Prcb != NULL) {
  2080. ContextSwitches += KeGetContextSwitches(Prcb);
  2081. }
  2082. }
  2083. ContextSwitchInformation->ContextSwitches = ContextSwitches;
  2084. ContextSwitchInformation->FindAny = KeThreadSwitchCounters.FindAny;
  2085. ContextSwitchInformation->FindLast = KeThreadSwitchCounters.FindLast;
  2086. ContextSwitchInformation->FindIdeal = KeThreadSwitchCounters.FindIdeal;
  2087. ContextSwitchInformation->IdleAny = KeThreadSwitchCounters.IdleAny;
  2088. ContextSwitchInformation->IdleCurrent = KeThreadSwitchCounters.IdleCurrent;
  2089. ContextSwitchInformation->IdleLast = KeThreadSwitchCounters.IdleLast;
  2090. ContextSwitchInformation->IdleIdeal = KeThreadSwitchCounters.IdleIdeal;
  2091. ContextSwitchInformation->PreemptAny = KeThreadSwitchCounters.PreemptAny;
  2092. ContextSwitchInformation->PreemptCurrent = KeThreadSwitchCounters.PreemptCurrent;
  2093. ContextSwitchInformation->PreemptLast = KeThreadSwitchCounters.PreemptLast;
  2094. ContextSwitchInformation->SwitchToIdle = KeThreadSwitchCounters.SwitchToIdle;
  2095. if (ARGUMENT_PRESENT( ReturnLength )) {
  2096. *ReturnLength = sizeof(SYSTEM_CONTEXT_SWITCH_INFORMATION);
  2097. }
  2098. break;
  2099. case SystemRegistryQuotaInformation:
  2100. if (SystemInformationLength < sizeof( SYSTEM_REGISTRY_QUOTA_INFORMATION)) {
  2101. return(STATUS_INFO_LENGTH_MISMATCH);
  2102. }
  2103. CmQueryRegistryQuotaInformation((PSYSTEM_REGISTRY_QUOTA_INFORMATION)SystemInformation);
  2104. if (ARGUMENT_PRESENT( ReturnLength )) {
  2105. *ReturnLength = sizeof(SYSTEM_REGISTRY_QUOTA_INFORMATION);
  2106. }
  2107. break;
  2108. case SystemDpcBehaviorInformation:
  2109. {
  2110. PSYSTEM_DPC_BEHAVIOR_INFORMATION DpcInfo;
  2111. //
  2112. // If the system information buffer is not the correct length,
  2113. // then return an error.
  2114. //
  2115. if (SystemInformationLength != sizeof(SYSTEM_DPC_BEHAVIOR_INFORMATION)) {
  2116. return STATUS_INFO_LENGTH_MISMATCH;
  2117. }
  2118. DpcInfo = (PSYSTEM_DPC_BEHAVIOR_INFORMATION)SystemInformation;
  2119. //
  2120. // Exception handler for this routine will return the correct
  2121. // error if any of these accesses fail.
  2122. //
  2123. //
  2124. // Return the current DPC behavior variables
  2125. //
  2126. DpcInfo->DpcQueueDepth = KiMaximumDpcQueueDepth;
  2127. DpcInfo->MinimumDpcRate = KiMinimumDpcRate;
  2128. DpcInfo->AdjustDpcThreshold = KiAdjustDpcThreshold;
  2129. DpcInfo->IdealDpcRate = KiIdealDpcRate;
  2130. }
  2131. break;
  2132. case SystemInterruptInformation:
  2133. if (SystemInformationLength < (sizeof(SYSTEM_INTERRUPT_INFORMATION) * KeNumberProcessors)) {
  2134. return(STATUS_INFO_LENGTH_MISMATCH);
  2135. }
  2136. InterruptInformation = (PSYSTEM_INTERRUPT_INFORMATION)SystemInformation;
  2137. for (i=0; i < (ULONG)KeNumberProcessors; i++) {
  2138. Prcb = KiProcessorBlock[i];
  2139. InterruptInformation->ContextSwitches = KeGetContextSwitches(Prcb);
  2140. InterruptInformation->DpcCount = Prcb->DpcData[DPC_NORMAL].DpcCount;
  2141. InterruptInformation->DpcRate = Prcb->DpcRequestRate;
  2142. InterruptInformation->TimeIncrement = KeTimeIncrement;
  2143. InterruptInformation->DpcBypassCount = 0;
  2144. InterruptInformation->ApcBypassCount = 0;
  2145. ++InterruptInformation;
  2146. }
  2147. break;
  2148. case SystemCurrentTimeZoneInformation:
  2149. if (SystemInformationLength < sizeof( RTL_TIME_ZONE_INFORMATION )) {
  2150. return STATUS_INFO_LENGTH_MISMATCH;
  2151. }
  2152. RtlCopyMemory(SystemInformation,&ExpTimeZoneInformation,sizeof(ExpTimeZoneInformation));
  2153. if (ARGUMENT_PRESENT( ReturnLength )) {
  2154. *ReturnLength = sizeof( RTL_TIME_ZONE_INFORMATION );
  2155. }
  2156. Status = STATUS_SUCCESS;
  2157. break;
  2158. //
  2159. // Query pool lookaside list and general lookaside list
  2160. // information.
  2161. //
  2162. case SystemLookasideInformation:
  2163. Status = ExpGetLookasideInformation(SystemInformation,
  2164. SystemInformationLength,
  2165. &Length);
  2166. if (ARGUMENT_PRESENT(ReturnLength)) {
  2167. *ReturnLength = Length;
  2168. }
  2169. break;
  2170. case SystemRangeStartInformation:
  2171. if ( SystemInformationLength != sizeof(ULONG_PTR) ) {
  2172. return STATUS_INFO_LENGTH_MISMATCH;
  2173. }
  2174. *(PULONG_PTR)SystemInformation = (ULONG_PTR)MmSystemRangeStart;
  2175. if (ARGUMENT_PRESENT(ReturnLength) ) {
  2176. *ReturnLength = sizeof(ULONG_PTR);
  2177. }
  2178. break;
  2179. case SystemVerifierInformation:
  2180. if (SystemInformationLength < sizeof( SYSTEM_VERIFIER_INFORMATION )) {
  2181. return STATUS_INFO_LENGTH_MISMATCH;
  2182. }
  2183. Status = MmGetVerifierInformation( SystemInformation,
  2184. SystemInformationLength,
  2185. &Length
  2186. );
  2187. if (ARGUMENT_PRESENT( ReturnLength )) {
  2188. *ReturnLength = Length;
  2189. }
  2190. break;
  2191. case SystemLegacyDriverInformation:
  2192. if (SystemInformationLength < sizeof(SYSTEM_LEGACY_DRIVER_INFORMATION)) {
  2193. return(STATUS_INFO_LENGTH_MISMATCH);
  2194. }
  2195. Length = SystemInformationLength;
  2196. Status = ExpQueryLegacyDriverInformation((PSYSTEM_LEGACY_DRIVER_INFORMATION)SystemInformation, &Length);
  2197. if (ARGUMENT_PRESENT(ReturnLength)) {
  2198. *ReturnLength = Length;
  2199. }
  2200. break;
  2201. case SystemPerformanceTraceInformation:
  2202. #ifdef NTPERF
  2203. Status = PerfInfoQueryPerformanceTraceInformation(SystemInformation,
  2204. SystemInformationLength,
  2205. &Length
  2206. );
  2207. if (ARGUMENT_PRESENT(ReturnLength)) {
  2208. *ReturnLength = Length;
  2209. }
  2210. #else
  2211. Status = STATUS_INVALID_INFO_CLASS;
  2212. #endif // NTPERF
  2213. break;
  2214. case SystemPrefetcherInformation:
  2215. Status = CcPfQueryPrefetcherInformation(SystemInformationClass,
  2216. SystemInformation,
  2217. SystemInformationLength,
  2218. PreviousMode,
  2219. &Length
  2220. );
  2221. if (ARGUMENT_PRESENT(ReturnLength)) {
  2222. *ReturnLength = Length;
  2223. }
  2224. break;
  2225. case SystemNumaProcessorMap:
  2226. Status = ExpQueryNumaProcessorMap(SystemInformation,
  2227. SystemInformationLength,
  2228. &Length);
  2229. if (ARGUMENT_PRESENT(ReturnLength)) {
  2230. *ReturnLength = Length;
  2231. }
  2232. break;
  2233. case SystemNumaAvailableMemory:
  2234. Status = ExpQueryNumaAvailableMemory(SystemInformation,
  2235. SystemInformationLength,
  2236. &Length);
  2237. if (ARGUMENT_PRESENT(ReturnLength)) {
  2238. *ReturnLength = Length;
  2239. }
  2240. break;
  2241. case SystemRecommendedSharedDataAlignment:
  2242. if (SystemInformationLength < sizeof(ULONG)) {
  2243. return(STATUS_INFO_LENGTH_MISMATCH);
  2244. }
  2245. //
  2246. // Alignment is guaranteed by the ProbeForWrite above
  2247. // so just store the value as a ULONG.
  2248. //
  2249. *(PULONG)SystemInformation = KeGetRecommendedSharedDataAlignment();
  2250. if (ARGUMENT_PRESENT(ReturnLength)) {
  2251. *ReturnLength = sizeof(ULONG);
  2252. }
  2253. break;
  2254. case SystemComPlusPackage:
  2255. if (SystemInformationLength != sizeof(ULONG)) {
  2256. return(STATUS_INFO_LENGTH_MISMATCH);
  2257. }
  2258. if (SharedUserData->ComPlusPackage == COMPLUS_PACKAGE_INVALID) {
  2259. //
  2260. // The initialization happens one time.
  2261. //
  2262. SharedUserData->ComPlusPackage = 0;
  2263. ExpReadComPlusPackage ();
  2264. }
  2265. *(PULONG)SystemInformation = SharedUserData->ComPlusPackage;
  2266. if (ARGUMENT_PRESENT(ReturnLength)) {
  2267. *ReturnLength = sizeof(ULONG);
  2268. }
  2269. break;
  2270. case SystemLostDelayedWriteInformation:
  2271. if (SystemInformationLength < sizeof(ULONG)) {
  2272. return(STATUS_INFO_LENGTH_MISMATCH);
  2273. }
  2274. *(PULONG)SystemInformation = CcLostDelayedWrites;
  2275. if (ARGUMENT_PRESENT(ReturnLength)) {
  2276. *ReturnLength = sizeof(ULONG);
  2277. }
  2278. break;
  2279. case SystemObjectSecurityMode:
  2280. if (SystemInformationLength != sizeof (ULONG)) {
  2281. return STATUS_INFO_LENGTH_MISMATCH;
  2282. }
  2283. *(PULONG)SystemInformation = ObGetSecurityMode ();
  2284. if (ARGUMENT_PRESENT (ReturnLength)) {
  2285. *ReturnLength = sizeof (ULONG);
  2286. }
  2287. break;
  2288. case SystemWatchdogTimerInformation:
  2289. {
  2290. PSYSTEM_WATCHDOG_TIMER_INFORMATION WdTimerInfo = (PSYSTEM_WATCHDOG_TIMER_INFORMATION) SystemInformation;
  2291. //
  2292. // Caller must be kernel mode with the proper parameters
  2293. //
  2294. if (PreviousMode != KernelMode || SystemInformation == NULL || SystemInformationLength != sizeof(SYSTEM_WATCHDOG_TIMER_INFORMATION)) {
  2295. ExRaiseStatus (STATUS_INVALID_PARAMETER);
  2296. }
  2297. if (ExpWdHandler == NULL) {
  2298. Status = STATUS_NOT_IMPLEMENTED;
  2299. } else {
  2300. switch (WdTimerInfo->WdInfoClass) {
  2301. case WdInfoTimeoutValue:
  2302. Status = ExpWdHandler( WdActionQueryTimeoutValue, ExpWdHandlerContext, &WdTimerInfo->DataValue, FALSE );
  2303. break;
  2304. case WdInfoTriggerAction:
  2305. Status = ExpWdHandler( WdActionQueryTriggerAction, ExpWdHandlerContext, &WdTimerInfo->DataValue, FALSE );
  2306. break;
  2307. case WdInfoState:
  2308. Status = ExpWdHandler( WdActionQueryState, ExpWdHandlerContext, &WdTimerInfo->DataValue, FALSE );
  2309. break;
  2310. default:
  2311. Status = STATUS_INVALID_PARAMETER;
  2312. break;
  2313. }
  2314. }
  2315. }
  2316. break;
  2317. case SystemLogicalProcessorInformation:
  2318. Status = KeQueryLogicalProcessorInformation(
  2319. SystemInformation,
  2320. SystemInformationLength,
  2321. &Length);
  2322. if (ARGUMENT_PRESENT(ReturnLength)) {
  2323. *ReturnLength = Length;
  2324. }
  2325. break;
  2326. default:
  2327. //
  2328. // Invalid argument.
  2329. //
  2330. return STATUS_INVALID_INFO_CLASS;
  2331. }
  2332. } except (EXCEPTION_EXECUTE_HANDLER) {
  2333. Status = GetExceptionCode();
  2334. }
  2335. return Status;
  2336. }
  2337. NTSTATUS
  2338. NTAPI
  2339. NtSetSystemInformation (
  2340. IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
  2341. IN PVOID SystemInformation,
  2342. IN ULONG SystemInformationLength
  2343. )
  2344. /*++
  2345. Routine Description:
  2346. This function set information about the system.
  2347. Arguments:
  2348. SystemInformationClass - The system information class which is to
  2349. be modified.
  2350. SystemInformation - A pointer to a buffer which contains the specified
  2351. information. The format and content of the buffer depend on the
  2352. specified system information class.
  2353. SystemInformationLength - Specifies the length in bytes of the system
  2354. information buffer.
  2355. Return Value:
  2356. Returns one of the following status codes:
  2357. STATUS_SUCCESS - Normal, successful completion.
  2358. STATUS_ACCESS_VIOLATION - The specified system information buffer
  2359. is not accessible.
  2360. STATUS_INVALID_INFO_CLASS - The SystemInformationClass parameter
  2361. did not specify a valid value.
  2362. STATUS_INFO_LENGTH_MISMATCH - The value of the SystemInformationLength
  2363. parameter did not match the length required for the information
  2364. class requested by the SystemInformationClass parameter.
  2365. STATUS_PRIVILEGE_NOT_HELD is returned if the caller does not have the
  2366. privilege to set the system time.
  2367. --*/
  2368. {
  2369. BOOLEAN Enable;
  2370. KPROCESSOR_MODE PreviousMode;
  2371. NTSTATUS Status;
  2372. ULONG TimeAdjustment;
  2373. PSYSTEM_SET_TIME_ADJUST_INFORMATION TimeAdjustmentInformation;
  2374. HANDLE EventHandle;
  2375. PVOID Event;
  2376. ULONG LoadFlags = MM_LOAD_IMAGE_IN_SESSION;
  2377. PAGED_CODE();
  2378. //
  2379. // Establish an exception handle in case the system information buffer
  2380. // is not accessible.
  2381. //
  2382. Status = STATUS_SUCCESS;
  2383. try {
  2384. //
  2385. // Get the previous processor mode and probe the input buffer for
  2386. // read access if necessary.
  2387. //
  2388. PreviousMode = KeGetPreviousMode();
  2389. if (PreviousMode != KernelMode) {
  2390. ProbeForRead((PVOID)SystemInformation,
  2391. SystemInformationLength,
  2392. sizeof(ULONG));
  2393. }
  2394. //
  2395. // Dispatch on the system information class.
  2396. //
  2397. switch (SystemInformationClass) {
  2398. case SystemFlagsInformation:
  2399. if (SystemInformationLength != sizeof( SYSTEM_FLAGS_INFORMATION )) {
  2400. return STATUS_INFO_LENGTH_MISMATCH;
  2401. }
  2402. if (!SeSinglePrivilegeCheck( SeDebugPrivilege, PreviousMode )) {
  2403. return STATUS_ACCESS_DENIED;
  2404. }
  2405. else {
  2406. ULONG Flags;
  2407. Flags = ((PSYSTEM_FLAGS_INFORMATION)SystemInformation)->Flags &
  2408. ~(FLG_KERNELMODE_VALID_BITS | FLG_BOOTONLY_VALID_BITS);
  2409. Flags |= NtGlobalFlag & (FLG_KERNELMODE_VALID_BITS | FLG_BOOTONLY_VALID_BITS);
  2410. NtGlobalFlag = Flags;
  2411. ((PSYSTEM_FLAGS_INFORMATION)SystemInformation)->Flags = NtGlobalFlag;
  2412. }
  2413. break;
  2414. //
  2415. // Set system time adjustment information.
  2416. //
  2417. // N.B. The caller must have the SeSystemTime privilege.
  2418. //
  2419. case SystemTimeAdjustmentInformation:
  2420. //
  2421. // If the system information buffer is not the correct length,
  2422. // then return an error.
  2423. //
  2424. if (SystemInformationLength != sizeof( SYSTEM_SET_TIME_ADJUST_INFORMATION )) {
  2425. return STATUS_INFO_LENGTH_MISMATCH;
  2426. }
  2427. //
  2428. // If the current thread does not have the privilege to set the
  2429. // time adjustment variables, then return an error.
  2430. //
  2431. if ((PreviousMode != KernelMode) &&
  2432. (SeSinglePrivilegeCheck(SeSystemtimePrivilege, PreviousMode) == FALSE)) {
  2433. return STATUS_PRIVILEGE_NOT_HELD;
  2434. }
  2435. //
  2436. // Set system time adjustment parameters.
  2437. //
  2438. TimeAdjustmentInformation =
  2439. (PSYSTEM_SET_TIME_ADJUST_INFORMATION)SystemInformation;
  2440. Enable = TimeAdjustmentInformation->Enable;
  2441. TimeAdjustment = TimeAdjustmentInformation->TimeAdjustment;
  2442. if (Enable == TRUE) {
  2443. KeTimeAdjustment = KeMaximumIncrement;
  2444. } else {
  2445. if (TimeAdjustment == 0) {
  2446. return STATUS_INVALID_PARAMETER_2;
  2447. }
  2448. KeTimeAdjustment = TimeAdjustment;
  2449. }
  2450. KeTimeSynchronization = Enable;
  2451. break;
  2452. //
  2453. // Set an event to signal when the clock interrupt has been
  2454. // masked for too long, causing the time to slip.
  2455. // The event will be referenced to prevent it from being
  2456. // deleted. If the new event handle is valid or NULL, the
  2457. // old event will be dereferenced and forgotten. If the
  2458. // event handle is non-NULL but invalid, the old event will
  2459. // be remembered and a failure status will be returned.
  2460. //
  2461. // N.B. The caller must have the SeSystemTime privilege.
  2462. //
  2463. case SystemTimeSlipNotification:
  2464. if (SystemInformationLength != sizeof(HANDLE)) {
  2465. return STATUS_INFO_LENGTH_MISMATCH;
  2466. }
  2467. //
  2468. // If the current thread does not have the privilege to set the
  2469. // time adjustment variables, then return an error.
  2470. //
  2471. if ((PreviousMode != KernelMode) &&
  2472. (SeSinglePrivilegeCheck(SeSystemtimePrivilege, PreviousMode) == FALSE)) {
  2473. return STATUS_PRIVILEGE_NOT_HELD;
  2474. }
  2475. EventHandle = *(PHANDLE)SystemInformation;
  2476. if (EventHandle == NULL) {
  2477. //
  2478. // Dereference the old event and don't signal anything
  2479. // for time slips.
  2480. //
  2481. Event = NULL;
  2482. Status = STATUS_SUCCESS;
  2483. } else {
  2484. Status = ObReferenceObjectByHandle(EventHandle,
  2485. EVENT_MODIFY_STATE,
  2486. ExEventObjectType,
  2487. PreviousMode,
  2488. &Event,
  2489. NULL);
  2490. }
  2491. if (NT_SUCCESS(Status)) {
  2492. KdUpdateTimeSlipEvent(Event);
  2493. }
  2494. break;
  2495. //
  2496. // Set registry quota limit.
  2497. //
  2498. // N.B. The caller must have SeIncreaseQuotaPrivilege
  2499. //
  2500. case SystemRegistryQuotaInformation:
  2501. //
  2502. // If the system information buffer is not the correct length,
  2503. // then return an error.
  2504. //
  2505. if (SystemInformationLength != sizeof( SYSTEM_REGISTRY_QUOTA_INFORMATION )) {
  2506. return STATUS_INFO_LENGTH_MISMATCH;
  2507. }
  2508. //
  2509. // If the current thread does not have the privilege to create
  2510. // a pagefile, then return an error.
  2511. //
  2512. if ((PreviousMode != KernelMode) &&
  2513. (SeSinglePrivilegeCheck(SeIncreaseQuotaPrivilege, PreviousMode) == FALSE)) {
  2514. return STATUS_PRIVILEGE_NOT_HELD;
  2515. }
  2516. //
  2517. // Set registry quota parameters.
  2518. //
  2519. CmSetRegistryQuotaInformation((PSYSTEM_REGISTRY_QUOTA_INFORMATION)SystemInformation);
  2520. break;
  2521. case SystemPrioritySeperation:
  2522. {
  2523. ULONG PrioritySeparation;
  2524. //
  2525. // If the system information buffer is not the correct length,
  2526. // then return an error.
  2527. //
  2528. if (SystemInformationLength != sizeof (ULONG)) {
  2529. return STATUS_INFO_LENGTH_MISMATCH;
  2530. }
  2531. if (!SeSinglePrivilegeCheck (SeTcbPrivilege, PreviousMode)) {
  2532. return STATUS_PRIVILEGE_NOT_HELD;
  2533. }
  2534. try {
  2535. PrioritySeparation = *(PULONG)SystemInformation;
  2536. }
  2537. except(EXCEPTION_EXECUTE_HANDLER) {
  2538. return GetExceptionCode();
  2539. }
  2540. PsChangeQuantumTable (TRUE, PrioritySeparation);
  2541. Status = STATUS_SUCCESS;
  2542. }
  2543. break;
  2544. case SystemExtendServiceTableInformation:
  2545. {
  2546. UNICODE_STRING Image;
  2547. PWSTR Buffer;
  2548. PVOID ImageBaseAddress;
  2549. ULONG_PTR EntryPoint;
  2550. PVOID SectionPointer;
  2551. PIMAGE_NT_HEADERS NtHeaders;
  2552. PDRIVER_INITIALIZE InitRoutine;
  2553. DRIVER_OBJECT Win32KDevice;
  2554. //
  2555. // If the system information buffer is not the correct length,
  2556. // then return an error.
  2557. //
  2558. if (SystemInformationLength != sizeof( UNICODE_STRING ) ) {
  2559. return STATUS_INFO_LENGTH_MISMATCH;
  2560. }
  2561. if (PreviousMode != KernelMode) {
  2562. //
  2563. // The caller's access mode is not kernel so check to ensure
  2564. // the caller has the privilege to load a driver.
  2565. //
  2566. if (!SeSinglePrivilegeCheck( SeLoadDriverPrivilege, PreviousMode )) {
  2567. return STATUS_PRIVILEGE_NOT_HELD;
  2568. }
  2569. Buffer = NULL;
  2570. try {
  2571. Image = *(PUNICODE_STRING)SystemInformation;
  2572. //
  2573. // Guard against overflow.
  2574. //
  2575. if (Image.Length > Image.MaximumLength) {
  2576. Image.Length = Image.MaximumLength;
  2577. }
  2578. if (Image.Length == 0) {
  2579. return STATUS_NO_MEMORY;
  2580. }
  2581. ProbeForRead(Image.Buffer, Image.Length, sizeof(UCHAR));
  2582. Buffer = ExAllocatePoolWithTag(PagedPool, Image.Length, 'ofnI');
  2583. if ( !Buffer ) {
  2584. return STATUS_NO_MEMORY;
  2585. }
  2586. RtlCopyMemory(Buffer, Image.Buffer, Image.Length);
  2587. Image.Buffer = Buffer;
  2588. Image.MaximumLength = Image.Length;
  2589. }
  2590. except(EXCEPTION_EXECUTE_HANDLER) {
  2591. if ( Buffer ) {
  2592. ExFreePool(Buffer);
  2593. }
  2594. return GetExceptionCode();
  2595. }
  2596. //
  2597. // Call MmLoadSystemImage with previous mode of kernel.
  2598. //
  2599. Status = ZwSetSystemInformation(
  2600. SystemExtendServiceTableInformation,
  2601. (PVOID)&Image,
  2602. sizeof(Image)
  2603. );
  2604. ExFreePool(Buffer);
  2605. return Status;
  2606. }
  2607. Image = *(PUNICODE_STRING)SystemInformation;
  2608. //
  2609. // Now in kernelmode, so load the driver.
  2610. //
  2611. Status = MmLoadSystemImage (&Image,
  2612. NULL,
  2613. NULL,
  2614. MM_LOAD_IMAGE_IN_SESSION,
  2615. &SectionPointer,
  2616. (PVOID *) &ImageBaseAddress);
  2617. if (!NT_SUCCESS (Status)) {
  2618. return Status;
  2619. }
  2620. NtHeaders = RtlImageNtHeader( ImageBaseAddress );
  2621. if (! NtHeaders) {
  2622. MmUnloadSystemImage (SectionPointer);
  2623. return STATUS_INVALID_IMAGE_FORMAT;
  2624. }
  2625. EntryPoint = NtHeaders->OptionalHeader.AddressOfEntryPoint;
  2626. EntryPoint += (ULONG_PTR) ImageBaseAddress;
  2627. InitRoutine = (PDRIVER_INITIALIZE) EntryPoint;
  2628. RtlZeroMemory (&Win32KDevice, sizeof(Win32KDevice));
  2629. ASSERT (KeGetCurrentIrql() == 0);
  2630. Win32KDevice.DriverStart = (PVOID)ImageBaseAddress;
  2631. Status = (InitRoutine)(&Win32KDevice,NULL);
  2632. ASSERT (KeGetCurrentIrql() == 0);
  2633. if (!NT_SUCCESS (Status)) {
  2634. MmUnloadSystemImage (SectionPointer);
  2635. }
  2636. else {
  2637. //
  2638. // Pass the driver object to memory management so the
  2639. // session can be unloaded cleanly.
  2640. //
  2641. MmSessionSetUnloadAddress (&Win32KDevice);
  2642. }
  2643. }
  2644. break;
  2645. case SystemUnloadGdiDriverInformation:
  2646. {
  2647. if (SystemInformationLength != sizeof( PVOID ) ) {
  2648. return STATUS_INFO_LENGTH_MISMATCH;
  2649. }
  2650. if (PreviousMode != KernelMode) {
  2651. //
  2652. // The caller's access mode is not kernel so fail.
  2653. // Only GDI from the kernel can call this.
  2654. //
  2655. return STATUS_PRIVILEGE_NOT_HELD;
  2656. }
  2657. MmUnloadSystemImage( *((PVOID *)SystemInformation) );
  2658. Status = STATUS_SUCCESS;
  2659. }
  2660. break;
  2661. case SystemLoadGdiDriverInSystemSpace:
  2662. {
  2663. LoadFlags &= ~MM_LOAD_IMAGE_IN_SESSION;
  2664. //
  2665. // Fall through
  2666. //
  2667. }
  2668. case SystemLoadGdiDriverInformation:
  2669. {
  2670. UNICODE_STRING Image;
  2671. PVOID ImageBaseAddress;
  2672. ULONG_PTR EntryPoint;
  2673. PVOID SectionPointer;
  2674. PIMAGE_NT_HEADERS NtHeaders;
  2675. //
  2676. // If the system information buffer is not the correct length,
  2677. // then return an error.
  2678. //
  2679. if (SystemInformationLength != sizeof( SYSTEM_GDI_DRIVER_INFORMATION ) ) {
  2680. return STATUS_INFO_LENGTH_MISMATCH;
  2681. }
  2682. if (PreviousMode != KernelMode) {
  2683. //
  2684. // The caller's access mode is not kernel so fail.
  2685. // Only GDI from the kernel can call this.
  2686. //
  2687. return STATUS_PRIVILEGE_NOT_HELD;
  2688. }
  2689. Image = ((PSYSTEM_GDI_DRIVER_INFORMATION)SystemInformation)->DriverName;
  2690. Status = MmLoadSystemImage (&Image,
  2691. NULL,
  2692. NULL,
  2693. LoadFlags,
  2694. &SectionPointer,
  2695. (PVOID *) &ImageBaseAddress);
  2696. if ((NT_SUCCESS( Status ))) {
  2697. PSYSTEM_GDI_DRIVER_INFORMATION GdiDriverInfo =
  2698. (PSYSTEM_GDI_DRIVER_INFORMATION) SystemInformation;
  2699. ULONG Size;
  2700. GdiDriverInfo->ExportSectionPointer =
  2701. RtlImageDirectoryEntryToData(ImageBaseAddress,
  2702. TRUE,
  2703. IMAGE_DIRECTORY_ENTRY_EXPORT,
  2704. &Size);
  2705. //
  2706. // Capture the entry point.
  2707. //
  2708. NtHeaders = RtlImageNtHeader( ImageBaseAddress );
  2709. EntryPoint = NtHeaders->OptionalHeader.AddressOfEntryPoint;
  2710. EntryPoint += (ULONG_PTR) ImageBaseAddress;
  2711. GdiDriverInfo->ImageAddress = (PVOID) ImageBaseAddress;
  2712. GdiDriverInfo->SectionPointer = SectionPointer;
  2713. GdiDriverInfo->EntryPoint = (PVOID) EntryPoint;
  2714. GdiDriverInfo->ImageLength = NtHeaders->OptionalHeader.SizeOfImage;
  2715. }
  2716. }
  2717. break;
  2718. case SystemFileCacheInformation:
  2719. if (SystemInformationLength < sizeof( SYSTEM_FILECACHE_INFORMATION )) {
  2720. return STATUS_INFO_LENGTH_MISMATCH;
  2721. }
  2722. if (!SeSinglePrivilegeCheck( SeIncreaseQuotaPrivilege, PreviousMode )) {
  2723. return STATUS_ACCESS_DENIED;
  2724. }
  2725. return MmAdjustWorkingSetSize (
  2726. ((PSYSTEM_FILECACHE_INFORMATION)SystemInformation)->MinimumWorkingSet,
  2727. ((PSYSTEM_FILECACHE_INFORMATION)SystemInformation)->MaximumWorkingSet,
  2728. TRUE,
  2729. TRUE);
  2730. break;
  2731. case SystemDpcBehaviorInformation:
  2732. {
  2733. SYSTEM_DPC_BEHAVIOR_INFORMATION DpcInfo;
  2734. //
  2735. // If the system information buffer is not the correct length,
  2736. // then return an error.
  2737. //
  2738. if (SystemInformationLength != sizeof(SYSTEM_DPC_BEHAVIOR_INFORMATION)) {
  2739. return STATUS_INFO_LENGTH_MISMATCH;
  2740. }
  2741. if (PreviousMode != KernelMode) {
  2742. //
  2743. // The caller's access mode is not kernel so check to ensure that
  2744. // the caller has the privilege to load a driver.
  2745. //
  2746. if (!SeSinglePrivilegeCheck( SeLoadDriverPrivilege, PreviousMode )) {
  2747. return STATUS_PRIVILEGE_NOT_HELD;
  2748. }
  2749. }
  2750. //
  2751. // Exception handler for this routine will return the correct
  2752. // error if this access fails.
  2753. //
  2754. DpcInfo = *(PSYSTEM_DPC_BEHAVIOR_INFORMATION)SystemInformation;
  2755. //
  2756. // Set the new DPC behavior variables
  2757. //
  2758. KiMaximumDpcQueueDepth = DpcInfo.DpcQueueDepth;
  2759. KiMinimumDpcRate = DpcInfo.MinimumDpcRate;
  2760. KiAdjustDpcThreshold = DpcInfo.AdjustDpcThreshold;
  2761. KiIdealDpcRate = DpcInfo.IdealDpcRate;
  2762. }
  2763. break;
  2764. case SystemSessionCreate:
  2765. {
  2766. //
  2767. // Creation of a session space.
  2768. //
  2769. ULONG SessionId;
  2770. //
  2771. // If the system information buffer is not the correct length,
  2772. // then return an error.
  2773. //
  2774. if (SystemInformationLength != sizeof(ULONG)) {
  2775. return STATUS_INFO_LENGTH_MISMATCH;
  2776. }
  2777. if (PreviousMode != KernelMode) {
  2778. //
  2779. // The caller's access mode is not kernel so check to
  2780. // ensure that the caller has the privilege to load
  2781. // a driver.
  2782. //
  2783. if (!SeSinglePrivilegeCheck (SeLoadDriverPrivilege, PreviousMode)) {
  2784. return STATUS_PRIVILEGE_NOT_HELD;
  2785. }
  2786. try {
  2787. ProbeForWriteUlong((PULONG)SystemInformation);
  2788. }
  2789. except (EXCEPTION_EXECUTE_HANDLER) {
  2790. return GetExceptionCode();
  2791. }
  2792. }
  2793. //
  2794. // Create a session space in the current process.
  2795. //
  2796. Status = MmSessionCreate (&SessionId);
  2797. if (NT_SUCCESS(Status)) {
  2798. if (PreviousMode != KernelMode) {
  2799. try {
  2800. *(PULONG)SystemInformation = SessionId;
  2801. }
  2802. except (EXCEPTION_EXECUTE_HANDLER) {
  2803. return GetExceptionCode();
  2804. }
  2805. }
  2806. else {
  2807. *(PULONG)SystemInformation = SessionId;
  2808. }
  2809. }
  2810. return Status;
  2811. }
  2812. break;
  2813. case SystemSessionDetach:
  2814. {
  2815. ULONG SessionId;
  2816. //
  2817. // If the system information buffer is not the correct length,
  2818. // then return an error.
  2819. //
  2820. if (SystemInformationLength != sizeof(ULONG)) {
  2821. return STATUS_INFO_LENGTH_MISMATCH;
  2822. }
  2823. if (PreviousMode != KernelMode) {
  2824. //
  2825. // The caller's access mode is not kernel so check to
  2826. // ensure that the caller has the privilege to load
  2827. // a driver.
  2828. //
  2829. if (!SeSinglePrivilegeCheck( SeLoadDriverPrivilege, PreviousMode )) {
  2830. return STATUS_PRIVILEGE_NOT_HELD;
  2831. }
  2832. try {
  2833. ProbeForRead ((PVOID)SystemInformation,
  2834. sizeof(ULONG),
  2835. sizeof(ULONG));
  2836. SessionId = *(PULONG)SystemInformation;
  2837. }
  2838. except (EXCEPTION_EXECUTE_HANDLER) {
  2839. return GetExceptionCode();
  2840. }
  2841. }
  2842. else {
  2843. SessionId = *(PULONG)SystemInformation;
  2844. }
  2845. //
  2846. // Detach the current process from a session space
  2847. // if it has one.
  2848. //
  2849. Status = MmSessionDelete (SessionId);
  2850. return Status;
  2851. }
  2852. break;
  2853. case SystemCrashDumpStateInformation:
  2854. //
  2855. // All this system information does when you set it is trigger a
  2856. // reconfigurating of the current crashdump state based on the
  2857. // registry.
  2858. //
  2859. Status = IoConfigureCrashDump(CrashDumpReconfigure);
  2860. break;
  2861. case SystemPerformanceTraceInformation:
  2862. #ifdef NTPERF
  2863. Status = PerfInfoSetPerformanceTraceInformation(SystemInformation,
  2864. SystemInformationLength
  2865. );
  2866. #else
  2867. Status = STATUS_INVALID_INFO_CLASS;
  2868. #endif // NTPERF
  2869. break;
  2870. case SystemVerifierThunkExtend:
  2871. if (PreviousMode != KernelMode) {
  2872. //
  2873. // The caller's access mode is not kernel so fail.
  2874. // Only device drivers can call this.
  2875. //
  2876. return STATUS_PRIVILEGE_NOT_HELD;
  2877. }
  2878. Status = MmAddVerifierThunks (SystemInformation,
  2879. SystemInformationLength);
  2880. break;
  2881. case SystemVerifierInformation:
  2882. if (!SeSinglePrivilegeCheck (SeDebugPrivilege, PreviousMode)) {
  2883. return STATUS_ACCESS_DENIED;
  2884. }
  2885. Status = MmSetVerifierInformation (SystemInformation,
  2886. SystemInformationLength);
  2887. break;
  2888. case SystemVerifierAddDriverInformation:
  2889. case SystemVerifierRemoveDriverInformation:
  2890. {
  2891. UNICODE_STRING Image;
  2892. PUNICODE_STRING ImagePointer;
  2893. PWSTR Buffer;
  2894. //
  2895. // If the system information buffer is not the correct length,
  2896. // then return an error.
  2897. //
  2898. if (SystemInformationLength != sizeof( UNICODE_STRING ) ) {
  2899. return STATUS_INFO_LENGTH_MISMATCH;
  2900. }
  2901. Buffer = NULL;
  2902. if (PreviousMode != KernelMode) {
  2903. //
  2904. // The caller's access mode is not kernel so check to ensure
  2905. // the caller has the privilege to add a verifier entry.
  2906. //
  2907. if (!SeSinglePrivilegeCheck( SeDebugPrivilege, PreviousMode )) {
  2908. return STATUS_PRIVILEGE_NOT_HELD;
  2909. }
  2910. try {
  2911. Image = *(PUNICODE_STRING)SystemInformation;
  2912. //
  2913. // Guard against overflow.
  2914. //
  2915. if (Image.Length > Image.MaximumLength) {
  2916. Image.Length = Image.MaximumLength;
  2917. }
  2918. if (Image.Length == 0) {
  2919. return STATUS_NO_MEMORY;
  2920. }
  2921. ProbeForRead(Image.Buffer, Image.Length, sizeof(UCHAR));
  2922. Buffer = ExAllocatePoolWithTag(PagedPool, Image.Length, 'ofnI');
  2923. if ( !Buffer ) {
  2924. return STATUS_NO_MEMORY;
  2925. }
  2926. RtlCopyMemory(Buffer, Image.Buffer, Image.Length);
  2927. Image.Buffer = Buffer;
  2928. Image.MaximumLength = Image.Length;
  2929. }
  2930. except(EXCEPTION_EXECUTE_HANDLER) {
  2931. if ( Buffer ) {
  2932. ExFreePool(Buffer);
  2933. }
  2934. return GetExceptionCode();
  2935. }
  2936. ImagePointer = &Image;
  2937. }
  2938. else {
  2939. ImagePointer = (PUNICODE_STRING)SystemInformation;
  2940. }
  2941. switch (SystemInformationClass) {
  2942. case SystemVerifierAddDriverInformation:
  2943. Status = MmAddVerifierEntry (ImagePointer);
  2944. break;
  2945. case SystemVerifierRemoveDriverInformation:
  2946. Status = MmRemoveVerifierEntry (ImagePointer);
  2947. break;
  2948. default:
  2949. Status = STATUS_INVALID_INFO_CLASS;
  2950. break;
  2951. }
  2952. if (Buffer) {
  2953. ExFreePool(Buffer);
  2954. }
  2955. }
  2956. break;
  2957. case SystemMirrorMemoryInformation:
  2958. Status = MmCreateMirror ();
  2959. break;
  2960. case SystemPrefetcherInformation:
  2961. Status = CcPfSetPrefetcherInformation(SystemInformationClass,
  2962. SystemInformation,
  2963. SystemInformationLength,
  2964. PreviousMode
  2965. );
  2966. break;
  2967. case SystemComPlusPackage:
  2968. if (SystemInformationLength != sizeof( ULONG ) ) {
  2969. return STATUS_INFO_LENGTH_MISMATCH;
  2970. }
  2971. Status = ExpUpdateComPlusPackage (*(PULONG)SystemInformation);
  2972. if (NT_SUCCESS (Status)) {
  2973. SharedUserData->ComPlusPackage = *(PULONG)SystemInformation;
  2974. }
  2975. break;
  2976. case SystemHotpatchInformation:
  2977. #if defined(_X86_)
  2978. Status = ExApplyCodePatch( SystemInformation,
  2979. SystemInformationLength
  2980. );
  2981. #else
  2982. //
  2983. // The platforms which no not support hotpatching yet
  2984. // simple return the appropriate status
  2985. //
  2986. Status = STATUS_NOT_IMPLEMENTED;
  2987. #endif
  2988. break;
  2989. case SystemWatchdogTimerHandler:
  2990. {
  2991. PSYSTEM_WATCHDOG_HANDLER_INFORMATION WdHandlerInfo = (PSYSTEM_WATCHDOG_HANDLER_INFORMATION) SystemInformation;
  2992. //
  2993. // Caller must be kernel mode with the proper parameters
  2994. //
  2995. if (PreviousMode != KernelMode || SystemInformation == NULL || SystemInformationLength != sizeof(SYSTEM_WATCHDOG_HANDLER_INFORMATION)) {
  2996. ExRaiseStatus (STATUS_INVALID_PARAMETER);
  2997. }
  2998. ExpWdHandler = WdHandlerInfo->WdHandler;
  2999. ExpWdHandlerContext = WdHandlerInfo->Context;
  3000. }
  3001. break;
  3002. case SystemWatchdogTimerInformation:
  3003. {
  3004. PSYSTEM_WATCHDOG_TIMER_INFORMATION WdTimerInfo = (PSYSTEM_WATCHDOG_TIMER_INFORMATION) SystemInformation;
  3005. //
  3006. // Caller must be kernel mode with the proper parameters
  3007. //
  3008. if (PreviousMode != KernelMode || SystemInformation == NULL || SystemInformationLength != sizeof(SYSTEM_WATCHDOG_TIMER_INFORMATION)) {
  3009. ExRaiseStatus (STATUS_INVALID_PARAMETER);
  3010. }
  3011. if (ExpWdHandler == NULL) {
  3012. Status = STATUS_NOT_IMPLEMENTED;
  3013. } else {
  3014. switch (WdTimerInfo->WdInfoClass) {
  3015. case WdInfoTimeoutValue:
  3016. Status = ExpWdHandler( WdActionSetTimeoutValue, ExpWdHandlerContext, &WdTimerInfo->DataValue, FALSE );
  3017. break;
  3018. case WdInfoResetTimer:
  3019. Status = ExpWdHandler( WdActionResetTimer, ExpWdHandlerContext, NULL, FALSE );
  3020. break;
  3021. case WdInfoStopTimer:
  3022. Status = ExpWdHandler( WdActionStopTimer, ExpWdHandlerContext, NULL, FALSE );
  3023. break;
  3024. case WdInfoStartTimer:
  3025. Status = ExpWdHandler( WdActionStartTimer, ExpWdHandlerContext, NULL, FALSE );
  3026. break;
  3027. case WdInfoTriggerAction:
  3028. Status = ExpWdHandler( WdActionSetTriggerAction, ExpWdHandlerContext, &WdTimerInfo->DataValue, FALSE );
  3029. break;
  3030. default:
  3031. Status = STATUS_INVALID_PARAMETER;
  3032. break;
  3033. }
  3034. }
  3035. }
  3036. break;
  3037. default:
  3038. //KeBugCheckEx(SystemInformationClass,KdPitchDebugger,0,0,0);
  3039. Status = STATUS_INVALID_INFO_CLASS;
  3040. break;
  3041. }
  3042. } except (EXCEPTION_EXECUTE_HANDLER) {
  3043. Status = GetExceptionCode();
  3044. }
  3045. return Status;
  3046. }
  3047. NTSTATUS
  3048. ExLockUserBuffer (
  3049. IN PVOID Buffer,
  3050. IN ULONG Length,
  3051. IN KPROCESSOR_MODE ProbeMode,
  3052. IN LOCK_OPERATION LockMode,
  3053. OUT PVOID *LockedBuffer,
  3054. OUT PVOID *LockVariable
  3055. )
  3056. /*++
  3057. Routine Description:
  3058. Wrapper for MmProbeAndLockPages. Creates an MDL and locks the
  3059. specified buffer with that MDL.
  3060. Arguments:
  3061. Buffer - pointer to the buffer to be locked.
  3062. Length - size of the buffer to be locked.
  3063. ProbeMode - processor mode for doing the probe in MmProbeAndLockPages.
  3064. LockMode - the mode the pages should be locked for.
  3065. LockedBuffer - returns a pointer to the locked buffer for use by the
  3066. caller.
  3067. LockVariable - returns a context pointer. This must be passed into
  3068. ExUnlockUserBuffer when complete so the MDL can be freed.
  3069. Return Value:
  3070. Returns one of the following status codes:
  3071. STATUS_SUCCESS - Normal, successful completion.
  3072. STATUS_ACCESS_VIOLATION - The buffer is not accessible with the
  3073. specified LockMode.
  3074. STATUS_INSUFFICIENT_RESOURCES - not enough memory to allocate the MDL.
  3075. --*/
  3076. {
  3077. PMDL Mdl;
  3078. SIZE_T MdlSize;
  3079. //
  3080. // It is the caller's responsibility to ensure zero cannot be passed in.
  3081. //
  3082. ASSERT (Length != 0);
  3083. *LockedBuffer = NULL;
  3084. *LockVariable = NULL;
  3085. //
  3086. // Allocate an MDL to map the request.
  3087. //
  3088. MdlSize = MmSizeOfMdl( Buffer, Length );
  3089. Mdl = ExAllocatePoolWithQuotaTag (NonPagedPool | POOL_QUOTA_FAIL_INSTEAD_OF_RAISE,
  3090. MdlSize,
  3091. 'ofnI');
  3092. if (Mdl == NULL) {
  3093. return STATUS_INSUFFICIENT_RESOURCES;
  3094. }
  3095. //
  3096. // Initialize MDL for request.
  3097. //
  3098. MmInitializeMdl(Mdl, Buffer, Length);
  3099. try {
  3100. MmProbeAndLockPages (Mdl, ProbeMode, LockMode);
  3101. } except (EXCEPTION_EXECUTE_HANDLER) {
  3102. ExFreePool (Mdl);
  3103. return GetExceptionCode();
  3104. }
  3105. Mdl->MdlFlags |= MDL_MAPPING_CAN_FAIL;
  3106. *LockedBuffer = MmGetSystemAddressForMdl (Mdl);
  3107. if (*LockedBuffer == NULL) {
  3108. ExUnlockUserBuffer (Mdl);
  3109. return STATUS_INSUFFICIENT_RESOURCES;
  3110. }
  3111. *LockVariable = Mdl;
  3112. return STATUS_SUCCESS;
  3113. }
  3114. VOID
  3115. ExUnlockUserBuffer(
  3116. IN PVOID LockVariable
  3117. )
  3118. {
  3119. MmUnlockPages ((PMDL)LockVariable);
  3120. ExFreePool ((PMDL)LockVariable);
  3121. return;
  3122. }
  3123. NTSTATUS
  3124. ExpGetProcessInformation (
  3125. OUT PVOID SystemInformation,
  3126. IN ULONG SystemInformationLength,
  3127. OUT PULONG Length,
  3128. IN PULONG SessionId OPTIONAL,
  3129. IN BOOLEAN ExtendedInformation
  3130. )
  3131. /*++
  3132. Routine Description:
  3133. This function returns information about all the processes and
  3134. threads in the system.
  3135. Arguments:
  3136. SystemInformation - A pointer to a buffer which receives the specified
  3137. information.
  3138. SystemInformationLength - Specifies the length in bytes of the system
  3139. information buffer.
  3140. Length - An optional pointer which, if specified, receives the
  3141. number of bytes placed in the system information buffer.
  3142. SessionId - Session Id.
  3143. ExtendedInformation - TRUE if extended information (e.g., Process PDE) is needed.
  3144. Environment:
  3145. Kernel mode.
  3146. This routine could be made PAGELK but it is a high frequency routine
  3147. so it is actually better to keep it nonpaged to avoid bringing in the
  3148. entire PAGELK section.
  3149. Return Value:
  3150. Returns one of the following status codes:
  3151. STATUS_SUCCESS - normal, successful completion.
  3152. STATUS_INVALID_INFO_CLASS - The SystemInformationClass parameter
  3153. did not specify a valid value.
  3154. STATUS_INFO_LENGTH_MISMATCH - The value of the SystemInformationLength
  3155. parameter did not match the length required for the information
  3156. class requested by the SystemInformationClass parameter.
  3157. STATUS_ACCESS_VIOLATION - Either the SystemInformation buffer pointer
  3158. or the Length pointer value specified an invalid address.
  3159. STATUS_WORKING_SET_QUOTA - The process does not have sufficient
  3160. working set to lock the specified output structure in memory.
  3161. STATUS_INSUFFICIENT_RESOURCES - Insufficient system resources exist
  3162. for this request to complete.
  3163. --*/
  3164. {
  3165. KLOCK_QUEUE_HANDLE LockHandle;
  3166. PEPROCESS Process = NULL;
  3167. PETHREAD Thread;
  3168. PSYSTEM_PROCESS_INFORMATION ProcessInfo;
  3169. PVOID ThreadInfo;
  3170. ULONG ThreadInfoSize;
  3171. PLIST_ENTRY NextThread;
  3172. PVOID MappedAddress;
  3173. PVOID LockVariable;
  3174. ULONG ProcessSessionId;
  3175. ULONG TotalSize = 0;
  3176. ULONG NextEntryOffset = 0;
  3177. PUCHAR Src;
  3178. PWCHAR SrcW;
  3179. PWSTR Dst;
  3180. ULONG n, nc;
  3181. NTSTATUS status = STATUS_SUCCESS, status1;
  3182. PUNICODE_STRING pImageFileName;
  3183. *Length = 0;
  3184. if (SystemInformationLength > 0) {
  3185. status1 = ExLockUserBuffer (SystemInformation,
  3186. SystemInformationLength,
  3187. KeGetPreviousMode(),
  3188. IoWriteAccess,
  3189. &MappedAddress,
  3190. &LockVariable);
  3191. if (!NT_SUCCESS(status1)) {
  3192. return status1;
  3193. }
  3194. } else {
  3195. //
  3196. // This indicates the caller just wants to know the size of the
  3197. // buffer to allocate but is not prepared to accept any data content
  3198. // in this instance.
  3199. //
  3200. MappedAddress = NULL;
  3201. LockVariable = NULL;
  3202. }
  3203. if (ExtendedInformation) {
  3204. ThreadInfoSize = sizeof(SYSTEM_EXTENDED_THREAD_INFORMATION);
  3205. } else {
  3206. ThreadInfoSize = sizeof(SYSTEM_THREAD_INFORMATION);
  3207. }
  3208. ProcessInfo = (PSYSTEM_PROCESS_INFORMATION) MappedAddress;
  3209. try {
  3210. //
  3211. // Do the idle process first then all the other processes.
  3212. //
  3213. for (Process = PsIdleProcess;
  3214. Process != NULL;
  3215. Process = PsGetNextProcess ((Process == PsIdleProcess) ? NULL : Process)) {
  3216. //
  3217. // Skip terminating processes
  3218. //
  3219. if (Process->Flags&PS_PROCESS_FLAGS_PROCESS_EXITING) {
  3220. continue;
  3221. }
  3222. if (ARGUMENT_PRESENT(SessionId) && Process == PsIdleProcess) {
  3223. continue;
  3224. }
  3225. ProcessSessionId = MmGetSessionId (Process);
  3226. if ((ARGUMENT_PRESENT(SessionId)) &&
  3227. (ProcessSessionId != *SessionId)) {
  3228. continue;
  3229. }
  3230. ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)
  3231. ((PUCHAR)MappedAddress + TotalSize);
  3232. NextEntryOffset = sizeof(SYSTEM_PROCESS_INFORMATION);
  3233. TotalSize += sizeof(SYSTEM_PROCESS_INFORMATION);
  3234. if (TotalSize > SystemInformationLength) {
  3235. status = STATUS_INFO_LENGTH_MISMATCH;
  3236. } else {
  3237. //
  3238. // Get information for each process.
  3239. //
  3240. ExpCopyProcessInfo (ProcessInfo, Process, ExtendedInformation);
  3241. ProcessInfo->NumberOfThreads = 0;
  3242. //
  3243. // Store the Remote Terminal SessionId
  3244. //
  3245. ProcessInfo->SessionId = ProcessSessionId;
  3246. ProcessInfo->ImageName.Buffer = NULL;
  3247. ProcessInfo->ImageName.Length = 0;
  3248. ProcessInfo->ImageName.MaximumLength = 0;
  3249. if (Process == PsIdleProcess) {
  3250. //
  3251. // Since Idle process and system process share the same
  3252. // object table, zero out idle processes handle count to
  3253. // reduce confusion
  3254. //
  3255. // Idle Process always has SessionId 0
  3256. //
  3257. ProcessInfo->HandleCount = 0;
  3258. ProcessInfo->SessionId = 0;
  3259. }
  3260. }
  3261. //
  3262. // Raise IRQL to SYNCH_LEVEL, acquire the kernel process lock, and
  3263. // get information for each thread.
  3264. //
  3265. ThreadInfo = (PVOID)(ProcessInfo + 1);
  3266. KeAcquireInStackQueuedSpinLockRaiseToSynch(&Process->Pcb.ProcessLock,
  3267. &LockHandle);
  3268. NextThread = Process->Pcb.ThreadListHead.Flink;
  3269. while (NextThread != &Process->Pcb.ThreadListHead) {
  3270. NextEntryOffset += ThreadInfoSize;
  3271. TotalSize += ThreadInfoSize;
  3272. if (TotalSize > SystemInformationLength) {
  3273. status = STATUS_INFO_LENGTH_MISMATCH;
  3274. } else {
  3275. Thread = (PETHREAD)(CONTAINING_RECORD(NextThread,
  3276. KTHREAD,
  3277. ThreadListEntry));
  3278. //
  3279. // Lock dispatcher database to get atomic view of thread
  3280. // attributes.
  3281. //
  3282. KiLockDispatcherDatabaseAtSynchLevel();
  3283. ExpCopyThreadInfo (ThreadInfo, Thread, ExtendedInformation);
  3284. KiUnlockDispatcherDatabaseFromSynchLevel();
  3285. ProcessInfo->NumberOfThreads += 1;
  3286. ThreadInfo = (PCHAR) ThreadInfo + ThreadInfoSize;
  3287. }
  3288. NextThread = NextThread->Flink;
  3289. }
  3290. //
  3291. // Unlock kernel process lock and lower IRQL to its previous value.
  3292. //
  3293. KeReleaseInStackQueuedSpinLock(&LockHandle);
  3294. //
  3295. // Get the image name.
  3296. //
  3297. if (Process != PsIdleProcess) {
  3298. //
  3299. // Try to use the real image name if we can that not limited to 16 characters
  3300. //
  3301. Dst = (PWSTR)(ThreadInfo);
  3302. status1 = SeLocateProcessImageName (Process, &pImageFileName);
  3303. if (NT_SUCCESS (status1)) {
  3304. n = pImageFileName->Length;
  3305. if (n == 0) {
  3306. ExFreePool (pImageFileName);
  3307. }
  3308. } else {
  3309. n = 0;
  3310. }
  3311. if (n) {
  3312. SrcW = pImageFileName->Buffer + n / sizeof (WCHAR);
  3313. while (SrcW != pImageFileName->Buffer) {
  3314. if (*--SrcW == L'\\') {
  3315. SrcW = SrcW + 1;
  3316. break;
  3317. }
  3318. }
  3319. nc = n - (ULONG)(SrcW - pImageFileName->Buffer) * sizeof (WCHAR);
  3320. n = ROUND_UP (nc + 1, sizeof(LARGE_INTEGER));
  3321. TotalSize += n;
  3322. NextEntryOffset += n;
  3323. if (TotalSize > SystemInformationLength) {
  3324. status = STATUS_INFO_LENGTH_MISMATCH;
  3325. } else {
  3326. RtlCopyMemory (Dst, SrcW, nc);
  3327. Dst += nc / sizeof (WCHAR);
  3328. *Dst++ = L'\0';
  3329. }
  3330. ExFreePool (pImageFileName);
  3331. } else {
  3332. Src = Process->ImageFileName;
  3333. n = (ULONG) strlen ((PCHAR)Src);
  3334. if (n != 0) {
  3335. n = ROUND_UP( ((n + 1) * sizeof( WCHAR )), sizeof(LARGE_INTEGER) );
  3336. TotalSize += n;
  3337. NextEntryOffset += n;
  3338. if (TotalSize > SystemInformationLength) {
  3339. status = STATUS_INFO_LENGTH_MISMATCH;
  3340. } else {
  3341. WCHAR c;
  3342. while (1) {
  3343. c = (WCHAR)*Src++;
  3344. *Dst++ = c;
  3345. if (c == L'\0') {
  3346. break;
  3347. }
  3348. }
  3349. }
  3350. }
  3351. }
  3352. if (NT_SUCCESS (status)) {
  3353. ProcessInfo->ImageName.Length = (USHORT)((PCHAR)Dst -
  3354. (PCHAR)ThreadInfo - sizeof( UNICODE_NULL ));
  3355. ProcessInfo->ImageName.MaximumLength = (USHORT)n;
  3356. //
  3357. // Set the image name to point into the user's memory.
  3358. //
  3359. ProcessInfo->ImageName.Buffer = (PWSTR)
  3360. ((PCHAR)SystemInformation +
  3361. ((PCHAR)(ThreadInfo) - (PCHAR)MappedAddress));
  3362. }
  3363. }
  3364. //
  3365. // Point to next process.
  3366. //
  3367. if (NT_SUCCESS (status)) {
  3368. ProcessInfo->NextEntryOffset = NextEntryOffset;
  3369. }
  3370. }
  3371. if (NT_SUCCESS (status)) {
  3372. ProcessInfo->NextEntryOffset = 0;
  3373. }
  3374. *Length = TotalSize;
  3375. } finally {
  3376. if (MappedAddress != NULL) {
  3377. ExUnlockUserBuffer (LockVariable);
  3378. }
  3379. }
  3380. return status;
  3381. }
  3382. NTSTATUS
  3383. ExGetSessionPoolTagInformation (
  3384. OUT PVOID SystemInformation,
  3385. IN ULONG SystemInformationLength,
  3386. OUT PULONG Length,
  3387. IN PULONG SessionId OPTIONAL
  3388. )
  3389. /*++
  3390. Routine Description:
  3391. This function returns information about all the per-session pool tag
  3392. information in the system.
  3393. Arguments:
  3394. SystemInformation - A pointer to a buffer which receives the specified
  3395. information.
  3396. SystemInformationLength - Specifies the length in bytes of the system
  3397. information buffer.
  3398. Length - Receives the number of bytes placed (or would have been placed)
  3399. in the system information buffer.
  3400. SessionId - Session Id (-1 indicates enumerate all sessions).
  3401. Environment:
  3402. Kernel mode.
  3403. Return Value:
  3404. Returns one of the following status codes:
  3405. STATUS_SUCCESS - normal, successful completion.
  3406. STATUS_INVALID_INFO_CLASS - The SystemInformationClass parameter
  3407. did not specify a valid value.
  3408. STATUS_INFO_LENGTH_MISMATCH - The value of the SystemInformationLength
  3409. parameter did not match the length required for the information
  3410. class requested by the SystemInformationClass parameter.
  3411. STATUS_ACCESS_VIOLATION - Either the SystemInformation buffer pointer
  3412. or the Length pointer value specified an invalid address.
  3413. STATUS_WORKING_SET_QUOTA - The process does not have sufficient
  3414. working set to lock the specified output structure in memory.
  3415. STATUS_INSUFFICIENT_RESOURCES - Insufficient system resources exist
  3416. for this request to complete.
  3417. --*/
  3418. {
  3419. KAPC_STATE ApcState;
  3420. PVOID MappedAddress;
  3421. PVOID OpaqueSession;
  3422. PVOID LockVariable;
  3423. ULONG TotalSize;
  3424. ULONG NextEntryOffset;
  3425. ULONG CurrentSessionId;
  3426. ULONG Count;
  3427. ULONG AbsoluteCount;
  3428. NTSTATUS status;
  3429. NTSTATUS status1;
  3430. PSYSTEM_SESSION_POOLTAG_INFORMATION SessionPoolTagInfo;
  3431. *Length = 0;
  3432. TotalSize = 0;
  3433. NextEntryOffset = 0;
  3434. status = STATUS_SUCCESS;
  3435. SessionPoolTagInfo = NULL;
  3436. if (SystemInformationLength > 0) {
  3437. status1 = ExLockUserBuffer (SystemInformation,
  3438. SystemInformationLength,
  3439. KeGetPreviousMode(),
  3440. IoWriteAccess,
  3441. &MappedAddress,
  3442. &LockVariable);
  3443. if (!NT_SUCCESS(status1)) {
  3444. return status1;
  3445. }
  3446. }
  3447. else {
  3448. //
  3449. // This indicates the caller just wants to know the size of the
  3450. // buffer to allocate but is not prepared to accept any data content
  3451. // in this instance.
  3452. //
  3453. MappedAddress = NULL;
  3454. LockVariable = NULL;
  3455. }
  3456. for (OpaqueSession = MmGetNextSession (NULL);
  3457. OpaqueSession != NULL;
  3458. OpaqueSession = MmGetNextSession (OpaqueSession)) {
  3459. SessionPoolTagInfo = (PSYSTEM_SESSION_POOLTAG_INFORMATION)
  3460. ((PUCHAR)MappedAddress + TotalSize);
  3461. //
  3462. // If a specific session was requested, only extract that one.
  3463. //
  3464. CurrentSessionId = MmGetSessionId (OpaqueSession);
  3465. if ((*SessionId == 0xFFFFFFFF) || (CurrentSessionId == *SessionId)) {
  3466. //
  3467. // Attach to session now to perform operations...
  3468. //
  3469. if (NT_SUCCESS (MmAttachSession (OpaqueSession, &ApcState))) {
  3470. //
  3471. // Session is still alive so include it.
  3472. //
  3473. NextEntryOffset = sizeof (SYSTEM_SESSION_POOLTAG_INFORMATION);
  3474. TotalSize += sizeof (SYSTEM_SESSION_POOLTAG_INFORMATION);
  3475. if (TotalSize > SystemInformationLength) {
  3476. status = STATUS_INFO_LENGTH_MISMATCH;
  3477. //
  3478. // Get absolute size for this session, ignore status as
  3479. // we must return the one above.
  3480. //
  3481. ExGetSessionPoolTagInfo (NULL,
  3482. 0,
  3483. &Count,
  3484. &AbsoluteCount);
  3485. }
  3486. else {
  3487. //
  3488. // Get pool tagging information for each session.
  3489. //
  3490. status = ExGetSessionPoolTagInfo (
  3491. SessionPoolTagInfo->TagInfo,
  3492. SystemInformationLength - TotalSize + sizeof (SYSTEM_POOLTAG),
  3493. &Count,
  3494. &AbsoluteCount);
  3495. SessionPoolTagInfo->SessionId = CurrentSessionId;
  3496. SessionPoolTagInfo->Count = Count;
  3497. //
  3498. // Point to next session.
  3499. //
  3500. if (NT_SUCCESS (status)) {
  3501. NextEntryOffset += ((Count - 1) * sizeof (SYSTEM_POOLTAG));
  3502. SessionPoolTagInfo->NextEntryOffset = NextEntryOffset;
  3503. }
  3504. }
  3505. TotalSize += ((AbsoluteCount - 1) * sizeof (SYSTEM_POOLTAG));
  3506. //
  3507. // Detach from session.
  3508. //
  3509. MmDetachSession (OpaqueSession, &ApcState);
  3510. }
  3511. //
  3512. // Bail if only this session was of interest.
  3513. //
  3514. if (*SessionId != 0xFFFFFFFF) {
  3515. MmQuitNextSession (OpaqueSession);
  3516. break;
  3517. }
  3518. }
  3519. }
  3520. if ((NT_SUCCESS (status)) && (SessionPoolTagInfo != NULL)) {
  3521. SessionPoolTagInfo->NextEntryOffset = 0;
  3522. }
  3523. if (MappedAddress != NULL) {
  3524. ExUnlockUserBuffer (LockVariable);
  3525. }
  3526. *Length = TotalSize;
  3527. return status;
  3528. }
  3529. VOID
  3530. ExpGetProcessorPowerInformation (
  3531. OUT PVOID SystemInformation,
  3532. IN ULONG SystemInformationLength,
  3533. OUT PULONG Length
  3534. )
  3535. {
  3536. KAFFINITY currentAffinity;
  3537. KAFFINITY processors;
  3538. KIRQL oldIrql;
  3539. PKPRCB Prcb;
  3540. PPROCESSOR_POWER_STATE PState;
  3541. PPROCESSOR_PERF_STATE PerfStates;
  3542. PSYSTEM_PROCESSOR_POWER_INFORMATION CallerPowerInfo;
  3543. SYSTEM_PROCESSOR_POWER_INFORMATION ProcessorPowerInfo;
  3544. //
  3545. // We will walk this pointer to store the user data...
  3546. //
  3547. CallerPowerInfo = (PSYSTEM_PROCESSOR_POWER_INFORMATION) SystemInformation;
  3548. *Length = 0;
  3549. //
  3550. // Lock everything down
  3551. //
  3552. MmLockPagableSectionByHandle (ExPageLockHandle);
  3553. //
  3554. // Walk the list of processors
  3555. //
  3556. processors = KeActiveProcessors;
  3557. currentAffinity = 1;
  3558. while (processors) {
  3559. if (!(processors & currentAffinity)) {
  3560. currentAffinity <<= 1;
  3561. }
  3562. //
  3563. // Check to see if we have the space for this
  3564. //
  3565. if (SystemInformationLength < *Length + sizeof(SYSTEM_PROCESSOR_POWER_INFORMATION)) {
  3566. break;
  3567. }
  3568. processors &= ~currentAffinity;
  3569. KeSetSystemAffinityThread(currentAffinity);
  3570. currentAffinity <<= 1;
  3571. //
  3572. // Raise to DPC level to synchronize access to the data structures
  3573. //
  3574. KeRaiseIrql(DISPATCH_LEVEL, &oldIrql );
  3575. //
  3576. // Get the PRCB and PowerState information
  3577. //
  3578. Prcb = KeGetCurrentPrcb();
  3579. PState = &(Prcb->PowerState);
  3580. PerfStates = PState->PerfStates;
  3581. //
  3582. // Grab the data that we care about
  3583. //
  3584. ProcessorPowerInfo.CurrentFrequency = PState->CurrentThrottle;
  3585. ProcessorPowerInfo.LastBusyFrequency = PState->LastBusyPercentage;
  3586. ProcessorPowerInfo.LastAdjustedBusyFrequency = PState->LastAdjustedBusyPercentage;
  3587. ProcessorPowerInfo.LastC3Frequency = PState->LastC3Percentage;
  3588. ProcessorPowerInfo.ProcessorMinThrottle = PState->ProcessorMinThrottle;
  3589. ProcessorPowerInfo.ProcessorMaxThrottle = PState->ProcessorMaxThrottle;
  3590. ProcessorPowerInfo.ErrorCount = PState->ErrorCount;
  3591. ProcessorPowerInfo.RetryCount = PState->RetryCount;
  3592. //
  3593. // Do we have any kind of PerfStates?
  3594. //
  3595. if (PerfStates) {
  3596. ProcessorPowerInfo.ThermalLimitFrequency = PerfStates[PState->ThermalThrottleIndex].PercentFrequency;
  3597. ProcessorPowerInfo.ConstantThrottleFrequency = PerfStates[PState->KneeThrottleIndex].PercentFrequency;
  3598. ProcessorPowerInfo.DegradedThrottleFrequency = PerfStates[PState->ThrottleLimitIndex].PercentFrequency;
  3599. } else {
  3600. ProcessorPowerInfo.ThermalLimitFrequency = 0;
  3601. ProcessorPowerInfo.ConstantThrottleFrequency = 0;
  3602. ProcessorPowerInfo.DegradedThrottleFrequency = 0;
  3603. }
  3604. ProcessorPowerInfo.CurrentFrequencyTime =
  3605. UInt32x32To64(
  3606. (Prcb->KernelTime + Prcb->UserTime - PState->PerfTickCount),
  3607. KeMaximumIncrement
  3608. );
  3609. ProcessorPowerInfo.CurrentProcessorTime =
  3610. UInt32x32To64(
  3611. Prcb->KernelTime + Prcb->UserTime,
  3612. KeMaximumIncrement
  3613. );
  3614. ProcessorPowerInfo.CurrentProcessorIdleTime =
  3615. UInt32x32To64( Prcb->IdleThread->KernelTime, KeMaximumIncrement );
  3616. ProcessorPowerInfo.LastProcessorTime =
  3617. UInt32x32To64( PState->PerfSystemTime, KeMaximumIncrement );
  3618. ProcessorPowerInfo.LastProcessorIdleTime =
  3619. UInt32x32To64( PState->PerfIdleTime, KeMaximumIncrement );
  3620. ProcessorPowerInfo.PromotionCount = PState->PromotionCount;
  3621. ProcessorPowerInfo.DemotionCount = PState->DemotionCount;
  3622. ProcessorPowerInfo.NumberOfFrequencies = PState->PerfStatesCount;
  3623. //
  3624. // Return to the original level (should be IRQL 0)
  3625. //
  3626. KeLowerIrql( oldIrql );
  3627. //
  3628. // Copy the data to the correct place
  3629. //
  3630. try {
  3631. RtlCopyMemory(
  3632. CallerPowerInfo,
  3633. &ProcessorPowerInfo,
  3634. sizeof(SYSTEM_PROCESSOR_POWER_INFORMATION)
  3635. );
  3636. } except (EXCEPTION_EXECUTE_HANDLER) {
  3637. MmUnlockPagableImageSection(ExPageLockHandle);
  3638. ExRaiseStatus (GetExceptionCode ());
  3639. }
  3640. //
  3641. // Point to the next structure element
  3642. //
  3643. CallerPowerInfo++;
  3644. *Length += sizeof(SYSTEM_PROCESSOR_POWER_INFORMATION);
  3645. }
  3646. //
  3647. // Revert to the original affinity
  3648. //
  3649. KeRevertToUserAffinityThread();
  3650. //
  3651. // Unlock everything
  3652. MmUnlockPagableImageSection(ExPageLockHandle);
  3653. }
  3654. VOID
  3655. ExpGetProcessorIdleInformation (
  3656. OUT PVOID SystemInformation,
  3657. IN ULONG SystemInformationLength,
  3658. OUT PULONG Length
  3659. )
  3660. {
  3661. KAFFINITY currentAffinity;
  3662. KAFFINITY processors;
  3663. KIRQL oldIrql;
  3664. LARGE_INTEGER PerfFrequency;
  3665. PKPRCB Prcb;
  3666. PPROCESSOR_POWER_STATE PState;
  3667. PSYSTEM_PROCESSOR_IDLE_INFORMATION CallerIdleInfo;
  3668. SYSTEM_PROCESSOR_IDLE_INFORMATION ProcessorIdleInfo;
  3669. //
  3670. // We will walk this pointer to store the user data...
  3671. //
  3672. CallerIdleInfo = (PSYSTEM_PROCESSOR_IDLE_INFORMATION) SystemInformation;
  3673. *Length = 0;
  3674. //
  3675. // We need to know what frequency the perf counters are running at
  3676. //
  3677. KeQueryPerformanceCounter(&PerfFrequency);
  3678. //
  3679. // Lock everything down
  3680. //
  3681. MmLockPagableSectionByHandle (ExPageLockHandle);
  3682. //
  3683. // Walk the list of processors
  3684. //
  3685. processors = KeActiveProcessors;
  3686. currentAffinity = 1;
  3687. while (processors) {
  3688. if (!(processors & currentAffinity)) {
  3689. currentAffinity <<= 1;
  3690. }
  3691. //
  3692. // Check to see if we have the space for this
  3693. //
  3694. if (SystemInformationLength < *Length + sizeof(SYSTEM_PROCESSOR_IDLE_INFORMATION)) {
  3695. break;
  3696. }
  3697. processors &= ~currentAffinity;
  3698. KeSetSystemAffinityThread(currentAffinity);
  3699. currentAffinity <<= 1;
  3700. //
  3701. // Raise to DPC level to synchronize access to the data structures
  3702. //
  3703. KeRaiseIrql(DISPATCH_LEVEL, &oldIrql );
  3704. //
  3705. // Get the PRCB and PowerState information
  3706. //
  3707. Prcb = KeGetCurrentPrcb();
  3708. PState = &(Prcb->PowerState);
  3709. //
  3710. // Grab the data that we care about
  3711. //
  3712. ProcessorIdleInfo.IdleTime = UInt32x32To64(Prcb->IdleThread->KernelTime,KeMaximumIncrement);
  3713. //
  3714. // The Cx times are kept in units of the same frequency as KeQueryPerformanceCounter
  3715. // This needs to be converted to standard 100ns units.
  3716. //
  3717. ProcessorIdleInfo.C1Time = (PState->TotalIdleStateTime[0]*1000)/(PerfFrequency.QuadPart/10000);
  3718. ProcessorIdleInfo.C2Time = (PState->TotalIdleStateTime[1]*1000)/(PerfFrequency.QuadPart/10000);
  3719. ProcessorIdleInfo.C3Time = (PState->TotalIdleStateTime[2]*1000)/(PerfFrequency.QuadPart/10000);
  3720. ProcessorIdleInfo.C1Transitions = PState->TotalIdleTransitions[0];
  3721. ProcessorIdleInfo.C2Transitions = PState->TotalIdleTransitions[1];
  3722. ProcessorIdleInfo.C3Transitions = PState->TotalIdleTransitions[2];
  3723. //
  3724. // Return to the original level (should be IRQL 0)
  3725. //
  3726. KeLowerIrql( oldIrql );
  3727. //
  3728. // Copy the data to the correct place
  3729. //
  3730. try {
  3731. RtlCopyMemory(
  3732. CallerIdleInfo,
  3733. &ProcessorIdleInfo,
  3734. sizeof(SYSTEM_PROCESSOR_IDLE_INFORMATION)
  3735. );
  3736. } except (EXCEPTION_EXECUTE_HANDLER) {
  3737. MmUnlockPagableImageSection (ExPageLockHandle);
  3738. ExRaiseStatus (GetExceptionCode ());
  3739. }
  3740. //
  3741. // Point to the next structure element
  3742. //
  3743. CallerIdleInfo++;
  3744. *Length += sizeof(SYSTEM_PROCESSOR_IDLE_INFORMATION);
  3745. }
  3746. //
  3747. // Revert to the original affinity
  3748. //
  3749. KeRevertToUserAffinityThread();
  3750. //
  3751. // Unlock everything
  3752. //
  3753. MmUnlockPagableImageSection(ExPageLockHandle);
  3754. }
  3755. VOID
  3756. ExpCopyProcessInfo (
  3757. IN PSYSTEM_PROCESS_INFORMATION ProcessInfo,
  3758. IN PEPROCESS Process,
  3759. IN BOOLEAN ExtendedInformation
  3760. )
  3761. {
  3762. PAGED_CODE();
  3763. ProcessInfo->HandleCount = ObGetProcessHandleCount (Process);
  3764. ProcessInfo->CreateTime = Process->CreateTime;
  3765. ProcessInfo->UserTime.QuadPart = UInt32x32To64(Process->Pcb.UserTime,
  3766. KeMaximumIncrement);
  3767. ProcessInfo->KernelTime.QuadPart = UInt32x32To64(Process->Pcb.KernelTime,
  3768. KeMaximumIncrement);
  3769. ProcessInfo->BasePriority = Process->Pcb.BasePriority;
  3770. ProcessInfo->UniqueProcessId = Process->UniqueProcessId;
  3771. ProcessInfo->InheritedFromUniqueProcessId = Process->InheritedFromUniqueProcessId;
  3772. ProcessInfo->PeakVirtualSize = Process->PeakVirtualSize;
  3773. ProcessInfo->VirtualSize = Process->VirtualSize;
  3774. ProcessInfo->PageFaultCount = Process->Vm.PageFaultCount;
  3775. ProcessInfo->PeakWorkingSetSize = ((SIZE_T)Process->Vm.PeakWorkingSetSize) << PAGE_SHIFT;
  3776. ProcessInfo->WorkingSetSize = ((SIZE_T)Process->Vm.WorkingSetSize) << PAGE_SHIFT;
  3777. ProcessInfo->QuotaPeakPagedPoolUsage =
  3778. Process->QuotaPeak[PsPagedPool];
  3779. ProcessInfo->QuotaPagedPoolUsage = Process->QuotaUsage[PsPagedPool];
  3780. ProcessInfo->QuotaPeakNonPagedPoolUsage =
  3781. Process->QuotaPeak[PsNonPagedPool];
  3782. ProcessInfo->QuotaNonPagedPoolUsage =
  3783. Process->QuotaUsage[PsNonPagedPool];
  3784. ProcessInfo->PagefileUsage = Process->QuotaUsage[PsPageFile] << PAGE_SHIFT;
  3785. ProcessInfo->PeakPagefileUsage = Process->QuotaPeak[PsPageFile] << PAGE_SHIFT;
  3786. ProcessInfo->PrivatePageCount = Process->CommitCharge << PAGE_SHIFT;
  3787. ProcessInfo->ReadOperationCount = Process->ReadOperationCount;
  3788. ProcessInfo->WriteOperationCount = Process->WriteOperationCount;
  3789. ProcessInfo->OtherOperationCount = Process->OtherOperationCount;
  3790. ProcessInfo->ReadTransferCount = Process->ReadTransferCount;
  3791. ProcessInfo->WriteTransferCount = Process->WriteTransferCount;
  3792. ProcessInfo->OtherTransferCount = Process->OtherTransferCount;
  3793. if (ExtendedInformation) {
  3794. ProcessInfo->PageDirectoryBase = MmGetDirectoryFrameFromProcess(Process);
  3795. }
  3796. }
  3797. VOID
  3798. ExpCopyThreadInfo (
  3799. IN PVOID ThreadInfoBuffer,
  3800. IN PETHREAD Thread,
  3801. IN BOOLEAN ExtendedInformation
  3802. )
  3803. /*++
  3804. Routine Description:
  3805. This function returns information about the specified thread.
  3806. Arguments:
  3807. ThreadInfoBuffer - A pointer to a buffer which receives the specified
  3808. information.
  3809. Thread - Supplies a pointer to the desired thread.
  3810. ExtendedInformation - TRUE if extended thread information is needed.
  3811. Environment:
  3812. Kernel mode. The dispatcher lock is held.
  3813. This routine could be made PAGELK but it is a high frequency routine
  3814. so it is actually better to keep it nonpaged to avoid bringing in the
  3815. entire PAGELK section.
  3816. Return Value:
  3817. None.
  3818. --*/
  3819. {
  3820. PSYSTEM_THREAD_INFORMATION ThreadInfo;
  3821. ThreadInfo = (PSYSTEM_THREAD_INFORMATION) ThreadInfoBuffer;
  3822. ThreadInfo->KernelTime.QuadPart = UInt32x32To64(Thread->Tcb.KernelTime,
  3823. KeMaximumIncrement);
  3824. ThreadInfo->UserTime.QuadPart = UInt32x32To64(Thread->Tcb.UserTime,
  3825. KeMaximumIncrement);
  3826. ThreadInfo->CreateTime.QuadPart = PS_GET_THREAD_CREATE_TIME (Thread);
  3827. ThreadInfo->WaitTime = Thread->Tcb.WaitTime;
  3828. ThreadInfo->ClientId = Thread->Cid;
  3829. ThreadInfo->ThreadState = Thread->Tcb.State;
  3830. ThreadInfo->WaitReason = Thread->Tcb.WaitReason;
  3831. ThreadInfo->Priority = Thread->Tcb.Priority;
  3832. ThreadInfo->BasePriority = Thread->Tcb.BasePriority;
  3833. ThreadInfo->ContextSwitches = Thread->Tcb.ContextSwitches;
  3834. ThreadInfo->StartAddress = Thread->StartAddress;
  3835. if (ExtendedInformation) {
  3836. PSYSTEM_EXTENDED_THREAD_INFORMATION ExtendedThreadInfo;
  3837. ExtendedThreadInfo = (PSYSTEM_EXTENDED_THREAD_INFORMATION) ThreadInfo;
  3838. ExtendedThreadInfo->StackBase = Thread->Tcb.StackBase;
  3839. ExtendedThreadInfo->StackLimit = Thread->Tcb.StackLimit;
  3840. if (Thread->LpcReceivedMsgIdValid) {
  3841. ExtendedThreadInfo->Win32StartAddress = 0;
  3842. } else {
  3843. ExtendedThreadInfo->Win32StartAddress = Thread->Win32StartAddress;
  3844. }
  3845. ExtendedThreadInfo->Reserved1 = 0;
  3846. ExtendedThreadInfo->Reserved2 = 0;
  3847. ExtendedThreadInfo->Reserved3 = 0;
  3848. ExtendedThreadInfo->Reserved4 = 0;
  3849. }
  3850. }
  3851. #if defined(_X86_)
  3852. extern ULONG ExVdmOpcodeDispatchCounts[256];
  3853. extern ULONG VdmBopCount;
  3854. extern ULONG ExVdmSegmentNotPresent;
  3855. #if defined(ALLOC_PRAGMA)
  3856. #pragma alloc_text(PAGE, ExpGetInstemulInformation)
  3857. #endif
  3858. NTSTATUS
  3859. ExpGetInstemulInformation(
  3860. OUT PSYSTEM_VDM_INSTEMUL_INFO Info
  3861. )
  3862. {
  3863. SYSTEM_VDM_INSTEMUL_INFO LocalInfo;
  3864. LocalInfo.VdmOpcode0F = ExVdmOpcodeDispatchCounts[VDM_INDEX_0F];
  3865. LocalInfo.OpcodeESPrefix = ExVdmOpcodeDispatchCounts[VDM_INDEX_ESPrefix];
  3866. LocalInfo.OpcodeCSPrefix = ExVdmOpcodeDispatchCounts[VDM_INDEX_CSPrefix];
  3867. LocalInfo.OpcodeSSPrefix = ExVdmOpcodeDispatchCounts[VDM_INDEX_SSPrefix];
  3868. LocalInfo.OpcodeDSPrefix = ExVdmOpcodeDispatchCounts[VDM_INDEX_DSPrefix];
  3869. LocalInfo.OpcodeFSPrefix = ExVdmOpcodeDispatchCounts[VDM_INDEX_FSPrefix];
  3870. LocalInfo.OpcodeGSPrefix = ExVdmOpcodeDispatchCounts[VDM_INDEX_GSPrefix];
  3871. LocalInfo.OpcodeOPER32Prefix= ExVdmOpcodeDispatchCounts[VDM_INDEX_OPER32Prefix];
  3872. LocalInfo.OpcodeADDR32Prefix= ExVdmOpcodeDispatchCounts[VDM_INDEX_ADDR32Prefix];
  3873. LocalInfo.OpcodeINSB = ExVdmOpcodeDispatchCounts[VDM_INDEX_INSB];
  3874. LocalInfo.OpcodeINSW = ExVdmOpcodeDispatchCounts[VDM_INDEX_INSW];
  3875. LocalInfo.OpcodeOUTSB = ExVdmOpcodeDispatchCounts[VDM_INDEX_OUTSB];
  3876. LocalInfo.OpcodeOUTSW = ExVdmOpcodeDispatchCounts[VDM_INDEX_OUTSW];
  3877. LocalInfo.OpcodePUSHF = ExVdmOpcodeDispatchCounts[VDM_INDEX_PUSHF];
  3878. LocalInfo.OpcodePOPF = ExVdmOpcodeDispatchCounts[VDM_INDEX_POPF];
  3879. LocalInfo.OpcodeINTnn = ExVdmOpcodeDispatchCounts[VDM_INDEX_INTnn];
  3880. LocalInfo.OpcodeINTO = ExVdmOpcodeDispatchCounts[VDM_INDEX_INTO];
  3881. LocalInfo.OpcodeIRET = ExVdmOpcodeDispatchCounts[VDM_INDEX_IRET];
  3882. LocalInfo.OpcodeINBimm = ExVdmOpcodeDispatchCounts[VDM_INDEX_INBimm];
  3883. LocalInfo.OpcodeINWimm = ExVdmOpcodeDispatchCounts[VDM_INDEX_INWimm];
  3884. LocalInfo.OpcodeOUTBimm = ExVdmOpcodeDispatchCounts[VDM_INDEX_OUTBimm];
  3885. LocalInfo.OpcodeOUTWimm = ExVdmOpcodeDispatchCounts[VDM_INDEX_OUTWimm];
  3886. LocalInfo.OpcodeINB = ExVdmOpcodeDispatchCounts[VDM_INDEX_INB];
  3887. LocalInfo.OpcodeINW = ExVdmOpcodeDispatchCounts[VDM_INDEX_INW];
  3888. LocalInfo.OpcodeOUTB = ExVdmOpcodeDispatchCounts[VDM_INDEX_OUTB];
  3889. LocalInfo.OpcodeOUTW = ExVdmOpcodeDispatchCounts[VDM_INDEX_OUTW];
  3890. LocalInfo.OpcodeLOCKPrefix = ExVdmOpcodeDispatchCounts[VDM_INDEX_LOCKPrefix];
  3891. LocalInfo.OpcodeREPNEPrefix = ExVdmOpcodeDispatchCounts[VDM_INDEX_REPNEPrefix];
  3892. LocalInfo.OpcodeREPPrefix = ExVdmOpcodeDispatchCounts[VDM_INDEX_REPPrefix];
  3893. LocalInfo.OpcodeHLT = ExVdmOpcodeDispatchCounts[VDM_INDEX_HLT];
  3894. LocalInfo.OpcodeCLI = ExVdmOpcodeDispatchCounts[VDM_INDEX_CLI];
  3895. LocalInfo.OpcodeSTI = ExVdmOpcodeDispatchCounts[VDM_INDEX_STI];
  3896. LocalInfo.BopCount = VdmBopCount;
  3897. LocalInfo.SegmentNotPresent = ExVdmSegmentNotPresent;
  3898. RtlCopyMemory(Info,&LocalInfo,sizeof(LocalInfo));
  3899. return STATUS_SUCCESS;
  3900. }
  3901. #endif
  3902. #if i386
  3903. NTSTATUS
  3904. ExpGetStackTraceInformation (
  3905. OUT PVOID SystemInformation,
  3906. IN ULONG SystemInformationLength,
  3907. OUT PULONG ReturnLength OPTIONAL
  3908. )
  3909. {
  3910. NTSTATUS Status;
  3911. PRTL_PROCESS_BACKTRACES BackTraceInformation;
  3912. PRTL_PROCESS_BACKTRACE_INFORMATION BackTraceInfo;
  3913. PSTACK_TRACE_DATABASE DataBase;
  3914. PRTL_STACK_TRACE_ENTRY p, *pp;
  3915. ULONG RequiredLength, n;
  3916. DataBase = RtlpAcquireStackTraceDataBase();
  3917. if (DataBase == NULL) {
  3918. return STATUS_UNSUCCESSFUL;
  3919. }
  3920. DataBase->DumpInProgress = TRUE;
  3921. RtlpReleaseStackTraceDataBase();
  3922. n = 0;
  3923. RequiredLength = 0;
  3924. Status = STATUS_INFO_LENGTH_MISMATCH;
  3925. BackTraceInformation = (PRTL_PROCESS_BACKTRACES) SystemInformation;
  3926. RequiredLength = FIELD_OFFSET( RTL_PROCESS_BACKTRACES, BackTraces );
  3927. try {
  3928. if (SystemInformationLength >= RequiredLength) {
  3929. BackTraceInformation->CommittedMemory =
  3930. (ULONG)DataBase->CurrentUpperCommitLimit - (ULONG)DataBase->CommitBase;
  3931. BackTraceInformation->ReservedMemory =
  3932. (ULONG)DataBase->EntryIndexArray - (ULONG)DataBase->CommitBase;
  3933. BackTraceInformation->NumberOfBackTraceLookups = DataBase->NumberOfEntriesLookedUp;
  3934. n = DataBase->NumberOfEntriesAdded;
  3935. BackTraceInformation->NumberOfBackTraces = n;
  3936. }
  3937. RequiredLength += (sizeof( *BackTraceInfo ) * n);
  3938. if (SystemInformationLength >= RequiredLength) {
  3939. Status = STATUS_SUCCESS;
  3940. BackTraceInfo = &BackTraceInformation->BackTraces[ 0 ];
  3941. pp = DataBase->EntryIndexArray;
  3942. while (n--) {
  3943. p = *--pp;
  3944. BackTraceInfo->SymbolicBackTrace = NULL;
  3945. BackTraceInfo->TraceCount = p->TraceCount;
  3946. BackTraceInfo->Index = p->Index;
  3947. BackTraceInfo->Depth = p->Depth;
  3948. RtlCopyMemory( BackTraceInfo->BackTrace,
  3949. p->BackTrace,
  3950. p->Depth * sizeof( PVOID )
  3951. );
  3952. BackTraceInfo += 1;
  3953. }
  3954. }
  3955. }
  3956. finally {
  3957. DataBase->DumpInProgress = FALSE;
  3958. }
  3959. if (ARGUMENT_PRESENT(ReturnLength)) {
  3960. *ReturnLength = RequiredLength;
  3961. }
  3962. return Status;
  3963. }
  3964. #endif // i386
  3965. NTSTATUS
  3966. ExpGetLockInformation (
  3967. OUT PVOID SystemInformation,
  3968. IN ULONG SystemInformationLength,
  3969. OUT PULONG Length
  3970. )
  3971. /*++
  3972. Routine Description:
  3973. This function returns information about all the ERESOURCE locks
  3974. in the system.
  3975. Arguments:
  3976. SystemInformation - A pointer to a buffer which receives the specified
  3977. information.
  3978. SystemInformationLength - Specifies the length in bytes of the system
  3979. information buffer.
  3980. Length - An optional pointer which, if specified, receives the
  3981. number of bytes placed in the system information buffer.
  3982. Return Value:
  3983. Returns one of the following status codes:
  3984. STATUS_SUCCESS - normal, successful completion.
  3985. STATUS_INVALID_INFO_CLASS - The SystemInformationClass parameter
  3986. did not specify a valid value.
  3987. STATUS_INFO_LENGTH_MISMATCH - The value of the SystemInformationLength
  3988. parameter did not match the length required for the information
  3989. class requested by the SystemInformationClass parameter.
  3990. STATUS_ACCESS_VIOLATION - Either the SystemInformation buffer pointer
  3991. or the Length pointer value specified an invalid address.
  3992. STATUS_WORKING_SET_QUOTA - The process does not have sufficient
  3993. working set to lock the specified output structure in memory.
  3994. STATUS_INSUFFICIENT_RESOURCES - Insufficient system resources exist
  3995. for this request to complete.
  3996. --*/
  3997. {
  3998. PRTL_PROCESS_LOCKS LockInfo;
  3999. PVOID LockVariable;
  4000. NTSTATUS Status;
  4001. *Length = 0;
  4002. Status = ExLockUserBuffer( SystemInformation,
  4003. SystemInformationLength,
  4004. KeGetPreviousMode(),
  4005. IoWriteAccess,
  4006. &LockInfo,
  4007. &LockVariable
  4008. );
  4009. if (!NT_SUCCESS(Status)) {
  4010. return( Status );
  4011. }
  4012. Status = STATUS_SUCCESS;
  4013. MmLockPagableSectionByHandle (ExPageLockHandle);
  4014. try {
  4015. Status = ExQuerySystemLockInformation( LockInfo,
  4016. SystemInformationLength,
  4017. Length
  4018. );
  4019. }
  4020. finally {
  4021. ExUnlockUserBuffer( LockVariable );
  4022. MmUnlockPagableImageSection(ExPageLockHandle);
  4023. }
  4024. return Status;
  4025. }
  4026. NTSTATUS
  4027. ExpGetLookasideInformation (
  4028. OUT PVOID Buffer,
  4029. IN ULONG BufferLength,
  4030. OUT PULONG Length
  4031. )
  4032. /*++
  4033. Routine Description:
  4034. This function returns pool lookaside list and general lookaside
  4035. list information.
  4036. Arguments:
  4037. Buffer - Supplies a pointer to the buffer which receives the lookaside
  4038. list information.
  4039. BufferLength - Supplies the length of the information buffer in bytes.
  4040. Length - Supplies a pointer to a variable that receives the length of
  4041. lookaside information returned.
  4042. Environment:
  4043. Kernel mode.
  4044. This routine could be made PAGELK but it is a high frequency routine
  4045. so it is actually better to keep it nonpaged to avoid bringing in the
  4046. entire PAGELK section.
  4047. Return Value:
  4048. Returns one of the following status codes:
  4049. STATUS_SUCCESS - Normal, successful completion.
  4050. STATUS_ACCESS_VIOLATION - The buffer could not be locked in memory.
  4051. --*/
  4052. {
  4053. PVOID BufferLock;
  4054. PLIST_ENTRY Entry;
  4055. KIRQL OldIrql;
  4056. ULONG Limit;
  4057. PSYSTEM_LOOKASIDE_INFORMATION Lookaside;
  4058. ULONG Number;
  4059. PNPAGED_LOOKASIDE_LIST NPagedLookaside;
  4060. PPAGED_LOOKASIDE_LIST PagedLookaside;
  4061. PGENERAL_LOOKASIDE PoolLookaside;
  4062. PGENERAL_LOOKASIDE SystemLookaside;
  4063. PKSPIN_LOCK SpinLock;
  4064. NTSTATUS Status;
  4065. //
  4066. // Compute the number of lookaside entries and set the return status to
  4067. // success.
  4068. //
  4069. Limit = BufferLength / sizeof(SYSTEM_LOOKASIDE_INFORMATION);
  4070. Number = 0;
  4071. Status = STATUS_SUCCESS;
  4072. //
  4073. // If the number of lookaside entries to return is not zero, then collect
  4074. // the lookaside information.
  4075. //
  4076. if (Limit != 0) {
  4077. Status = ExLockUserBuffer(Buffer,
  4078. BufferLength,
  4079. KeGetPreviousMode(),
  4080. IoWriteAccess,
  4081. &Lookaside,
  4082. &BufferLock);
  4083. if (NT_SUCCESS(Status)) {
  4084. Status = STATUS_SUCCESS;
  4085. //
  4086. // Copy nonpaged and paged pool lookaside information to
  4087. // information buffer.
  4088. //
  4089. Entry = ExPoolLookasideListHead.Flink;
  4090. while (Entry != &ExPoolLookasideListHead) {
  4091. PoolLookaside = CONTAINING_RECORD(Entry,
  4092. GENERAL_LOOKASIDE,
  4093. ListEntry);
  4094. Lookaside->CurrentDepth = ExQueryDepthSList(&PoolLookaside->ListHead);
  4095. Lookaside->MaximumDepth = PoolLookaside->Depth;
  4096. Lookaside->TotalAllocates = PoolLookaside->TotalAllocates;
  4097. Lookaside->AllocateMisses =
  4098. PoolLookaside->TotalAllocates - PoolLookaside->AllocateHits;
  4099. Lookaside->TotalFrees = PoolLookaside->TotalFrees;
  4100. Lookaside->FreeMisses =
  4101. PoolLookaside->TotalFrees - PoolLookaside->FreeHits;
  4102. Lookaside->Type = PoolLookaside->Type;
  4103. Lookaside->Tag = PoolLookaside->Tag;
  4104. Lookaside->Size = PoolLookaside->Size;
  4105. Number += 1;
  4106. if (Number == Limit) {
  4107. goto Finish2;
  4108. }
  4109. Entry = Entry->Flink;
  4110. Lookaside += 1;
  4111. }
  4112. //
  4113. // Copy nonpaged and paged system lookaside information to
  4114. // information buffer.
  4115. //
  4116. Entry = ExSystemLookasideListHead.Flink;
  4117. while (Entry != &ExSystemLookasideListHead) {
  4118. SystemLookaside = CONTAINING_RECORD(Entry,
  4119. GENERAL_LOOKASIDE,
  4120. ListEntry);
  4121. Lookaside->CurrentDepth = ExQueryDepthSList(&SystemLookaside->ListHead);
  4122. Lookaside->MaximumDepth = SystemLookaside->Depth;
  4123. Lookaside->TotalAllocates = SystemLookaside->TotalAllocates;
  4124. Lookaside->AllocateMisses = SystemLookaside->AllocateMisses;
  4125. Lookaside->TotalFrees = SystemLookaside->TotalFrees;
  4126. Lookaside->FreeMisses = SystemLookaside->FreeMisses;
  4127. Lookaside->Type = SystemLookaside->Type;
  4128. Lookaside->Tag = SystemLookaside->Tag;
  4129. Lookaside->Size = SystemLookaside->Size;
  4130. Number += 1;
  4131. if (Number == Limit) {
  4132. goto Finish2;
  4133. }
  4134. Entry = Entry->Flink;
  4135. Lookaside += 1;
  4136. }
  4137. //
  4138. // Copy nonpaged general lookaside information to buffer.
  4139. //
  4140. SpinLock = &ExNPagedLookasideLock;
  4141. ExAcquireSpinLock(SpinLock, &OldIrql);
  4142. Entry = ExNPagedLookasideListHead.Flink;
  4143. while (Entry != &ExNPagedLookasideListHead) {
  4144. NPagedLookaside = CONTAINING_RECORD(Entry,
  4145. NPAGED_LOOKASIDE_LIST,
  4146. L.ListEntry);
  4147. Lookaside->CurrentDepth = ExQueryDepthSList(&NPagedLookaside->L.ListHead);
  4148. Lookaside->MaximumDepth = NPagedLookaside->L.Depth;
  4149. Lookaside->TotalAllocates = NPagedLookaside->L.TotalAllocates;
  4150. Lookaside->AllocateMisses = NPagedLookaside->L.AllocateMisses;
  4151. Lookaside->TotalFrees = NPagedLookaside->L.TotalFrees;
  4152. Lookaside->FreeMisses = NPagedLookaside->L.FreeMisses;
  4153. Lookaside->Type = 0;
  4154. Lookaside->Tag = NPagedLookaside->L.Tag;
  4155. Lookaside->Size = NPagedLookaside->L.Size;
  4156. Number += 1;
  4157. if (Number == Limit) {
  4158. goto Finish1;
  4159. }
  4160. Entry = Entry->Flink;
  4161. Lookaside += 1;
  4162. }
  4163. ExReleaseSpinLock(SpinLock, OldIrql);
  4164. //
  4165. // Copy paged general lookaside information to buffer.
  4166. //
  4167. SpinLock = &ExPagedLookasideLock;
  4168. ExAcquireSpinLock(SpinLock, &OldIrql);
  4169. Entry = ExPagedLookasideListHead.Flink;
  4170. while (Entry != &ExPagedLookasideListHead) {
  4171. PagedLookaside = CONTAINING_RECORD(Entry,
  4172. PAGED_LOOKASIDE_LIST,
  4173. L.ListEntry);
  4174. Lookaside->CurrentDepth = ExQueryDepthSList(&PagedLookaside->L.ListHead);
  4175. Lookaside->MaximumDepth = PagedLookaside->L.Depth;
  4176. Lookaside->TotalAllocates = PagedLookaside->L.TotalAllocates;
  4177. Lookaside->AllocateMisses = PagedLookaside->L.AllocateMisses;
  4178. Lookaside->TotalFrees = PagedLookaside->L.TotalFrees;
  4179. Lookaside->FreeMisses = PagedLookaside->L.FreeMisses;
  4180. Lookaside->Type = 1;
  4181. Lookaside->Tag = PagedLookaside->L.Tag;
  4182. Lookaside->Size = PagedLookaside->L.Size;
  4183. Number += 1;
  4184. if (Number == Limit) {
  4185. goto Finish1;
  4186. }
  4187. Entry = Entry->Flink;
  4188. Lookaside += 1;
  4189. }
  4190. Finish1:
  4191. ExReleaseSpinLock(SpinLock, OldIrql);
  4192. Finish2:
  4193. //
  4194. // Unlock user buffer.
  4195. //
  4196. ExUnlockUserBuffer(BufferLock);
  4197. }
  4198. }
  4199. *Length = Number * sizeof(SYSTEM_LOOKASIDE_INFORMATION);
  4200. return Status;
  4201. }
  4202. NTSTATUS
  4203. ExpGetHandleInformation(
  4204. OUT PVOID SystemInformation,
  4205. IN ULONG SystemInformationLength,
  4206. OUT PULONG Length
  4207. )
  4208. /*++
  4209. Routine Description:
  4210. This function returns information about the open handles in the system.
  4211. Arguments:
  4212. SystemInformation - A pointer to a buffer which receives the specified
  4213. information.
  4214. SystemInformationLength - Specifies the length in bytes of the system
  4215. information buffer.
  4216. Length - An optional pointer which, if specified, receives the
  4217. number of bytes placed in the system information buffer.
  4218. Return Value:
  4219. Returns one of the following status codes:
  4220. STATUS_SUCCESS - normal, successful completion.
  4221. STATUS_INVALID_INFO_CLASS - The SystemInformationClass parameter
  4222. did not specify a valid value.
  4223. STATUS_INFO_LENGTH_MISMATCH - The value of the SystemInformationLength
  4224. parameter did not match the length required for the information
  4225. class requested by the SystemInformationClass parameter.
  4226. STATUS_ACCESS_VIOLATION - Either the SystemInformation buffer pointer
  4227. or the Length pointer value specified an invalid address.
  4228. STATUS_WORKING_SET_QUOTA - The process does not have sufficient
  4229. working set to lock the specified output structure in memory.
  4230. STATUS_INSUFFICIENT_RESOURCES - Insufficient system resources exist
  4231. for this request to complete.
  4232. --*/
  4233. {
  4234. PSYSTEM_HANDLE_INFORMATION HandleInfo;
  4235. PVOID LockVariable;
  4236. NTSTATUS Status;
  4237. PAGED_CODE();
  4238. *Length = 0;
  4239. Status = ExLockUserBuffer( SystemInformation,
  4240. SystemInformationLength,
  4241. KeGetPreviousMode(),
  4242. IoWriteAccess,
  4243. &HandleInfo,
  4244. &LockVariable
  4245. );
  4246. if (!NT_SUCCESS(Status)) {
  4247. return Status;
  4248. }
  4249. Status = STATUS_SUCCESS;
  4250. try {
  4251. Status = ObGetHandleInformation( HandleInfo,
  4252. SystemInformationLength,
  4253. Length
  4254. );
  4255. }
  4256. finally {
  4257. ExUnlockUserBuffer( LockVariable );
  4258. }
  4259. return Status;
  4260. }
  4261. NTSTATUS
  4262. ExpGetHandleInformationEx(
  4263. OUT PVOID SystemInformation,
  4264. IN ULONG SystemInformationLength,
  4265. OUT PULONG Length
  4266. )
  4267. /*++
  4268. Routine Description:
  4269. This function returns information about the open handles in the system.
  4270. Arguments:
  4271. SystemInformation - A pointer to a buffer which receives the specified
  4272. information.
  4273. SystemInformationLength - Specifies the length in bytes of the system
  4274. information buffer.
  4275. Length - An optional pointer which, if specified, receives the
  4276. number of bytes placed in the system information buffer.
  4277. Return Value:
  4278. Returns one of the following status codes:
  4279. STATUS_SUCCESS - normal, successful completion.
  4280. STATUS_INVALID_INFO_CLASS - The SystemInformationClass parameter
  4281. did not specify a valid value.
  4282. STATUS_INFO_LENGTH_MISMATCH - The value of the SystemInformationLength
  4283. parameter did not match the length required for the information
  4284. class requested by the SystemInformationClass parameter.
  4285. STATUS_ACCESS_VIOLATION - Either the SystemInformation buffer pointer
  4286. or the Length pointer value specified an invalid address.
  4287. STATUS_WORKING_SET_QUOTA - The process does not have sufficient
  4288. working set to lock the specified output structure in memory.
  4289. STATUS_INSUFFICIENT_RESOURCES - Insufficient system resources exist
  4290. for this request to complete.
  4291. --*/
  4292. {
  4293. PSYSTEM_HANDLE_INFORMATION_EX HandleInfo;
  4294. PVOID LockVariable;
  4295. NTSTATUS Status;
  4296. PAGED_CODE();
  4297. *Length = 0;
  4298. Status = ExLockUserBuffer( SystemInformation,
  4299. SystemInformationLength,
  4300. KeGetPreviousMode(),
  4301. IoWriteAccess,
  4302. &HandleInfo,
  4303. &LockVariable
  4304. );
  4305. if (!NT_SUCCESS(Status)) {
  4306. return Status;
  4307. }
  4308. Status = STATUS_SUCCESS;
  4309. try {
  4310. Status = ObGetHandleInformationEx( HandleInfo,
  4311. SystemInformationLength,
  4312. Length
  4313. );
  4314. }
  4315. finally {
  4316. ExUnlockUserBuffer( LockVariable );
  4317. }
  4318. return Status;
  4319. }
  4320. NTSTATUS
  4321. ExpGetObjectInformation(
  4322. OUT PVOID SystemInformation,
  4323. IN ULONG SystemInformationLength,
  4324. OUT PULONG Length
  4325. )
  4326. /*++
  4327. Routine Description:
  4328. This function returns information about the objects in the system.
  4329. Arguments:
  4330. SystemInformation - A pointer to a buffer which receives the specified
  4331. information.
  4332. SystemInformationLength - Specifies the length in bytes of the system
  4333. information buffer.
  4334. Length - An optional pointer which, if specified, receives the
  4335. number of bytes placed in the system information buffer.
  4336. Return Value:
  4337. Returns one of the following status codes:
  4338. STATUS_SUCCESS - normal, successful completion.
  4339. STATUS_INVALID_INFO_CLASS - The SystemInformationClass parameter
  4340. did not specify a valid value.
  4341. STATUS_INFO_LENGTH_MISMATCH - The value of the SystemInformationLength
  4342. parameter did not match the length required for the information
  4343. class requested by the SystemInformationClass parameter.
  4344. STATUS_ACCESS_VIOLATION - Either the SystemInformation buffer pointer
  4345. or the Length pointer value specified an invalid address.
  4346. STATUS_WORKING_SET_QUOTA - The process does not have sufficient
  4347. working set to lock the specified output structure in memory.
  4348. STATUS_INSUFFICIENT_RESOURCES - Insufficient system resources exist
  4349. for this request to complete.
  4350. --*/
  4351. {
  4352. PSYSTEM_OBJECTTYPE_INFORMATION ObjectInfo;
  4353. PVOID LockVariable;
  4354. NTSTATUS Status;
  4355. PAGED_CODE();
  4356. *Length = 0;
  4357. Status = ExLockUserBuffer( SystemInformation,
  4358. SystemInformationLength,
  4359. KeGetPreviousMode(),
  4360. IoWriteAccess,
  4361. &ObjectInfo,
  4362. &LockVariable
  4363. );
  4364. if (!NT_SUCCESS(Status)) {
  4365. return( Status );
  4366. }
  4367. Status = STATUS_SUCCESS;
  4368. try {
  4369. Status = ObGetObjectInformation( SystemInformation,
  4370. ObjectInfo,
  4371. SystemInformationLength,
  4372. Length
  4373. );
  4374. }
  4375. finally {
  4376. ExUnlockUserBuffer( LockVariable );
  4377. }
  4378. return Status;
  4379. }
  4380. NTSTATUS
  4381. ExpQueryModuleInformation(
  4382. IN PLIST_ENTRY LoadOrderListHead,
  4383. IN PLIST_ENTRY UserModeLoadOrderListHead,
  4384. OUT PRTL_PROCESS_MODULES ModuleInformation,
  4385. IN ULONG ModuleInformationLength,
  4386. OUT PULONG ReturnLength OPTIONAL
  4387. )
  4388. {
  4389. NTSTATUS Status;
  4390. ULONG RequiredLength;
  4391. PLIST_ENTRY Next;
  4392. PRTL_PROCESS_MODULE_INFORMATION ModuleInfo;
  4393. PKLDR_DATA_TABLE_ENTRY LdrDataTableEntry;
  4394. ANSI_STRING AnsiString;
  4395. PCHAR s;
  4396. ULONG NumberOfModules;
  4397. NumberOfModules = 0;
  4398. Status = STATUS_SUCCESS;
  4399. RequiredLength = FIELD_OFFSET( RTL_PROCESS_MODULES, Modules );
  4400. ModuleInfo = &ModuleInformation->Modules[ 0 ];
  4401. Next = LoadOrderListHead->Flink;
  4402. while ( Next != LoadOrderListHead ) {
  4403. LdrDataTableEntry = CONTAINING_RECORD( Next,
  4404. KLDR_DATA_TABLE_ENTRY,
  4405. InLoadOrderLinks
  4406. );
  4407. RequiredLength += sizeof( RTL_PROCESS_MODULE_INFORMATION );
  4408. if (ModuleInformationLength < RequiredLength) {
  4409. Status = STATUS_INFO_LENGTH_MISMATCH;
  4410. }
  4411. else {
  4412. ModuleInfo->MappedBase = NULL;
  4413. ModuleInfo->ImageBase = LdrDataTableEntry->DllBase;
  4414. ModuleInfo->ImageSize = LdrDataTableEntry->SizeOfImage;
  4415. ModuleInfo->Flags = LdrDataTableEntry->Flags;
  4416. ModuleInfo->LoadCount = LdrDataTableEntry->LoadCount;
  4417. ModuleInfo->LoadOrderIndex = (USHORT)(NumberOfModules);
  4418. ModuleInfo->InitOrderIndex = 0;
  4419. AnsiString.Buffer = (PCHAR) ModuleInfo->FullPathName;
  4420. AnsiString.Length = 0;
  4421. AnsiString.MaximumLength = sizeof( ModuleInfo->FullPathName );
  4422. RtlUnicodeStringToAnsiString( &AnsiString,
  4423. &LdrDataTableEntry->FullDllName,
  4424. FALSE
  4425. );
  4426. s = AnsiString.Buffer + AnsiString.Length;
  4427. while (s > AnsiString.Buffer && *--s) {
  4428. if (*s == (UCHAR)OBJ_NAME_PATH_SEPARATOR) {
  4429. s += 1;
  4430. break;
  4431. }
  4432. }
  4433. ModuleInfo->OffsetToFileName = (USHORT)(s - AnsiString.Buffer);
  4434. ModuleInfo += 1;
  4435. }
  4436. NumberOfModules += 1;
  4437. Next = Next->Flink;
  4438. }
  4439. if (ARGUMENT_PRESENT( UserModeLoadOrderListHead )) {
  4440. Next = UserModeLoadOrderListHead->Flink;
  4441. while ( Next != UserModeLoadOrderListHead ) {
  4442. LdrDataTableEntry = CONTAINING_RECORD( Next,
  4443. KLDR_DATA_TABLE_ENTRY,
  4444. InLoadOrderLinks
  4445. );
  4446. RequiredLength += sizeof( RTL_PROCESS_MODULE_INFORMATION );
  4447. if (ModuleInformationLength < RequiredLength) {
  4448. Status = STATUS_INFO_LENGTH_MISMATCH;
  4449. }
  4450. else {
  4451. ModuleInfo->MappedBase = NULL;
  4452. ModuleInfo->ImageBase = LdrDataTableEntry->DllBase;
  4453. ModuleInfo->ImageSize = LdrDataTableEntry->SizeOfImage;
  4454. ModuleInfo->Flags = LdrDataTableEntry->Flags;
  4455. ModuleInfo->LoadCount = LdrDataTableEntry->LoadCount;
  4456. ModuleInfo->LoadOrderIndex = (USHORT)(NumberOfModules);
  4457. ModuleInfo->InitOrderIndex = ModuleInfo->LoadOrderIndex;
  4458. AnsiString.Buffer = (PCHAR) ModuleInfo->FullPathName;
  4459. AnsiString.Length = 0;
  4460. AnsiString.MaximumLength = sizeof( ModuleInfo->FullPathName );
  4461. RtlUnicodeStringToAnsiString( &AnsiString,
  4462. &LdrDataTableEntry->FullDllName,
  4463. FALSE
  4464. );
  4465. s = AnsiString.Buffer + AnsiString.Length;
  4466. while (s > AnsiString.Buffer && *--s) {
  4467. if (*s == (UCHAR)OBJ_NAME_PATH_SEPARATOR) {
  4468. s += 1;
  4469. break;
  4470. }
  4471. }
  4472. ModuleInfo->OffsetToFileName = (USHORT)(s - AnsiString.Buffer);
  4473. ModuleInfo += 1;
  4474. }
  4475. NumberOfModules += 1;
  4476. Next = Next->Flink;
  4477. }
  4478. }
  4479. if (ARGUMENT_PRESENT(ReturnLength)) {
  4480. *ReturnLength = RequiredLength;
  4481. }
  4482. if (ModuleInformationLength >= FIELD_OFFSET( RTL_PROCESS_MODULES, Modules )) {
  4483. ModuleInformation->NumberOfModules = NumberOfModules;
  4484. } else {
  4485. Status = STATUS_INFO_LENGTH_MISMATCH;
  4486. }
  4487. return Status;
  4488. }
  4489. BOOLEAN
  4490. ExIsProcessorFeaturePresent(
  4491. ULONG ProcessorFeature
  4492. )
  4493. {
  4494. BOOLEAN rv;
  4495. if ( ProcessorFeature < PROCESSOR_FEATURE_MAX ) {
  4496. rv = SharedUserData->ProcessorFeatures[ProcessorFeature];
  4497. }
  4498. else {
  4499. rv = FALSE;
  4500. }
  4501. return rv;
  4502. }
  4503. NTSTATUS
  4504. ExpQueryLegacyDriverInformation(
  4505. IN PSYSTEM_LEGACY_DRIVER_INFORMATION LegacyInfo,
  4506. IN PULONG Length
  4507. )
  4508. /*++
  4509. Routine Description:
  4510. Returns legacy driver information for figuring out why PNP/Power functionality
  4511. is disabled.
  4512. Arguments:
  4513. LegacyInfo - Returns the legacy driver information
  4514. Length - Supplies the length of the LegacyInfo buffer
  4515. Returns the amount of data written
  4516. Return Value:
  4517. NTSTATUS
  4518. --*/
  4519. {
  4520. PNP_VETO_TYPE VetoType;
  4521. PWSTR VetoList = NULL;
  4522. NTSTATUS Status;
  4523. UNICODE_STRING String;
  4524. ULONG ReturnLength;
  4525. Status = IoGetLegacyVetoList(&VetoList, &VetoType);
  4526. if (!NT_SUCCESS(Status)) {
  4527. return(Status);
  4528. }
  4529. RtlInitUnicodeString(&String, VetoList);
  4530. ReturnLength = sizeof(SYSTEM_LEGACY_DRIVER_INFORMATION) + String.Length;
  4531. try {
  4532. if (ReturnLength > *Length) {
  4533. Status = STATUS_BUFFER_OVERFLOW;
  4534. } else {
  4535. LegacyInfo->VetoType = VetoType;
  4536. LegacyInfo->VetoList.Length = String.Length;
  4537. LegacyInfo->VetoList.Buffer = (PWSTR)(LegacyInfo+1);
  4538. RtlCopyMemory(LegacyInfo+1, String.Buffer, String.Length);
  4539. }
  4540. } finally {
  4541. if (VetoList) {
  4542. ExFreePool(VetoList);
  4543. }
  4544. }
  4545. *Length = ReturnLength;
  4546. return(Status);
  4547. }
  4548. VOID
  4549. ExGetCurrentProcessorCpuUsage(
  4550. OUT PULONG CpuUsage
  4551. )
  4552. /*++
  4553. Routine Description:
  4554. Returns an estimation of current cpu usage in percent.
  4555. Arguments:
  4556. CpuUsage - Returns the current cpu usage in percent.
  4557. Return Value:
  4558. Nothing
  4559. --*/
  4560. {
  4561. PKPRCB Prcb;
  4562. Prcb = KeGetCurrentPrcb();
  4563. *CpuUsage = 100 - (ULONG)(UInt32x32To64(Prcb->IdleThread->KernelTime, 100) /
  4564. (ULONGLONG)(Prcb->KernelTime + Prcb->UserTime));
  4565. }
  4566. VOID
  4567. ExGetCurrentProcessorCounts(
  4568. OUT PULONG IdleCount,
  4569. OUT PULONG KernelAndUser,
  4570. OUT PULONG Index
  4571. )
  4572. /*++
  4573. Routine Description:
  4574. Returns information regarding idle time and kernel + user time for
  4575. the current processor.
  4576. Arguments:
  4577. IdleCount - Returns the kernel time of the idle thread on the current
  4578. processor.
  4579. KernelAndUser - Returns the kernel pluse user on the current processor.
  4580. Index - Returns the number identifiying the current processor.
  4581. Return Value:
  4582. Nothing
  4583. --*/
  4584. {
  4585. PKPRCB Prcb;
  4586. Prcb = KeGetCurrentPrcb();
  4587. *IdleCount = Prcb->IdleThread->KernelTime;
  4588. *KernelAndUser = Prcb->KernelTime + Prcb->UserTime;
  4589. *Index = (ULONG)Prcb->Number;
  4590. }
  4591. BOOLEAN
  4592. ExpIsValidUILanguage(
  4593. IN WCHAR * pLangId
  4594. )
  4595. /*++
  4596. Routine Description:
  4597. Check if specified language ID is valid.
  4598. Arguments:
  4599. pLangId - language ID hex string.
  4600. Return Value:
  4601. TRUE: Valid
  4602. FALSE: Invalid
  4603. --*/
  4604. {
  4605. NTSTATUS Status;
  4606. UNICODE_STRING KeyPath, KeyValueName;
  4607. HANDLE hKey;
  4608. WCHAR KeyValueBuffer[ 128 ];
  4609. PKEY_VALUE_PARTIAL_INFORMATION KeyValueInformation;
  4610. OBJECT_ATTRIBUTES ObjectAttributes;
  4611. ULONG ResultLength;
  4612. BOOLEAN bRet = FALSE;
  4613. int iLen = 0;
  4614. RtlInitUnicodeString(&KeyPath, L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Nls\\MUILanguages");
  4615. //
  4616. // pLangId is passed in as DWORD or WORD hex string
  4617. // LangId string in MUILanguages is set as WORD hex string
  4618. //
  4619. while (pLangId[iLen])
  4620. {
  4621. iLen++;
  4622. }
  4623. //
  4624. // We need to validate both 4 digits and 8 digits LangId
  4625. //
  4626. RtlInitUnicodeString(&KeyValueName, iLen < 8? pLangId : &pLangId[4]);
  4627. InitializeObjectAttributes (&ObjectAttributes,
  4628. &KeyPath,
  4629. OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
  4630. NULL,
  4631. NULL);
  4632. if (NT_SUCCESS(ZwOpenKey( &hKey, GENERIC_READ, &ObjectAttributes)))
  4633. {
  4634. KeyValueInformation = (PKEY_VALUE_PARTIAL_INFORMATION)KeyValueBuffer;
  4635. Status = ZwQueryValueKey( hKey,
  4636. &KeyValueName,
  4637. KeyValuePartialInformation,
  4638. KeyValueInformation,
  4639. sizeof( KeyValueBuffer ),
  4640. &ResultLength
  4641. );
  4642. if (NT_SUCCESS(Status))
  4643. {
  4644. if (KeyValueInformation->Type == REG_SZ && *((PWSTR)(KeyValueInformation->Data)) == L'1')
  4645. {
  4646. bRet = TRUE;
  4647. }
  4648. }
  4649. ZwClose(hKey);
  4650. }
  4651. return bRet;
  4652. }