Source code of Windows XP (NT5)
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.

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