Source code of Windows XP (NT5)
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.

742 lines
20 KiB

  1. /*++
  2. Copyright (c) 1989-1999 Microsoft Corporation
  3. Module Name:
  4. ioTestUserSup.c
  5. Abstract:
  6. // @@BEGIN_DDKSPLIT
  7. Author:
  8. George Jenkins (GeorgeJe)
  9. // @@END_DDKSPLIT
  10. Environment:
  11. User mode
  12. // @@BEGIN_DDKSPLIT
  13. Revision History:
  14. Molly Brown (MollyBro) 21-Apr-1999
  15. Broke out the logging code and added command mode functionality.
  16. // @@END_DDKSPLIT
  17. --*/
  18. #include <windows.h>
  19. #include <stdlib.h>
  20. #include <stdio.h>
  21. #include <winioctl.h>
  22. #include <string.h>
  23. #include <crtdbg.h>
  24. #include "ioTest.h"
  25. #include "ioTestLog.h"
  26. #include "ioTestLib.h"
  27. #define NT_SUCCESS(Status) ((LONG)(Status) >= 0)
  28. #define TEST_DIRECTORY_NAME L"\\ioTest"
  29. #define READ_TEST_FILE_NAME TEST_DIRECTORY_NAME L"\\read.txt"
  30. #define READ_TEST_DATA L"Hello world!"
  31. EXPECTED_OPERATION gExpectedReadOperationsTop[] = { { TOP_FILTER, IRP_MJ_CREATE },
  32. { BOTTOM_FILTER, IRP_MJ_CREATE },
  33. { TOP_FILTER, IRP_MJ_READ },
  34. { BOTTOM_FILTER, IRP_MJ_READ },
  35. { TOP_FILTER, IRP_MJ_CLEANUP },
  36. { BOTTOM_FILTER, IRP_MJ_CLEANUP },
  37. { BOTTOM_FILTER, IRP_MJ_MAXIMUM_FUNCTION + 1 } };
  38. EXPECTED_OPERATION gExpectedReadOperationsDirected[] = { { BOTTOM_FILTER, IRP_MJ_CREATE },
  39. { BOTTOM_FILTER, IRP_MJ_READ },
  40. { BOTTOM_FILTER, IRP_MJ_CLEANUP },
  41. { BOTTOM_FILTER, IRP_MJ_MAXIMUM_FUNCTION + 1 } };
  42. #define WRITE_TEST_FILE_NAME TEST_DIRECTORY_NAME L"\\write.txt"
  43. #define WRITE_TEST_DATA L"Good morning!"
  44. EXPECTED_OPERATION gExpectedWriteOperationsTop[] = { { TOP_FILTER, IRP_MJ_CREATE },
  45. { BOTTOM_FILTER, IRP_MJ_CREATE },
  46. { TOP_FILTER, IRP_MJ_WRITE },
  47. { BOTTOM_FILTER, IRP_MJ_WRITE },
  48. { TOP_FILTER, IRP_MJ_CLEANUP },
  49. { BOTTOM_FILTER, IRP_MJ_CLEANUP },
  50. { BOTTOM_FILTER, IRP_MJ_MAXIMUM_FUNCTION + 1 } };
  51. EXPECTED_OPERATION gExpectedWriteOperationsDirected[] = { { BOTTOM_FILTER, IRP_MJ_CREATE },
  52. { BOTTOM_FILTER, IRP_MJ_WRITE },
  53. { BOTTOM_FILTER, IRP_MJ_CLEANUP },
  54. { BOTTOM_FILTER, IRP_MJ_MAXIMUM_FUNCTION + 1 } };
  55. #define RENAME_SOURCE_FILE_NAME TEST_DIRECTORY_NAME L"\\renameSource.txt"
  56. #define RENAME_TARGET_FILE_NAME TEST_DIRECTORY_NAME L"\\renameTarget.txt"
  57. EXPECTED_OPERATION gExpectedRenameOperationsTop[] = { { TOP_FILTER, IRP_MJ_CREATE },
  58. { BOTTOM_FILTER, IRP_MJ_CREATE },
  59. { TOP_FILTER, IRP_MJ_SET_INFORMATION },
  60. { BOTTOM_FILTER, IRP_MJ_SET_INFORMATION },
  61. { TOP_FILTER, IRP_MJ_CLEANUP },
  62. { BOTTOM_FILTER, IRP_MJ_CLEANUP },
  63. { BOTTOM_FILTER, IRP_MJ_MAXIMUM_FUNCTION + 1 } };
  64. EXPECTED_OPERATION gExpectedRenameOperationsDirected[] = { { BOTTOM_FILTER, IRP_MJ_CREATE },
  65. { BOTTOM_FILTER, IRP_MJ_SET_INFORMATION },
  66. { BOTTOM_FILTER, IRP_MJ_CLEANUP },
  67. { BOTTOM_FILTER, IRP_MJ_MAXIMUM_FUNCTION + 1 } };
  68. #define SHARE_FILE_NAME TEST_DIRECTORY_NAME L"\\share.txt"
  69. EXPECTED_OPERATION gExpectedShareOperationsTop[] = { { TOP_FILTER, IRP_MJ_CREATE },
  70. { BOTTOM_FILTER, IRP_MJ_CREATE },
  71. { TOP_FILTER, IRP_MJ_CLEANUP },
  72. { BOTTOM_FILTER, IRP_MJ_CLEANUP },
  73. { BOTTOM_FILTER, IRP_MJ_MAXIMUM_FUNCTION + 1 } };
  74. EXPECTED_OPERATION gExpectedShareOperationsDirected[] = { { BOTTOM_FILTER, IRP_MJ_CREATE },
  75. { BOTTOM_FILTER, IRP_MJ_CLEANUP },
  76. { BOTTOM_FILTER, IRP_MJ_MAXIMUM_FUNCTION + 1 } };
  77. BOOL
  78. CreateTestDirectory (
  79. PWCHAR DriveName,
  80. ULONG DriveNameLength
  81. )
  82. {
  83. WCHAR testDirName[MAX_PATH];
  84. DWORD result;
  85. BOOL bResult;
  86. if (sizeof( TEST_DIRECTORY_NAME ) + DriveNameLength > MAX_PATH) {
  87. printf ("Can't create test directory -- name buffer too small\n");
  88. return FALSE;
  89. }
  90. wcscpy( testDirName, DriveName );
  91. wcscat( testDirName, TEST_DIRECTORY_NAME );
  92. bResult = CreateDirectory( testDirName,
  93. NULL );
  94. if (!bResult) {
  95. result = GetLastError();
  96. if (result != ERROR_ALREADY_EXISTS) {
  97. DisplayError( result );
  98. return FALSE;
  99. }
  100. }
  101. return TRUE;
  102. }
  103. VOID
  104. DumpTestResultBanner (
  105. PWCHAR TestName,
  106. BOOL Begin
  107. )
  108. {
  109. if (Begin) {
  110. printf( "***BEGIN %S TEST RESULTS***\n", TestName );
  111. } else {
  112. printf( "***END %S TEST RESULTS***\n", TestName );
  113. }
  114. }
  115. VOID
  116. DumpKernelResults (
  117. PIOTEST_STATUS TestStatus
  118. )
  119. {
  120. printf( "Kernel verification: " );
  121. if (NT_SUCCESS( TestStatus->TestResult )) {
  122. printf( "\tTest PASSED\n" );
  123. } else {
  124. switch( TestStatus->Phase ) {
  125. case IoTestSetup:
  126. printf( "\tTest failed in SETUP phase with status 0x%08x\n",
  127. TestStatus->TestResult );
  128. break;
  129. case IoTestAction:
  130. printf( "\tTest failed in ACTION phase with status 0x%08x\n",
  131. TestStatus->TestResult );
  132. break;
  133. case IoTestValidation:
  134. printf( "\tTest failed in VALIDATION phase with status 0x%08x\n",
  135. TestStatus->TestResult );
  136. break;
  137. case IoTestCleanup:
  138. printf( "\tTest failed in CLEANUP phase with status 0x%08x\n",
  139. TestStatus->TestResult );
  140. break;
  141. case IoTestCompleted:
  142. printf( "\tTest failed in COMPLETED phase with status 0x%08x\n",
  143. TestStatus->TestResult );
  144. break;
  145. default:
  146. printf( "\tTest failed in UNKNOWN phase with status 0x%08x\n",
  147. TestStatus->TestResult );
  148. break;
  149. }
  150. }
  151. }
  152. VOID
  153. ReadTest (
  154. PLOG_CONTEXT Context,
  155. PWCHAR DriveName,
  156. ULONG DriveNameLength,
  157. BOOLEAN TopOfStack
  158. )
  159. {
  160. HANDLE testFile = INVALID_HANDLE_VALUE;
  161. PIOTEST_READ_WRITE_PARAMETERS parms = NULL;
  162. DWORD parmsLength;
  163. IOTEST_STATUS testStatus;
  164. BOOL bResult;
  165. DWORD bytesReturned;
  166. DWORD result;
  167. bResult = CreateTestDirectory( DriveName, DriveNameLength );
  168. if (!bResult) {
  169. goto ReadTest_Cleanup;
  170. }
  171. //
  172. // Setup parms
  173. //
  174. parmsLength = sizeof( IOTEST_READ_WRITE_PARAMETERS ) + sizeof( READ_TEST_DATA );
  175. parms = malloc (parmsLength);
  176. if (parms == NULL) {
  177. printf( "Insufficient resources to run READ test\n" );
  178. goto ReadTest_Cleanup;
  179. }
  180. CopyMemory( parms->DriveNameBuffer, DriveName, DriveNameLength );
  181. parms->DriveNameLength = DriveNameLength;
  182. if ((sizeof( READ_TEST_FILE_NAME ) + DriveNameLength) >
  183. MAX_PATH ) {
  184. //
  185. // The READ test file name is longer than our FileNameBuffer,
  186. // so return an error and quit.
  187. //
  188. printf( "READ Test file name is too long.\n" );
  189. goto ReadTest_Cleanup;
  190. }
  191. //
  192. // We've got enough room, so build up the file name.
  193. //
  194. wcscpy( parms->FileNameBuffer, parms->DriveNameBuffer );
  195. wcscat( parms->FileNameBuffer, READ_TEST_FILE_NAME );
  196. parms->FileNameLength = wcslen( parms->FileNameBuffer ) * sizeof( WCHAR );
  197. parms->FileDataLength = sizeof( READ_TEST_DATA );
  198. CopyMemory( parms->FileData, READ_TEST_DATA, parms->FileDataLength );
  199. parms->Flags = 0;
  200. if (TopOfStack) {
  201. parms->Flags |= IO_TEST_TOP_OF_STACK;
  202. }
  203. //
  204. // Create test file
  205. //
  206. testFile = CreateFile( parms->FileNameBuffer,
  207. GENERIC_WRITE,
  208. 0,
  209. NULL,
  210. CREATE_ALWAYS,
  211. FILE_ATTRIBUTE_NORMAL,
  212. NULL );
  213. if (testFile == INVALID_HANDLE_VALUE) {
  214. result = GetLastError();
  215. printf ("Error opening READ test file.\n");
  216. DisplayError( result );
  217. goto ReadTest_Cleanup;
  218. }
  219. //
  220. // Write data to test file
  221. //
  222. bResult = WriteFile( testFile,
  223. READ_TEST_DATA,
  224. sizeof( READ_TEST_DATA ),
  225. &bytesReturned,
  226. NULL );
  227. if (!bResult) {
  228. result = GetLastError();
  229. printf("ERROR writing data READ test file...\n");
  230. DisplayError( result );
  231. goto ReadTest_Cleanup;
  232. }
  233. CloseHandle( testFile );
  234. testFile = INVALID_HANDLE_VALUE;
  235. //
  236. // Send message down to filter
  237. //
  238. bResult = DeviceIoControl( Context->Device,
  239. IOTEST_ReadTest,
  240. parms,
  241. parmsLength,
  242. &testStatus,
  243. sizeof( testStatus ),
  244. &bytesReturned,
  245. NULL);
  246. if (!bResult) {
  247. result = GetLastError();
  248. printf("ERROR running READ test...\n");
  249. DisplayError( result );
  250. goto ReadTest_Cleanup;
  251. }
  252. //
  253. // Print out the result of the kernel verification tests.
  254. //
  255. DumpTestResultBanner( L"READ", TRUE );
  256. DumpKernelResults( &testStatus );
  257. //
  258. // Read and verify log
  259. //
  260. if (TopOfStack) {
  261. VerifyCurrentLogRecords( Context,
  262. gExpectedReadOperationsTop );
  263. } else {
  264. VerifyCurrentLogRecords( Context,
  265. gExpectedReadOperationsDirected );
  266. }
  267. DumpTestResultBanner( L"READ", FALSE );
  268. ReadTest_Cleanup:
  269. if (testFile != INVALID_HANDLE_VALUE) {
  270. CloseHandle( testFile );
  271. }
  272. if (parms != NULL) {
  273. free( parms );
  274. }
  275. return;
  276. }
  277. VOID
  278. RenameTest (
  279. PLOG_CONTEXT Context,
  280. PWCHAR DriveName,
  281. ULONG DriveNameLength,
  282. BOOLEAN TopOfStack
  283. )
  284. {
  285. BOOL bResult;
  286. IOTEST_RENAME_PARAMETERS parms;
  287. IOTEST_STATUS testStatus;
  288. HANDLE sourceFile;
  289. HANDLE targetFile;
  290. DWORD bytesReturned;
  291. DWORD result;
  292. bResult = CreateTestDirectory( DriveName, DriveNameLength );
  293. if (!bResult) {
  294. goto RenameTest_Cleanup;
  295. }
  296. //
  297. // Setup parameters
  298. //
  299. CopyMemory( &(parms.DriveNameBuffer), DriveName, DriveNameLength );
  300. parms.DriveNameLength = DriveNameLength;
  301. if ((sizeof( RENAME_SOURCE_FILE_NAME ) + DriveNameLength) >
  302. MAX_PATH ) {
  303. //
  304. // The RENAME test source file name is longer than our
  305. // SourceFileNameBuffer, so return an error and quit.
  306. //
  307. printf( "RENAME Test source file name is too long.\n" );
  308. goto RenameTest_Cleanup;
  309. }
  310. //
  311. // We've got enough room, so build up the source file name.
  312. //
  313. wcscpy( parms.SourceFileNameBuffer, parms.DriveNameBuffer );
  314. wcscat( parms.SourceFileNameBuffer, RENAME_SOURCE_FILE_NAME );
  315. parms.SourceFileNameLength = wcslen( parms.SourceFileNameBuffer ) * sizeof( WCHAR );
  316. if ((sizeof( RENAME_TARGET_FILE_NAME ) + DriveNameLength) >
  317. MAX_PATH ) {
  318. //
  319. // The RENAME test target file name is longer than our
  320. // TargetFileNameBuffer, so return an error and quit.
  321. //
  322. printf( "RENAME Test target file name is too long.\n" );
  323. goto RenameTest_Cleanup;
  324. }
  325. //
  326. // We've got enough room, so build up the source file name.
  327. //
  328. wcscpy( parms.TargetFileNameBuffer, parms.DriveNameBuffer );
  329. wcscat( parms.TargetFileNameBuffer, RENAME_TARGET_FILE_NAME );
  330. parms.TargetFileNameLength = wcslen( parms.TargetFileNameBuffer ) * sizeof( WCHAR );
  331. parms.Flags = 0;
  332. if (TopOfStack) {
  333. parms.Flags |= IO_TEST_TOP_OF_STACK;
  334. }
  335. //
  336. // Setup source file
  337. //
  338. sourceFile = CreateFile( RENAME_SOURCE_FILE_NAME,
  339. GENERIC_WRITE,
  340. 0,
  341. NULL,
  342. CREATE_ALWAYS,
  343. FILE_ATTRIBUTE_NORMAL,
  344. NULL );
  345. if (sourceFile == INVALID_HANDLE_VALUE) {
  346. result = GetLastError();
  347. printf ("Error opening RENAME test source file.\n");
  348. DisplayError( result );
  349. goto RenameTest_Cleanup;
  350. }
  351. CloseHandle( sourceFile );
  352. sourceFile = INVALID_HANDLE_VALUE;
  353. //
  354. // Make sure that the target file does NOT exist.
  355. //
  356. targetFile = CreateFile( RENAME_TARGET_FILE_NAME,
  357. GENERIC_ALL,
  358. 0,
  359. NULL,
  360. OPEN_EXISTING,
  361. FILE_FLAG_DELETE_ON_CLOSE,
  362. NULL );
  363. if (targetFile == INVALID_HANDLE_VALUE) {
  364. result = GetLastError();
  365. if (result != ERROR_ALREADY_EXISTS &&
  366. result != ERROR_FILE_NOT_FOUND) {
  367. printf ("Error opening RENAME test target file.\n");
  368. DisplayError( result );
  369. goto RenameTest_Cleanup;
  370. }
  371. } else {
  372. //
  373. // The file does exist, so lets delete by closing the handle.
  374. //
  375. CloseHandle( targetFile );
  376. targetFile = INVALID_HANDLE_VALUE;
  377. }
  378. //
  379. // Send message down to filter
  380. //
  381. bResult = DeviceIoControl( Context->Device,
  382. IOTEST_RenameTest,
  383. &parms,
  384. sizeof( parms ),
  385. &testStatus,
  386. sizeof( testStatus ),
  387. &bytesReturned,
  388. NULL);
  389. if (!bResult) {
  390. result = GetLastError();
  391. printf("ERROR running RENAME test...\n");
  392. DisplayError( result );
  393. goto RenameTest_Cleanup;
  394. }
  395. //
  396. // Display test results.
  397. //
  398. DumpTestResultBanner( L"RENAME", TRUE );
  399. DumpKernelResults( &testStatus );
  400. //
  401. // Read and verify logs
  402. //
  403. if (TopOfStack) {
  404. VerifyCurrentLogRecords( Context,
  405. gExpectedRenameOperationsTop );
  406. } else {
  407. VerifyCurrentLogRecords( Context,
  408. gExpectedRenameOperationsDirected );
  409. }
  410. //
  411. // Verify that the sourceFile is no longer present.
  412. //
  413. sourceFile = CreateFile( RENAME_SOURCE_FILE_NAME,
  414. GENERIC_ALL,
  415. 0,
  416. NULL,
  417. OPEN_EXISTING,
  418. FILE_FLAG_DELETE_ON_CLOSE,
  419. NULL );
  420. if (sourceFile == INVALID_HANDLE_VALUE) {
  421. printf( "User test verification:\tPASSED - Source file no longer present.\n" );
  422. } else {
  423. printf( "User test verification:\tFAILED - Source test file still exists.\n" );
  424. CloseHandle( sourceFile );
  425. }
  426. //
  427. // Verify that the targetFile is present
  428. //
  429. targetFile = CreateFile( RENAME_TARGET_FILE_NAME,
  430. GENERIC_ALL,
  431. 0,
  432. NULL,
  433. OPEN_EXISTING,
  434. FILE_FLAG_DELETE_ON_CLOSE,
  435. NULL );
  436. if (targetFile == INVALID_HANDLE_VALUE) {
  437. result = GetLastError();
  438. printf( "User test verification:\tFAILED - Unexpected error trying to open target file %d.\n",
  439. result );
  440. } else {
  441. printf( "User test verification:\tPASSED - Target test file exists.\n" );
  442. CloseHandle( targetFile );
  443. targetFile = INVALID_HANDLE_VALUE;
  444. }
  445. DumpTestResultBanner( L"RENAME", FALSE );
  446. RenameTest_Cleanup:
  447. if (sourceFile != INVALID_HANDLE_VALUE) {
  448. CloseHandle( sourceFile );
  449. }
  450. if (targetFile != INVALID_HANDLE_VALUE) {
  451. CloseHandle( targetFile );
  452. }
  453. return;
  454. }
  455. VOID
  456. ShareTest (
  457. PLOG_CONTEXT Context,
  458. PWCHAR DriveName,
  459. ULONG DriveNameLength,
  460. BOOLEAN TopOfStack
  461. )
  462. {
  463. BOOL bResult;
  464. IOTEST_SHARE_PARAMETERS parms;
  465. IOTEST_STATUS testStatus;
  466. HANDLE file;
  467. DWORD bytesReturned;
  468. DWORD result;
  469. bResult = CreateTestDirectory( DriveName, DriveNameLength );
  470. if (!bResult) {
  471. goto ShareTest_Cleanup;
  472. }
  473. //
  474. // Setup parameters
  475. //
  476. CopyMemory( &(parms.DriveNameBuffer), DriveName, DriveNameLength );
  477. parms.DriveNameLength = DriveNameLength;
  478. if ((sizeof( SHARE_FILE_NAME ) + DriveNameLength) >
  479. MAX_PATH ) {
  480. //
  481. // The RENAME test source file name is longer than our
  482. // SourceFileNameBuffer, so return an error and quit.
  483. //
  484. printf( "SHARE Test file name is too long.\n" );
  485. goto ShareTest_Cleanup;
  486. }
  487. //
  488. // We've got enough room, so build up the source file name.
  489. //
  490. wcscpy( parms.FileNameBuffer, parms.DriveNameBuffer );
  491. wcscat( parms.FileNameBuffer, SHARE_FILE_NAME );
  492. parms.FileNameLength = wcslen( parms.FileNameBuffer ) * sizeof( WCHAR );
  493. parms.Flags = 0;
  494. if (TopOfStack) {
  495. parms.Flags |= IO_TEST_TOP_OF_STACK;
  496. }
  497. //
  498. // Setup source file
  499. //
  500. file = CreateFile( SHARE_FILE_NAME,
  501. GENERIC_WRITE,
  502. 0,
  503. NULL,
  504. CREATE_ALWAYS,
  505. FILE_ATTRIBUTE_NORMAL,
  506. NULL );
  507. if (file == INVALID_HANDLE_VALUE) {
  508. result = GetLastError();
  509. printf ("Error opening SHARE test file.\n");
  510. DisplayError( result );
  511. goto ShareTest_Cleanup;
  512. }
  513. //
  514. // Send message down to filter
  515. //
  516. bResult = DeviceIoControl( Context->Device,
  517. IOTEST_ShareTest,
  518. &parms,
  519. sizeof( parms ),
  520. &testStatus,
  521. sizeof( testStatus ),
  522. &bytesReturned,
  523. NULL);
  524. if (!bResult) {
  525. result = GetLastError();
  526. printf("ERROR running SHARE test...\n");
  527. DisplayError( result );
  528. goto ShareTest_Cleanup;
  529. }
  530. //
  531. // Display test results.
  532. //
  533. DumpTestResultBanner( L"SHARE", TRUE );
  534. DumpKernelResults( &testStatus );
  535. //
  536. // Read and verify logs
  537. //
  538. if (TopOfStack) {
  539. VerifyCurrentLogRecords( Context,
  540. gExpectedShareOperationsTop );
  541. } else {
  542. VerifyCurrentLogRecords( Context,
  543. gExpectedShareOperationsDirected );
  544. }
  545. DumpTestResultBanner( L"SHARE", FALSE );
  546. ShareTest_Cleanup:
  547. if (file != INVALID_HANDLE_VALUE) {
  548. CloseHandle( file );
  549. }
  550. return;
  551. }