1 /* 2 * PROJECT: ReactOS system properties, control panel applet 3 * LICENSE: GPL - See COPYING in the top level directory 4 * FILE: dll/cpl/sysdm/virtmem.c 5 * PURPOSE: Virtual memory control dialog 6 * COPYRIGHT: Copyright 2006 Ged Murphy <gedmurphy@gmail.com> 7 * 8 */ 9 10 #include "precomp.h" 11 12 #ifdef _M_IX86 13 /* Used for SharedUserData by GetMaxPageFileSize() in the PAE case */ 14 #define NTOS_MODE_USER 15 #include <ndk/pstypes.h> 16 #endif 17 18 #define NDEBUG 19 #include <debug.h> 20 21 // #define MAX_PAGING_FILES 16 // See also ntoskrnl/include/internal/mm.h 22 #define MEGABYTE (1024 * 1024) 23 24 /* Values adapted from smss/pagefile.c, converted in megabytes and rounded-down. 25 * Compare to the more "accurate" values from SMSS (and NTOS) in bytes. */ 26 27 /* Minimum pagefile size: 2 MB, instead of 256 pages (1 MB) */ 28 #define MINIMUM_PAGEFILE_SIZE 2 29 30 /* Maximum pagefile sizes for different architectures */ 31 #define MAXIMUM_PAGEFILE_SIZE32 (4UL * 1024 - 1) 32 #define MAXIMUM_PAGEFILE_SIZE64 (16UL * 1024 * 1024 - 1) 33 34 #if defined(_M_IX86) 35 /* 4095 MB */ 36 #define MAXIMUM_PAGEFILE_SIZE MAXIMUM_PAGEFILE_SIZE32 37 /* PAE uses the same size as x64 */ 38 #define MAXIMUM_PAGEFILE_SIZE_PAE MAXIMUM_PAGEFILE_SIZE64 39 #elif defined (_M_AMD64) || defined(_M_ARM64) 40 /* Around 16 TB */ 41 #define MAXIMUM_PAGEFILE_SIZE MAXIMUM_PAGEFILE_SIZE64 42 #elif defined (_M_IA64) 43 /* Around 32 TB */ 44 #define MAXIMUM_PAGEFILE_SIZE (32UL * 1024 * 1024 - 1) 45 #elif defined(_M_ARM) 46 /* Around 2 GB */ 47 #if (NTDDI_VERSION >= NTDDI_WINBLUE) // NTDDI_WIN81 48 #define MAXIMUM_PAGEFILE_SIZE (2UL * 1024 - 1) 49 #else 50 /* Around 4 GB */ 51 #define MAXIMUM_PAGEFILE_SIZE MAXIMUM_PAGEFILE_SIZE32 52 #endif 53 #else 54 /* On unknown architectures, default to either one of the 32 or 64 bit sizes */ 55 #pragma message("Unknown architecture") 56 #ifdef _WIN64 57 #define MAXIMUM_PAGEFILE_SIZE MAXIMUM_PAGEFILE_SIZE64 58 #else 59 #define MAXIMUM_PAGEFILE_SIZE MAXIMUM_PAGEFILE_SIZE32 60 #endif 61 #endif 62 63 typedef struct _PAGEFILE 64 { 65 TCHAR szDrive[3]; 66 LPTSTR pszVolume; 67 INT OldMinSize; 68 INT OldMaxSize; 69 INT NewMinSize; 70 INT NewMaxSize; 71 UINT FreeSize; 72 BOOL bIsNotFAT; 73 BOOL bUsed; 74 } PAGEFILE, *PPAGEFILE; 75 76 typedef struct _VIRTMEM 77 { 78 HWND hSelf; 79 HWND hListBox; 80 LPTSTR szPagingFiles; 81 UINT Count; 82 BOOL bModified; 83 PAGEFILE PageFile[26]; 84 } VIRTMEM, *PVIRTMEM; 85 86 87 static __inline 88 UINT 89 GetMaxPageFileSize( 90 _In_ PPAGEFILE PageFile) 91 { 92 #ifdef _M_IX86 93 /* For x86 PAE-enabled systems, where the maximum pagefile size is 94 * greater than 4 GB, verify also that the drive's filesystem on which 95 * the pagefile is stored can support it. */ 96 if (SharedUserData->ProcessorFeatures[PF_PAE_ENABLED] && PageFile->bIsNotFAT) 97 return min(PageFile->FreeSize, MAXIMUM_PAGEFILE_SIZE_PAE); 98 #endif 99 return min(PageFile->FreeSize, MAXIMUM_PAGEFILE_SIZE); 100 } 101 102 static LPCTSTR lpKey = _T("SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Memory Management"); 103 104 static BOOL 105 ReadPageFileSettings(PVIRTMEM pVirtMem) 106 { 107 BOOL bRet = FALSE; 108 HKEY hkey = NULL; 109 DWORD dwType; 110 DWORD dwDataSize; 111 112 if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, 113 lpKey, 114 0, 115 NULL, 116 REG_OPTION_NON_VOLATILE, 117 KEY_QUERY_VALUE, 118 NULL, 119 &hkey, 120 NULL) == ERROR_SUCCESS) 121 { 122 if (RegQueryValueEx(hkey, 123 _T("PagingFiles"), 124 NULL, 125 &dwType, 126 NULL, 127 &dwDataSize) == ERROR_SUCCESS) 128 { 129 pVirtMem->szPagingFiles = (LPTSTR)HeapAlloc(GetProcessHeap(), 130 HEAP_ZERO_MEMORY, 131 dwDataSize); 132 if (pVirtMem->szPagingFiles != NULL) 133 { 134 if (RegQueryValueEx(hkey, 135 _T("PagingFiles"), 136 NULL, 137 &dwType, 138 (PBYTE)pVirtMem->szPagingFiles, 139 &dwDataSize) == ERROR_SUCCESS) 140 { 141 bRet = TRUE; 142 } 143 } 144 } 145 } 146 147 if (!bRet) 148 ShowLastWin32Error(pVirtMem->hSelf); 149 150 if (hkey != NULL) 151 RegCloseKey(hkey); 152 153 return bRet; 154 } 155 156 157 static VOID 158 GetPageFileSizes(LPTSTR lpPageFiles, 159 LPINT lpInitialSize, 160 LPINT lpMaximumSize) 161 { 162 UINT i = 0; 163 164 *lpInitialSize = -1; 165 *lpMaximumSize = -1; 166 167 while (*lpPageFiles != _T('\0')) 168 { 169 if (*lpPageFiles == _T(' ')) 170 { 171 lpPageFiles++; 172 173 switch (i) 174 { 175 case 0: 176 *lpInitialSize = (INT)_ttoi(lpPageFiles); 177 i = 1; 178 break; 179 180 case 1: 181 *lpMaximumSize = (INT)_ttoi(lpPageFiles); 182 return; 183 } 184 } 185 186 lpPageFiles++; 187 } 188 } 189 190 191 static VOID 192 ParseMemSettings(PVIRTMEM pVirtMem) 193 { 194 TCHAR szDrives[1024]; // All drives 195 LPTSTR DrivePtr = szDrives; 196 TCHAR szDrive[3]; // Single drive 197 TCHAR szVolume[MAX_PATH + 1]; 198 TCHAR szFSName[MAX_PATH + 1]; 199 INT MinSize; 200 INT MaxSize; 201 INT DriveLen; 202 INT Len; 203 UINT PgCnt = 0; 204 PPAGEFILE PageFile; 205 206 DriveLen = GetLogicalDriveStrings(_countof(szDrives) - 1, 207 szDrives); 208 209 while (DriveLen != 0) 210 { 211 Len = lstrlen(DrivePtr) + 1; 212 DriveLen -= Len; 213 214 DrivePtr = _tcsupr(DrivePtr); 215 216 /* Copy the 'X:' portion */ 217 lstrcpyn(szDrive, DrivePtr, _countof(szDrive)); 218 219 if (GetDriveType(DrivePtr) == DRIVE_FIXED) 220 { 221 MinSize = -1; 222 MaxSize = -1; 223 224 /* Does drive match the one in the registry ? */ 225 if (_tcsnicmp(pVirtMem->szPagingFiles, szDrive, 2) == 0) 226 { 227 GetPageFileSizes(pVirtMem->szPagingFiles, 228 &MinSize, 229 &MaxSize); 230 } 231 232 PageFile = &pVirtMem->PageFile[PgCnt]; 233 PageFile->OldMinSize = MinSize; 234 PageFile->OldMaxSize = MaxSize; 235 PageFile->NewMinSize = MinSize; 236 PageFile->NewMaxSize = MaxSize; 237 PageFile->bIsNotFAT = TRUE; /* Suppose this is not a FAT volume */ 238 PageFile->bUsed = TRUE; 239 lstrcpy(PageFile->szDrive, szDrive); 240 241 /* Get the volume label if there is one */ 242 if (GetVolumeInformation(DrivePtr, 243 szVolume, _countof(szVolume), 244 NULL, NULL, NULL, 245 szFSName, _countof(szFSName))) 246 { 247 PageFile->pszVolume = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 248 (_tcslen(szVolume) + 1) * sizeof(TCHAR)); 249 if (PageFile->pszVolume != NULL) 250 _tcscpy(PageFile->pszVolume, szVolume); 251 252 /* 253 * Check whether the volume is FAT, which cannot support files 254 * larger than 4GB (for FAT32 and FATX, and less for FAT16). 255 * This will limit the maximum size of the pagefile this volume 256 * can contain (see GetMaxPageFileSize()). 257 */ 258 PageFile->bIsNotFAT = (_tcsnicmp(szFSName, _T("FAT"), 3) != 0); 259 } 260 261 PgCnt++; 262 } 263 264 DrivePtr += Len; 265 } 266 267 pVirtMem->Count = PgCnt; 268 } 269 270 271 static VOID 272 WritePageFileSettings(PVIRTMEM pVirtMem) 273 { 274 BOOL bErr = TRUE; 275 HKEY hk = NULL; 276 TCHAR szText[256]; 277 TCHAR szPagingFiles[2048]; 278 UINT i, nPos = 0; 279 PPAGEFILE PageFile; 280 281 for (i = 0; i < pVirtMem->Count; ++i) 282 { 283 PageFile = &pVirtMem->PageFile[i]; 284 285 if (PageFile->bUsed && 286 PageFile->NewMinSize != -1 && 287 PageFile->NewMaxSize != -1) 288 { 289 _stprintf(szText, 290 _T("%s\\pagefile.sys %i %i"), 291 PageFile->szDrive, 292 PageFile->NewMinSize, 293 PageFile->NewMaxSize); 294 295 /* Add it to our overall registry string */ 296 lstrcpy(szPagingFiles + nPos, szText); 297 298 /* Record the position where the next string will start */ 299 nPos += (UINT)lstrlen(szText) + 1; 300 301 /* Add another NULL for REG_MULTI_SZ */ 302 szPagingFiles[nPos] = _T('\0'); 303 nPos++; 304 } 305 } 306 307 if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, 308 lpKey, 309 0, 310 NULL, 311 REG_OPTION_NON_VOLATILE, 312 KEY_WRITE, 313 NULL, 314 &hk, 315 NULL) == ERROR_SUCCESS) 316 { 317 if (RegSetValueEx(hk, 318 _T("PagingFiles"), 319 0, 320 REG_MULTI_SZ, 321 (LPBYTE)szPagingFiles, 322 (DWORD)nPos * sizeof(TCHAR)) == ERROR_SUCCESS) 323 { 324 bErr = FALSE; 325 } 326 327 RegCloseKey(hk); 328 } 329 330 if (bErr == FALSE) 331 { 332 /* Delete obsolete paging files on the next boot */ 333 for (i = 0; i < _countof(pVirtMem->PageFile); i++) 334 { 335 if (pVirtMem->PageFile[i].OldMinSize != -1 && 336 pVirtMem->PageFile[i].NewMinSize == -1) 337 { 338 _stprintf(szText, 339 _T("%s\\pagefile.sys"), 340 pVirtMem->PageFile[i].szDrive); 341 342 MoveFileEx(szText, NULL, MOVEFILE_DELAY_UNTIL_REBOOT); 343 } 344 } 345 } 346 347 if (bErr) 348 ShowLastWin32Error(pVirtMem->hSelf); 349 } 350 351 352 static VOID 353 SetListBoxColumns(HWND hwndListBox) 354 { 355 RECT rect = {0, 0, 103, 0}; 356 MapDialogRect(hwndListBox, &rect); 357 358 SendMessage(hwndListBox, LB_SETTABSTOPS, (WPARAM)1, (LPARAM)&rect.right); 359 } 360 361 362 static VOID 363 OnNoPagingFile(PVIRTMEM pVirtMem) 364 { 365 /* Disable the page file custom size boxes */ 366 EnableWindow(GetDlgItem(pVirtMem->hSelf, IDC_INITIALSIZE), FALSE); 367 EnableWindow(GetDlgItem(pVirtMem->hSelf, IDC_MAXSIZE), FALSE); 368 } 369 370 371 static VOID 372 OnSysManSize(PVIRTMEM pVirtMem) 373 { 374 /* Disable the page file custom size boxes */ 375 EnableWindow(GetDlgItem(pVirtMem->hSelf, IDC_INITIALSIZE), FALSE); 376 EnableWindow(GetDlgItem(pVirtMem->hSelf, IDC_MAXSIZE), FALSE); 377 } 378 379 380 static VOID 381 OnCustom(PVIRTMEM pVirtMem) 382 { 383 /* Enable the page file custom size boxes */ 384 EnableWindow(GetDlgItem(pVirtMem->hSelf, IDC_INITIALSIZE), TRUE); 385 EnableWindow(GetDlgItem(pVirtMem->hSelf, IDC_MAXSIZE), TRUE); 386 } 387 388 389 static BOOL OnSelChange(PVIRTMEM pVirtMem); 390 391 static VOID 392 InitPagefileList(PVIRTMEM pVirtMem) 393 { 394 INT Index; 395 UINT i; 396 PPAGEFILE PageFile; 397 TCHAR szSize[64]; 398 TCHAR szDisplayString[256]; 399 400 for (i = 0; i < _countof(pVirtMem->PageFile); i++) 401 { 402 PageFile = &pVirtMem->PageFile[i]; 403 404 if (PageFile->bUsed) 405 { 406 if ((PageFile->NewMinSize == -1) && 407 (PageFile->NewMaxSize == -1)) 408 { 409 LoadString(hApplet, 410 IDS_PAGEFILE_NONE, 411 szSize, 412 _countof(szSize)); 413 } 414 else if ((PageFile->NewMinSize == 0) && 415 (PageFile->NewMaxSize == 0)) 416 { 417 LoadString(hApplet, 418 IDS_PAGEFILE_SYSTEM, 419 szSize, 420 _countof(szSize)); 421 } 422 else 423 { 424 _stprintf(szSize, _T("%d - %d"), 425 PageFile->NewMinSize, 426 PageFile->NewMaxSize); 427 } 428 429 _stprintf(szDisplayString, 430 _T("%s [%s]\t%s"), 431 PageFile->szDrive, 432 PageFile->pszVolume ? PageFile->pszVolume : _T(""), 433 szSize); 434 435 Index = SendMessage(pVirtMem->hListBox, LB_ADDSTRING, (WPARAM)0, (LPARAM)szDisplayString); 436 SendMessage(pVirtMem->hListBox, LB_SETITEMDATA, Index, i); 437 } 438 } 439 440 SendMessage(pVirtMem->hListBox, LB_SETCURSEL, (WPARAM)0, (LPARAM)0); 441 442 OnSelChange(pVirtMem); 443 } 444 445 446 static VOID 447 UpdatePagefileEntry(PVIRTMEM pVirtMem, 448 INT ListIndex, 449 INT DriveIndex) 450 { 451 PPAGEFILE PageFile = &pVirtMem->PageFile[DriveIndex]; 452 TCHAR szSize[64]; 453 TCHAR szDisplayString[256]; 454 455 if ((PageFile->NewMinSize == -1) && 456 (PageFile->NewMaxSize == -1)) 457 { 458 LoadString(hApplet, 459 IDS_PAGEFILE_NONE, 460 szSize, 461 _countof(szSize)); 462 } 463 else if ((PageFile->NewMinSize == 0) && 464 (PageFile->NewMaxSize == 0)) 465 { 466 LoadString(hApplet, 467 IDS_PAGEFILE_SYSTEM, 468 szSize, 469 _countof(szSize)); 470 } 471 else 472 { 473 _stprintf(szSize, 474 _T("%d - %d"), 475 PageFile->NewMinSize, 476 PageFile->NewMaxSize); 477 } 478 479 _stprintf(szDisplayString, 480 _T("%s [%s]\t%s"), 481 PageFile->szDrive, 482 PageFile->pszVolume ? PageFile->pszVolume : _T(""), 483 szSize); 484 485 SendMessage(pVirtMem->hListBox, LB_DELETESTRING, (WPARAM)ListIndex, 0); 486 SendMessage(pVirtMem->hListBox, LB_INSERTSTRING, (WPARAM)ListIndex, (LPARAM)szDisplayString); 487 SendMessage(pVirtMem->hListBox, LB_SETCURSEL, (WPARAM)ListIndex, 0); 488 } 489 490 491 static VOID 492 OnSet(PVIRTMEM pVirtMem) 493 { 494 INT Index; 495 UINT MinSize = -1; 496 UINT MaxSize = -1; 497 BOOL bTranslated; 498 UINT DriveIndex; 499 PPAGEFILE PageFile; 500 501 Index = (INT)SendDlgItemMessage(pVirtMem->hSelf, 502 IDC_PAGEFILELIST, 503 LB_GETCURSEL, 504 0, 505 0); 506 if (Index >= 0 && Index < pVirtMem->Count) 507 { 508 DriveIndex = SendDlgItemMessage(pVirtMem->hSelf, 509 IDC_PAGEFILELIST, 510 LB_GETITEMDATA, 511 (WPARAM)Index, 512 0); 513 514 PageFile = &pVirtMem->PageFile[DriveIndex]; 515 516 /* Check if custom settings are checked */ 517 if (IsDlgButtonChecked(pVirtMem->hSelf, 518 IDC_CUSTOM) == BST_CHECKED) 519 { 520 UINT maxPageFileSize; 521 522 MinSize = GetDlgItemInt(pVirtMem->hSelf, 523 IDC_INITIALSIZE, 524 &bTranslated, 525 FALSE); 526 if (!bTranslated) 527 { 528 ResourceMessageBox(hApplet, 529 NULL, 530 MB_ICONWARNING | MB_OK, 531 IDS_MESSAGEBOXTITLE, 532 IDS_WARNINITIALSIZE); 533 return; 534 } 535 536 MaxSize = GetDlgItemInt(pVirtMem->hSelf, 537 IDC_MAXSIZE, 538 &bTranslated, 539 FALSE); 540 if (!bTranslated) 541 { 542 ResourceMessageBox(hApplet, 543 NULL, 544 MB_ICONWARNING | MB_OK, 545 IDS_MESSAGEBOXTITLE, 546 IDS_WARNMAXIMUMSIZE); 547 return; 548 } 549 550 maxPageFileSize = GetMaxPageFileSize(PageFile); 551 552 /* Check the valid range of the minimum size */ 553 if ((MinSize < MINIMUM_PAGEFILE_SIZE) || 554 (MinSize > maxPageFileSize)) 555 { 556 ResourceMessageBox(hApplet, 557 NULL, 558 MB_ICONWARNING | MB_OK, 559 IDS_MESSAGEBOXTITLE, 560 IDS_WARNINITIALRANGE, 561 maxPageFileSize); 562 return; 563 } 564 565 /* Check the valid range of the maximum size */ 566 if ((MaxSize < MinSize) || 567 (MaxSize > maxPageFileSize)) 568 { 569 ResourceMessageBox(hApplet, 570 NULL, 571 MB_ICONWARNING | MB_OK, 572 IDS_MESSAGEBOXTITLE, 573 IDS_WARNMAXIMUMRANGE, 574 maxPageFileSize); 575 return; 576 } 577 578 // TODO: Check how much disk space would remain after 579 // storing a pagefile of a certain size. Warn/error out 580 // if less than 5 MB would remain. 581 582 PageFile->NewMinSize = MinSize; 583 PageFile->NewMaxSize = MaxSize; 584 PageFile->bUsed = TRUE; 585 } 586 else if (IsDlgButtonChecked(pVirtMem->hSelf, 587 IDC_NOPAGEFILE) == BST_CHECKED) 588 { 589 /* No pagefile */ 590 PageFile->NewMinSize = -1; 591 PageFile->NewMaxSize = -1; 592 PageFile->bUsed = TRUE; 593 } 594 else 595 { 596 /* System managed size*/ 597 PageFile->NewMinSize = 0; 598 PageFile->NewMaxSize = 0; 599 PageFile->bUsed = TRUE; 600 } 601 602 /* Set the modified flag if min or max size has changed */ 603 if ((PageFile->OldMinSize != PageFile->NewMinSize) || 604 (PageFile->OldMaxSize != PageFile->NewMaxSize)) 605 { 606 pVirtMem->bModified = TRUE; 607 } 608 609 UpdatePagefileEntry(pVirtMem, Index, DriveIndex); 610 } 611 } 612 613 614 static BOOL 615 OnSelChange(PVIRTMEM pVirtMem) 616 { 617 INT Index; 618 UINT DriveIndex; 619 PPAGEFILE PageFile; 620 MEMORYSTATUSEX MemoryStatus; 621 ULARGE_INTEGER FreeDiskSpace; 622 UINT i, PageFileSizeMb; 623 TCHAR szMegabytes[8]; 624 TCHAR szBuffer[64]; 625 TCHAR szText[MAX_PATH]; 626 WIN32_FIND_DATA fdata = {0}; 627 HANDLE hFind; 628 ULARGE_INTEGER pfSize; 629 630 Index = (INT)SendDlgItemMessage(pVirtMem->hSelf, 631 IDC_PAGEFILELIST, 632 LB_GETCURSEL, 633 0, 634 0); 635 if (Index >= 0 && Index < pVirtMem->Count) 636 { 637 DriveIndex = SendDlgItemMessage(pVirtMem->hSelf, 638 IDC_PAGEFILELIST, 639 LB_GETITEMDATA, 640 (WPARAM)Index, 641 0); 642 643 PageFile = &pVirtMem->PageFile[DriveIndex]; 644 645 LoadString(hApplet, 646 IDS_PAGEFILE_MB, 647 szMegabytes, 648 _countof(szMegabytes)); 649 650 /* Set drive letter */ 651 SetDlgItemText(pVirtMem->hSelf, IDC_DRIVE, 652 PageFile->szDrive); 653 654 /* Set available disk space */ 655 if (GetDiskFreeSpaceEx(PageFile->szDrive, 656 NULL, NULL, &FreeDiskSpace)) 657 { 658 PageFile->FreeSize = (UINT)(FreeDiskSpace.QuadPart / MEGABYTE); 659 _stprintf(szBuffer, szMegabytes, PageFile->FreeSize); 660 SetDlgItemText(pVirtMem->hSelf, IDC_SPACEAVAIL, szBuffer); 661 } 662 663 if (PageFile->NewMinSize == -1 && 664 PageFile->NewMaxSize == -1) 665 { 666 /* No pagefile */ 667 OnNoPagingFile(pVirtMem); 668 CheckDlgButton(pVirtMem->hSelf, IDC_NOPAGEFILE, BST_CHECKED); 669 } 670 else if (PageFile->NewMinSize == 0 && 671 PageFile->NewMaxSize == 0) 672 { 673 /* System managed size */ 674 OnSysManSize(pVirtMem); 675 CheckDlgButton(pVirtMem->hSelf, IDC_SYSMANSIZE, BST_CHECKED); 676 } 677 else 678 { 679 /* Custom size */ 680 681 /* Enable and fill the custom values */ 682 OnCustom(pVirtMem); 683 684 SetDlgItemInt(pVirtMem->hSelf, 685 IDC_INITIALSIZE, 686 PageFile->NewMinSize, 687 FALSE); 688 689 SetDlgItemInt(pVirtMem->hSelf, 690 IDC_MAXSIZE, 691 PageFile->NewMaxSize, 692 FALSE); 693 694 CheckDlgButton(pVirtMem->hSelf, 695 IDC_CUSTOM, 696 BST_CHECKED); 697 } 698 699 /* Set minimum pagefile size */ 700 _stprintf(szBuffer, szMegabytes, MINIMUM_PAGEFILE_SIZE); 701 SetDlgItemText(pVirtMem->hSelf, IDC_MINIMUM, szBuffer); 702 703 /* Set recommended pagefile size */ 704 MemoryStatus.dwLength = sizeof(MemoryStatus); 705 if (GlobalMemoryStatusEx(&MemoryStatus)) 706 { 707 UINT FreeMemMb, RecoMemMb; 708 UINT maxPageFileSize = GetMaxPageFileSize(PageFile); 709 710 FreeMemMb = (UINT)(MemoryStatus.ullTotalPhys / MEGABYTE); 711 /* The recommended VM size is 150% of free memory */ 712 RecoMemMb = FreeMemMb + (FreeMemMb / 2); 713 if (RecoMemMb > maxPageFileSize) 714 RecoMemMb = maxPageFileSize; 715 _stprintf(szBuffer, szMegabytes, RecoMemMb); 716 SetDlgItemText(pVirtMem->hSelf, IDC_RECOMMENDED, szBuffer); 717 } 718 719 /* Set current pagefile size */ 720 PageFileSizeMb = 0; 721 722 for (i = 0; i < pVirtMem->Count; i++) 723 { 724 _stprintf(szText, 725 _T("%c:\\pagefile.sys"), 726 pVirtMem->PageFile[i].szDrive[0]); 727 728 hFind = FindFirstFile(szText, &fdata); 729 if (hFind == INVALID_HANDLE_VALUE) 730 { 731 // FIXME: MsgBox error? 732 DPRINT1("Unable to read PageFile size: %ls due to error %d\n", 733 szText, GetLastError()); 734 } 735 else 736 { 737 pfSize.LowPart = fdata.nFileSizeLow; 738 pfSize.HighPart = fdata.nFileSizeHigh; 739 PageFileSizeMb += pfSize.QuadPart / MEGABYTE; 740 FindClose(hFind); 741 } 742 } 743 744 _stprintf(szBuffer, szMegabytes, PageFileSizeMb); 745 SetDlgItemText(pVirtMem->hSelf, IDC_CURRENT, szBuffer); 746 } 747 748 return TRUE; 749 } 750 751 752 static VOID 753 OnVirtMemDialogOk(PVIRTMEM pVirtMem) 754 { 755 if (pVirtMem->bModified != FALSE) 756 { 757 ResourceMessageBox(hApplet, 758 NULL, 759 MB_ICONINFORMATION | MB_OK, 760 IDS_MESSAGEBOXTITLE, 761 IDS_INFOREBOOT); 762 763 WritePageFileSettings(pVirtMem); 764 } 765 } 766 767 768 static VOID 769 OnInitVirtMemDialog(HWND hwnd, PVIRTMEM pVirtMem) 770 { 771 UINT i; 772 PPAGEFILE PageFile; 773 774 pVirtMem->hSelf = hwnd; 775 pVirtMem->hListBox = GetDlgItem(hwnd, IDC_PAGEFILELIST); 776 pVirtMem->bModified = FALSE; 777 778 SetListBoxColumns(pVirtMem->hListBox); 779 780 for (i = 0; i < _countof(pVirtMem->PageFile); i++) 781 { 782 PageFile = &pVirtMem->PageFile[i]; 783 PageFile->bUsed = FALSE; 784 PageFile->OldMinSize = -1; 785 PageFile->OldMaxSize = -1; 786 PageFile->NewMinSize = -1; 787 PageFile->NewMaxSize = -1; 788 PageFile->FreeSize = 0; 789 PageFile->bIsNotFAT = TRUE; /* Suppose this is not a FAT volume */ 790 } 791 792 /* Load the pagefile systems from the reg */ 793 ReadPageFileSettings(pVirtMem); 794 795 /* Parse our settings and set up dialog */ 796 ParseMemSettings(pVirtMem); 797 798 InitPagefileList(pVirtMem); 799 } 800 801 802 static VOID 803 OnDestroy(PVIRTMEM pVirtMem) 804 { 805 UINT i; 806 807 for (i = 0; i < _countof(pVirtMem->PageFile); i++) 808 { 809 if (pVirtMem->PageFile[i].pszVolume != NULL) 810 HeapFree(GetProcessHeap(), 0, pVirtMem->PageFile[i].pszVolume); 811 } 812 813 if (pVirtMem->szPagingFiles) 814 HeapFree(GetProcessHeap(), 0, pVirtMem->szPagingFiles); 815 816 HeapFree(GetProcessHeap(), 0, pVirtMem); 817 } 818 819 820 INT_PTR CALLBACK 821 VirtMemDlgProc(HWND hwndDlg, 822 UINT uMsg, 823 WPARAM wParam, 824 LPARAM lParam) 825 { 826 PVIRTMEM pVirtMem; 827 828 UNREFERENCED_PARAMETER(lParam); 829 830 pVirtMem = (PVIRTMEM)GetWindowLongPtr(hwndDlg, DWLP_USER); 831 832 switch (uMsg) 833 { 834 case WM_INITDIALOG: 835 { 836 pVirtMem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(VIRTMEM)); 837 if (pVirtMem == NULL) 838 { 839 EndDialog(hwndDlg, 0); 840 return FALSE; 841 } 842 843 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pVirtMem); 844 845 OnInitVirtMemDialog(hwndDlg, pVirtMem); 846 break; 847 } 848 849 case WM_DESTROY: 850 OnDestroy(pVirtMem); 851 break; 852 853 case WM_COMMAND: 854 switch (LOWORD(wParam)) 855 { 856 case IDCANCEL: 857 EndDialog(hwndDlg, 0); 858 return TRUE; 859 860 case IDOK: 861 OnVirtMemDialogOk(pVirtMem); 862 EndDialog(hwndDlg, pVirtMem->bModified); 863 return TRUE; 864 865 case IDC_NOPAGEFILE: 866 OnNoPagingFile(pVirtMem); 867 return TRUE; 868 869 case IDC_SYSMANSIZE: 870 OnSysManSize(pVirtMem); 871 return TRUE; 872 873 case IDC_CUSTOM: 874 OnCustom(pVirtMem); 875 return TRUE; 876 877 case IDC_SET: 878 OnSet(pVirtMem); 879 return TRUE; 880 881 case IDC_PAGEFILELIST: 882 switch (HIWORD(wParam)) 883 { 884 case LBN_SELCHANGE: 885 OnSelChange(pVirtMem); 886 return TRUE; 887 } 888 break; 889 } 890 break; 891 } 892 893 return FALSE; 894 } 895