windows-nt/Source/XPSP1/NT/base/fs/fltsamples/iotest/user/iotestusersup.c

743 lines
20 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
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;
}