- Move NCI generated files to arch-specific directories
[reactos.git] / reactos / dll / cpl / sysdm / virtmem.c
1 /*
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>
7 *
8 */
9
10 #include "precomp.h"
11
12 static LPCTSTR lpKey = _T("SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Memory Management");
13
14 static BOOL
15 ReadPageFileSettings(PVIRTMEM pVirtMem)
16 {
17 HKEY hkey = NULL;
18 DWORD dwType;
19 DWORD dwDataSize;
20 BOOL bRet = FALSE;
21
22 if(RegCreateKeyEx(HKEY_LOCAL_MACHINE,
23 lpKey,
24 0,
25 NULL,
26 REG_OPTION_NON_VOLATILE,
27 KEY_QUERY_VALUE,
28 NULL,
29 &hkey,
30 NULL) == ERROR_SUCCESS)
31 {
32 if(RegQueryValueEx(hkey,
33 _T("PagingFiles"),
34 NULL,
35 &dwType,
36 NULL,
37 &dwDataSize) == ERROR_SUCCESS)
38 {
39 pVirtMem->szPagingFiles = (LPTSTR)HeapAlloc(GetProcessHeap(),
40 0,
41 dwDataSize);
42 if (pVirtMem->szPagingFiles != NULL)
43 {
44 ZeroMemory(pVirtMem->szPagingFiles,
45 dwDataSize);
46 if(RegQueryValueEx(hkey,
47 _T("PagingFiles"),
48 NULL,
49 &dwType,
50 (PBYTE)pVirtMem->szPagingFiles,
51 &dwDataSize) == ERROR_SUCCESS)
52 {
53 bRet = TRUE;
54 }
55 }
56
57 }
58 }
59
60 if (!bRet)
61 ShowLastWin32Error(pVirtMem->hSelf);
62
63 if (hkey != NULL)
64 RegCloseKey(hkey);
65
66 return bRet;
67 }
68
69
70 static INT
71 GetPageFileSizes(LPTSTR lpPageFiles)
72 {
73 while (*lpPageFiles != _T('\0'))
74 {
75 if (*lpPageFiles == _T(' '))
76 {
77 lpPageFiles++;
78 return (INT)_ttoi(lpPageFiles);
79 }
80
81 lpPageFiles++;
82 }
83
84 return -1;
85 }
86
87
88 static VOID
89 ParseMemSettings(PVIRTMEM pVirtMem)
90 {
91 TCHAR szDrives[1024]; // all drives
92 LPTSTR DrivePtr = szDrives;
93 TCHAR szDrive[MAX_PATH]; // single drive
94 TCHAR szVolume[MAX_PATH];
95 INT InitialSize = 0;
96 INT MaxSize = 0;
97 INT DriveLen;
98 INT PgCnt = 0;
99
100 DriveLen = GetLogicalDriveStrings(1023,
101 szDrives);
102
103 while (DriveLen != 0)
104 {
105 LVITEM Item;
106 INT Len;
107
108 Len = lstrlen(DrivePtr) + 1;
109 DriveLen -= Len;
110
111 DrivePtr = _tcsupr(DrivePtr);
112
113 /* copy the 'X:' portion */
114 lstrcpyn(szDrive, DrivePtr, 3);
115
116 if(GetDriveType(DrivePtr) == DRIVE_FIXED)
117 {
118 /* does drive match the one in the registry ? */
119 if(!_tcsncmp(pVirtMem->szPagingFiles, szDrive, 2))
120 {
121 /* FIXME: we only check the first available pagefile in the reg */
122 InitialSize = GetPageFileSizes(pVirtMem->szPagingFiles);
123 MaxSize = GetPageFileSizes(pVirtMem->szPagingFiles);
124
125 pVirtMem->Pagefile[PgCnt].InitialValue = InitialSize;
126 pVirtMem->Pagefile[PgCnt].MaxValue = MaxSize;
127 pVirtMem->Pagefile[PgCnt].bUsed = TRUE;
128 lstrcpy(pVirtMem->Pagefile[PgCnt].szDrive, szDrive);
129 }
130 else
131 {
132 pVirtMem->Pagefile[PgCnt].InitialValue = 0;
133 pVirtMem->Pagefile[PgCnt].MaxValue = 0;
134 pVirtMem->Pagefile[PgCnt].bUsed = FALSE;
135 lstrcpy(pVirtMem->Pagefile[PgCnt].szDrive, szDrive);
136 }
137
138 /* fill out the listview */
139 ZeroMemory(&Item, sizeof(Item));
140 Item.mask = LVIF_TEXT;
141 Item.iItem = ListView_GetItemCount(pVirtMem->hListView);
142 Item.pszText = szDrive;
143 (void)ListView_InsertItem(pVirtMem->hListView, &Item);
144
145 /* set a volume label if there is one */
146 if (GetVolumeInformation(DrivePtr,
147 szVolume,
148 255,
149 NULL,
150 NULL,
151 NULL,
152 NULL,
153 0))
154 {
155 if (szVolume[0] != _T('\0'))
156 {
157 TCHAR szVol[MAX_PATH + 2];
158
159 _stprintf(szVol, _T("[%s]"), szVolume);
160
161 Item.iSubItem = 1;
162 Item.pszText = szVol;
163 (void)ListView_InsertItem(pVirtMem->hListView, &Item);
164 }
165 }
166
167 if ((InitialSize != 0) || (MaxSize != 0))
168 {
169 TCHAR szSize[64];
170
171 _stprintf(szSize, _T("%i - %i"), InitialSize, MaxSize);
172
173 Item.iSubItem = 2;
174 Item.pszText = szSize;
175 (void)ListView_InsertItem(pVirtMem->hListView, &Item);
176 }
177
178 PgCnt++;
179 }
180
181 DrivePtr += Len;
182 }
183
184 pVirtMem->Count = PgCnt;
185 }
186
187
188 static VOID
189 WritePageFileSettings(PVIRTMEM pVirtMem)
190 {
191 HKEY hk = NULL;
192 TCHAR szPagingFiles[2048];
193 INT i;
194 INT nPos = 0;
195 BOOL bErr = TRUE;
196
197 for(i = 0; i < pVirtMem->Count; ++i)
198 {
199 if(pVirtMem->Pagefile[i].bUsed)
200 {
201 TCHAR szText[256];
202
203 _stprintf(szText, _T("%s\\pagefile.sys %i %i"),
204 pVirtMem->Pagefile[i].szDrive,
205 pVirtMem->Pagefile[i].InitialValue,
206 pVirtMem->Pagefile[i].MaxValue);
207
208 /* Add it to our overall registry string */
209 lstrcat(szPagingFiles + nPos, szText);
210
211 /* Record the position where the next string will start */
212 nPos += (INT)lstrlen(szText) + 1;
213
214 /* add another NULL for REG_MULTI_SZ */
215 szPagingFiles[nPos] = _T('\0');
216 nPos++;
217 }
218 }
219
220 if(RegCreateKeyEx(HKEY_LOCAL_MACHINE,
221 lpKey,
222 0,
223 NULL,
224 REG_OPTION_NON_VOLATILE,
225 KEY_WRITE,
226 NULL,
227 &hk,
228 NULL) == ERROR_SUCCESS)
229 {
230 if (RegSetValueEx(hk,
231 _T("PagingFiles"),
232 0,
233 REG_MULTI_SZ,
234 (LPBYTE) szPagingFiles,
235 (DWORD) nPos * sizeof(TCHAR)))
236 {
237 bErr = FALSE;
238 }
239
240 RegCloseKey(hk);
241 }
242
243 if (bErr)
244 ShowLastWin32Error(pVirtMem->hSelf);
245 }
246
247
248 static VOID
249 SetListViewColumns(HWND hwndListView)
250 {
251 RECT rect;
252 LV_COLUMN lvc;
253
254 GetClientRect(hwndListView, &rect);
255
256 (void)ListView_SetExtendedListViewStyle(hwndListView,
257 LVS_EX_FULLROWSELECT);
258
259 ZeroMemory(&lvc, sizeof(lvc));
260 lvc.mask = LVCF_SUBITEM | LVCF_WIDTH | LVCF_FMT;
261 lvc.fmt = LVCFMT_LEFT;
262
263 lvc.cx = (INT)((rect.right - rect.left) * 0.1);
264 lvc.iSubItem = 0;
265 (void)ListView_InsertColumn(hwndListView, 0, &lvc);
266
267 lvc.cx = (INT)((rect.right - rect.left) * 0.3);
268 lvc.iSubItem = 1;
269 (void)ListView_InsertColumn(hwndListView, 1, &lvc);
270
271 lvc.cx = (INT)((rect.right - rect.left) * 0.6);
272 lvc.iSubItem = 2;
273 (void)ListView_InsertColumn(hwndListView, 2, &lvc);
274 }
275
276
277 static VOID
278 OnNoPagingFile(PVIRTMEM pVirtMem)
279 {
280 /* Disable the page file custom size boxes */
281 EnableWindow(GetDlgItem(pVirtMem->hSelf, IDC_INITIALSIZE), FALSE);
282 EnableWindow(GetDlgItem(pVirtMem->hSelf, IDC_MAXSIZE), FALSE);
283 }
284
285
286 static VOID
287 OnSysManSize(PVIRTMEM pVirtMem)
288 {
289 /* Disable the page file custom size boxes */
290 EnableWindow(GetDlgItem(pVirtMem->hSelf, IDC_INITIALSIZE), FALSE);
291 EnableWindow(GetDlgItem(pVirtMem->hSelf, IDC_MAXSIZE), FALSE);
292 }
293
294
295 static VOID
296 OnCustom(PVIRTMEM pVirtMem)
297 {
298 /* Enable the page file custom size boxes */
299 EnableWindow(GetDlgItem(pVirtMem->hSelf, IDC_INITIALSIZE), TRUE);
300 EnableWindow(GetDlgItem(pVirtMem->hSelf, IDC_MAXSIZE), TRUE);
301 }
302
303
304 static VOID
305 OnSet(PVIRTMEM pVirtMem)
306 {
307 INT Index;
308
309 pVirtMem->bSave = TRUE;
310
311 Index = (INT)SendDlgItemMessage(pVirtMem->hSelf,
312 IDC_PAGEFILELIST,
313 LB_GETCURSEL,
314 0,
315 0);
316
317 if(Index < pVirtMem->Count)
318 {
319 TCHAR szText[255];
320
321 /* check if custom settings are checked */
322 if(SendDlgItemMessage(pVirtMem->hSelf,
323 IDC_CUSTOM,
324 BM_GETCHECK,
325 0,
326 0) == BST_CHECKED)
327 {
328 SendDlgItemMessage(pVirtMem->hSelf,
329 IDC_INITIALSIZE,
330 WM_GETTEXT,
331 254,
332 (LPARAM)szText);
333 pVirtMem->Pagefile[Index].InitialValue = _ttoi(szText);
334
335 SendDlgItemMessage(pVirtMem->hSelf,
336 IDC_MAXSIZE,
337 WM_GETTEXT,
338 254,
339 (LPARAM)szText);
340 pVirtMem->Pagefile[Index].MaxValue = _ttoi(szText);
341 }
342 else
343 {
344 /* set sizes to 0 */
345 pVirtMem->Pagefile[Index].InitialValue = pVirtMem->Pagefile[Index].MaxValue = 0;
346
347 // check to see if this drive is used for a paging file
348 if (SendDlgItemMessage(pVirtMem->hSelf,
349 IDC_NOPAGEFILE,
350 BM_GETCHECK,
351 0,
352 0) == BST_UNCHECKED)
353 {
354 pVirtMem->Pagefile[Index].bUsed = TRUE;
355 }
356 else
357 {
358 pVirtMem->Pagefile[Index].bUsed = FALSE;
359 }
360 }
361 }
362 }
363
364
365 static BOOL
366 OnSelChange(PVIRTMEM pVirtMem,
367 LPNMLISTVIEW pnmv)
368 {
369 TCHAR szCustVals[255];
370 INT Index;
371
372 UNREFERENCED_PARAMETER(pnmv);
373
374 Index = (INT)SendDlgItemMessage(pVirtMem->hSelf,
375 IDC_PAGEFILELIST,
376 LB_GETCURSEL,
377 0,
378 0);
379
380 if(Index < pVirtMem->Count)
381 {
382
383 if(pVirtMem->Pagefile[Index].InitialValue != 0 &&
384 pVirtMem->Pagefile[Index].MaxValue != 0)
385 {
386 /* enable and fill the custom values */
387 EnableWindow(GetDlgItem(pVirtMem->hSelf, IDC_MAXSIZE), TRUE);
388 EnableWindow(GetDlgItem(pVirtMem->hSelf, IDC_INITIALSIZE), TRUE);
389
390 _itot(pVirtMem->Pagefile[Index].InitialValue , szCustVals, 10);
391 SendDlgItemMessage(pVirtMem->hSelf,
392 IDC_INITIALSIZE,
393 WM_SETTEXT,
394 0,
395 (LPARAM)szCustVals);
396
397 _itot(pVirtMem->Pagefile[Index].MaxValue, szCustVals, 10);
398 SendDlgItemMessage(pVirtMem->hSelf,
399 IDC_MAXSIZE,
400 WM_SETTEXT,
401 0,
402 (LPARAM)szCustVals);
403
404 SendDlgItemMessage(pVirtMem->hSelf,
405 IDC_CUSTOM,
406 BM_SETCHECK,
407 1,
408 0);
409 }
410 else
411 {
412 /* It's not a custom value */
413 EnableWindow(GetDlgItem(pVirtMem->hSelf, IDC_MAXSIZE), FALSE);
414 EnableWindow(GetDlgItem(pVirtMem->hSelf, IDC_INITIALSIZE), FALSE);
415
416 /* is it system managed */
417 if(pVirtMem->Pagefile[Index].bUsed)
418 {
419 SendDlgItemMessage(pVirtMem->hSelf,
420 IDC_SYSMANSIZE,
421 BM_SETCHECK,
422 1,
423 0);
424 }
425 else
426 {
427 SendDlgItemMessage(pVirtMem->hSelf,
428 IDC_NOPAGEFILE,
429 BM_SETCHECK,
430 1,
431 0);
432 }
433 }
434 }
435
436 return TRUE;
437 }
438
439
440 static VOID
441 OnOk(PVIRTMEM pVirtMem)
442 {
443 if(pVirtMem->bSave == TRUE)
444 {
445 WritePageFileSettings(pVirtMem);
446 }
447
448 if (pVirtMem->szPagingFiles)
449 HeapFree(GetProcessHeap(),
450 0,
451 pVirtMem->szPagingFiles);
452
453 HeapFree(GetProcessHeap(),
454 0,
455 pVirtMem);
456 }
457
458
459 static VOID
460 OnCancel(PVIRTMEM pVirtMem)
461 {
462 if (pVirtMem->szPagingFiles)
463 HeapFree(GetProcessHeap(),
464 0,
465 pVirtMem->szPagingFiles);
466
467 HeapFree(GetProcessHeap(),
468 0,
469 pVirtMem);
470 }
471
472
473 static PVIRTMEM
474 OnInitDialog(HWND hwnd)
475 {
476 PVIRTMEM pVirtMem = (PVIRTMEM)HeapAlloc(GetProcessHeap(),
477 HEAP_ZERO_MEMORY,
478 sizeof(VIRTMEM));
479 if (pVirtMem == NULL)
480 {
481 EndDialog(hwnd, 0);
482 }
483
484 pVirtMem->hSelf = hwnd;
485 pVirtMem->hListView = GetDlgItem(hwnd, IDC_PAGEFILELIST);
486 pVirtMem->bSave = FALSE;
487
488 SetListViewColumns(pVirtMem->hListView);
489
490 /* Load the pagefile systems from the reg */
491 if (ReadPageFileSettings(pVirtMem))
492 {
493 /* Parse our settings and set up dialog */
494 ParseMemSettings(pVirtMem);
495 }
496
497 return pVirtMem;
498 }
499
500
501 INT_PTR CALLBACK
502 VirtMemDlgProc(HWND hwndDlg,
503 UINT uMsg,
504 WPARAM wParam,
505 LPARAM lParam)
506 {
507 /* there can only be one instance of this dialog */
508 static PVIRTMEM pVirtMem = NULL;
509
510 UNREFERENCED_PARAMETER(lParam);
511
512 switch (uMsg)
513 {
514 case WM_INITDIALOG:
515 pVirtMem = OnInitDialog(hwndDlg);
516 break;
517
518 case WM_COMMAND:
519 {
520 switch (LOWORD(wParam))
521 {
522 case IDCANCEL:
523 OnCancel(pVirtMem);
524 EndDialog(hwndDlg, 0);
525 return TRUE;
526
527 case IDOK:
528 OnOk(pVirtMem);
529 EndDialog(hwndDlg, 0);
530 return TRUE;
531
532 case IDC_NOPAGEFILE:
533 OnNoPagingFile(pVirtMem);
534 return TRUE;
535
536 case IDC_SYSMANSIZE:
537 OnSysManSize(pVirtMem);
538 return TRUE;
539
540 case IDC_CUSTOM:
541 OnCustom(pVirtMem);
542 return TRUE;
543
544 case IDC_SET:
545 OnSet(pVirtMem);
546 return TRUE;
547 }
548 }
549 break;
550
551 case WM_NOTIFY:
552 {
553 LPNMHDR pnmhdr = (LPNMHDR)lParam;
554
555 switch (pnmhdr->code)
556 {
557 case LVN_ITEMCHANGED:
558 {
559 LPNMLISTVIEW pnmv = (LPNMLISTVIEW) lParam;
560
561 OnSelChange(pVirtMem, pnmv);
562
563 }
564 }
565 }
566 break;
567 }
568
569 return FALSE;
570 }