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>
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
||
461 ResourceMessageBox(hApplet
,
463 MB_ICONWARNING
| MB_OK
,
465 IDS_WARNMAXIMUMRANGE
);
469 pVirtMem
->Pagefile
[DriveIndex
].NewMinSize
= MinSize
;
470 pVirtMem
->Pagefile
[DriveIndex
].NewMaxSize
= MaxSize
;
471 pVirtMem
->Pagefile
[DriveIndex
].bUsed
= TRUE
;
473 else if (IsDlgButtonChecked(pVirtMem
->hSelf
,
474 IDC_NOPAGEFILE
) == BST_CHECKED
)
477 pVirtMem
->Pagefile
[DriveIndex
].NewMinSize
= -1;
478 pVirtMem
->Pagefile
[DriveIndex
].NewMaxSize
= -1;
479 pVirtMem
->Pagefile
[DriveIndex
].bUsed
= TRUE
;
483 /* System managed size*/
484 pVirtMem
->Pagefile
[DriveIndex
].NewMinSize
= 0;
485 pVirtMem
->Pagefile
[DriveIndex
].NewMaxSize
= 0;
486 pVirtMem
->Pagefile
[DriveIndex
].bUsed
= TRUE
;
489 /* Set the modified flag if min or max size has changed */
490 if ((pVirtMem
->Pagefile
[DriveIndex
].OldMinSize
!= pVirtMem
->Pagefile
[DriveIndex
].NewMinSize
) ||
491 (pVirtMem
->Pagefile
[DriveIndex
].OldMaxSize
!= pVirtMem
->Pagefile
[DriveIndex
].NewMaxSize
))
492 pVirtMem
->bModified
= TRUE
;
494 UpdatePagefileEntry(pVirtMem
, Index
, DriveIndex
);
500 OnSelChange(HWND hwndDlg
, PVIRTMEM pVirtMem
)
503 MEMORYSTATUSEX MemoryStatus
;
504 ULARGE_INTEGER FreeDiskSpace
;
505 UINT
/*i,*/ FreeMemMb
/*, PageFileSizeMb*/;
508 Index
= (INT
)SendDlgItemMessage(hwndDlg
,
513 if (Index
>= 0 && Index
< pVirtMem
->Count
)
515 /* Set drive letter */
516 SetDlgItemText(hwndDlg
, IDC_DRIVE
,
517 pVirtMem
->Pagefile
[Index
].szDrive
);
519 /* Set available disk space */
520 if (GetDiskFreeSpaceEx(pVirtMem
->Pagefile
[Index
].szDrive
,
521 NULL
, NULL
, &FreeDiskSpace
))
523 pVirtMem
->Pagefile
[Index
].FreeSize
= (UINT
)(FreeDiskSpace
.QuadPart
/ (1024 * 1024));
524 _stprintf(szBuffer
, _T("%u MB"), pVirtMem
->Pagefile
[Index
].FreeSize
);
525 SetDlgItemText(hwndDlg
, IDC_SPACEAVAIL
, szBuffer
);
528 if (pVirtMem
->Pagefile
[Index
].NewMinSize
== -1 &&
529 pVirtMem
->Pagefile
[Index
].NewMaxSize
== -1)
533 EnableWindow(GetDlgItem(pVirtMem
->hSelf
, IDC_MAXSIZE
), FALSE
);
534 EnableWindow(GetDlgItem(pVirtMem
->hSelf
, IDC_INITIALSIZE
), FALSE
);
536 CheckDlgButton(pVirtMem
->hSelf
, IDC_NOPAGEFILE
, BST_CHECKED
);
538 else if (pVirtMem
->Pagefile
[Index
].NewMinSize
== 0 &&
539 pVirtMem
->Pagefile
[Index
].NewMaxSize
== 0)
541 /* System managed size*/
543 EnableWindow(GetDlgItem(pVirtMem
->hSelf
, IDC_MAXSIZE
), FALSE
);
544 EnableWindow(GetDlgItem(pVirtMem
->hSelf
, IDC_INITIALSIZE
), FALSE
);
546 CheckDlgButton(pVirtMem
->hSelf
, IDC_SYSMANSIZE
, BST_CHECKED
);
552 /* Enable and fill the custom values */
553 EnableWindow(GetDlgItem(pVirtMem
->hSelf
, IDC_MAXSIZE
), TRUE
);
554 EnableWindow(GetDlgItem(pVirtMem
->hSelf
, IDC_INITIALSIZE
), TRUE
);
556 SetDlgItemInt(pVirtMem
->hSelf
,
558 pVirtMem
->Pagefile
[Index
].NewMinSize
,
561 SetDlgItemInt(pVirtMem
->hSelf
,
563 pVirtMem
->Pagefile
[Index
].NewMaxSize
,
566 CheckDlgButton(pVirtMem
->hSelf
,
571 /* Set minimum pagefile size */
572 SetDlgItemText(hwndDlg
, IDC_MINIMUM
, _T("16 MB"));
574 /* Set recommended pagefile size */
575 MemoryStatus
.dwLength
= sizeof(MEMORYSTATUSEX
);
576 if (GlobalMemoryStatusEx(&MemoryStatus
))
578 FreeMemMb
= (UINT
)(MemoryStatus
.ullTotalPhys
/ (1024 * 1024));
579 _stprintf(szBuffer
, _T("%u MB"), FreeMemMb
+ (FreeMemMb
/ 2));
580 SetDlgItemText(hwndDlg
, IDC_RECOMMENDED
, szBuffer
);
583 /* Set current pagefile size */
586 for (i
= 0; i
< 26; i
++)
588 PageFileSizeMb
+= pVirtMem
->Pagefile
[i
].InitialSize
;
590 _stprintf(szBuffer
, _T("%u MB"), PageFileSizeMb
);
591 SetDlgItemText(hwndDlg
, IDC_CURRENT
, szBuffer
);
600 OnVirtMemDialogOk(PVIRTMEM pVirtMem
)
602 if (pVirtMem
->bModified
!= FALSE
)
604 ResourceMessageBox(hApplet
,
606 MB_ICONINFORMATION
| MB_OK
,
610 WritePageFileSettings(pVirtMem
);
616 OnInitVirtMemDialog(HWND hwnd
, PVIRTMEM pVirtMem
)
620 pVirtMem
->hSelf
= hwnd
;
621 pVirtMem
->hListBox
= GetDlgItem(hwnd
, IDC_PAGEFILELIST
);
622 pVirtMem
->bModified
= FALSE
;
624 SetListBoxColumns(pVirtMem
->hListBox
);
626 for (i
= 0; i
< 26; i
++)
628 pVirtMem
->Pagefile
[i
].bUsed
= FALSE
;
629 pVirtMem
->Pagefile
[i
].OldMinSize
= -1;
630 pVirtMem
->Pagefile
[i
].OldMaxSize
= -1;
631 pVirtMem
->Pagefile
[i
].NewMinSize
= -1;
632 pVirtMem
->Pagefile
[i
].NewMaxSize
= -1;
635 /* Load the pagefile systems from the reg */
636 ReadPageFileSettings(pVirtMem
);
638 /* Parse our settings and set up dialog */
639 ParseMemSettings(pVirtMem
);
641 InitPagefileList(pVirtMem
);
646 OnDestroy(PVIRTMEM pVirtMem
)
650 for (i
= 0; i
< 26; i
++)
652 if (pVirtMem
->Pagefile
[i
].pszVolume
!= NULL
)
653 HeapFree(GetProcessHeap(), 0, pVirtMem
->Pagefile
[i
].pszVolume
);
656 if (pVirtMem
->szPagingFiles
)
657 HeapFree(GetProcessHeap(), 0, pVirtMem
->szPagingFiles
);
659 HeapFree(GetProcessHeap(), 0, pVirtMem
);
664 VirtMemDlgProc(HWND hwndDlg
,
671 UNREFERENCED_PARAMETER(lParam
);
673 pVirtMem
= (PVIRTMEM
)GetWindowLongPtr(hwndDlg
, DWLP_USER
);
678 pVirtMem
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(VIRTMEM
));
679 if (pVirtMem
== NULL
)
681 EndDialog(hwndDlg
, 0);
685 SetWindowLongPtr(hwndDlg
, DWLP_USER
, (LONG_PTR
)pVirtMem
);
687 OnInitVirtMemDialog(hwndDlg
, pVirtMem
);
695 switch (LOWORD(wParam
))
698 EndDialog(hwndDlg
, 0);
702 OnVirtMemDialogOk(pVirtMem
);
703 EndDialog(hwndDlg
, pVirtMem
->bModified
);
707 OnNoPagingFile(pVirtMem
);
711 OnSysManSize(pVirtMem
);
722 case IDC_PAGEFILELIST
:
723 switch (HIWORD(wParam
))
726 OnSelChange(hwndDlg
, pVirtMem
);