Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

sysinfo.c

Go to the documentation of this file.
00001 /*++ 00002 00003 Copyright (c) 1989 Microsoft Corporation 00004 00005 Module Name: 00006 00007 sysinfo.c 00008 00009 Abstract: 00010 00011 This module implements the NT set and query system information services. 00012 00013 Author: 00014 00015 Steve Wood (stevewo) 21-Aug-1989 00016 00017 Environment: 00018 00019 Kernel mode only. 00020 00021 Revision History: 00022 00023 --*/ 00024 00025 #include "exp.h" 00026 #pragma hdrstop 00027 00028 #include "stdlib.h" 00029 #include "string.h" 00030 #include "vdmntos.h" 00031 #include <nturtl.h> 00032 #include "pool.h" 00033 #include "stktrace.h" 00034 #include "align.h" 00035 #include "..\..\..\inc\alpha.h" 00036 00037 extern PVOID PspCidTable; // BUGBUG - Copied from ps\psp.h 00038 00039 extern ULONG MmAvailablePages; 00040 extern ULONG MmTotalCommittedPages; 00041 extern ULONG MmTotalCommitLimit; 00042 extern ULONG MmPeakCommitment; 00043 extern ULONG MmLowestPhysicalPage; 00044 extern ULONG MmHighestPhysicalPage; 00045 extern ULONG MmTotalFreeSystemPtes[1]; 00046 extern ULONG MmSystemCodePage; 00047 extern ULONG MmSystemCachePage; 00048 extern ULONG MmPagedPoolPage; 00049 extern ULONG MmSystemDriverPage; 00050 extern ULONG MmTotalSystemCodePages; 00051 extern ULONG MmTotalSystemDriverPages; 00052 extern RTL_TIME_ZONE_INFORMATION ExpTimeZoneInformation; 00053 00054 // 00055 // For SystemDpcBehaviorInformation 00056 // 00057 extern ULONG KiMaximumDpcQueueDepth; 00058 extern ULONG KiMinimumDpcRate; 00059 extern ULONG KiAdjustDpcThreshold; 00060 extern ULONG KiIdealDpcRate; 00061 00062 extern LIST_ENTRY MmLoadedUserImageList; 00063 00064 extern MMSUPPORT MmSystemCacheWs; 00065 extern ULONG MmTransitionSharedPages; 00066 extern ULONG MmTransitionSharedPagesPeak; 00067 00068 #define ROUND_UP(VALUE,ROUND) ((ULONG)(((ULONG)VALUE + \ 00069 ((ULONG)ROUND - 1L)) & (~((ULONG)ROUND - 1L)))) 00070 00071 // 00072 // For referencing a user-supplied event handle 00073 // 00074 extern POBJECT_TYPE ExEventObjectType; 00075 00076 00077 NTSTATUS 00078 ExpValidateLocale( 00079 IN LCID LocaleId 00080 ); 00081 00082 NTSTATUS 00083 ExpGetCurrentUserUILanguage( 00084 IN WCHAR *ValueName, 00085 OUT LANGID *CurrentUserUILanguageId 00086 ); 00087 00088 NTSTATUS 00089 ExpSetCurrentUserUILanguage( 00090 IN WCHAR *ValueName, 00091 IN LANGID DefaultUILanguageId 00092 ); 00093 00094 NTSTATUS 00095 ExpGetUILanguagePolicy( 00096 IN HANDLE CurrentUserKey, 00097 OUT LANGID *PolicyUILanguageId 00098 ); 00099 00100 NTSTATUS 00101 ExpGetProcessInformation ( 00102 OUT PVOID SystemInformation, 00103 IN ULONG SystemInformationLength, 00104 OUT PULONG Length, 00105 IN PULONG SessionId OPTIONAL 00106 ); 00107 00108 VOID 00109 ExpCopyProcessInfo ( 00110 IN PSYSTEM_PROCESS_INFORMATION ProcessInfo, 00111 IN PEPROCESS Process 00112 ); 00113 00114 VOID 00115 ExpCopyThreadInfo ( 00116 IN PSYSTEM_THREAD_INFORMATION ThreadInfo, 00117 IN PETHREAD Thread 00118 ); 00119 00120 #if i386 && !FPO 00121 NTSTATUS 00122 ExpGetStackTraceInformation ( 00123 OUT PVOID SystemInformation, 00124 IN ULONG SystemInformationLength, 00125 OUT PULONG Length 00126 ); 00127 #endif // i386 && !FPO 00128 00129 NTSTATUS 00130 ExpGetLockInformation ( 00131 OUT PVOID SystemInformation, 00132 IN ULONG SystemInformationLength, 00133 OUT PULONG Length 00134 ); 00135 00136 NTSTATUS 00137 ExpGetLookasideInformation ( 00138 OUT PVOID Buffer, 00139 IN ULONG BufferLength, 00140 OUT PULONG Length 00141 ); 00142 00143 NTSTATUS 00144 ExpGetPoolInformation( 00145 IN POOL_TYPE PoolType, 00146 OUT PVOID SystemInformation, 00147 IN ULONG SystemInformationLength, 00148 OUT PULONG Length 00149 ); 00150 00151 NTSTATUS 00152 ExpGetHandleInformation( 00153 OUT PVOID SystemInformation, 00154 IN ULONG SystemInformationLength, 00155 OUT PULONG Length 00156 ); 00157 00158 NTSTATUS 00159 ExpGetObjectInformation( 00160 OUT PVOID SystemInformation, 00161 IN ULONG SystemInformationLength, 00162 OUT PULONG Length 00163 ); 00164 00165 00166 NTSTATUS 00167 ExpGetInstemulInformation( 00168 OUT PSYSTEM_VDM_INSTEMUL_INFO Info 00169 ); 00170 00171 NTSTATUS 00172 ExpGetPoolTagInfo ( 00173 IN PVOID SystemInformation, 00174 IN ULONG SystemInformationLength, 00175 IN OUT PULONG ReturnLength OPTIONAL 00176 ); 00177 00178 NTSTATUS 00179 ExpQueryModuleInformation( 00180 IN PLIST_ENTRY LoadOrderListHead, 00181 IN PLIST_ENTRY UserModeLoadOrderListHead, 00182 OUT PRTL_PROCESS_MODULES ModuleInformation, 00183 IN ULONG ModuleInformationLength, 00184 OUT PULONG ReturnLength OPTIONAL 00185 ); 00186 00187 NTSTATUS 00188 ExpQueryLegacyDriverInformation( 00189 IN PSYSTEM_LEGACY_DRIVER_INFORMATION LegacyInfo, 00190 IN PULONG Length 00191 ); 00192 00193 #if defined(ALLOC_PRAGMA) 00194 #pragma alloc_text(PAGE, NtQueryDefaultLocale) 00195 #pragma alloc_text(PAGE, NtSetDefaultLocale) 00196 #pragma alloc_text(PAGE, NtQueryInstallUILanguage) 00197 #pragma alloc_text(PAGE, NtQueryDefaultUILanguage) 00198 #pragma alloc_text(PAGE, ExpGetCurrentUserUILanguage) 00199 #pragma alloc_text(PAGE, NtSetDefaultUILanguage) 00200 #pragma alloc_text(PAGE, ExpSetCurrentUserUILanguage) 00201 #pragma alloc_text(PAGE, ExpValidateLocale) 00202 #pragma alloc_text(PAGE, ExpGetUILanguagePolicy) 00203 #pragma alloc_text(PAGE, NtQuerySystemInformation) 00204 #pragma alloc_text(PAGE, NtSetSystemInformation) 00205 #pragma alloc_text(PAGE, ExpGetHandleInformation) 00206 #pragma alloc_text(PAGE, ExpGetObjectInformation) 00207 #pragma alloc_text(PAGE, ExpQueryModuleInformation) 00208 #pragma alloc_text(PAGE, ExpCopyProcessInfo) 00209 #pragma alloc_text(PAGE, ExpQueryLegacyDriverInformation) 00210 #pragma alloc_text(PAGELK, ExpGetProcessInformation) 00211 #pragma alloc_text(PAGELK, ExpCopyThreadInfo) 00212 #pragma alloc_text(PAGELK, ExpGetLockInformation) 00213 #pragma alloc_text(PAGELK, ExpGetLookasideInformation) 00214 #pragma alloc_text(PAGELK, ExpGetPoolInformation) 00215 #endif 00216 00217 00218 00219 NTSTATUS 00220 NtQueryDefaultLocale( 00221 IN BOOLEAN UserProfile, 00222 OUT PLCID DefaultLocaleId 00223 ) 00224 { 00225 KPROCESSOR_MODE PreviousMode; 00226 NTSTATUS Status; 00227 00228 PAGED_CODE(); 00229 00230 Status = STATUS_SUCCESS; 00231 try { 00232 00233 // 00234 // Get previous processor mode and probe output argument if necessary. 00235 // 00236 00237 PreviousMode = KeGetPreviousMode(); 00238 if (PreviousMode != KernelMode) { 00239 ProbeForWriteUlong( (PULONG)DefaultLocaleId ); 00240 } 00241 00242 if (UserProfile) { 00243 *DefaultLocaleId = PsDefaultThreadLocaleId; 00244 } 00245 else { 00246 *DefaultLocaleId = PsDefaultSystemLocaleId; 00247 } 00248 } 00249 except (EXCEPTION_EXECUTE_HANDLER) { 00250 Status = GetExceptionCode(); 00251 } 00252 00253 return Status; 00254 } 00255 00256 00257 NTSTATUS 00258 NtSetDefaultLocale( 00259 IN BOOLEAN UserProfile, 00260 IN LCID DefaultLocaleId 00261 ) 00262 { 00263 NTSTATUS Status; 00264 OBJECT_ATTRIBUTES ObjectAttributes; 00265 UNICODE_STRING KeyPath, KeyValueName; 00266 HANDLE CurrentUserKey, Key; 00267 WCHAR KeyValueBuffer[ 128 ]; 00268 PKEY_VALUE_PARTIAL_INFORMATION KeyValueInformation; 00269 ULONG ResultLength; 00270 PWSTR s; 00271 ULONG n, i, Digit; 00272 WCHAR c; 00273 00274 PAGED_CODE(); 00275 00276 if (DefaultLocaleId & 0xFFFF0000) { 00277 return STATUS_INVALID_PARAMETER; 00278 } 00279 00280 KeyValueInformation = (PKEY_VALUE_PARTIAL_INFORMATION)KeyValueBuffer; 00281 if (UserProfile) { 00282 Status = RtlOpenCurrentUser( MAXIMUM_ALLOWED, &CurrentUserKey ); 00283 if (!NT_SUCCESS( Status )) { 00284 return Status; 00285 } 00286 00287 RtlInitUnicodeString( &KeyValueName, L"Locale" ); 00288 RtlInitUnicodeString( &KeyPath, L"Control Panel\\International" ); 00289 } 00290 else { 00291 RtlInitUnicodeString( &KeyValueName, L"Default" ); 00292 RtlInitUnicodeString( &KeyPath, L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Nls\\Language" ); 00293 CurrentUserKey = NULL; 00294 } 00295 00296 InitializeObjectAttributes( &ObjectAttributes, 00297 &KeyPath, 00298 (OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE), 00299 CurrentUserKey, 00300 NULL 00301 ); 00302 if (DefaultLocaleId == 0) { 00303 Status = ZwOpenKey( &Key, 00304 GENERIC_READ, 00305 &ObjectAttributes 00306 ); 00307 if (NT_SUCCESS( Status )) { 00308 Status = ZwQueryValueKey( Key, 00309 &KeyValueName, 00310 KeyValuePartialInformation, 00311 KeyValueInformation, 00312 sizeof( KeyValueBuffer ), 00313 &ResultLength 00314 ); 00315 if (NT_SUCCESS( Status )) { 00316 if (KeyValueInformation->Type == REG_SZ) { 00317 s = (PWSTR)KeyValueInformation->Data; 00318 for (i=0; i<KeyValueInformation->DataLength; i += sizeof( WCHAR )) { 00319 c = *s++; 00320 if (c >= L'0' && c <= L'9') { 00321 Digit = c - L'0'; 00322 } 00323 else 00324 if (c >= L'A' && c <= L'F') { 00325 Digit = c - L'A' + 10; 00326 } 00327 else 00328 if (c >= L'a' && c <= L'f') { 00329 Digit = c - L'a' + 10; 00330 } 00331 else { 00332 break; 00333 } 00334 00335 if (Digit >= 16) { 00336 break; 00337 } 00338 00339 DefaultLocaleId = (DefaultLocaleId << 4) | Digit; 00340 } 00341 } 00342 else 00343 if (KeyValueInformation->Type == REG_DWORD && 00344 KeyValueInformation->DataLength == sizeof( ULONG ) 00345 ) { 00346 DefaultLocaleId = *(PLCID)KeyValueInformation->Data; 00347 } 00348 else { 00349 Status = STATUS_UNSUCCESSFUL; 00350 } 00351 } 00352 00353 ZwClose( Key ); 00354 } 00355 } 00356 else { 00357 00358 Status = ExpValidateLocale( DefaultLocaleId ); 00359 00360 if (NT_SUCCESS(Status)) { 00361 00362 Status = ZwOpenKey( &Key, 00363 GENERIC_WRITE, 00364 &ObjectAttributes 00365 ); 00366 00367 if (NT_SUCCESS( Status )) { 00368 if (UserProfile) { 00369 n = 8; 00370 } 00371 else { 00372 n = 4; 00373 } 00374 s = &KeyValueBuffer[ n ]; 00375 *s-- = UNICODE_NULL; 00376 i = (ULONG)DefaultLocaleId; 00377 while (s >= KeyValueBuffer) { 00378 Digit = i & 0x0000000F; 00379 if (Digit <= 9) { 00380 *s-- = (WCHAR)(Digit + L'0'); 00381 } 00382 else { 00383 *s-- = (WCHAR)((Digit - 10) + L'A'); 00384 } 00385 00386 i = i >> 4; 00387 } 00388 00389 Status = ZwSetValueKey( Key, 00390 &KeyValueName, 00391 0, 00392 REG_SZ, 00393 KeyValueBuffer, 00394 (n+1) * sizeof( WCHAR ) 00395 ); 00396 ZwClose( Key ); 00397 } 00398 } 00399 } 00400 00401 ZwClose( CurrentUserKey ); 00402 00403 if (NT_SUCCESS( Status )) { 00404 if (UserProfile) { 00405 PsDefaultThreadLocaleId = DefaultLocaleId; 00406 } 00407 else { 00408 PsDefaultSystemLocaleId = DefaultLocaleId; 00409 } 00410 } 00411 00412 return Status; 00413 } 00414 00415 NTSTATUS 00416 NtQueryInstallUILanguage( 00417 OUT LANGID *InstallUILanguageId 00418 ) 00419 { 00420 KPROCESSOR_MODE PreviousMode; 00421 NTSTATUS Status; 00422 00423 PAGED_CODE(); 00424 00425 Status = STATUS_SUCCESS; 00426 try { 00427 00428 // 00429 // Get previous processor mode and probe output argument if necessary. 00430 // 00431 00432 PreviousMode = KeGetPreviousMode(); 00433 if (PreviousMode != KernelMode) { 00434 ProbeForWriteUshort( (USHORT *)InstallUILanguageId ); 00435 } 00436 00437 *InstallUILanguageId = PsInstallUILanguageId; 00438 } 00439 except (EXCEPTION_EXECUTE_HANDLER) { 00440 Status = GetExceptionCode(); 00441 } 00442 00443 return Status; 00444 } 00445 00446 NTSTATUS 00447 NtQueryDefaultUILanguage( 00448 OUT LANGID *DefaultUILanguageId 00449 ) 00450 { 00451 KPROCESSOR_MODE PreviousMode; 00452 NTSTATUS Status; 00453 00454 PAGED_CODE(); 00455 00456 Status = STATUS_SUCCESS; 00457 try { 00458 00459 // 00460 // Get previous processor mode and probe output argument if necessary. 00461 // 00462 00463 PreviousMode = KeGetPreviousMode(); 00464 if (PreviousMode != KernelMode) { 00465 ProbeForWriteUshort( (USHORT *)DefaultUILanguageId ); 00466 } 00467 00468 // 00469 // Read the UI language from the current security context. 00470 // 00471 if (!NT_SUCCESS(ExpGetCurrentUserUILanguage( L"MultiUILanguageId", 00472 DefaultUILanguageId))) { 00473 *DefaultUILanguageId = PsInstallUILanguageId; 00474 } 00475 } 00476 except (EXCEPTION_EXECUTE_HANDLER) { 00477 Status = GetExceptionCode(); 00478 } 00479 00480 return Status; 00481 } 00482 00483 00484 00485 NTSTATUS 00486 ExpGetUILanguagePolicy( 00487 IN HANDLE CurrentUserKey, 00488 OUT LANGID *PolicyUILanguageId 00489 ) 00490 { 00491 NTSTATUS Status; 00492 OBJECT_ATTRIBUTES ObjectAttributes, MuiObjectAttributes; 00493 UNICODE_STRING KeyPath, KeyValueName, MuiLanguagesKeyPath; 00494 HANDLE Key, KeyMui; 00495 WCHAR KeyValueBuffer[ 128 ]; 00496 PKEY_VALUE_PARTIAL_INFORMATION KeyValueInformation; 00497 ULONG ResultLength; 00498 ULONG Language; 00499 00500 PAGED_CODE(); 00501 00502 00503 // 00504 // Let's verify that this is an MUI system first 00505 // 00506 RtlInitUnicodeString( &MuiLanguagesKeyPath, 00507 L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Nls\\MUILanguages" ); 00508 InitializeObjectAttributes( &MuiObjectAttributes, 00509 &MuiLanguagesKeyPath, 00510 (OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE), 00511 NULL, 00512 NULL 00513 ); 00514 00515 Status = ZwOpenKey( &KeyMui, 00516 GENERIC_READ, 00517 &MuiObjectAttributes 00518 ); 00519 if (!NT_SUCCESS( Status )) { 00520 return Status; 00521 } 00522 00523 ZwClose( KeyMui ); 00524 00525 00526 00527 KeyValueInformation = (PKEY_VALUE_PARTIAL_INFORMATION)KeyValueBuffer; 00528 RtlInitUnicodeString( &KeyValueName, L"MultiUILanguageId" ); 00529 RtlInitUnicodeString( &KeyPath, L"Software\\Policies\\Microsoft\\Control Panel\\Desktop" ); 00530 00531 InitializeObjectAttributes( &ObjectAttributes, 00532 &KeyPath, 00533 (OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE), 00534 CurrentUserKey, 00535 NULL 00536 ); 00537 00538 // 00539 // Check if there is a Policy key 00540 // 00541 Status = ZwOpenKey( &Key, 00542 GENERIC_READ, 00543 &ObjectAttributes 00544 ); 00545 00546 if (NT_SUCCESS( Status )) { 00547 00548 Status = ZwQueryValueKey( Key, 00549 &KeyValueName, 00550 KeyValuePartialInformation, 00551 KeyValueInformation, 00552 sizeof( KeyValueBuffer ), 00553 &ResultLength 00554 ); 00555 00556 if (NT_SUCCESS( Status )) { 00557 if ((KeyValueInformation->DataLength > 2) && 00558 (KeyValueInformation->Type == REG_SZ)) { 00559 00560 RtlInitUnicodeString( &KeyValueName, (PWSTR) KeyValueInformation->Data ); 00561 Status = RtlUnicodeStringToInteger( &KeyValueName, 00562 (ULONG)16, 00563 &Language 00564 ); 00565 // 00566 // Final check to make sure this is an MUI system 00567 // 00568 if (NT_SUCCESS( Status )) { 00569 *PolicyUILanguageId = (LANGID)Language; 00570 } 00571 } 00572 else { 00573 Status = STATUS_UNSUCCESSFUL; 00574 } 00575 } 00576 ZwClose( Key ); 00577 } 00578 00579 return Status; 00580 } 00581 00582 00583 00584 NTSTATUS 00585 ExpSetCurrentUserUILanguage( 00586 IN WCHAR *ValueName, 00587 IN LANGID CurrentUserUILanguage 00588 ) 00589 { 00590 NTSTATUS Status; 00591 OBJECT_ATTRIBUTES ObjectAttributes; 00592 UNICODE_STRING KeyPath, KeyValueName, UILanguage; 00593 HANDLE CurrentUserKey, Key; 00594 WCHAR KeyValueBuffer[ 128 ]; 00595 PKEY_VALUE_PARTIAL_INFORMATION KeyValueInformation; 00596 PWSTR s; 00597 ULONG i, Digit; 00598 WCHAR c; 00599 00600 PAGED_CODE(); 00601 00602 if (CurrentUserUILanguage & 0xFFFF0000) { 00603 return STATUS_INVALID_PARAMETER; 00604 } 00605 00606 KeyValueInformation = (PKEY_VALUE_PARTIAL_INFORMATION)KeyValueBuffer; 00607 Status = RtlOpenCurrentUser( MAXIMUM_ALLOWED, &CurrentUserKey ); 00608 if (!NT_SUCCESS( Status )) { 00609 return Status; 00610 } 00611 00612 RtlInitUnicodeString( &KeyValueName, ValueName ); 00613 RtlInitUnicodeString( &KeyPath, L"Control Panel\\Desktop" ); 00614 InitializeObjectAttributes( &ObjectAttributes, 00615 &KeyPath, 00616 (OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE), 00617 CurrentUserKey, 00618 NULL 00619 ); 00620 00621 00622 Status = ExpValidateLocale( MAKELCID( CurrentUserUILanguage, SORT_DEFAULT ) ); 00623 00624 if (NT_SUCCESS(Status)) { 00625 00626 Status = ZwOpenKey( &Key, 00627 GENERIC_WRITE, 00628 &ObjectAttributes 00629 ); 00630 if (NT_SUCCESS( Status )) { 00631 00632 s = &KeyValueBuffer[ 8 ]; 00633 *s-- = UNICODE_NULL; 00634 i = (ULONG)CurrentUserUILanguage; 00635 00636 while (s >= KeyValueBuffer) { 00637 Digit = i & 0x0000000F; 00638 if (Digit <= 9) { 00639 *s-- = (WCHAR)(Digit + L'0'); 00640 } 00641 else { 00642 *s-- = (WCHAR)((Digit - 10) + L'A'); 00643 } 00644 00645 i = i >> 4; 00646 } 00647 00648 Status = ZwSetValueKey( Key, 00649 &KeyValueName, 00650 0, 00651 REG_SZ, 00652 KeyValueBuffer, 00653 9 * sizeof( WCHAR ) 00654 ); 00655 ZwClose( Key ); 00656 } 00657 } 00658 00659 ZwClose( CurrentUserKey ); 00660 00661 return Status; 00662 } 00663 00664 00665 NTSTATUS 00666 ExpGetCurrentUserUILanguage( 00667 IN WCHAR *ValueName, 00668 OUT LANGID *CurrentUserUILanguageId 00669 ) 00670 { 00671 NTSTATUS Status; 00672 OBJECT_ATTRIBUTES ObjectAttributes; 00673 UNICODE_STRING KeyPath, KeyValueName, UILanguage; 00674 HANDLE CurrentUserKey, Key; 00675 WCHAR KeyValueBuffer[ 128 ]; 00676 PKEY_VALUE_PARTIAL_INFORMATION KeyValueInformation; 00677 ULONG ResultLength; 00678 ULONG Digit; 00679 00680 PAGED_CODE(); 00681 00682 KeyValueInformation = (PKEY_VALUE_PARTIAL_INFORMATION)KeyValueBuffer; 00683 Status = RtlOpenCurrentUser( MAXIMUM_ALLOWED, &CurrentUserKey ); 00684 if (!NT_SUCCESS( Status )) { 00685 return Status; 00686 } 00687 00688 RtlInitUnicodeString( &KeyValueName, ValueName ); 00689 RtlInitUnicodeString( &KeyPath, L"Control Panel\\Desktop" ); 00690 InitializeObjectAttributes( &ObjectAttributes, 00691 &KeyPath, 00692 (OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE), 00693 CurrentUserKey, 00694 NULL 00695 ); 00696 00697 // 00698 // Let's check if there is a policy installed for the UI language, 00699 // and if so, let's use it. 00700 // 00701 if (!NT_SUCCESS( ExpGetUILanguagePolicy( CurrentUserKey, CurrentUserUILanguageId ))) { 00702 Status = ZwOpenKey( &Key, 00703 GENERIC_READ, 00704 &ObjectAttributes 00705 ); 00706 if (NT_SUCCESS( Status )) { 00707 Status = ZwQueryValueKey( Key, 00708 &KeyValueName, 00709 KeyValuePartialInformation, 00710 KeyValueInformation, 00711 sizeof( KeyValueBuffer ), 00712 &ResultLength 00713 ); 00714 if (NT_SUCCESS( Status )) { 00715 if (KeyValueInformation->Type == REG_SZ) { 00716 00717 RtlInitUnicodeString( &UILanguage, (PWSTR) KeyValueInformation->Data); 00718 Status = RtlUnicodeStringToInteger( &UILanguage, 00719 (ULONG) 16, 00720 &Digit 00721 ); 00722 if (NT_SUCCESS( Status )) { 00723 *CurrentUserUILanguageId = (LANGID) Digit; 00724 } 00725 } 00726 else { 00727 Status = STATUS_UNSUCCESSFUL; 00728 } 00729 } 00730 ZwClose( Key ); 00731 } 00732 } 00733 00734 ZwClose( CurrentUserKey ); 00735 00736 return Status; 00737 } 00738 00739 00740 NTSTATUS 00741 NtSetDefaultUILanguage( 00742 IN LANGID DefaultUILanguageId 00743 ) 00744 { 00745 NTSTATUS Status; 00746 LANGID LangId; 00747 00748 // 00749 // if this is called during user logon, then we need to update the user's registry. 00750 // 00751 if (DefaultUILanguageId == 0) { 00752 00753 Status = ExpGetCurrentUserUILanguage( L"MUILanguagePending" , 00754 &LangId 00755 ); 00756 if (NT_SUCCESS( Status )) { 00757 Status = ExpSetCurrentUserUILanguage( L"MultiUILanguageId" , 00758 LangId 00759 ); 00760 } 00761 00762 return Status; 00763 } 00764 00765 return ExpSetCurrentUserUILanguage( L"MUILanguagePending", DefaultUILanguageId ); 00766 } 00767 00768 NTSTATUS 00769 ExpValidateLocale( 00770 IN LCID LocaleId 00771 ) 00772 { 00773 NTSTATUS Status = STATUS_INVALID_PARAMETER, ReturnStatus; 00774 UNICODE_STRING LocaleName, KeyValueName; 00775 UNICODE_STRING NlsLocaleKeyPath, NlsSortKeyPath, NlsLangGroupKeyPath; 00776 WCHAR LocaleNameBuffer[ 32 ]; 00777 WCHAR KeyValueNameBuffer[ 32 ]; 00778 WCHAR KeyValueBuffer[ 128 ]; 00779 WCHAR *Ptr; 00780 HANDLE LocaleKey, SortKey, LangGroupKey; 00781 OBJECT_ATTRIBUTES NlsLocaleObjA, NlsSortObjA, NlsLangGroupObjA; 00782 PKEY_VALUE_PARTIAL_INFORMATION KeyValueInformation; 00783 ULONG i, ResultLength; 00784 00785 00786 // 00787 // Convert the LCID to the form %08x (e.g. 00000409) 00788 // 00789 LocaleName.Length = sizeof( LocaleNameBuffer ) / sizeof( WCHAR ); 00790 LocaleName.MaximumLength = LocaleName.Length; 00791 LocaleName.Buffer = LocaleNameBuffer; 00792 00793 // 00794 // Convert LCID to a string 00795 // 00796 ReturnStatus = RtlIntegerToUnicodeString( LocaleId, 16, &LocaleName ); 00797 if (!NT_SUCCESS(ReturnStatus)) 00798 goto Failed1; 00799 00800 Ptr = KeyValueNameBuffer; 00801 for (i = ((LocaleName.Length)/sizeof(WCHAR)); 00802 i < 8; 00803 i++, Ptr++) { 00804 *Ptr = L'0'; 00805 } 00806 *Ptr = UNICODE_NULL; 00807 00808 RtlInitUnicodeString(&KeyValueName, KeyValueNameBuffer); 00809 KeyValueName.MaximumLength = sizeof( KeyValueNameBuffer ) / sizeof( WCHAR ); 00810 RtlAppendUnicodeToString(&KeyValueName, LocaleName.Buffer); 00811 00812 00813 // 00814 // Open Registry Keys : Locale, Sort and LanguageGroup 00815 // 00816 RtlInitUnicodeString(&NlsLocaleKeyPath, 00817 L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Nls\\Locale"); 00818 00819 InitializeObjectAttributes( &NlsLocaleObjA, 00820 &NlsLocaleKeyPath, 00821 (OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE), 00822 NULL, 00823 NULL 00824 ); 00825 00826 ReturnStatus = ZwOpenKey( &LocaleKey, 00827 GENERIC_READ, 00828 &NlsLocaleObjA 00829 ); 00830 if (!NT_SUCCESS(ReturnStatus)) 00831 goto Failed1; 00832 00833 RtlInitUnicodeString(&NlsSortKeyPath, 00834 L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Nls\\Locale\\Alternate Sorts"); 00835 00836 InitializeObjectAttributes( &NlsSortObjA, 00837 &NlsSortKeyPath, 00838 (OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE), 00839 NULL, 00840 NULL 00841 ); 00842 00843 ReturnStatus = ZwOpenKey( &SortKey, 00844 GENERIC_READ, 00845 &NlsSortObjA 00846 ); 00847 if (!NT_SUCCESS(ReturnStatus)) 00848 goto Failed2; 00849 00850 RtlInitUnicodeString(&NlsLangGroupKeyPath, 00851 L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Nls\\Language Groups"); 00852 00853 InitializeObjectAttributes( &NlsLangGroupObjA, 00854 &NlsLangGroupKeyPath, 00855 (OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE), 00856 NULL, 00857 NULL 00858 ); 00859 00860 00861 ReturnStatus = ZwOpenKey( &LangGroupKey, 00862 GENERIC_READ, 00863 &NlsLangGroupObjA 00864 ); 00865 if (!NT_SUCCESS(ReturnStatus)) 00866 goto Failed3; 00867 00868 // 00869 // Validate Locale : Lookup the Locale's Language group, and make sure it is there. 00870 // 00871 KeyValueInformation = (PKEY_VALUE_PARTIAL_INFORMATION) KeyValueBuffer; 00872 ReturnStatus = ZwQueryValueKey( LocaleKey, 00873 &KeyValueName, 00874 KeyValuePartialInformation, 00875 KeyValueInformation, 00876 sizeof( KeyValueBuffer ), 00877 &ResultLength 00878 ); 00879 00880 if (!NT_SUCCESS(ReturnStatus)) { 00881 ReturnStatus = ZwQueryValueKey( SortKey, 00882 &KeyValueName, 00883 KeyValuePartialInformation, 00884 KeyValueInformation, 00885 sizeof( KeyValueBuffer ), 00886 &ResultLength 00887 ); 00888 } 00889 00890 if ((NT_SUCCESS(ReturnStatus)) && 00891 (KeyValueInformation->DataLength > 2) 00892 ) { 00893 00894 RtlInitUnicodeString( &KeyValueName, (PWSTR) KeyValueInformation->Data ); 00895 00896 ReturnStatus = ZwQueryValueKey( LangGroupKey, 00897 &KeyValueName, 00898 KeyValuePartialInformation, 00899 KeyValueInformation, 00900 sizeof( KeyValueBuffer ), 00901 &ResultLength 00902 ); 00903 if ((NT_SUCCESS(ReturnStatus)) && 00904 (KeyValueInformation->Type == REG_SZ) && 00905 (KeyValueInformation->DataLength > 2) 00906 ) { 00907 Ptr = (PWSTR) KeyValueInformation->Data; 00908 if (Ptr[0] == L'1' && Ptr[1] == UNICODE_NULL) { 00909 Status = STATUS_SUCCESS; 00910 } 00911 } 00912 } 00913 00914 // 00915 // Close opened keys 00916 // 00917 00918 ZwClose( LangGroupKey ); 00919 00920 Failed3: 00921 ZwClose( SortKey ); 00922 00923 Failed2: 00924 ZwClose( LocaleKey ); 00925 00926 Failed1: 00927 00928 // 00929 // If an error happens, let's record it. 00930 // 00931 if (!NT_SUCCESS(ReturnStatus)) { 00932 Status = ReturnStatus; 00933 } 00934 00935 return Status; 00936 } 00937 00938 00939 00940 NTSTATUS 00941 NtQuerySystemInformation ( 00942 IN SYSTEM_INFORMATION_CLASS SystemInformationClass, 00943 OUT PVOID SystemInformation, 00944 IN ULONG SystemInformationLength, 00945 OUT PULONG ReturnLength OPTIONAL 00946 ) 00947 00948 /*++ 00949 00950 Routine Description: 00951 00952 This function queries information about the system. 00953 00954 Arguments: 00955 00956 SystemInformationClass - The system information class about which 00957 to retrieve information. 00958 00959 SystemInformation - A pointer to a buffer which receives the specified 00960 information. The format and content of the buffer depend on the 00961 specified system information class. 00962 00963 SystemInformation Format by Information Class: 00964 00965 SystemBasicInformation - Data type is SYSTEM_BASIC_INFORMATION 00966 00967 SYSTEM_BASIC_INFORMATION Structure 00968 00969 ULONG Reserved - Always zero. 00970 00971 ULONG TimerResolutionInMicroSeconds - The resolution of 00972 the hardware time. All time values in NT are 00973 specified as 64-bit LARGE_INTEGER values in units of 00974 100 nanoseconds. This field allows an application to 00975 understand how many of the low order bits of a system 00976 time value are insignificant. 00977 00978 ULONG PageSize - The physical page size for virtual memory 00979 objects. Physical memory is committed in PageSize 00980 chunks. 00981 00982 ULONG AllocationGranularity - The logical page size for 00983 virtual memory objects. Allocating 1 byte of virtual 00984 memory will actually allocate AllocationGranularity 00985 bytes of virtual memory. Storing into that byte will 00986 commit the first physical page of the virtual memory. 00987 00988 ULONG MinimumUserModeAddress - The smallest valid user mode 00989 address. The first AllocationGranularity bytes of 00990 the virtual address space are reserved. This forces 00991 access violations for code the dereferences a zero 00992 pointer. 00993 00994 ULONG MaximumUserModeAddress - The largest valid user mode 00995 address. The next AllocationGranularity bytes of 00996 the virtual address space are reserved. This allows 00997 system service routines to validate user mode pointer 00998 parameters quickly. 00999 01000 KAFFINITY ActiveProcessorsAffinityMask - The affinity mask 01001 for the current hardware configuration. 01002 01003 CCHAR NumberOfProcessors - The number of processors 01004 in the current hardware configuration. 01005 01006 SystemProcessorInformation - Data type is SYSTEM_PROCESSOR_INFORMATION 01007 01008 SYSTEM_PROCESSOR_INFORMATION Structure 01009 01010 USHORT ProcessorArchitecture - The processor architecture: 01011 PROCESSOR_ARCHITECTURE_INTEL 01012 PROCESSOR_ARCHITECTURE_MIPS 01013 PROCESSOR_ARCHITECTURE_ALPHA 01014 PROCESSOR_ARCHITECTURE_PPC 01015 01016 USHORT ProcessorLevel - architecture dependent processor level. 01017 This is the least common denominator for an MP system: 01018 01019 For PROCESSOR_ARCHITECTURE_INTEL: 01020 3 - 386 01021 4 - 486 01022 5 - 586 or Pentium 01023 01024 For PROCESSOR_ARCHITECTURE_MIPS: 01025 00xx - where xx is 8-bit implementation number (bits 8-15 of 01026 PRId register. 01027 0004 - R4000 01028 01029 For PROCESSOR_ARCHITECTURE_ALPHA: 01030 xxxx - where xxxx is 16-bit processor version number (low 01031 order 16 bits of processor version number from firmware) 01032 01033 21064 - 21064 01034 21066 - 21066 01035 21164 - 21164 01036 01037 For PROCESSOR_ARCHITECTURE_PPC: 01038 xxxx - where xxxx is 16-bit processor version number (high 01039 order 16 bits of Processor Version Register). 01040 1 - 601 01041 3 - 603 01042 4 - 604 01043 6 - 603+ 01044 9 - 604+ 01045 20 - 620 01046 01047 USHORT ProcessorRevision - architecture dependent processor revision. 01048 This is the least common denominator for an MP system: 01049 01050 For PROCESSOR_ARCHITECTURE_INTEL: 01051 For Old Intel 386 or 486: 01052 FFxx - where xx is displayed as a hexadecimal CPU stepping 01053 (e.g. FFD0 is D0 stepping) 01054 01055 For Intel Pentium or Cyrix/NexGen 486 01056 xxyy - where xx is model number and yy is stepping, so 01057 0201 is Model 2, Stepping 1 01058 01059 For PROCESSOR_ARCHITECTURE_MIPS: 01060 00xx is 8-bit revision number of processor (low order 8 bits 01061 of PRId Register 01062 01063 For PROCESSOR_ARCHITECTURE_ALPHA: 01064 xxyy - where xxyy is 16-bit processor revision number (low 01065 order 16 bits of processor revision number from firmware). 01066 Displayed as Model 'A'+xx, Pass yy 01067 01068 For PROCESSOR_ARCHITECTURE_PPC: 01069 xxyy - where xxyy is 16-bit processor revision number (low 01070 order 16 bits of Processor Version Register). Displayed 01071 as a fixed point number xx.yy 01072 01073 USHORT Reserved - Always zero. 01074 01075 ULONG ProcessorFeatureBits - architecture dependent processor feature bits. 01076 This is the least common denominator for an MP system. 01077 01078 SystemPerformanceInformation - Data type is SYSTEM_PERFORMANCE_INFORMATION 01079 01080 SYSTEM_PERFORMANCE_INFORMATION Structure 01081 01082 LARGE_INTEGER IdleProcessTime - Returns the kernel time of the idle 01083 process. 01084 BUGBUG complete comment. 01085 LARGE_INTEGER IoReadTransferCount; 01086 LARGE_INTEGER IoWriteTransferCount; 01087 LARGE_INTEGER IoOtherTransferCount; 01088 LARGE_INTEGER KernelTime; 01089 LARGE_INTEGER UserTime; 01090 ULONG IoReadOperationCount; 01091 ULONG IoWriteOperationCount; 01092 ULONG IoOtherOperationCount; 01093 ULONG AvailablePages; 01094 ULONG CommittedPages; 01095 ULONG PageFaultCount; 01096 ULONG CopyOnWriteCount; 01097 ULONG TransitionCount; 01098 ULONG CacheTransitionCount; 01099 ULONG DemandZeroCount; 01100 ULONG PageReadCount; 01101 ULONG PageReadIoCount; 01102 ULONG CacheReadCount; 01103 ULONG CacheIoCount; 01104 ULONG DirtyPagesWriteCount; 01105 ULONG DirtyWriteIoCount; 01106 ULONG MappedPagesWriteCount; 01107 ULONG MappedWriteIoCount; 01108 ULONG PagedPoolPages; 01109 ULONG NonPagedPoolPages; 01110 ULONG PagedPoolAllocs; 01111 ULONG PagedPoolFrees; 01112 ULONG NonPagedPoolAllocs; 01113 ULONG NonPagedPoolFrees; 01114 ULONG LpcThreadsWaitingInReceive; 01115 ULONG LpcThreadsWaitingForReply; 01116 01117 SystemProcessInformation - Data type is SYSTEM_PROCESS_INFORMATION 01118 01119 SYSTEM_PROCESSOR_INFORMATION Structure 01120 BUGBUG - add here when done. 01121 01122 SystemDockInformation - Data type is SYSTEM_DOCK_INFORMATION 01123 01124 SYSTEM_DOCK_INFORMATION Structure 01125 01126 SYSTEM_DOCKED_STATE DockState - Ordinal specifying the current docking state. Possible values: 01127 SystemDockStateUnknown - The docking state of the system could not be determined. 01128 SystemUndocked - The system is undocked. 01129 SystemDocked - The system is docked. 01130 01131 ULONG DockIdLength - Specifies the length in characters of the Dock ID string 01132 (not including terminating NULL). 01133 01134 ULONG SerialNumberOffset - Specifies the character offset of the Serial Number within 01135 the DockId buffer. 01136 01137 ULONG SerialNumberLength - Specifies the length in characters of the Serial Number 01138 string (not including terminating NULL). 01139 01140 WCHAR DockId - Character buffer containing two null-terminated strings. The first 01141 string is a character representation of the dock ID number, starting 01142 at the beginning of the buffer. The second string is a character 01143 representation of the machine's serial number, starting at character 01144 offset SerialNumberOffset in the buffer. 01145 01146 01147 SystemPowerSettings - Data type is SYSTEM_POWER_SETTINGS 01148 SYSTEM_POWER_INFORMATION Structure 01149 BOOLEAN SystemSuspendSupported - Supplies a BOOLEAN as to 01150 whether the system suspend is enabled or not. 01151 BOOLEAN SystemHibernateSupported - Supplies a BOOLEAN as to 01152 whether the system hibernate is enabled or not. 01153 BOOLEAN ResumeTimerSupportsSuspend - Supplies a BOOLEAN as to 01154 whether the resuming from an external programmed timer 01155 from within a system suspend is enabled or not. 01156 BOOLEAN ResumeTimerSupportsHibernate - Supplies a BOOLEAN as to 01157 whether or resuming from an external programmed timer 01158 from within a system hibernate is enabled or not. 01159 BOOLEAN LidSupported - Supplies a BOOLEAN as to whether or not 01160 the suspending and resuming by Lid are enabled or not. 01161 BOOLEAN TurboSettingSupported - Supplies a BOOLEAN as to whether 01162 or not the system supports a turbo mode setting. 01163 BOOLEAN TurboMode - Supplies a BOOLEAN as to whether or not 01164 the system is in turbo mode. 01165 BOOLEAN SystemAcOrDc - Supplies a BOOLEAN as to whether or not 01166 the system is in AC mode. 01167 BOOLEAN DisablePowerDown - If TRUE, signifies that all requests to 01168 PoRequestPowerChange for a SET_POWER-PowerDown irp are to 01169 be ignored. 01170 LARGE_INTEGER SpindownDrives - If non-zero, signifies to the 01171 cache manager (or the IO subsystem) to optimize drive 01172 accesses based upon power saves, are that drives are to 01173 be spun down as appropriate. The value represents to user's 01174 requested disk spin down timeout. 01175 01176 SystemProcessorSpeedInformation - Data type is SYSTEM_PROCESSOR_SPEED_INFORMATION 01177 SYSTEM_PROCESSOR_SPEED_INFORMATION Structure (same as HalProcessorSpeedInformation) 01178 ULONG MaximumProcessorSpeed - The maximum hertz the processor is 01179 capable of. This information is used by the UI to draw the 01180 appropriate scale. This field is read-only and cannot be 01181 set. 01182 ULONG CurrentAvailableSpeed - The hertz for which the processor 01183 runs at when not idle. This field is read-only and cannot 01184 be set. 01185 ULONG ConfiguredSpeedLimit - The hertz for which the processor 01186 is limited to due to the current configuration. 01187 UCHAR PowerState 01188 0 - Normal 01189 1 - The processor speed is being limited due to available 01190 power restrictions. This field id read-only by the system. 01191 UCHAR ThermalState 01192 0 - Normal 01193 1 - The processors speed is being limited due to thermal 01194 restrictions. This field is read-only by the system. 01195 UCHAR TurboState 01196 0 - Normal 01197 1 - The processors speed is being limited by the fact that 01198 the system turbo mode is currently disabled which is 01199 requested to obtain more processor speed. 01200 01201 SystemInformationLength - Specifies the length in bytes of the system 01202 information buffer. 01203 01204 ReturnLength - An optional pointer which, if specified, receives the 01205 number of bytes placed in the system information buffer. 01206 01207 Return Value: 01208 01209 Returns one of the following status codes: 01210 01211 STATUS_SUCCESS - normal, successful completion. 01212 01213 STATUS_INVALID_INFO_CLASS - The SystemInformationClass parameter 01214 did not specify a valid value. 01215 01216 STATUS_INFO_LENGTH_MISMATCH - The value of the SystemInformationLength 01217 parameter did not match the length required for the information 01218 class requested by the SystemInformationClass parameter. 01219 01220 STATUS_ACCESS_VIOLATION - Either the SystemInformation buffer pointer 01221 or the ReturnLength pointer value specified an invalid address. 01222 01223 STATUS_WORKING_SET_QUOTA - The process does not have sufficient 01224 working set to lock the specified output structure in memory. 01225 01226 STATUS_INSUFFICIENT_RESOURCES - Insufficient system resources exist 01227 for this request to complete. 01228 01229 --*/ 01230 01231 { 01232 01233 KPROCESSOR_MODE PreviousMode; 01234 PSYSTEM_BASIC_INFORMATION BasicInfo; 01235 PSYSTEM_PROCESSOR_INFORMATION ProcessorInfo; 01236 SYSTEM_TIMEOFDAY_INFORMATION LocalTimeOfDayInfo; 01237 SYSTEM_PERFORMANCE_INFORMATION LocalPerformanceInfo; 01238 PSYSTEM_PERFORMANCE_INFORMATION PerformanceInfo; 01239 PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION ProcessorPerformanceInfo; 01240 PSYSTEM_CALL_COUNT_INFORMATION CallCountInformation; 01241 PSYSTEM_DEVICE_INFORMATION DeviceInformation; 01242 PCONFIGURATION_INFORMATION ConfigInfo; 01243 PSYSTEM_EXCEPTION_INFORMATION ExceptionInformation; 01244 PSYSTEM_FILECACHE_INFORMATION FileCache; 01245 PSYSTEM_QUERY_TIME_ADJUST_INFORMATION TimeAdjustmentInformation; 01246 PSYSTEM_KERNEL_DEBUGGER_INFORMATION KernelDebuggerInformation; 01247 PSYSTEM_CONTEXT_SWITCH_INFORMATION ContextSwitchInformation; 01248 PSYSTEM_INTERRUPT_INFORMATION InterruptInformation; 01249 PSYSTEM_SESSION_PROCESS_INFORMATION SessionProcessInformation; 01250 PVOID ProcessInformation; 01251 ULONG ProcessInformationLength; 01252 01253 NTSTATUS Status; 01254 BOOLEAN ReleaseModuleResoure = FALSE; 01255 PKPRCB Prcb; 01256 ULONG Length = 0; 01257 ULONG i; 01258 ULONG ContextSwitches; 01259 PULONG TableLimit, TableCounts; 01260 PKSERVICE_TABLE_DESCRIPTOR Table; 01261 ULONG SessionId; 01262 01263 PAGED_CODE(); 01264 01265 // 01266 // Assume successful completion. 01267 // 01268 01269 Status = STATUS_SUCCESS; 01270 try { 01271 01272 // 01273 // Get previous processor mode and probe output argument if necessary. 01274 // 01275 01276 PreviousMode = KeGetPreviousMode(); 01277 if (PreviousMode != KernelMode) { 01278 ProbeForWrite(SystemInformation, 01279 SystemInformationLength, 01280 SystemInformationClass == SystemKernelDebuggerInformation ? sizeof(BOOLEAN) 01281 : sizeof(ULONG)); 01282 01283 if (ARGUMENT_PRESENT(ReturnLength)) { 01284 ProbeForWriteUlong(ReturnLength); 01285 } 01286 } 01287 01288 if (ARGUMENT_PRESENT(ReturnLength)) { 01289 *ReturnLength = 0; 01290 } 01291 01292 switch (SystemInformationClass) { 01293 01294 case SystemBasicInformation: 01295 01296 if (SystemInformationLength != sizeof( SYSTEM_BASIC_INFORMATION )) { 01297 return STATUS_INFO_LENGTH_MISMATCH; 01298 } 01299 01300 BasicInfo = (PSYSTEM_BASIC_INFORMATION)SystemInformation; 01301 BasicInfo->NumberOfProcessors = KeNumberProcessors; 01302 BasicInfo->ActiveProcessorsAffinityMask = (ULONG_PTR)KeActiveProcessors; 01303 BasicInfo->Reserved = 0; 01304 BasicInfo->TimerResolution = KeMaximumIncrement; 01305 BasicInfo->NumberOfPhysicalPages = MmNumberOfPhysicalPages; 01306 BasicInfo->LowestPhysicalPageNumber = MmLowestPhysicalPage; 01307 BasicInfo->HighestPhysicalPageNumber = MmHighestPhysicalPage; 01308 BasicInfo->PageSize = PAGE_SIZE; 01309 BasicInfo->AllocationGranularity = MM_ALLOCATION_GRANULARITY; 01310 BasicInfo->MinimumUserModeAddress = (ULONG_PTR)MM_LOWEST_USER_ADDRESS; 01311 BasicInfo->MaximumUserModeAddress = (ULONG_PTR)MM_HIGHEST_USER_ADDRESS; 01312 01313 if (ARGUMENT_PRESENT( ReturnLength )) { 01314 *ReturnLength = sizeof( SYSTEM_BASIC_INFORMATION ); 01315 } 01316 break; 01317 01318 case SystemProcessorInformation: 01319 if (SystemInformationLength < sizeof( SYSTEM_PROCESSOR_INFORMATION )) { 01320 return STATUS_INFO_LENGTH_MISMATCH; 01321 } 01322 01323 ProcessorInfo = (PSYSTEM_PROCESSOR_INFORMATION)SystemInformation; 01324 01325 ProcessorInfo->ProcessorArchitecture = KeProcessorArchitecture; 01326 ProcessorInfo->ProcessorLevel = KeProcessorLevel; 01327 ProcessorInfo->ProcessorRevision = KeProcessorRevision; 01328 ProcessorInfo->Reserved = 0; 01329 ProcessorInfo->ProcessorFeatureBits = KeFeatureBits; 01330 01331 if (ARGUMENT_PRESENT( ReturnLength )) { 01332 *ReturnLength = sizeof( SYSTEM_PROCESSOR_INFORMATION ); 01333 } 01334 01335 break; 01336 01337 case SystemPerformanceInformation: 01338 if (SystemInformationLength < sizeof( SYSTEM_PERFORMANCE_INFORMATION )) { 01339 return STATUS_INFO_LENGTH_MISMATCH; 01340 } 01341 01342 PerformanceInfo = (PSYSTEM_PERFORMANCE_INFORMATION)SystemInformation; 01343 01344 // 01345 // Io information. 01346 // 01347 01348 LocalPerformanceInfo.IoReadTransferCount = IoReadTransferCount; 01349 LocalPerformanceInfo.IoWriteTransferCount = IoWriteTransferCount; 01350 LocalPerformanceInfo.IoOtherTransferCount = IoOtherTransferCount; 01351 LocalPerformanceInfo.IoReadOperationCount = IoReadOperationCount; 01352 LocalPerformanceInfo.IoWriteOperationCount = IoWriteOperationCount; 01353 LocalPerformanceInfo.IoOtherOperationCount = IoOtherOperationCount; 01354 01355 // 01356 // Ke information. 01357 // 01358 // These counters are kept on a per processor basis and must 01359 // be totaled. 01360 // 01361 01362 { 01363 ULONG FirstLevelTbFills = 0; 01364 ULONG SecondLevelTbFills = 0; 01365 ULONG SystemCalls = 0; 01366 // ULONG InterruptCount = 0; 01367 01368 ContextSwitches = 0; 01369 for (i = 0; i < (ULONG)KeNumberProcessors; i += 1) { 01370 Prcb = KiProcessorBlock[i]; 01371 if (Prcb != NULL) { 01372 ContextSwitches += Prcb->KeContextSwitches; 01373 FirstLevelTbFills += Prcb->KeFirstLevelTbFills; 01374 // InterruptCount += Prcb->KeInterruptCount; 01375 SecondLevelTbFills += Prcb->KeSecondLevelTbFills; 01376 SystemCalls += Prcb->KeSystemCalls; 01377 } 01378 } 01379 01380 LocalPerformanceInfo.ContextSwitches = ContextSwitches; 01381 LocalPerformanceInfo.FirstLevelTbFills = FirstLevelTbFills; 01382 // LocalPerformanceInfo.InterruptCount = KeInterruptCount; 01383 LocalPerformanceInfo.SecondLevelTbFills = SecondLevelTbFills; 01384 LocalPerformanceInfo.SystemCalls = SystemCalls; 01385 } 01386 01387 // 01388 // Mm information. 01389 // 01390 01391 LocalPerformanceInfo.AvailablePages = MmAvailablePages; 01392 LocalPerformanceInfo.CommittedPages = MmTotalCommittedPages; 01393 LocalPerformanceInfo.CommitLimit = MmTotalCommitLimit; 01394 LocalPerformanceInfo.PeakCommitment = MmPeakCommitment; 01395 LocalPerformanceInfo.PageFaultCount = MmInfoCounters.PageFaultCount; 01396 LocalPerformanceInfo.CopyOnWriteCount = MmInfoCounters.CopyOnWriteCount; 01397 LocalPerformanceInfo.TransitionCount = MmInfoCounters.TransitionCount; 01398 LocalPerformanceInfo.CacheTransitionCount = MmInfoCounters.CacheTransitionCount; 01399 LocalPerformanceInfo.DemandZeroCount = MmInfoCounters.DemandZeroCount; 01400 LocalPerformanceInfo.PageReadCount = MmInfoCounters.PageReadCount; 01401 LocalPerformanceInfo.PageReadIoCount = MmInfoCounters.PageReadIoCount; 01402 LocalPerformanceInfo.CacheReadCount = MmInfoCounters.CacheReadCount; 01403 LocalPerformanceInfo.CacheIoCount = MmInfoCounters.CacheIoCount; 01404 LocalPerformanceInfo.DirtyPagesWriteCount = MmInfoCounters.DirtyPagesWriteCount; 01405 LocalPerformanceInfo.DirtyWriteIoCount = MmInfoCounters.DirtyWriteIoCount; 01406 LocalPerformanceInfo.MappedPagesWriteCount = MmInfoCounters.MappedPagesWriteCount; 01407 LocalPerformanceInfo.MappedWriteIoCount = MmInfoCounters.MappedWriteIoCount; 01408 LocalPerformanceInfo.FreeSystemPtes = MmTotalFreeSystemPtes[0]; 01409 01410 LocalPerformanceInfo.ResidentSystemCodePage = MmSystemCodePage; 01411 LocalPerformanceInfo.ResidentSystemCachePage = MmSystemCachePage; 01412 LocalPerformanceInfo.ResidentPagedPoolPage = MmPagedPoolPage; 01413 LocalPerformanceInfo.ResidentSystemDriverPage = MmSystemDriverPage; 01414 LocalPerformanceInfo.TotalSystemCodePages = MmTotalSystemCodePages; 01415 LocalPerformanceInfo.TotalSystemDriverPages = MmTotalSystemDriverPages; 01416 01417 // 01418 // Process information. 01419 // 01420 01421 LocalPerformanceInfo.IdleProcessTime.QuadPart = 01422 UInt32x32To64(PsIdleProcess->Pcb.KernelTime, 01423 KeMaximumIncrement); 01424 01425 // 01426 // Pool information. 01427 // 01428 01429 LocalPerformanceInfo.PagedPoolPages = 0; 01430 LocalPerformanceInfo.NonPagedPoolPages = 0; 01431 LocalPerformanceInfo.PagedPoolAllocs = 0; 01432 LocalPerformanceInfo.PagedPoolFrees = 0; 01433 LocalPerformanceInfo.PagedPoolLookasideHits = 0; 01434 LocalPerformanceInfo.NonPagedPoolAllocs = 0; 01435 LocalPerformanceInfo.NonPagedPoolFrees = 0; 01436 LocalPerformanceInfo.NonPagedPoolLookasideHits = 0; 01437 ExQueryPoolUsage( &LocalPerformanceInfo.PagedPoolPages, 01438 &LocalPerformanceInfo.NonPagedPoolPages, 01439 &LocalPerformanceInfo.PagedPoolAllocs, 01440 &LocalPerformanceInfo.PagedPoolFrees, 01441 &LocalPerformanceInfo.PagedPoolLookasideHits, 01442 &LocalPerformanceInfo.NonPagedPoolAllocs, 01443 &LocalPerformanceInfo.NonPagedPoolFrees, 01444 &LocalPerformanceInfo.NonPagedPoolLookasideHits 01445 ); 01446 01447 // 01448 // Cache Manager information. 01449 // 01450 01451 LocalPerformanceInfo.CcFastReadNoWait = CcFastReadNoWait; 01452 LocalPerformanceInfo.CcFastReadWait = CcFastReadWait; 01453 LocalPerformanceInfo.CcFastReadResourceMiss = CcFastReadResourceMiss; 01454 LocalPerformanceInfo.CcFastReadNotPossible = CcFastReadNotPossible; 01455 LocalPerformanceInfo.CcFastMdlReadNoWait = CcFastMdlReadNoWait; 01456 LocalPerformanceInfo.CcFastMdlReadWait = CcFastMdlReadWait; 01457 LocalPerformanceInfo.CcFastMdlReadResourceMiss = CcFastMdlReadResourceMiss; 01458 LocalPerformanceInfo.CcFastMdlReadNotPossible = CcFastMdlReadNotPossible; 01459 LocalPerformanceInfo.CcMapDataNoWait = CcMapDataNoWait; 01460 LocalPerformanceInfo.CcMapDataWait = CcMapDataWait; 01461 LocalPerformanceInfo.CcMapDataNoWaitMiss = CcMapDataNoWaitMiss; 01462 LocalPerformanceInfo.CcMapDataWaitMiss = CcMapDataWaitMiss; 01463 LocalPerformanceInfo.CcPinMappedDataCount = CcPinMappedDataCount; 01464 LocalPerformanceInfo.CcPinReadNoWait = CcPinReadNoWait; 01465 LocalPerformanceInfo.CcPinReadWait = CcPinReadWait; 01466 LocalPerformanceInfo.CcPinReadNoWaitMiss = CcPinReadNoWaitMiss; 01467 LocalPerformanceInfo.CcPinReadWaitMiss = CcPinReadWaitMiss; 01468 LocalPerformanceInfo.CcCopyReadNoWait = CcCopyReadNoWait; 01469 LocalPerformanceInfo.CcCopyReadWait = CcCopyReadWait; 01470 LocalPerformanceInfo.CcCopyReadNoWaitMiss = CcCopyReadNoWaitMiss; 01471 LocalPerformanceInfo.CcCopyReadWaitMiss = CcCopyReadWaitMiss; 01472 LocalPerformanceInfo.CcMdlReadNoWait = CcMdlReadNoWait; 01473 LocalPerformanceInfo.CcMdlReadWait = CcMdlReadWait; 01474 LocalPerformanceInfo.CcMdlReadNoWaitMiss = CcMdlReadNoWaitMiss; 01475 LocalPerformanceInfo.CcMdlReadWaitMiss = CcMdlReadWaitMiss; 01476 LocalPerformanceInfo.CcReadAheadIos = CcReadAheadIos; 01477 LocalPerformanceInfo.CcLazyWriteIos = CcLazyWriteIos; 01478 LocalPerformanceInfo.CcLazyWritePages = CcLazyWritePages; 01479 LocalPerformanceInfo.CcDataFlushes = CcDataFlushes; 01480 LocalPerformanceInfo.CcDataPages = CcDataPages; 01481 01482 #if !defined(NT_UP) 01483 // 01484 // On an MP machines go sum up some other 'hot' cache manager 01485 // statistics. 01486 // 01487 01488 for (i = 0; i < (ULONG)KeNumberProcessors; i++) { 01489 Prcb = KiProcessorBlock[i]; 01490 01491 LocalPerformanceInfo.CcFastReadNoWait += Prcb->CcFastReadNoWait; 01492 LocalPerformanceInfo.CcFastReadWait += Prcb->CcFastReadWait; 01493 LocalPerformanceInfo.CcFastReadNotPossible += Prcb->CcFastReadNotPossible; 01494 LocalPerformanceInfo.CcCopyReadNoWait += Prcb->CcCopyReadNoWait; 01495 LocalPerformanceInfo.CcCopyReadWait += Prcb->CcCopyReadWait; 01496 LocalPerformanceInfo.CcCopyReadNoWaitMiss += Prcb->CcCopyReadNoWaitMiss; 01497 } 01498 #endif 01499 *PerformanceInfo = LocalPerformanceInfo; 01500 if (ARGUMENT_PRESENT( ReturnLength )) { 01501 *ReturnLength = sizeof(LocalPerformanceInfo); 01502 } 01503 01504 break; 01505 01506 case SystemProcessorPerformanceInformation: 01507 if (SystemInformationLength < 01508 sizeof( SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION )) { 01509 return STATUS_INFO_LENGTH_MISMATCH; 01510 } 01511 01512 ProcessorPerformanceInfo = 01513 (PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) SystemInformation; 01514 01515 Length = 0; 01516 for (i = 0; i < (ULONG)KeNumberProcessors; i++) { 01517 Prcb = KiProcessorBlock[i]; 01518 if (Prcb != NULL) { 01519 if (SystemInformationLength < Length + sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION)) 01520 break; 01521 01522 Length += sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION); 01523 01524 ProcessorPerformanceInfo->UserTime.QuadPart = 01525 UInt32x32To64(Prcb->UserTime, 01526 KeMaximumIncrement); 01527 01528 ProcessorPerformanceInfo->KernelTime.QuadPart = 01529 UInt32x32To64(Prcb->KernelTime, 01530 KeMaximumIncrement); 01531 01532 ProcessorPerformanceInfo->DpcTime.QuadPart = 01533 UInt32x32To64(Prcb->DpcTime, 01534 KeMaximumIncrement); 01535 01536 ProcessorPerformanceInfo->InterruptTime.QuadPart = 01537 UInt32x32To64(Prcb->InterruptTime, 01538 KeMaximumIncrement); 01539 01540 ProcessorPerformanceInfo->IdleTime.QuadPart = 01541 UInt32x32To64(Prcb->IdleThread->KernelTime, 01542 KeMaximumIncrement); 01543 01544 ProcessorPerformanceInfo->InterruptCount = Prcb->InterruptCount; 01545 01546 ProcessorPerformanceInfo++; 01547 } 01548 } 01549 01550 if (ARGUMENT_PRESENT( ReturnLength )) { 01551 *ReturnLength = Length; 01552 } 01553 01554 break; 01555 01556 case SystemTimeOfDayInformation: 01557 if (SystemInformationLength > sizeof (SYSTEM_TIMEOFDAY_INFORMATION)) { 01558 return STATUS_INFO_LENGTH_MISMATCH; 01559 } 01560 01561 RtlZeroMemory (&LocalTimeOfDayInfo, sizeof(LocalTimeOfDayInfo)); 01562 KeQuerySystemTime(&LocalTimeOfDayInfo.CurrentTime); 01563 LocalTimeOfDayInfo.BootTime = KeBootTime; 01564 LocalTimeOfDayInfo.TimeZoneBias = ExpTimeZoneBias; 01565 LocalTimeOfDayInfo.TimeZoneId = ExpCurrentTimeZoneId; 01566 LocalTimeOfDayInfo.BootTimeBias = KeBootTimeBias; 01567 LocalTimeOfDayInfo.SleepTimeBias = KeInterruptTimeBias; 01568 01569 try { 01570 RtlCopyMemory ( 01571 SystemInformation, 01572 &LocalTimeOfDayInfo, 01573 SystemInformationLength 01574 ); 01575 01576 if (ARGUMENT_PRESENT(ReturnLength) ) { 01577 *ReturnLength = SystemInformationLength; 01578 } 01579 } except(EXCEPTION_EXECUTE_HANDLER) { 01580 return STATUS_SUCCESS; 01581 } 01582 01583 break; 01584 01585 // 01586 // Query system time adjustment information. 01587 // 01588 01589 case SystemTimeAdjustmentInformation: 01590 if (SystemInformationLength != sizeof( SYSTEM_QUERY_TIME_ADJUST_INFORMATION )) { 01591 return STATUS_INFO_LENGTH_MISMATCH; 01592 } 01593 01594 TimeAdjustmentInformation = 01595 (PSYSTEM_QUERY_TIME_ADJUST_INFORMATION)SystemInformation; 01596 01597 TimeAdjustmentInformation->TimeAdjustment = KeTimeAdjustment; 01598 TimeAdjustmentInformation->TimeIncrement = KeMaximumIncrement; 01599 TimeAdjustmentInformation->Enable = KeTimeSynchronization; 01600 break; 01601 01602 case SystemSummaryMemoryInformation: 01603 case SystemFullMemoryInformation: 01604 01605 if (SystemInformationLength < sizeof( SYSTEM_MEMORY_INFORMATION )) { 01606 return STATUS_INFO_LENGTH_MISMATCH; 01607 } 01608 01609 Status = MmMemoryUsage (SystemInformation, 01610 SystemInformationLength, 01611 (SystemInformationClass == SystemFullMemoryInformation) ? 0 : 1, 01612 &Length); 01613 01614 if (NT_SUCCESS(Status) && ARGUMENT_PRESENT( ReturnLength )) { 01615 *ReturnLength = Length; 01616 } 01617 break; 01618 01619 case SystemPathInformation: 01620 DbgPrint( "EX: SystemPathInformation now available via SharedUserData\n" ); 01621 DbgBreakPoint(); 01622 return STATUS_NOT_IMPLEMENTED; 01623 break; 01624 01625 case SystemProcessInformation: 01626 if (SystemInformationLength < sizeof( SYSTEM_PROCESS_INFORMATION)) { 01627 return STATUS_INFO_LENGTH_MISMATCH; 01628 } 01629 01630 Status = ExpGetProcessInformation (SystemInformation, 01631 SystemInformationLength, 01632 &Length, 01633 NULL); 01634 01635 if (NT_SUCCESS(Status) && ARGUMENT_PRESENT( ReturnLength )) { 01636 *ReturnLength = Length; 01637 } 01638 01639 break; 01640 01641 case SystemSessionProcessInformation: 01642 01643 if (SystemInformationLength < sizeof( SYSTEM_SESSION_PROCESS_INFORMATION)) { 01644 return STATUS_INFO_LENGTH_MISMATCH; 01645 } 01646 01647 SessionProcessInformation = 01648 (PSYSTEM_SESSION_PROCESS_INFORMATION)SystemInformation; 01649 01650 // 01651 // The lower level locks the buffer specified below into memory using MmProbeAndLockPages. 01652 // We don't need to probe the buffers here. 01653 // 01654 SessionId = SessionProcessInformation->SessionId; 01655 ProcessInformation = SessionProcessInformation->Buffer; 01656 ProcessInformationLength = SessionProcessInformation->SizeOfBuf; 01657 01658 if (ProcessInformationLength < sizeof(SYSTEM_PROCESS_INFORMATION)) { 01659 return STATUS_INFO_LENGTH_MISMATCH; 01660 } 01661 01662 if (!POINTER_IS_ALIGNED (ProcessInformation, sizeof (ULONG))) { 01663 return STATUS_DATATYPE_MISALIGNMENT; 01664 } 01665 01666 Status = ExpGetProcessInformation (ProcessInformation, 01667 ProcessInformationLength, 01668 &Length, 01669 &SessionId); 01670 01671 if (NT_SUCCESS(Status) && ARGUMENT_PRESENT( ReturnLength )) { 01672 *ReturnLength = Length; 01673 } 01674 01675 break; 01676 01677 case SystemCallCountInformation: 01678 01679 Length = sizeof(SYSTEM_CALL_COUNT_INFORMATION) + 01680 (NUMBER_SERVICE_TABLES * sizeof(ULONG)); 01681 for ( i = 0, Table = KeServiceDescriptorTableShadow; 01682 i < NUMBER_SERVICE_TABLES; 01683 i++, Table++ ) { 01684 if ( (Table->Limit != 0) && (Table->Count != NULL) ) { 01685 Length += Table->Limit * sizeof(ULONG); 01686 } 01687 } 01688 01689 if (ARGUMENT_PRESENT( ReturnLength )) { 01690 *ReturnLength = Length; 01691 } 01692 01693 if (SystemInformationLength < Length) { 01694 return STATUS_INFO_LENGTH_MISMATCH; 01695 } 01696 01697 CallCountInformation = (PSYSTEM_CALL_COUNT_INFORMATION)SystemInformation; 01698 CallCountInformation->Length = Length; 01699 CallCountInformation->NumberOfTables = NUMBER_SERVICE_TABLES; 01700 01701 TableLimit = (PULONG)(CallCountInformation + 1); 01702 TableCounts = TableLimit + NUMBER_SERVICE_TABLES; 01703 for ( i = 0, Table = KeServiceDescriptorTableShadow; 01704 i < NUMBER_SERVICE_TABLES; 01705 i++, Table++ ) { 01706 if ((Table->Limit == 0) || (Table->Count == NULL)) { 01707 *TableLimit++ = 0; 01708 } else { 01709 *TableLimit++ = Table->Limit; 01710 RtlMoveMemory((PVOID)TableCounts, 01711 (PVOID)Table->Count, 01712 Table->Limit * sizeof(ULONG)); 01713 TableCounts += Table->Limit; 01714 } 01715 } 01716 01717 break; 01718 01719 case SystemDeviceInformation: 01720 if (SystemInformationLength != sizeof( SYSTEM_DEVICE_INFORMATION )) { 01721 return STATUS_INFO_LENGTH_MISMATCH; 01722 } 01723 01724 ConfigInfo = IoGetConfigurationInformation(); 01725 DeviceInformation = (PSYSTEM_DEVICE_INFORMATION)SystemInformation; 01726 DeviceInformation->NumberOfDisks = ConfigInfo->DiskCount; 01727 DeviceInformation->NumberOfFloppies = ConfigInfo->FloppyCount; 01728 DeviceInformation->NumberOfCdRoms = ConfigInfo->CdRomCount; 01729 DeviceInformation->NumberOfTapes = ConfigInfo->TapeCount; 01730 DeviceInformation->NumberOfSerialPorts = ConfigInfo->SerialCount; 01731 DeviceInformation->NumberOfParallelPorts = ConfigInfo->ParallelCount; 01732 01733 if (ARGUMENT_PRESENT( ReturnLength )) { 01734 *ReturnLength = sizeof( SYSTEM_DEVICE_INFORMATION ); 01735 } 01736 break; 01737 01738 case SystemFlagsInformation: 01739 if (SystemInformationLength != sizeof( SYSTEM_FLAGS_INFORMATION )) { 01740 return STATUS_INFO_LENGTH_MISMATCH; 01741 } 01742 01743 ((PSYSTEM_FLAGS_INFORMATION)SystemInformation)->Flags = NtGlobalFlag; 01744 01745 if (ARGUMENT_PRESENT( ReturnLength )) { 01746 *ReturnLength = sizeof( SYSTEM_FLAGS_INFORMATION ); 01747 } 01748 break; 01749 01750 case SystemCallTimeInformation: 01751 return STATUS_NOT_IMPLEMENTED; 01752 01753 case SystemModuleInformation: 01754 KeEnterCriticalRegion(); 01755 ExAcquireResourceExclusive( &PsLoadedModuleResource, TRUE ); 01756 ReleaseModuleResoure = TRUE; 01757 Status = ExpQueryModuleInformation( &PsLoadedModuleList, 01758 &MmLoadedUserImageList, 01759 (PRTL_PROCESS_MODULES)SystemInformation, 01760 SystemInformationLength, 01761 ReturnLength 01762 ); 01763 ExReleaseResource (&PsLoadedModuleResource); 01764 ReleaseModuleResoure = FALSE; 01765 KeLeaveCriticalRegion(); 01766 break; 01767 01768 case SystemLocksInformation: 01769 if (SystemInformationLength < sizeof( RTL_PROCESS_LOCKS )) { 01770 return STATUS_INFO_LENGTH_MISMATCH; 01771 } 01772 01773 Status = ExpGetLockInformation (SystemInformation, 01774 SystemInformationLength, 01775 &Length); 01776 01777 if (ARGUMENT_PRESENT( ReturnLength )) { 01778 *ReturnLength = Length; 01779 } 01780 01781 break; 01782 01783 case SystemStackTraceInformation: 01784 if (SystemInformationLength < sizeof( RTL_PROCESS_BACKTRACES )) { 01785 return STATUS_INFO_LENGTH_MISMATCH; 01786 } 01787 01788 #if i386 && !FPO 01789 Status = ExpGetStackTraceInformation (SystemInformation, 01790 SystemInformationLength, 01791 &Length); 01792 #else 01793 Status = STATUS_NOT_IMPLEMENTED; 01794 #endif // i386 && !FPO 01795 01796 if (ARGUMENT_PRESENT( ReturnLength )) { 01797 *ReturnLength = Length; 01798 } 01799 01800 break; 01801 01802 case SystemPagedPoolInformation: 01803 if (SystemInformationLength < sizeof( SYSTEM_POOL_INFORMATION )) { 01804 return STATUS_INFO_LENGTH_MISMATCH; 01805 } 01806 01807 Status = ExpGetPoolInformation( PagedPool, 01808 SystemInformation, 01809 SystemInformationLength, 01810 &Length 01811 ); 01812 01813 if (ARGUMENT_PRESENT( ReturnLength )) { 01814 *ReturnLength = Length; 01815 } 01816 break; 01817 01818 case SystemNonPagedPoolInformation: 01819 if (SystemInformationLength < sizeof( SYSTEM_POOL_INFORMATION )) { 01820 return STATUS_INFO_LENGTH_MISMATCH; 01821 } 01822 01823 Status = ExpGetPoolInformation( NonPagedPool, 01824 SystemInformation, 01825 SystemInformationLength, 01826 &Length 01827 ); 01828 01829 if (ARGUMENT_PRESENT( ReturnLength )) { 01830 *ReturnLength = Length; 01831 } 01832 break; 01833 01834 case SystemHandleInformation: 01835 if (SystemInformationLength < sizeof( SYSTEM_HANDLE_INFORMATION )) { 01836 return STATUS_INFO_LENGTH_MISMATCH; 01837 } 01838 01839 Status = ExpGetHandleInformation( SystemInformation, 01840 SystemInformationLength, 01841 &Length 01842 ); 01843 01844 if (ARGUMENT_PRESENT( ReturnLength )) { 01845 *ReturnLength = Length; 01846 } 01847 break; 01848 01849 case SystemObjectInformation: 01850 if (SystemInformationLength < sizeof( SYSTEM_OBJECTTYPE_INFORMATION )) { 01851 return STATUS_INFO_LENGTH_MISMATCH; 01852 } 01853 01854 Status = ExpGetObjectInformation( SystemInformation, 01855 SystemInformationLength, 01856 &Length 01857 ); 01858 01859 if (ARGUMENT_PRESENT( ReturnLength )) { 01860 *ReturnLength = Length; 01861 } 01862 break; 01863 01864 case SystemPageFileInformation: 01865 01866 if (SystemInformationLength < sizeof( SYSTEM_PAGEFILE_INFORMATION )) { 01867 return STATUS_INFO_LENGTH_MISMATCH; 01868 } 01869 01870 Status = MmGetPageFileInformation( SystemInformation, 01871 SystemInformationLength, 01872 &Length 01873 ); 01874 01875 if (ARGUMENT_PRESENT( ReturnLength )) { 01876 *ReturnLength = Length; 01877 } 01878 break; 01879 01880 01881 case SystemFileCacheInformation: 01882 01883 // 01884 // This structure was extended in NT 4.0 from 12 bytes. 01885 // Use the previous size of 12 bytes for versioning info. 01886 // 01887 01888 if (SystemInformationLength < 12) { 01889 return STATUS_INFO_LENGTH_MISMATCH; 01890 } 01891 01892 FileCache = (PSYSTEM_FILECACHE_INFORMATION)SystemInformation; 01893 FileCache->CurrentSize = MmSystemCacheWs.WorkingSetSize << PAGE_SHIFT; 01894 FileCache->PeakSize = MmSystemCacheWs.PeakWorkingSetSize << PAGE_SHIFT; 01895 FileCache->CurrentSizeIncludingTransitionInPages = MmSystemCacheWs.WorkingSetSize + MmTransitionSharedPages; 01896 FileCache->PeakSizeIncludingTransitionInPages = MmTransitionSharedPagesPeak; 01897 FileCache->PageFaultCount = MmSystemCacheWs.PageFaultCount; 01898 01899 i = 12; 01900 if (SystemInformationLength >= sizeof( SYSTEM_FILECACHE_INFORMATION )) { 01901 i = sizeof (SYSTEM_FILECACHE_INFORMATION); 01902 FileCache->MinimumWorkingSet = 01903 MmSystemCacheWs.MinimumWorkingSetSize; 01904 FileCache->MaximumWorkingSet = 01905 MmSystemCacheWs.MaximumWorkingSetSize; 01906 } 01907 01908 if (ARGUMENT_PRESENT( ReturnLength )) { 01909 *ReturnLength = i; 01910 } 01911 break; 01912 01913 case SystemPoolTagInformation: 01914 01915 #ifdef POOL_TAGGING 01916 if (SystemInformationLength < sizeof( SYSTEM_POOLTAG_INFORMATION )) { 01917 return STATUS_INFO_LENGTH_MISMATCH; 01918 } 01919 01920 Status = ExpGetPoolTagInfo (SystemInformation, 01921 SystemInformationLength, 01922 ReturnLength); 01923 #else 01924 return STATUS_NOT_IMPLEMENTED; 01925 #endif //POOL_TAGGING 01926 01927 break; 01928 01929 case SystemVdmInstemulInformation: 01930 #ifdef i386 01931 if (SystemInformationLength < sizeof( SYSTEM_VDM_INSTEMUL_INFO )) { 01932 return STATUS_INFO_LENGTH_MISMATCH; 01933 } 01934 01935 Status = ExpGetInstemulInformation( 01936 (PSYSTEM_VDM_INSTEMUL_INFO)SystemInformation 01937 ); 01938 01939 if (ARGUMENT_PRESENT( ReturnLength )) { 01940 *ReturnLength = sizeof(SYSTEM_VDM_INSTEMUL_INFO); 01941 } 01942 #else 01943 Status = STATUS_NOT_IMPLEMENTED; 01944 #endif 01945 break; 01946 01947 case SystemCrashDumpInformation: 01948 01949 if (SystemInformationLength < sizeof( SYSTEM_CRASH_DUMP_INFORMATION)) { 01950 return STATUS_INFO_LENGTH_MISMATCH; 01951 } 01952 01953 // Only allow callers that have create page file privilege 01954 // to access crash dump information 01955 // 01956 01957 if (!SeSinglePrivilegeCheck(SeCreatePagefilePrivilege,PreviousMode)) { 01958 return STATUS_ACCESS_DENIED; 01959 } 01960 01961 Status = MmGetCrashDumpInformation ( 01962 (PSYSTEM_CRASH_DUMP_INFORMATION)SystemInformation); 01963 01964 01965 if ( NT_SUCCESS( Status ) ) { 01966 Status = IoGetCrashDumpInformation ( 01967 (PSYSTEM_CRASH_DUMP_INFORMATION)SystemInformation); 01968 } 01969 01970 if (ARGUMENT_PRESENT( ReturnLength )) { 01971 *ReturnLength = sizeof(SYSTEM_CRASH_DUMP_INFORMATION); 01972 } 01973 01974 break; 01975 01976 // 01977 // Get system exception information which includes the number 01978 // of exceptions that have dispatched, the number of alignment 01979 // fixups, and the number of floating emulations that have been 01980 // performed. 01981 // 01982 01983 case SystemExceptionInformation: 01984 if (SystemInformationLength < sizeof( SYSTEM_EXCEPTION_INFORMATION)) { 01985 return STATUS_INFO_LENGTH_MISMATCH; 01986 } 01987 01988 if (ARGUMENT_PRESENT( ReturnLength )) { 01989 *ReturnLength = sizeof(SYSTEM_EXCEPTION_INFORMATION); 01990 } 01991 01992 ExceptionInformation = (PSYSTEM_EXCEPTION_INFORMATION)SystemInformation; 01993 01994 // 01995 // Ke information. 01996 // 01997 // These counters are kept on a per processor basis and must 01998 // be totaled. 01999 // 02000 02001 { 02002 ULONG AlignmentFixupCount = 0; 02003 ULONG ExceptionDispatchCount = 0; 02004 ULONG FloatingEmulationCount = 0; 02005 ULONG ByteWordEmulationCount = 0; 02006 02007 for (i = 0; i < (ULONG)KeNumberProcessors; i += 1) { 02008 Prcb = KiProcessorBlock[i]; 02009 if (Prcb != NULL) { 02010 AlignmentFixupCount += Prcb->KeAlignmentFixupCount; 02011 ExceptionDispatchCount += Prcb->KeExceptionDispatchCount; 02012 FloatingEmulationCount += Prcb->KeFloatingEmulationCount; 02013 #if defined(_ALPHA_) 02014 AlignmentFixupCount += 02015 (ULONG)Prcb->Pcr->PalAlignmentFixupCount; 02016 02017 ByteWordEmulationCount += Prcb->KeByteWordEmulationCount; 02018 #endif // defined(_ALPHA_) 02019 } 02020 } 02021 02022 ExceptionInformation->AlignmentFixupCount = AlignmentFixupCount; 02023 ExceptionInformation->ExceptionDispatchCount = ExceptionDispatchCount; 02024 ExceptionInformation->FloatingEmulationCount = FloatingEmulationCount; 02025 ExceptionInformation->ByteWordEmulationCount = ByteWordEmulationCount; 02026 } 02027 02028 break; 02029 02030 case SystemCrashDumpStateInformation: 02031 02032 if (SystemInformationLength < sizeof( SYSTEM_CRASH_STATE_INFORMATION)) { 02033 return STATUS_INFO_LENGTH_MISMATCH; 02034 } 02035 02036 Status = MmGetCrashDumpStateInformation ( 02037 (PSYSTEM_CRASH_STATE_INFORMATION)SystemInformation); 02038 02039 if ( NT_SUCCESS( Status ) ) { 02040 if (SystemInformationLength >= sizeof (SYSTEM_CRASH_STATE_INFORMATION) ) { 02041 Status = IoGetCrashDumpStateInformation ( 02042 (PSYSTEM_CRASH_STATE_INFORMATION)SystemInformation); 02043 } 02044 } 02045 02046 if (ARGUMENT_PRESENT( ReturnLength )) { 02047 *ReturnLength = sizeof(SYSTEM_CRASH_STATE_INFORMATION); 02048 } 02049 02050 break; 02051 02052 case SystemKernelDebuggerInformation: 02053 02054 if (SystemInformationLength < sizeof( SYSTEM_KERNEL_DEBUGGER_INFORMATION)) { 02055 return STATUS_INFO_LENGTH_MISMATCH; 02056 } 02057 02058 KernelDebuggerInformation = 02059 (PSYSTEM_KERNEL_DEBUGGER_INFORMATION)SystemInformation; 02060 KernelDebuggerInformation->KernelDebuggerEnabled = KdDebuggerEnabled; 02061 KernelDebuggerInformation->KernelDebuggerNotPresent = KdDebuggerNotPresent; 02062 02063 if (ARGUMENT_PRESENT( ReturnLength )) { 02064 *ReturnLength = sizeof(SYSTEM_KERNEL_DEBUGGER_INFORMATION); 02065 } 02066 02067 break; 02068 02069 case SystemContextSwitchInformation: 02070 02071 if (SystemInformationLength < sizeof( SYSTEM_CONTEXT_SWITCH_INFORMATION)) { 02072 return STATUS_INFO_LENGTH_MISMATCH; 02073 } 02074 02075 ContextSwitchInformation = 02076 (PSYSTEM_CONTEXT_SWITCH_INFORMATION)SystemInformation; 02077 02078 // 02079 // Compute the total number of context switches and fill in the 02080 // remainder of the context switch information. 02081 // 02082 02083 ContextSwitches = 0; 02084 for (i = 0; i < (ULONG)KeNumberProcessors; i += 1) { 02085 Prcb = KiProcessorBlock[i]; 02086 if (Prcb != NULL) { 02087 ContextSwitches += Prcb->KeContextSwitches; 02088 } 02089 02090 } 02091 02092 ContextSwitchInformation->ContextSwitches = ContextSwitches; 02093 ContextSwitchInformation->FindAny = KeThreadSwitchCounters.FindAny; 02094 ContextSwitchInformation->FindLast = KeThreadSwitchCounters.FindLast; 02095 ContextSwitchInformation->FindIdeal = KeThreadSwitchCounters.FindIdeal; 02096 ContextSwitchInformation->IdleAny = KeThreadSwitchCounters.IdleAny; 02097 ContextSwitchInformation->IdleCurrent = KeThreadSwitchCounters.IdleCurrent; 02098 ContextSwitchInformation->IdleLast = KeThreadSwitchCounters.IdleLast; 02099 ContextSwitchInformation->IdleIdeal = KeThreadSwitchCounters.IdleIdeal; 02100 ContextSwitchInformation->PreemptAny = KeThreadSwitchCounters.PreemptAny; 02101 ContextSwitchInformation->PreemptCurrent = KeThreadSwitchCounters.PreemptCurrent; 02102 ContextSwitchInformation->PreemptLast = KeThreadSwitchCounters.PreemptLast; 02103 ContextSwitchInformation->SwitchToIdle = KeThreadSwitchCounters.SwitchToIdle; 02104 02105 if (ARGUMENT_PRESENT( ReturnLength )) { 02106 *ReturnLength = sizeof(SYSTEM_CONTEXT_SWITCH_INFORMATION); 02107 } 02108 02109 break; 02110 02111 case SystemRegistryQuotaInformation: 02112 02113 if (SystemInformationLength < sizeof( SYSTEM_REGISTRY_QUOTA_INFORMATION)) { 02114 return(STATUS_INFO_LENGTH_MISMATCH); 02115 } 02116 CmQueryRegistryQuotaInformation((PSYSTEM_REGISTRY_QUOTA_INFORMATION)SystemInformation); 02117 02118 if (ARGUMENT_PRESENT( ReturnLength )) { 02119 *ReturnLength = sizeof(SYSTEM_REGISTRY_QUOTA_INFORMATION); 02120 } 02121 break; 02122 02123 case SystemDpcBehaviorInformation: 02124 { 02125 PSYSTEM_DPC_BEHAVIOR_INFORMATION DpcInfo; 02126 // 02127 // If the system information buffer is not the correct length, 02128 // then return an error. 02129 // 02130 if (SystemInformationLength != sizeof(SYSTEM_DPC_BEHAVIOR_INFORMATION)) { 02131 return STATUS_INFO_LENGTH_MISMATCH; 02132 } 02133 02134 DpcInfo = (PSYSTEM_DPC_BEHAVIOR_INFORMATION)SystemInformation; 02135 02136 // 02137 // Exception handler for this routine will return the correct 02138 // error if any of these accesses fail. 02139 // 02140 // 02141 // Return the current DPC behavior variables 02142 // 02143 DpcInfo->DpcQueueDepth = KiMaximumDpcQueueDepth; 02144 DpcInfo->MinimumDpcRate = KiMinimumDpcRate; 02145 DpcInfo->AdjustDpcThreshold = KiAdjustDpcThreshold; 02146 DpcInfo->IdealDpcRate = KiIdealDpcRate; 02147 } 02148 break; 02149 02150 case SystemInterruptInformation: 02151 02152 if (SystemInformationLength < (sizeof(SYSTEM_INTERRUPT_INFORMATION) * KeNumberProcessors)) { 02153 return(STATUS_INFO_LENGTH_MISMATCH); 02154 } 02155 02156 InterruptInformation = (PSYSTEM_INTERRUPT_INFORMATION)SystemInformation; 02157 for (i=0; i < (ULONG)KeNumberProcessors; i++) { 02158 Prcb = KiProcessorBlock[i]; 02159 InterruptInformation->ContextSwitches = Prcb->KeContextSwitches; 02160 InterruptInformation->DpcCount = Prcb->DpcCount; 02161 InterruptInformation->DpcRate = Prcb->DpcRequestRate; 02162 InterruptInformation->TimeIncrement = KeTimeIncrement; 02163 InterruptInformation->DpcBypassCount = Prcb->DpcBypassCount; 02164 InterruptInformation->ApcBypassCount = Prcb->ApcBypassCount; 02165 02166 ++InterruptInformation; 02167 } 02168 02169 break; 02170 02171 case SystemCurrentTimeZoneInformation: 02172 if (SystemInformationLength < sizeof( RTL_TIME_ZONE_INFORMATION )) { 02173 return STATUS_INFO_LENGTH_MISMATCH; 02174 } 02175 02176 RtlCopyMemory(SystemInformation,&ExpTimeZoneInformation,sizeof(ExpTimeZoneInformation)); 02177 if (ARGUMENT_PRESENT( ReturnLength )) { 02178 *ReturnLength = sizeof( RTL_TIME_ZONE_INFORMATION ); 02179 } 02180 02181 Status = STATUS_SUCCESS; 02182 break; 02183 02184 // 02185 // Query pool lookaside list and general lookaside list 02186 // information. 02187 // 02188 02189 case SystemLookasideInformation: 02190 Status = ExpGetLookasideInformation(SystemInformation, 02191 SystemInformationLength, 02192 &Length); 02193 02194 if (ARGUMENT_PRESENT(ReturnLength)) { 02195 *ReturnLength = Length; 02196 } 02197 02198 break; 02199 02200 case SystemRangeStartInformation: 02201 02202 if ( SystemInformationLength != sizeof(ULONG_PTR) ) { 02203 return STATUS_INFO_LENGTH_MISMATCH; 02204 } 02205 02206 *(PULONG_PTR)SystemInformation = (ULONG_PTR)MmSystemRangeStart; 02207 02208 if (ARGUMENT_PRESENT(ReturnLength) ) { 02209 *ReturnLength = sizeof(ULONG_PTR); 02210 } 02211 02212 break; 02213 02214 case SystemVerifierInformation: 02215 02216 if (SystemInformationLength < sizeof( SYSTEM_VERIFIER_INFORMATION )) { 02217 return STATUS_INFO_LENGTH_MISMATCH; 02218 } 02219 02220 Status = MmGetVerifierInformation( SystemInformation, 02221 SystemInformationLength, 02222 &Length 02223 ); 02224 02225 if (ARGUMENT_PRESENT( ReturnLength )) { 02226 *ReturnLength = Length; 02227 } 02228 break; 02229 02230 case SystemLegacyDriverInformation: 02231 if (SystemInformationLength < sizeof(SYSTEM_LEGACY_DRIVER_INFORMATION)) { 02232 return(STATUS_INFO_LENGTH_MISMATCH); 02233 } 02234 Length = SystemInformationLength; 02235 Status = ExpQueryLegacyDriverInformation((PSYSTEM_LEGACY_DRIVER_INFORMATION)SystemInformation, &Length); 02236 if (ARGUMENT_PRESENT(ReturnLength)) { 02237 *ReturnLength = Length; 02238 } 02239 break; 02240 02241 default: 02242 02243 // 02244 // Invalid argument. 02245 // 02246 02247 return STATUS_INVALID_INFO_CLASS; 02248 } 02249 02250 } except (EXCEPTION_EXECUTE_HANDLER) { 02251 if (ReleaseModuleResoure) { 02252 ExReleaseResource (&PsLoadedModuleResource); 02253 KeLeaveCriticalRegion(); 02254 } 02255 02256 Status = GetExceptionCode(); 02257 } 02258 02259 return Status; 02260 } 02261 02262 NTSTATUS 02263 NTAPI 02264 NtSetSystemInformation ( 02265 IN SYSTEM_INFORMATION_CLASS SystemInformationClass, 02266 IN PVOID SystemInformation, 02267 IN ULONG SystemInformationLength 02268 ) 02269 02270 /*++ 02271 02272 Routine Description: 02273 02274 This function set information about the system. 02275 02276 Arguments: 02277 02278 SystemInformationClass - The system information class which is to 02279 be modified. 02280 02281 SystemInformation - A pointer to a buffer which contains the specified 02282 information. The format and content of the buffer depend on the 02283 specified system information class. 02284 02285 02286 SystemInformationLength - Specifies the length in bytes of the system 02287 information buffer. 02288 02289 Return Value: 02290 02291 Returns one of the following status codes: 02292 02293 STATUS_SUCCESS - Normal, successful completion. 02294 02295 STATUS_ACCESS_VIOLATION - The specified system information buffer 02296 is not accessible. 02297 02298 STATUS_INVALID_INFO_CLASS - The SystemInformationClass parameter 02299 did not specify a valid value. 02300 02301 STATUS_INFO_LENGTH_MISMATCH - The value of the SystemInformationLength 02302 parameter did not match the length required for the information 02303 class requested by the SystemInformationClass parameter. 02304 02305 STATUS_PRIVILEGE_NOT_HELD is returned if the caller does not have the 02306 privilege to set the system time. 02307 02308 --*/ 02309 02310 { 02311 02312 BOOLEAN Enable; 02313 KPROCESSOR_MODE PreviousMode; 02314 NTSTATUS Status; 02315 ULONG TimeAdjustment; 02316 PSYSTEM_SET_TIME_ADJUST_INFORMATION TimeAdjustmentInformation; 02317 HANDLE EventHandle; 02318 PVOID Event; 02319 02320 PAGED_CODE(); 02321 02322 // 02323 // Establish an exception handle in case the system information buffer 02324 // is not accessible. 02325 // 02326 02327 Status = STATUS_SUCCESS; 02328 02329 try { 02330 02331 // 02332 // Get the previous processor mode and probe the input buffer for 02333 // read access if necessary. 02334 // 02335 02336 PreviousMode = KeGetPreviousMode(); 02337 if (PreviousMode != KernelMode) { 02338 ProbeForRead((PVOID)SystemInformation, 02339 SystemInformationLength, 02340 sizeof(ULONG)); 02341 } 02342 02343 // 02344 // Dispatch on the system information class. 02345 // 02346 02347 switch (SystemInformationClass) { 02348 case SystemFlagsInformation: 02349 if (SystemInformationLength != sizeof( SYSTEM_FLAGS_INFORMATION )) { 02350 return STATUS_INFO_LENGTH_MISMATCH; 02351 } 02352 02353 if (!SeSinglePrivilegeCheck( SeDebugPrivilege, PreviousMode )) { 02354 return STATUS_ACCESS_DENIED; 02355 } 02356 else { 02357 NtGlobalFlag = ((PSYSTEM_FLAGS_INFORMATION)SystemInformation)->Flags & FLG_KERNELMODE_VALID_BITS; 02358 ((PSYSTEM_FLAGS_INFORMATION)SystemInformation)->Flags = NtGlobalFlag; 02359 } 02360 break; 02361 02362 // 02363 // Set system time adjustment information. 02364 // 02365 // N.B. The caller must have the SeSystemTime privilege. 02366 // 02367 02368 case SystemTimeAdjustmentInformation: 02369 02370 // 02371 // If the system information buffer is not the correct length, 02372 // then return an error. 02373 // 02374 02375 if (SystemInformationLength != sizeof( SYSTEM_SET_TIME_ADJUST_INFORMATION )) { 02376 return STATUS_INFO_LENGTH_MISMATCH; 02377 } 02378 02379 // 02380 // If the current thread does not have the privilege to set the 02381 // time adjustment variables, then return an error. 02382 // 02383 02384 if ((PreviousMode != KernelMode) && 02385 (SeSinglePrivilegeCheck(SeSystemtimePrivilege, PreviousMode) == FALSE)) { 02386 return STATUS_PRIVILEGE_NOT_HELD; 02387 } 02388 02389 // 02390 // Set system time adjustment parameters. 02391 // 02392 02393 TimeAdjustmentInformation = 02394 (PSYSTEM_SET_TIME_ADJUST_INFORMATION)SystemInformation; 02395 02396 Enable = TimeAdjustmentInformation->Enable; 02397 TimeAdjustment = TimeAdjustmentInformation->TimeAdjustment; 02398 02399 if (Enable == TRUE) { 02400 KeTimeAdjustment = KeMaximumIncrement; 02401 } else { 02402 if (TimeAdjustment == 0) { 02403 return STATUS_INVALID_PARAMETER_2; 02404 } 02405 KeTimeAdjustment = TimeAdjustment; 02406 } 02407 02408 KeTimeSynchronization = Enable; 02409 break; 02410 02411 // 02412 // Set an event to signal when the clock interrupt has been 02413 // masked for too long, causing the time to slip. 02414 // The event will be referenced to prevent it from being 02415 // deleted. If the new event handle is valid or NULL, the 02416 // old event will be dereferenced and forgotten. If the 02417 // event handle is non-NULL but invalid, the old event will 02418 // be remembered and a failure status will be returned. 02419 // 02420 // N.B. The caller must have the SeSystemTime privilege. 02421 // 02422 case SystemTimeSlipNotification: 02423 02424 if (SystemInformationLength != sizeof(HANDLE)) { 02425 return STATUS_INFO_LENGTH_MISMATCH; 02426 } 02427 02428 // 02429 // If the current thread does not have the privilege to set the 02430 // time adjustment variables, then return an error. 02431 // 02432 02433 if ((PreviousMode != KernelMode) && 02434 (SeSinglePrivilegeCheck(SeSystemtimePrivilege, PreviousMode) == FALSE)) { 02435 return STATUS_PRIVILEGE_NOT_HELD; 02436 } 02437 02438 EventHandle = *(PHANDLE)SystemInformation; 02439 02440 if (EventHandle == NULL) { 02441 02442 // 02443 // Dereference the old event and don't signal anything 02444 // for time slips. 02445 // 02446 02447 Event = NULL; 02448 Status = STATUS_SUCCESS; 02449 02450 } else { 02451 02452 Status = ObReferenceObjectByHandle(EventHandle, 02453 EVENT_MODIFY_STATE, 02454 ExEventObjectType, 02455 PreviousMode, 02456 &Event, 02457 NULL); 02458 } 02459 02460 if (NT_SUCCESS(Status)) { 02461 KdUpdateTimeSlipEvent(Event); 02462 } 02463 02464 break; 02465 02466 // 02467 // Set registry quota limit. 02468 // 02469 // N.B. The caller must have SeIncreaseQuotaPrivilege 02470 // 02471 case SystemRegistryQuotaInformation: 02472 02473 // 02474 // If the system information buffer is not the correct length, 02475 // then return an error. 02476 // 02477 02478 if (SystemInformationLength != sizeof( SYSTEM_REGISTRY_QUOTA_INFORMATION )) { 02479 return STATUS_INFO_LENGTH_MISMATCH; 02480 } 02481 02482 // 02483 // If the current thread does not have the privilege to create 02484 // a pagefile, then return an error. 02485 // 02486 02487 if ((PreviousMode != KernelMode) && 02488 (SeSinglePrivilegeCheck(SeIncreaseQuotaPrivilege, PreviousMode) == FALSE)) { 02489 return STATUS_PRIVILEGE_NOT_HELD; 02490 } 02491 02492 // 02493 // Set registry quota parameters. 02494 // 02495 CmSetRegistryQuotaInformation((PSYSTEM_REGISTRY_QUOTA_INFORMATION)SystemInformation); 02496 02497 break; 02498 02499 case SystemPrioritySeperation: 02500 { 02501 ULONG PrioritySeparation; 02502 02503 // 02504 // If the system information buffer is not the correct length, 02505 // then return an error. 02506 // 02507 02508 if (SystemInformationLength != sizeof( ULONG )) { 02509 return STATUS_INFO_LENGTH_MISMATCH; 02510 } 02511 02512 try { 02513 PrioritySeparation = *(PULONG)SystemInformation; 02514 } 02515 except(EXCEPTION_EXECUTE_HANDLER) { 02516 return GetExceptionCode(); 02517 } 02518 02519 PsChangeQuantumTable(TRUE,PrioritySeparation); 02520 Status = STATUS_SUCCESS; 02521 } 02522 break; 02523 02524 case SystemExtendServiceTableInformation: 02525 { 02526 02527 UNICODE_STRING Image; 02528 PWSTR Buffer; 02529 PVOID ImageBaseAddress; 02530 ULONG_PTR EntryPoint; 02531 PVOID SectionPointer; 02532 PIMAGE_NT_HEADERS NtHeaders; 02533 PDRIVER_INITIALIZE InitRoutine; 02534 DRIVER_OBJECT Win32KDevice; 02535 02536 // 02537 // If the system information buffer is not the correct length, 02538 // then return an error. 02539 // 02540 02541 if (SystemInformationLength != sizeof( UNICODE_STRING ) ) { 02542 return STATUS_INFO_LENGTH_MISMATCH; 02543 } 02544 02545 if (PreviousMode != KernelMode) { 02546 02547 // 02548 // The caller's access mode is not kernel so check to ensure that 02549 // the caller has the privilege to load a driver. 02550 // 02551 02552 if (!SeSinglePrivilegeCheck( SeLoadDriverPrivilege, PreviousMode )) { 02553 return STATUS_PRIVILEGE_NOT_HELD; 02554 } 02555 02556 try { 02557 UNICODE_STRING tImage; 02558 USHORT maxLength; 02559 02560 Buffer = NULL; 02561 tImage = *(PUNICODE_STRING)SystemInformation; 02562 02563 // 02564 // Leave room for the NUL, if possible. 02565 // Guard against overflow. 02566 // 02567 maxLength = tImage.Length + sizeof(UNICODE_NULL); 02568 if (maxLength < tImage.Length || maxLength > tImage.MaximumLength) { 02569 maxLength = tImage.Length; 02570 } 02571 02572 ProbeForRead(tImage.Buffer, maxLength, sizeof(UCHAR)); 02573 02574 Buffer = ExAllocatePoolWithTag(PagedPool, maxLength, 'ofnI'); 02575 if ( !Buffer ) { 02576 return STATUS_NO_MEMORY; 02577 } 02578 02579 RtlCopyMemory(Buffer, tImage.Buffer, tImage.Length); 02580 Image.Buffer = Buffer; 02581 Image.Length = tImage.Length; 02582 Image.MaximumLength = maxLength; 02583 } 02584 except(EXCEPTION_EXECUTE_HANDLER) { 02585 if ( Buffer ) { 02586 ExFreePool(Buffer); 02587 } 02588 return GetExceptionCode(); 02589 } 02590 02591 // 02592 // Call MmLoadSystemImage with previous mode of kernel. 02593 // 02594 02595 Status = ZwSetSystemInformation( 02596 SystemExtendServiceTableInformation, 02597 (PVOID)&Image, 02598 sizeof(Image) 02599 ); 02600 02601 ExFreePool(Buffer); 02602 02603 return Status; 02604 02605 } 02606 02607 Image = *(PUNICODE_STRING)SystemInformation; 02608 02609 // 02610 // Now in kernelmode, so load the driver. 02611 // 02612 02613 Status = MmLoadSystemImage (&Image, 02614 NULL, 02615 NULL, 02616 TRUE, 02617 &SectionPointer, 02618 (PVOID *) &ImageBaseAddress); 02619 02620 if (!NT_SUCCESS (Status)) { 02621 return Status; 02622 } 02623 02624 NtHeaders = RtlImageNtHeader( ImageBaseAddress ); 02625 EntryPoint = NtHeaders->OptionalHeader.AddressOfEntryPoint; 02626 EntryPoint += (ULONG_PTR) ImageBaseAddress; 02627 InitRoutine = (PDRIVER_INITIALIZE) EntryPoint; 02628 02629 RtlZeroMemory (&Win32KDevice, sizeof(Win32KDevice)); 02630 ASSERT (KeGetCurrentIrql() == 0); 02631 02632 Status = (InitRoutine)(&Win32KDevice,NULL); 02633 02634 ASSERT (KeGetCurrentIrql() == 0); 02635 02636 if (!NT_SUCCESS (Status)) { 02637 MmUnloadSystemImage (SectionPointer); 02638 } 02639 else { 02640 02641 // 02642 // Pass the driver object to memory management so the 02643 // session can be unloaded cleanly. 02644 // 02645 02646 MmSessionSetUnloadAddress (&Win32KDevice); 02647 } 02648 } 02649 break; 02650 02651 02652 case SystemUnloadGdiDriverInformation: 02653 { 02654 02655 if (SystemInformationLength != sizeof( PVOID ) ) { 02656 return STATUS_INFO_LENGTH_MISMATCH; 02657 } 02658 02659 if (PreviousMode != KernelMode) { 02660 02661 // 02662 // The caller's access mode is not kernel so fail. 02663 // Only GDI from the kernel can call this. 02664 // 02665 02666 return STATUS_PRIVILEGE_NOT_HELD; 02667 02668 } 02669 02670 MmUnloadSystemImage( *((PVOID *)SystemInformation) ); 02671 02672 Status = STATUS_SUCCESS; 02673 02674 } 02675 break; 02676 02677 02678 case SystemLoadGdiDriverInformation: 02679 { 02680 02681 UNICODE_STRING Image; 02682 PVOID ImageBaseAddress; 02683 ULONG_PTR EntryPoint; 02684 PVOID SectionPointer; 02685 02686 PIMAGE_NT_HEADERS NtHeaders; 02687 02688 // 02689 // If the system information buffer is not the correct length, 02690 // then return an error. 02691 // 02692 02693 if (SystemInformationLength != sizeof( SYSTEM_GDI_DRIVER_INFORMATION ) ) { 02694 return STATUS_INFO_LENGTH_MISMATCH; 02695 } 02696 02697 if (PreviousMode != KernelMode) { 02698 02699 // 02700 // The caller's access mode is not kernel so fail. 02701 // Only GDI from the kernel can call this. 02702 // 02703 02704 return STATUS_PRIVILEGE_NOT_HELD; 02705 } 02706 02707 Image = ((PSYSTEM_GDI_DRIVER_INFORMATION)SystemInformation)->DriverName; 02708 Status = MmLoadSystemImage (&Image, 02709 NULL, 02710 NULL, 02711 TRUE, 02712 &SectionPointer, 02713 (PVOID *) &ImageBaseAddress); 02714 02715 // 02716 // Some drivers (like dxapi.sys) may be already loaded by a 02717 // minidriver that links to it - allow these to re-succeed. 02718 // 02719 02720 if ((NT_SUCCESS( Status )) || 02721 (Status == STATUS_IMAGE_ALREADY_LOADED)) { 02722 02723 PSYSTEM_GDI_DRIVER_INFORMATION GdiDriverInfo = 02724 (PSYSTEM_GDI_DRIVER_INFORMATION) SystemInformation; 02725 02726 ULONG Size; 02727 PVOID BaseAddress; 02728 02729 GdiDriverInfo->ExportSectionPointer = 02730 RtlImageDirectoryEntryToData(ImageBaseAddress, 02731 TRUE, 02732 IMAGE_DIRECTORY_ENTRY_EXPORT, 02733 &Size); 02734 02735 // 02736 // Capture the entry point. 02737 // 02738 02739 NtHeaders = RtlImageNtHeader( ImageBaseAddress ); 02740 EntryPoint = NtHeaders->OptionalHeader.AddressOfEntryPoint; 02741 EntryPoint += (ULONG_PTR) ImageBaseAddress; 02742 02743 GdiDriverInfo->ImageAddress = (PVOID) ImageBaseAddress; 02744 GdiDriverInfo->SectionPointer = SectionPointer; 02745 GdiDriverInfo->EntryPoint = (PVOID) EntryPoint; 02746 02747 // 02748 // GDI drivers are always completely pagable. 02749 // 02750 02751 if (NT_SUCCESS( Status )) { 02752 BaseAddress = MmPageEntireDriver((PVOID)ImageBaseAddress); 02753 ASSERT(BaseAddress == ImageBaseAddress); 02754 } 02755 } 02756 } 02757 break; 02758 02759 case SystemFileCacheInformation: 02760 02761 if (SystemInformationLength < sizeof( SYSTEM_FILECACHE_INFORMATION )) { 02762 return STATUS_INFO_LENGTH_MISMATCH; 02763 } 02764 02765 if (!SeSinglePrivilegeCheck( SeIncreaseQuotaPrivilege, PreviousMode )) { 02766 return STATUS_ACCESS_DENIED; 02767 } 02768 02769 return MmAdjustWorkingSetSize ( 02770 ((PSYSTEM_FILECACHE_INFORMATION)SystemInformation)->MinimumWorkingSet, 02771 ((PSYSTEM_FILECACHE_INFORMATION)SystemInformation)->MaximumWorkingSet, 02772 TRUE); 02773 02774 break; 02775 02776 case SystemDpcBehaviorInformation: 02777 { 02778 SYSTEM_DPC_BEHAVIOR_INFORMATION DpcInfo; 02779 // 02780 // If the system information buffer is not the correct length, 02781 // then return an error. 02782 // 02783 if (SystemInformationLength != sizeof(SYSTEM_DPC_BEHAVIOR_INFORMATION)) { 02784 return STATUS_INFO_LENGTH_MISMATCH; 02785 } 02786 02787 if (PreviousMode != KernelMode) { 02788 // 02789 // The caller's access mode is not kernel so check to ensure that 02790 // the caller has the privilege to load a driver. 02791 // 02792 02793 if (!SeSinglePrivilegeCheck( SeLoadDriverPrivilege, PreviousMode )) { 02794 return STATUS_PRIVILEGE_NOT_HELD; 02795 } 02796 } 02797 02798 // 02799 // Exception handler for this routine will return the correct 02800 // error if this access fails. 02801 // 02802 DpcInfo = *(PSYSTEM_DPC_BEHAVIOR_INFORMATION)SystemInformation; 02803 02804 // 02805 // Set the new DPC behavior variables 02806 // 02807 KiMaximumDpcQueueDepth = DpcInfo.DpcQueueDepth; 02808 KiMinimumDpcRate = DpcInfo.MinimumDpcRate; 02809 KiAdjustDpcThreshold = DpcInfo.AdjustDpcThreshold; 02810 KiIdealDpcRate = DpcInfo.IdealDpcRate; 02811 } 02812 break; 02813 02814 case SystemSessionCreate: 02815 { 02816 02817 // 02818 // Creation of a session space. 02819 // 02820 02821 ULONG SessionId; 02822 02823 // 02824 // If the system information buffer is not the correct length, 02825 // then return an error. 02826 // 02827 02828 if (SystemInformationLength != sizeof(ULONG)) { 02829 return STATUS_INFO_LENGTH_MISMATCH; 02830 } 02831 02832 if (PreviousMode != KernelMode) { 02833 02834 // 02835 // The caller's access mode is not kernel so check to 02836 // ensure that the caller has the privilege to load 02837 // a driver. 02838 // 02839 02840 if (!SeSinglePrivilegeCheck (SeLoadDriverPrivilege, PreviousMode)) { 02841 return STATUS_PRIVILEGE_NOT_HELD; 02842 } 02843 02844 try { 02845 ProbeForWriteUlong((PULONG)SystemInformation); 02846 } 02847 except (EXCEPTION_EXECUTE_HANDLER) { 02848 return GetExceptionCode(); 02849 } 02850 } 02851 02852 // 02853 // Create a session space in the current process. 02854 // 02855 02856 Status = MmSessionCreate (&SessionId); 02857 02858 if (NT_SUCCESS(Status)) { 02859 if (PreviousMode != KernelMode) { 02860 try { 02861 *(PULONG)SystemInformation = SessionId; 02862 } 02863 except (EXCEPTION_EXECUTE_HANDLER) { 02864 return GetExceptionCode(); 02865 } 02866 } 02867 else { 02868 *(PULONG)SystemInformation = SessionId; 02869 } 02870 } 02871 02872 return Status; 02873 } 02874 break; 02875 02876 case SystemSessionDetach: 02877 { 02878 ULONG SessionId; 02879 02880 // 02881 // If the system information buffer is not the correct length, 02882 // then return an error. 02883 // 02884 02885 if (SystemInformationLength != sizeof(ULONG)) { 02886 return STATUS_INFO_LENGTH_MISMATCH; 02887 } 02888 02889 if (PreviousMode != KernelMode) { 02890 02891 // 02892 // The caller's access mode is not kernel so check to 02893 // ensure that the caller has the privilege to load 02894 // a driver. 02895 // 02896 02897 if (!SeSinglePrivilegeCheck( SeLoadDriverPrivilege, PreviousMode )) { 02898 return STATUS_PRIVILEGE_NOT_HELD; 02899 } 02900 02901 try { 02902 ProbeForRead ((PVOID)SystemInformation, 02903 sizeof(ULONG), 02904 sizeof(ULONG)); 02905 02906 SessionId = *(PULONG)SystemInformation; 02907 } 02908 except (EXCEPTION_EXECUTE_HANDLER) { 02909 return GetExceptionCode(); 02910 } 02911 } 02912 else { 02913 SessionId = *(PULONG)SystemInformation; 02914 } 02915 02916 // 02917 // Detach the current process from a session space 02918 // if it has one. 02919 // 02920 02921 Status = MmSessionDelete (SessionId); 02922 02923 return Status; 02924 } 02925 break; 02926 02927 case SystemCrashDumpStateInformation: 02928 02929 02930 if (SystemInformationLength < sizeof( SYSTEM_CRASH_STATE_INFORMATION)) { 02931 return STATUS_INFO_LENGTH_MISMATCH; 02932 } 02933 02934 if (!SeSinglePrivilegeCheck( SeCreatePagefilePrivilege, PreviousMode )) { 02935 return STATUS_ACCESS_DENIED; 02936 } 02937 02938 Status = IoSetCrashDumpState( (SYSTEM_CRASH_STATE_INFORMATION *)SystemInformation); 02939 02940 break; 02941 02942 case SystemPerformanceTraceInformation: 02943 #ifdef NTPERF 02944 Status = PerformanceTraceInformation(SystemInformationClass, 02945 SystemInformation, 02946 SystemInformationLength 02947 ); 02948 #else 02949 Status = STATUS_INVALID_INFO_CLASS; 02950 #endif 02951 break; 02952 02953 case SystemVerifierThunkExtend: 02954 02955 if (PreviousMode != KernelMode) { 02956 02957 // 02958 // The caller's access mode is not kernel so fail. 02959 // Only device drivers can call this. 02960 // 02961 02962 return STATUS_PRIVILEGE_NOT_HELD; 02963 } 02964 02965 Status = MmAddVerifierThunks (SystemInformation, 02966 SystemInformationLength); 02967 02968 break; 02969 02970 case SystemVerifierInformation: 02971 02972 if (!SeSinglePrivilegeCheck (SeDebugPrivilege, PreviousMode)) { 02973 return STATUS_ACCESS_DENIED; 02974 } 02975 02976 Status = MmSetVerifierInformation (SystemInformation, 02977 SystemInformationLength); 02978 02979 break; 02980 02981 default: 02982 //KeBugCheckEx(SystemInformationClass,KdPitchDebugger,0,0,0); 02983 Status = STATUS_INVALID_INFO_CLASS; 02984 break; 02985 } 02986 02987 } except (EXCEPTION_EXECUTE_HANDLER) { 02988 Status = GetExceptionCode(); 02989 } 02990 02991 return Status; 02992 } 02993 02994 PVOID 02995 ExLockUserBuffer( 02996 IN PVOID Buffer, 02997 IN ULONG Length, 02998 OUT PVOID *LockVariable 02999 ) 03000 03001 { 03002 PMDL Mdl; 03003 PVOID Address; 03004 SIZE_T MdlSize; 03005 03006 // 03007 // Allocate an MDL to map the request. 03008 // 03009 03010 MdlSize = MmSizeOfMdl( Buffer, Length ); 03011 Mdl = ExAllocatePoolWithQuotaTag (NonPagedPool, 03012 MdlSize, 03013 'ofnI'); 03014 if (Mdl == NULL) { 03015 return NULL; 03016 } 03017 03018 // 03019 // Initialize MDL for request. 03020 // 03021 03022 MmInitializeMdl(Mdl, Buffer, Length); 03023 03024 try { 03025 03026 MmProbeAndLockPages (Mdl, KeGetPreviousMode(), IoWriteAccess); 03027 03028 } except (EXCEPTION_EXECUTE_HANDLER) { 03029 03030 ExFreePool (Mdl); 03031 03032 return( NULL ); 03033 } 03034 03035 Mdl->MdlFlags |= MDL_MAPPING_CAN_FAIL; 03036 Address = MmGetSystemAddressForMdl (Mdl); 03037 *LockVariable = Mdl; 03038 if (Address == NULL) { 03039 ExUnlockUserBuffer (Mdl); 03040 *LockVariable = NULL; 03041 } 03042 03043 return Address; 03044 } 03045 03046 03047 VOID 03048 ExUnlockUserBuffer( 03049 IN PVOID LockVariable 03050 ) 03051 03052 { 03053 MmUnlockPages ((PMDL)LockVariable); 03054 ExFreePool ((PMDL)LockVariable); 03055 return; 03056 } 03057 03058 extern FAST_MUTEX PspActiveProcessMutex; 03059 NTSTATUS 03060 ExpGetProcessInformation ( 03061 OUT PVOID SystemInformation, 03062 IN ULONG SystemInformationLength, 03063 OUT PULONG Length, 03064 IN PULONG SessionId OPTIONAL 03065 ) 03066 /*++ 03067 03068 Routine Description: 03069 03070 This function returns information about all the processes and 03071 threads in the system. 03072 03073 Arguments: 03074 03075 SystemInformation - A pointer to a buffer which receives the specified 03076 information. 03077 03078 SystemInformationLength - Specifies the length in bytes of the system 03079 information buffer. 03080 03081 Length - An optional pointer which, if specified, receives the 03082 number of bytes placed in the system information buffer. 03083 03084 03085 Return Value: 03086 03087 Returns one of the following status codes: 03088 03089 STATUS_SUCCESS - normal, successful completion. 03090 03091 STATUS_INVALID_INFO_CLASS - The SystemInformationClass parameter 03092 did not specify a valid value. 03093 03094 STATUS_INFO_LENGTH_MISMATCH - The value of the SystemInformationLength 03095 parameter did not match the length required for the information 03096 class requested by the SystemInformationClass parameter. 03097 03098 STATUS_ACCESS_VIOLATION - Either the SystemInformation buffer pointer 03099 or the Length pointer value specified an invalid address. 03100 03101 STATUS_WORKING_SET_QUOTA - The process does not have sufficient 03102 working set to lock the specified output structure in memory. 03103 03104 STATUS_INSUFFICIENT_RESOURCES - Insufficient system resources exist 03105 for this request to complete. 03106 03107 --*/ 03108 03109 { 03110 KEVENT Event; 03111 PEPROCESS Process; 03112 PETHREAD Thread; 03113 PSYSTEM_PROCESS_INFORMATION ProcessInfo; 03114 PSYSTEM_THREAD_INFORMATION ThreadInfo; 03115 PLIST_ENTRY NextProcess; 03116 PLIST_ENTRY NextThread; 03117 PVOID MappedAddress; 03118 PVOID LockVariable; 03119 ULONG TotalSize = 0; 03120 ULONG NextEntryOffset = 0; 03121 PUCHAR Src; 03122 PWSTR Dst; 03123 ULONG n; 03124 NTSTATUS status = STATUS_SUCCESS; 03125 03126 *Length = 0; 03127 03128 MappedAddress = ExLockUserBuffer( SystemInformation, 03129 SystemInformationLength, 03130 &LockVariable 03131 ); 03132 if (MappedAddress == NULL) { 03133 return( STATUS_ACCESS_VIOLATION ); 03134 } 03135 MmLockPagableSectionByHandle (ExPageLockHandle); 03136 ExAcquireFastMutex(&PspActiveProcessMutex); 03137 03138 03139 // 03140 // Initialize an event object and then set the event with the wait 03141 // parameter TRUE. This causes the event to be set and control is 03142 // returned with the dispatcher database locked at dispatch IRQL. 03143 // 03144 03145 KeInitializeEvent (&Event, NotificationEvent, FALSE); 03146 try { 03147 03148 03149 ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)MappedAddress; 03150 03151 03152 if (!ARGUMENT_PRESENT(SessionId)) { 03153 03154 NextEntryOffset = sizeof(SYSTEM_PROCESS_INFORMATION); 03155 03156 TotalSize = sizeof(SYSTEM_PROCESS_INFORMATION); 03157 03158 ExpCopyProcessInfo (ProcessInfo, PsIdleProcess); 03159 03160 // 03161 // Since Idle process and system process share the same 03162 // object table, zero out idle processes handle count to 03163 // reduce confusion 03164 // 03165 03166 ProcessInfo->HandleCount = 0; 03167 03168 // Idle Process always has SessionId 0 03169 ProcessInfo->SessionId = 0; 03170 // 03171 // Set the event with the wait 03172 // parameter TRUE. This causes the event to be set and control is 03173 // returned with the dispatcher database locked at dispatch IRQL. 03174 // 03175 // WARNING - The following code assumes that the process structure 03176 // uses kernel objects to synchronize access to the thread and 03177 // process lists. 03178 // 03179 03180 KeSetEvent (&Event, 0, TRUE); 03181 03182 // 03183 // WARNING - The following code runs with the kernel dispatch database 03184 // locked. EXTREME caution should be taken when modifying this 03185 // code. Extended execution will ADVERSELY affect system operation 03186 // and integrity. 03187 // 03188 // Get info for idle process's threads 03189 // 03190 // 03191 // Get information for each thread. 03192 // 03193 03194 ThreadInfo = (PSYSTEM_THREAD_INFORMATION)(ProcessInfo + 1); 03195 ProcessInfo->NumberOfThreads = 0; 03196 NextThread = PsIdleProcess->Pcb.ThreadListHead.Flink; 03197 while (NextThread != &PsIdleProcess->Pcb.ThreadListHead) { 03198 NextEntryOffset += sizeof(SYSTEM_THREAD_INFORMATION); 03199 TotalSize += sizeof(SYSTEM_THREAD_INFORMATION); 03200 03201 if (TotalSize > SystemInformationLength) { 03202 status = STATUS_INFO_LENGTH_MISMATCH; 03203 KeWaitForSingleObject (&Event, Executive, KernelMode, FALSE, NULL); 03204 goto Failed; 03205 } 03206 Thread = (PETHREAD)(CONTAINING_RECORD(NextThread, 03207 KTHREAD, 03208 ThreadListEntry)); 03209 ExpCopyThreadInfo (ThreadInfo,Thread); 03210 03211 ProcessInfo->NumberOfThreads += 1; 03212 NextThread = NextThread->Flink; 03213 ThreadInfo += 1; 03214 } 03215 03216 // 03217 // Unlock the dispatch database by waiting on the event that was 03218 // previously set with the wait parameter TRUE. 03219 // 03220 03221 KeWaitForSingleObject (&Event, Executive, KernelMode, FALSE, NULL); 03222 03223 ProcessInfo->ImageName.Buffer = NULL; 03224 ProcessInfo->ImageName.Length = 0; 03225 ProcessInfo->NextEntryOffset = NextEntryOffset; 03226 } 03227 03228 NextProcess = PsActiveProcessHead.Flink; 03229 03230 while (NextProcess != &PsActiveProcessHead) { 03231 Process = CONTAINING_RECORD(NextProcess, 03232 EPROCESS, 03233 ActiveProcessLinks); 03234 03235 if (ARGUMENT_PRESENT(SessionId) && (Process->SessionId != *SessionId)) { 03236 NextProcess = NextProcess->Flink; 03237 continue; 03238 } 03239 03240 ProcessInfo = (PSYSTEM_PROCESS_INFORMATION) 03241 ((PUCHAR)MappedAddress + TotalSize); 03242 03243 NextEntryOffset = sizeof(SYSTEM_PROCESS_INFORMATION); 03244 TotalSize += sizeof(SYSTEM_PROCESS_INFORMATION); 03245 if (TotalSize > SystemInformationLength) { 03246 status = STATUS_INFO_LENGTH_MISMATCH; 03247 goto Failed; 03248 } 03249 03250 // 03251 // Get information for each process. 03252 // 03253 03254 ExpCopyProcessInfo (ProcessInfo, Process); 03255 03256 03257 // 03258 // Set the event with the wait 03259 // parameter TRUE. This causes the event to be set and control is 03260 // returned with the dispatcher database locked at dispatch IRQL. 03261 // 03262 // WARNING - The following code assumes that the process structure 03263 // uses kernel objects to synchronize access to the thread and 03264 // process lists. 03265 // 03266 03267 KeSetEvent (&Event, 0, TRUE); 03268 03269 // 03270 // WARNING - The following code runs with the kernel dispatch database 03271 // locked. EXTREME caution should be taken when modifying this 03272 // code. Extended execution will ADVERSELY affect system operation 03273 // and integrity. 03274 // 03275 03276 // 03277 // Get information for each thread. 03278 // 03279 03280 ThreadInfo = (PSYSTEM_THREAD_INFORMATION)(ProcessInfo + 1); 03281 ProcessInfo->NumberOfThreads = 0; 03282 NextThread = Process->Pcb.ThreadListHead.Flink; 03283 while (NextThread != &Process->Pcb.ThreadListHead) { 03284 NextEntryOffset += sizeof(SYSTEM_THREAD_INFORMATION); 03285 TotalSize += sizeof(SYSTEM_THREAD_INFORMATION); 03286 03287 if (TotalSize > SystemInformationLength) { 03288 status = STATUS_INFO_LENGTH_MISMATCH; 03289 KeWaitForSingleObject (&Event, Executive, KernelMode, FALSE, NULL); 03290 goto Failed; 03291 } 03292 Thread = (PETHREAD)(CONTAINING_RECORD(NextThread, 03293 KTHREAD, 03294 ThreadListEntry)); 03295 ExpCopyThreadInfo (ThreadInfo,Thread); 03296 03297 ProcessInfo->NumberOfThreads += 1; 03298 NextThread = NextThread->Flink; 03299 ThreadInfo += 1; 03300 } 03301 03302 // 03303 // Store the Remote Terminal SessionId 03304 // 03305 ProcessInfo->SessionId = Process->SessionId; 03306 03307 03308 // 03309 // Unlock the dispatch database by waiting on the event that was 03310 // previously set with the wait parameter TRUE. 03311 // 03312 03313 KeWaitForSingleObject (&Event, Executive, KernelMode, FALSE, NULL); 03314 // 03315 // Get the image name. 03316 // 03317 03318 ProcessInfo->ImageName.Buffer = NULL; 03319 ProcessInfo->ImageName.Length = 0; 03320 ProcessInfo->ImageName.MaximumLength = 0; 03321 03322 if ((n = strlen( Src = Process->ImageFileName ))) { 03323 n = ROUND_UP( ((n + 1) * sizeof( WCHAR )), sizeof(LARGE_INTEGER) ); 03324 TotalSize += n; 03325 NextEntryOffset += n; 03326 if (TotalSize > SystemInformationLength) { 03327 status = STATUS_INFO_LENGTH_MISMATCH; 03328 } else { 03329 Dst = (PWSTR)(ThreadInfo); 03330 while (*Dst++ = (WCHAR)*Src++) { 03331 ; 03332 } 03333 ProcessInfo->ImageName.Length = (USHORT)((PCHAR)Dst - (PCHAR)ThreadInfo - sizeof( UNICODE_NULL )); 03334 ProcessInfo->ImageName.MaximumLength = (USHORT)n; 03335 03336 // 03337 // Set the image name to point into the user's memory. 03338 // 03339 03340 ProcessInfo->ImageName.Buffer = (PWSTR) 03341 ((PCHAR)SystemInformation + 03342 ((PCHAR)(ThreadInfo) - (PCHAR)MappedAddress)); 03343 } 03344 03345 if (!NT_SUCCESS( status )) { 03346 goto Failed; 03347 } 03348 } 03349 03350 // 03351 // Point to next process. 03352 // 03353 03354 ProcessInfo->NextEntryOffset = NextEntryOffset; 03355 NextProcess = NextProcess->Flink; 03356 } 03357 03358 ProcessInfo->NextEntryOffset = 0; 03359 status = STATUS_SUCCESS; 03360 *Length = TotalSize; 03361 03362 Failed: 03363 ; 03364 03365 } finally { 03366 ExReleaseFastMutex(&PspActiveProcessMutex); 03367 MmUnlockPagableImageSection(ExPageLockHandle); 03368 ExUnlockUserBuffer( LockVariable ); 03369 } 03370 03371 return(status); 03372 } 03373 03374 VOID 03375 ExpCopyProcessInfo ( 03376 IN PSYSTEM_PROCESS_INFORMATION ProcessInfo, 03377 IN PEPROCESS Process 03378 ) 03379 03380 { 03381 PHANDLE_TABLE Ht; 03382 03383 PAGED_CODE(); 03384 03385 Ht = (PHANDLE_TABLE)Process->ObjectTable; 03386 if ( Ht ) { 03387 ProcessInfo->HandleCount = Ht->HandleCount; 03388 } 03389 else { 03390 ProcessInfo->HandleCount = 0; 03391 } 03392 ProcessInfo->CreateTime = Process->CreateTime; 03393 ProcessInfo->UserTime.QuadPart = UInt32x32To64(Process->Pcb.UserTime, 03394 KeMaximumIncrement); 03395 03396 ProcessInfo->KernelTime.QuadPart = UInt32x32To64(Process->Pcb.KernelTime, 03397 KeMaximumIncrement); 03398 03399 ProcessInfo->BasePriority = Process->Pcb.BasePriority; 03400 ProcessInfo->UniqueProcessId = Process->UniqueProcessId; 03401 ProcessInfo->InheritedFromUniqueProcessId = Process->InheritedFromUniqueProcessId; 03402 ProcessInfo->PeakVirtualSize = Process->PeakVirtualSize; 03403 ProcessInfo->VirtualSize = Process->VirtualSize; 03404 ProcessInfo->PageFaultCount = Process->Vm.PageFaultCount; 03405 ProcessInfo->PeakWorkingSetSize = Process->Vm.PeakWorkingSetSize << PAGE_SHIFT; 03406 ProcessInfo->WorkingSetSize = Process->Vm.WorkingSetSize << PAGE_SHIFT; 03407 ProcessInfo->QuotaPeakPagedPoolUsage = 03408 Process->QuotaPeakPoolUsage[PagedPool]; 03409 ProcessInfo->QuotaPagedPoolUsage = Process->QuotaPoolUsage[PagedPool]; 03410 ProcessInfo->QuotaPeakNonPagedPoolUsage = 03411 Process->QuotaPeakPoolUsage[NonPagedPool]; 03412 ProcessInfo->QuotaNonPagedPoolUsage = 03413 Process->QuotaPoolUsage[NonPagedPool]; 03414 ProcessInfo->PagefileUsage = Process->PagefileUsage << PAGE_SHIFT; 03415 ProcessInfo->PeakPagefileUsage = Process->PeakPagefileUsage << PAGE_SHIFT; 03416 ProcessInfo->PrivatePageCount = Process->CommitCharge << PAGE_SHIFT; 03417 03418 ProcessInfo->ReadOperationCount = Process->ReadOperationCount; 03419 ProcessInfo->WriteOperationCount = Process->WriteOperationCount; 03420 ProcessInfo->OtherOperationCount = Process->OtherOperationCount; 03421 ProcessInfo->ReadTransferCount = Process->ReadTransferCount; 03422 ProcessInfo->WriteTransferCount = Process->WriteTransferCount; 03423 ProcessInfo->OtherTransferCount = Process->OtherTransferCount; 03424 } 03425 03426 VOID 03427 ExpCopyThreadInfo ( 03428 IN PSYSTEM_THREAD_INFORMATION ThreadInfo, 03429 IN PETHREAD Thread 03430 ) 03431 03432 { 03433 03434 ThreadInfo->KernelTime.QuadPart = UInt32x32To64(Thread->Tcb.KernelTime, 03435 KeMaximumIncrement); 03436 03437 ThreadInfo->UserTime.QuadPart = UInt32x32To64(Thread->Tcb.UserTime, 03438 KeMaximumIncrement); 03439 03440 ThreadInfo->CreateTime.QuadPart = PS_GET_THREAD_CREATE_TIME (Thread); 03441 ThreadInfo->WaitTime = Thread->Tcb.WaitTime; 03442 ThreadInfo->ClientId = Thread->Cid; 03443 ThreadInfo->ThreadState = Thread->Tcb.State; 03444 ThreadInfo->WaitReason = Thread->Tcb.WaitReason; 03445 ThreadInfo->Priority = Thread->Tcb.Priority; 03446 ThreadInfo->BasePriority = Thread->Tcb.BasePriority; 03447 ThreadInfo->ContextSwitches = Thread->Tcb.ContextSwitches; 03448 ThreadInfo->StartAddress = Thread->StartAddress; 03449 } 03450 03451 #ifdef i386 03452 extern ULONG ExVdmOpcodeDispatchCounts[256]; 03453 extern ULONG VdmBopCount; 03454 extern ULONG ExVdmSegmentNotPresent; 03455 03456 #if defined(ALLOC_PRAGMA) 03457 #pragma alloc_text(PAGE, ExpGetInstemulInformation) 03458 #endif 03459 03460 03461 NTSTATUS 03462 ExpGetInstemulInformation( 03463 OUT PSYSTEM_VDM_INSTEMUL_INFO Info 03464 ) 03465 { 03466 SYSTEM_VDM_INSTEMUL_INFO LocalInfo; 03467 03468 LocalInfo.VdmOpcode0F = ExVdmOpcodeDispatchCounts[VDM_INDEX_0F]; 03469 LocalInfo.OpcodeESPrefix = ExVdmOpcodeDispatchCounts[VDM_INDEX_ESPrefix]; 03470 LocalInfo.OpcodeCSPrefix = ExVdmOpcodeDispatchCounts[VDM_INDEX_CSPrefix]; 03471 LocalInfo.OpcodeSSPrefix = ExVdmOpcodeDispatchCounts[VDM_INDEX_SSPrefix]; 03472 LocalInfo.OpcodeDSPrefix = ExVdmOpcodeDispatchCounts[VDM_INDEX_DSPrefix]; 03473 LocalInfo.OpcodeFSPrefix = ExVdmOpcodeDispatchCounts[VDM_INDEX_FSPrefix]; 03474 LocalInfo.OpcodeGSPrefix = ExVdmOpcodeDispatchCounts[VDM_INDEX_GSPrefix]; 03475 LocalInfo.OpcodeOPER32Prefix= ExVdmOpcodeDispatchCounts[VDM_INDEX_OPER32Prefix]; 03476 LocalInfo.OpcodeADDR32Prefix= ExVdmOpcodeDispatchCounts[VDM_INDEX_ADDR32Prefix]; 03477 LocalInfo.OpcodeINSB = ExVdmOpcodeDispatchCounts[VDM_INDEX_INSB]; 03478 LocalInfo.OpcodeINSW = ExVdmOpcodeDispatchCounts[VDM_INDEX_INSW]; 03479 LocalInfo.OpcodeOUTSB = ExVdmOpcodeDispatchCounts[VDM_INDEX_OUTSB]; 03480 LocalInfo.OpcodeOUTSW = ExVdmOpcodeDispatchCounts[VDM_INDEX_OUTSW]; 03481 LocalInfo.OpcodePUSHF = ExVdmOpcodeDispatchCounts[VDM_INDEX_PUSHF]; 03482 LocalInfo.OpcodePOPF = ExVdmOpcodeDispatchCounts[VDM_INDEX_POPF]; 03483 LocalInfo.OpcodeINTnn = ExVdmOpcodeDispatchCounts[VDM_INDEX_INTnn]; 03484 LocalInfo.OpcodeINTO = ExVdmOpcodeDispatchCounts[VDM_INDEX_INTO]; 03485 LocalInfo.OpcodeIRET = ExVdmOpcodeDispatchCounts[VDM_INDEX_IRET]; 03486 LocalInfo.OpcodeINBimm = ExVdmOpcodeDispatchCounts[VDM_INDEX_INBimm]; 03487 LocalInfo.OpcodeINWimm = ExVdmOpcodeDispatchCounts[VDM_INDEX_INWimm]; 03488 LocalInfo.OpcodeOUTBimm = ExVdmOpcodeDispatchCounts[VDM_INDEX_OUTBimm]; 03489 LocalInfo.OpcodeOUTWimm = ExVdmOpcodeDispatchCounts[VDM_INDEX_OUTWimm]; 03490 LocalInfo.OpcodeINB = ExVdmOpcodeDispatchCounts[VDM_INDEX_INB]; 03491 LocalInfo.OpcodeINW = ExVdmOpcodeDispatchCounts[VDM_INDEX_INW]; 03492 LocalInfo.OpcodeOUTB = ExVdmOpcodeDispatchCounts[VDM_INDEX_OUTB]; 03493 LocalInfo.OpcodeOUTW = ExVdmOpcodeDispatchCounts[VDM_INDEX_OUTW]; 03494 LocalInfo.OpcodeLOCKPrefix = ExVdmOpcodeDispatchCounts[VDM_INDEX_LOCKPrefix]; 03495 LocalInfo.OpcodeREPNEPrefix = ExVdmOpcodeDispatchCounts[VDM_INDEX_REPNEPrefix]; 03496 LocalInfo.OpcodeREPPrefix = ExVdmOpcodeDispatchCounts[VDM_INDEX_REPPrefix]; 03497 LocalInfo.OpcodeHLT = ExVdmOpcodeDispatchCounts[VDM_INDEX_HLT]; 03498 LocalInfo.OpcodeCLI = ExVdmOpcodeDispatchCounts[VDM_INDEX_CLI]; 03499 LocalInfo.OpcodeSTI = ExVdmOpcodeDispatchCounts[VDM_INDEX_STI]; 03500 LocalInfo.BopCount = VdmBopCount; 03501 LocalInfo.SegmentNotPresent = ExVdmSegmentNotPresent; 03502 03503 RtlMoveMemory(Info,&LocalInfo,sizeof(LocalInfo)); 03504 03505 return STATUS_SUCCESS; 03506 } 03507 #endif 03508 03509 #if i386 && !FPO 03510 NTSTATUS 03511 ExpGetStackTraceInformation ( 03512 OUT PVOID SystemInformation, 03513 IN ULONG SystemInformationLength, 03514 OUT PULONG ReturnLength OPTIONAL 03515 ) 03516 { 03517 NTSTATUS Status; 03518 PRTL_PROCESS_BACKTRACES BackTraceInformation = (PRTL_PROCESS_BACKTRACES)SystemInformation; 03519 PRTL_PROCESS_BACKTRACE_INFORMATION BackTraceInfo; 03520 PSTACK_TRACE_DATABASE DataBase; 03521 PRTL_STACK_TRACE_ENTRY p, *pp; 03522 ULONG RequiredLength, n; 03523 03524 DataBase = RtlpAcquireStackTraceDataBase(); 03525 if (DataBase == NULL) { 03526 return STATUS_UNSUCCESSFUL; 03527 } 03528 DataBase->DumpInProgress = TRUE; 03529 RtlpReleaseStackTraceDataBase(); 03530 try { 03531 RequiredLength = FIELD_OFFSET( RTL_PROCESS_BACKTRACES, BackTraces ); 03532 if (SystemInformationLength < RequiredLength) { 03533 Status = STATUS_INFO_LENGTH_MISMATCH; 03534 } 03535 else { 03536 BackTraceInformation->CommittedMemory = 03537 (ULONG)DataBase->CurrentUpperCommitLimit - (ULONG)DataBase->CommitBase; 03538 BackTraceInformation->ReservedMemory = 03539 (ULONG)DataBase->EntryIndexArray - (ULONG)DataBase->CommitBase; 03540 BackTraceInformation->NumberOfBackTraceLookups = DataBase->NumberOfEntriesLookedUp; 03541 n = DataBase->NumberOfEntriesAdded; 03542 BackTraceInformation->NumberOfBackTraces = n; 03543 } 03544 03545 RequiredLength += (sizeof( *BackTraceInfo ) * n); 03546 if (SystemInformationLength < RequiredLength) { 03547 Status = STATUS_INFO_LENGTH_MISMATCH; 03548 } 03549 else { 03550 Status = STATUS_SUCCESS; 03551 BackTraceInfo = &BackTraceInformation->BackTraces[ 0 ]; 03552 pp = DataBase->EntryIndexArray; 03553 while (n--) { 03554 p = *--pp; 03555 BackTraceInfo->SymbolicBackTrace = NULL; 03556 BackTraceInfo->TraceCount = p->TraceCount; 03557 BackTraceInfo->Index = p->Index; 03558 BackTraceInfo->Depth = p->Depth; 03559 RtlMoveMemory( BackTraceInfo->BackTrace, 03560 p->BackTrace, 03561 p->Depth * sizeof( PVOID ) 03562 ); 03563 BackTraceInfo++; 03564 } 03565 } 03566 } 03567 finally { 03568 DataBase->DumpInProgress = FALSE; 03569 } 03570 03571 if (ARGUMENT_PRESENT(ReturnLength)) { 03572 *ReturnLength = RequiredLength; 03573 } 03574 return Status; 03575 } 03576 #endif // i386 && !FPO 03577 03578 NTSTATUS 03579 ExpGetLockInformation ( 03580 OUT PVOID SystemInformation, 03581 IN ULONG SystemInformationLength, 03582 OUT PULONG Length 03583 ) 03584 /*++ 03585 03586 Routine Description: 03587 03588 This function returns information about all the ERESOURCE locks 03589 in the system. 03590 03591 Arguments: 03592 03593 SystemInformation - A pointer to a buffer which receives the specified 03594 information. 03595 03596 SystemInformationLength - Specifies the length in bytes of the system 03597 information buffer. 03598 03599 Length - An optional pointer which, if specified, receives the 03600 number of bytes placed in the system information buffer. 03601 03602 03603 Return Value: 03604 03605 Returns one of the following status codes: 03606 03607 STATUS_SUCCESS - normal, successful completion. 03608 03609 STATUS_INVALID_INFO_CLASS - The SystemInformationClass parameter 03610 did not specify a valid value. 03611 03612 STATUS_INFO_LENGTH_MISMATCH - The value of the SystemInformationLength 03613 parameter did not match the length required for the information 03614 class requested by the SystemInformationClass parameter. 03615 03616 STATUS_ACCESS_VIOLATION - Either the SystemInformation buffer pointer 03617 or the Length pointer value specified an invalid address. 03618 03619 STATUS_WORKING_SET_QUOTA - The process does not have sufficient 03620 working set to lock the specified output structure in memory. 03621 03622 STATUS_INSUFFICIENT_RESOURCES - Insufficient system resources exist 03623 for this request to complete. 03624 03625 --*/ 03626 03627 { 03628 PRTL_PROCESS_LOCKS LockInfo; 03629 PVOID LockVariable; 03630 NTSTATUS Status; 03631 03632 03633 *Length = 0; 03634 03635 LockInfo = (PRTL_PROCESS_LOCKS) 03636 ExLockUserBuffer( SystemInformation, 03637 SystemInformationLength, 03638 &LockVariable 03639 ); 03640 if (LockInfo == NULL) { 03641 return( STATUS_ACCESS_VIOLATION ); 03642 } 03643 03644 MmLockPagableSectionByHandle (ExPageLockHandle); 03645 try { 03646 03647 Status = ExQuerySystemLockInformation( LockInfo, 03648 SystemInformationLength, 03649 Length 03650 ); 03651 } 03652 finally { 03653 ExUnlockUserBuffer( LockVariable ); 03654 MmUnlockPagableImageSection(ExPageLockHandle); 03655 } 03656 03657 return( Status ); 03658 } 03659 03660 NTSTATUS 03661 ExpGetLookasideInformation ( 03662 OUT PVOID Buffer, 03663 IN ULONG BufferLength, 03664 OUT PULONG Length 03665 ) 03666 03667 /*++ 03668 03669 Routine Description: 03670 03671 This function returns pool lookaside list and general lookaside 03672 list information. 03673 03674 Arguments: 03675 03676 Buffer - Supplies a pointer to the buffer which receives the lookaside 03677 list information. 03678 03679 BufferLength - Supplies the length of the information buffer in bytes. 03680 03681 Length - Supplies a pointer to a variable that receives the length of 03682 lookaside information returned. 03683 03684 Return Value: 03685 03686 Returns one of the following status codes: 03687 03688 STATUS_SUCCESS - Normal, successful completion. 03689 03690 STATUS_ACCESS_VIOLATION - The buffer could not be locked in memory. 03691 03692 --*/ 03693 03694 { 03695 03696 PVOID BufferLock; 03697 PLIST_ENTRY Entry; 03698 ULONG Index; 03699 KIRQL OldIrql; 03700 ULONG Limit; 03701 PSYSTEM_LOOKASIDE_INFORMATION Lookaside; 03702 ULONG Number; 03703 PNPAGED_LOOKASIDE_LIST NPagedLookaside; 03704 PPAGED_LOOKASIDE_LIST PagedLookaside; 03705 PNPAGED_LOOKASIDE_LIST PoolLookaside; 03706 PKSPIN_LOCK SpinLock; 03707 NTSTATUS Status; 03708 03709 // 03710 // Compute the number of lookaside entries and set the return status to 03711 // success. 03712 // 03713 03714 Limit = BufferLength / sizeof(SYSTEM_LOOKASIDE_INFORMATION); 03715 Number = 0; 03716 Status = STATUS_SUCCESS; 03717 03718 // 03719 // If the number of lookaside entries to return is not zero, then collect 03720 // the lookaside information. 03721 // 03722 03723 if (Limit != 0) { 03724 if ((Lookaside = 03725 (PSYSTEM_LOOKASIDE_INFORMATION)ExLockUserBuffer(Buffer, 03726 BufferLength, 03727 &BufferLock)) == NULL) { 03728 Status = STATUS_ACCESS_VIOLATION; 03729 03730 } else { 03731 MmLockPagableSectionByHandle(ExPageLockHandle); 03732 03733 // 03734 // Copy nonpaged and paged pool lookaside information to 03735 // information buffer. 03736 // 03737 03738 Entry = ExPoolLookasideListHead.Flink; 03739 while (Entry != &ExPoolLookasideListHead) { 03740 PoolLookaside = CONTAINING_RECORD(Entry, 03741 NPAGED_LOOKASIDE_LIST, 03742 L.ListEntry); 03743 03744 Lookaside->CurrentDepth = (USHORT)PoolLookaside->L.ListHead.Depth; 03745 Lookaside->MaximumDepth = PoolLookaside->L.Depth; 03746 Lookaside->TotalAllocates = PoolLookaside->L.TotalAllocates; 03747 Lookaside->AllocateMisses = 03748 PoolLookaside->L.TotalAllocates - PoolLookaside->L.AllocateHits; 03749 03750 Lookaside->TotalFrees = PoolLookaside->L.TotalFrees; 03751 Lookaside->FreeMisses = 03752 PoolLookaside->L.TotalFrees - PoolLookaside->L.FreeHits; 03753 03754 Lookaside->Type = PoolLookaside->L.Type; 03755 Lookaside->Tag = PoolLookaside->L.Tag; 03756 Lookaside->Size = PoolLookaside->L.Size; 03757 Number += 1; 03758 if (Number == Limit) { 03759 goto Finish2; 03760 } 03761 03762 Entry = Entry->Flink; 03763 Lookaside += 1; 03764 } 03765 03766 // 03767 // Copy nonpaged general lookaside information to buffer. 03768 // 03769 03770 SpinLock = &ExNPagedLookasideLock; 03771 ExAcquireSpinLock(SpinLock, &OldIrql); 03772 Entry = ExNPagedLookasideListHead.Flink; 03773 while (Entry != &ExNPagedLookasideListHead) { 03774 NPagedLookaside = CONTAINING_RECORD(Entry, 03775 NPAGED_LOOKASIDE_LIST, 03776 L.ListEntry); 03777 03778 Lookaside->CurrentDepth = (USHORT)NPagedLookaside->L.ListHead.Depth; 03779 Lookaside->MaximumDepth = NPagedLookaside->L.Depth; 03780 Lookaside->TotalAllocates = NPagedLookaside->L.TotalAllocates; 03781 Lookaside->AllocateMisses = NPagedLookaside->L.AllocateMisses; 03782 Lookaside->TotalFrees = NPagedLookaside->L.TotalFrees; 03783 Lookaside->FreeMisses = NPagedLookaside->L.FreeMisses; 03784 Lookaside->Type = 0; 03785 Lookaside->Tag = NPagedLookaside->L.Tag; 03786 Lookaside->Size = NPagedLookaside->L.Size; 03787 Number += 1; 03788 if (Number == Limit) { 03789 goto Finish1; 03790 } 03791 03792 Entry = Entry->Flink; 03793 Lookaside += 1; 03794 } 03795 03796 ExReleaseSpinLock(SpinLock, OldIrql); 03797 03798 // 03799 // Copy paged general lookaside information to buffer. 03800 // 03801 03802 SpinLock = &ExPagedLookasideLock; 03803 ExAcquireSpinLock(SpinLock, &OldIrql); 03804 Entry = ExPagedLookasideListHead.Flink; 03805 while (Entry != &ExPagedLookasideListHead) { 03806 PagedLookaside = CONTAINING_RECORD(Entry, 03807 PAGED_LOOKASIDE_LIST, 03808 L.ListEntry); 03809 03810 Lookaside->CurrentDepth = (USHORT)PagedLookaside->L.ListHead.Depth; 03811 Lookaside->MaximumDepth = PagedLookaside->L.Depth; 03812 Lookaside->TotalAllocates = PagedLookaside->L.TotalAllocates; 03813 Lookaside->AllocateMisses = PagedLookaside->L.AllocateMisses; 03814 Lookaside->TotalFrees = PagedLookaside->L.TotalFrees; 03815 Lookaside->FreeMisses = PagedLookaside->L.FreeMisses; 03816 Lookaside->Type = 1; 03817 Lookaside->Tag = PagedLookaside->L.Tag; 03818 Lookaside->Size = PagedLookaside->L.Size; 03819 Number += 1; 03820 if (Number == Limit) { 03821 goto Finish1; 03822 } 03823 03824 Entry = Entry->Flink; 03825 Lookaside += 1; 03826 } 03827 03828 Finish1: 03829 ExReleaseSpinLock(SpinLock, OldIrql); 03830 03831 // 03832 // Unlock user buffer and page lock image section. 03833 // 03834 03835 Finish2: 03836 MmUnlockPagableImageSection(ExPageLockHandle); 03837 ExUnlockUserBuffer(BufferLock); 03838 } 03839 } 03840 03841 *Length = Number * sizeof(SYSTEM_LOOKASIDE_INFORMATION); 03842 return Status; 03843 } 03844 03845 NTSTATUS 03846 ExpGetPoolInformation( 03847 IN POOL_TYPE PoolType, 03848 OUT PVOID SystemInformation, 03849 IN ULONG SystemInformationLength, 03850 OUT PULONG Length 03851 ) 03852 /*++ 03853 03854 Routine Description: 03855 03856 This function returns information about the specified type of pool memory. 03857 03858 Arguments: 03859 03860 SystemInformation - A pointer to a buffer which receives the specified 03861 information. 03862 03863 SystemInformationLength - Specifies the length in bytes of the system 03864 information buffer. 03865 03866 Length - An optional pointer which, if specified, receives the 03867 number of bytes placed in the system information buffer. 03868 03869 03870 Return Value: 03871 03872 Returns one of the following status codes: 03873 03874 STATUS_SUCCESS - normal, successful completion. 03875 03876 STATUS_INVALID_INFO_CLASS - The SystemInformationClass parameter 03877 did not specify a valid value. 03878 03879 STATUS_INFO_LENGTH_MISMATCH - The value of the SystemInformationLength 03880 parameter did not match the length required for the information 03881 class requested by the SystemInformationClass parameter. 03882 03883 STATUS_ACCESS_VIOLATION - Either the SystemInformation buffer pointer 03884 or the Length pointer value specified an invalid address. 03885 03886 STATUS_WORKING_SET_QUOTA - The process does not have sufficient 03887 working set to lock the specified output structure in memory. 03888 03889 STATUS_INSUFFICIENT_RESOURCES - Insufficient system resources exist 03890 for this request to complete. 03891 03892 --*/ 03893 03894 { 03895 #if DBG || (i386 && !FPO) 03896 03897 // 03898 // Only works on checked builds or free x86 builds with FPO turned off 03899 // See comment in mm\allocpag.c 03900 // 03901 03902 PSYSTEM_POOL_INFORMATION PoolInfo; 03903 PVOID LockVariable; 03904 NTSTATUS Status; 03905 03906 03907 *Length = 0; 03908 03909 PoolInfo = (PSYSTEM_POOL_INFORMATION) 03910 ExLockUserBuffer( SystemInformation, 03911 SystemInformationLength, 03912 &LockVariable 03913 ); 03914 if (PoolInfo == NULL) { 03915 return( STATUS_ACCESS_VIOLATION ); 03916 } 03917 03918 MmLockPagableSectionByHandle (ExPageLockHandle); 03919 try { 03920 Status = ExSnapShotPool( PoolType, 03921 PoolInfo, 03922 SystemInformationLength, 03923 Length 03924 ); 03925 03926 } 03927 finally { 03928 ExUnlockUserBuffer( LockVariable ); 03929 MmUnlockPagableImageSection(ExPageLockHandle); 03930 } 03931 03932 return( Status ); 03933 #else 03934 return STATUS_NOT_IMPLEMENTED; 03935 #endif // DBG || (i386 && !FPO) 03936 } 03937 03938 NTSTATUS 03939 ExpGetHandleInformation( 03940 OUT PVOID SystemInformation, 03941 IN ULONG SystemInformationLength, 03942 OUT PULONG Length 03943 ) 03944 /*++ 03945 03946 Routine Description: 03947 03948 This function returns information about the open handles in the system. 03949 03950 Arguments: 03951 03952 SystemInformation - A pointer to a buffer which receives the specified 03953 information. 03954 03955 SystemInformationLength - Specifies the length in bytes of the system 03956 information buffer. 03957 03958 Length - An optional pointer which, if specified, receives the 03959 number of bytes placed in the system information buffer. 03960 03961 03962 Return Value: 03963 03964 Returns one of the following status codes: 03965 03966 STATUS_SUCCESS - normal, successful completion. 03967 03968 STATUS_INVALID_INFO_CLASS - The SystemInformationClass parameter 03969 did not specify a valid value. 03970 03971 STATUS_INFO_LENGTH_MISMATCH - The value of the SystemInformationLength 03972 parameter did not match the length required for the information 03973 class requested by the SystemInformationClass parameter. 03974 03975 STATUS_ACCESS_VIOLATION - Either the SystemInformation buffer pointer 03976 or the Length pointer value specified an invalid address. 03977 03978 STATUS_WORKING_SET_QUOTA - The process does not have sufficient 03979 working set to lock the specified output structure in memory. 03980 03981 STATUS_INSUFFICIENT_RESOURCES - Insufficient system resources exist 03982 for this request to complete. 03983 03984 --*/ 03985 03986 { 03987 PSYSTEM_HANDLE_INFORMATION HandleInfo; 03988 PVOID LockVariable; 03989 NTSTATUS Status; 03990 03991 PAGED_CODE(); 03992 03993 *Length = 0; 03994 03995 HandleInfo = (PSYSTEM_HANDLE_INFORMATION) 03996 ExLockUserBuffer( SystemInformation, 03997 SystemInformationLength, 03998 &LockVariable 03999 ); 04000 if (HandleInfo == NULL) { 04001 return( STATUS_ACCESS_VIOLATION ); 04002 } 04003 04004 try { 04005 Status = ObGetHandleInformation( HandleInfo, 04006 SystemInformationLength, 04007 Length 04008 ); 04009 04010 } 04011 finally { 04012 ExUnlockUserBuffer( LockVariable ); 04013 } 04014 04015 return( Status ); 04016 } 04017 04018 NTSTATUS 04019 ExpGetObjectInformation( 04020 OUT PVOID SystemInformation, 04021 IN ULONG SystemInformationLength, 04022 OUT PULONG Length 04023 ) 04024 04025 /*++ 04026 04027 Routine Description: 04028 04029 This function returns information about the objects in the system. 04030 04031 Arguments: 04032 04033 SystemInformation - A pointer to a buffer which receives the specified 04034 information. 04035 04036 SystemInformationLength - Specifies the length in bytes of the system 04037 information buffer. 04038 04039 Length - An optional pointer which, if specified, receives the 04040 number of bytes placed in the system information buffer. 04041 04042 04043 Return Value: 04044 04045 Returns one of the following status codes: 04046 04047 STATUS_SUCCESS - normal, successful completion. 04048 04049 STATUS_INVALID_INFO_CLASS - The SystemInformationClass parameter 04050 did not specify a valid value. 04051 04052 STATUS_INFO_LENGTH_MISMATCH - The value of the SystemInformationLength 04053 parameter did not match the length required for the information 04054 class requested by the SystemInformationClass parameter. 04055 04056 STATUS_ACCESS_VIOLATION - Either the SystemInformation buffer pointer 04057 or the Length pointer value specified an invalid address. 04058 04059 STATUS_WORKING_SET_QUOTA - The process does not have sufficient 04060 working set to lock the specified output structure in memory. 04061 04062 STATUS_INSUFFICIENT_RESOURCES - Insufficient system resources exist 04063 for this request to complete. 04064 04065 --*/ 04066 04067 { 04068 PSYSTEM_OBJECTTYPE_INFORMATION ObjectInfo; 04069 PVOID LockVariable; 04070 NTSTATUS Status; 04071 04072 PAGED_CODE(); 04073 04074 *Length = 0; 04075 04076 ObjectInfo = (PSYSTEM_OBJECTTYPE_INFORMATION) 04077 ExLockUserBuffer( SystemInformation, 04078 SystemInformationLength, 04079 &LockVariable 04080 ); 04081 if (ObjectInfo == NULL) { 04082 return( STATUS_ACCESS_VIOLATION ); 04083 } 04084 04085 try { 04086 Status = ObGetObjectInformation( SystemInformation, 04087 ObjectInfo, 04088 SystemInformationLength, 04089 Length 04090 ); 04091 04092 } 04093 finally { 04094 ExUnlockUserBuffer( LockVariable ); 04095 } 04096 04097 return( Status ); 04098 } 04099 04100 extern SIZE_T PoolTrackTableSize; 04101 extern KSPIN_LOCK ExpTaggedPoolLock; 04102 04103 NTSTATUS 04104 ExpGetPoolTagInfo ( 04105 IN PVOID SystemInformation, 04106 IN ULONG SystemInformationLength, 04107 IN OUT PULONG ReturnLength OPTIONAL 04108 ) 04109 04110 { 04111 SIZE_T NumberOfBytes; 04112 ULONG totalBytes; 04113 ULONG i; 04114 KIRQL OldIrql; 04115 NTSTATUS status; 04116 PSYSTEM_POOLTAG_INFORMATION taginfo; 04117 PSYSTEM_POOLTAG poolTag; 04118 PPOOL_TRACKER_TABLE PoolTrackInfo; 04119 04120 PAGED_CODE(); 04121 if (!PoolTrackTable) { 04122 return STATUS_NOT_IMPLEMENTED; 04123 } 04124 04125 totalBytes = 0; 04126 status = STATUS_SUCCESS; 04127 04128 taginfo = (PSYSTEM_POOLTAG_INFORMATION)SystemInformation; 04129 poolTag = &taginfo->TagInfo[0]; 04130 totalBytes = FIELD_OFFSET(SYSTEM_POOLTAG_INFORMATION, TagInfo); 04131 taginfo->Count = 0; 04132 04133 // 04134 // Synchronize access to PoolTrackTable as it can move. 04135 // 04136 04137 NumberOfBytes = PoolTrackTableSize * sizeof(POOL_TRACKER_TABLE); 04138 04139 PoolTrackInfo = (PPOOL_TRACKER_TABLE) ExAllocatePoolWithTag (NonPagedPool, 04140 NumberOfBytes, 04141 'ofnI'); 04142 04143 if (PoolTrackInfo == NULL) { 04144 return STATUS_INSUFFICIENT_RESOURCES; 04145 } 04146 04147 ExAcquireSpinLock(&ExpTaggedPoolLock, &OldIrql); 04148 04149 RtlCopyMemory ((PVOID)PoolTrackInfo, 04150 (PVOID)PoolTrackTable, 04151 NumberOfBytes); 04152 04153 ExReleaseSpinLock(&ExpTaggedPoolLock, OldIrql); 04154 04155 for (i = 0; i < NumberOfBytes / sizeof(POOL_TRACKER_TABLE); i += 1) { 04156 if (PoolTrackInfo[i].Key != 0) { 04157 taginfo->Count += 1; 04158 totalBytes += sizeof (SYSTEM_POOLTAG); 04159 if (SystemInformationLength < totalBytes) { 04160 status = STATUS_INFO_LENGTH_MISMATCH; 04161 } else { 04162 poolTag->TagUlong = PoolTrackInfo[i].Key; 04163 poolTag->PagedAllocs = PoolTrackInfo[i].PagedAllocs; 04164 poolTag->PagedFrees = PoolTrackInfo[i].PagedFrees; 04165 poolTag->PagedUsed = PoolTrackInfo[i].PagedBytes; 04166 poolTag->NonPagedAllocs = PoolTrackInfo[i].NonPagedAllocs; 04167 poolTag->NonPagedFrees = PoolTrackInfo[i].NonPagedFrees; 04168 poolTag->NonPagedUsed = PoolTrackInfo[i].NonPagedBytes; 04169 poolTag += 1; 04170 } 04171 } 04172 } 04173 04174 ExFreePool (PoolTrackInfo); 04175 04176 if (ARGUMENT_PRESENT(ReturnLength)) { 04177 *ReturnLength = totalBytes; 04178 } 04179 04180 return status; 04181 } 04182 04183 04184 NTSTATUS 04185 ExpQueryModuleInformation( 04186 IN PLIST_ENTRY LoadOrderListHead, 04187 IN PLIST_ENTRY UserModeLoadOrderListHead, 04188 OUT PRTL_PROCESS_MODULES ModuleInformation, 04189 IN ULONG ModuleInformationLength, 04190 OUT PULONG ReturnLength OPTIONAL 04191 ) 04192 { 04193 NTSTATUS Status; 04194 ULONG RequiredLength; 04195 PLIST_ENTRY Next; 04196 PLIST_ENTRY Next1; 04197 PRTL_PROCESS_MODULE_INFORMATION ModuleInfo; 04198 PLDR_DATA_TABLE_ENTRY LdrDataTableEntry; 04199 PLDR_DATA_TABLE_ENTRY LdrDataTableEntry1; 04200 ANSI_STRING AnsiString; 04201 PUCHAR s; 04202 04203 RequiredLength = FIELD_OFFSET( RTL_PROCESS_MODULES, Modules ); 04204 if (ModuleInformationLength < RequiredLength) { 04205 Status = STATUS_INFO_LENGTH_MISMATCH; 04206 } 04207 else { 04208 ModuleInformation->NumberOfModules = 0; 04209 ModuleInfo = &ModuleInformation->Modules[ 0 ]; 04210 Status = STATUS_SUCCESS; 04211 } 04212 04213 Next = LoadOrderListHead->Flink; 04214 while ( Next != LoadOrderListHead ) { 04215 LdrDataTableEntry = CONTAINING_RECORD( Next, 04216 LDR_DATA_TABLE_ENTRY, 04217 InLoadOrderLinks 04218 ); 04219 04220 RequiredLength += sizeof( RTL_PROCESS_MODULE_INFORMATION ); 04221 if (ModuleInformationLength < RequiredLength) { 04222 Status = STATUS_INFO_LENGTH_MISMATCH; 04223 } 04224 else { 04225 04226 ModuleInfo->MappedBase = NULL; 04227 ModuleInfo->ImageBase = LdrDataTableEntry->DllBase; 04228 ModuleInfo->ImageSize = LdrDataTableEntry->SizeOfImage; 04229 ModuleInfo->Flags = LdrDataTableEntry->Flags; 04230 ModuleInfo->LoadCount = LdrDataTableEntry->LoadCount; 04231 04232 ModuleInfo->LoadOrderIndex = (USHORT)(ModuleInformation->NumberOfModules); 04233 ModuleInfo->InitOrderIndex = 0; 04234 AnsiString.Buffer = ModuleInfo->FullPathName; 04235 AnsiString.Length = 0; 04236 AnsiString.MaximumLength = sizeof( ModuleInfo->FullPathName ); 04237 RtlUnicodeStringToAnsiString( &AnsiString, 04238 &LdrDataTableEntry->FullDllName, 04239 FALSE 04240 ); 04241 s = AnsiString.Buffer + AnsiString.Length; 04242 while (s > AnsiString.Buffer && *--s) { 04243 if (*s == (UCHAR)OBJ_NAME_PATH_SEPARATOR) { 04244 s++; 04245 break; 04246 } 04247 } 04248 ModuleInfo->OffsetToFileName = (USHORT)(s - AnsiString.Buffer); 04249 04250 ModuleInfo++; 04251 } 04252 04253 ModuleInformation->NumberOfModules++; 04254 Next = Next->Flink; 04255 } 04256 04257 if (ARGUMENT_PRESENT( UserModeLoadOrderListHead )) { 04258 Next = UserModeLoadOrderListHead->Flink; 04259 while ( Next != UserModeLoadOrderListHead ) { 04260 LdrDataTableEntry = CONTAINING_RECORD( Next, 04261 LDR_DATA_TABLE_ENTRY, 04262 InLoadOrderLinks 04263 ); 04264 04265 RequiredLength += sizeof( RTL_PROCESS_MODULE_INFORMATION ); 04266 if (ModuleInformationLength < RequiredLength) { 04267 Status = STATUS_INFO_LENGTH_MISMATCH; 04268 } 04269 else { 04270 ModuleInfo->MappedBase = NULL; 04271 ModuleInfo->ImageBase = LdrDataTableEntry->DllBase; 04272 ModuleInfo->ImageSize = LdrDataTableEntry->SizeOfImage; 04273 ModuleInfo->Flags = LdrDataTableEntry->Flags; 04274 ModuleInfo->LoadCount = LdrDataTableEntry->LoadCount; 04275 04276 ModuleInfo->LoadOrderIndex = (USHORT)(ModuleInformation->NumberOfModules); 04277 04278 ModuleInfo->InitOrderIndex = ModuleInfo->LoadOrderIndex; 04279 04280 AnsiString.Buffer = ModuleInfo->FullPathName; 04281 AnsiString.Length = 0; 04282 AnsiString.MaximumLength = sizeof( ModuleInfo->FullPathName ); 04283 RtlUnicodeStringToAnsiString( &AnsiString, 04284 &LdrDataTableEntry->FullDllName, 04285 FALSE 04286 ); 04287 s = AnsiString.Buffer + AnsiString.Length; 04288 while (s > AnsiString.Buffer && *--s) { 04289 if (*s == (UCHAR)OBJ_NAME_PATH_SEPARATOR) { 04290 s++; 04291 break; 04292 } 04293 } 04294 ModuleInfo->OffsetToFileName = (USHORT)(s - AnsiString.Buffer); 04295 04296 ModuleInfo++; 04297 } 04298 04299 ModuleInformation->NumberOfModules++; 04300 Next = Next->Flink; 04301 } 04302 } 04303 04304 if (ARGUMENT_PRESENT(ReturnLength)) { 04305 *ReturnLength = RequiredLength; 04306 } 04307 return( Status ); 04308 } 04309 04310 BOOLEAN 04311 ExIsProcessorFeaturePresent( 04312 ULONG ProcessorFeature 04313 ) 04314 { 04315 BOOLEAN rv; 04316 04317 if ( ProcessorFeature < PROCESSOR_FEATURE_MAX ) { 04318 rv = SharedUserData->ProcessorFeatures[ProcessorFeature]; 04319 } 04320 else { 04321 rv = FALSE; 04322 } 04323 return rv; 04324 } 04325 04326 04327 NTSTATUS 04328 ExpQueryLegacyDriverInformation( 04329 IN PSYSTEM_LEGACY_DRIVER_INFORMATION LegacyInfo, 04330 IN PULONG Length 04331 ) 04332 /*++ 04333 04334 Routine Description: 04335 04336 Returns legacy driver information for figuring out why PNP/Power functionality 04337 is disabled. 04338 04339 Arguments: 04340 04341 LegacyInfo - Returns the legacy driver information 04342 04343 Length - Supplies the length of the LegacyInfo buffer 04344 Returns the amount of data written 04345 04346 Return Value: 04347 04348 NTSTATUS 04349 04350 --*/ 04351 04352 { 04353 PNP_VETO_TYPE VetoType; 04354 PWSTR VetoList = NULL; 04355 NTSTATUS Status; 04356 UNICODE_STRING String; 04357 ULONG ReturnLength; 04358 04359 Status = IoGetLegacyVetoList(&VetoList, &VetoType); 04360 if (!NT_SUCCESS(Status)) { 04361 return(Status); 04362 } 04363 04364 RtlInitUnicodeString(&String, VetoList); 04365 ReturnLength = sizeof(SYSTEM_LEGACY_DRIVER_INFORMATION) + String.Length; 04366 if (ReturnLength > *Length) { 04367 Status = STATUS_BUFFER_OVERFLOW; 04368 } else { 04369 try { 04370 LegacyInfo->VetoType = VetoType; 04371 LegacyInfo->VetoList.Length = String.Length; 04372 LegacyInfo->VetoList.Buffer = (PWSTR)(LegacyInfo+1); 04373 RtlCopyMemory(LegacyInfo+1, String.Buffer, String.Length); 04374 } finally { 04375 if (VetoList) { 04376 ExFreePool(VetoList); 04377 } 04378 } 04379 } 04380 04381 *Length = ReturnLength; 04382 return(Status); 04383 }

Generated on Sat May 15 19:41:56 2004 for test by doxygen 1.3.7