|
|
/*++
Copyright (c) 1989-1999 Microsoft Corporation
Module Name:
ioTestUserSup.c
Abstract:
// @@BEGIN_DDKSPLIT
Author:
George Jenkins (GeorgeJe)
// @@END_DDKSPLIT
Environment:
User mode
// @@BEGIN_DDKSPLIT
Revision History:
Molly Brown (MollyBro) 21-Apr-1999 Broke out the logging code and added command mode functionality.
// @@END_DDKSPLIT
--*/
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <winioctl.h>
#include <string.h>
#include <crtdbg.h>
#include "ioTest.h"
#include "ioTestLog.h"
#include "ioTestLib.h"
#define NT_SUCCESS(Status) ((LONG)(Status) >= 0)
#define TEST_DIRECTORY_NAME L"\\ioTest"
#define READ_TEST_FILE_NAME TEST_DIRECTORY_NAME L"\\read.txt"
#define READ_TEST_DATA L"Hello world!"
EXPECTED_OPERATION gExpectedReadOperationsTop[] = { { TOP_FILTER, IRP_MJ_CREATE }, { BOTTOM_FILTER, IRP_MJ_CREATE }, { TOP_FILTER, IRP_MJ_READ }, { BOTTOM_FILTER, IRP_MJ_READ }, { TOP_FILTER, IRP_MJ_CLEANUP }, { BOTTOM_FILTER, IRP_MJ_CLEANUP }, { BOTTOM_FILTER, IRP_MJ_MAXIMUM_FUNCTION + 1 } }; EXPECTED_OPERATION gExpectedReadOperationsDirected[] = { { BOTTOM_FILTER, IRP_MJ_CREATE }, { BOTTOM_FILTER, IRP_MJ_READ }, { BOTTOM_FILTER, IRP_MJ_CLEANUP }, { BOTTOM_FILTER, IRP_MJ_MAXIMUM_FUNCTION + 1 } };
#define WRITE_TEST_FILE_NAME TEST_DIRECTORY_NAME L"\\write.txt"
#define WRITE_TEST_DATA L"Good morning!"
EXPECTED_OPERATION gExpectedWriteOperationsTop[] = { { TOP_FILTER, IRP_MJ_CREATE }, { BOTTOM_FILTER, IRP_MJ_CREATE }, { TOP_FILTER, IRP_MJ_WRITE }, { BOTTOM_FILTER, IRP_MJ_WRITE }, { TOP_FILTER, IRP_MJ_CLEANUP }, { BOTTOM_FILTER, IRP_MJ_CLEANUP }, { BOTTOM_FILTER, IRP_MJ_MAXIMUM_FUNCTION + 1 } }; EXPECTED_OPERATION gExpectedWriteOperationsDirected[] = { { BOTTOM_FILTER, IRP_MJ_CREATE }, { BOTTOM_FILTER, IRP_MJ_WRITE }, { BOTTOM_FILTER, IRP_MJ_CLEANUP }, { BOTTOM_FILTER, IRP_MJ_MAXIMUM_FUNCTION + 1 } };
#define RENAME_SOURCE_FILE_NAME TEST_DIRECTORY_NAME L"\\renameSource.txt"
#define RENAME_TARGET_FILE_NAME TEST_DIRECTORY_NAME L"\\renameTarget.txt"
EXPECTED_OPERATION gExpectedRenameOperationsTop[] = { { TOP_FILTER, IRP_MJ_CREATE }, { BOTTOM_FILTER, IRP_MJ_CREATE }, { TOP_FILTER, IRP_MJ_SET_INFORMATION }, { BOTTOM_FILTER, IRP_MJ_SET_INFORMATION }, { TOP_FILTER, IRP_MJ_CLEANUP }, { BOTTOM_FILTER, IRP_MJ_CLEANUP }, { BOTTOM_FILTER, IRP_MJ_MAXIMUM_FUNCTION + 1 } }; EXPECTED_OPERATION gExpectedRenameOperationsDirected[] = { { BOTTOM_FILTER, IRP_MJ_CREATE }, { BOTTOM_FILTER, IRP_MJ_SET_INFORMATION }, { BOTTOM_FILTER, IRP_MJ_CLEANUP }, { BOTTOM_FILTER, IRP_MJ_MAXIMUM_FUNCTION + 1 } };
#define SHARE_FILE_NAME TEST_DIRECTORY_NAME L"\\share.txt"
EXPECTED_OPERATION gExpectedShareOperationsTop[] = { { TOP_FILTER, IRP_MJ_CREATE }, { BOTTOM_FILTER, IRP_MJ_CREATE }, { TOP_FILTER, IRP_MJ_CLEANUP }, { BOTTOM_FILTER, IRP_MJ_CLEANUP }, { BOTTOM_FILTER, IRP_MJ_MAXIMUM_FUNCTION + 1 } }; EXPECTED_OPERATION gExpectedShareOperationsDirected[] = { { BOTTOM_FILTER, IRP_MJ_CREATE }, { BOTTOM_FILTER, IRP_MJ_CLEANUP }, { BOTTOM_FILTER, IRP_MJ_MAXIMUM_FUNCTION + 1 } }; BOOL CreateTestDirectory ( PWCHAR DriveName, ULONG DriveNameLength ) { WCHAR testDirName[MAX_PATH]; DWORD result; BOOL bResult;
if (sizeof( TEST_DIRECTORY_NAME ) + DriveNameLength > MAX_PATH) {
printf ("Can't create test directory -- name buffer too small\n"); return FALSE; }
wcscpy( testDirName, DriveName ); wcscat( testDirName, TEST_DIRECTORY_NAME );
bResult = CreateDirectory( testDirName, NULL );
if (!bResult) {
result = GetLastError(); if (result != ERROR_ALREADY_EXISTS) {
DisplayError( result ); return FALSE; } }
return TRUE; }
VOID DumpTestResultBanner ( PWCHAR TestName, BOOL Begin ) { if (Begin) {
printf( "***BEGIN %S TEST RESULTS***\n", TestName );
} else {
printf( "***END %S TEST RESULTS***\n", TestName ); } }
VOID DumpKernelResults ( PIOTEST_STATUS TestStatus ) { printf( "Kernel verification: " ); if (NT_SUCCESS( TestStatus->TestResult )) {
printf( "\tTest PASSED\n" ); } else {
switch( TestStatus->Phase ) { case IoTestSetup: printf( "\tTest failed in SETUP phase with status 0x%08x\n", TestStatus->TestResult ); break;
case IoTestAction: printf( "\tTest failed in ACTION phase with status 0x%08x\n", TestStatus->TestResult ); break;
case IoTestValidation: printf( "\tTest failed in VALIDATION phase with status 0x%08x\n", TestStatus->TestResult ); break;
case IoTestCleanup: printf( "\tTest failed in CLEANUP phase with status 0x%08x\n", TestStatus->TestResult ); break;
case IoTestCompleted: printf( "\tTest failed in COMPLETED phase with status 0x%08x\n", TestStatus->TestResult ); break;
default: printf( "\tTest failed in UNKNOWN phase with status 0x%08x\n", TestStatus->TestResult ); break;
} } }
VOID ReadTest ( PLOG_CONTEXT Context, PWCHAR DriveName, ULONG DriveNameLength, BOOLEAN TopOfStack ) { HANDLE testFile = INVALID_HANDLE_VALUE; PIOTEST_READ_WRITE_PARAMETERS parms = NULL; DWORD parmsLength; IOTEST_STATUS testStatus; BOOL bResult; DWORD bytesReturned; DWORD result;
bResult = CreateTestDirectory( DriveName, DriveNameLength );
if (!bResult) {
goto ReadTest_Cleanup; }
//
// Setup parms
//
parmsLength = sizeof( IOTEST_READ_WRITE_PARAMETERS ) + sizeof( READ_TEST_DATA ); parms = malloc (parmsLength);
if (parms == NULL) {
printf( "Insufficient resources to run READ test\n" ); goto ReadTest_Cleanup; }
CopyMemory( parms->DriveNameBuffer, DriveName, DriveNameLength ); parms->DriveNameLength = DriveNameLength;
if ((sizeof( READ_TEST_FILE_NAME ) + DriveNameLength) > MAX_PATH ) {
//
// The READ test file name is longer than our FileNameBuffer,
// so return an error and quit.
//
printf( "READ Test file name is too long.\n" ); goto ReadTest_Cleanup; }
//
// We've got enough room, so build up the file name.
//
wcscpy( parms->FileNameBuffer, parms->DriveNameBuffer ); wcscat( parms->FileNameBuffer, READ_TEST_FILE_NAME ); parms->FileNameLength = wcslen( parms->FileNameBuffer ) * sizeof( WCHAR );
parms->FileDataLength = sizeof( READ_TEST_DATA ); CopyMemory( parms->FileData, READ_TEST_DATA, parms->FileDataLength );
parms->Flags = 0; if (TopOfStack) {
parms->Flags |= IO_TEST_TOP_OF_STACK; }
//
// Create test file
//
testFile = CreateFile( parms->FileNameBuffer, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
if (testFile == INVALID_HANDLE_VALUE) {
result = GetLastError(); printf ("Error opening READ test file.\n"); DisplayError( result ); goto ReadTest_Cleanup; } //
// Write data to test file
//
bResult = WriteFile( testFile, READ_TEST_DATA, sizeof( READ_TEST_DATA ), &bytesReturned, NULL );
if (!bResult) { result = GetLastError(); printf("ERROR writing data READ test file...\n"); DisplayError( result ); goto ReadTest_Cleanup; }
CloseHandle( testFile ); testFile = INVALID_HANDLE_VALUE; //
// Send message down to filter
//
bResult = DeviceIoControl( Context->Device, IOTEST_ReadTest, parms, parmsLength, &testStatus, sizeof( testStatus ), &bytesReturned, NULL); if (!bResult) { result = GetLastError(); printf("ERROR running READ test...\n"); DisplayError( result ); goto ReadTest_Cleanup; }
//
// Print out the result of the kernel verification tests.
//
DumpTestResultBanner( L"READ", TRUE ); DumpKernelResults( &testStatus ); //
// Read and verify log
//
if (TopOfStack) { VerifyCurrentLogRecords( Context, gExpectedReadOperationsTop );
} else {
VerifyCurrentLogRecords( Context, gExpectedReadOperationsDirected ); } DumpTestResultBanner( L"READ", FALSE ); ReadTest_Cleanup:
if (testFile != INVALID_HANDLE_VALUE) {
CloseHandle( testFile ); }
if (parms != NULL) {
free( parms ); }
return; }
VOID RenameTest ( PLOG_CONTEXT Context, PWCHAR DriveName, ULONG DriveNameLength, BOOLEAN TopOfStack ) { BOOL bResult; IOTEST_RENAME_PARAMETERS parms; IOTEST_STATUS testStatus; HANDLE sourceFile; HANDLE targetFile; DWORD bytesReturned; DWORD result; bResult = CreateTestDirectory( DriveName, DriveNameLength );
if (!bResult) {
goto RenameTest_Cleanup; }
//
// Setup parameters
//
CopyMemory( &(parms.DriveNameBuffer), DriveName, DriveNameLength ); parms.DriveNameLength = DriveNameLength;
if ((sizeof( RENAME_SOURCE_FILE_NAME ) + DriveNameLength) > MAX_PATH ) {
//
// The RENAME test source file name is longer than our
// SourceFileNameBuffer, so return an error and quit.
//
printf( "RENAME Test source file name is too long.\n" ); goto RenameTest_Cleanup; }
//
// We've got enough room, so build up the source file name.
//
wcscpy( parms.SourceFileNameBuffer, parms.DriveNameBuffer ); wcscat( parms.SourceFileNameBuffer, RENAME_SOURCE_FILE_NAME ); parms.SourceFileNameLength = wcslen( parms.SourceFileNameBuffer ) * sizeof( WCHAR ); if ((sizeof( RENAME_TARGET_FILE_NAME ) + DriveNameLength) > MAX_PATH ) {
//
// The RENAME test target file name is longer than our
// TargetFileNameBuffer, so return an error and quit.
//
printf( "RENAME Test target file name is too long.\n" ); goto RenameTest_Cleanup; }
//
// We've got enough room, so build up the source file name.
//
wcscpy( parms.TargetFileNameBuffer, parms.DriveNameBuffer ); wcscat( parms.TargetFileNameBuffer, RENAME_TARGET_FILE_NAME ); parms.TargetFileNameLength = wcslen( parms.TargetFileNameBuffer ) * sizeof( WCHAR );
parms.Flags = 0; if (TopOfStack) {
parms.Flags |= IO_TEST_TOP_OF_STACK; }
//
// Setup source file
//
sourceFile = CreateFile( RENAME_SOURCE_FILE_NAME, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
if (sourceFile == INVALID_HANDLE_VALUE) {
result = GetLastError(); printf ("Error opening RENAME test source file.\n"); DisplayError( result ); goto RenameTest_Cleanup; }
CloseHandle( sourceFile ); sourceFile = INVALID_HANDLE_VALUE;
//
// Make sure that the target file does NOT exist.
//
targetFile = CreateFile( RENAME_TARGET_FILE_NAME, GENERIC_ALL, 0, NULL, OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, NULL );
if (targetFile == INVALID_HANDLE_VALUE) {
result = GetLastError();
if (result != ERROR_ALREADY_EXISTS && result != ERROR_FILE_NOT_FOUND) { printf ("Error opening RENAME test target file.\n"); DisplayError( result ); goto RenameTest_Cleanup; } } else {
//
// The file does exist, so lets delete by closing the handle.
//
CloseHandle( targetFile ); targetFile = INVALID_HANDLE_VALUE; }
//
// Send message down to filter
//
bResult = DeviceIoControl( Context->Device, IOTEST_RenameTest, &parms, sizeof( parms ), &testStatus, sizeof( testStatus ), &bytesReturned, NULL); if (!bResult) { result = GetLastError(); printf("ERROR running RENAME test...\n"); DisplayError( result ); goto RenameTest_Cleanup; }
//
// Display test results.
//
DumpTestResultBanner( L"RENAME", TRUE );
DumpKernelResults( &testStatus );
//
// Read and verify logs
//
if (TopOfStack) { VerifyCurrentLogRecords( Context, gExpectedRenameOperationsTop );
} else {
VerifyCurrentLogRecords( Context, gExpectedRenameOperationsDirected ); } //
// Verify that the sourceFile is no longer present.
//
sourceFile = CreateFile( RENAME_SOURCE_FILE_NAME, GENERIC_ALL, 0, NULL, OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, NULL );
if (sourceFile == INVALID_HANDLE_VALUE) {
printf( "User test verification:\tPASSED - Source file no longer present.\n" );
} else { printf( "User test verification:\tFAILED - Source test file still exists.\n" ); CloseHandle( sourceFile ); }
//
// Verify that the targetFile is present
//
targetFile = CreateFile( RENAME_TARGET_FILE_NAME, GENERIC_ALL, 0, NULL, OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, NULL );
if (targetFile == INVALID_HANDLE_VALUE) {
result = GetLastError(); printf( "User test verification:\tFAILED - Unexpected error trying to open target file %d.\n", result ); } else { printf( "User test verification:\tPASSED - Target test file exists.\n" ); CloseHandle( targetFile ); targetFile = INVALID_HANDLE_VALUE; }
DumpTestResultBanner( L"RENAME", FALSE ); RenameTest_Cleanup:
if (sourceFile != INVALID_HANDLE_VALUE) {
CloseHandle( sourceFile ); }
if (targetFile != INVALID_HANDLE_VALUE) {
CloseHandle( targetFile ); }
return; }
VOID ShareTest ( PLOG_CONTEXT Context, PWCHAR DriveName, ULONG DriveNameLength, BOOLEAN TopOfStack ) { BOOL bResult; IOTEST_SHARE_PARAMETERS parms; IOTEST_STATUS testStatus; HANDLE file; DWORD bytesReturned; DWORD result; bResult = CreateTestDirectory( DriveName, DriveNameLength );
if (!bResult) {
goto ShareTest_Cleanup; }
//
// Setup parameters
//
CopyMemory( &(parms.DriveNameBuffer), DriveName, DriveNameLength ); parms.DriveNameLength = DriveNameLength;
if ((sizeof( SHARE_FILE_NAME ) + DriveNameLength) > MAX_PATH ) {
//
// The RENAME test source file name is longer than our
// SourceFileNameBuffer, so return an error and quit.
//
printf( "SHARE Test file name is too long.\n" ); goto ShareTest_Cleanup; }
//
// We've got enough room, so build up the source file name.
//
wcscpy( parms.FileNameBuffer, parms.DriveNameBuffer ); wcscat( parms.FileNameBuffer, SHARE_FILE_NAME ); parms.FileNameLength = wcslen( parms.FileNameBuffer ) * sizeof( WCHAR );
parms.Flags = 0; if (TopOfStack) {
parms.Flags |= IO_TEST_TOP_OF_STACK; } //
// Setup source file
//
file = CreateFile( SHARE_FILE_NAME, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
if (file == INVALID_HANDLE_VALUE) {
result = GetLastError(); printf ("Error opening SHARE test file.\n"); DisplayError( result ); goto ShareTest_Cleanup; }
//
// Send message down to filter
//
bResult = DeviceIoControl( Context->Device, IOTEST_ShareTest, &parms, sizeof( parms ), &testStatus, sizeof( testStatus ), &bytesReturned, NULL); if (!bResult) { result = GetLastError(); printf("ERROR running SHARE test...\n"); DisplayError( result ); goto ShareTest_Cleanup; }
//
// Display test results.
//
DumpTestResultBanner( L"SHARE", TRUE );
DumpKernelResults( &testStatus );
//
// Read and verify logs
//
if (TopOfStack) { VerifyCurrentLogRecords( Context, gExpectedShareOperationsTop );
} else {
VerifyCurrentLogRecords( Context, gExpectedShareOperationsDirected ); } DumpTestResultBanner( L"SHARE", FALSE ); ShareTest_Cleanup:
if (file != INVALID_HANDLE_VALUE) {
CloseHandle( file ); }
return; }
|