[KSPROXY]
[reactos.git] / reactos / dll / cpl / sysdm / virtmem.c
index 4aefd68..6dcd9ad 100644 (file)
-#include <windows.h>\r
-#include <commctrl.h>\r
-#include <stdlib.h>\r
-#include <tchar.h>\r
-\r
-#include "resource.h"\r
-#include "sysdm.h"\r
-\r
-\r
-/* Environment dialog procedure */\r
-INT_PTR CALLBACK\r
-VirtMemDlgProc(HWND hwndDlg,\r
-                  UINT uMsg,\r
-                  WPARAM wParam,\r
-                  LPARAM lParam)\r
-{\r
-  UNREFERENCED_PARAMETER(lParam)\r
-  switch (uMsg)\r
-  {\r
-    case WM_INITDIALOG:\r
-      break;\r
-\r
-    case WM_COMMAND:\r
-      switch (LOWORD(wParam))\r
-      {\r
-        case IDCANCEL:\r
-          EndDialog(hwndDlg, 0);\r
-          return TRUE;\r
-      }\r
-      break;\r
-\r
-    case WM_NOTIFY:\r
-      break;\r
-  }\r
-\r
-  return FALSE;\r
-}\r
-\r
-/* EOF */\r
+/*
+ * PROJECT:     ReactOS system properties, control panel applet
+ * LICENSE:     GPL - See COPYING in the top level directory
+ * FILE:        dll/cpl/sysdm/virtual.c
+ * PURPOSE:     Virtual memory control dialog
+ * COPYRIGHT:   Copyright 2006 Ged Murphy <gedmurphy@gmail.com>
+ *
+ */
+
+#include "precomp.h"
+
+static BOOL OnSelChange(HWND hwndDlg, PVIRTMEM pVirtMem);
+static LPCTSTR lpKey = _T("SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Memory Management");
+
+static BOOL
+ReadPageFileSettings(PVIRTMEM pVirtMem)
+{
+    HKEY hkey = NULL;
+    DWORD dwType;
+    DWORD dwDataSize;
+    BOOL bRet = FALSE;
+
+    if (RegCreateKeyEx(HKEY_LOCAL_MACHINE,
+                       lpKey,
+                       0,
+                       NULL,
+                       REG_OPTION_NON_VOLATILE,
+                       KEY_QUERY_VALUE,
+                       NULL,
+                       &hkey,
+                       NULL) == ERROR_SUCCESS)
+    {
+        if (RegQueryValueEx(hkey,
+                            _T("PagingFiles"),
+                            NULL,
+                            &dwType,
+                            NULL,
+                            &dwDataSize) == ERROR_SUCCESS)
+        {
+            pVirtMem->szPagingFiles = (LPTSTR)HeapAlloc(GetProcessHeap(),
+                                                        0,
+                                                        dwDataSize);
+            if (pVirtMem->szPagingFiles != NULL)
+            {
+                ZeroMemory(pVirtMem->szPagingFiles,
+                           dwDataSize);
+                if (RegQueryValueEx(hkey,
+                                    _T("PagingFiles"),
+                                    NULL,
+                                    &dwType,
+                                    (PBYTE)pVirtMem->szPagingFiles,
+                                    &dwDataSize) == ERROR_SUCCESS)
+                {
+                    bRet = TRUE;
+                }
+            }
+        }
+    }
+
+    if (!bRet)
+        ShowLastWin32Error(pVirtMem->hSelf);
+
+    if (hkey != NULL)
+        RegCloseKey(hkey);
+
+    return bRet;
+}
+
+
+static VOID
+GetPageFileSizes(LPTSTR lpPageFiles,
+                 LPINT lpInitialSize,
+                 LPINT lpMaximumSize)
+{
+    INT i = 0;
+
+    *lpInitialSize = -1;
+    *lpMaximumSize = -1;
+
+    while (*lpPageFiles != _T('\0'))
+    {
+        if (*lpPageFiles == _T(' '))
+        {
+            lpPageFiles++;
+
+            switch (i)
+            {
+                case 0:
+                    *lpInitialSize = (INT)_ttoi(lpPageFiles);
+                    i = 1;
+                    break;
+
+                case 1:
+                    *lpMaximumSize = (INT)_ttoi(lpPageFiles);
+                    return;
+            }
+        }
+
+        lpPageFiles++;
+    }
+}
+
+
+static VOID
+ParseMemSettings(PVIRTMEM pVirtMem)
+{
+    TCHAR szDrives[1024];    // all drives
+    LPTSTR DrivePtr = szDrives;
+    TCHAR szDrive[3]; // single drive
+    TCHAR szVolume[MAX_PATH];
+    TCHAR *szDisplayString;
+    INT InitialSize = 0;
+    INT MaxSize = 0;
+    INT DriveLen;
+    INT PgCnt = 0;
+
+    DriveLen = GetLogicalDriveStrings(1023,
+                                      szDrives);
+
+    szDisplayString = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (MAX_PATH * 2 + 69) * sizeof(TCHAR));
+    if (szDisplayString == NULL)
+        return;
+
+    while (DriveLen != 0)
+    {
+        INT Len;
+
+        Len = lstrlen(DrivePtr) + 1;
+        DriveLen -= Len;
+
+        DrivePtr = _tcsupr(DrivePtr);
+
+        /* copy the 'X:' portion */
+        lstrcpyn(szDrive, DrivePtr, sizeof(szDrive) / sizeof(TCHAR));
+
+        if (GetDriveType(DrivePtr) == DRIVE_FIXED)
+        {
+            /* does drive match the one in the registry ? */
+            if (!_tcsncmp(pVirtMem->szPagingFiles, szDrive, 2))
+            {
+                /* FIXME: we only check the first available pagefile in the reg */
+                GetPageFileSizes(pVirtMem->szPagingFiles,
+                                 &InitialSize,
+                                 &MaxSize);
+
+                pVirtMem->Pagefile[PgCnt].InitialValue = InitialSize;
+                pVirtMem->Pagefile[PgCnt].MaxValue = MaxSize;
+                pVirtMem->Pagefile[PgCnt].bUsed = TRUE;
+                lstrcpy(pVirtMem->Pagefile[PgCnt].szDrive, szDrive);
+            }
+            else
+            {
+                pVirtMem->Pagefile[PgCnt].InitialValue = 0;
+                pVirtMem->Pagefile[PgCnt].MaxValue = 0;
+                pVirtMem->Pagefile[PgCnt].bUsed = FALSE;
+                lstrcpy(pVirtMem->Pagefile[PgCnt].szDrive, szDrive);
+            }
+
+            _tcscpy(szDisplayString, szDrive);
+            _tcscat(szDisplayString, _T("\t"));
+
+            /* set a volume label if there is one */
+            if (GetVolumeInformation(DrivePtr,
+                                     szVolume,
+                                     255,
+                                     NULL,
+                                     NULL,
+                                     NULL,
+                                     NULL,
+                                     0))
+            {
+                if (szVolume[0] != _T('\0'))
+                {
+                    TCHAR szVol[MAX_PATH + 2];
+                    _stprintf(szVol, _T("[%s]"), szVolume);
+                    _tcscat(szDisplayString, szVol);
+                }
+            }
+
+            if ((InitialSize != 0) || (MaxSize != 0))
+            {
+                TCHAR szSize[64];
+
+                _stprintf(szSize, _T("%i - %i"), InitialSize, MaxSize);
+                _tcscat(szDisplayString, _T("\t"));
+                _tcscat(szDisplayString, szSize);
+            }
+
+            SendMessage(pVirtMem->hListBox, LB_ADDSTRING, (WPARAM)0, (LPARAM)szDisplayString);
+            PgCnt++;
+        }
+
+        DrivePtr += Len;
+    }
+
+    SendMessage(pVirtMem->hListBox, LB_SETCURSEL, (WPARAM)0, (LPARAM)0);
+    HeapFree(GetProcessHeap(), 0, szDisplayString);
+    pVirtMem->Count = PgCnt;
+    OnSelChange(pVirtMem->hSelf, pVirtMem);
+}
+
+
+static VOID
+WritePageFileSettings(PVIRTMEM pVirtMem)
+{
+    HKEY hk = NULL;
+    TCHAR szPagingFiles[2048];
+    TCHAR szText[256];
+    INT i;
+    INT nPos = 0;
+    BOOL bErr = TRUE;
+
+    for (i = 0; i < pVirtMem->Count; ++i)
+    {
+        if (pVirtMem->Pagefile[i].bUsed)
+        {
+            _stprintf(szText, _T("%s\\pagefile.sys %i %i"),
+                      pVirtMem->Pagefile[i].szDrive,
+                      pVirtMem->Pagefile[i].InitialValue,
+                      pVirtMem->Pagefile[i].MaxValue);
+
+            /* Add it to our overall registry string */
+            lstrcat(szPagingFiles + nPos, szText);
+
+            /* Record the position where the next string will start */
+            nPos += (INT)lstrlen(szText) + 1;
+
+            /* add another NULL for REG_MULTI_SZ */
+            szPagingFiles[nPos] = _T('\0');
+            nPos++;
+        }
+    }
+
+    if (RegCreateKeyEx(HKEY_LOCAL_MACHINE,
+                       lpKey,
+                       0,
+                       NULL,
+                       REG_OPTION_NON_VOLATILE,
+                       KEY_WRITE,
+                       NULL,
+                       &hk,
+                       NULL) == ERROR_SUCCESS)
+    {
+        if (RegSetValueEx(hk,
+                          _T("PagingFiles"),
+                          0,
+                          REG_MULTI_SZ,
+                          (LPBYTE) szPagingFiles,
+                          (DWORD) nPos * sizeof(TCHAR)) == ERROR_SUCCESS)
+        {
+            bErr = FALSE;
+        }
+
+        RegCloseKey(hk);
+    }
+
+    if (bErr)
+        ShowLastWin32Error(pVirtMem->hSelf);
+}
+
+
+static VOID
+SetListBoxColumns(HWND hwndListBox)
+{
+    const INT tabs[2] = {30, 120};
+
+    SendMessage(hwndListBox, LB_SETTABSTOPS, (WPARAM)2, (LPARAM)&tabs[0]);
+}
+
+
+static VOID
+OnNoPagingFile(PVIRTMEM pVirtMem)
+{
+    /* Disable the page file custom size boxes */
+    EnableWindow(GetDlgItem(pVirtMem->hSelf, IDC_INITIALSIZE), FALSE);
+    EnableWindow(GetDlgItem(pVirtMem->hSelf, IDC_MAXSIZE), FALSE);
+}
+
+
+static VOID
+OnSysManSize(PVIRTMEM pVirtMem)
+{
+    /* Disable the page file custom size boxes */
+    EnableWindow(GetDlgItem(pVirtMem->hSelf, IDC_INITIALSIZE), FALSE);
+    EnableWindow(GetDlgItem(pVirtMem->hSelf, IDC_MAXSIZE), FALSE);
+}
+
+
+static VOID
+OnCustom(PVIRTMEM pVirtMem)
+{
+    /* Enable the page file custom size boxes */
+    EnableWindow(GetDlgItem(pVirtMem->hSelf, IDC_INITIALSIZE), TRUE);
+    EnableWindow(GetDlgItem(pVirtMem->hSelf, IDC_MAXSIZE), TRUE);
+}
+
+
+static VOID
+OnSet(PVIRTMEM pVirtMem)
+{
+    INT Index;
+    UINT Value;
+    BOOL bTranslated;
+
+    pVirtMem->bSave = TRUE;
+
+    Index  = (INT)SendDlgItemMessage(pVirtMem->hSelf,
+                                     IDC_PAGEFILELIST,
+                                     LB_GETCURSEL,
+                                     0,
+                                     0);
+    if (Index < pVirtMem->Count)
+    {
+        /* check if custom settings are checked */
+        if (IsDlgButtonChecked(pVirtMem->hSelf,
+                               IDC_CUSTOM) == BST_CHECKED)
+        {
+            Value = GetDlgItemInt(pVirtMem->hSelf,
+                                  IDC_INITIALSIZE,
+                                  &bTranslated,
+                                  FALSE);
+            if (!bTranslated)
+            {
+                /* FIXME: Show error message instead of setting the edit
+                          field to the previous value */
+                SetDlgItemInt(pVirtMem->hSelf,
+                              IDC_INITIALSIZE,
+                              pVirtMem->Pagefile[Index].InitialValue,
+                              FALSE);
+            }
+            else
+            {
+                pVirtMem->Pagefile[Index].InitialValue = Value;
+            }
+
+            Value = GetDlgItemInt(pVirtMem->hSelf,
+                                  IDC_MAXSIZE,
+                                  &bTranslated,
+                                  FALSE);
+            if (!bTranslated)
+            {
+                /* FIXME: Show error message instead of setting the edit
+                          field to the previous value */
+                SetDlgItemInt(pVirtMem->hSelf,
+                              IDC_MAXSIZE,
+                              pVirtMem->Pagefile[Index].MaxValue,
+                              FALSE);
+            }
+            else
+            {
+                pVirtMem->Pagefile[Index].MaxValue = Value;
+            }
+        }
+        else
+        {
+            /* set sizes to 0 */
+            pVirtMem->Pagefile[Index].InitialValue = pVirtMem->Pagefile[Index].MaxValue = 0;
+
+            // check to see if this drive is used for a paging file
+            if (IsDlgButtonChecked(pVirtMem->hSelf,
+                                   IDC_NOPAGEFILE) == BST_UNCHECKED)
+            {
+                pVirtMem->Pagefile[Index].bUsed = TRUE;
+            }
+            else
+            {
+                pVirtMem->Pagefile[Index].bUsed = FALSE;
+            }
+        }
+    }
+}
+
+
+static BOOL
+OnSelChange(HWND hwndDlg, PVIRTMEM pVirtMem)
+{
+    TCHAR szBuffer[64];
+    MEMORYSTATUSEX MemoryStatus;
+    ULARGE_INTEGER FreeBytes;
+    DWORDLONG FreeMemory;
+    INT Index;
+    INT i;
+    INT FileSize;
+
+    Index = (INT)SendDlgItemMessage(hwndDlg,
+                                    IDC_PAGEFILELIST,
+                                    LB_GETCURSEL,
+                                    0,
+                                    0);
+    if (Index < pVirtMem->Count)
+    {
+        /* Set drive letter */
+        SetDlgItemText(hwndDlg, IDC_DRIVE,
+                       pVirtMem->Pagefile[Index].szDrive);
+
+        /* Set available disk space */
+        if (GetDiskFreeSpaceEx(pVirtMem->Pagefile[Index].szDrive,
+                               NULL, NULL, &FreeBytes))
+        {
+            _stprintf(szBuffer, _T("%I64u MB"), FreeBytes.QuadPart / (1024 * 1024));
+            SetDlgItemText(hwndDlg, IDC_SPACEAVAIL, szBuffer);
+        }
+
+        if (pVirtMem->Pagefile[Index].InitialValue  != 0 &&
+            pVirtMem->Pagefile[Index].MaxValue != 0)
+        {
+            /* enable and fill the custom values */
+            EnableWindow(GetDlgItem(pVirtMem->hSelf, IDC_MAXSIZE), TRUE);
+            EnableWindow(GetDlgItem(pVirtMem->hSelf, IDC_INITIALSIZE), TRUE);
+
+            SetDlgItemInt(pVirtMem->hSelf,
+                          IDC_INITIALSIZE,
+                          pVirtMem->Pagefile[Index].InitialValue,
+                          FALSE);
+
+            SetDlgItemInt(pVirtMem->hSelf,
+                          IDC_MAXSIZE,
+                          pVirtMem->Pagefile[Index].MaxValue,
+                          FALSE);
+
+            CheckDlgButton(pVirtMem->hSelf,
+                           IDC_CUSTOM,
+                           BST_CHECKED);
+        }
+        else
+        {
+            /* It's not a custom value */
+            EnableWindow(GetDlgItem(pVirtMem->hSelf, IDC_MAXSIZE), FALSE);
+            EnableWindow(GetDlgItem(pVirtMem->hSelf, IDC_INITIALSIZE), FALSE);
+
+            /* is it system managed */
+            if (pVirtMem->Pagefile[Index].bUsed)
+            {
+                CheckDlgButton(pVirtMem->hSelf,
+                               IDC_SYSMANSIZE,
+                               BST_CHECKED);
+            }
+            else
+            {
+                CheckDlgButton(pVirtMem->hSelf,
+                               IDC_NOPAGEFILE,
+                               BST_CHECKED);
+            }
+        }
+
+        /* Set minimum pagefile size */
+        SetDlgItemText(hwndDlg, IDC_MINIMUM, _T("2 MB"));
+
+        /* Set recommended pagefile size */
+        MemoryStatus.dwLength = sizeof(MEMORYSTATUSEX);
+        if (GlobalMemoryStatusEx(&MemoryStatus))
+        {
+            FreeMemory = MemoryStatus.ullTotalPhys / (1024 * 1024);
+            _stprintf(szBuffer, _T("%I64u MB"), FreeMemory + (FreeMemory / 2));
+            SetDlgItemText(hwndDlg, IDC_RECOMMENDED, szBuffer);
+        }
+
+        /* Set current pagefile size */
+        FileSize = 0;
+        for (i = 0; i < 26; i++)
+        {
+            FileSize += pVirtMem->Pagefile[i].InitialValue;
+        }
+        _stprintf(szBuffer, _T("%u MB"), FileSize);
+        SetDlgItemText(hwndDlg, IDC_CURRENT, szBuffer);
+    }
+
+    return TRUE;
+}
+
+
+static VOID
+OnOk(PVIRTMEM pVirtMem)
+{
+    if (pVirtMem->bSave == TRUE)
+    {
+        WritePageFileSettings(pVirtMem);
+    }
+}
+
+
+static VOID
+OnInitDialog(HWND hwnd, PVIRTMEM pVirtMem)
+{
+    pVirtMem->hSelf = hwnd;
+    pVirtMem->hListBox = GetDlgItem(hwnd, IDC_PAGEFILELIST);
+    pVirtMem->bSave = FALSE;
+
+    SetListBoxColumns(pVirtMem->hListBox);
+
+    /* Load the pagefile systems from the reg */
+    if (ReadPageFileSettings(pVirtMem))
+    {
+        /* Parse our settings and set up dialog */
+        ParseMemSettings(pVirtMem);
+    }
+}
+
+
+INT_PTR CALLBACK
+VirtMemDlgProc(HWND hwndDlg,
+               UINT uMsg,
+               WPARAM wParam,
+               LPARAM lParam)
+{
+    PVIRTMEM pVirtMem;
+
+    UNREFERENCED_PARAMETER(lParam);
+
+    pVirtMem = (PVIRTMEM)GetWindowLongPtr(hwndDlg, DWLP_USER);
+
+    switch (uMsg)
+    {
+        case WM_INITDIALOG:
+            pVirtMem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(VIRTMEM));
+            if (pVirtMem == NULL)
+            {
+                EndDialog(hwndDlg, 0);
+                return FALSE;
+            }
+
+            SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pVirtMem);
+
+            OnInitDialog(hwndDlg, pVirtMem);
+            break;
+
+        case WM_DESTROY:
+            if (pVirtMem->szPagingFiles)
+                HeapFree(GetProcessHeap(), 0,
+                         pVirtMem->szPagingFiles);
+            HeapFree(GetProcessHeap(), 0, pVirtMem);
+            break;
+
+        case WM_COMMAND:
+            switch (LOWORD(wParam))
+            {
+                case IDCANCEL:
+                    EndDialog(hwndDlg, 0);
+                    return TRUE;
+
+                case IDOK:
+                    OnOk(pVirtMem);
+                    EndDialog(hwndDlg, 0);
+                    return TRUE;
+
+                case IDC_NOPAGEFILE:
+                    OnNoPagingFile(pVirtMem);
+                    return TRUE;
+
+                case IDC_SYSMANSIZE:
+                    OnSysManSize(pVirtMem);
+                    return TRUE;
+
+                case IDC_CUSTOM:
+                    OnCustom(pVirtMem);
+                    return TRUE;
+
+                case IDC_SET:
+                    OnSet(pVirtMem);
+                    return TRUE;
+
+                case IDC_PAGEFILELIST:
+                    switch HIWORD(wParam)
+                    {
+                        case LBN_SELCHANGE:
+                            OnSelChange(hwndDlg, pVirtMem);
+                            return TRUE;
+                    }
+                    break;
+            }
+            break;
+    }
+
+    return FALSE;
+}