2 * PROJECT: ReactOS system properties, control panel applet
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: dll/cpl/sysdm/virtual.c
5 * PURPOSE: Virtual memory control dialog
6 * COPYRIGHT: Copyright 2006 Ged Murphy <gedmurphy@gmail.com>
12 static BOOL
OnSelChange(HWND hwndDlg
, PVIRTMEM pVirtMem
);
13 static LPCTSTR lpKey
= _T("SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Memory Management");
16 ReadPageFileSettings(PVIRTMEM pVirtMem
)
23 if (RegCreateKeyEx(HKEY_LOCAL_MACHINE
,
27 REG_OPTION_NON_VOLATILE
,
31 NULL
) == ERROR_SUCCESS
)
33 if (RegQueryValueEx(hkey
,
38 &dwDataSize
) == ERROR_SUCCESS
)
40 pVirtMem
->szPagingFiles
= (LPTSTR
)HeapAlloc(GetProcessHeap(),
43 if (pVirtMem
->szPagingFiles
!= NULL
)
45 ZeroMemory(pVirtMem
->szPagingFiles
,
47 if (RegQueryValueEx(hkey
,
51 (PBYTE
)pVirtMem
->szPagingFiles
,
52 &dwDataSize
) == ERROR_SUCCESS
)
61 ShowLastWin32Error(pVirtMem
->hSelf
);
71 GetPageFileSizes(LPTSTR lpPageFiles
,
80 while (*lpPageFiles
!= _T('\0'))
82 if (*lpPageFiles
== _T(' '))
89 *lpInitialSize
= (INT
)_ttoi(lpPageFiles
);
94 *lpMaximumSize
= (INT
)_ttoi(lpPageFiles
);
105 ParseMemSettings(PVIRTMEM pVirtMem
)
107 TCHAR szDrives
[1024]; // All drives
108 LPTSTR DrivePtr
= szDrives
;
109 TCHAR szDrive
[3]; // Single drive
110 TCHAR szVolume
[MAX_PATH
+ 1];
117 DriveLen
= GetLogicalDriveStrings(1023,
120 while (DriveLen
!= 0)
122 Len
= lstrlen(DrivePtr
) + 1;
125 DrivePtr
= _tcsupr(DrivePtr
);
127 /* Copy the 'X:' portion */
128 lstrcpyn(szDrive
, DrivePtr
, sizeof(szDrive
) / sizeof(TCHAR
));
130 if (GetDriveType(DrivePtr
) == DRIVE_FIXED
)
135 /* Does drive match the one in the registry ? */
136 if (!_tcsncmp(pVirtMem
->szPagingFiles
, szDrive
, 2))
138 GetPageFileSizes(pVirtMem
->szPagingFiles
,
143 pVirtMem
->Pagefile
[PgCnt
].OldMinSize
= MinSize
;
144 pVirtMem
->Pagefile
[PgCnt
].OldMaxSize
= MaxSize
;
145 pVirtMem
->Pagefile
[PgCnt
].NewMinSize
= MinSize
;
146 pVirtMem
->Pagefile
[PgCnt
].NewMaxSize
= MaxSize
;
147 pVirtMem
->Pagefile
[PgCnt
].bUsed
= TRUE
;
148 lstrcpy(pVirtMem
->Pagefile
[PgCnt
].szDrive
, szDrive
);
151 /* Get the volume label if there is one */
152 if (GetVolumeInformation(DrivePtr
,
161 pVirtMem
->Pagefile
[PgCnt
].pszVolume
= HeapAlloc(GetProcessHeap(),
163 (_tcslen(szVolume
) + 1) * sizeof(TCHAR
));
164 if (pVirtMem
->Pagefile
[PgCnt
].pszVolume
!= NULL
)
165 _tcscpy(pVirtMem
->Pagefile
[PgCnt
].pszVolume
, szVolume
);
174 pVirtMem
->Count
= PgCnt
;
179 WritePageFileSettings(PVIRTMEM pVirtMem
)
182 TCHAR szPagingFiles
[2048];
187 for (i
= 0; i
< pVirtMem
->Count
; ++i
)
189 if (pVirtMem
->Pagefile
[i
].bUsed
&&
190 pVirtMem
->Pagefile
[i
].NewMinSize
!= -1 &&
191 pVirtMem
->Pagefile
[i
].NewMaxSize
!= -1)
194 _T("%s\\pagefile.sys %i %i"),
195 pVirtMem
->Pagefile
[i
].szDrive
,
196 pVirtMem
->Pagefile
[i
].NewMinSize
,
197 pVirtMem
->Pagefile
[i
].NewMaxSize
);
199 /* Add it to our overall registry string */
200 lstrcpy(szPagingFiles
+ nPos
, szText
);
202 /* Record the position where the next string will start */
203 nPos
+= (INT
)lstrlen(szText
) + 1;
205 /* Add another NULL for REG_MULTI_SZ */
206 szPagingFiles
[nPos
] = _T('\0');
211 if (RegCreateKeyEx(HKEY_LOCAL_MACHINE
,
215 REG_OPTION_NON_VOLATILE
,
219 NULL
) == ERROR_SUCCESS
)
221 if (RegSetValueEx(hk
,
225 (LPBYTE
) szPagingFiles
,
226 (DWORD
) nPos
* sizeof(TCHAR
)) == ERROR_SUCCESS
)
236 /* Delete obsolete paging files on the next boot */
237 for (i
= 0; i
< 26; i
++)
239 if (pVirtMem
->Pagefile
[i
].OldMinSize
!= -1 &&
240 pVirtMem
->Pagefile
[i
].NewMinSize
== -1)
243 _T("%s\\pagefile.sys"),
244 pVirtMem
->Pagefile
[i
].szDrive
);
246 MoveFileEx(szText
, NULL
, MOVEFILE_DELAY_UNTIL_REBOOT
);
252 ShowLastWin32Error(pVirtMem
->hSelf
);
258 SetListBoxColumns(HWND hwndListBox
)
260 RECT rect
= {0, 0, 103, 0};
261 MapDialogRect(hwndListBox
, &rect
);
263 SendMessage(hwndListBox
, LB_SETTABSTOPS
, (WPARAM
)1, (LPARAM
)&rect
.right
);
268 OnNoPagingFile(PVIRTMEM pVirtMem
)
270 /* Disable the page file custom size boxes */
271 EnableWindow(GetDlgItem(pVirtMem
->hSelf
, IDC_INITIALSIZE
), FALSE
);
272 EnableWindow(GetDlgItem(pVirtMem
->hSelf
, IDC_MAXSIZE
), FALSE
);
277 OnSysManSize(PVIRTMEM pVirtMem
)
279 /* Disable the page file custom size boxes */
280 EnableWindow(GetDlgItem(pVirtMem
->hSelf
, IDC_INITIALSIZE
), FALSE
);
281 EnableWindow(GetDlgItem(pVirtMem
->hSelf
, IDC_MAXSIZE
), FALSE
);
286 OnCustom(PVIRTMEM pVirtMem
)
288 /* Enable the page file custom size boxes */
289 EnableWindow(GetDlgItem(pVirtMem
->hSelf
, IDC_INITIALSIZE
), TRUE
);
290 EnableWindow(GetDlgItem(pVirtMem
->hSelf
, IDC_MAXSIZE
), TRUE
);
295 InitPagefileList(PVIRTMEM pVirtMem
)
297 TCHAR szDisplayString
[256];
302 for (i
= 0; i
< 26; i
++)
304 if (pVirtMem
->Pagefile
[i
].bUsed
)
306 if ((pVirtMem
->Pagefile
[i
].NewMinSize
== -1) &&
307 (pVirtMem
->Pagefile
[i
].NewMaxSize
== -1))
312 sizeof(szSize
) / sizeof(szSize
[0]));
314 else if ((pVirtMem
->Pagefile
[i
].NewMinSize
== 0) &&
315 (pVirtMem
->Pagefile
[i
].NewMaxSize
== 0))
320 sizeof(szSize
) / sizeof(szSize
[0]));
324 _stprintf(szSize
, _T("%d - %d"),
325 pVirtMem
->Pagefile
[i
].NewMinSize
,
326 pVirtMem
->Pagefile
[i
].NewMaxSize
);
329 _stprintf(szDisplayString
,
331 pVirtMem
->Pagefile
[i
].szDrive
,
332 pVirtMem
->Pagefile
[i
].pszVolume
? pVirtMem
->Pagefile
[i
].pszVolume
: _T(""),
335 Index
= SendMessage(pVirtMem
->hListBox
, LB_ADDSTRING
, (WPARAM
)0, (LPARAM
)szDisplayString
);
336 SendMessage(pVirtMem
->hListBox
, LB_SETITEMDATA
, Index
, i
);
340 SendMessage(pVirtMem
->hListBox
, LB_SETCURSEL
, (WPARAM
)0, (LPARAM
)0);
342 OnSelChange(pVirtMem
->hSelf
, pVirtMem
);
347 UpdatePagefileEntry(PVIRTMEM pVirtMem
,
351 TCHAR szDisplayString
[256];
354 if ((pVirtMem
->Pagefile
[DriveIndex
].NewMinSize
== -1) &&
355 (pVirtMem
->Pagefile
[DriveIndex
].NewMaxSize
== -1))
360 sizeof(szSize
) / sizeof(szSize
[0]));
362 else if ((pVirtMem
->Pagefile
[DriveIndex
].NewMinSize
== 0) &&
363 (pVirtMem
->Pagefile
[DriveIndex
].NewMaxSize
== 0))
368 sizeof(szSize
) / sizeof(szSize
[0]));
374 pVirtMem
->Pagefile
[DriveIndex
].NewMinSize
,
375 pVirtMem
->Pagefile
[DriveIndex
].NewMaxSize
);
378 _stprintf(szDisplayString
,
380 pVirtMem
->Pagefile
[DriveIndex
].szDrive
,
381 pVirtMem
->Pagefile
[DriveIndex
].pszVolume
? pVirtMem
->Pagefile
[DriveIndex
].pszVolume
: L
"",
384 SendMessage(pVirtMem
->hListBox
, LB_DELETESTRING
, (WPARAM
)ListIndex
, 0);
385 SendMessage(pVirtMem
->hListBox
, LB_INSERTSTRING
, (WPARAM
)ListIndex
, (LPARAM
)szDisplayString
);
386 SendMessage(pVirtMem
->hListBox
, LB_SETCURSEL
, (WPARAM
)ListIndex
, 0);
391 OnSet(PVIRTMEM pVirtMem
)
399 Index
= (INT
)SendDlgItemMessage(pVirtMem
->hSelf
,
404 if (Index
>= 0 && Index
< pVirtMem
->Count
)
406 DriveIndex
= SendDlgItemMessage(pVirtMem
->hSelf
,
412 /* Check if custom settings are checked */
413 if (IsDlgButtonChecked(pVirtMem
->hSelf
,
414 IDC_CUSTOM
) == BST_CHECKED
)
416 MinSize
= GetDlgItemInt(pVirtMem
->hSelf
,
422 ResourceMessageBox(hApplet
,
424 MB_ICONWARNING
| MB_OK
,
426 IDS_WARNINITIALSIZE
);
430 MaxSize
= GetDlgItemInt(pVirtMem
->hSelf
,
436 ResourceMessageBox(hApplet
,
438 MB_ICONWARNING
| MB_OK
,
440 IDS_WARNMAXIMUMSIZE
);
444 /* Check the valid range of the minimum size */
446 MinSize
> pVirtMem
->Pagefile
[DriveIndex
].FreeSize
)
448 ResourceMessageBox(hApplet
,
450 MB_ICONWARNING
| MB_OK
,
452 IDS_WARNINITIALRANGE
);
456 /* Check the valid range of the maximum size */
457 if (MaxSize
< MinSize
||
458 MaxSize
> pVirtMem
->Pagefile
[DriveIndex
].FreeSize
)
460 ResourceMessageBox(hApplet
,
462 MB_ICONWARNING
| MB_OK
,
464 IDS_WARNMAXIMUMRANGE
);
468 pVirtMem
->Pagefile
[DriveIndex
].NewMinSize
= MinSize
;
469 pVirtMem
->Pagefile
[DriveIndex
].NewMaxSize
= MaxSize
;
470 pVirtMem
->Pagefile
[DriveIndex
].bUsed
= TRUE
;
472 else if (IsDlgButtonChecked(pVirtMem
->hSelf
,
473 IDC_NOPAGEFILE
) == BST_CHECKED
)
476 pVirtMem
->Pagefile
[DriveIndex
].NewMinSize
= -1;
477 pVirtMem
->Pagefile
[DriveIndex
].NewMaxSize
= -1;
478 pVirtMem
->Pagefile
[DriveIndex
].bUsed
= TRUE
;
482 /* System managed size*/
483 pVirtMem
->Pagefile
[DriveIndex
].NewMinSize
= 0;
484 pVirtMem
->Pagefile
[DriveIndex
].NewMaxSize
= 0;
485 pVirtMem
->Pagefile
[DriveIndex
].bUsed
= TRUE
;
488 /* Set the modified flag if min or max size has changed */
489 if ((pVirtMem
->Pagefile
[DriveIndex
].OldMinSize
!= pVirtMem
->Pagefile
[DriveIndex
].NewMinSize
) ||
490 (pVirtMem
->Pagefile
[DriveIndex
].OldMaxSize
!= pVirtMem
->Pagefile
[DriveIndex
].NewMaxSize
))
491 pVirtMem
->bModified
= TRUE
;
493 UpdatePagefileEntry(pVirtMem
, Index
, DriveIndex
);
499 OnSelChange(HWND hwndDlg
, PVIRTMEM pVirtMem
)
502 MEMORYSTATUSEX MemoryStatus
;
503 ULARGE_INTEGER FreeDiskSpace
;
504 UINT
/*i,*/ FreeMemMb
/*, PageFileSizeMb*/;
507 Index
= (INT
)SendDlgItemMessage(hwndDlg
,
512 if (Index
>= 0 && Index
< pVirtMem
->Count
)
514 /* Set drive letter */
515 SetDlgItemText(hwndDlg
, IDC_DRIVE
,
516 pVirtMem
->Pagefile
[Index
].szDrive
);
518 /* Set available disk space */
519 if (GetDiskFreeSpaceEx(pVirtMem
->Pagefile
[Index
].szDrive
,
520 NULL
, NULL
, &FreeDiskSpace
))
522 pVirtMem
->Pagefile
[Index
].FreeSize
= (UINT
)(FreeDiskSpace
.QuadPart
/ (1024 * 1024));
523 _stprintf(szBuffer
, _T("%u MB"), pVirtMem
->Pagefile
[Index
].FreeSize
);
524 SetDlgItemText(hwndDlg
, IDC_SPACEAVAIL
, szBuffer
);
527 if (pVirtMem
->Pagefile
[Index
].NewMinSize
== -1 &&
528 pVirtMem
->Pagefile
[Index
].NewMaxSize
== -1)
532 EnableWindow(GetDlgItem(pVirtMem
->hSelf
, IDC_MAXSIZE
), FALSE
);
533 EnableWindow(GetDlgItem(pVirtMem
->hSelf
, IDC_INITIALSIZE
), FALSE
);
535 CheckDlgButton(pVirtMem
->hSelf
, IDC_NOPAGEFILE
, BST_CHECKED
);
537 else if (pVirtMem
->Pagefile
[Index
].NewMinSize
== 0 &&
538 pVirtMem
->Pagefile
[Index
].NewMaxSize
== 0)
540 /* System managed size*/
542 EnableWindow(GetDlgItem(pVirtMem
->hSelf
, IDC_MAXSIZE
), FALSE
);
543 EnableWindow(GetDlgItem(pVirtMem
->hSelf
, IDC_INITIALSIZE
), FALSE
);
545 CheckDlgButton(pVirtMem
->hSelf
, IDC_SYSMANSIZE
, BST_CHECKED
);
551 /* Enable and fill the custom values */
552 EnableWindow(GetDlgItem(pVirtMem
->hSelf
, IDC_MAXSIZE
), TRUE
);
553 EnableWindow(GetDlgItem(pVirtMem
->hSelf
, IDC_INITIALSIZE
), TRUE
);
555 SetDlgItemInt(pVirtMem
->hSelf
,
557 pVirtMem
->Pagefile
[Index
].NewMinSize
,
560 SetDlgItemInt(pVirtMem
->hSelf
,
562 pVirtMem
->Pagefile
[Index
].NewMaxSize
,
565 CheckDlgButton(pVirtMem
->hSelf
,
570 /* Set minimum pagefile size */
571 SetDlgItemText(hwndDlg
, IDC_MINIMUM
, _T("2 MB"));
573 /* Set recommended pagefile size */
574 MemoryStatus
.dwLength
= sizeof(MEMORYSTATUSEX
);
575 if (GlobalMemoryStatusEx(&MemoryStatus
))
577 FreeMemMb
= (UINT
)(MemoryStatus
.ullTotalPhys
/ (1024 * 1024));
578 _stprintf(szBuffer
, _T("%u MB"), FreeMemMb
+ (FreeMemMb
/ 2));
579 SetDlgItemText(hwndDlg
, IDC_RECOMMENDED
, szBuffer
);
582 /* Set current pagefile size */
585 for (i
= 0; i
< 26; i
++)
587 PageFileSizeMb
+= pVirtMem
->Pagefile
[i
].InitialSize
;
589 _stprintf(szBuffer
, _T("%u MB"), PageFileSizeMb
);
590 SetDlgItemText(hwndDlg
, IDC_CURRENT
, szBuffer
);
599 OnOk(PVIRTMEM pVirtMem
)
601 if (pVirtMem
->bModified
== TRUE
)
603 ResourceMessageBox(hApplet
,
605 MB_ICONINFORMATION
| MB_OK
,
609 WritePageFileSettings(pVirtMem
);
615 OnInitDialog(HWND hwnd
, PVIRTMEM pVirtMem
)
619 pVirtMem
->hSelf
= hwnd
;
620 pVirtMem
->hListBox
= GetDlgItem(hwnd
, IDC_PAGEFILELIST
);
621 pVirtMem
->bModified
= FALSE
;
623 SetListBoxColumns(pVirtMem
->hListBox
);
625 for (i
= 0; i
< 26; i
++)
627 pVirtMem
->Pagefile
[i
].bUsed
= FALSE
;
628 pVirtMem
->Pagefile
[i
].OldMinSize
= -1;
629 pVirtMem
->Pagefile
[i
].OldMaxSize
= -1;
630 pVirtMem
->Pagefile
[i
].NewMinSize
= -1;
631 pVirtMem
->Pagefile
[i
].NewMaxSize
= -1;
634 /* Load the pagefile systems from the reg */
635 ReadPageFileSettings(pVirtMem
);
637 /* Parse our settings and set up dialog */
638 ParseMemSettings(pVirtMem
);
640 InitPagefileList(pVirtMem
);
645 OnDestroy(PVIRTMEM pVirtMem
)
649 for (i
= 0; i
< 26; i
++)
651 if (pVirtMem
->Pagefile
[i
].pszVolume
!= NULL
)
652 HeapFree(GetProcessHeap(), 0, pVirtMem
->Pagefile
[i
].pszVolume
);
655 if (pVirtMem
->szPagingFiles
)
656 HeapFree(GetProcessHeap(), 0, pVirtMem
->szPagingFiles
);
658 HeapFree(GetProcessHeap(), 0, pVirtMem
);
663 VirtMemDlgProc(HWND hwndDlg
,
670 UNREFERENCED_PARAMETER(lParam
);
672 pVirtMem
= (PVIRTMEM
)GetWindowLongPtr(hwndDlg
, DWLP_USER
);
677 pVirtMem
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(VIRTMEM
));
678 if (pVirtMem
== NULL
)
680 EndDialog(hwndDlg
, 0);
684 SetWindowLongPtr(hwndDlg
, DWLP_USER
, (LONG_PTR
)pVirtMem
);
686 OnInitDialog(hwndDlg
, pVirtMem
);
694 switch (LOWORD(wParam
))
697 EndDialog(hwndDlg
, 0);
702 EndDialog(hwndDlg
, pVirtMem
->bModified
);
706 OnNoPagingFile(pVirtMem
);
710 OnSysManSize(pVirtMem
);
721 case IDC_PAGEFILELIST
:
722 switch (HIWORD(wParam
))
725 OnSelChange(hwndDlg
, pVirtMem
);