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.

2252 lines
62 KiB

  1. /*++
  2. Microsoft Confidential
  3. Copyright (c) 1992-1997 Microsoft Corporation
  4. All rights reserved
  5. Module Name:
  6. virtual.c
  7. Abstract:
  8. Implements the Change Virtual Memory dialog of the System
  9. Control Panel Applet
  10. Notes:
  11. The virtual memory settings and the crash dump (core dump) settings
  12. are tightly-coupled. Therefore, virtual.c and virtual.h have some
  13. heavy dependencies on crashdmp.c and startup.h (and vice versa).
  14. Author:
  15. Byron Dazey 06-Jun-1992
  16. Revision History:
  17. 14-Apr-93 JonPa
  18. maintain paging path if != \pagefile.sys
  19. 15-Dec-93 JonPa
  20. added Crash Recovery dialog
  21. 02-Feb-1994 JonPa
  22. integrated crash recover and virtual memory settings
  23. 18-Sep-1995 Steve Cathcart
  24. split system.cpl out from NT3.51 main.cpl
  25. 12-Jan-1996 JonPa
  26. made part of the new SUR pagified system.cpl
  27. 15-Oct-1997 scotthal
  28. Split out CoreDump*() stuff into separate file
  29. 09-Jul-2000 SilviuC
  30. Allow very big page files if architecture supports it.
  31. Allow booting without a page file.
  32. Allow the system to scale the page file size based on RAM changes.
  33. --*/
  34. //==========================================================================
  35. // Include files
  36. //==========================================================================
  37. // NT base apis
  38. #include <nt.h>
  39. #include <ntrtl.h>
  40. #include <nturtl.h>
  41. #include <ntdddisk.h>
  42. #include <help.h>
  43. // Application specific
  44. #include "sysdm.h"
  45. //==========================================================================
  46. // External Data Declarations
  47. //==========================================================================
  48. extern HFONT hfontBold;
  49. //==========================================================================
  50. // Local Definitions
  51. //==========================================================================
  52. #define MAX_SIZE_LEN 8 // Max chars in the Swap File Size edit.
  53. #define MIN_FREESPACE 5 // Must have 5 meg free after swap file
  54. #define MIN_SUGGEST 22 // Always suggest at least 22 meg
  55. #define CCHMBSTRING 12 // Space for localizing the "MB" string.
  56. /*
  57. * Space for 26 pagefile info structures and 26 paths to pagefiles.
  58. */
  59. #define PAGEFILE_INFO_BUFFER_SIZE MAX_DRIVES * sizeof(SYSTEM_PAGEFILE_INFORMATION) + \
  60. MAX_DRIVES * MAX_PATH * sizeof(TCHAR)
  61. /*
  62. * Maximum length of volume info line in the listbox.
  63. * A: [ Vol_label ] %d - %d
  64. */
  65. #define MAX_VOL_LINE (3 + 1 + MAX_PATH + 2 + 10 + 3 + 10)
  66. /*
  67. * This amount will be added to the minimum page file size to determine
  68. * the maximum page file size if it is not explicitly specified.
  69. */
  70. #define MAXOVERMINFACTOR 50
  71. #define TABSTOP_VOL 22
  72. #define TABSTOP_SIZE 122
  73. /*
  74. * My privilege 'handle' structure
  75. */
  76. typedef struct {
  77. HANDLE hTok;
  78. TOKEN_PRIVILEGES tp;
  79. } PRIVDAT, *PPRIVDAT;
  80. //==========================================================================
  81. // Typedefs and Structs
  82. //==========================================================================
  83. // registry info for a page file (but not yet formatted).
  84. //Note: since this structure gets passed to FormatMessage, all fields must
  85. //be 4 bytes wide (or 8 bytes on Win64)
  86. typedef struct
  87. {
  88. LPTSTR pszName;
  89. DWORD_PTR nMin;
  90. DWORD_PTR nMax;
  91. DWORD_PTR chNull;
  92. } PAGEFILDESC;
  93. //==========================================================================
  94. // Global Data Declarations
  95. //==========================================================================
  96. HKEY ghkeyMemMgt = NULL;
  97. int gcrefMemMgt = 0;
  98. VCREG_RET gvcMemMgt = VCREG_ERROR;
  99. int gcrefPagingFiles = 0;
  100. TCHAR g_szSysDir[ MAX_PATH ];
  101. //==========================================================================
  102. // Local Data Declarations
  103. //==========================================================================
  104. /*
  105. * Virtual Memory Vars
  106. */
  107. // Registry Key and Value Names
  108. TCHAR szMemMan[] =
  109. TEXT("System\\CurrentControlSet\\Control\\Session Manager\\Memory Management");
  110. TCHAR szSessionManager[] = TEXT("System\\CurrentControlSet\\Control\\Session Manager");
  111. TCHAR szPendingRename[] = TEXT("PendingFileRenameOperations");
  112. TCHAR szRenameFunkyPrefix[] = TEXT("\\??\\");
  113. #ifndef VM_DBG
  114. TCHAR szPagingFiles[] = TEXT("PagingFiles");
  115. TCHAR szPagedPoolSize[] = TEXT("PagedPoolSize");
  116. #else
  117. // temp values for testing only!
  118. TCHAR szPagingFiles[] = TEXT("TestPagingFiles");
  119. TCHAR szPagedPoolSize[] = TEXT("TestPagedPoolSize");
  120. #endif
  121. /* Array of paging files. This is indexed by the drive letter (A: is 0). */
  122. PAGING_FILE apf[MAX_DRIVES];
  123. PAGING_FILE apfOriginal[MAX_DRIVES];
  124. // Other VM Vars
  125. TCHAR szPagefile[] = TEXT("x:\\pagefile.sys");
  126. TCHAR szNoPageFile[] = TEXT("TempPageFile");
  127. TCHAR szMB[CCHMBSTRING];
  128. DWORD dwFreeMB;
  129. DWORD cmTotalVM;
  130. DWORD cmRegSizeLim;
  131. DWORD cmPagedPoolLim;
  132. DWORD cmRegUsed;
  133. static DWORD cxLBExtent;
  134. static int cxExtra;
  135. //
  136. // Help IDs
  137. //
  138. DWORD aVirtualMemHelpIds[] = {
  139. IDC_STATIC, NO_HELP,
  140. IDD_VM_VOLUMES, NO_HELP,
  141. IDD_VM_DRIVE_HDR, (IDH_DLG_VIRTUALMEM + 0),
  142. IDD_VM_PF_SIZE_LABEL, (IDH_DLG_VIRTUALMEM + 1),
  143. IDD_VM_DRIVE_LABEL, (IDH_DLG_VIRTUALMEM + 2),
  144. IDD_VM_SF_DRIVE, (IDH_DLG_VIRTUALMEM + 2),
  145. IDD_VM_SPACE_LABEL, (IDH_DLG_VIRTUALMEM + 3),
  146. IDD_VM_SF_SPACE, (IDH_DLG_VIRTUALMEM + 3),
  147. IDD_VM_ST_INITSIZE, (IDH_DLG_VIRTUALMEM + 4),
  148. IDD_VM_SF_SIZE, (IDH_DLG_VIRTUALMEM + 4),
  149. IDD_VM_ST_MAXSIZE, (IDH_DLG_VIRTUALMEM + 5),
  150. IDD_VM_SF_SIZEMAX, (IDH_DLG_VIRTUALMEM + 5),
  151. IDD_VM_SF_SET, (IDH_DLG_VIRTUALMEM + 6),
  152. IDD_VM_MIN_LABEL, (IDH_DLG_VIRTUALMEM + 7),
  153. IDD_VM_MIN, (IDH_DLG_VIRTUALMEM + 7),
  154. IDD_VM_RECOMMEND_LABEL, (IDH_DLG_VIRTUALMEM + 8),
  155. IDD_VM_RECOMMEND, (IDH_DLG_VIRTUALMEM + 8),
  156. IDD_VM_ALLOCD_LABEL, (IDH_DLG_VIRTUALMEM + 9),
  157. IDD_VM_ALLOCD, (IDH_DLG_VIRTUALMEM + 9),
  158. IDD_VM_CUSTOMSIZE_RADIO,(IDH_DLG_VIRTUALMEM + 12),
  159. IDD_VM_RAMBASED_RADIO, (IDH_DLG_VIRTUALMEM + 13),
  160. IDD_VM_NOPAGING_RADIO, (IDH_DLG_VIRTUALMEM + 14),
  161. 0,0
  162. };
  163. /*
  164. Plan for splitting this into property sheets:
  165. 1. Make the VM and CC registry keys globals that are inited
  166. to NULL (or INVALID_HANDLE_VALUE). Also make gvcVirt and
  167. vcCore to be globals (so we can tell how the reg was opened
  168. inside virtinit().)
  169. 1. Change all RegCloseKey's to VirtualCloseKey and CoreDumpCloseKey
  170. 2. Change VirtualOpenKey and CoreDumpOpenKey from macros to
  171. functions that return the global handles if they are already
  172. opened, or else opens them.
  173. 3. In the Perf and Startup pages, call VirtualOpenKey,
  174. CoreDumpOpenKey, and VirtualGetPageFiles.
  175. -- now we can call VirtualMemComputeAlloced() from the perf page
  176. -- we can also just execute the CrashDump code in the startup page
  177. 4. rewrite VirtInit to not try and open the keys again, but instesd
  178. use gvcVirt, vcCore, hkeyVM and kheyCC.
  179. 4. Write VirtualCloseKey and CoreDumpCloseKey as follows...
  180. 4.a If hkey == NULL return
  181. 4.b RegCloseKey(hkey)
  182. 4.c hkey = NULL
  183. 5. In the PSN_RESET and PSN_APPLY cases for Perf and Startup pages
  184. call VirtualCloseKey and CoreDumpCloseKey
  185. */
  186. //==========================================================================
  187. // Local Function Prototypes
  188. //==========================================================================
  189. static BOOL VirtualMemInit(HWND hDlg);
  190. static BOOL ParsePageFileDesc(LPTSTR *ppszDesc, INT *pnDrive,
  191. INT *pnMinFileSize, INT *pnMaxFileSize, LPTSTR *ppszName);
  192. static VOID VirtualMemBuildLBLine(LPTSTR pszBuf, INT cchBuf, INT iDrive);
  193. static INT GetMaxSpaceMB(INT iDrive);
  194. static VOID VirtualMemSelChange(HWND hDlg);
  195. static VOID VirtualMemUpdateAllocated(HWND hDlg);
  196. int VirtualMemComputeTotalMax( void );
  197. static BOOL VirtualMemSetNewSize(HWND hDlg);
  198. void VirtualMemReconcileState();
  199. BOOL GetAPrivilege( LPTSTR pszPrivilegeName, PPRIVDAT ppd );
  200. BOOL ResetOldPrivilege( PPRIVDAT ppdOld );
  201. DWORD VirtualMemDeletePagefile( LPTSTR szPagefile );
  202. #define GetPageFilePrivilege( ppd ) \
  203. GetAPrivilege(SE_CREATE_PAGEFILE_NAME, ppd)
  204. //==========================================================================
  205. VCREG_RET VirtualOpenKey( void ) {
  206. DOUT("In VirtOpenKey" );
  207. if (gvcMemMgt == VCREG_ERROR) {
  208. gvcMemMgt = OpenRegKey( szMemMan, &ghkeyMemMgt );
  209. }
  210. if (gvcMemMgt != VCREG_ERROR)
  211. gcrefMemMgt++;
  212. DPRINTF((TEXT("SYSCPL.CPL: VirtOpenKey, cref=%d\n"), gcrefMemMgt ));
  213. return gvcMemMgt;
  214. }
  215. void VirtualCloseKey(void) {
  216. DOUT( "In VirtCloseKey" );
  217. if (gcrefMemMgt > 0) {
  218. gcrefMemMgt--;
  219. if (gcrefMemMgt == 0) {
  220. CloseRegKey( ghkeyMemMgt );
  221. gvcMemMgt = VCREG_ERROR;
  222. }
  223. }
  224. DPRINTF((TEXT("SYSCPL.CPL: VirtCloseKey, cref=%d\n"), gcrefMemMgt ));
  225. }
  226. LPTSTR SkipNonWhiteSpace( LPTSTR sz ) {
  227. while( *sz != TEXT('\0') && !IsWhiteSpace(*sz))
  228. sz++;
  229. return sz;
  230. }
  231. LPTSTR SZPageFileName (int i)
  232. {
  233. if (apf[i].pszPageFile != NULL) {
  234. return apf[i].pszPageFile;
  235. }
  236. szPagefile[0] = (TCHAR)(i + (int)TEXT('a'));
  237. return szPagefile;
  238. }
  239. void VirtualCopyPageFiles( PAGING_FILE *apfDest, BOOL fFreeOld, PAGING_FILE *apfSrc, BOOL fCloneStrings )
  240. {
  241. int i;
  242. for (i = 0; i < MAX_DRIVES; i++) {
  243. if (fFreeOld && apfDest[i].pszPageFile != NULL) {
  244. LocalFree(apfDest[i].pszPageFile);
  245. }
  246. if (apfSrc != NULL) {
  247. apfDest[i] = apfSrc[i];
  248. if (fCloneStrings && apfDest[i].pszPageFile != NULL) {
  249. apfDest[i].pszPageFile = StrDup(apfDest[i].pszPageFile);
  250. }
  251. }
  252. }
  253. }
  254. /*
  255. * VirtualMemDlg
  256. *
  257. *
  258. *
  259. */
  260. INT_PTR
  261. APIENTRY
  262. VirtualMemDlg(
  263. HWND hDlg,
  264. UINT message,
  265. WPARAM wParam,
  266. LPARAM lParam
  267. )
  268. {
  269. static int fEdtCtlHasFocus = 0;
  270. switch (message)
  271. {
  272. case WM_INITDIALOG:
  273. VirtualMemInit(hDlg);
  274. return TRUE;
  275. case WM_COMMAND:
  276. switch (LOWORD(wParam))
  277. {
  278. case IDD_VM_VOLUMES:
  279. /*
  280. * Make edit control reflect the listbox selection.
  281. */
  282. if (HIWORD(wParam) == LBN_SELCHANGE)
  283. VirtualMemSelChange(hDlg);
  284. break;
  285. case IDD_VM_SF_SET:
  286. if (VirtualMemSetNewSize(hDlg))
  287. SetDefButton(hDlg, IDOK);
  288. break;
  289. case IDOK:
  290. {
  291. int iRet = VirtualMemPromptForReboot(hDlg);
  292. // RET_ERROR means the user told us not to overwrite an
  293. // existing file called pagefile.sys, so we shouldn't
  294. // end the dialog just yet.
  295. if (RET_ERROR == iRet) {
  296. break;
  297. }
  298. else if (RET_BREAK == iRet)
  299. {
  300. EndDialog(hDlg, iRet);
  301. HourGlass(FALSE);
  302. break;
  303. }
  304. else
  305. {
  306. VirtualMemUpdateRegistry();
  307. VirtualMemReconcileState();
  308. VirtualCloseKey();
  309. //
  310. // get rid of backup copy of pagefile structs
  311. //
  312. VirtualCopyPageFiles( apfOriginal, TRUE, NULL, FALSE );
  313. EndDialog(hDlg, iRet);
  314. HourGlass(FALSE);
  315. break;
  316. }
  317. }
  318. case IDCANCEL:
  319. //
  320. // get rid of changes and restore original values
  321. //
  322. VirtualCopyPageFiles( apf, TRUE, apfOriginal, FALSE );
  323. VirtualCloseKey();
  324. EndDialog(hDlg, RET_NO_CHANGE);
  325. HourGlass(FALSE);
  326. break;
  327. case IDD_VM_SF_SIZE:
  328. case IDD_VM_SF_SIZEMAX:
  329. switch(HIWORD(wParam))
  330. {
  331. case EN_CHANGE:
  332. if (fEdtCtlHasFocus != 0)
  333. SetDefButton( hDlg, IDD_VM_SF_SET);
  334. break;
  335. case EN_SETFOCUS:
  336. fEdtCtlHasFocus++;
  337. break;
  338. case EN_KILLFOCUS:
  339. fEdtCtlHasFocus--;
  340. break;
  341. }
  342. break;
  343. case IDD_VM_NOPAGING_RADIO:
  344. case IDD_VM_RAMBASED_RADIO:
  345. if( HIWORD(wParam) == BN_CLICKED )
  346. {
  347. EnableWindow( GetDlgItem( hDlg, IDD_VM_SF_SIZE ), FALSE );
  348. EnableWindow( GetDlgItem( hDlg, IDD_VM_SF_SIZEMAX ), FALSE );
  349. }
  350. break;
  351. case IDD_VM_CUSTOMSIZE_RADIO:
  352. if( HIWORD(wParam) == BN_CLICKED )
  353. {
  354. EnableWindow( GetDlgItem( hDlg, IDD_VM_SF_SIZE ), TRUE );
  355. EnableWindow( GetDlgItem( hDlg, IDD_VM_SF_SIZEMAX ), TRUE );
  356. }
  357. break;
  358. default:
  359. break;
  360. }
  361. break;
  362. case WM_HELP: // F1
  363. WinHelp((HWND)((LPHELPINFO) lParam)->hItemHandle, HELP_FILE, HELP_WM_HELP,
  364. (DWORD_PTR) (LPSTR) aVirtualMemHelpIds);
  365. break;
  366. case WM_CONTEXTMENU: // right mouse click
  367. WinHelp((HWND) wParam, HELP_FILE, HELP_CONTEXTMENU,
  368. (DWORD_PTR) (LPSTR) aVirtualMemHelpIds);
  369. break;
  370. case WM_DESTROY:
  371. {
  372. VirtualFreePageFiles(apf);
  373. /*
  374. * The docs were not clear as to what a dialog box should return
  375. * for this message, so I am going to punt and let the defdlgproc
  376. * doit.
  377. */
  378. /* FALL THROUGH TO DEFAULT CASE! */
  379. }
  380. default:
  381. return FALSE;
  382. break;
  383. }
  384. return TRUE;
  385. }
  386. /*
  387. * BOOL VirtualGetPageFiles(PAGING_FILE *apf)
  388. *
  389. * Fills in the PAGING_FILE array from the values stored in the registry
  390. */
  391. BOOL VirtualGetPageFiles(PAGING_FILE *apf) {
  392. DWORD cbTemp;
  393. LPTSTR pszTemp;
  394. INT nDrive;
  395. INT nMinFileSize;
  396. INT nMaxFileSize;
  397. LPTSTR psz;
  398. DWORD dwDriveMask;
  399. int i;
  400. static TCHAR szDir[] = TEXT("?:");
  401. DPRINTF((TEXT("SYSCPL: In VirtualGetPageFile, cref=%d\n"), gcrefPagingFiles));
  402. if (gcrefPagingFiles++ > 0) {
  403. // Paging files already loaded
  404. return TRUE;
  405. }
  406. dwDriveMask = GetLogicalDrives();
  407. for (i = 0; i < MAX_DRIVES; dwDriveMask >>= 1, i++)
  408. {
  409. apf[i].fCanHavePagefile = FALSE;
  410. apf[i].nMinFileSize = 0;
  411. apf[i].nMaxFileSize = 0;
  412. apf[i].nMinFileSizePrev = 0;
  413. apf[i].nMaxFileSizePrev = 0;
  414. apf[i].fRamBasedPagefile = FALSE;
  415. apf[i].fRamBasedPrev = FALSE;
  416. apf[i].pszPageFile = NULL;
  417. if (dwDriveMask & 0x01)
  418. {
  419. szDir[0] = TEXT('a') + i;
  420. switch (VMGetDriveType(szDir))
  421. {
  422. case DRIVE_FIXED:
  423. apf[i].fCanHavePagefile = TRUE;
  424. break;
  425. default:
  426. break;
  427. }
  428. }
  429. }
  430. if (SHRegGetValue(ghkeyMemMgt, NULL, szPagingFiles, SRRF_RT_REG_MULTI_SZ, NULL,
  431. (LPBYTE) NULL, &cbTemp) != ERROR_SUCCESS)
  432. {
  433. // Could not get the current virtual memory settings size.
  434. return FALSE;
  435. }
  436. pszTemp = LocalAlloc(LPTR, cbTemp);
  437. if (pszTemp == NULL)
  438. {
  439. // Could not alloc a buffer for the vmem settings
  440. return FALSE;
  441. }
  442. pszTemp[0] = 0;
  443. if (SHRegGetValue(ghkeyMemMgt, NULL, szPagingFiles, SRRF_RT_REG_MULTI_SZ, NULL,
  444. (LPBYTE) pszTemp, &cbTemp) != ERROR_SUCCESS)
  445. {
  446. // Could not read the current virtual memory settings.
  447. LocalFree(pszTemp);
  448. return FALSE;
  449. }
  450. psz = pszTemp;
  451. while (*psz)
  452. {
  453. LPTSTR pszPageName;
  454. /*
  455. * If the parse works, and this drive can have a pagefile on it,
  456. * update the apf table. Note that this means that currently
  457. * specified pagefiles for invalid drives will be stripped out
  458. * of the registry if the user presses OK for this dialog.
  459. */
  460. if (ParsePageFileDesc(&psz, &nDrive, &nMinFileSize, &nMaxFileSize, &pszPageName))
  461. {
  462. if (apf[nDrive].fCanHavePagefile)
  463. {
  464. apf[nDrive].nMinFileSize =
  465. apf[nDrive].nMinFileSizePrev = nMinFileSize;
  466. apf[nDrive].nMaxFileSize =
  467. apf[nDrive].nMaxFileSizePrev = nMaxFileSize;
  468. apf[nDrive].fRamBasedPagefile =
  469. apf[nDrive].fRamBasedPrev = (nMinFileSize == 0 && nMaxFileSize == 0);
  470. apf[nDrive].pszPageFile = pszPageName;
  471. }
  472. }
  473. }
  474. LocalFree(pszTemp);
  475. return TRUE;
  476. }
  477. /*
  478. * VirtualFreePageFiles
  479. *
  480. * Frees data alloced by VirtualGetPageFiles
  481. *
  482. */
  483. void VirtualFreePageFiles(PAGING_FILE *apf) {
  484. int i;
  485. DPRINTF((TEXT("SYSCPL: In VirtualFreePageFile, cref=%d\n"), gcrefPagingFiles));
  486. if (gcrefPagingFiles > 0) {
  487. gcrefPagingFiles--;
  488. if (gcrefPagingFiles == 0) {
  489. for (i = 0; i < MAX_DRIVES; i++) {
  490. if (apf[i].pszPageFile != NULL)
  491. LocalFree(apf[i].pszPageFile);
  492. }
  493. }
  494. }
  495. }
  496. /*
  497. * VirtualInitStructures()
  498. *
  499. * Calls VirtualGetPageFiles so other helpers can be called from the Perf Page.
  500. *
  501. * Returns:
  502. * TRUE if success, FALSE if failure
  503. */
  504. BOOL VirtualInitStructures( void ) {
  505. VCREG_RET vcVirt;
  506. BOOL fRet = FALSE;
  507. vcVirt = VirtualOpenKey();
  508. if (vcVirt != VCREG_ERROR)
  509. fRet = VirtualGetPageFiles( apf );
  510. LoadString(hInstance, IDS_SYSDM_MB, szMB, CCHMBSTRING);
  511. return fRet;
  512. }
  513. void VirtualFreeStructures( void ) {
  514. VirtualFreePageFiles(apf);
  515. VirtualCloseKey();
  516. }
  517. /*
  518. * VirtualMemInit
  519. *
  520. * Initializes the Virtual Memory dialog.
  521. *
  522. * Arguments:
  523. * HWND hDlg - Handle to the dialog window.
  524. *
  525. * Returns:
  526. * TRUE
  527. */
  528. static
  529. BOOL
  530. VirtualMemInit(
  531. HWND hDlg
  532. )
  533. {
  534. TCHAR szTemp[MAX_VOL_LINE];
  535. DWORD i;
  536. INT iItem;
  537. HWND hwndLB;
  538. INT aTabs[2];
  539. RECT rc;
  540. VCREG_RET vcVirt;
  541. SYSTEM_BASIC_INFORMATION BasicInfo;
  542. NTSTATUS status;
  543. unsigned __int64 TotalPhys;
  544. HourGlass(TRUE);
  545. //
  546. // Load the "MB" string.
  547. //
  548. LoadString(hInstance, IDS_SYSDM_MB, szMB, CCHMBSTRING);
  549. ////////////////////////////////////////////////////////////////////
  550. // List all drives
  551. ////////////////////////////////////////////////////////////////////
  552. vcVirt = VirtualOpenKey();
  553. if (vcVirt == VCREG_ERROR ) {
  554. // Error - cannot even get list of paging files from registry
  555. MsgBoxParam(hDlg, IDS_SYSDM_NOOPEN_VM_NOTUSER, IDS_SYSDM_TITLE, MB_ICONEXCLAMATION);
  556. EndDialog(hDlg, RET_NO_CHANGE);
  557. HourGlass(FALSE);
  558. if (ghkeyMemMgt != NULL)
  559. VirtualCloseKey();
  560. return FALSE;
  561. }
  562. /*
  563. * To change Virtual Memory size or Crash control, we need access
  564. * to both the CrashCtl key and the PagingFiles value in the MemMgr key
  565. */
  566. if (vcVirt == VCREG_READONLY ) {
  567. /*
  568. * Disable some fields, because they only have Read access.
  569. */
  570. EnableWindow(GetDlgItem(hDlg, IDD_VM_SF_SIZE), FALSE);
  571. EnableWindow(GetDlgItem(hDlg, IDD_VM_SF_SIZEMAX), FALSE);
  572. EnableWindow(GetDlgItem(hDlg, IDD_VM_ST_INITSIZE), FALSE);
  573. EnableWindow(GetDlgItem(hDlg, IDD_VM_ST_MAXSIZE), FALSE);
  574. EnableWindow(GetDlgItem(hDlg, IDD_VM_SF_SET), FALSE);
  575. }
  576. if (!VirtualGetPageFiles(apf)) {
  577. // Could not read the current virtual memory settings.
  578. MsgBoxParam(hDlg, IDS_SYSDM_CANNOTREAD, IDS_SYSDM_TITLE, MB_ICONEXCLAMATION);
  579. }
  580. //
  581. // Save a backup copy of the current pagefile structs
  582. //
  583. VirtualCopyPageFiles( apfOriginal, FALSE, apf, TRUE );
  584. hwndLB = GetDlgItem(hDlg, IDD_VM_VOLUMES);
  585. aTabs[0] = TABSTOP_VOL;
  586. aTabs[1] = TABSTOP_SIZE;
  587. SendMessage(hwndLB, LB_SETTABSTOPS, 2, (LPARAM)aTabs);
  588. /*
  589. * Since SetGenLBWidth only counts tabs as one character, we must compute
  590. * the maximum extra space that the tab characters will expand to and
  591. * arbitrarily tack it onto the end of the string width.
  592. *
  593. * cxExtra = 1st Tab width + 1 default tab width (8 chrs) - strlen("d:\t\t");
  594. *
  595. * (I know the docs for LB_SETTABSTOPS says that a default tab == 2 dlg
  596. * units, but I have read the code, and it is really 8 chars)
  597. */
  598. rc.top = rc.left = 0;
  599. rc.bottom = 8;
  600. rc.right = TABSTOP_VOL + (4 * 8) - (4 * 4);
  601. MapDialogRect( hDlg, &rc );
  602. cxExtra = rc.right - rc.left;
  603. cxLBExtent = 0;
  604. for (i = 0; i < MAX_DRIVES; i++)
  605. {
  606. // Assume we don't have to create anything
  607. apf[i].fCreateFile = FALSE;
  608. if (apf[i].fCanHavePagefile)
  609. {
  610. VirtualMemBuildLBLine(szTemp, ARRAYSIZE(szTemp), i);
  611. iItem = (INT)SendMessage(hwndLB, LB_ADDSTRING, 0, (LPARAM)szTemp);
  612. SendMessage(hwndLB, LB_SETITEMDATA, iItem, i);
  613. // SetGenLBWidth(hwndLB, szTemp, &cxLBExtent, hfontBold, cxExtra);
  614. cxLBExtent = SetLBWidthEx( hwndLB, szTemp, cxLBExtent, cxExtra);
  615. }
  616. }
  617. SendDlgItemMessage(hDlg, IDD_VM_SF_SIZE, EM_LIMITTEXT, MAX_SIZE_LEN, 0L);
  618. SendDlgItemMessage(hDlg, IDD_VM_SF_SIZEMAX, EM_LIMITTEXT, MAX_SIZE_LEN, 0L);
  619. /*
  620. * Get the total physical memory in the machine.
  621. */
  622. status = NtQuerySystemInformation(
  623. SystemBasicInformation,
  624. &BasicInfo,
  625. sizeof(BasicInfo),
  626. NULL
  627. );
  628. if (NT_SUCCESS(status)) {
  629. TotalPhys = (unsigned __int64) BasicInfo.NumberOfPhysicalPages * BasicInfo.PageSize;
  630. }
  631. else {
  632. TotalPhys = 0;
  633. }
  634. SetDlgItemMB(hDlg, IDD_VM_MIN, MIN_SWAPSIZE);
  635. // Recommended pagefile size is 1.5 * RAM size these days.
  636. // Nonintegral multiplication with unsigned __int64s is fun!
  637. // This will obviously fail if the machine has total RAM
  638. // greater than 13194139533312 MB (75% of a full 64-bit address
  639. // space). Hopefully by the time someone has such a beast we'll
  640. // have __int128s to hold the results of this calculation.
  641. TotalPhys >>= 20; // Bytes to MB
  642. TotalPhys *= 3; // This will always fit because of the operation above
  643. TotalPhys >>= 1; // x*3/2 == 1.5*x, more or less
  644. i = (DWORD) TotalPhys; // This cast actually causes the
  645. // algorithm to fail if the machine has
  646. // more than ~ 3.2 billion MB of RAM.
  647. // At that point, either the Win32 API has
  648. // to change to allow me to pass __int64s
  649. // as message params, or we have to start
  650. // reporting these stats in GB.
  651. SetDlgItemMB(hDlg, IDD_VM_RECOMMEND, max(i, MIN_SUGGEST));
  652. /*
  653. * Select the first drive in the listbox.
  654. */
  655. SendDlgItemMessage(hDlg, IDD_VM_VOLUMES, LB_SETCURSEL, 0, 0L);
  656. VirtualMemSelChange(hDlg);
  657. VirtualMemUpdateAllocated(hDlg);
  658. /*
  659. * Show RegQuota
  660. */
  661. cmTotalVM = VirtualMemComputeTotalMax();
  662. HourGlass(FALSE);
  663. return TRUE;
  664. }
  665. /*
  666. * ParseSDD
  667. */
  668. int ParseSDD( LPTSTR psz, LPTSTR szPath, INT cchPath, INT *pnMinFileSize, INT *pnMaxFileSize) {
  669. int cMatched = 0;
  670. LPTSTR pszNext;
  671. psz = SkipWhiteSpace(psz);
  672. if (*psz) {
  673. int cch;
  674. cMatched++;
  675. pszNext = SkipNonWhiteSpace(psz);
  676. cch = (int)(pszNext - psz);
  677. if (cch < cchPath)
  678. {
  679. CopyMemory( szPath, psz, sizeof(TCHAR) * cch );
  680. szPath[cch] = TEXT('\0');
  681. psz = SkipWhiteSpace(pszNext);
  682. if (*psz) {
  683. cMatched++;
  684. pszNext = SkipNonWhiteSpace(psz);
  685. *pnMinFileSize = StringToInt( psz );
  686. psz = SkipWhiteSpace(pszNext);
  687. if (*psz) {
  688. cMatched++;
  689. *pnMaxFileSize = StringToInt( psz );
  690. }
  691. }
  692. }
  693. }
  694. return cMatched;
  695. }
  696. /*
  697. * ParsePageFileDesc
  698. *
  699. *
  700. *
  701. * Arguments:
  702. *
  703. * Returns:
  704. *
  705. */
  706. static
  707. BOOL
  708. ParsePageFileDesc(
  709. LPTSTR *ppszDesc,
  710. INT *pnDrive,
  711. INT *pnMinFileSize,
  712. INT *pnMaxFileSize,
  713. LPTSTR *ppstr
  714. )
  715. {
  716. LPTSTR psz;
  717. LPTSTR pszName = NULL;
  718. int cFields;
  719. TCHAR chDrive;
  720. TCHAR szPath[MAX_PATH];
  721. /*
  722. * Find the end of this REG_MULTI_SZ string and point to the next one
  723. */
  724. psz = *ppszDesc;
  725. *ppszDesc = psz + lstrlen(psz) + 1;
  726. /*
  727. * Parse the string from "filename minsize maxsize"
  728. */
  729. szPath[0] = TEXT('\0');
  730. *pnMinFileSize = 0;
  731. *pnMaxFileSize = 0;
  732. /* Try it without worrying about quotes */
  733. cFields = ParseSDD( psz, szPath, ARRAYSIZE(szPath), pnMinFileSize, pnMaxFileSize);
  734. if (cFields < 2)
  735. return FALSE;
  736. /*
  737. * Find the drive index
  738. */
  739. chDrive = (TCHAR)tolower(*szPath);
  740. if (chDrive < TEXT('a') || chDrive > TEXT('z'))
  741. return FALSE;
  742. *pnDrive = (INT)(chDrive - TEXT('a'));
  743. /* if the path != x:\pagefile.sys then save it */
  744. if (lstrcmpi(szPagefile + 1, szPath + 1) != 0)
  745. {
  746. pszName = StrDup(szPath);
  747. if (!pszName)
  748. {
  749. return FALSE;
  750. }
  751. }
  752. *ppstr = pszName;
  753. if (cFields < 3)
  754. {
  755. INT nSpace;
  756. // don't call GetDriveSpace if the drive is invalid
  757. if (apf[*pnDrive].fCanHavePagefile)
  758. nSpace = GetMaxSpaceMB(*pnDrive);
  759. else
  760. nSpace = 0;
  761. *pnMaxFileSize = min(*pnMinFileSize + MAXOVERMINFACTOR, nSpace);
  762. }
  763. /*
  764. * If the page file size in the registry is zero it means this is
  765. * a RAM based page file.
  766. */
  767. if (*pnMinFileSize == 0) {
  768. apf[*pnDrive].fRamBasedPagefile = TRUE;
  769. }
  770. else {
  771. apf[*pnDrive].fRamBasedPagefile = FALSE;
  772. }
  773. return TRUE;
  774. }
  775. /*
  776. * VirtualMemBuildLBLine
  777. *
  778. *
  779. *
  780. */
  781. static
  782. VOID
  783. VirtualMemBuildLBLine(
  784. LPTSTR pszBuf,
  785. INT cchBuf,
  786. INT iDrive
  787. )
  788. {
  789. HRESULT hr;
  790. TCHAR szVolume[MAX_PATH];
  791. TCHAR szTemp[MAX_PATH];
  792. PathBuildRoot(szTemp, iDrive);
  793. *szVolume = 0;
  794. if (!GetVolumeInformation(szTemp, szVolume, MAX_PATH, NULL, NULL, NULL, NULL, 0))
  795. {
  796. *szVolume = 0;
  797. }
  798. szTemp[2] = TEXT('\t');
  799. if (*szVolume)
  800. {
  801. hr = StringCchPrintf(pszBuf, cchBuf, TEXT("%s[%s]"),szTemp,szVolume);
  802. }
  803. else
  804. {
  805. hr = StringCchCopy(pszBuf, cchBuf, szTemp);
  806. }
  807. if (SUCCEEDED(hr))
  808. {
  809. if (apf[iDrive].fRamBasedPagefile)
  810. {
  811. if (LoadString(hInstance, 164, szTemp, ARRAYSIZE(szTemp))) // what does 164 mean here?
  812. {
  813. hr = StringCchCat(pszBuf, cchBuf, szTemp);
  814. }
  815. }
  816. else if (apf[iDrive].nMinFileSize)
  817. {
  818. if (SUCCEEDED(StringCchPrintf(szTemp, ARRAYSIZE(szTemp), TEXT("\t%d - %d"),
  819. apf[iDrive].nMinFileSize, apf[iDrive].nMaxFileSize)))
  820. {
  821. hr = StringCchCat(pszBuf, cchBuf, szTemp);
  822. }
  823. }
  824. }
  825. }
  826. /*
  827. * SetDlgItemMB
  828. *
  829. *
  830. */
  831. VOID SetDlgItemMB( HWND hDlg, INT idControl, DWORD dwMBValue )
  832. {
  833. TCHAR szBuf[32];
  834. if (SUCCEEDED(StringCchPrintf(szBuf, ARRAYSIZE(szBuf), TEXT("%d %s"), dwMBValue, szMB)))
  835. {
  836. SetDlgItemText(hDlg, idControl, szBuf);
  837. }
  838. }
  839. /*
  840. * GetFreeSpaceMB
  841. *
  842. *
  843. *
  844. */
  845. DWORD
  846. GetFreeSpaceMB(
  847. INT iDrive
  848. )
  849. {
  850. TCHAR szDriveRoot[4];
  851. DWORD dwSectorsPerCluster;
  852. DWORD dwBytesPerSector;
  853. DWORD dwFreeClusters;
  854. DWORD dwClusters;
  855. DWORD iSpace;
  856. DWORD iSpaceExistingPagefile;
  857. HANDLE hff;
  858. WIN32_FIND_DATA ffd;
  859. ULARGE_INTEGER ullPagefileSize;
  860. PathBuildRoot(szDriveRoot, iDrive);
  861. if (!GetDiskFreeSpace(szDriveRoot, &dwSectorsPerCluster, &dwBytesPerSector,
  862. &dwFreeClusters, &dwClusters))
  863. return 0;
  864. iSpace = (INT)((dwSectorsPerCluster * dwFreeClusters) /
  865. (ONE_MEG / dwBytesPerSector));
  866. //
  867. // Be sure to include the size of any existing pagefile.
  868. // Because this space can be reused for a new paging file,
  869. // it is effectively "disk free space" as well. The
  870. // FindFirstFile api is safe to use, even if the pagefile
  871. // is in use, because it does not need to open the file
  872. // to get its size.
  873. //
  874. iSpaceExistingPagefile = 0;
  875. if ((hff = FindFirstFile(SZPageFileName(iDrive), &ffd)) !=
  876. INVALID_HANDLE_VALUE)
  877. {
  878. ullPagefileSize.HighPart = ffd.nFileSizeHigh;
  879. ullPagefileSize.LowPart = ffd.nFileSizeLow;
  880. iSpaceExistingPagefile = (INT)(ullPagefileSize.QuadPart / (ULONGLONG)ONE_MEG);
  881. FindClose(hff);
  882. }
  883. return iSpace + iSpaceExistingPagefile;
  884. }
  885. /*
  886. * GetMaxSpaceMB
  887. *
  888. *
  889. *
  890. */
  891. static
  892. INT
  893. GetMaxSpaceMB(
  894. INT iDrive
  895. )
  896. {
  897. TCHAR szDriveRoot[4];
  898. DWORD dwSectorsPerCluster;
  899. DWORD dwBytesPerSector;
  900. DWORD dwFreeClusters;
  901. DWORD dwClusters;
  902. INT iSpace;
  903. PathBuildRoot(szDriveRoot, iDrive);
  904. if (!GetDiskFreeSpace(szDriveRoot, &dwSectorsPerCluster, &dwBytesPerSector,
  905. &dwFreeClusters, &dwClusters))
  906. return 0;
  907. iSpace = (INT)((dwSectorsPerCluster * dwClusters) /
  908. (ONE_MEG / dwBytesPerSector));
  909. return iSpace;
  910. }
  911. /*
  912. * VirtualMemSelChange
  913. *
  914. *
  915. *
  916. */
  917. static
  918. VOID
  919. VirtualMemSelChange(
  920. HWND hDlg
  921. )
  922. {
  923. TCHAR szDriveRoot[4];
  924. TCHAR szTemp[MAX_PATH];
  925. TCHAR szVolume[MAX_PATH];
  926. INT iSel;
  927. INT iDrive;
  928. INT nCrtRadioButtonId;
  929. BOOL fEditsEnabled;
  930. if ((iSel = (INT)SendDlgItemMessage(
  931. hDlg, IDD_VM_VOLUMES, LB_GETCURSEL, 0, 0)) == LB_ERR)
  932. return;
  933. iDrive = (INT)SendDlgItemMessage(hDlg, IDD_VM_VOLUMES,
  934. LB_GETITEMDATA, iSel, 0);
  935. PathBuildRoot(szDriveRoot, iDrive);
  936. PathBuildRoot(szTemp, iDrive);
  937. szTemp[2] = 0;
  938. szVolume[0] = 0;
  939. if (GetVolumeInformation(szDriveRoot, szVolume, MAX_PATH, NULL, NULL, NULL, NULL, 0) && *szVolume)
  940. {
  941. if (FAILED(StringCchCat(szTemp, ARRAYSIZE(szTemp), TEXT(" ["))) ||
  942. FAILED(StringCchCat(szTemp, ARRAYSIZE(szTemp), szVolume)) ||
  943. FAILED(StringCchCat(szTemp, ARRAYSIZE(szTemp), TEXT("]"))))
  944. {
  945. szTemp[2] = 0; // if we fail to concat all the pieces, concat none
  946. }
  947. }
  948. //LATER: should we also put up total drive size as well as free space?
  949. SetDlgItemText(hDlg, IDD_VM_SF_DRIVE, szTemp);
  950. SetDlgItemMB(hDlg, IDD_VM_SF_SPACE, GetFreeSpaceMB(iDrive));
  951. if ( apf[iDrive].fRamBasedPagefile )
  952. {
  953. //
  954. // Paging file size based on RAM size
  955. //
  956. nCrtRadioButtonId = IDD_VM_RAMBASED_RADIO;
  957. fEditsEnabled = FALSE;
  958. }
  959. else
  960. {
  961. if ( apf[iDrive].nMinFileSize != 0 )
  962. {
  963. //
  964. // Custom size paging file
  965. //
  966. nCrtRadioButtonId = IDD_VM_CUSTOMSIZE_RADIO;
  967. SetDlgItemInt(hDlg, IDD_VM_SF_SIZE, apf[iDrive].nMinFileSize, FALSE);
  968. SetDlgItemInt(hDlg, IDD_VM_SF_SIZEMAX, apf[iDrive].nMaxFileSize, FALSE);
  969. fEditsEnabled = TRUE;
  970. }
  971. else
  972. {
  973. //
  974. // No paging file
  975. //
  976. nCrtRadioButtonId = IDD_VM_NOPAGING_RADIO;
  977. SetDlgItemText(hDlg, IDD_VM_SF_SIZE, TEXT(""));
  978. SetDlgItemText(hDlg, IDD_VM_SF_SIZEMAX, TEXT(""));
  979. fEditsEnabled = FALSE;
  980. }
  981. }
  982. //
  983. // Select the appropriate radio button
  984. //
  985. CheckRadioButton(
  986. hDlg,
  987. IDD_VM_CUSTOMSIZE_RADIO,
  988. IDD_VM_NOPAGING_RADIO,
  989. nCrtRadioButtonId );
  990. //
  991. // Enable/disable the min & max size edit boxes
  992. //
  993. EnableWindow( GetDlgItem( hDlg, IDD_VM_SF_SIZE ), fEditsEnabled );
  994. EnableWindow( GetDlgItem( hDlg, IDD_VM_SF_SIZEMAX ), fEditsEnabled );
  995. }
  996. /*
  997. * VirtualMemUpdateAllocated
  998. *
  999. *
  1000. *
  1001. */
  1002. INT VirtualMemComputeAllocated( HWND hWnd , BOOL *pfTempPf)
  1003. {
  1004. BOOL fSuccess = FALSE;
  1005. static BOOL fWarned = FALSE;
  1006. ULONG ulPagefileSize = 0;
  1007. unsigned __int64 PagefileSize;
  1008. NTSTATUS result = ERROR_ACCESS_DENIED;
  1009. SYSTEM_INFO SysInfo;
  1010. PSYSTEM_PAGEFILE_INFORMATION pPagefileInfo = NULL;
  1011. PSYSTEM_PAGEFILE_INFORMATION pCurrentPagefile = NULL;
  1012. LONG lResult = ERROR_ACCESS_DENIED;
  1013. DWORD dwValueType = 0;
  1014. DWORD fTempPagefile = 0;
  1015. DWORD cbSize = sizeof(DWORD);
  1016. __try {
  1017. pCurrentPagefile = pPagefileInfo = (PSYSTEM_PAGEFILE_INFORMATION) LocalAlloc(
  1018. LPTR,
  1019. PAGEFILE_INFO_BUFFER_SIZE
  1020. );
  1021. if (!pPagefileInfo) {
  1022. __leave;
  1023. } // if
  1024. // Get the page size in bytes
  1025. GetSystemInfo(&SysInfo);
  1026. // Get the sizes (in pages) of all of the pagefiles on the system
  1027. result = NtQuerySystemInformation(
  1028. SystemPageFileInformation,
  1029. pPagefileInfo,
  1030. PAGEFILE_INFO_BUFFER_SIZE,
  1031. NULL
  1032. );
  1033. if (ERROR_SUCCESS != result) {
  1034. __leave;
  1035. } // if
  1036. if (pfTempPf) {
  1037. // Check to see if the system created a temporary pagefile
  1038. lResult = SHRegGetValue(
  1039. ghkeyMemMgt,
  1040. NULL,
  1041. szNoPageFile,
  1042. SRRF_RT_REG_DWORD,
  1043. &dwValueType,
  1044. (LPBYTE) &fTempPagefile,
  1045. &cbSize
  1046. );
  1047. if ((ERROR_SUCCESS == lResult) && fTempPagefile) {
  1048. *pfTempPf = TRUE;
  1049. } // if (ERROR_SUCCESS...
  1050. else {
  1051. *pfTempPf = FALSE;
  1052. } // else
  1053. } // if (pfTempPf)
  1054. // Add up pagefile sizes
  1055. while (pCurrentPagefile->NextEntryOffset) {
  1056. ulPagefileSize += pCurrentPagefile->TotalSize;
  1057. ((LPBYTE) pCurrentPagefile) += pCurrentPagefile->NextEntryOffset;
  1058. } // while
  1059. ulPagefileSize += pCurrentPagefile->TotalSize;
  1060. // Convert pages to bytes
  1061. PagefileSize = (unsigned __int64) ulPagefileSize * SysInfo.dwPageSize;
  1062. // Convert bytes to MB
  1063. ulPagefileSize = (ULONG) (PagefileSize / ONE_MEG);
  1064. fSuccess = TRUE;
  1065. } // __try
  1066. __finally {
  1067. // If we failed to determine the pagefile size, then
  1068. // warn the user that the reported size is incorrect,
  1069. // once per applet invokation.
  1070. if (!fSuccess && !fWarned) {
  1071. MsgBoxParam(
  1072. hWnd,
  1073. IDS_SYSDM_DONTKNOWCURRENT,
  1074. IDS_SYSDM_TITLE,
  1075. MB_ICONERROR | MB_OK
  1076. );
  1077. fWarned = TRUE;
  1078. } // if
  1079. LocalFree(pPagefileInfo);
  1080. } // __finally
  1081. return(ulPagefileSize);
  1082. }
  1083. static VOID VirtualMemUpdateAllocated(
  1084. HWND hDlg
  1085. )
  1086. {
  1087. SetDlgItemMB(hDlg, IDD_VM_ALLOCD, VirtualMemComputeAllocated(hDlg, NULL));
  1088. }
  1089. int VirtualMemComputeTotalMax( void ) {
  1090. INT nTotalAllocated;
  1091. INT i;
  1092. for (nTotalAllocated = 0, i = 0; i < MAX_DRIVES; i++)
  1093. {
  1094. nTotalAllocated += apf[i].nMaxFileSize;
  1095. }
  1096. return nTotalAllocated;
  1097. }
  1098. /*
  1099. * VirtualMemSetNewSize
  1100. *
  1101. *
  1102. *
  1103. */
  1104. static
  1105. BOOL
  1106. VirtualMemSetNewSize(
  1107. HWND hDlg
  1108. )
  1109. {
  1110. DWORD nSwapSize;
  1111. DWORD nSwapSizeMax;
  1112. BOOL fTranslated;
  1113. INT iSel;
  1114. INT iDrive = 2; // default to C
  1115. TCHAR szTemp[MAX_PATH];
  1116. DWORD nFreeSpace;
  1117. DWORD CrashDumpSizeInMbytes;
  1118. TCHAR Drive;
  1119. INT iBootDrive;
  1120. BOOL fRamBasedPagefile = FALSE;
  1121. //
  1122. // Initialize variables for crashdump.
  1123. //
  1124. if (GetSystemDrive (&Drive)) {
  1125. iBootDrive = tolower (Drive) - 'a';
  1126. } else {
  1127. iBootDrive = 0;
  1128. }
  1129. if ((iSel = (INT)SendDlgItemMessage(
  1130. hDlg, IDD_VM_VOLUMES, LB_GETCURSEL, 0, 0)) != LB_ERR)
  1131. {
  1132. if (LB_ERR ==
  1133. (iDrive = (INT)SendDlgItemMessage(hDlg, IDD_VM_VOLUMES,
  1134. LB_GETITEMDATA, iSel, 0)))
  1135. {
  1136. return FALSE; // failure!
  1137. }
  1138. }
  1139. CrashDumpSizeInMbytes =
  1140. (DWORD) ( CoreDumpGetRequiredFileSize (NULL) / ONE_MEG );
  1141. if( IsDlgButtonChecked( hDlg, IDD_VM_NOPAGING_RADIO ) == BST_CHECKED )
  1142. {
  1143. //
  1144. // No paging file on this drive.
  1145. //
  1146. nSwapSize = 0;
  1147. nSwapSizeMax = 0;
  1148. fTranslated = TRUE;
  1149. }
  1150. else
  1151. {
  1152. if( IsDlgButtonChecked( hDlg, IDD_VM_RAMBASED_RADIO ) == BST_CHECKED )
  1153. {
  1154. MEMORYSTATUSEX MemoryInfo;
  1155. //
  1156. // User requested a RAM based page file. We will compute a page file
  1157. // size based on the RAM currently available so that we can benefit of
  1158. // all the verifications done below related to disk space available etc.
  1159. // The final page file specification written to the registry will contain
  1160. // zero sizes though because this is the way we signal that we
  1161. // want a RAM based page file.
  1162. //
  1163. ZeroMemory (&MemoryInfo, sizeof(MemoryInfo));
  1164. MemoryInfo.dwLength = sizeof(MemoryInfo);
  1165. if (GlobalMemoryStatusEx (&MemoryInfo))
  1166. {
  1167. fRamBasedPagefile = TRUE;
  1168. //
  1169. // We do not lose info because we first divide the RAM size to
  1170. // 1Mb and only after that we convert to a DWORD.
  1171. //
  1172. nSwapSize = (DWORD)(MemoryInfo.ullTotalPhys / 0x100000) + 12;
  1173. nSwapSizeMax = nSwapSize;
  1174. fTranslated = TRUE;
  1175. }
  1176. else
  1177. {
  1178. nSwapSize = 0;
  1179. nSwapSizeMax = 0;
  1180. fTranslated = TRUE;
  1181. }
  1182. }
  1183. else
  1184. {
  1185. //
  1186. // User requested a custom size paging file
  1187. //
  1188. nSwapSize = (INT)GetDlgItemInt(hDlg, IDD_VM_SF_SIZE,
  1189. &fTranslated, FALSE);
  1190. if (!fTranslated)
  1191. {
  1192. MsgBoxParam(hDlg, IDS_SYSDM_ENTERINITIALSIZE, IDS_SYSDM_TITLE, MB_ICONEXCLAMATION);
  1193. SetFocus(GetDlgItem(hDlg, IDD_VM_SF_SIZE));
  1194. return FALSE;
  1195. }
  1196. if ((nSwapSize < MIN_SWAPSIZE && nSwapSize != 0))
  1197. {
  1198. MsgBoxParam(hDlg, IDS_SYSDM_PAGEFILESIZE_START, IDS_SYSDM_TITLE, MB_ICONEXCLAMATION,
  1199. GetMaxPagefileSizeInMB(iDrive));
  1200. SetFocus(GetDlgItem(hDlg, IDD_VM_SF_SIZE));
  1201. return FALSE;
  1202. }
  1203. if (nSwapSize == 0)
  1204. {
  1205. nSwapSizeMax = 0;
  1206. }
  1207. else
  1208. {
  1209. nSwapSizeMax = (INT)GetDlgItemInt(hDlg, IDD_VM_SF_SIZEMAX,
  1210. &fTranslated, FALSE);
  1211. if (!fTranslated)
  1212. {
  1213. MsgBoxParam(hDlg, IDS_SYSDM_ENTERMAXIMUMSIZE, IDS_SYSDM_TITLE, MB_ICONEXCLAMATION,
  1214. GetMaxPagefileSizeInMB(iDrive));
  1215. SetFocus(GetDlgItem(hDlg, IDD_VM_SF_SIZEMAX));
  1216. return FALSE;
  1217. }
  1218. if (nSwapSizeMax < nSwapSize || nSwapSizeMax > GetMaxPagefileSizeInMB(iDrive))
  1219. {
  1220. MsgBoxParam(hDlg, IDS_SYSDM_PAGEFILESIZE_MAX, IDS_SYSDM_TITLE, MB_ICONEXCLAMATION,
  1221. GetMaxPagefileSizeInMB(iDrive));
  1222. SetFocus(GetDlgItem(hDlg, IDD_VM_SF_SIZEMAX));
  1223. return FALSE;
  1224. }
  1225. }
  1226. }
  1227. }
  1228. if (fTranslated && iSel != LB_ERR)
  1229. {
  1230. nFreeSpace = GetMaxSpaceMB(iDrive);
  1231. if (nSwapSizeMax > nFreeSpace)
  1232. {
  1233. MsgBoxParam(hDlg, IDS_SYSDM_PAGEFILESIZE_TOOSMALL_NAMED, IDS_SYSDM_TITLE, MB_ICONEXCLAMATION,
  1234. (TCHAR)(iDrive + TEXT('a')));
  1235. SetFocus(GetDlgItem(hDlg, IDD_VM_SF_SIZEMAX));
  1236. return FALSE;
  1237. }
  1238. nFreeSpace = GetFreeSpaceMB(iDrive);
  1239. if (nSwapSize > nFreeSpace)
  1240. {
  1241. MsgBoxParam(hDlg, IDS_SYSDM_PAGEFILESIZE_TOOSMALL, IDS_SYSDM_TITLE, MB_ICONEXCLAMATION);
  1242. SetFocus(GetDlgItem(hDlg, IDD_VM_SF_SIZE));
  1243. return FALSE;
  1244. }
  1245. if (nSwapSize != 0 && nFreeSpace - nSwapSize < MIN_FREESPACE)
  1246. {
  1247. MsgBoxParam(hDlg, IDS_SYSDM_NOTENOUGHSPACE_PAGE, IDS_SYSDM_TITLE, MB_ICONEXCLAMATION,
  1248. (int)MIN_FREESPACE);
  1249. SetFocus(GetDlgItem(hDlg, IDD_VM_SF_SIZE));
  1250. return FALSE;
  1251. }
  1252. if (nSwapSizeMax > nFreeSpace)
  1253. {
  1254. if (MsgBoxParam(hDlg, IDS_SYSDM_PAGEFILESIZE_TOOSMALL_GROW, IDS_SYSDM_TITLE, MB_ICONINFORMATION |
  1255. MB_OKCANCEL, (TCHAR)(iDrive + TEXT('a'))) == IDCANCEL)
  1256. {
  1257. SetFocus(GetDlgItem(hDlg, IDD_VM_SF_SIZEMAX));
  1258. return FALSE;
  1259. }
  1260. }
  1261. if (iDrive == iBootDrive &&
  1262. (ULONG64) nSwapSize < CrashDumpSizeInMbytes) {
  1263. DWORD Ret;
  1264. //
  1265. // The new boot drive page file size is less than we need for
  1266. // crashdump. The message notifies the user that the resultant
  1267. // dump file may be truncated.
  1268. //
  1269. // NOTE: DO NOT, turn off dumping at this point, because a valid
  1270. // dump could still be generated.
  1271. //
  1272. Ret = MsgBoxParam (hDlg,
  1273. IDS_SYSDM_DEBUGGING_MINIMUM,
  1274. IDS_SYSDM_TITLE,
  1275. MB_ICONEXCLAMATION | MB_YESNO,
  1276. (TCHAR) ( iBootDrive + TEXT ('a') ),
  1277. (DWORD) CrashDumpSizeInMbytes
  1278. );
  1279. if (Ret != IDYES) {
  1280. SetFocus(GetDlgItem(hDlg, IDD_VM_SF_SIZE));
  1281. return FALSE;
  1282. }
  1283. }
  1284. apf[iDrive].nMinFileSize = nSwapSize;
  1285. apf[iDrive].nMaxFileSize = nSwapSizeMax;
  1286. apf[iDrive].fRamBasedPagefile = fRamBasedPagefile;
  1287. // Remember if the page file does not exist so we can create it later
  1288. if (GetFileAttributes(SZPageFileName(iDrive)) == 0xFFFFFFFF &&
  1289. GetLastError() == ERROR_FILE_NOT_FOUND) {
  1290. apf[iDrive].fCreateFile = TRUE;
  1291. }
  1292. VirtualMemBuildLBLine(szTemp, ARRAYSIZE(szTemp), iDrive);
  1293. SendDlgItemMessage(hDlg, IDD_VM_VOLUMES, LB_DELETESTRING, iSel, 0);
  1294. SendDlgItemMessage(hDlg, IDD_VM_VOLUMES, LB_INSERTSTRING, iSel,
  1295. (LPARAM)szTemp);
  1296. SendDlgItemMessage(hDlg, IDD_VM_VOLUMES, LB_SETITEMDATA, iSel,
  1297. (LPARAM)iDrive);
  1298. SendDlgItemMessage(hDlg, IDD_VM_VOLUMES, LB_SETCURSEL, iSel, 0L);
  1299. cxLBExtent = SetLBWidthEx(GetDlgItem(hDlg, IDD_VM_VOLUMES), szTemp, cxLBExtent, cxExtra);
  1300. if ( ( ! apf[iDrive].fRamBasedPagefile ) && ( apf[iDrive].nMinFileSize != 0 ) ) {
  1301. SetDlgItemInt(hDlg, IDD_VM_SF_SIZE, apf[iDrive].nMinFileSize, FALSE);
  1302. SetDlgItemInt(hDlg, IDD_VM_SF_SIZEMAX, apf[iDrive].nMaxFileSize, FALSE);
  1303. }
  1304. else {
  1305. SetDlgItemText(hDlg, IDD_VM_SF_SIZE, TEXT(""));
  1306. SetDlgItemText(hDlg, IDD_VM_SF_SIZEMAX, TEXT(""));
  1307. }
  1308. VirtualMemUpdateAllocated(hDlg);
  1309. SetFocus(GetDlgItem(hDlg, IDD_VM_VOLUMES));
  1310. }
  1311. return TRUE;
  1312. }
  1313. /*
  1314. * VirtualMemUpdateRegistry
  1315. *
  1316. *
  1317. *
  1318. */
  1319. BOOL
  1320. VirtualMemUpdateRegistry(
  1321. VOID
  1322. )
  1323. {
  1324. LPTSTR pszBuf;
  1325. TCHAR szTmp[MAX_DRIVES * 22]; //max_drives * sizeof(fmt_string)
  1326. LONG i;
  1327. INT c;
  1328. int j;
  1329. PAGEFILDESC aparm[MAX_DRIVES];
  1330. static TCHAR szNULLs[] = TEXT("\0\0");
  1331. c = 0;
  1332. szTmp[0] = TEXT('\0');
  1333. pszBuf = szTmp;
  1334. for (i = 0; i < MAX_DRIVES; i++)
  1335. {
  1336. if (apf[i].fRamBasedPagefile || apf[i].nMinFileSize)
  1337. {
  1338. j = (c * 4);
  1339. aparm[c].nMin = (apf[i].fRamBasedPagefile) ? 0 : apf[i].nMinFileSize;
  1340. aparm[c].nMax = (apf[i].fRamBasedPagefile) ? 0 : apf[i].nMaxFileSize;
  1341. aparm[c].chNull = (DWORD)TEXT('\0');
  1342. aparm[c].pszName = StrDup(SZPageFileName(i));
  1343. if (!aparm[c].pszName)
  1344. {
  1345. return FALSE;
  1346. }
  1347. if (SUCCEEDED(StringCchPrintf(pszBuf, ARRAYSIZE(szTmp), TEXT("%%%d!s! %%%d!d! %%%d!d!%%%d!c!"), j+1, j+2, j+3, j+4)))
  1348. {
  1349. pszBuf += lstrlen(pszBuf);
  1350. }
  1351. else
  1352. {
  1353. return FALSE;
  1354. }
  1355. c++;
  1356. }
  1357. }
  1358. /*
  1359. * Alloc and fill in the page file registry string
  1360. */
  1361. //since FmtMsg returns 0 for error, it can not return a zero length string
  1362. //therefore, force string to be at least one space long.
  1363. if (szTmp[0] == TEXT('\0')) {
  1364. pszBuf = szNULLs;
  1365. j = 1; //Length of string == 1 char (ZTerm null will be added later).
  1366. } else {
  1367. j = FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER |
  1368. FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_MAX_WIDTH_MASK |
  1369. FORMAT_MESSAGE_ARGUMENT_ARRAY,
  1370. szTmp, 0, 0, (LPTSTR)&pszBuf, 1, (va_list *)aparm); // TODO: do we really want &pszBuf here?
  1371. }
  1372. for( i = 0; i < c; i++ )
  1373. LocalFree(aparm[i].pszName);
  1374. if (j == 0)
  1375. return FALSE;
  1376. i = RegSetValueEx (ghkeyMemMgt, szPagingFiles, 0, REG_MULTI_SZ,
  1377. (LPBYTE)pszBuf, sizeof(TCHAR) * (j+1));
  1378. // free the string now that it is safely stored in the registry
  1379. if (pszBuf != szNULLs)
  1380. LocalFree(pszBuf);
  1381. // if the string didn't get there, then return error
  1382. if (i != ERROR_SUCCESS)
  1383. return FALSE;
  1384. /*
  1385. * Now be sure that any previous pagefiles will be deleted on
  1386. * the next boot.
  1387. */
  1388. for (i = 0; i < MAX_DRIVES; i++)
  1389. {
  1390. /*
  1391. * Did this drive have a pagefile before, but does not have
  1392. * one now?
  1393. */
  1394. if ((apf[i].nMinFileSizePrev != 0 || apf[i].fRamBasedPrev != FALSE) && apf[i].nMinFileSize == 0)
  1395. {
  1396. //
  1397. // Hack workaround -- MoveFileEx() is broken
  1398. //
  1399. TCHAR szPagefilePath[MAX_PATH];
  1400. if (SUCCEEDED(StringCchCopy(szPagefilePath, ARRAYSIZE(szPagefilePath), szRenameFunkyPrefix)) &&
  1401. SUCCEEDED(StringCchCat(szPagefilePath, ARRAYSIZE(szPagefilePath), SZPageFileName(i))))
  1402. {
  1403. VirtualMemDeletePagefile(szPagefilePath);
  1404. }
  1405. }
  1406. }
  1407. return TRUE;
  1408. }
  1409. BOOL GetAPrivilege( LPTSTR szPrivilegeName, PPRIVDAT ppd ) {
  1410. BOOL fRet = FALSE;
  1411. HANDLE hTok;
  1412. LUID luid;
  1413. TOKEN_PRIVILEGES tpNew;
  1414. DWORD cb;
  1415. if (LookupPrivilegeValue( NULL, szPrivilegeName, &luid ) &&
  1416. OpenProcessToken(GetCurrentProcess(),
  1417. TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hTok)) {
  1418. tpNew.PrivilegeCount = 1;
  1419. tpNew.Privileges[0].Luid = luid;
  1420. tpNew.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  1421. if (AdjustTokenPrivileges(hTok, FALSE, &tpNew, sizeof(ppd->tp), &(ppd->tp), &cb))
  1422. {
  1423. fRet = TRUE;
  1424. }
  1425. else
  1426. {
  1427. GetLastError();
  1428. }
  1429. ppd->hTok = hTok;
  1430. } else {
  1431. ppd->hTok = NULL;
  1432. }
  1433. return fRet;
  1434. }
  1435. BOOL ResetOldPrivilege( PPRIVDAT ppdOld ) {
  1436. BOOL fRet = FALSE;
  1437. if (ppdOld->hTok != NULL )
  1438. {
  1439. if (AdjustTokenPrivileges(ppdOld->hTok, FALSE, &(ppdOld->tp), 0, NULL, NULL) &&
  1440. ERROR_NOT_ALL_ASSIGNED != GetLastError())
  1441. {
  1442. fRet = TRUE;
  1443. }
  1444. CloseHandle( ppdOld->hTok );
  1445. ppdOld->hTok = NULL;
  1446. }
  1447. return fRet;
  1448. }
  1449. /*
  1450. * VirtualMemReconcileState
  1451. *
  1452. * Reconciles the n*FileSizePrev fields of apf with the n*FileSize fields.
  1453. *
  1454. */
  1455. void
  1456. VirtualMemReconcileState(
  1457. )
  1458. {
  1459. INT i;
  1460. for (i = 0; i < MAX_DRIVES; i++) {
  1461. apf[i].nMinFileSizePrev = apf[i].nMinFileSize;
  1462. apf[i].nMaxFileSizePrev = apf[i].nMaxFileSize;
  1463. apf[i].fRamBasedPrev = apf[i].fRamBasedPagefile;
  1464. } // for
  1465. }
  1466. /*
  1467. * VirtualMemDeletePagefile
  1468. *
  1469. * Hack workaround -- MoveFileEx() is broken.
  1470. *
  1471. */
  1472. DWORD
  1473. VirtualMemDeletePagefile(
  1474. IN LPTSTR pszPagefile
  1475. )
  1476. {
  1477. HKEY hKey;
  1478. BOOL fhKeyOpened = FALSE;
  1479. DWORD dwResult;
  1480. LONG lResult;
  1481. LPTSTR pszBuffer = NULL;
  1482. LPTSTR pszBufferEnd = NULL;
  1483. DWORD dwValueType;
  1484. DWORD cbRegistry;
  1485. DWORD cbBuffer;
  1486. DWORD cchPagefile;
  1487. DWORD dwRetVal = ERROR_SUCCESS;
  1488. __try {
  1489. cchPagefile = lstrlen(pszPagefile) + 1;
  1490. lResult = RegOpenKeyEx(
  1491. HKEY_LOCAL_MACHINE,
  1492. szSessionManager,
  1493. 0L,
  1494. KEY_READ | KEY_WRITE,
  1495. &hKey
  1496. );
  1497. if (ERROR_SUCCESS != lResult) {
  1498. dwRetVal = lResult;
  1499. __leave;
  1500. } // if
  1501. //
  1502. // Find out of PendingFileRenameOperations exists, and,
  1503. // if it does, how big it is
  1504. //
  1505. lResult = SHRegGetValue(
  1506. hKey,
  1507. NULL,
  1508. szPendingRename,
  1509. SRRF_RT_REG_SZ | SRRF_RT_REG_EXPAND_SZ | SRRF_NOEXPAND,
  1510. &dwValueType,
  1511. (LPBYTE) NULL,
  1512. &cbRegistry
  1513. );
  1514. if (ERROR_SUCCESS != lResult) {
  1515. //
  1516. // If the value doesn't exist, we still need to set
  1517. // it's size to one character so the formulas below (which are
  1518. // written for the "we're appending to an existing string"
  1519. // case) still work.
  1520. //
  1521. cbRegistry = sizeof(TCHAR);
  1522. } // if
  1523. //
  1524. // Buffer needs to hold the existing registry value
  1525. // plus the supplied pagefile path, plus two extra
  1526. // terminating NULL characters. However, we only have to add
  1527. // room for one extra character, because we'll be overwriting
  1528. // the terminating NULL character in the existing buffer.
  1529. //
  1530. cbBuffer = cbRegistry + ((cchPagefile + 1) * sizeof(TCHAR));
  1531. pszBufferEnd = pszBuffer = (LPTSTR) LocalAlloc(LPTR, cbBuffer);
  1532. if (!pszBuffer) {
  1533. dwRetVal = ERROR_NOT_ENOUGH_MEMORY;
  1534. __leave;
  1535. } // if
  1536. //
  1537. // Grab the existing value, if there is one
  1538. //
  1539. if (ERROR_SUCCESS == lResult) {
  1540. lResult = SHRegGetValue(
  1541. hKey,
  1542. NULL,
  1543. szPendingRename,
  1544. SRRF_RT_REG_SZ | SRRF_RT_REG_EXPAND_SZ | SRRF_NOEXPAND,
  1545. &dwValueType,
  1546. (LPBYTE) pszBuffer,
  1547. &cbRegistry
  1548. );
  1549. if (ERROR_SUCCESS != lResult) {
  1550. dwRetVal = ERROR_FILE_NOT_FOUND;
  1551. __leave;
  1552. } // if
  1553. //
  1554. // We'll start our scribbling right on the final
  1555. // terminating NULL character of the existing
  1556. // value.
  1557. //
  1558. pszBufferEnd += (cbRegistry / sizeof(TCHAR)) - 1;
  1559. } // if
  1560. //
  1561. // Copy in the supplied pagefile path.
  1562. //
  1563. if (FAILED(StringCchCopy(pszBufferEnd, cchPagefile, pszPagefile)))
  1564. {
  1565. dwRetVal = ERROR_INSUFFICIENT_BUFFER;
  1566. }
  1567. else
  1568. {
  1569. //
  1570. // Add the final two terminating NULL characters
  1571. // required for REG_MULTI_SZ-ness. Yes, those indeces
  1572. // are correct--when cchPagfile was calculated above,
  1573. // we added one for its own terminating NULL character.
  1574. //
  1575. pszBufferEnd[cchPagefile] = TEXT('\0');
  1576. pszBufferEnd[cchPagefile + 1] = TEXT('\0');
  1577. dwValueType = REG_MULTI_SZ;
  1578. lResult = RegSetValueEx(
  1579. hKey,
  1580. szPendingRename,
  1581. 0L,
  1582. dwValueType,
  1583. (CONST BYTE *) pszBuffer,
  1584. cbBuffer
  1585. );
  1586. if (ERROR_SUCCESS != lResult) {
  1587. dwRetVal = lResult;
  1588. } // if
  1589. }
  1590. } // __try
  1591. __finally {
  1592. if (fhKeyOpened)
  1593. {
  1594. RegCloseKey(hKey);
  1595. } // if
  1596. LocalFree(pszBuffer);
  1597. } // __finally
  1598. return dwRetVal;
  1599. }
  1600. /*
  1601. * VirtualMemCreatePagefileFromIndex
  1602. *
  1603. *
  1604. */
  1605. NTSTATUS
  1606. VirtualMemCreatePagefileFromIndex(
  1607. IN INT i
  1608. )
  1609. {
  1610. UNICODE_STRING us;
  1611. LARGE_INTEGER liMin, liMax;
  1612. NTSTATUS status;
  1613. WCHAR wszPath[MAX_PATH*2];
  1614. TCHAR szDrive[3];
  1615. DWORD cch;
  1616. HourGlass(TRUE);
  1617. PathBuildRoot(szDrive, i);
  1618. szDrive[2] = 0;
  1619. cch = QueryDosDevice( szDrive, wszPath, ARRAYSIZE(wszPath));
  1620. if (cch != 0) {
  1621. // Concat the filename only (skip 'd:') to the nt device
  1622. // path, and convert it to a UNICODE_STRING
  1623. if (FAILED(StringCchCat(wszPath, ARRAYSIZE(wszPath), SZPageFileName(i) + 2)))
  1624. {
  1625. status = STATUS_BUFFER_OVERFLOW;
  1626. }
  1627. else
  1628. {
  1629. status = RtlInitUnicodeStringEx( &us, wszPath );
  1630. if (status != STATUS_NAME_TOO_LONG)
  1631. {
  1632. liMin.QuadPart = ((LONGLONG)apf[i].nMinFileSize) * ONE_MEG;
  1633. liMax.QuadPart = ((LONGLONG)apf[i].nMaxFileSize) * ONE_MEG;
  1634. status = NtCreatePagingFile ( &us, &liMin, &liMax, 0L );
  1635. }
  1636. }
  1637. }
  1638. else
  1639. {
  1640. status = STATUS_NO_SUCH_DEVICE;
  1641. }
  1642. HourGlass(FALSE);
  1643. return status;
  1644. }
  1645. /*
  1646. * VirtualMemUpdateListboxFromIndex
  1647. *
  1648. */
  1649. void
  1650. VirtualMemUpdateListboxFromIndex(
  1651. HWND hDlg,
  1652. INT i
  1653. )
  1654. {
  1655. int j, cLBEntries, iTemp;
  1656. int iLBEntry = -1;
  1657. TCHAR szTemp[MAX_PATH];
  1658. cLBEntries = (int)SendDlgItemMessage(
  1659. (HWND) hDlg,
  1660. (int) IDD_VM_VOLUMES,
  1661. (UINT) LB_GETCOUNT,
  1662. (WPARAM) 0,
  1663. (LPARAM) 0
  1664. );
  1665. if (LB_ERR != cLBEntries) {
  1666. // Loop through all the listbox entries, looking for the one
  1667. // that corresponds to the drive index we were supplied.
  1668. for (j = 0; j < cLBEntries; j++) {
  1669. iTemp = (int)SendDlgItemMessage(
  1670. (HWND) hDlg,
  1671. (int) IDD_VM_VOLUMES,
  1672. (UINT) LB_GETITEMDATA,
  1673. (WPARAM) j,
  1674. (LPARAM) 0
  1675. );
  1676. if (iTemp == i) {
  1677. iLBEntry = j;
  1678. break;
  1679. } // if
  1680. } // for
  1681. if (-1 != iLBEntry) {
  1682. // Found the desired entry, so update it.
  1683. VirtualMemBuildLBLine(szTemp, ARRAYSIZE(szTemp), i);
  1684. SendDlgItemMessage(
  1685. hDlg,
  1686. IDD_VM_VOLUMES,
  1687. LB_DELETESTRING,
  1688. (WPARAM) iLBEntry,
  1689. 0
  1690. );
  1691. SendDlgItemMessage(
  1692. hDlg,
  1693. IDD_VM_VOLUMES,
  1694. LB_INSERTSTRING,
  1695. (WPARAM) iLBEntry,
  1696. (LPARAM) szTemp
  1697. );
  1698. SendDlgItemMessage(
  1699. hDlg,
  1700. IDD_VM_VOLUMES,
  1701. LB_SETITEMDATA,
  1702. (WPARAM) iLBEntry,
  1703. (LPARAM) i
  1704. );
  1705. SendDlgItemMessage(
  1706. hDlg,
  1707. IDD_VM_VOLUMES,
  1708. LB_SETCURSEL,
  1709. (WPARAM) iLBEntry,
  1710. 0
  1711. );
  1712. if (apf[i].nMinFileSize) {
  1713. SetDlgItemInt(hDlg, IDD_VM_SF_SIZE, apf[i].nMinFileSize, FALSE);
  1714. SetDlgItemInt(hDlg, IDD_VM_SF_SIZEMAX, apf[i].nMaxFileSize, FALSE);
  1715. }
  1716. else {
  1717. SetDlgItemText(hDlg, IDD_VM_SF_SIZE, TEXT(""));
  1718. SetDlgItemText(hDlg, IDD_VM_SF_SIZEMAX, TEXT(""));
  1719. }
  1720. VirtualMemUpdateAllocated(hDlg);
  1721. } // if (-1 != iLBEntry)
  1722. } // if (LB_ERR...
  1723. return;
  1724. }
  1725. /*
  1726. * VirtualMemPromptForReboot
  1727. *
  1728. *
  1729. *
  1730. */
  1731. int
  1732. VirtualMemPromptForReboot(
  1733. HWND hDlg
  1734. )
  1735. {
  1736. INT i, result;
  1737. int iReboot = RET_NO_CHANGE;
  1738. int iThisDrv;
  1739. UNICODE_STRING us;
  1740. LARGE_INTEGER liMin, liMax;
  1741. NTSTATUS status;
  1742. TCHAR szDrive[3];
  1743. PRIVDAT pdOld;
  1744. if (GetPageFilePrivilege(&pdOld))
  1745. {
  1746. // Have to make two passes through the list of pagefiles.
  1747. // The first checks to see if files called "pagefile.sys" exist
  1748. // on any of the drives that will be getting new pagefiles.
  1749. // If there are existing files called "pagefile.sys" and the user
  1750. // doesn't want any one of them to be overwritten, we bail out.
  1751. // The second pass through the list does the actual work of
  1752. // creating the pagefiles.
  1753. for (i = 0; i < MAX_DRIVES; i++) {
  1754. //
  1755. // Did something change?
  1756. //
  1757. if (apf[i].nMinFileSize != apf[i].nMinFileSizePrev ||
  1758. apf[i].nMaxFileSize != apf[i].nMaxFileSizePrev ||
  1759. apf[i].fRamBasedPagefile != apf[i].fRamBasedPrev ||
  1760. apf[i].fCreateFile ) {
  1761. // Assume we have permission to nuke existing files called pagefile.sys
  1762. // (we'll confirm the assumption later)
  1763. result = IDYES;
  1764. if (0 != apf[i].nMinFileSize || FALSE != apf[i].fRamBasedPagefile) { // Pagefile wanted for this drive
  1765. if (0 == apf[i].nMinFileSizePrev) { // There wasn't one there before
  1766. if (!(((GetFileAttributes(SZPageFileName(i)) == 0xFFFFFFFF)) || (GetLastError() == ERROR_FILE_NOT_FOUND))) {
  1767. // A file named pagefile.sys exists on the drive
  1768. // We need to confirm that we can overwrite it
  1769. result = MsgBoxParam(
  1770. hDlg,
  1771. IDS_SYSDM_OVERWRITE,
  1772. IDS_SYSDM_TITLE,
  1773. MB_ICONQUESTION | MB_YESNO,
  1774. SZPageFileName(i)
  1775. );
  1776. } // if (!((GetFileAttributes...
  1777. } // if (0 == apf[i].nMinFileSizePrev)
  1778. if (IDYES != result) {
  1779. // User doesn't want us overwriting an existing
  1780. // file called pagefile.sys, so back out the changes
  1781. apf[i].nMinFileSize = apf[i].nMinFileSizePrev;
  1782. apf[i].nMaxFileSize = apf[i].nMaxFileSizePrev;
  1783. apf[i].fRamBasedPagefile = apf[i].fRamBasedPrev;
  1784. apf[i].fCreateFile = FALSE;
  1785. // Update the listbox
  1786. VirtualMemUpdateListboxFromIndex(hDlg, i);
  1787. SetFocus(GetDlgItem(hDlg, IDD_VM_VOLUMES));
  1788. // Bail, telling the DlgProc not to end the dialog
  1789. iReboot = RET_ERROR;
  1790. goto bailout;
  1791. } // if (IDYES != result)
  1792. } // if (0 != apf[i].nMinFileSize)
  1793. } // if
  1794. } // for
  1795. for (i = 0; i < MAX_DRIVES; i++)
  1796. {
  1797. //
  1798. // Did something change?
  1799. //
  1800. if (apf[i].nMinFileSize != apf[i].nMinFileSizePrev ||
  1801. apf[i].nMaxFileSize != apf[i].nMaxFileSizePrev ||
  1802. apf[i].fRamBasedPagefile != apf[i].fRamBasedPrev ||
  1803. apf[i].fCreateFile ) {
  1804. /*
  1805. * If we are strictly creating a *new* page file, or *enlarging*
  1806. * the minimum or maximum size of an existing page file, then
  1807. * we can try do it on the fly. If no errors are returned by
  1808. * the system then no reboot will be required.
  1809. */
  1810. // assume we will have to reboot
  1811. iThisDrv = RET_VIRTUAL_CHANGE;
  1812. /*
  1813. * IF we are creating a new page file
  1814. */
  1815. if ((0 != apf[i].nMinFileSize || FALSE != apf[i].fRamBasedPagefile) && (0 == apf[i].nMinFileSizePrev)) {
  1816. status = VirtualMemCreatePagefileFromIndex(i);
  1817. if (NT_SUCCESS(status)) {
  1818. // made it on the fly, no need to reboot for this drive!
  1819. iThisDrv = RET_CHANGE_NO_REBOOT;
  1820. }
  1821. }
  1822. /*
  1823. * If we're enlarging the minimum or maximum size of an existing
  1824. * page file, we can try to do it on the fly
  1825. */
  1826. else if ((apf[i].nMinFileSize != 0) &&
  1827. ((apf[i].nMinFileSize > apf[i].nMinFileSizePrev) ||
  1828. (apf[i].nMaxFileSize > apf[i].nMaxFileSizePrev))) {
  1829. status = VirtualMemCreatePagefileFromIndex(i);
  1830. if (NT_SUCCESS(status)) {
  1831. iThisDrv = RET_CHANGE_NO_REBOOT;
  1832. }
  1833. } /* else if */
  1834. // if this drive has changed, we must reboot
  1835. if (RET_VIRTUAL_CHANGE == iThisDrv)
  1836. {
  1837. iReboot |= RET_VIRTUAL_CHANGE;
  1838. }
  1839. }
  1840. }
  1841. bailout:
  1842. if (!ResetOldPrivilege( &pdOld ))
  1843. {
  1844. iReboot = RET_BREAK;
  1845. }
  1846. }
  1847. //
  1848. // If Nothing changed, then change our IDOK to IDCANCEL so System.cpl will
  1849. // know not to reboot.
  1850. //
  1851. return iReboot;
  1852. }