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
].InitialSize
= InitialSize
;
144 pVirtMem
->Pagefile
[PgCnt
].MaximumSize
= MaximumSize
;
145 pVirtMem
->Pagefile
[PgCnt
].bUsed
= TRUE
;
146 lstrcpy(pVirtMem
->Pagefile
[PgCnt
].szDrive
, szDrive
);
149 /* Get the volume label if there is one */
150 if (GetVolumeInformation(DrivePtr
,
159 pVirtMem
->Pagefile
[PgCnt
].pszVolume
= HeapAlloc(GetProcessHeap(),
161 (_tcslen(szVolume
) + 1) * sizeof(TCHAR
));
162 if (pVirtMem
->Pagefile
[PgCnt
].pszVolume
!= NULL
)
163 _tcscpy(pVirtMem
->Pagefile
[PgCnt
].pszVolume
, szVolume
);
172 pVirtMem
->Count
= PgCnt
;
177 WritePageFileSettings(PVIRTMEM pVirtMem
)
180 TCHAR szPagingFiles
[2048];
185 for (i
= 0; i
< pVirtMem
->Count
; ++i
)
187 if (pVirtMem
->Pagefile
[i
].bUsed
&&
188 pVirtMem
->Pagefile
[i
].InitialSize
!= -1 &&
189 pVirtMem
->Pagefile
[i
].MaximumSize
!= -1)
192 _T("%s\\pagefile.sys %i %i"),
193 pVirtMem
->Pagefile
[i
].szDrive
,
194 pVirtMem
->Pagefile
[i
].InitialSize
,
195 pVirtMem
->Pagefile
[i
].MaximumSize
);
197 /* Add it to our overall registry string */
198 lstrcpy(szPagingFiles
+ nPos
, szText
);
200 /* Record the position where the next string will start */
201 nPos
+= (INT
)lstrlen(szText
) + 1;
203 /* Add another NULL for REG_MULTI_SZ */
204 szPagingFiles
[nPos
] = _T('\0');
209 if (RegCreateKeyEx(HKEY_LOCAL_MACHINE
,
213 REG_OPTION_NON_VOLATILE
,
217 NULL
) == ERROR_SUCCESS
)
219 if (RegSetValueEx(hk
,
223 (LPBYTE
) szPagingFiles
,
224 (DWORD
) nPos
* sizeof(TCHAR
)) == ERROR_SUCCESS
)
233 ShowLastWin32Error(pVirtMem
->hSelf
);
238 SetListBoxColumns(HWND hwndListBox
)
240 RECT rect
= {0, 0, 103, 0};
241 MapDialogRect(hwndListBox
, &rect
);
243 SendMessage(hwndListBox
, LB_SETTABSTOPS
, (WPARAM
)1, (LPARAM
)&rect
.right
);
248 OnNoPagingFile(PVIRTMEM pVirtMem
)
250 /* Disable the page file custom size boxes */
251 EnableWindow(GetDlgItem(pVirtMem
->hSelf
, IDC_INITIALSIZE
), FALSE
);
252 EnableWindow(GetDlgItem(pVirtMem
->hSelf
, IDC_MAXSIZE
), FALSE
);
257 OnSysManSize(PVIRTMEM pVirtMem
)
259 /* Disable the page file custom size boxes */
260 EnableWindow(GetDlgItem(pVirtMem
->hSelf
, IDC_INITIALSIZE
), FALSE
);
261 EnableWindow(GetDlgItem(pVirtMem
->hSelf
, IDC_MAXSIZE
), FALSE
);
266 OnCustom(PVIRTMEM pVirtMem
)
268 /* Enable the page file custom size boxes */
269 EnableWindow(GetDlgItem(pVirtMem
->hSelf
, IDC_INITIALSIZE
), TRUE
);
270 EnableWindow(GetDlgItem(pVirtMem
->hSelf
, IDC_MAXSIZE
), TRUE
);
275 InitPagefileList(PVIRTMEM pVirtMem
)
277 TCHAR szDisplayString
[256];
282 for (i
= 0; i
< 26; i
++)
284 if (pVirtMem
->Pagefile
[i
].bUsed
)
286 if ((pVirtMem
->Pagefile
[i
].InitialSize
== -1) &&
287 (pVirtMem
->Pagefile
[i
].MaximumSize
== -1))
292 sizeof(szSize
) / sizeof(szSize
[0]));
294 else if ((pVirtMem
->Pagefile
[i
].InitialSize
== 0) &&
295 (pVirtMem
->Pagefile
[i
].MaximumSize
== 0))
300 sizeof(szSize
) / sizeof(szSize
[0]));
304 _stprintf(szSize
, _T("%d - %d"),
305 pVirtMem
->Pagefile
[i
].InitialSize
,
306 pVirtMem
->Pagefile
[i
].MaximumSize
);
309 _stprintf(szDisplayString
,
311 pVirtMem
->Pagefile
[i
].szDrive
,
312 pVirtMem
->Pagefile
[i
].pszVolume
? pVirtMem
->Pagefile
[i
].pszVolume
: _T(""),
315 Index
= SendMessage(pVirtMem
->hListBox
, LB_ADDSTRING
, (WPARAM
)0, (LPARAM
)szDisplayString
);
316 SendMessage(pVirtMem
->hListBox
, LB_SETITEMDATA
, Index
, i
);
320 SendMessage(pVirtMem
->hListBox
, LB_SETCURSEL
, (WPARAM
)0, (LPARAM
)0);
322 OnSelChange(pVirtMem
->hSelf
, pVirtMem
);
327 UpdatePagefileEntry(PVIRTMEM pVirtMem
,
331 TCHAR szDisplayString
[256];
334 if ((pVirtMem
->Pagefile
[DriveIndex
].InitialSize
== -1) &&
335 (pVirtMem
->Pagefile
[DriveIndex
].MaximumSize
== -1))
340 sizeof(szSize
) / sizeof(szSize
[0]));
342 else if ((pVirtMem
->Pagefile
[DriveIndex
].InitialSize
== 0) &&
343 (pVirtMem
->Pagefile
[DriveIndex
].MaximumSize
== 0))
348 sizeof(szSize
) / sizeof(szSize
[0]));
354 pVirtMem
->Pagefile
[DriveIndex
].InitialSize
,
355 pVirtMem
->Pagefile
[DriveIndex
].MaximumSize
);
358 _stprintf(szDisplayString
,
360 pVirtMem
->Pagefile
[DriveIndex
].szDrive
,
361 pVirtMem
->Pagefile
[DriveIndex
].pszVolume
? pVirtMem
->Pagefile
[DriveIndex
].pszVolume
: L
"",
364 SendMessage(pVirtMem
->hListBox
, LB_DELETESTRING
, (WPARAM
)ListIndex
, 0);
365 SendMessage(pVirtMem
->hListBox
, LB_INSERTSTRING
, (WPARAM
)ListIndex
, (LPARAM
)szDisplayString
);
366 SendMessage(pVirtMem
->hListBox
, LB_SETCURSEL
, (WPARAM
)ListIndex
, 0);
371 OnSet(PVIRTMEM pVirtMem
)
374 UINT InitialSize
= -1;
375 UINT MaximumSize
= -1;
379 Index
= (INT
)SendDlgItemMessage(pVirtMem
->hSelf
,
384 if (Index
>= 0 && Index
< pVirtMem
->Count
)
386 DriveIndex
= SendDlgItemMessage(pVirtMem
->hSelf
,
392 /* Check if custom settings are checked */
393 if (IsDlgButtonChecked(pVirtMem
->hSelf
,
394 IDC_CUSTOM
) == BST_CHECKED
)
396 InitialSize
= GetDlgItemInt(pVirtMem
->hSelf
,
402 ResourceMessageBox(hApplet
,
404 MB_ICONWARNING
| MB_OK
,
406 IDS_WARNINITIALSIZE
);
410 MaximumSize
= GetDlgItemInt(pVirtMem
->hSelf
,
416 ResourceMessageBox(hApplet
,
418 MB_ICONWARNING
| MB_OK
,
420 IDS_WARNMAXIMUMSIZE
);
424 /* Check the valid range of the inial size */
425 if (InitialSize
< 2 ||
426 InitialSize
> pVirtMem
->Pagefile
[DriveIndex
].FreeSize
)
428 ResourceMessageBox(hApplet
,
430 MB_ICONWARNING
| MB_OK
,
432 IDS_WARNINITIALRANGE
);
436 /* Check the valid range of the maximum size */
437 if (MaximumSize
< InitialSize
||
438 MaximumSize
> pVirtMem
->Pagefile
[DriveIndex
].FreeSize
)
440 ResourceMessageBox(hApplet
,
442 MB_ICONWARNING
| MB_OK
,
444 IDS_WARNMAXIMUMRANGE
);
448 if ((pVirtMem
->Pagefile
[DriveIndex
].InitialSize
!= InitialSize
) &&
449 (pVirtMem
->Pagefile
[DriveIndex
].MaximumSize
!= MaximumSize
))
450 pVirtMem
->bModified
= TRUE
;
452 pVirtMem
->Pagefile
[DriveIndex
].InitialSize
= InitialSize
;
453 pVirtMem
->Pagefile
[DriveIndex
].MaximumSize
= MaximumSize
;
454 pVirtMem
->Pagefile
[DriveIndex
].bUsed
= TRUE
;
456 else if (IsDlgButtonChecked(pVirtMem
->hSelf
,
457 IDC_NOPAGEFILE
) == BST_CHECKED
)
459 if ((pVirtMem
->Pagefile
[DriveIndex
].InitialSize
!= InitialSize
) &&
460 (pVirtMem
->Pagefile
[DriveIndex
].MaximumSize
!= MaximumSize
))
461 pVirtMem
->bModified
= TRUE
;
463 /* Set sizes to -1 */
464 pVirtMem
->Pagefile
[DriveIndex
].InitialSize
= -1;
465 pVirtMem
->Pagefile
[DriveIndex
].MaximumSize
= -1;
466 pVirtMem
->Pagefile
[DriveIndex
].bUsed
= TRUE
;
470 if ((pVirtMem
->Pagefile
[DriveIndex
].InitialSize
!= InitialSize
) &&
471 (pVirtMem
->Pagefile
[DriveIndex
].MaximumSize
!= MaximumSize
))
472 pVirtMem
->bModified
= TRUE
;
474 pVirtMem
->Pagefile
[DriveIndex
].InitialSize
= 0;
475 pVirtMem
->Pagefile
[DriveIndex
].MaximumSize
= 0;
476 pVirtMem
->Pagefile
[DriveIndex
].bUsed
= TRUE
;
479 UpdatePagefileEntry(pVirtMem
, Index
, DriveIndex
);
485 OnSelChange(HWND hwndDlg
, PVIRTMEM pVirtMem
)
488 MEMORYSTATUSEX MemoryStatus
;
489 ULARGE_INTEGER FreeDiskSpace
;
490 UINT
/*i,*/ FreeMemMb
/*, PageFileSizeMb*/;
493 Index
= (INT
)SendDlgItemMessage(hwndDlg
,
498 if (Index
>= 0 && Index
< pVirtMem
->Count
)
500 /* Set drive letter */
501 SetDlgItemText(hwndDlg
, IDC_DRIVE
,
502 pVirtMem
->Pagefile
[Index
].szDrive
);
504 /* Set available disk space */
505 if (GetDiskFreeSpaceEx(pVirtMem
->Pagefile
[Index
].szDrive
,
506 NULL
, NULL
, &FreeDiskSpace
))
508 pVirtMem
->Pagefile
[Index
].FreeSize
= (UINT
)(FreeDiskSpace
.QuadPart
/ (1024 * 1024));
509 _stprintf(szBuffer
, _T("%u MB"), pVirtMem
->Pagefile
[Index
].FreeSize
);
510 SetDlgItemText(hwndDlg
, IDC_SPACEAVAIL
, szBuffer
);
513 if (pVirtMem
->Pagefile
[Index
].InitialSize
== -1 &&
514 pVirtMem
->Pagefile
[Index
].MaximumSize
== -1)
518 EnableWindow(GetDlgItem(pVirtMem
->hSelf
, IDC_MAXSIZE
), FALSE
);
519 EnableWindow(GetDlgItem(pVirtMem
->hSelf
, IDC_INITIALSIZE
), FALSE
);
521 CheckDlgButton(pVirtMem
->hSelf
, IDC_NOPAGEFILE
, BST_CHECKED
);
523 else if (pVirtMem
->Pagefile
[Index
].InitialSize
== 0 &&
524 pVirtMem
->Pagefile
[Index
].MaximumSize
== 0)
526 /* System managed size*/
528 EnableWindow(GetDlgItem(pVirtMem
->hSelf
, IDC_MAXSIZE
), FALSE
);
529 EnableWindow(GetDlgItem(pVirtMem
->hSelf
, IDC_INITIALSIZE
), FALSE
);
531 CheckDlgButton(pVirtMem
->hSelf
, IDC_SYSMANSIZE
, BST_CHECKED
);
537 /* Enable and fill the custom values */
538 EnableWindow(GetDlgItem(pVirtMem
->hSelf
, IDC_MAXSIZE
), TRUE
);
539 EnableWindow(GetDlgItem(pVirtMem
->hSelf
, IDC_INITIALSIZE
), TRUE
);
541 SetDlgItemInt(pVirtMem
->hSelf
,
543 pVirtMem
->Pagefile
[Index
].InitialSize
,
546 SetDlgItemInt(pVirtMem
->hSelf
,
548 pVirtMem
->Pagefile
[Index
].MaximumSize
,
551 CheckDlgButton(pVirtMem
->hSelf
,
556 /* Set minimum pagefile size */
557 SetDlgItemText(hwndDlg
, IDC_MINIMUM
, _T("2 MB"));
559 /* Set recommended pagefile size */
560 MemoryStatus
.dwLength
= sizeof(MEMORYSTATUSEX
);
561 if (GlobalMemoryStatusEx(&MemoryStatus
))
563 FreeMemMb
= (UINT
)(MemoryStatus
.ullTotalPhys
/ (1024 * 1024));
564 _stprintf(szBuffer
, _T("%u MB"), FreeMemMb
+ (FreeMemMb
/ 2));
565 SetDlgItemText(hwndDlg
, IDC_RECOMMENDED
, szBuffer
);
568 /* Set current pagefile size */
571 for (i
= 0; i
< 26; i
++)
573 PageFileSizeMb
+= pVirtMem
->Pagefile
[i
].InitialSize
;
575 _stprintf(szBuffer
, _T("%u MB"), PageFileSizeMb
);
576 SetDlgItemText(hwndDlg
, IDC_CURRENT
, szBuffer
);
585 OnOk(PVIRTMEM pVirtMem
)
587 if (pVirtMem
->bModified
== TRUE
)
589 ResourceMessageBox(hApplet
,
591 MB_ICONINFORMATION
| MB_OK
,
595 WritePageFileSettings(pVirtMem
);
601 OnInitDialog(HWND hwnd
, PVIRTMEM pVirtMem
)
605 pVirtMem
->hSelf
= hwnd
;
606 pVirtMem
->hListBox
= GetDlgItem(hwnd
, IDC_PAGEFILELIST
);
607 pVirtMem
->bModified
= FALSE
;
609 SetListBoxColumns(pVirtMem
->hListBox
);
611 for (i
= 0; i
< 26; i
++)
613 pVirtMem
->Pagefile
[i
].bUsed
= FALSE
;
614 pVirtMem
->Pagefile
[i
].InitialSize
= -1;
615 pVirtMem
->Pagefile
[i
].MaximumSize
= -1;
618 /* Load the pagefile systems from the reg */
619 ReadPageFileSettings(pVirtMem
);
621 /* Parse our settings and set up dialog */
622 ParseMemSettings(pVirtMem
);
624 InitPagefileList(pVirtMem
);
629 OnDestroy(PVIRTMEM pVirtMem
)
633 for (i
= 0; i
< 26; i
++)
635 if (pVirtMem
->Pagefile
[i
].pszVolume
!= NULL
)
636 HeapFree(GetProcessHeap(), 0, pVirtMem
->Pagefile
[i
].pszVolume
);
639 if (pVirtMem
->szPagingFiles
)
640 HeapFree(GetProcessHeap(), 0, pVirtMem
->szPagingFiles
);
642 HeapFree(GetProcessHeap(), 0, pVirtMem
);
647 VirtMemDlgProc(HWND hwndDlg
,
654 UNREFERENCED_PARAMETER(lParam
);
656 pVirtMem
= (PVIRTMEM
)GetWindowLongPtr(hwndDlg
, DWLP_USER
);
661 pVirtMem
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(VIRTMEM
));
662 if (pVirtMem
== NULL
)
664 EndDialog(hwndDlg
, 0);
668 SetWindowLongPtr(hwndDlg
, DWLP_USER
, (LONG_PTR
)pVirtMem
);
670 OnInitDialog(hwndDlg
, pVirtMem
);
678 switch (LOWORD(wParam
))
681 EndDialog(hwndDlg
, 0);
686 EndDialog(hwndDlg
, pVirtMem
->bModified
);
690 OnNoPagingFile(pVirtMem
);
694 OnSysManSize(pVirtMem
);
705 case IDC_PAGEFILELIST
:
706 switch (HIWORD(wParam
))
709 OnSelChange(hwndDlg
, pVirtMem
);