Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1691 lines
53 KiB

  1. // Copyright (c) 1997-1999 Microsoft Corporation
  2. #include "precomp.h"
  3. #ifdef EXT_DEBUG
  4. #undef THIS_FILE
  5. static char THIS_FILE[] = __FILE__;
  6. #endif
  7. // Application specific
  8. #include "sysdm.h"
  9. #include "VirtualMemDlg.h"
  10. #include "..\common\util.h"
  11. #include <windowsx.h>
  12. #include "helpid.h"
  13. #include "shlwapi.h"
  14. #include "common.h"
  15. #define RET_ERROR (-1)
  16. #define RET_NO_CHANGE 0x00
  17. #define RET_VIRTUAL_CHANGE 0x01
  18. #define RET_RECOVER_CHANGE 0x02
  19. #define RET_CHANGE_NO_REBOOT 0x04
  20. #define RET_CONTINUE 0x08
  21. #define RET_BREAK 0x10
  22. #define RET_VIRT_AND_RECOVER (RET_VIRTUAL_CHANGE | RET_RECOVER_CHANGE)
  23. //==========================================================================
  24. // Local Definitions
  25. //==========================================================================
  26. #define MAX_SIZE_LEN 8 // Max chars in the Swap File Size edit.
  27. #define MAX_DRIVES 26 // Max number of drives.
  28. #define MIN_SWAPSIZE 2 // Min swap file size (see note below).
  29. #define MIN_FREESPACE 5 // Must have 5 meg free after swap file
  30. #define MIN_SUGGEST 22 // Always suggest at least 22 meg
  31. #define ONE_MEG 1048576
  32. //New consts for Win Server 2003
  33. #define MAX_SWAPSIZE_X86 (4 * 1024) // 4 Gb (number stored in megabytes)
  34. #define MAX_SWAPSIZE_X86_PAE (16 * 1024 * 1024) // 16 Tb
  35. #define MAX_SWAPSIZE_IA64 (32 * 1024 * 1024) // 32 Tb
  36. #define MAX_SWAPSIZE_AMD64 (16 * 1024 * 1024) // 16 Tb
  37. #define MIN_FREESPACE_STR _T("5") // equal their manifests.
  38. #define TABSTOP_VOL 22
  39. #define TABSTOP_SIZE 122
  40. TCHAR gszPageFileSettings[] = _T("Win32_PageFileSetting");
  41. TCHAR gszPageFileUsage[] = _T("Win32_PageFileUsage");
  42. TCHAR gszLogicalFile[] = _T("CIM_LogicalFile");
  43. TCHAR gszAllocatedBaseSize[] = _T("AllocatedBaseSize");
  44. TCHAR gszFileSize[] = _T("FileSize");
  45. TCHAR gszInitialSize[] = _T("InitialSize");
  46. TCHAR gszMaximumSize[] = _T("MaximumSize");
  47. TCHAR gszName[] = _T("Name");
  48. TCHAR gszPFNameFormat[] = _T("%s\\\\pagefile.sys");
  49. // My privilege 'handle' structure
  50. typedef struct
  51. {
  52. HANDLE hTok;
  53. TOKEN_PRIVILEGES tp;
  54. } PRIVDAT, *PPRIVDAT;
  55. DWORD aVirtualMemHelpIds[] = {
  56. IDD_VM_VOLUMES, -1,
  57. IDD_VM_DRIVE_HDR, (IDH_DLG_VIRTUALMEM + 0),
  58. IDD_VM_PF_SIZE_LABEL, (IDH_DLG_VIRTUALMEM + 1),
  59. IDD_VM_DRIVE_LABEL, (IDH_DLG_VIRTUALMEM + 2),
  60. IDD_VM_SF_DRIVE, (IDH_DLG_VIRTUALMEM + 2),
  61. IDD_VM_SPACE_LABEL, (IDH_DLG_VIRTUALMEM + 3),
  62. IDD_VM_SF_SPACE, (IDH_DLG_VIRTUALMEM + 3),
  63. IDD_VM_ST_INITSIZE, (IDH_DLG_VIRTUALMEM + 4),
  64. IDD_VM_SF_SIZE, (IDH_DLG_VIRTUALMEM + 4),
  65. IDD_VM_ST_MAXSIZE, (IDH_DLG_VIRTUALMEM + 5),
  66. IDD_VM_SF_SIZEMAX, (IDH_DLG_VIRTUALMEM + 5),
  67. IDD_VM_SF_SET, (IDH_DLG_VIRTUALMEM + 6),
  68. IDD_VM_MIN_LABEL, (IDH_DLG_VIRTUALMEM + 7),
  69. IDD_VM_MIN, (IDH_DLG_VIRTUALMEM + 7),
  70. IDD_VM_RECOMMEND_LABEL, (IDH_DLG_VIRTUALMEM + 8),
  71. IDD_VM_RECOMMEND, (IDH_DLG_VIRTUALMEM + 8),
  72. IDD_VM_ALLOCD_LABEL, (IDH_DLG_VIRTUALMEM + 9),
  73. IDD_VM_ALLOCD, (IDH_DLG_VIRTUALMEM + 9),
  74. IDD_VM_CUSTOMSIZE_RADIO,(IDH_DLG_VIRTUALMEM + 12), //IDH_PERFOPT_ADVTAB_VIRTUALMEM_CUSTOM in sysdm.h
  75. IDD_VM_RAMBASED_RADIO, (IDH_DLG_VIRTUALMEM + 13), //IDH_PERFOPT_ADVTAB_VIRTUALMEM_SYSMANAGED in sysdm.h
  76. IDD_VM_NOPAGING_RADIO, (IDH_DLG_VIRTUALMEM + 14), //IDH_PERFOPT_ADVTAB_VIRTUALMEM_NOFILE in sysdm.h
  77. 0,0
  78. };
  79. //==========================================================================
  80. // Typedefs and Structs
  81. //==========================================================================
  82. // registry info for a page file (but not yet formatted).
  83. //Note: since this structure gets passed to FormatMessage, all fields must
  84. //be 4 bytes wide.
  85. typedef struct
  86. {
  87. LPTSTR pszName;
  88. DWORD nMin;
  89. DWORD nMax;
  90. DWORD chNull;
  91. } PAGEFILDESC;
  92. //==========================================================================
  93. // Global Data Declarations
  94. //==========================================================================
  95. //TCHAR m_szSysHelp[] = TEXT("sysdm.hlp");
  96. //TCHAR g_szSysDir[ MAX_PATH ];
  97. //UINT g_wHelpMessage;
  98. //==========================================================================
  99. // Local Data Declarations
  100. //==========================================================================
  101. // Other VM Vars
  102. BOOL gfCoreDumpChanged;
  103. DWORD cmTotalVM;
  104. //==========================================================================
  105. // Local Function Prototypes
  106. //==========================================================================
  107. HRESULT QueryInstanceProperties(
  108. const TCHAR * pszClass,
  109. const TCHAR * pszRequestedProperties,
  110. const TCHAR * pszKeyPropertyName,
  111. const TCHAR * pszKeyPropertyValue,
  112. CWbemServices &Services,
  113. IWbemClassObject ** ppcoInst);
  114. //--------------------------------------------------------------
  115. INT_PTR CALLBACK StaticVirtDlgProc(HWND hwndDlg, UINT message,
  116. WPARAM wParam, LPARAM lParam)
  117. {
  118. // if this is the initDlg msg...
  119. if(message == WM_INITDIALOG)
  120. {
  121. // transfer the 'this' ptr to the extraBytes.
  122. SetWindowLongPtr(hwndDlg, DWLP_USER, lParam);
  123. }
  124. // DWL_USER is the 'this' ptr.
  125. VirtualMemDlg *me = (VirtualMemDlg *)GetWindowLongPtr(hwndDlg, DWLP_USER);
  126. if(me != NULL)
  127. {
  128. // call into the DlgProc() that has some context.
  129. return me->DlgProc(hwndDlg, message, wParam, lParam);
  130. }
  131. else
  132. {
  133. return FALSE;
  134. }
  135. }
  136. //--------------------------------------------------------------
  137. VirtualMemDlg::VirtualMemDlg(WbemServiceThread *serviceThread)
  138. : WBEMPageHelper(serviceThread)
  139. {
  140. IWbemClassObject *pInst = NULL;
  141. // this is initialized properly in Init()
  142. m_VMWriteAccess = FALSE;
  143. m_pgEnumSettings = NULL;
  144. m_pgEnumUsage = NULL;
  145. m_cxLBExtent = 0;
  146. if((pInst = FirstInstanceOf("Win32_LogicalMemoryConfiguration")) != NULL)
  147. {
  148. m_memory = pInst;
  149. }
  150. if((pInst = FirstInstanceOf("Win32_Registry")) != NULL)
  151. {
  152. m_registry = pInst;
  153. }
  154. if((pInst = FirstInstanceOf("Win32_OSRecoveryConfiguration")) != NULL)
  155. {
  156. m_recovery = pInst;
  157. }
  158. }
  159. //--------------------------------------------------------------
  160. VirtualMemDlg::~VirtualMemDlg()
  161. {
  162. if(m_pgEnumSettings != NULL)
  163. {
  164. m_pgEnumSettings->Release();
  165. m_pgEnumSettings = NULL;
  166. }
  167. if(m_pgEnumUsage != NULL)
  168. {
  169. m_pgEnumUsage->Release();
  170. m_pgEnumUsage = NULL;
  171. }
  172. }
  173. //--------------------------------------------------------------
  174. int VirtualMemDlg::DoModal(HWND hDlg)
  175. {
  176. return (int) DialogBoxParam(HINST_THISDLL,
  177. (LPTSTR) MAKEINTRESOURCE(DLG_VIRTUALMEM),
  178. hDlg,
  179. StaticVirtDlgProc,
  180. (LPARAM)this);
  181. }
  182. //--------------------------------------------------------------
  183. int TranslateDlgItemInt( HWND hDlg, int id )
  184. {
  185. /*
  186. * We can't just call GetDlgItemInt because the
  187. * string we are trying to translate looks like:
  188. * nnn (MB), and the '(MB)' would break GetDlgInt.
  189. */
  190. TCHAR szBuffer[256] = {0};
  191. int i = 0;
  192. if (GetDlgItemText(hDlg, id, szBuffer,
  193. sizeof(szBuffer) / sizeof(*szBuffer)))
  194. {
  195. _stscanf(szBuffer, _T("%d"), &i);
  196. }
  197. return i;
  198. }
  199. //----------------------------------------------------
  200. bool VirtualMemDlg::DlgProc(HWND hDlg,
  201. UINT message,
  202. WPARAM wParam,
  203. LPARAM lParam)
  204. {
  205. static int fEdtCtlHasFocus = 0;
  206. m_hDlg = hDlg;
  207. switch (message)
  208. {
  209. case WM_INITDIALOG:
  210. Init(hDlg);
  211. return TRUE;
  212. case WM_COMMAND:
  213. switch (LOWORD(wParam))
  214. {
  215. case IDD_VM_VOLUMES:
  216. // Make edit control reflect the listbox selection.
  217. if (HIWORD(wParam) == LBN_SELCHANGE)
  218. SelChange(hDlg);
  219. break;
  220. case IDD_VM_SF_SET:
  221. if (SetNewSize(hDlg))
  222. {
  223. ::EnableWindow(::GetDlgItem(hDlg, IDD_VM_SF_SET), FALSE);
  224. SetDefButton(hDlg, IDOK);
  225. }
  226. break;
  227. case IDOK:
  228. {
  229. int iRet = UpdateWBEM();
  230. // iRet |= PromptForReboot(hDlg);
  231. if (iRet & RET_CHANGE_NO_REBOOT)
  232. {
  233. // We created a pagefile, turn off temp page file flag
  234. DWORD dwRegData;
  235. dwRegData = 0;
  236. }
  237. else
  238. {
  239. // reboot required, warn user & set global flag
  240. MsgBoxParam(m_hDlg, IDS_MUST_REBOOT, IDS_SYS_CHANGE_CAPTION, MB_OK | MB_ICONINFORMATION, NULL, NULL);
  241. g_fRebootRequired = true;
  242. }
  243. if (gfCoreDumpChanged)
  244. iRet |= RET_RECOVER_CHANGE;
  245. EndDialog(hDlg, iRet );
  246. HourGlass(FALSE);
  247. break;
  248. }
  249. case IDCANCEL:
  250. // get rid of changes and restore original values.
  251. EndDialog(hDlg, RET_NO_CHANGE);
  252. HourGlass(FALSE);
  253. break;
  254. case IDD_HELP:
  255. break;
  256. case IDD_VM_SF_SIZE:
  257. case IDD_VM_SF_SIZEMAX:
  258. switch(HIWORD(wParam))
  259. {
  260. case EN_CHANGE:
  261. if ((fEdtCtlHasFocus != 0) && m_VMWriteAccess)
  262. {
  263. ::EnableWindow(::GetDlgItem(hDlg, IDD_VM_SF_SET), TRUE);
  264. SetDefButton( hDlg, IDD_VM_SF_SET);
  265. }
  266. break;
  267. case EN_SETFOCUS:
  268. fEdtCtlHasFocus++;
  269. break;
  270. case EN_KILLFOCUS:
  271. fEdtCtlHasFocus--;
  272. break;
  273. }
  274. break;
  275. case IDD_VM_NOPAGING_RADIO:
  276. case IDD_VM_RAMBASED_RADIO:
  277. if( HIWORD(wParam) == BN_CLICKED )
  278. {
  279. EnableWindow( GetDlgItem( hDlg, IDD_VM_SF_SIZE ), FALSE );
  280. EnableWindow( GetDlgItem( hDlg, IDD_VM_SF_SIZEMAX ), FALSE );
  281. if (m_VMWriteAccess)
  282. {
  283. ::EnableWindow(::GetDlgItem(hDlg, IDD_VM_SF_SET), TRUE);
  284. SetDefButton( hDlg, IDD_VM_SF_SET);
  285. }
  286. }
  287. break;
  288. case IDD_VM_CUSTOMSIZE_RADIO:
  289. if( HIWORD(wParam) == BN_CLICKED )
  290. {
  291. EnableWindow( GetDlgItem( hDlg, IDD_VM_SF_SIZE ), TRUE );
  292. EnableWindow( GetDlgItem( hDlg, IDD_VM_SF_SIZEMAX ), TRUE );
  293. if (m_VMWriteAccess)
  294. {
  295. ::EnableWindow(::GetDlgItem(hDlg, IDD_VM_SF_SET), TRUE);
  296. SetDefButton( hDlg, IDD_VM_SF_SET);
  297. }
  298. }
  299. break;
  300. default:
  301. break;
  302. }
  303. break;
  304. case WM_DESTROY:
  305. {
  306. PAGING_FILE *pgVal = NULL;
  307. HWND lbHWND = GetDlgItem(m_hDlg, IDD_VM_VOLUMES);
  308. int last = ListBox_GetCount(lbHWND);
  309. // zero-based loop.
  310. for(int x = 0; x < last; x++)
  311. {
  312. pgVal = (PAGING_FILE *)ListBox_GetItemData(lbHWND, x);
  313. delete pgVal;
  314. }
  315. }
  316. break;
  317. case WM_HELP: // F1
  318. ::WinHelp((HWND)((LPHELPINFO)lParam)->hItemHandle,
  319. L"sysdm.hlp",
  320. HELP_WM_HELP,
  321. (ULONG_PTR)(LPSTR)aVirtualMemHelpIds);
  322. break;
  323. case WM_CONTEXTMENU: // right mouse click
  324. WinHelp((HWND) wParam, HELP_FILE, HELP_CONTEXTMENU,
  325. (ULONG_PTR)(LPSTR) aVirtualMemHelpIds);
  326. break;
  327. default:
  328. return FALSE;
  329. break;
  330. }
  331. return TRUE;
  332. }
  333. //---------------------------------------------------------------
  334. TCHAR szCrashControl[] = TEXT("System\\CurrentControlSet\\Control\\CrashControl");
  335. TCHAR szMemMan[] = TEXT("System\\CurrentControlSet\\Control\\Session Manager\\Memory Management");
  336. TCHAR szRegSizeLim[] = TEXT("System\\CurrentControlSet\\Control");
  337. BOOL VirtualMemDlg::Init(HWND hDlg)
  338. {
  339. INT i;
  340. HWND hwndLB;
  341. INT aTabs[2];
  342. RECT rc;
  343. DWORD dwTotalPhys = 0;
  344. HourGlass(TRUE);
  345. // g_wHelpMessage = RegisterWindowMessage( TEXT( "ShellHelp" ) );
  346. if(m_pgEnumUsage == NULL)
  347. {
  348. // Error - cannot even get list of paging files from WBEM
  349. MsgBoxParam(hDlg, SYSTEM+11, IDS_TITLE, MB_ICONEXCLAMATION);
  350. EndDialog(hDlg, RET_NO_CHANGE);
  351. HourGlass(FALSE);
  352. return FALSE;
  353. }
  354. BOOL vcVirtRO = TRUE, vcCoreRO = TRUE;
  355. RemoteRegWriteable(szCrashControl, vcCoreRO);
  356. RemoteRegWriteable(szMemMan, vcVirtRO);
  357. // EXCUSE: I wanted to preserve as much of the original logic but its
  358. // writability was reversed from my util so I do this wierd thing to
  359. // flip it back.
  360. vcCoreRO = !vcCoreRO;
  361. vcVirtRO = !vcVirtRO;
  362. // To change Virtual Memory size or Crash control, we need access
  363. // to both the CrashCtl key and the PagingFiles value in the MemMgr key
  364. if(vcVirtRO || vcCoreRO)
  365. {
  366. // Disable some fields, because they only have Read access.
  367. EnableWindow(GetDlgItem(hDlg, IDD_VM_CUSTOMSIZE_RADIO), FALSE);
  368. EnableWindow(GetDlgItem(hDlg, IDD_VM_RAMBASED_RADIO), FALSE);
  369. EnableWindow(GetDlgItem(hDlg, IDD_VM_NOPAGING_RADIO), FALSE);
  370. EnableWindow(GetDlgItem(hDlg, IDD_VM_SF_SIZE), FALSE);
  371. EnableWindow(GetDlgItem(hDlg, IDD_VM_SF_SIZEMAX), FALSE);
  372. EnableWindow(GetDlgItem(hDlg, IDD_VM_ST_INITSIZE), FALSE);
  373. EnableWindow(GetDlgItem(hDlg, IDD_VM_ST_MAXSIZE), FALSE);
  374. EnableWindow(GetDlgItem(hDlg, IDD_VM_SF_SET), FALSE);
  375. m_VMWriteAccess = FALSE;
  376. }
  377. else
  378. m_VMWriteAccess = TRUE;
  379. hwndLB = GetDlgItem(hDlg, IDD_VM_VOLUMES);
  380. aTabs[0] = TABSTOP_VOL;
  381. aTabs[1] = TABSTOP_SIZE;
  382. SendMessage(hwndLB, LB_SETTABSTOPS, 2, (LPARAM)&aTabs);
  383. // Since SetGenLBWidth only counts tabs as one character, we must compute
  384. // the maximum extra space that the tab characters will expand to and
  385. // arbitrarily tack it onto the end of the string width.
  386. //
  387. // cxExtra = 1st Tab width + 1 default tab width (8 chrs) - strlen("d:\t\t");
  388. //
  389. // (I know the docs for LB_SETTABSTOPS says that a default tab == 2 dlg
  390. // units, but I have read the code, and it is really 8 chars)
  391. rc.top = rc.left = 0;
  392. rc.bottom = 8;
  393. rc.right = TABSTOP_VOL + (4 * 8) - (4 * 4);
  394. MapDialogRect( hDlg, &rc );
  395. m_cxExtra = rc.right - rc.left;
  396. // List all drives
  397. LoadVolumeList();
  398. SendDlgItemMessage(hDlg, IDD_VM_SF_SIZE, EM_LIMITTEXT, MAX_SIZE_LEN, 0L);
  399. SendDlgItemMessage(hDlg, IDD_VM_SF_SIZEMAX, EM_LIMITTEXT, MAX_SIZE_LEN, 0L);
  400. // Get the total physical memory in the machine.
  401. dwTotalPhys = m_memory.GetLong("TotalPhysicalMemory");
  402. SetDlgItemMB(hDlg, IDD_VM_MIN, MIN_SWAPSIZE);
  403. // convert to KBs for the calculation.
  404. dwTotalPhys /= 1024;
  405. dwTotalPhys *= 3;
  406. dwTotalPhys >>=1; // x*3/2 == 1.5*x more or less.
  407. i = (DWORD)dwTotalPhys;
  408. SetDlgItemMB(hDlg, IDD_VM_RECOMMEND, max(i, MIN_SUGGEST));
  409. // Select the first drive in the listbox.
  410. SendDlgItemMessage(hDlg, IDD_VM_VOLUMES, LB_SETCURSEL, 0, 0L);
  411. SelChange(hDlg);
  412. //since the data is already loaded into the listbox, we use this lightweight
  413. // way of calculating.
  414. SetDlgItemMB(hDlg, IDD_VM_ALLOCD, RecomputeAllocated());
  415. // Show RegQuota
  416. cmTotalVM = ComputeTotalMax();
  417. HourGlass(FALSE);
  418. return TRUE;
  419. }
  420. //-------------------------------------------------------------------
  421. int VirtualMemDlg::ComputeTotalMax( void )
  422. {
  423. INT nTotalAllocated = 0;
  424. INT i;
  425. HWND VolHWND = GetDlgItem(m_hDlg, IDD_VM_VOLUMES);
  426. int cItems = ListBox_GetCount(VolHWND);
  427. for(i = 0; i < cItems; i++)
  428. {
  429. PAGING_FILE *pgVal = (PAGING_FILE *)ListBox_GetItemData(VolHWND, i);
  430. nTotalAllocated += pgVal->nMaxFileSize;
  431. }
  432. return nTotalAllocated;
  433. }
  434. //--------------------------------------------------------
  435. void VirtualMemDlg::BuildLBLine(LPTSTR pszBuf,
  436. const PAGING_FILE *pgVal)
  437. {
  438. //
  439. // Build a string according to the following format:
  440. //
  441. // C: [ Vol_label ] %d - %d
  442. //
  443. TCHAR szVolume[MAX_PATH] = {0};
  444. TCHAR szTemp[MAX_PATH] = {0};
  445. if (pgVal->name != NULL)
  446. {
  447. lstrcpy(pszBuf, pgVal->name);
  448. }
  449. else
  450. {
  451. *pszBuf = _T('\0');
  452. }
  453. lstrcat(pszBuf, _T("\t"));
  454. if (pgVal->volume != NULL && *pgVal->volume)
  455. {
  456. lstrcat(pszBuf, _T("["));
  457. lstrcat(pszBuf, pgVal->volume);
  458. lstrcat(pszBuf, _T("]"));
  459. }
  460. if (!pgVal->fRamBasedPagefile && pgVal->nMinFileSize)
  461. {
  462. //
  463. // Drive has a page file with specific settings.
  464. //
  465. wsprintf(szTemp, _T("\t%d - %d"), pgVal->nMinFileSize,
  466. pgVal->nMaxFileSize);
  467. lstrcat(pszBuf, szTemp);
  468. }
  469. else
  470. {
  471. //
  472. // Either the page file size is derived from the RAM size or the
  473. // drive doesn't have a page file.
  474. //
  475. // In either case, do nothing else.
  476. //
  477. }
  478. }
  479. //--------------------------------------------------------------
  480. void VirtualMemDlg::SelChange(HWND hDlg)
  481. {
  482. TCHAR szTemp[MAX_PATH] = {0};
  483. INT iSel;
  484. INT nCrtRadioButtonId;
  485. PAGING_FILE *iDrive;
  486. BOOL fEditsEnabled;
  487. // where are we pointing now.
  488. if ((iSel = (INT)SendDlgItemMessage(hDlg, IDD_VM_VOLUMES,
  489. LB_GETCURSEL, 0, 0)) == LB_ERR)
  490. {
  491. return;
  492. }
  493. // get its data.
  494. iDrive = (PAGING_FILE *)SendDlgItemMessage(hDlg, IDD_VM_VOLUMES,
  495. LB_GETITEMDATA, iSel, 0);
  496. TCHAR volBuf[40] = {0};
  497. if(_tcslen(iDrive->volume) != 0)
  498. {
  499. _tcscpy(volBuf, _T("["));
  500. _tcscat(volBuf, iDrive->volume);
  501. _tcscat(volBuf, _T("]"));
  502. }
  503. wsprintf(szTemp, _T("%s %s"),
  504. iDrive->name,
  505. volBuf);
  506. //LATER: should we also put up total drive size as well as free space?
  507. SetDlgItemText(hDlg, IDD_VM_SF_DRIVE, szTemp);
  508. if ( iDrive->fRamBasedPagefile )
  509. {
  510. //
  511. // Paging file size based on RAM size
  512. //
  513. nCrtRadioButtonId = IDD_VM_RAMBASED_RADIO;
  514. fEditsEnabled = FALSE;
  515. }
  516. else
  517. {
  518. if ( iDrive->nMinFileSize )
  519. {
  520. //
  521. // Custom size paging file
  522. //
  523. nCrtRadioButtonId = IDD_VM_CUSTOMSIZE_RADIO;
  524. SetDlgItemInt(hDlg, IDD_VM_SF_SIZE, iDrive->nMinFileSize,
  525. FALSE);
  526. SetDlgItemInt(hDlg, IDD_VM_SF_SIZEMAX, iDrive->nMaxFileSize,
  527. FALSE);
  528. fEditsEnabled = TRUE;
  529. }
  530. else
  531. {
  532. //
  533. // No paging file
  534. //
  535. nCrtRadioButtonId = IDD_VM_NOPAGING_RADIO;
  536. SetDlgItemText(hDlg, IDD_VM_SF_SIZE, TEXT(""));
  537. SetDlgItemText(hDlg, IDD_VM_SF_SIZEMAX, TEXT(""));
  538. fEditsEnabled = FALSE;
  539. //
  540. // If the allocated size is zero, then this is a volume which
  541. // had a page file previously but does not now. In this case,
  542. // there is no settings/usage information in the repository.
  543. // Since the pagefile.sys file size is considered free space
  544. // in the free space size computation, then it needs to be
  545. // obtained here.
  546. //
  547. if ( iDrive->nAllocatedFileSize == 0 )
  548. {
  549. //
  550. // Fetch x:\pagefile.sys file size.
  551. //
  552. CWbemClassObject LogicalFile;
  553. IWbemClassObject * pcoInst;
  554. HRESULT hr;
  555. wsprintf(szTemp, gszPFNameFormat, iDrive->name);
  556. hr = QueryInstanceProperties(gszLogicalFile,
  557. gszFileSize,
  558. gszName,
  559. szTemp,
  560. m_WbemServices,
  561. &pcoInst);
  562. LogicalFile = pcoInst;
  563. if (SUCCEEDED(hr))
  564. {
  565. iDrive->nAllocatedFileSize =
  566. (LogicalFile.GetLong(gszFileSize) / ONE_MEG);
  567. }
  568. }
  569. }
  570. }
  571. //
  572. // Set 'Space Available'.
  573. //
  574. SetDlgItemMB(hDlg, IDD_VM_SF_SPACE,
  575. iDrive->freeSpace + iDrive->nAllocatedFileSize);
  576. //
  577. // Select the appropriate radio button
  578. //
  579. CheckRadioButton(
  580. hDlg,
  581. IDD_VM_CUSTOMSIZE_RADIO,
  582. IDD_VM_NOPAGING_RADIO,
  583. nCrtRadioButtonId );
  584. //
  585. // Enable/disable the min & max size edit boxes (if user has write access !)
  586. //
  587. if (m_VMWriteAccess)
  588. {
  589. EnableWindow( GetDlgItem( hDlg, IDD_VM_SF_SIZE ), fEditsEnabled );
  590. EnableWindow( GetDlgItem( hDlg, IDD_VM_SF_SIZEMAX ), fEditsEnabled );
  591. }
  592. }
  593. //--------------------------------------------------------------
  594. bool VirtualMemDlg::EnsureEnumerator(const bstr_t bstrClass)
  595. {
  596. HRESULT hr = S_OK;
  597. //
  598. // This code used to retain/cache these interface ptrs and call
  599. // CreateInstanceEnum once. But the logic was commented out for
  600. // some reason with a comment that it was expensive to cache the
  601. // interfaces, although the data member was set each time with no
  602. // call to Release!).
  603. //
  604. if (lstrcmpi(gszPageFileSettings, bstrClass) == 0)
  605. {
  606. IEnumWbemClassObject * pgEnumSettings = NULL;
  607. hr = m_WbemServices.CreateInstanceEnum(bstrClass, WBEM_FLAG_SHALLOW,
  608. &pgEnumSettings);
  609. if (SUCCEEDED(hr))
  610. {
  611. if (m_pgEnumSettings != NULL)
  612. {
  613. m_pgEnumSettings->Release();
  614. }
  615. m_pgEnumSettings = pgEnumSettings;
  616. }
  617. }
  618. else if (lstrcmpi(gszPageFileUsage, bstrClass) == 0)
  619. {
  620. IEnumWbemClassObject * pgEnumUsage = NULL;
  621. hr = m_WbemServices.CreateInstanceEnum(bstrClass, WBEM_FLAG_SHALLOW,
  622. &pgEnumUsage);
  623. if (SUCCEEDED(hr))
  624. {
  625. if (m_pgEnumUsage != NULL)
  626. {
  627. m_pgEnumUsage->Release();
  628. }
  629. m_pgEnumUsage = pgEnumUsage;
  630. }
  631. }
  632. else
  633. {
  634. // Do nothing.
  635. }
  636. return (SUCCEEDED(hr));
  637. }
  638. //--------------------------------------------------------------
  639. void VirtualMemDlg::LoadVolumeList(void)
  640. {
  641. IEnumWbemClassObject *diskEnum = NULL;
  642. IWbemClassObject *pInst = NULL;
  643. CWbemClassObject newInst;
  644. DWORD uReturned = 0;
  645. HRESULT hr = 0;
  646. bstr_t sNameProp(gszName);
  647. bstr_t sVolumeProp("VolumeName");
  648. bstr_t sFileSystemProp("FileSystem");
  649. bstr_t sDriveTypeProp("DriveType");
  650. bstr_t sFreeProp("FreeSpace");
  651. bstr_t sSizeProp("Size"), temp;
  652. long driveType;
  653. __int64 temp64 = 0;
  654. variant_t pVal;
  655. int idx;
  656. TCHAR volumeLine[100] = {0};
  657. PAGING_FILE *pgVar;
  658. HWND VolHWND = GetDlgItem(m_hDlg, IDD_VM_VOLUMES);
  659. // walk the disks.
  660. if(hr = m_WbemServices.ExecQuery(bstr_t("Select __PATH, DriveType from Win32_LogicalDisk"),
  661. 0, &diskEnum) == S_OK)
  662. {
  663. TCHAR bootLtr[2] = {0};
  664. if((pInst = FirstInstanceOf("Win32_OperatingSystem")) != NULL)
  665. {
  666. CWbemClassObject os = pInst;
  667. bstr_t temp = os.GetString(L"SystemDirectory");
  668. _tcsncpy(bootLtr, temp, 1);
  669. m_PAEEnabled = os.GetBool(L"PAEEnabled");
  670. }
  671. // get the first and only instance.
  672. while(SUCCEEDED(diskEnum->Next(-1, 1, &pInst, &uReturned)) &&
  673. (uReturned != 0))
  674. {
  675. // get the DriveType.
  676. if ((pInst->Get(sDriveTypeProp, 0L, &pVal, NULL, NULL) == S_OK))
  677. {
  678. // look at the DriveType to see if this drive can have a swapfile.
  679. driveType = pVal;
  680. if(driveType == DRIVE_FIXED)
  681. {
  682. // it can so get the expensive properties now.
  683. // NOTE: This releases pInst; cuz you EXCHANGED
  684. // it for a better one.
  685. newInst = ExchangeInstance(&pInst);
  686. // extract.
  687. pgVar = new PAGING_FILE;
  688. pgVar->name = CloneString(newInst.GetString(sNameProp));
  689. pgVar->volume = CloneString(newInst.GetString(sVolumeProp));
  690. pgVar->filesystem = CloneString(newInst.GetString(sFileSystemProp));
  691. if(bootLtr[0] == pgVar->name[0])
  692. {
  693. pgVar->bootDrive = true;
  694. }
  695. temp64 = 0;
  696. temp = newInst.GetString(sFreeProp);
  697. _stscanf(temp, _T("%I64d"), &temp64);
  698. pgVar->freeSpace = (ULONG)(temp64 / ONE_MEG);
  699. temp64 = 0;
  700. temp = newInst.GetString(sSizeProp);
  701. _stscanf(temp, _T("%I64d"), &temp64);
  702. pgVar->totalSize = (ULONG)(temp64 / ONE_MEG);
  703. // match with a Win32_PageFileSettings if possible.
  704. FindSwapfile(pgVar);
  705. // add it to the listbox.
  706. BuildLBLine(volumeLine, pgVar);
  707. idx = ListBox_AddString(VolHWND, volumeLine);
  708. int nRet = ListBox_SetItemData(VolHWND, idx, pgVar);
  709. if(nRet == LB_ERR)
  710. {
  711. MessageBox(NULL,_T("Error"),_T("Error"),MB_OK);
  712. }
  713. m_cxLBExtent = SetLBWidthEx(VolHWND, volumeLine, m_cxLBExtent, m_cxExtra);
  714. } //endif drive can have swapfile.
  715. } //endif get the cheap variable.
  716. // in case it wasn't exchanged, release it now.
  717. if(pInst)
  718. {
  719. pInst->Release();
  720. pInst = NULL;
  721. }
  722. } // endwhile Enum
  723. diskEnum->Release();
  724. } //endif CreateInstanceEnum() SUCCEEDED (one way or another :)
  725. }
  726. //---------------------------------------------------------------
  727. void VirtualMemDlg::FindSwapfile(PAGING_FILE *pgVar)
  728. {
  729. IWbemClassObject *pInst = NULL;
  730. CWbemClassObject PFSettings;
  731. CWbemClassObject PFUsage;
  732. DWORD uReturned = 0;
  733. HRESULT hr = 0;
  734. bstr_t sNameProp(gszName);
  735. bstr_t sMaxProp(gszMaximumSize);
  736. bstr_t sInitProp(gszInitialSize);
  737. bstr_t sPathProp("__PATH");
  738. bstr_t sAllocSize(gszAllocatedBaseSize);
  739. variant_t pVal, pVal1, pVal2, pVal3;
  740. bstr_t bName;
  741. // do we have one?
  742. if(EnsureEnumerator(gszPageFileSettings))
  743. {
  744. m_pgEnumSettings->Reset();
  745. // walk through the pagefiles...
  746. while((hr = m_pgEnumSettings->Next(-1, 1, &pInst,
  747. &uReturned) == S_OK) &&
  748. (uReturned != 0))
  749. {
  750. PFSettings = pInst;
  751. // trying to match the drive letter.
  752. bName = PFSettings.GetString(sNameProp);
  753. if(_wcsnicmp((wchar_t *)bName, pgVar->name, 1) == 0)
  754. {
  755. // letter matched; get some details.
  756. pgVar->nMinFileSize =
  757. pgVar->nMinFileSizePrev = PFSettings.GetLong(sInitProp);
  758. //
  759. // If the page file InitialSize property is zero, it is an
  760. // indication that the page file size is to be computed based
  761. // on RAM size.
  762. //
  763. pgVar->fRamBasedPagefile = (pgVar->nMinFileSize ?
  764. FALSE : TRUE);
  765. pgVar->nMaxFileSize =
  766. pgVar->nMaxFileSizePrev = PFSettings.GetLong(sMaxProp);
  767. pgVar->objPath = CloneString(PFSettings.GetString(sPathProp));
  768. pgVar->pszPageFile = CloneString(bName);
  769. //
  770. // Fetch the Win32_PageFileUsage.AllocatedBaseSize property.
  771. //
  772. TCHAR szTemp[sizeof(gszPFNameFormat) / sizeof(TCHAR)];
  773. wsprintf(szTemp, gszPFNameFormat, pgVar->name);
  774. IWbemClassObject * pcoInst;
  775. hr = QueryInstanceProperties(gszPageFileUsage,
  776. gszAllocatedBaseSize,
  777. gszName,
  778. szTemp,
  779. m_WbemServices,
  780. &pcoInst);
  781. PFUsage = pcoInst;
  782. if (SUCCEEDED(hr))
  783. {
  784. pgVar->nAllocatedFileSize = PFUsage.GetLong(sAllocSize);
  785. }
  786. else
  787. {
  788. pgVar->nAllocatedFileSize = 0;
  789. }
  790. // found the one and only-- cleanup early and bail out.
  791. pInst->Release();
  792. break; // while()
  793. } //endif match the drive letter.
  794. // in case that BREAK didn't jump over the endwhile()
  795. pInst->Release();
  796. } // endwhile envEnum
  797. // NOTE: The BREAK jumps here. Duplicate any cleanup from before the
  798. // endwhile.
  799. } //endif CreateInstanceEnum() SUCCEEDED one way or another :)
  800. }
  801. //--------------------------------------------------------------
  802. // this version calculates based on pre-existing wbem data.
  803. bool VirtualMemDlg::ComputeAllocated(unsigned long *value)
  804. {
  805. bool retval = false;
  806. IWbemClassObject *pgInst = NULL;
  807. DWORD uReturned = 0;
  808. bstr_t sAllocSize(gszAllocatedBaseSize);
  809. variant_t pVal, pVal1;
  810. // do we have one?
  811. if(EnsureEnumerator(gszPageFileUsage))
  812. {
  813. m_pgEnumUsage->Reset();
  814. // get the first and only instance.
  815. while(SUCCEEDED(m_pgEnumUsage->Next(-1, 1, &pgInst, &uReturned)) &&
  816. (uReturned != 0))
  817. {
  818. // get the variables.
  819. if((pgInst->Get(sAllocSize, 0L, &pVal1, NULL, NULL) == S_OK) &&
  820. (pVal1.vt == VT_I4))
  821. {
  822. *value += pVal1.ulVal;
  823. } //endif get the variable.
  824. pgInst->Release();
  825. } // endwhile envEnum
  826. retval = true;
  827. } //endif CreateInstanceEnum() SUCCEEDED (one way or another :)
  828. return retval;
  829. }
  830. //--------------------------------------------------------------
  831. // this version calculates based on the listbox.
  832. unsigned long VirtualMemDlg::RecomputeAllocated(void)
  833. {
  834. unsigned long nTotalAllocated = 0;
  835. PAGING_FILE *pgVal = NULL;
  836. HWND lbHWND = GetDlgItem(m_hDlg, IDD_VM_VOLUMES);
  837. int last = ListBox_GetCount(lbHWND);
  838. // zero-based loop.
  839. for(int x = 0; x < last; x++)
  840. {
  841. pgVal = (PAGING_FILE *)ListBox_GetItemData(lbHWND, x);
  842. if ( pgVal->fRamBasedPagefile || pgVal->nMinFileSize )
  843. {
  844. //
  845. // Add in only pagefiles in use.
  846. //
  847. nTotalAllocated += pgVal->nAllocatedFileSize;
  848. }
  849. }
  850. return nTotalAllocated;
  851. }
  852. //--------------------------------------------------------------
  853. void VirtualMemDlg::GetRecoveryFlags(bool &bWrite, bool &bLog, bool &bSend)
  854. {
  855. if((bool)m_recovery)
  856. {
  857. bWrite = m_recovery.GetBool("WriteDebugInfo");
  858. bLog = m_recovery.GetBool("WriteToSystemLog");
  859. bSend = m_recovery.GetBool("SendAdminAlert");
  860. }
  861. else
  862. {
  863. bWrite = bLog = bSend = false;
  864. }
  865. }
  866. //--------------------------------------------------------------
  867. /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!! IMPORTANT !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
  868. /* THIS FUNCTION IS A REPLICA OF THE FUNCTION in \\depot\shell\cpls\system\util.c */
  869. /* OFCOURSE WITH A BIT OF MODIFICATION FOR USING WMI */
  870. /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
  871. DWORD
  872. VirtualMemDlg::GetMaxPagefileSizeInMB(
  873. PAGING_FILE *iDrive // drive to check on
  874. )
  875. {
  876. #if defined(_AMD64_)
  877. return MAX_SWAPSIZE_AMD64;
  878. #elif defined(_X86_)
  879. if (m_PAEEnabled && !(_wcsnicmp(iDrive->filesystem, L"NTFS",4)))
  880. {
  881. return MAX_SWAPSIZE_X86_PAE;
  882. }
  883. else
  884. {
  885. return MAX_SWAPSIZE_X86;
  886. }
  887. #elif defined(_IA64_)
  888. return MAX_SWAPSIZE_IA64;
  889. #else
  890. return 0;
  891. #endif
  892. }
  893. //--------------------------------------------------------------
  894. /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!! IMPORTANT !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
  895. /* THIS FUNCTION IS A REPLICA OF THE FUNCTION in \\depot\shell\cpls\system\virtual.c */
  896. /* OFCOURSE WITH A BIT OF MODIFICATION FOR USING WMI */
  897. /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
  898. bool VirtualMemDlg::SetNewSize(HWND hDlg)
  899. {
  900. ULONG nSwapSize;
  901. ULONG nSwapSizeMax;
  902. BOOL fTranslated;
  903. INT iSel;
  904. PAGING_FILE *iDrive;
  905. TCHAR szTemp[MAX_PATH] = {0};
  906. ULONG nBootPF = 0;
  907. bool fRamBasedPagefile = FALSE;
  908. // get the item's data.
  909. if ((iSel = (INT)SendDlgItemMessage(
  910. hDlg, IDD_VM_VOLUMES, LB_GETCURSEL,0, 0)) != LB_ERR)
  911. {
  912. if ((LRESULT)(iDrive = (PAGING_FILE *)SendDlgItemMessage(hDlg, IDD_VM_VOLUMES,
  913. LB_GETITEMDATA, iSel, 0)) == LB_ERR)
  914. {
  915. return FALSE; //failure !
  916. }
  917. }
  918. // Initialize variables for crashdump.
  919. // nBootPF == crash dump size required.
  920. //
  921. bool bWrite = false, bLog = false, bSend = false;
  922. GetRecoveryFlags(bWrite, bLog, bSend);
  923. if (bWrite)
  924. {
  925. nBootPF = -1;
  926. }
  927. else if (bLog || bSend)
  928. {
  929. nBootPF = MIN_SWAPSIZE;
  930. }
  931. if (nBootPF == -1)
  932. {
  933. nBootPF = ((DWORD)m_memory.GetLong("TotalPhysicalMemory") / 1024);
  934. }
  935. if ( IsDlgButtonChecked( hDlg, IDD_VM_NOPAGING_RADIO ) == BST_CHECKED )
  936. {
  937. //
  938. // No paging file on this drive.
  939. //
  940. nSwapSize = 0;
  941. nSwapSizeMax = 0;
  942. fTranslated = TRUE;
  943. }
  944. else
  945. {
  946. if ( IsDlgButtonChecked( hDlg,
  947. IDD_VM_RAMBASED_RADIO ) == BST_CHECKED )
  948. {
  949. MEMORYSTATUSEX MemoryInfo;
  950. //
  951. // User requested a RAM based page file. We will compute a page
  952. // file size based on the RAM currently available so that we can
  953. // benefit of all the verifications done below related to disk
  954. // space available etc.
  955. //
  956. // The final page file specification written to the registry will
  957. // contain zero sizes though because this is the way we signal
  958. // that we want a RAM based page file.
  959. //
  960. ZeroMemory (&MemoryInfo, sizeof MemoryInfo);
  961. MemoryInfo.dwLength = sizeof MemoryInfo;
  962. if (GlobalMemoryStatusEx (&MemoryInfo))
  963. {
  964. fRamBasedPagefile = TRUE;
  965. //
  966. // We do not lose info because we first divide the RAM size to
  967. // 1Mb and only after that we convert to a DWORD.
  968. //
  969. nSwapSize = (DWORD)(MemoryInfo.ullTotalPhys / 0x100000) + 12;
  970. nSwapSizeMax = nSwapSize;
  971. fTranslated = TRUE;
  972. }
  973. else
  974. {
  975. nSwapSize = 0;
  976. nSwapSizeMax = 0;
  977. fTranslated = TRUE;
  978. }
  979. }
  980. else
  981. {
  982. //
  983. // User requested a custom size page file.
  984. //
  985. nSwapSize = (ULONG)GetDlgItemInt(hDlg, IDD_VM_SF_SIZE,
  986. &fTranslated, FALSE);
  987. // was it an integer?
  988. if (!fTranslated)
  989. {
  990. // need a valid integer for initial size.
  991. MsgBoxParam(hDlg, SYSTEM+37, IDS_TITLE, MB_ICONEXCLAMATION);
  992. SetFocus(GetDlgItem(hDlg, IDD_VM_SF_SIZE));
  993. return FALSE;
  994. }
  995. // was it in range > 2MB
  996. if ((nSwapSize < MIN_SWAPSIZE && nSwapSize != 0))
  997. {
  998. // initial value out of range.
  999. MsgBoxParam(hDlg, SYSTEM+13, IDS_TITLE, MB_ICONEXCLAMATION);
  1000. SetFocus(GetDlgItem(hDlg, IDD_VM_SF_SIZE));
  1001. return FALSE;
  1002. }
  1003. // deleting swapfile?
  1004. if (nSwapSize == 0)
  1005. {
  1006. nSwapSizeMax = 0;
  1007. }
  1008. else // adding/changing.
  1009. {
  1010. nSwapSizeMax = (ULONG)GetDlgItemInt(hDlg, IDD_VM_SF_SIZEMAX,
  1011. &fTranslated, FALSE);
  1012. // was it an integer?
  1013. if (!fTranslated)
  1014. {
  1015. // need an integer.
  1016. MsgBoxParam(hDlg, SYSTEM+38, IDS_TITLE,
  1017. MB_ICONEXCLAMATION);
  1018. SetFocus(GetDlgItem(hDlg, IDD_VM_SF_SIZEMAX));
  1019. return FALSE;
  1020. }
  1021. // in range?
  1022. if (nSwapSizeMax < nSwapSize || nSwapSizeMax > GetMaxPagefileSizeInMB(iDrive))
  1023. {
  1024. TCHAR strTemp[16];
  1025. MsgBoxParam(hDlg, SYSTEM+14, IDS_TITLE,
  1026. MB_ICONEXCLAMATION, _ultow(GetMaxPagefileSizeInMB(iDrive), strTemp, 10));
  1027. SetFocus(GetDlgItem(hDlg, IDD_VM_SF_SIZEMAX));
  1028. return FALSE;
  1029. }
  1030. }
  1031. }
  1032. }
  1033. // if we have integers and the listbox has a good focus...
  1034. if (fTranslated && iSel != LB_ERR)
  1035. {
  1036. // will it fit?
  1037. if (nSwapSizeMax > iDrive->totalSize)
  1038. {
  1039. // nope.
  1040. MsgBoxParam(hDlg, SYSTEM+16, IDS_TITLE,
  1041. MB_ICONEXCLAMATION, iDrive->name);
  1042. SetFocus(GetDlgItem(hDlg, IDD_VM_SF_SIZEMAX));
  1043. return FALSE;
  1044. }
  1045. //Actual FreeSpace is freespace in the disk + page file size.
  1046. ULONG freeSpace = iDrive->freeSpace + iDrive->nAllocatedFileSize;
  1047. // room to spare??
  1048. if (nSwapSize > freeSpace)
  1049. {
  1050. // nope.
  1051. MsgBoxParam(hDlg, SYSTEM+15, IDS_TITLE, MB_ICONEXCLAMATION);
  1052. SetFocus(GetDlgItem(hDlg, IDD_VM_SF_SIZE));
  1053. return FALSE;
  1054. }
  1055. // don't hog the last 5MB.
  1056. if (nSwapSize != 0 && freeSpace - nSwapSize < MIN_FREESPACE)
  1057. {
  1058. MsgBoxParam(hDlg, SYSTEM+26, IDS_TITLE, MB_ICONEXCLAMATION,
  1059. MIN_FREESPACE_STR);
  1060. SetFocus(GetDlgItem(hDlg, IDD_VM_SF_SIZE));
  1061. return FALSE;
  1062. }
  1063. // max too big, should I just use all the space anyway.
  1064. if (nSwapSizeMax > freeSpace)
  1065. {
  1066. if (MsgBoxParam(hDlg, SYSTEM+20, IDS_TITLE, MB_ICONINFORMATION |
  1067. MB_OKCANCEL, iDrive->name) == IDCANCEL)
  1068. {
  1069. SetFocus(GetDlgItem(hDlg, IDD_VM_SF_SIZEMAX));
  1070. return FALSE;
  1071. }
  1072. }
  1073. // enough room for core dumps??
  1074. if (iDrive->bootDrive && nSwapSize < nBootPF)
  1075. {
  1076. // The new boot drive page file size is less than we need for
  1077. // crash control. Inform the user.
  1078. if (MsgBoxParam(hDlg, SYSTEM+29, IDS_TITLE,
  1079. MB_ICONEXCLAMATION |MB_YESNO,
  1080. iDrive->name, _itow(nBootPF, szTemp, 10)) != IDYES)
  1081. {
  1082. SetFocus(GetDlgItem(hDlg, IDD_VM_SF_SIZE));
  1083. return FALSE;
  1084. }
  1085. }
  1086. iDrive->nMinFileSize = nSwapSize;
  1087. iDrive->nMaxFileSize = nSwapSizeMax;
  1088. iDrive->fRamBasedPagefile = fRamBasedPagefile;
  1089. BuildLBLine(szTemp, iDrive);
  1090. SendDlgItemMessage(hDlg, IDD_VM_VOLUMES, LB_DELETESTRING, iSel, 0);
  1091. SendDlgItemMessage(hDlg, IDD_VM_VOLUMES, LB_INSERTSTRING, iSel,
  1092. (LPARAM)szTemp);
  1093. SendDlgItemMessage(hDlg, IDD_VM_VOLUMES, LB_SETITEMDATA, iSel,
  1094. (LPARAM)iDrive);
  1095. SendDlgItemMessage(hDlg, IDD_VM_VOLUMES, LB_SETCURSEL, iSel, 0L);
  1096. m_cxLBExtent = SetLBWidthEx(GetDlgItem(hDlg, IDD_VM_VOLUMES),
  1097. szTemp, m_cxLBExtent, m_cxExtra);
  1098. if (!iDrive->fRamBasedPagefile && iDrive->nMinFileSize)
  1099. {
  1100. SetDlgItemInt(hDlg, IDD_VM_SF_SIZE, iDrive->nMinFileSize, FALSE);
  1101. SetDlgItemInt(hDlg, IDD_VM_SF_SIZEMAX, iDrive->nMaxFileSize, FALSE);
  1102. }
  1103. else
  1104. {
  1105. SetDlgItemText(hDlg, IDD_VM_SF_SIZE, _T(""));
  1106. SetDlgItemText(hDlg, IDD_VM_SF_SIZEMAX, _T(""));
  1107. }
  1108. SetDlgItemMB(hDlg, IDD_VM_ALLOCD, RecomputeAllocated());
  1109. SetFocus(GetDlgItem(hDlg, IDD_VM_VOLUMES));
  1110. }
  1111. return true;
  1112. }
  1113. //--------------------------------------------------------------
  1114. int VirtualMemDlg::UpdateWBEM(void)
  1115. {
  1116. int iRet = RET_NO_CHANGE;
  1117. bool bRebootRequired = false;
  1118. CWbemClassObject inst;
  1119. bstr_t sNameProp(gszName);
  1120. bstr_t sMaxProp(gszMaximumSize);
  1121. bstr_t sInitProp(gszInitialSize);
  1122. HRESULT hr = 0;
  1123. PAGING_FILE *pgVal = NULL;
  1124. HWND lbHWND = GetDlgItem(m_hDlg, IDD_VM_VOLUMES);
  1125. int last = ListBox_GetCount(lbHWND);
  1126. BOOL fNewPFInstance;
  1127. #ifdef NTONLY
  1128. BOOL fCreatePFPrivEnabled = FALSE;
  1129. #endif // NTONLY
  1130. // MAINTAINERS NOTE:
  1131. // the iRet value gets *overwritten* each time through the loop
  1132. // it looks to me like the flags should be OR'd together instead
  1133. // but it's way too scary to change it at this late date...
  1134. for(int x = 0; x < last; x++)
  1135. {
  1136. // get it's state structure.
  1137. pgVal = (PAGING_FILE *)ListBox_GetItemData(lbHWND, x);
  1138. //
  1139. // Should assert objPath != NULL && *pgVal->objPath != 0.
  1140. // Do NOT assume when objPath is non-NULL that objPath
  1141. // is a non-empty string.
  1142. //
  1143. fNewPFInstance = (pgVal->objPath == NULL || !*pgVal->objPath);
  1144. if (!fNewPFInstance)
  1145. {
  1146. //
  1147. // Instance doesn't yet exist, of course, if no object path.
  1148. //
  1149. inst = m_WbemServices.GetObject(pgVal->objPath);
  1150. }
  1151. //
  1152. // This condition evaluates pagefile previous/current state.
  1153. // Evaluate to true if:
  1154. // 1. (MINprev != MINcur or MAXprev != MAXcur) - Simple case
  1155. // where the values changed.
  1156. // 2. (RAMBasedPagefile == TRUE) - Important special case from
  1157. // custom to RAM-based AND all min/max prev/cur values
  1158. // coincidentally equal.
  1159. // 3. (MINcur == 0) - Another special case from RAM-based to no
  1160. // pagefile. In this case, min/max prev/cur values are all
  1161. // zero and the RAM-Based pagefile flag is FALSE.
  1162. //
  1163. if ((pgVal->nMinFileSizePrev != pgVal->nMinFileSize ||
  1164. pgVal->nMaxFileSizePrev != pgVal->nMaxFileSize) ||
  1165. pgVal->fRamBasedPagefile ||
  1166. pgVal->nMinFileSize == 0)
  1167. {
  1168. // reboot required if a page file has *shrunk* in size
  1169. if (pgVal->nMaxFileSizePrev > pgVal->nMaxFileSize)
  1170. bRebootRequired = true;
  1171. if (pgVal->nMinFileSize != 0 || pgVal->fRamBasedPagefile)
  1172. {
  1173. //
  1174. // Custom or RAM-based. Note, the RAM-based pagefile flag
  1175. // check seems redundant but it is important for error cases
  1176. // in the SetSize code.
  1177. //
  1178. // Create the instance if it does not exist.
  1179. //
  1180. BOOL fCreate = FALSE, fModified = FALSE;
  1181. if (inst.IsNull())
  1182. {
  1183. inst = m_WbemServices.CreateInstance(
  1184. gszPageFileSettings);
  1185. }
  1186. //
  1187. // Now write out changes. Sigh, too close to RC1 to rewrite
  1188. // this existing code.
  1189. //
  1190. if(!inst.IsNull())
  1191. {
  1192. if (fNewPFInstance) // Write name at creation time only.
  1193. {
  1194. BOOL fRet = TRUE;
  1195. #ifdef NTONLY
  1196. if (!fCreatePFPrivEnabled)
  1197. {
  1198. //
  1199. // Pagefile creation requires pagefile creation
  1200. // privilege.
  1201. //
  1202. // Aargh! No return code to check here...
  1203. //
  1204. m_WbemServices.SetPriv(SE_CREATE_PAGEFILE_NAME);
  1205. fCreatePFPrivEnabled = TRUE;
  1206. }
  1207. #endif // NTONLY
  1208. if (fRet)
  1209. {
  1210. TCHAR temp[30] = {0};
  1211. wsprintf(temp, _T("%s\\pagefile.sys"),
  1212. pgVal->name);
  1213. hr = inst.Put(sNameProp, _bstr_t(temp));
  1214. if (SUCCEEDED(hr))
  1215. {
  1216. fModified = TRUE;
  1217. }
  1218. }
  1219. }
  1220. //
  1221. // Write zeros for min/max values when the page file
  1222. // size is to be computed based on RAM size.
  1223. //
  1224. if (pgVal->nMinFileSizePrev != pgVal->nMinFileSize)
  1225. {
  1226. hr = inst.Put(sInitProp,
  1227. (pgVal->fRamBasedPagefile ? 0
  1228. : (long)pgVal->nMinFileSize));
  1229. if (SUCCEEDED(hr))
  1230. {
  1231. fModified = TRUE;
  1232. }
  1233. }
  1234. if (pgVal->nMaxFileSizePrev != pgVal->nMaxFileSize)
  1235. {
  1236. hr = inst.Put(sMaxProp,
  1237. (pgVal->fRamBasedPagefile ? 0
  1238. : (long)pgVal->nMaxFileSize));
  1239. if (SUCCEEDED(hr))
  1240. {
  1241. fModified = TRUE;
  1242. }
  1243. }
  1244. if (fModified)
  1245. {
  1246. hr = m_WbemServices.PutInstance(
  1247. inst,
  1248. WBEM_FLAG_CREATE_OR_UPDATE,
  1249. EOAC_STATIC_CLOAKING);
  1250. }
  1251. if(FAILED(hr))
  1252. {
  1253. CHString errorDescription;
  1254. CHString errorMessage;
  1255. TCHAR formatString[1024];
  1256. ::LoadString(HINST_THISDLL,IDS_ERR_PAGECREATE,
  1257. formatString, 1024);
  1258. TCHAR errorHeading[20];
  1259. ::LoadString(HINST_THISDLL,IDS_ERR_HEADING,
  1260. errorHeading, 20);
  1261. ErrorLookup(hr, errorDescription);
  1262. errorMessage.Format(formatString, errorDescription);
  1263. ::MessageBox(m_hDlg,errorMessage,errorHeading,MB_OK);
  1264. }
  1265. else
  1266. {
  1267. if (fModified)
  1268. {
  1269. iRet = RET_VIRTUAL_CHANGE;
  1270. }
  1271. }
  1272. }
  1273. }
  1274. else
  1275. {
  1276. //
  1277. // No paging file. Delete the instance.
  1278. //
  1279. if (!inst.IsNull() && !fNewPFInstance &&
  1280. pgVal->objPath != NULL) // 3rd condition insures
  1281. // extra safety.
  1282. {
  1283. hr = m_WbemServices.DeleteInstance(pgVal->objPath);
  1284. // I'm taking it on faith that we can only get here
  1285. // if we *deleted* a page file...
  1286. if (hr != WBEM_E_NOT_FOUND)
  1287. bRebootRequired = true;
  1288. if (SUCCEEDED(hr))
  1289. {
  1290. iRet = RET_VIRTUAL_CHANGE;
  1291. }
  1292. }
  1293. }
  1294. }
  1295. } // endfor
  1296. #ifdef NTONLY
  1297. if (fCreatePFPrivEnabled)
  1298. {
  1299. m_WbemServices.ClearPriv();
  1300. }
  1301. #endif // NTONLY
  1302. if (!bRebootRequired)
  1303. iRet |= RET_CHANGE_NO_REBOOT;
  1304. return iRet;
  1305. }
  1306. //--------------------------------------------------------------
  1307. int VirtualMemDlg::PromptForReboot(HWND hDlg)
  1308. {
  1309. int iReboot = RET_NO_CHANGE;
  1310. /* int i;
  1311. int iThisDrv;
  1312. WCHAR us;
  1313. LARGE_INTEGER liMin, liMax;
  1314. NTSTATUS status;
  1315. WCHAR wszPath[MAX_PATH*2];
  1316. TCHAR szDrive[3] = {0};
  1317. PRIVDAT pdOld;
  1318. GetPageFilePrivilege( &pdOld );
  1319. for (i = 0; i < MAX_DRIVES; i++)
  1320. {
  1321. // Did something change?
  1322. if (apf[i].nMinFileSize != apf[i].nMinFileSizePrev ||
  1323. apf[i].nMaxFileSize != apf[i].nMaxFileSizePrev ||
  1324. apf[i].fCreateFile )
  1325. {
  1326. // If we are strictly creating a *new* page file, then
  1327. // we can do it on the fly, otherwise we have to reboot.
  1328. // assume we will have to reboot
  1329. iThisDrv = RET_VIRTUAL_CHANGE;
  1330. // IF we are not deleting a page file
  1331. // - AND -
  1332. // The Page file does not exist
  1333. // - OR -
  1334. // (This is a New page file AND We are allowed to erase the
  1335. // old, unused pagefile that exists there now)
  1336. if (apf[i].nMinFileSize != 0 &&
  1337. ((GetFileAttributes(SZPageFileName(i)) == 0xFFFFFFFF &&
  1338. GetLastError() == ERROR_FILE_NOT_FOUND) ||
  1339. (apf[i].nMinFileSizePrev == 0 && MsgBoxParam(hDlg,
  1340. SYSTEM+25, IDS_TITLE, MB_ICONQUESTION | MB_YESNO,
  1341. SZPageFileName(i)) == IDYES)) )
  1342. {
  1343. DWORD cch;
  1344. // Create the page file on the fly so JVert and MGlass will
  1345. // stop bugging me!
  1346. HourGlass(TRUE);
  1347. // convert path drive letter to an NT device path
  1348. wsprintf(szDrive, TEXT("%c:"), (TCHAR)(i + (int)TEXT('A')));
  1349. cch = QueryDosDevice( szDrive, wszPath, sizeof(wszPath) /
  1350. sizeof(TCHAR));
  1351. if (cch != 0)
  1352. {
  1353. // Concat the filename only (skip 'd:') to the nt device
  1354. // path, and convert it to a UNICODE_STRING
  1355. lstrcat( wszPath, SZPageFileName(i) + 2 );
  1356. RtlInitUnicodeString( &us, wszPath );
  1357. liMin.QuadPart = (LONGLONG)(apf[i].nMinFileSize * ONE_MEG);
  1358. liMax.QuadPart = (LONGLONG)(apf[i].nMaxFileSize * ONE_MEG);
  1359. status = NtCreatePagingFile ( &us, &liMin, &liMax, 0L );
  1360. if (NT_SUCCESS(status)) {
  1361. // made it on the fly, no need to reboot for this drive!
  1362. iThisDrv = RET_CHANGE_NO_REBOOT;
  1363. }
  1364. }
  1365. HourGlass(FALSE);
  1366. }
  1367. iReboot |= iThisDrv;
  1368. }
  1369. }
  1370. ResetOldPrivilege( &pdOld );
  1371. // If Nothing changed, then change our IDOK to IDCANCEL so System.cpl will
  1372. // know not to reboot.
  1373. */
  1374. return iReboot;
  1375. }
  1376. /************************************************************************
  1377. * *
  1378. * Function: QueryInstanceProperties *
  1379. * *
  1380. * Description: Returns requested object properties associated with *
  1381. * the instance matching the key property value/name. *
  1382. * *
  1383. * Arguments: pszClass -- Object class. *
  1384. * pszRequestedProperties -- Space-separated property *
  1385. * names or *. *
  1386. * pszKeyPropertyName -- Specific instance key *
  1387. * property name. *
  1388. * pszKeyPropertyValue -- Key property value. *
  1389. * Services -- Wbem services. *
  1390. * ppcoInstEnum -- Returned instance. *
  1391. * *
  1392. * Returns: HRESULT *
  1393. * *
  1394. ***********************************************************************/
  1395. #define QUERY_INSTANCEPROPERTY _T("SELECT %s FROM %s WHERE %s=\"%s\"")
  1396. HRESULT QueryInstanceProperties(
  1397. const TCHAR * pszClass,
  1398. const TCHAR * pszRequestedProperties,
  1399. const TCHAR * pszKeyPropertyName,
  1400. const TCHAR * pszKeyPropertyValue,
  1401. CWbemServices &Services,
  1402. IWbemClassObject ** ppcoInst)
  1403. {
  1404. TCHAR * pszQuery;
  1405. BSTR bstrQuery;
  1406. HRESULT hr;
  1407. *ppcoInst = NULL;
  1408. // Dislike multiple allocations of bstr_t.
  1409. //
  1410. pszQuery = new TCHAR[(sizeof(QUERY_INSTANCEPROPERTY) / sizeof(TCHAR)) +
  1411. lstrlen(pszClass) +
  1412. lstrlen(pszRequestedProperties) +
  1413. lstrlen(pszKeyPropertyName) + // No +1 ala
  1414. lstrlen(pszKeyPropertyValue)]; // sizeof.
  1415. if (pszQuery == NULL)
  1416. {
  1417. return ERROR_NOT_ENOUGH_MEMORY;
  1418. }
  1419. wsprintf(pszQuery, QUERY_INSTANCEPROPERTY, pszRequestedProperties,
  1420. pszClass, pszKeyPropertyName, pszKeyPropertyValue);
  1421. // Sigh, must create a bstr.
  1422. //
  1423. bstrQuery = SysAllocString(pszQuery);
  1424. delete pszQuery;
  1425. if (bstrQuery == NULL)
  1426. {
  1427. return ERROR_NOT_ENOUGH_MEMORY;
  1428. }
  1429. IEnumWbemClassObject * pecoInstEnum;
  1430. hr = Services.ExecQuery(bstrQuery, 0, &pecoInstEnum);
  1431. SysFreeString(bstrQuery);
  1432. if (SUCCEEDED(hr))
  1433. {
  1434. DWORD uReturned = 0;
  1435. hr = pecoInstEnum->Next(-1, 1, ppcoInst, &uReturned);
  1436. pecoInstEnum->Release();
  1437. }
  1438. return hr;
  1439. }