Author: turner Date: Mon Jul 31 03:14:02 2006 New Revision: 23381
URL: http://svn.reactos.org/svn/reactos?rev=23381&view=rev Log: Implement the reading and writing of pagefile settings. We should not longer have to edit it by hand in regedit. This works 100% flawlessly in win2k3 but has not been tested in ros yet. Patch by Christian Wallukat (cwallukat@gmx.at) and myself.
Modified: trunk/reactos/dll/cpl/sysdm/sysdm.rbuild trunk/reactos/dll/cpl/sysdm/virtmem.c
Modified: trunk/reactos/dll/cpl/sysdm/sysdm.rbuild URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/cpl/sysdm/sysdm.rbuild?... ============================================================================== --- trunk/reactos/dll/cpl/sysdm/sysdm.rbuild (original) +++ trunk/reactos/dll/cpl/sysdm/sysdm.rbuild Mon Jul 31 03:14:02 2006 @@ -11,6 +11,7 @@ <library>user32</library> <library>comctl32</library> <library>netapi32</library> + <library>ntdll</library> <file>advanced.c</file> <file>computer.c</file> <file>environment.c</file>
Modified: trunk/reactos/dll/cpl/sysdm/virtmem.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/cpl/sysdm/virtmem.c?rev... ============================================================================== --- trunk/reactos/dll/cpl/sysdm/virtmem.c (original) +++ trunk/reactos/dll/cpl/sysdm/virtmem.c Mon Jul 31 03:14:02 2006 @@ -1,39 +1,735 @@ +/* +* ReactOS +* Copyright (C) 2004 ReactOS Team +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +/* $Id$ +* +* PROJECT: ReactOS System Control Panel +* FILE: lib/cpl/sysdm/virtmem.c +* PURPOSE: pagefile settings +* PROGRAMMER: Christian Wallukat cwallukat(at)gmx(dot)at +*/ + #include <windows.h> #include <commctrl.h> #include <stdlib.h> #include <tchar.h> - #include "resource.h" #include "sysdm.h" - - -/* Environment dialog procedure */ -INT_PTR CALLBACK -VirtMemDlgProc(HWND hwndDlg, - UINT uMsg, - WPARAM wParam, - LPARAM lParam) +#include <stdio.h> +#include <winternl.h> + + + +// +// An array of these structs will interally manage system page files +// +typedef struct _sPagefiles { - UNREFERENCED_PARAMETER(lParam); - switch (uMsg) - { + WCHAR szDrive[10]; + INT nMinValue; + INT nMaxValue; + INT nUsed; +} sPageFiles; + + + +// +// At most there can be 32 drives, so only 32 page files +// +sPageFiles g_sPagefile[32]; +// +// This is the number of drives that could have page files +// +INT g_nCount; +// +// Will save the user set action signal saving to the registry on exit +// +BOOL g_bSave; + + +// +// ReadRegSettings reads the page file settings from the regisrty +// +VOID ReadRegSettings(HWND hwndDlg); +// +// ParseMemSettings takes the regisrty string and create the internal page file array +// +VOID ParseMemSettings(TCHAR *szSettings, HWND hwndDlg); +// +// SaveSettings writes the paging file array to the registry +// +VOID SaveSettings(HWND hwndDlg); + +// +// Callback function for messages for the windows +// +INT_PTR +CALLBACK +VirtMemDlgProc(HWND hwndDlg, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) +{ + SYSTEM_PROCESS_INFORMATION siSysPInfo; + TCHAR szTemp[255]; + INT nIndex = 0; + + // + // We dont need to look at this part of the message + // + UNREFERENCED_PARAMETER(lParam); + + switch (uMsg) + { case WM_INITDIALOG: - break; + { + // + // We dont save the changes until set is clicked + // + g_bSave = FALSE; + // + // We start with no page files + // + g_nCount = 0; + // + // Clear out the file pagefile + // + g_sPagefile[0].nMaxValue = 0; + g_sPagefile[0].nMinValue = 0; + g_sPagefile[0].nUsed = 0; + + // + // Grad the system stats to get some page file into + // + NtQuerySystemInformation(SystemProcessInformation, &siSysPInfo, sizeof(SYSTEM_PROCESS_INFORMATION), NULL); + + // + // Convert the pagefile usage to a string + // + _itow(siSysPInfo.PeakPagefileUsage, szTemp, 10); + + // + // Set pagefle useage to its label + // + SendDlgItemMessage(hwndDlg, IDC_CURRENT, WM_SETTEXT, (WPARAM)0, (LPARAM)szTemp); + + // + // Load the pagefile systems from the reg + // + ReadRegSettings(hwndDlg); + }; + break;
case WM_COMMAND: - switch (LOWORD(wParam)) - { - case IDCANCEL: - EndDialog(hwndDlg, 0); - return TRUE; - } - break; + { + switch (LOWORD(wParam)) + { + case IDCANCEL: + { + // + // If the user hits cancel we just close and dont save + // + EndDialog(hwndDlg, 0); + return TRUE; + }; + break; + + + case IDOK: + { + // + // Check to make sure that the user hit set and we will save the settings + // + if(g_bSave == TRUE) + { + SaveSettings(hwndDlg); + }; + + // + // Close out the window + // + EndDialog(hwndDlg, 0); + }; + break; + + + case IDC_PAGEFILELIST: + { + switch(HIWORD(wParam)) + { + case LBN_SELCHANGE: + { + // + // Get the currently selected page file from the list box + // + nIndex = (INT)SendDlgItemMessage(hwndDlg, IDC_PAGEFILELIST, LB_GETCURSEL, (WPARAM)0, (LPARAM)0); + + // + // If the index is in our range then process that page file + // + if(nIndex < g_nCount) + { + // + // Convert the minvalue for the page file + // + _itow(g_sPagefile[nIndex].nMinValue, szTemp, 10); + + // + // Set the min value to its textbox + // + SendDlgItemMessage(hwndDlg, IDC_INITIALSIZE, WM_SETTEXT, (WPARAM)0, (LPARAM)szTemp); + + // + // Convert the max value of the page file to a string + // + _itow(g_sPagefile[nIndex].nMaxValue, szTemp, 10); + + // + // Set the max value to its textbox + // + SendDlgItemMessage(hwndDlg, IDC_MAXSIZE, WM_SETTEXT, (WPARAM)0, (LPARAM)szTemp); + + // + // Figure out what type of page file it is + // + if(g_sPagefile[nIndex].nMinValue == 0 && g_sPagefile[nIndex].nMaxValue == 0) + { + // + // There is either no page file or a system managed page file so we disable custom sizes + // + EnableWindow(GetDlgItem(hwndDlg, IDC_MAXSIZE), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_INITIALSIZE), FALSE); + // + // Check to see if that drive is used for paging + // + if(g_sPagefile[nIndex].nUsed == 1) + { + // + // This is a system managed page file + // + SendDlgItemMessage(hwndDlg, IDC_NOPAGEFILE, BM_SETCHECK, (WPARAM)0, (LPARAM)0); + SendDlgItemMessage(hwndDlg, IDC_SYSMANSIZE, BM_SETCHECK, (WPARAM)1, (LPARAM)0); + SendDlgItemMessage(hwndDlg, IDC_CUSTOM, BM_SETCHECK, (WPARAM)0, (LPARAM)0); + } + else + { + // + // There is no page file on this drive + // + SendDlgItemMessage(hwndDlg, IDC_NOPAGEFILE, BM_SETCHECK, (WPARAM)1, (LPARAM)0); + SendDlgItemMessage(hwndDlg, IDC_SYSMANSIZE, BM_SETCHECK, (WPARAM)0, (LPARAM)0); + SendDlgItemMessage(hwndDlg, IDC_CUSTOM, BM_SETCHECK, (WPARAM)0, (LPARAM)0); + } + } + else + { + // + // THis is a custom sized page file + // + SendDlgItemMessage(hwndDlg, IDC_NOPAGEFILE, BM_SETCHECK, (WPARAM)0, (LPARAM)0); + SendDlgItemMessage(hwndDlg, IDC_SYSMANSIZE, BM_SETCHECK, (WPARAM)0, (LPARAM)0); + SendDlgItemMessage(hwndDlg, IDC_CUSTOM, BM_SETCHECK, (WPARAM)1, (LPARAM)0); + // + // We need to allow the user to change the sizes + // + EnableWindow(GetDlgItem(hwndDlg, IDC_MAXSIZE), TRUE); + EnableWindow(GetDlgItem(hwndDlg, IDC_INITIALSIZE), TRUE); + } + }; + }; + break; + }; + }; + break; + + + case IDC_NOPAGEFILE: + { + // + // Set the pagefile to no page file + // + SendDlgItemMessage(hwndDlg, IDC_NOPAGEFILE, BM_SETCHECK, (WPARAM)1, (LPARAM)0); + SendDlgItemMessage(hwndDlg, IDC_SYSMANSIZE, BM_SETCHECK, (WPARAM)0, (LPARAM)0); + SendDlgItemMessage(hwndDlg, IDC_CUSTOM, BM_SETCHECK, (WPARAM)0, (LPARAM)0); + + // + // Disable the page file custom size boxes + // + EnableWindow(GetDlgItem(hwndDlg, IDC_MAXSIZE), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_INITIALSIZE), FALSE); + }; + break; + + case IDC_SYSMANSIZE: + { + // + // User changed this to a system managed page file + // + SendDlgItemMessage(hwndDlg, IDC_NOPAGEFILE, BM_SETCHECK, (WPARAM)0, (LPARAM)0); + SendDlgItemMessage(hwndDlg, IDC_SYSMANSIZE, BM_SETCHECK, (WPARAM)1, (LPARAM)0); + SendDlgItemMessage(hwndDlg, IDC_CUSTOM, BM_SETCHECK, (WPARAM)0, (LPARAM)0); + + // + // Disable the page file custom size boxes + // + EnableWindow(GetDlgItem(hwndDlg, IDC_MAXSIZE), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_INITIALSIZE), FALSE); + }; + break; + + case IDC_CUSTOM: + { + // + // User changed this to a cutom sized page file + // + SendDlgItemMessage(hwndDlg, IDC_NOPAGEFILE, BM_SETCHECK, (WPARAM)0, (LPARAM)0); + SendDlgItemMessage(hwndDlg, IDC_SYSMANSIZE, BM_SETCHECK, (WPARAM)0, (LPARAM)0); + SendDlgItemMessage(hwndDlg, IDC_CUSTOM, BM_SETCHECK, (WPARAM)1, (LPARAM)0); + + // + // The user should be able to change the size of these files + // + EnableWindow(GetDlgItem(hwndDlg, IDC_MAXSIZE), TRUE); + EnableWindow(GetDlgItem(hwndDlg, IDC_INITIALSIZE), TRUE); + }; + break; + + case IDC_SET: + { + // + // The user hit set, so we are clear to save the settings when we are done + // + g_bSave = TRUE; + + // + // Figure out which pagefile we are saving the settings too + // + nIndex = SendDlgItemMessage(hwndDlg, IDC_PAGEFILELIST, LB_GETCURSEL, (WPARAM)0, (LPARAM)0); + + // + // Make sure it isnt out of our range + // + if(nIndex < g_nCount) + { + // + // Check to see what the current user input settings are + // + if(SendDlgItemMessage(hwndDlg, IDC_CUSTOM, BM_GETCHECK, (WPARAM)0, (LPARAM)0) == BST_CHECKED) + { + // + // If custom is checked we need to get the min size + // + SendDlgItemMessage(hwndDlg, IDC_INITIALSIZE, WM_GETTEXT, (WPARAM)254, (LPARAM)szTemp); + + // + // Convert the size to an int and save it + // + g_sPagefile[nIndex].nMinValue = _wtoi(szTemp); + + // + // If custom is checked we need to get the max size + // + SendDlgItemMessage(hwndDlg, IDC_MAXSIZE, WM_GETTEXT, (WPARAM)254, (LPARAM)szTemp); + + // + // If custom is checked we need to get the max size + // + g_sPagefile[nIndex].nMaxValue = _wtoi(szTemp); + + } + else + { + // + // If it is no paging file or system then we set the sizes to zero + // + g_sPagefile[nIndex].nMinValue = g_sPagefile[nIndex].nMaxValue = 0; + } + + // + // We check to see if this drive is used for a paging file anymore + // + g_sPagefile[nIndex].nUsed = (SendDlgItemMessage(hwndDlg, IDC_NOPAGEFILE, BM_GETCHECK, (WPARAM)0, (LPARAM)0) == BST_UNCHECKED); + + + // + // FIXME: Rebuild the paging list + // + }; + }; + break; + }; + }; + break;
case WM_NOTIFY: - break; - } - - return FALSE; -} + { + }; + break; + }; + + return FALSE; +}; + + +VOID +ReadRegSettings(HWND hwndDlg) +{ + HKEY hk = NULL; + DWORD dwType = 0x0; + DWORD dwDataSize = 0x0; + TCHAR szValue[2048]; + + + // + // Open or create this key to read our settings + // + if(RegCreateKeyEx(HKEY_LOCAL_MACHINE, + _T("SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management"), + 0x0, + NULL, + REG_OPTION_NON_VOLATILE, + KEY_WRITE | KEY_READ, + NULL, + &hk, + NULL) == ERROR_SUCCESS) + { + + // + // Get the size of the data + // + if(RegQueryValueEx(hk, _T("PagingFiles"), 0, &dwType, (PBYTE)NULL, &dwDataSize) == ERROR_SUCCESS) + { + + // + // Read paging file settings from the regisrty + // + if(RegQueryValueEx(hk, _T("PagingFiles"), 0, &dwType, (PBYTE)(LPTSTR)szValue, &dwDataSize) == ERROR_SUCCESS) + { + // + // Parse our settings and set up controls accordingly + // + ParseMemSettings(szValue, hwndDlg); + } + else + { + // + // We had a problem :( + // + OutputDebugString(_T("Err read pagefile\n")); + }; + } + else + { + // + // We had a problem :( + // + OutputDebugString(_T("Err open reg pagefile\n")); + }; + + // + // Close our key + // + RegCloseKey(hk); + }; +}; + + +VOID +ParseMemSettings(TCHAR *szSettings, HWND hwndDlg) +{ + TCHAR szVolName[256]; + TCHAR szDrive[25]; + TCHAR szDrvLst[256]; + TCHAR szTemp[256]; + TCHAR szList[256]; + INT nLastPos = 0; + INT nMinSize = 0; + INT nMaxSize = 0; + INT nTemp = 0; + BOOL bFound = FALSE; + + g_nCount = 0; + + // + // Clear out all our buffers + // + _wcsnset(szTemp, 0, sizeof(szTemp)); + _wcsnset(szVolName, 0, sizeof(szVolName)); + _wcsnset(szDrive, 0, sizeof(szDrive)); + _wcsnset(szList, 0, sizeof(szList)); + + // + // Get a list of all the drives + // + GetLogicalDriveStrings(255, szDrvLst); + + // + // Print out our drives and our reg string + // + OutputDebugString(szDrvLst); + OutputDebugString((TCHAR*)szSettings); + + // + // Loop through all the drives + // + while(TRUE) + { + // + // Copy over the drive letter + // + wsprintf(szDrive, _T("%s"), szDrvLst + nLastPos); + nLastPos += 4; + + // + // We should fixed and removeable drives, no network / cd + // + if(GetDriveType(szDrive) == DRIVE_FIXED || GetDriveType(szDrive) == DRIVE_REMOVABLE) + { + // + // Get some info about out drive + // + GetVolumeInformation(szDrive, (LPTSTR)szVolName, 255, NULL, NULL, NULL, NULL, 0); + + // + // Cut off the Drive letter : + // + szDrive[2] = 0; + + // + // Clear out our vars to prepare to walk page file setting string + // + nTemp = 0; + bFound = FALSE; + + // + // Walk through the list of page files + // + while(TRUE) + { + // + // Copy over a page file setting for a drive skipping already processed ones + // + wsprintf(szTemp, _T("%s"), szSettings + nTemp); + + + // + // Check to see if the drive for the page file setting matches our current drive + // + if(!_tcsnicmp(szTemp,szDrive,1)) + { + // + // Extract the min/max size from the string + // + nMinSize = (INT)(wcsstr(szTemp + 16, _T(" ")) - (szTemp + 16)) + 1; + nMaxSize = _wtoi(szTemp + 16 + nMinSize); + nMinSize = _wtoi(szTemp + 16); + + // + // Fill in the page file settings in the internal array + // + g_sPagefile[g_nCount].nMaxValue = nMaxSize; + g_sPagefile[g_nCount].nMinValue = nMinSize; + g_sPagefile[g_nCount].nUsed = 1; + wsprintf(g_sPagefile[g_nCount].szDrive, _T("%s"), szDrive); + + // + // Add up one more page file found + // + ++g_nCount; + + // + // Indicate that we found a pagefile for this drive + // + bFound = TRUE; + + break; + }; + + // + // Skip passed the just processed drive setting + // + nTemp += _tcslen(szSettings + nTemp) + 1; + + // + // If we are done looking through the page file settings + // or found a matching setting then break out + // + if((_tcslen(szSettings + nTemp) <= 0) || (bFound == TRUE)) + { + break; + }; + }; + + // + // If we found a page file we make a string for the list box with the size + // + if(bFound == TRUE) + { + wsprintf(szList, _T("%s [%s] %i - %i"), szDrive, szVolName, nMinSize, nMaxSize); + } + else + { + // + // Otherwise we make a blank pagefile element to show no page file + // + g_sPagefile[g_nCount].nMaxValue = 0; + g_sPagefile[g_nCount].nMinValue = 0; + g_sPagefile[g_nCount].nUsed = 0; + + // + // Copy over the drive for the blank page file element + // + wsprintf(g_sPagefile[g_nCount].szDrive, _T("%s"), szDrive); + + // + // Add up one for the blank page file + // + ++g_nCount; + + // + // We just show the name of the drive if there is no page file + // + wsprintf(szList, _T("%s [%s]"), szDrive, szVolName); + }; + + // + // Add our string to the page file list + // + SendDlgItemMessage(hwndDlg, IDC_PAGEFILELIST, LB_ADDSTRING, (WPARAM)NULL, (LPARAM)szList); + + // + // Print out the newly added string + // + OutputDebugString(szList); + }; + + // + // Once all drive have finished being processed then we break out + // + if(_tcslen(szDrvLst + nLastPos) <= 0) + { + return; + }; + }; +}; + + +void SaveSettings(HWND hwndDlg) +{ + HKEY hk = NULL; + TCHAR szValue[2048]; + TCHAR szTemp[512]; + INT nCount = 0; + INT nPos = 0; + + // + // Clear out our buffers + // + _wcsnset(szValue, 0, sizeof(szValue)); + _wcsnset(szTemp, 0, sizeof(szTemp)); + + // + // Go through all our internal pagefile records + // + for(nCount = 0; nCount < g_nCount; ++nCount) + { + // + // We only save it to the regisrty if is used + // + if(g_sPagefile[nCount].nUsed == 1) + { + // + // Clear out our temp buffer + // + _wcsnset(szTemp, 0, sizeof(szTemp)); + // + // Copy the path and sizes to our temp buffer for the page file + // + wsprintf(szTemp, _T("%s\pagefile.sys %i %i"), g_sPagefile[nCount].szDrive, g_sPagefile[nCount].nMinValue, g_sPagefile[nCount].nMaxValue); + + // + // Add it to our overall regisrty string + // + _tcscat(szValue+nPos,szTemp); + + // + // Record the positioon where the next string will be placed in the buffer + // + nPos += _tcslen(szTemp) + 1; + // Add our null chars in to seperate the page files(REG_MULTI_SZ string) + szValue[nPos - 1] = 0; + szValue[nPos] = 0; + }; + }; + + // + // Now that we have page file setting string we open up the key to save it + // + if(RegCreateKeyEx(HKEY_LOCAL_MACHINE, + _T("SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management"), + 0x0, + NULL, + REG_OPTION_NON_VOLATILE, + KEY_ALL_ACCESS, + NULL, + &hk, + NULL) == ERROR_SUCCESS) + { + // + // We save our page file settings to the PagingFiles value + // + if (RegSetValueEx(hk, + _T("PagingFiles"), + 0, + REG_MULTI_SZ, + (LPBYTE) szValue, + (DWORD) (nPos+2)*sizeof(TCHAR))) + { + // + // We had a problem, so print out a message + // + OutputDebugString(_T("Could not save")); + + // + // Get the error for our last operation + // + _ltow(GetLastError(), szValue, 10); + + // + // Print out the error code + // + OutputDebugString(szValue); + + } + + // + // Close up the regisrty + // + RegCloseKey(hk); + } + else + { + // + // Print out an error that we couldnt open(create) the registry key. + // + OutputDebugString(_T("Could not open key")); + }; +}; +
/* EOF */