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.

828 lines
18 KiB

  1. /*** ClearMem.C - Win 32 clear memory
  2. *
  3. *
  4. * Title:
  5. *
  6. * ClearMem - Win 32 clear memory Main File
  7. *
  8. * Copyright (c) 1990-1994, Microsoft Corporation.
  9. * Russ Blake.
  10. *
  11. *
  12. * Description:
  13. *
  14. * This is the main part of the clear memory tool.
  15. * It takes as a parameter a file to use to flush the memory.
  16. *
  17. * Usage: clearmem filename [-q] [-d]
  18. *
  19. * filename: name of file to use to flush the
  20. * memory. Should be at least 128kb.
  21. *
  22. *
  23. * The Clear Memory is organized as follows:
  24. *
  25. * o ClearMem.c ........ Tools main body
  26. * o ClearMem.h
  27. *
  28. * o cmUtl.c ..... clear memory utility routines
  29. * o cmUtl.h
  30. *
  31. *
  32. *
  33. *
  34. *
  35. *
  36. * Modification History:
  37. *
  38. * 90.03.08 RussBl -- Created (copy of response probe)
  39. * 92.07.24 MarkLea -- Added -t -w -b switches
  40. * -- Modified AccessSection algorithm.
  41. * 93.05.12 HonWahChan
  42. * -- used total physical memory (instead of SECTION_SIZE);
  43. * -- used GetTickCount() instead of timer calls.
  44. *
  45. *
  46. */
  47. char *VERSION = "1.17x (93.05.12)";
  48. /* * * * * * * * * * * * * I N C L U D E F I L E S * * * * * * * * * * */
  49. #include <stdio.h>
  50. #include <stdlib.h>
  51. #include <string.h>
  52. #include <malloc.h>
  53. #include <time.h>
  54. #include <nt.h>
  55. #include <ntrtl.h>
  56. #include <nturtl.h>
  57. #include <windows.h>
  58. #include "clearmem.h"
  59. #include "cmUtl.h"
  60. /* * * * * * * * * * G L O B A L D E C L A R A T I O N S * * * * * * * * */
  61. /* none */
  62. /* * * * * * * * * * F U N C T I O N P R O T O T Y P E S * * * * * * * * */
  63. __cdecl main (int argc, char *argv[]);
  64. STATIC RC Initialize (int argc, char *argv[]);
  65. STATIC RC Cleanup (void);
  66. STATIC RC FlushCache (void);
  67. STATIC RC AccessSection (void);
  68. STATIC RC ReadFlushFile (void);
  69. void ParseCmdLine (int argc, char *argv[]);
  70. void Usage (char *argv[], char *);
  71. /* * * * * * * * * * * G L O B A L V A R I A B L E S * * * * * * * * * */
  72. BOOL bQuiet,
  73. bRead = TRUE,
  74. bWrite;
  75. BOOL bDebugBreakOnEntry;
  76. ULONG ulMemSize,
  77. ulPageCount,
  78. ulTouchCount = 1;
  79. ULONG_PTR ulSectionSize;
  80. /* * * * * * E X P O R T E D G L O B A L V A R I A B L E S * * * * * */
  81. /* none */
  82. /********************************* m a i n **********************************
  83. *
  84. * main(argc, argv)
  85. *
  86. * ENTRY argc - number of input arguments
  87. * argv - contains command line arguments
  88. *
  89. * EXIT -none-
  90. *
  91. * RETURN rc - return code in case of failure
  92. * STATUS_SUCCESS - if successful
  93. *
  94. * WARNING:
  95. * -none-
  96. *
  97. * COMMENT:
  98. * -none-
  99. *
  100. */
  101. __cdecl main (int argc, char *argv[])
  102. {
  103. RC rc;
  104. DWORD ulFlushTime; // Total time for flushing
  105. ParseCmdLine (argc, argv);
  106. if(ulMemSize){
  107. ulSectionSize = ulMemSize * 1024 * 1024;
  108. }
  109. else {
  110. // get total physical memory size in the system
  111. MEMORYSTATUS MemStat;
  112. GlobalMemoryStatus (&MemStat);
  113. ulSectionSize = MemStat.dwTotalPhys;
  114. }
  115. // ExitProcess(STATUS_SUCCESS);
  116. if (bDebugBreakOnEntry)
  117. DebugBreak();
  118. if (!bQuiet) {
  119. //
  120. // set initial total flushing time
  121. //
  122. ulFlushTime = GetTickCount() ;
  123. }
  124. //
  125. // Do initialization
  126. //
  127. rc = Initialize(argc, argv);
  128. if (Failed(rc, __FILE__, __LINE__, "main() - Initialize")) {
  129. return(rc);
  130. }
  131. //
  132. // Now flush the cache
  133. //
  134. rc = FlushCache();
  135. if (Failed(rc, __FILE__, __LINE__, "main() - FlushCache")) {
  136. return(rc);
  137. }
  138. if (!bQuiet) {
  139. ulFlushTime = GetTickCount() - ulFlushTime;
  140. printf("Elapsed Time for Flushing: %lu milliseconds \n", ulFlushTime);
  141. }
  142. //
  143. // Cleanup
  144. //
  145. rc = Cleanup();
  146. if (Failed(rc, __FILE__, __LINE__, "main() - Cleanup")) {
  147. return(rc);
  148. }
  149. #ifdef CF_DEBUG_L1
  150. if (!bQuiet) {
  151. printf("| ==> Exiting PROCESS: %s \n", CF_EXE );
  152. }
  153. #endif
  154. if (bDebugBreakOnEntry)
  155. DebugBreak();
  156. ExitProcess(STATUS_SUCCESS);
  157. } /* main() */
  158. /*************************** I n i t i a l i z e ****************************
  159. *
  160. * Initialize(argc, argv) -
  161. * Performs basic initializations (getting input arguments,
  162. * creating semaphores, display debug info, ...)
  163. *
  164. * ENTRY argc - number of input arguments
  165. * argv - list of input arguments
  166. *
  167. * EXIT -none-
  168. *
  169. * RETURN rc - return code in case of failure
  170. * STATUS_SUCCESS - if successful
  171. *
  172. * WARNING:
  173. * -none-
  174. *
  175. * COMMENT:
  176. * -none-
  177. *
  178. */
  179. STATIC RC Initialize (int argc, char *argv[])
  180. {
  181. int i;
  182. //
  183. // Sign on message
  184. //
  185. if (!bQuiet) {
  186. printf("\nNT Win 32 Clear Memory.\n"
  187. "Copyright 1990-1993, Microsoft Corporation.\n"
  188. "Version %s\n\n", VERSION);
  189. }
  190. #ifdef CF_DEBUG_L1
  191. //
  192. // Display debugging info
  193. //
  194. if (!bQuiet) {
  195. printf("/-------------------------------\n");
  196. printf("| %s:\n", CF_EXE);
  197. printf("|\n");
  198. for (i=0; i<argc; i++) {
  199. printf("| o argv[%i]=%s\n", i, argv[i]);
  200. }
  201. printf("\\-------------------------------\n");
  202. }
  203. #else
  204. i; // Prevent compiler from complaining about unreferenced variable
  205. #endif
  206. return(STATUS_SUCCESS);
  207. } /* Initialize() */
  208. /****************************** C l e a n u p *******************************
  209. *
  210. * Cleanup(void) -
  211. * Basic cleanup. (closing semaphores, freeing memory, ...)
  212. *
  213. * ENTRY -none-
  214. *
  215. * EXIT -none-
  216. *
  217. * RETURN rc - return code in case of failure
  218. * STATUS_SUCCESS - if successful
  219. *
  220. * WARNING:
  221. * -none-
  222. *
  223. * COMMENT:
  224. * -none-
  225. *
  226. */
  227. STATIC RC Cleanup (void)
  228. {
  229. return(STATUS_SUCCESS);
  230. } /* Cleanup() */
  231. /************************ F l u s h C a c h e *****************************
  232. *
  233. * FlushCache(void) -
  234. * Flushes the file cache by createing a large data
  235. * segment, and touching every page to shrink the cache
  236. * to 128kb, then reading in a 128kb file to clear the
  237. * remaining cache
  238. *
  239. * ENTRY -none-
  240. *
  241. * EXIT -none-
  242. *
  243. * RETURN rc - return code in case of failure
  244. * STATUS_SUCCESS - if successful
  245. *
  246. * WARNING:
  247. * -none-
  248. *
  249. * COMMENT:
  250. * -none-
  251. *
  252. */
  253. RC FlushCache (void)
  254. {
  255. RC rc;
  256. //
  257. // First touch all the data pages
  258. //
  259. #ifdef CF_DEBUG_L1
  260. if (!bQuiet) {
  261. printf("| ==> Start Flushing: Access Section of size: %lu \n",
  262. ulSectionSize );
  263. }
  264. #endif
  265. rc = AccessSection();
  266. if (Failed(rc, __FILE__, __LINE__, "FlushCache() - AccessSection")) {
  267. return(rc);
  268. }
  269. //
  270. // Next read the flushing file to what's left of the cache
  271. //
  272. #ifdef CF_DEBUG_L1
  273. if (!bQuiet) {
  274. printf("| ==> Start Flushing: Read File: %s \n",
  275. "FLUSH1" );
  276. }
  277. #endif
  278. // while (ulTouchCount) {
  279. rc = ReadFlushFile();
  280. // --ulTouchCount;
  281. if (Failed(rc, __FILE__, __LINE__, "FlushCache() - Read Flush File")) {
  282. return(rc);
  283. }
  284. // }
  285. return(STATUS_SUCCESS);
  286. } /* FlushCache() */
  287. /************************ A c c e s s S e c t i o n ************************
  288. *
  289. * AccessSection(void) -
  290. * Touches every page in the data section
  291. *
  292. * ENTRY -none-
  293. *
  294. * EXIT -none-
  295. *
  296. * RETURN rc - return code in case of failure
  297. * STATUS_SUCCESS - if successful
  298. *
  299. * WARNING:
  300. * -none-
  301. *
  302. * COMMENT:
  303. * -none-
  304. *
  305. */
  306. RC AccessSection (void)
  307. {
  308. RC rc;
  309. ULONG uli,
  310. ulj;
  311. PULONG puSectionData; //Points to data section for flushing memory
  312. //
  313. // Allocate virtual memory
  314. //
  315. if ( (puSectionData = (PULONG)VirtualAlloc(NULL, // New allocation
  316. ulSectionSize, // Size in bytes
  317. MEM_RESERVE | MEM_COMMIT,
  318. PAGE_READWRITE)) == NULL ) { //Changed to READWRITE
  319. rc = GetLastError();
  320. Failed(rc, __FILE__, __LINE__, "AccessSection() - VirtualAlloc");
  321. return(rc);
  322. }
  323. //
  324. // Now touch every page of the section
  325. //
  326. if(bWrite){
  327. while (ulTouchCount) {
  328. puSectionData = &puSectionData[0];
  329. for ( uli = 0; uli < (ulSectionSize-1); uli+=sizeof(ULONG)) {
  330. *puSectionData = 0xFFFFFFFF;
  331. ++puSectionData;
  332. }
  333. --ulTouchCount;
  334. }
  335. }
  336. if(bRead) {
  337. // DbgBreakPoint();
  338. ulj = 0;
  339. while (ulTouchCount) {
  340. for ( uli = 0; uli < ulSectionSize; uli += PAGESIZE ) {
  341. ulj += *(puSectionData+(uli/sizeof(ULONG)));
  342. }
  343. --ulTouchCount;
  344. }
  345. }
  346. return(STATUS_SUCCESS);
  347. } /* AccessSection() */
  348. /************************ R e a d F l u s h F i l e ************************
  349. *
  350. * ReadFlushFile(void) -
  351. * Touches every page in the flush file, non-sequentially
  352. *
  353. * ENTRY -none-
  354. *
  355. * EXIT -none-
  356. *
  357. * RETURN rc - return code in case of failure
  358. * STATUS_SUCCESS - if successful
  359. *
  360. * WARNING:
  361. * -none-
  362. *
  363. * COMMENT:
  364. * -none-
  365. *
  366. */
  367. CHAR chBuffer[PAGESIZE];
  368. RC ReadFlushFile (void)
  369. {
  370. RC rc;
  371. SHORT sNewPos;
  372. ULONG uli;
  373. ULONG ulNumReads,
  374. ulNumBytesRead;
  375. BOOL bFileCreated;
  376. SHORT sFile; // Indicates which of the three
  377. // files is being used to flush
  378. CHAR chFlushFileName1[] = "FLUSH1";
  379. CHAR chFlushFileName2[] = "FLUSH2";
  380. CHAR chFlushFileName3[] = "FLUSH3";
  381. CHAR *pchFlushFileName[3] = { chFlushFileName1,
  382. chFlushFileName2,
  383. chFlushFileName3 };
  384. FILE *pfFlushFile; // Points to the file used for
  385. // flushing the cache
  386. FILE *pfSaveFile[3]; // Remembers them for the close
  387. CHAR achErrMsg[LINE_LEN];
  388. //
  389. // Assume no file is created: all three already exist
  390. //
  391. bFileCreated = FALSE;
  392. for (sFile = 0; sFile < NUM_FILES; sFile++) {
  393. //
  394. // First attempt to create the file
  395. //
  396. if ( (pfFlushFile = CreateFile(pchFlushFileName[sFile],
  397. GENERIC_WRITE,
  398. FILE_SHARE_READ,
  399. NULL,
  400. CREATE_NEW,
  401. 0,
  402. 0))
  403. == INVALID_HANDLE_VALUE ) {
  404. //
  405. // Could not create the file
  406. //
  407. rc = GetLastError();
  408. if (!(rc == ERROR_FILE_EXISTS || rc == ERROR_ACCESS_DENIED)) {
  409. //
  410. // Cannot create a new file
  411. //
  412. sprintf(achErrMsg,
  413. "ReadFlushFile() - Error creating %s: %lu",
  414. pchFlushFileName[sFile], rc);
  415. Failed(FILEARG_ERR, __FILE__, __LINE__, achErrMsg);
  416. return(FILEARG_ERR);
  417. }
  418. }
  419. else {
  420. //
  421. // New file has been created without difficulty
  422. // Fill it with data
  423. //
  424. bFileCreated = TRUE;
  425. for (uli = 0; uli < FLUSH_FILE_SIZE; uli += PAGESIZE) {
  426. if (!WriteFile(pfFlushFile,
  427. &chBuffer,
  428. PAGESIZE,
  429. &ulNumBytesRead,
  430. RESERVED_NULL)) {
  431. rc = GetLastError();
  432. Failed(rc, __FILE__, __LINE__,
  433. "ReadFlushFile() - Write File Record to New File");
  434. return(rc);
  435. }
  436. }
  437. //
  438. // Now close it for write, so we can open it for read access
  439. //
  440. if (!CloseHandle(pfFlushFile)) {
  441. rc = GetLastError();
  442. sprintf(achErrMsg, "ReadFlushFile() - Error closing %s: %lu",
  443. pchFlushFileName[sFile], rc);
  444. Failed(FILEARG_ERR, __FILE__, __LINE__, achErrMsg);
  445. return(FILEARG_ERR);
  446. }
  447. }
  448. }
  449. if (bFileCreated) {
  450. //
  451. // Wrote at least 1 file: wait for lazy writer to flush
  452. // data to disk
  453. //
  454. Sleep(LAZY_DELAY);
  455. }
  456. for (sFile = 0; sFile < NUM_FILES; sFile++) {
  457. if ((pfFlushFile = CreateFile( pchFlushFileName[sFile],
  458. GENERIC_READ,
  459. FILE_SHARE_READ,
  460. NULL,
  461. OPEN_EXISTING,
  462. 0,
  463. 0))
  464. == INVALID_HANDLE_VALUE) {
  465. //
  466. // Cannot open an existing file
  467. //
  468. rc = GetLastError();
  469. sprintf(achErrMsg,
  470. "ReadFlushFile() - Error opening %s: %lu",
  471. pchFlushFileName[sFile], rc);
  472. Failed(FILEARG_ERR, __FILE__, __LINE__, achErrMsg);
  473. return(FILEARG_ERR);
  474. }
  475. //
  476. // Remember the handle for the close
  477. //
  478. pfSaveFile[sFile] = pfFlushFile;
  479. //
  480. // Read first record
  481. //
  482. if (!ReadFile( pfFlushFile,
  483. &chBuffer,
  484. 1,
  485. &ulNumBytesRead,
  486. RESERVED_NULL)) {
  487. rc = GetLastError();
  488. Failed(rc, __FILE__, __LINE__,
  489. "ReadFlushFile() - Read First Record");
  490. return(rc);
  491. }
  492. ulNumReads = 1;
  493. while (++ulNumReads <= ulPageCount) {
  494. if (ulNumReads & 1) {
  495. //
  496. // Read an odd record: read previous record
  497. // Move backward to start of prior record: -1 (start of
  498. // this record) -4096 (start of previous record) = -4097
  499. //
  500. if (SetFilePointer( pfFlushFile, -4097, 0L, FILE_CURRENT) == (DWORD)-1) {
  501. rc = GetLastError();
  502. Failed(rc, __FILE__, __LINE__,
  503. "ReadFlushFile() - Read Odd Record");
  504. return(rc);
  505. }
  506. if (!ReadFile( pfFlushFile,
  507. &chBuffer,
  508. 1,
  509. &ulNumBytesRead,
  510. RESERVED_NULL)) {
  511. rc = GetLastError();
  512. if (rc == ERROR_HANDLE_EOF)
  513. break;
  514. Failed(rc, __FILE__, __LINE__,
  515. "ReadFlushFile() - SetPos Odd Record");
  516. return(rc);
  517. }
  518. }
  519. else {
  520. //
  521. // Read an even record: read the one after the next record
  522. // Move forward to end of this record (4095) + 2 more
  523. // (8192) = 12287. (But second record is special, 'cause
  524. // can't set file pointer negative initially.)
  525. //
  526. sNewPos = (SHORT) (ulNumReads == 2L ? 8191 : 12287);
  527. if (SetFilePointer( pfFlushFile, sNewPos, 0L, FILE_CURRENT) == (DWORD) -1) {
  528. rc = GetLastError();
  529. Failed(rc, __FILE__, __LINE__,
  530. "ReadFlushFile() - Read Even Record");
  531. return(rc);
  532. }
  533. if (!ReadFile( pfFlushFile,
  534. &chBuffer,
  535. 1,
  536. &ulNumBytesRead,
  537. RESERVED_NULL)) {
  538. rc = GetLastError();
  539. if (rc == ERROR_HANDLE_EOF)
  540. break;
  541. Failed(rc, __FILE__, __LINE__,
  542. "ReadFlushFile() - SetPos Even Record");
  543. return(rc);
  544. }
  545. }
  546. }
  547. }
  548. for (sFile = 0; sFile < NUM_FILES; sFile++) {
  549. //
  550. // Close the files
  551. //
  552. if (!CloseHandle(pfSaveFile[sFile])) {
  553. rc = GetLastError();
  554. sprintf(achErrMsg, "ReadFlushFile() - Error closing %s: %lu",
  555. pchFlushFileName[sFile], rc);
  556. Failed(FILEARG_ERR, __FILE__, __LINE__, achErrMsg);
  557. return(FILEARG_ERR);
  558. }
  559. }
  560. return(STATUS_SUCCESS);
  561. } /* ReadFlushFile() */
  562. /************************ R e a d F l u s h F i l e ************************
  563. *
  564. * parseCmdLine(void) -
  565. * For Parsing the command line switches
  566. *
  567. * ENTRY -none-
  568. *
  569. * EXIT -none-
  570. *
  571. * RETURN -none-
  572. *
  573. * WARNING:
  574. * -none-
  575. *
  576. * COMMENT:
  577. * -none-
  578. *
  579. */
  580. VOID ParseCmdLine (int argc, char *argv[])
  581. {
  582. char *pchParam;
  583. int iParamCount;
  584. for ( iParamCount = 1; iParamCount < argc; iParamCount++) {
  585. if (argv[iParamCount][0] == '-') { /* process options */
  586. pchParam = &(argv[iParamCount][1]);
  587. while (*pchParam) {
  588. switch (*pchParam) {
  589. case '?':
  590. Usage (argv, " ");
  591. break;
  592. case 'Q':
  593. case 'q':
  594. pchParam++;
  595. bQuiet = TRUE;
  596. break;
  597. case 'd':
  598. case 'D': /* print banner */
  599. pchParam++;
  600. bDebugBreakOnEntry = TRUE;
  601. break;
  602. case 'm':
  603. case 'M':
  604. ulMemSize = (ULONG)atol(&pchParam[1]);
  605. if (ulPageCount > 32) {
  606. Usage (argv, "Mem size must be less than the amount of physical memory!");
  607. }
  608. pchParam += strlen(pchParam);
  609. break;
  610. case 'p':
  611. case 'P':
  612. ulPageCount = (ULONG)atol(&pchParam[1]);
  613. if (ulPageCount > 63) {
  614. Usage (argv, "Page Count must be 63 or less!");
  615. }
  616. pchParam += strlen(pchParam);
  617. break;
  618. case 't':
  619. case 'T':
  620. ulTouchCount = (ULONG)atol(&pchParam[1]);
  621. pchParam += strlen(pchParam);
  622. break;
  623. case 'w':
  624. case 'W':
  625. bWrite = TRUE;
  626. bRead = FALSE;
  627. break;
  628. case 'b':
  629. case 'B':
  630. bRead = TRUE;
  631. bWrite = TRUE;
  632. break;
  633. default:
  634. Usage (argv, "unknown flag");
  635. break;
  636. } // end of switch
  637. } // end of while
  638. } // end of if
  639. } // end of for...
  640. if(!ulPageCount){
  641. ulPageCount = NUM_FLUSH_READS;
  642. }
  643. return;
  644. }
  645. /*
  646. *
  647. * Usage - generates a usage message and an error message
  648. * and terminates program.
  649. *
  650. * Accepts - argv - char *[]
  651. * message - char * - an error message
  652. *
  653. * Returns - nothing.
  654. *
  655. */
  656. VOID Usage (char *argv[], char *message)
  657. {
  658. printf( "%s\n", message);
  659. printf( "usage: ");
  660. printf( "%s [-q] [-d] [-mx] [-px] [-w] [-tx]\n", argv[0]);
  661. printf( "\t-? : This message\n");
  662. printf( "\t-q : Quiet mode - Nothing printed.\n");
  663. printf( "\t-d : Debug break on Entry into and Exit from app.\n");
  664. printf( "\t-m : Number of megabytes to allocate.\n");
  665. printf( "\t : (default is to use all physical memory.)\n");
  666. printf( "\t-p : Number of pages to read (must be less than 63).\n");
  667. printf( "\t-w : Write to the virtual memory section.\n");
  668. printf( "\t-b : Read and Write the virtual memory section.\n");
  669. printf( "\t-t : Times to touch a page.\n");
  670. printf( "**DEFAULT: clearmem -p63 -t1\n");
  671. exit (1);
  672. }
  673.