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
];
111 TCHAR
*szDisplayString
;
117 DriveLen
= GetLogicalDriveStrings(1023,
120 szDisplayString
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, (MAX_PATH
* 2 + 69) * sizeof(TCHAR
));
121 if (szDisplayString
== NULL
)
124 while (DriveLen
!= 0)
128 Len
= lstrlen(DrivePtr
) + 1;
131 DrivePtr
= _tcsupr(DrivePtr
);
133 /* Copy the 'X:' portion */
134 lstrcpyn(szDrive
, DrivePtr
, sizeof(szDrive
) / sizeof(TCHAR
));
136 if (GetDriveType(DrivePtr
) == DRIVE_FIXED
)
138 /* Does drive match the one in the registry ? */
139 if (!_tcsncmp(pVirtMem
->szPagingFiles
, szDrive
, 2))
141 /* FIXME: We only check the first available pagefile in the reg */
142 GetPageFileSizes(pVirtMem
->szPagingFiles
,
146 pVirtMem
->Pagefile
[PgCnt
].InitialSize
= InitialSize
;
147 pVirtMem
->Pagefile
[PgCnt
].MaximumSize
= MaximumSize
;
148 pVirtMem
->Pagefile
[PgCnt
].bUsed
= TRUE
;
149 lstrcpy(pVirtMem
->Pagefile
[PgCnt
].szDrive
, szDrive
);
153 pVirtMem
->Pagefile
[PgCnt
].InitialSize
= 0;
154 pVirtMem
->Pagefile
[PgCnt
].MaximumSize
= 0;
155 pVirtMem
->Pagefile
[PgCnt
].bUsed
= FALSE
;
156 lstrcpy(pVirtMem
->Pagefile
[PgCnt
].szDrive
, szDrive
);
159 _tcscpy(szDisplayString
, szDrive
);
160 _tcscat(szDisplayString
, _T("\t"));
162 /* Set a volume label if there is one */
163 if (GetVolumeInformation(DrivePtr
,
172 if (szVolume
[0] != _T('\0'))
174 TCHAR szVol
[MAX_PATH
+ 2];
175 _stprintf(szVol
, _T("[%s]"), szVolume
);
176 _tcscat(szDisplayString
, szVol
);
180 if ((InitialSize
!= 0) || (MaximumSize
!= 0))
184 _stprintf(szSize
, _T("%i - %i"), InitialSize
, MaximumSize
);
185 _tcscat(szDisplayString
, _T("\t"));
186 _tcscat(szDisplayString
, szSize
);
189 SendMessage(pVirtMem
->hListBox
, LB_ADDSTRING
, (WPARAM
)0, (LPARAM
)szDisplayString
);
196 SendMessage(pVirtMem
->hListBox
, LB_SETCURSEL
, (WPARAM
)0, (LPARAM
)0);
197 HeapFree(GetProcessHeap(), 0, szDisplayString
);
198 pVirtMem
->Count
= PgCnt
;
199 OnSelChange(pVirtMem
->hSelf
, pVirtMem
);
204 WritePageFileSettings(PVIRTMEM pVirtMem
)
207 TCHAR szPagingFiles
[2048];
212 for (i
= 0; i
< pVirtMem
->Count
; ++i
)
214 if (pVirtMem
->Pagefile
[i
].bUsed
)
216 _stprintf(szText
, _T("%s\\pagefile.sys %i %i"),
217 pVirtMem
->Pagefile
[i
].szDrive
,
218 pVirtMem
->Pagefile
[i
].InitialSize
,
219 pVirtMem
->Pagefile
[i
].MaximumSize
);
221 /* Add it to our overall registry string */
222 lstrcpy(szPagingFiles
+ nPos
, szText
);
224 /* Record the position where the next string will start */
225 nPos
+= (INT
)lstrlen(szText
) + 1;
227 /* Add another NULL for REG_MULTI_SZ */
228 szPagingFiles
[nPos
] = _T('\0');
233 if (RegCreateKeyEx(HKEY_LOCAL_MACHINE
,
237 REG_OPTION_NON_VOLATILE
,
241 NULL
) == ERROR_SUCCESS
)
243 if (RegSetValueEx(hk
,
247 (LPBYTE
) szPagingFiles
,
248 (DWORD
) nPos
* sizeof(TCHAR
)) == ERROR_SUCCESS
)
257 ShowLastWin32Error(pVirtMem
->hSelf
);
262 SetListBoxColumns(HWND hwndListBox
)
264 const INT tabs
[2] = {30, 120};
266 SendMessage(hwndListBox
, LB_SETTABSTOPS
, (WPARAM
)2, (LPARAM
)&tabs
[0]);
271 OnNoPagingFile(PVIRTMEM pVirtMem
)
273 /* Disable the page file custom size boxes */
274 EnableWindow(GetDlgItem(pVirtMem
->hSelf
, IDC_INITIALSIZE
), FALSE
);
275 EnableWindow(GetDlgItem(pVirtMem
->hSelf
, IDC_MAXSIZE
), FALSE
);
280 OnSysManSize(PVIRTMEM pVirtMem
)
282 /* Disable the page file custom size boxes */
283 EnableWindow(GetDlgItem(pVirtMem
->hSelf
, IDC_INITIALSIZE
), FALSE
);
284 EnableWindow(GetDlgItem(pVirtMem
->hSelf
, IDC_MAXSIZE
), FALSE
);
289 OnCustom(PVIRTMEM pVirtMem
)
291 /* Enable the page file custom size boxes */
292 EnableWindow(GetDlgItem(pVirtMem
->hSelf
, IDC_INITIALSIZE
), TRUE
);
293 EnableWindow(GetDlgItem(pVirtMem
->hSelf
, IDC_MAXSIZE
), TRUE
);
298 OnSet(PVIRTMEM pVirtMem
)
305 TCHAR szMessage
[256];
307 pVirtMem
->bSave
= TRUE
;
309 Index
= (INT
)SendDlgItemMessage(pVirtMem
->hSelf
,
314 if (Index
>= 0 && Index
< pVirtMem
->Count
)
316 /* Check if custom settings are checked */
317 if (IsDlgButtonChecked(pVirtMem
->hSelf
,
318 IDC_CUSTOM
) == BST_CHECKED
)
320 InitialSize
= GetDlgItemInt(pVirtMem
->hSelf
,
326 if (LoadString(hApplet
,
329 sizeof(szTitle
) / sizeof(szTitle
[0])) == 0)
330 _tcscpy(szTitle
, _T("System control panel applet"));
332 if (LoadString(hApplet
,
335 sizeof(szMessage
) / sizeof(szMessage
[0])) == 0)
336 _tcscpy(szMessage
, _T("Enter a numeric value for the initial size of the paging file."));
341 MB_ICONWARNING
| MB_OK
);
345 MaximumSize
= GetDlgItemInt(pVirtMem
->hSelf
,
351 if (LoadString(hApplet
,
354 sizeof(szTitle
) / sizeof(szTitle
[0])) == 0)
355 _tcscpy(szTitle
, _T("System control panel applet"));
357 if (LoadString(hApplet
,
360 sizeof(szMessage
) / sizeof(szMessage
[0])) == 0)
361 _tcscpy(szMessage
, _T("Enter a numeric value for the maximum size of the paging file."));
366 MB_ICONWARNING
| MB_OK
);
370 /* Check the valid range of the inial size */
371 if (InitialSize
< 2 ||
372 InitialSize
> pVirtMem
->Pagefile
[Index
].FreeSize
)
374 if (LoadString(hApplet
,
377 sizeof(szTitle
) / sizeof(szTitle
[0])) == 0)
378 _tcscpy(szTitle
, _T("System control panel applet"));
381 IDS_WARNINITIALRANGE
,
383 sizeof(szMessage
) / sizeof(szMessage
[0]));
388 MB_ICONWARNING
| MB_OK
);
392 /* Check the valid range of the maximum size */
393 if (MaximumSize
< InitialSize
||
394 MaximumSize
> pVirtMem
->Pagefile
[Index
].FreeSize
)
396 if (LoadString(hApplet
,
399 sizeof(szTitle
) / sizeof(szTitle
[0])) == 0)
400 _tcscpy(szTitle
, _T("System control panel applet"));
403 IDS_WARNMAXIMUMRANGE
,
405 sizeof(szMessage
) / sizeof(szMessage
[0]));
410 MB_ICONWARNING
| MB_OK
);
414 pVirtMem
->Pagefile
[Index
].InitialSize
= InitialSize
;
415 pVirtMem
->Pagefile
[Index
].MaximumSize
= MaximumSize
;
416 pVirtMem
->Pagefile
[Index
].bUsed
= TRUE
;
421 pVirtMem
->Pagefile
[Index
].InitialSize
= 0;
422 pVirtMem
->Pagefile
[Index
].MaximumSize
= 0;
424 // Check to see if this drive is used for a paging file
425 if (IsDlgButtonChecked(pVirtMem
->hSelf
,
426 IDC_NOPAGEFILE
) == BST_UNCHECKED
)
428 pVirtMem
->Pagefile
[Index
].bUsed
= TRUE
;
432 pVirtMem
->Pagefile
[Index
].bUsed
= FALSE
;
440 OnSelChange(HWND hwndDlg
, PVIRTMEM pVirtMem
)
443 MEMORYSTATUSEX MemoryStatus
;
444 ULARGE_INTEGER FreeDiskSpace
;
445 UINT i
, FreeMemMb
, PageFileSizeMb
;
448 Index
= (INT
)SendDlgItemMessage(hwndDlg
,
453 if (Index
>= 0 && Index
< pVirtMem
->Count
)
455 /* Set drive letter */
456 SetDlgItemText(hwndDlg
, IDC_DRIVE
,
457 pVirtMem
->Pagefile
[Index
].szDrive
);
459 /* Set available disk space */
460 if (GetDiskFreeSpaceEx(pVirtMem
->Pagefile
[Index
].szDrive
,
461 NULL
, NULL
, &FreeDiskSpace
))
463 pVirtMem
->Pagefile
[Index
].FreeSize
= (UINT
)(FreeDiskSpace
.QuadPart
/ (1024 * 1024));
464 _stprintf(szBuffer
, _T("%u MB"), pVirtMem
->Pagefile
[Index
].FreeSize
);
465 SetDlgItemText(hwndDlg
, IDC_SPACEAVAIL
, szBuffer
);
468 if (pVirtMem
->Pagefile
[Index
].InitialSize
!= 0 &&
469 pVirtMem
->Pagefile
[Index
].MaximumSize
!= 0)
471 /* Enable and fill the custom values */
472 EnableWindow(GetDlgItem(pVirtMem
->hSelf
, IDC_MAXSIZE
), TRUE
);
473 EnableWindow(GetDlgItem(pVirtMem
->hSelf
, IDC_INITIALSIZE
), TRUE
);
475 SetDlgItemInt(pVirtMem
->hSelf
,
477 pVirtMem
->Pagefile
[Index
].InitialSize
,
480 SetDlgItemInt(pVirtMem
->hSelf
,
482 pVirtMem
->Pagefile
[Index
].MaximumSize
,
485 CheckDlgButton(pVirtMem
->hSelf
,
491 /* It's not a custom value */
492 EnableWindow(GetDlgItem(pVirtMem
->hSelf
, IDC_MAXSIZE
), FALSE
);
493 EnableWindow(GetDlgItem(pVirtMem
->hSelf
, IDC_INITIALSIZE
), FALSE
);
495 /* Is it system managed */
496 if (pVirtMem
->Pagefile
[Index
].bUsed
)
498 CheckDlgButton(pVirtMem
->hSelf
,
504 CheckDlgButton(pVirtMem
->hSelf
,
510 /* Set minimum pagefile size */
511 SetDlgItemText(hwndDlg
, IDC_MINIMUM
, _T("2 MB"));
513 /* Set recommended pagefile size */
514 MemoryStatus
.dwLength
= sizeof(MEMORYSTATUSEX
);
515 if (GlobalMemoryStatusEx(&MemoryStatus
))
517 FreeMemMb
= (UINT
)(MemoryStatus
.ullTotalPhys
/ (1024 * 1024));
518 _stprintf(szBuffer
, _T("%u MB"), FreeMemMb
+ (FreeMemMb
/ 2));
519 SetDlgItemText(hwndDlg
, IDC_RECOMMENDED
, szBuffer
);
522 /* Set current pagefile size */
524 for (i
= 0; i
< 26; i
++)
526 PageFileSizeMb
+= pVirtMem
->Pagefile
[i
].InitialSize
;
528 _stprintf(szBuffer
, _T("%u MB"), PageFileSizeMb
);
529 SetDlgItemText(hwndDlg
, IDC_CURRENT
, szBuffer
);
537 OnOk(PVIRTMEM pVirtMem
)
539 if (pVirtMem
->bSave
== TRUE
)
541 WritePageFileSettings(pVirtMem
);
547 OnInitDialog(HWND hwnd
, PVIRTMEM pVirtMem
)
549 pVirtMem
->hSelf
= hwnd
;
550 pVirtMem
->hListBox
= GetDlgItem(hwnd
, IDC_PAGEFILELIST
);
551 pVirtMem
->bSave
= FALSE
;
553 SetListBoxColumns(pVirtMem
->hListBox
);
555 /* Load the pagefile systems from the reg */
556 if (ReadPageFileSettings(pVirtMem
))
558 /* Parse our settings and set up dialog */
559 ParseMemSettings(pVirtMem
);
565 VirtMemDlgProc(HWND hwndDlg
,
572 UNREFERENCED_PARAMETER(lParam
);
574 pVirtMem
= (PVIRTMEM
)GetWindowLongPtr(hwndDlg
, DWLP_USER
);
579 pVirtMem
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(VIRTMEM
));
580 if (pVirtMem
== NULL
)
582 EndDialog(hwndDlg
, 0);
586 SetWindowLongPtr(hwndDlg
, DWLP_USER
, (LONG_PTR
)pVirtMem
);
588 OnInitDialog(hwndDlg
, pVirtMem
);
592 if (pVirtMem
->szPagingFiles
)
593 HeapFree(GetProcessHeap(), 0,
594 pVirtMem
->szPagingFiles
);
595 HeapFree(GetProcessHeap(), 0, pVirtMem
);
599 switch (LOWORD(wParam
))
602 EndDialog(hwndDlg
, 0);
607 EndDialog(hwndDlg
, 0);
611 OnNoPagingFile(pVirtMem
);
615 OnSysManSize(pVirtMem
);
626 case IDC_PAGEFILELIST
:
627 switch HIWORD(wParam
)
630 OnSelChange(hwndDlg
, pVirtMem
);