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
)
378 TCHAR szMessage
[256];
381 pVirtMem
->bSave
= TRUE
;
383 Index
= (INT
)SendDlgItemMessage(pVirtMem
->hSelf
,
388 if (Index
>= 0 && Index
< pVirtMem
->Count
)
390 DriveIndex
= SendDlgItemMessage(pVirtMem
->hSelf
,
396 /* Check if custom settings are checked */
397 if (IsDlgButtonChecked(pVirtMem
->hSelf
,
398 IDC_CUSTOM
) == BST_CHECKED
)
400 InitialSize
= GetDlgItemInt(pVirtMem
->hSelf
,
406 if (LoadString(hApplet
,
409 sizeof(szTitle
) / sizeof(szTitle
[0])) == 0)
410 _tcscpy(szTitle
, _T("System control panel applet"));
412 if (LoadString(hApplet
,
415 sizeof(szMessage
) / sizeof(szMessage
[0])) == 0)
416 _tcscpy(szMessage
, _T("Enter a numeric value for the initial size of the paging file."));
421 MB_ICONWARNING
| MB_OK
);
425 MaximumSize
= GetDlgItemInt(pVirtMem
->hSelf
,
431 if (LoadString(hApplet
,
434 sizeof(szTitle
) / sizeof(szTitle
[0])) == 0)
435 _tcscpy(szTitle
, _T("System control panel applet"));
437 if (LoadString(hApplet
,
440 sizeof(szMessage
) / sizeof(szMessage
[0])) == 0)
441 _tcscpy(szMessage
, _T("Enter a numeric value for the maximum size of the paging file."));
446 MB_ICONWARNING
| MB_OK
);
450 /* Check the valid range of the inial size */
451 if (InitialSize
< 2 ||
452 InitialSize
> pVirtMem
->Pagefile
[DriveIndex
].FreeSize
)
454 if (LoadString(hApplet
,
457 sizeof(szTitle
) / sizeof(szTitle
[0])) == 0)
458 _tcscpy(szTitle
, _T("System control panel applet"));
461 IDS_WARNINITIALRANGE
,
463 sizeof(szMessage
) / sizeof(szMessage
[0]));
468 MB_ICONWARNING
| MB_OK
);
472 /* Check the valid range of the maximum size */
473 if (MaximumSize
< InitialSize
||
474 MaximumSize
> pVirtMem
->Pagefile
[DriveIndex
].FreeSize
)
476 if (LoadString(hApplet
,
479 sizeof(szTitle
) / sizeof(szTitle
[0])) == 0)
480 _tcscpy(szTitle
, _T("System control panel applet"));
483 IDS_WARNMAXIMUMRANGE
,
485 sizeof(szMessage
) / sizeof(szMessage
[0]));
490 MB_ICONWARNING
| MB_OK
);
494 pVirtMem
->Pagefile
[DriveIndex
].InitialSize
= InitialSize
;
495 pVirtMem
->Pagefile
[DriveIndex
].MaximumSize
= MaximumSize
;
496 pVirtMem
->Pagefile
[DriveIndex
].bUsed
= TRUE
;
498 else if (IsDlgButtonChecked(pVirtMem
->hSelf
,
499 IDC_NOPAGEFILE
) == BST_CHECKED
)
501 /* Set sizes to -1 */
502 pVirtMem
->Pagefile
[DriveIndex
].InitialSize
= -1;
503 pVirtMem
->Pagefile
[DriveIndex
].MaximumSize
= -1;
504 pVirtMem
->Pagefile
[DriveIndex
].bUsed
= TRUE
;
508 pVirtMem
->Pagefile
[DriveIndex
].InitialSize
= 0;
509 pVirtMem
->Pagefile
[DriveIndex
].MaximumSize
= 0;
510 pVirtMem
->Pagefile
[DriveIndex
].bUsed
= TRUE
;
513 UpdatePagefileEntry(pVirtMem
, Index
, DriveIndex
);
519 OnSelChange(HWND hwndDlg
, PVIRTMEM pVirtMem
)
522 MEMORYSTATUSEX MemoryStatus
;
523 ULARGE_INTEGER FreeDiskSpace
;
524 UINT
/*i,*/ FreeMemMb
/*, PageFileSizeMb*/;
527 Index
= (INT
)SendDlgItemMessage(hwndDlg
,
532 if (Index
>= 0 && Index
< pVirtMem
->Count
)
534 /* Set drive letter */
535 SetDlgItemText(hwndDlg
, IDC_DRIVE
,
536 pVirtMem
->Pagefile
[Index
].szDrive
);
538 /* Set available disk space */
539 if (GetDiskFreeSpaceEx(pVirtMem
->Pagefile
[Index
].szDrive
,
540 NULL
, NULL
, &FreeDiskSpace
))
542 pVirtMem
->Pagefile
[Index
].FreeSize
= (UINT
)(FreeDiskSpace
.QuadPart
/ (1024 * 1024));
543 _stprintf(szBuffer
, _T("%u MB"), pVirtMem
->Pagefile
[Index
].FreeSize
);
544 SetDlgItemText(hwndDlg
, IDC_SPACEAVAIL
, szBuffer
);
547 if (pVirtMem
->Pagefile
[Index
].InitialSize
== -1 &&
548 pVirtMem
->Pagefile
[Index
].MaximumSize
== -1)
552 EnableWindow(GetDlgItem(pVirtMem
->hSelf
, IDC_MAXSIZE
), FALSE
);
553 EnableWindow(GetDlgItem(pVirtMem
->hSelf
, IDC_INITIALSIZE
), FALSE
);
555 CheckDlgButton(pVirtMem
->hSelf
, IDC_NOPAGEFILE
, BST_CHECKED
);
557 else if (pVirtMem
->Pagefile
[Index
].InitialSize
== 0 &&
558 pVirtMem
->Pagefile
[Index
].MaximumSize
== 0)
560 /* System managed size*/
562 EnableWindow(GetDlgItem(pVirtMem
->hSelf
, IDC_MAXSIZE
), FALSE
);
563 EnableWindow(GetDlgItem(pVirtMem
->hSelf
, IDC_INITIALSIZE
), FALSE
);
565 CheckDlgButton(pVirtMem
->hSelf
, IDC_SYSMANSIZE
, BST_CHECKED
);
571 /* Enable and fill the custom values */
572 EnableWindow(GetDlgItem(pVirtMem
->hSelf
, IDC_MAXSIZE
), TRUE
);
573 EnableWindow(GetDlgItem(pVirtMem
->hSelf
, IDC_INITIALSIZE
), TRUE
);
575 SetDlgItemInt(pVirtMem
->hSelf
,
577 pVirtMem
->Pagefile
[Index
].InitialSize
,
580 SetDlgItemInt(pVirtMem
->hSelf
,
582 pVirtMem
->Pagefile
[Index
].MaximumSize
,
585 CheckDlgButton(pVirtMem
->hSelf
,
590 /* Set minimum pagefile size */
591 SetDlgItemText(hwndDlg
, IDC_MINIMUM
, _T("2 MB"));
593 /* Set recommended pagefile size */
594 MemoryStatus
.dwLength
= sizeof(MEMORYSTATUSEX
);
595 if (GlobalMemoryStatusEx(&MemoryStatus
))
597 FreeMemMb
= (UINT
)(MemoryStatus
.ullTotalPhys
/ (1024 * 1024));
598 _stprintf(szBuffer
, _T("%u MB"), FreeMemMb
+ (FreeMemMb
/ 2));
599 SetDlgItemText(hwndDlg
, IDC_RECOMMENDED
, szBuffer
);
602 /* Set current pagefile size */
605 for (i
= 0; i
< 26; i
++)
607 PageFileSizeMb
+= pVirtMem
->Pagefile
[i
].InitialSize
;
609 _stprintf(szBuffer
, _T("%u MB"), PageFileSizeMb
);
610 SetDlgItemText(hwndDlg
, IDC_CURRENT
, szBuffer
);
619 OnOk(PVIRTMEM pVirtMem
)
621 if (pVirtMem
->bSave
== TRUE
)
623 WritePageFileSettings(pVirtMem
);
629 OnInitDialog(HWND hwnd
, PVIRTMEM pVirtMem
)
633 pVirtMem
->hSelf
= hwnd
;
634 pVirtMem
->hListBox
= GetDlgItem(hwnd
, IDC_PAGEFILELIST
);
635 pVirtMem
->bSave
= FALSE
;
637 SetListBoxColumns(pVirtMem
->hListBox
);
639 for (i
= 0; i
< 26; i
++)
641 pVirtMem
->Pagefile
[i
].bUsed
= FALSE
;
642 pVirtMem
->Pagefile
[i
].InitialSize
= -1;
643 pVirtMem
->Pagefile
[i
].MaximumSize
= -1;
646 /* Load the pagefile systems from the reg */
647 ReadPageFileSettings(pVirtMem
);
649 /* Parse our settings and set up dialog */
650 ParseMemSettings(pVirtMem
);
652 InitPagefileList(pVirtMem
);
657 OnDestroy(PVIRTMEM pVirtMem
)
661 for (i
= 0; i
< 26; i
++)
663 if (pVirtMem
->Pagefile
[i
].pszVolume
!= NULL
)
664 HeapFree(GetProcessHeap(), 0, pVirtMem
->Pagefile
[i
].pszVolume
);
667 if (pVirtMem
->szPagingFiles
)
668 HeapFree(GetProcessHeap(), 0, pVirtMem
->szPagingFiles
);
670 HeapFree(GetProcessHeap(), 0, pVirtMem
);
675 VirtMemDlgProc(HWND hwndDlg
,
682 UNREFERENCED_PARAMETER(lParam
);
684 pVirtMem
= (PVIRTMEM
)GetWindowLongPtr(hwndDlg
, DWLP_USER
);
689 pVirtMem
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(VIRTMEM
));
690 if (pVirtMem
== NULL
)
692 EndDialog(hwndDlg
, 0);
696 SetWindowLongPtr(hwndDlg
, DWLP_USER
, (LONG_PTR
)pVirtMem
);
698 OnInitDialog(hwndDlg
, pVirtMem
);
706 switch (LOWORD(wParam
))
709 EndDialog(hwndDlg
, 0);
714 EndDialog(hwndDlg
, 0);
718 OnNoPagingFile(pVirtMem
);
722 OnSysManSize(pVirtMem
);
733 case IDC_PAGEFILELIST
:
734 switch (HIWORD(wParam
))
737 OnSelChange(hwndDlg
, pVirtMem
);