3 * Copyright (C) 2004 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 * PROJECT: ReactOS System Control Panel
22 * FILE: lib/cpl/sysdm/virtmem.c
23 * PURPOSE: pagefile settings
24 * PROGRAMMER: Christian Wallukat cwallukat(at)gmx(dot)at
39 // An array of these structs will interally manage system page files
41 typedef struct _sPagefiles
52 // At most there can be 32 drives, so only 32 page files
54 sPageFiles g_sPagefile
[32];
56 // This is the number of drives that could have page files
60 // Will save the user set action signal saving to the registry on exit
66 // ReadRegSettings reads the page file settings from the regisrty
68 VOID
ReadRegSettings(HWND hwndDlg
);
70 // ParseMemSettings takes the regisrty string and create the internal page file array
72 VOID
ParseMemSettings(TCHAR
*szSettings
, HWND hwndDlg
);
74 // SaveSettings writes the paging file array to the registry
76 VOID
SaveSettings(HWND hwndDlg
);
79 // Callback function for messages for the windows
83 VirtMemDlgProc(HWND hwndDlg
,
88 SYSTEM_PROCESS_INFORMATION siSysPInfo
;
93 // We dont need to look at this part of the message
95 UNREFERENCED_PARAMETER(lParam
);
102 // We dont save the changes until set is clicked
106 // We start with no page files
110 // Clear out the file pagefile
112 g_sPagefile
[0].nMaxValue
= 0;
113 g_sPagefile
[0].nMinValue
= 0;
114 g_sPagefile
[0].nUsed
= 0;
117 // Grad the system stats to get some page file into
119 NtQuerySystemInformation(SystemProcessInformation
, &siSysPInfo
, sizeof(SYSTEM_PROCESS_INFORMATION
), NULL
);
122 // Convert the pagefile usage to a string
124 _itow(siSysPInfo
.PeakPagefileUsage
, szTemp
, 10);
127 // Set pagefle useage to its label
129 SendDlgItemMessage(hwndDlg
, IDC_CURRENT
, WM_SETTEXT
, (WPARAM
)0, (LPARAM
)szTemp
);
132 // Load the pagefile systems from the reg
134 ReadRegSettings(hwndDlg
);
140 switch (LOWORD(wParam
))
145 // If the user hits cancel we just close and dont save
147 EndDialog(hwndDlg
, 0);
156 // Check to make sure that the user hit set and we will save the settings
160 SaveSettings(hwndDlg
);
164 // Close out the window
166 EndDialog(hwndDlg
, 0);
171 case IDC_PAGEFILELIST
:
173 switch(HIWORD(wParam
))
178 // Get the currently selected page file from the list box
180 nIndex
= (INT
)SendDlgItemMessage(hwndDlg
, IDC_PAGEFILELIST
, LB_GETCURSEL
, (WPARAM
)0, (LPARAM
)0);
183 // If the index is in our range then process that page file
185 if(nIndex
< g_nCount
)
188 // Convert the minvalue for the page file
190 _itow(g_sPagefile
[nIndex
].nMinValue
, szTemp
, 10);
193 // Set the min value to its textbox
195 SendDlgItemMessage(hwndDlg
, IDC_INITIALSIZE
, WM_SETTEXT
, (WPARAM
)0, (LPARAM
)szTemp
);
198 // Convert the max value of the page file to a string
200 _itow(g_sPagefile
[nIndex
].nMaxValue
, szTemp
, 10);
203 // Set the max value to its textbox
205 SendDlgItemMessage(hwndDlg
, IDC_MAXSIZE
, WM_SETTEXT
, (WPARAM
)0, (LPARAM
)szTemp
);
208 // Figure out what type of page file it is
210 if(g_sPagefile
[nIndex
].nMinValue
== 0 && g_sPagefile
[nIndex
].nMaxValue
== 0)
213 // There is either no page file or a system managed page file so we disable custom sizes
215 EnableWindow(GetDlgItem(hwndDlg
, IDC_MAXSIZE
), FALSE
);
216 EnableWindow(GetDlgItem(hwndDlg
, IDC_INITIALSIZE
), FALSE
);
218 // Check to see if that drive is used for paging
220 if(g_sPagefile
[nIndex
].nUsed
== 1)
223 // This is a system managed page file
225 SendDlgItemMessage(hwndDlg
, IDC_NOPAGEFILE
, BM_SETCHECK
, (WPARAM
)0, (LPARAM
)0);
226 SendDlgItemMessage(hwndDlg
, IDC_SYSMANSIZE
, BM_SETCHECK
, (WPARAM
)1, (LPARAM
)0);
227 SendDlgItemMessage(hwndDlg
, IDC_CUSTOM
, BM_SETCHECK
, (WPARAM
)0, (LPARAM
)0);
232 // There is no page file on this drive
234 SendDlgItemMessage(hwndDlg
, IDC_NOPAGEFILE
, BM_SETCHECK
, (WPARAM
)1, (LPARAM
)0);
235 SendDlgItemMessage(hwndDlg
, IDC_SYSMANSIZE
, BM_SETCHECK
, (WPARAM
)0, (LPARAM
)0);
236 SendDlgItemMessage(hwndDlg
, IDC_CUSTOM
, BM_SETCHECK
, (WPARAM
)0, (LPARAM
)0);
242 // THis is a custom sized page file
244 SendDlgItemMessage(hwndDlg
, IDC_NOPAGEFILE
, BM_SETCHECK
, (WPARAM
)0, (LPARAM
)0);
245 SendDlgItemMessage(hwndDlg
, IDC_SYSMANSIZE
, BM_SETCHECK
, (WPARAM
)0, (LPARAM
)0);
246 SendDlgItemMessage(hwndDlg
, IDC_CUSTOM
, BM_SETCHECK
, (WPARAM
)1, (LPARAM
)0);
248 // We need to allow the user to change the sizes
250 EnableWindow(GetDlgItem(hwndDlg
, IDC_MAXSIZE
), TRUE
);
251 EnableWindow(GetDlgItem(hwndDlg
, IDC_INITIALSIZE
), TRUE
);
264 // Set the pagefile to no page file
266 SendDlgItemMessage(hwndDlg
, IDC_NOPAGEFILE
, BM_SETCHECK
, (WPARAM
)1, (LPARAM
)0);
267 SendDlgItemMessage(hwndDlg
, IDC_SYSMANSIZE
, BM_SETCHECK
, (WPARAM
)0, (LPARAM
)0);
268 SendDlgItemMessage(hwndDlg
, IDC_CUSTOM
, BM_SETCHECK
, (WPARAM
)0, (LPARAM
)0);
271 // Disable the page file custom size boxes
273 EnableWindow(GetDlgItem(hwndDlg
, IDC_MAXSIZE
), FALSE
);
274 EnableWindow(GetDlgItem(hwndDlg
, IDC_INITIALSIZE
), FALSE
);
281 // User changed this to a system managed page file
283 SendDlgItemMessage(hwndDlg
, IDC_NOPAGEFILE
, BM_SETCHECK
, (WPARAM
)0, (LPARAM
)0);
284 SendDlgItemMessage(hwndDlg
, IDC_SYSMANSIZE
, BM_SETCHECK
, (WPARAM
)1, (LPARAM
)0);
285 SendDlgItemMessage(hwndDlg
, IDC_CUSTOM
, BM_SETCHECK
, (WPARAM
)0, (LPARAM
)0);
288 // Disable the page file custom size boxes
290 EnableWindow(GetDlgItem(hwndDlg
, IDC_MAXSIZE
), FALSE
);
291 EnableWindow(GetDlgItem(hwndDlg
, IDC_INITIALSIZE
), FALSE
);
298 // User changed this to a cutom sized page file
300 SendDlgItemMessage(hwndDlg
, IDC_NOPAGEFILE
, BM_SETCHECK
, (WPARAM
)0, (LPARAM
)0);
301 SendDlgItemMessage(hwndDlg
, IDC_SYSMANSIZE
, BM_SETCHECK
, (WPARAM
)0, (LPARAM
)0);
302 SendDlgItemMessage(hwndDlg
, IDC_CUSTOM
, BM_SETCHECK
, (WPARAM
)1, (LPARAM
)0);
305 // The user should be able to change the size of these files
307 EnableWindow(GetDlgItem(hwndDlg
, IDC_MAXSIZE
), TRUE
);
308 EnableWindow(GetDlgItem(hwndDlg
, IDC_INITIALSIZE
), TRUE
);
315 // The user hit set, so we are clear to save the settings when we are done
320 // Figure out which pagefile we are saving the settings too
322 nIndex
= SendDlgItemMessage(hwndDlg
, IDC_PAGEFILELIST
, LB_GETCURSEL
, (WPARAM
)0, (LPARAM
)0);
325 // Make sure it isnt out of our range
327 if(nIndex
< g_nCount
)
330 // Check to see what the current user input settings are
332 if(SendDlgItemMessage(hwndDlg
, IDC_CUSTOM
, BM_GETCHECK
, (WPARAM
)0, (LPARAM
)0) == BST_CHECKED
)
335 // If custom is checked we need to get the min size
337 SendDlgItemMessage(hwndDlg
, IDC_INITIALSIZE
, WM_GETTEXT
, (WPARAM
)254, (LPARAM
)szTemp
);
340 // Convert the size to an int and save it
342 g_sPagefile
[nIndex
].nMinValue
= _wtoi(szTemp
);
345 // If custom is checked we need to get the max size
347 SendDlgItemMessage(hwndDlg
, IDC_MAXSIZE
, WM_GETTEXT
, (WPARAM
)254, (LPARAM
)szTemp
);
350 // If custom is checked we need to get the max size
352 g_sPagefile
[nIndex
].nMaxValue
= _wtoi(szTemp
);
358 // If it is no paging file or system then we set the sizes to zero
360 g_sPagefile
[nIndex
].nMinValue
= g_sPagefile
[nIndex
].nMaxValue
= 0;
364 // We check to see if this drive is used for a paging file anymore
366 g_sPagefile
[nIndex
].nUsed
= (SendDlgItemMessage(hwndDlg
, IDC_NOPAGEFILE
, BM_GETCHECK
, (WPARAM
)0, (LPARAM
)0) == BST_UNCHECKED
);
370 // FIXME: Rebuild the paging list
390 ReadRegSettings(HWND hwndDlg
)
394 DWORD dwDataSize
= 0x0;
399 // Open or create this key to read our settings
401 if(RegCreateKeyEx(HKEY_LOCAL_MACHINE
,
402 _T("SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Memory Management"),
405 REG_OPTION_NON_VOLATILE
,
406 KEY_WRITE
| KEY_READ
,
409 NULL
) == ERROR_SUCCESS
)
413 // Get the size of the data
415 if(RegQueryValueEx(hk
, _T("PagingFiles"), 0, &dwType
, (PBYTE
)NULL
, &dwDataSize
) == ERROR_SUCCESS
)
419 // Read paging file settings from the regisrty
421 if(RegQueryValueEx(hk
, _T("PagingFiles"), 0, &dwType
, (PBYTE
)(LPTSTR
)szValue
, &dwDataSize
) == ERROR_SUCCESS
)
424 // Parse our settings and set up controls accordingly
426 ParseMemSettings(szValue
, hwndDlg
);
431 // We had a problem :(
433 OutputDebugString(_T("Err read pagefile\n"));
439 // We had a problem :(
441 OutputDebugString(_T("Err open reg pagefile\n"));
453 ParseMemSettings(TCHAR
*szSettings
, HWND hwndDlg
)
455 TCHAR szVolName
[256];
469 // Clear out all our buffers
471 _wcsnset(szTemp
, 0, sizeof(szTemp
));
472 _wcsnset(szVolName
, 0, sizeof(szVolName
));
473 _wcsnset(szDrive
, 0, sizeof(szDrive
));
474 _wcsnset(szList
, 0, sizeof(szList
));
477 // Get a list of all the drives
479 GetLogicalDriveStrings(255, szDrvLst
);
482 // Print out our drives and our reg string
484 OutputDebugString(szDrvLst
);
485 OutputDebugString((TCHAR
*)szSettings
);
488 // Loop through all the drives
493 // Copy over the drive letter
495 wsprintf(szDrive
, _T("%s"), szDrvLst
+ nLastPos
);
499 // We should fixed and removeable drives, no network / cd
501 if(GetDriveType(szDrive
) == DRIVE_FIXED
|| GetDriveType(szDrive
) == DRIVE_REMOVABLE
)
504 // Get some info about out drive
506 GetVolumeInformation(szDrive
, (LPTSTR
)szVolName
, 255, NULL
, NULL
, NULL
, NULL
, 0);
509 // Cut off the Drive letter :
514 // Clear out our vars to prepare to walk page file setting string
520 // Walk through the list of page files
525 // Copy over a page file setting for a drive skipping already processed ones
527 wsprintf(szTemp
, _T("%s"), szSettings
+ nTemp
);
531 // Check to see if the drive for the page file setting matches our current drive
533 if(!_tcsnicmp(szTemp
,szDrive
,1))
536 // Extract the min/max size from the string
538 nMinSize
= (INT
)(wcsstr(szTemp
+ 16, _T(" ")) - (szTemp
+ 16)) + 1;
539 nMaxSize
= _wtoi(szTemp
+ 16 + nMinSize
);
540 nMinSize
= _wtoi(szTemp
+ 16);
543 // Fill in the page file settings in the internal array
545 g_sPagefile
[g_nCount
].nMaxValue
= nMaxSize
;
546 g_sPagefile
[g_nCount
].nMinValue
= nMinSize
;
547 g_sPagefile
[g_nCount
].nUsed
= 1;
548 wsprintf(g_sPagefile
[g_nCount
].szDrive
, _T("%s"), szDrive
);
551 // Add up one more page file found
556 // Indicate that we found a pagefile for this drive
564 // Skip passed the just processed drive setting
566 nTemp
+= _tcslen(szSettings
+ nTemp
) + 1;
569 // If we are done looking through the page file settings
570 // or found a matching setting then break out
572 if((_tcslen(szSettings
+ nTemp
) <= 0) || (bFound
== TRUE
))
579 // If we found a page file we make a string for the list box with the size
583 wsprintf(szList
, _T("%s [%s] %i - %i"), szDrive
, szVolName
, nMinSize
, nMaxSize
);
588 // Otherwise we make a blank pagefile element to show no page file
590 g_sPagefile
[g_nCount
].nMaxValue
= 0;
591 g_sPagefile
[g_nCount
].nMinValue
= 0;
592 g_sPagefile
[g_nCount
].nUsed
= 0;
595 // Copy over the drive for the blank page file element
597 wsprintf(g_sPagefile
[g_nCount
].szDrive
, _T("%s"), szDrive
);
600 // Add up one for the blank page file
605 // We just show the name of the drive if there is no page file
607 wsprintf(szList
, _T("%s [%s]"), szDrive
, szVolName
);
611 // Add our string to the page file list
613 SendDlgItemMessage(hwndDlg
, IDC_PAGEFILELIST
, LB_ADDSTRING
, (WPARAM
)NULL
, (LPARAM
)szList
);
616 // Print out the newly added string
618 OutputDebugString(szList
);
622 // Once all drive have finished being processed then we break out
624 if(_tcslen(szDrvLst
+ nLastPos
) <= 0)
632 void SaveSettings(HWND hwndDlg
)
641 // Clear out our buffers
643 _wcsnset(szValue
, 0, sizeof(szValue
));
644 _wcsnset(szTemp
, 0, sizeof(szTemp
));
647 // Go through all our internal pagefile records
649 for(nCount
= 0; nCount
< g_nCount
; ++nCount
)
652 // We only save it to the regisrty if is used
654 if(g_sPagefile
[nCount
].nUsed
== 1)
657 // Clear out our temp buffer
659 _wcsnset(szTemp
, 0, sizeof(szTemp
));
661 // Copy the path and sizes to our temp buffer for the page file
663 wsprintf(szTemp
, _T("%s\\pagefile.sys %i %i"), g_sPagefile
[nCount
].szDrive
, g_sPagefile
[nCount
].nMinValue
, g_sPagefile
[nCount
].nMaxValue
);
666 // Add it to our overall regisrty string
668 _tcscat(szValue
+nPos
,szTemp
);
671 // Record the positioon where the next string will be placed in the buffer
673 nPos
+= _tcslen(szTemp
) + 1;
674 // Add our null chars in to seperate the page files(REG_MULTI_SZ string)
675 szValue
[nPos
- 1] = 0;
681 // Now that we have page file setting string we open up the key to save it
683 if(RegCreateKeyEx(HKEY_LOCAL_MACHINE
,
684 _T("SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Memory Management"),
687 REG_OPTION_NON_VOLATILE
,
691 NULL
) == ERROR_SUCCESS
)
694 // We save our page file settings to the PagingFiles value
696 if (RegSetValueEx(hk
,
701 (DWORD
) (nPos
+2)*sizeof(TCHAR
)))
704 // We had a problem, so print out a message
706 OutputDebugString(_T("Could not save"));
709 // Get the error for our last operation
711 _ltow(GetLastError(), szValue
, 10);
714 // Print out the error code
716 OutputDebugString(szValue
);
721 // Close up the regisrty
728 // Print out an error that we couldnt open(create) the registry key.
730 OutputDebugString(_T("Could not open key"));