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
GetMaxPageFileSize(_In_ PPAGEFILE PageFile)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
ReadPageFileSettings(PVIRTMEM pVirtMem)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
GetPageFileSizes(LPTSTR lpPageFiles,LPINT lpInitialSize,LPINT lpMaximumSize)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
ParseMemSettings(PVIRTMEM pVirtMem)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
WritePageFileSettings(PVIRTMEM pVirtMem)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
SetListBoxColumns(HWND hwndListBox)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
OnNoPagingFile(PVIRTMEM pVirtMem)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
OnSysManSize(PVIRTMEM pVirtMem)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
OnCustom(PVIRTMEM pVirtMem)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
InitPagefileList(PVIRTMEM pVirtMem)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
UpdatePagefileEntry(PVIRTMEM pVirtMem,INT ListIndex,INT DriveIndex)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
OnSet(PVIRTMEM pVirtMem)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
OnSelChange(PVIRTMEM pVirtMem)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
OnVirtMemDialogOk(PVIRTMEM pVirtMem)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
OnInitVirtMemDialog(HWND hwnd,PVIRTMEM pVirtMem)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
OnDestroy(PVIRTMEM pVirtMem)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
VirtMemDlgProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)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