windows-nt/Source/XPSP1/NT/base/fs/fastfat/tests/tfatwinn.c

829 lines
22 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 1989 Microsoft Corporation
Module Name:
tfat.c
Abstract:
Test program for the Fat File system
Author:
Gary Kimura [GaryKi] 24-May-1989
Revision History:
--*/
#include <stdio.h>
#include <string.h>
#define toupper(C) ((C) >= 'a' && (C) <= 'z' ? (C) - ('a' - 'A') : (C))
#define isdigit(C) ((C) >= '0' && (C) <= '9')
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#define simprintf(X,Y) {if (!Silent) {printf(X,Y);} }
BOOLEAN Silent;
//
// The buffer size must be a multiple of 512
//
#define BUFFERSIZE 1024
UCHAR Buffer[BUFFERSIZE];
CHAR Prefix[64];
ULONG WriteThrough = 0;
VOID
WaitForSingleObjectError(
IN NTSTATUS Status
);
VOID
CreateFileError(
IN NTSTATUS Status,
PCHAR File
);
VOID
OpenFileError(
IN NTSTATUS Status,
PCHAR File
);
VOID
ReadFileError(
IN NTSTATUS Status
);
VOID
WriteFileError(
IN NTSTATUS Status
);
VOID
CheckIoStatus(
IN PIO_STATUS_BLOCK IoStatus,
IN ULONG Length,
IN BOOLEAN Read
);
VOID
SetInformationFileError(
IN NTSTATUS Status
);
VOID
QueryInformationFileError(
IN NTSTATUS Status
);
VOID
CloseError(
IN NTSTATUS Status
);
VOID
IoStatusError(
IN NTSTATUS Status
);
VOID
main(
int argc,
char *argv[]
)
{
ULONG i;
ULONG Count;
VOID FatMain();
CHAR Device[8];
STRING NtDevice;
CHAR NtDeviceBuffer[32];
if (argc <= 1) {
printf("usage: %s drive: [iterations [writethrough] ]\n", argv[0]);
return;
}
//
// Decode the device/drive
//
strcpy( Device, argv[1] );
NtDevice.MaximumLength = NtDevice.Length = 32;
NtDevice.Buffer = NtDeviceBuffer;
if (!RtlDosPathNameToNtPathName( Device, &NtDevice, NULL, NULL )) {
printf( "Invalid Dos Device Name\n" );
RtlFreeHeap(RtlProcessHeap(), 0, NtDevice.Buffer);
return;
}
if (NtDevice.Length > 31) {
NtDevice.Length = 31;
}
NtDevice.Buffer[NtDevice.Length] = 0;
//
// Now do the iteration count
//
if (argc >= 3) {
Count = 0;
for (i = 0; isdigit(argv[2][i]); i += 1) {
Count = Count * 10 + argv[2][i] - '0';
}
} else {
Count = 1;
}
//
// Check for write through
//
if (argc >= 4) {
WriteThrough = FILE_WRITE_THROUGH;
}
//
// Check for silent operation
//
if (toupper(Device[0]) != Device[0]) {
Silent = TRUE;
} else {
Silent = FALSE;
}
//
// Do the work
//
FatMain(Count, NtDevice.Buffer);
RtlFreeHeap(RtlProcessHeap(), 0, NtDevice.Buffer);
return;
}
VOID
FatMain(
IN ULONG LoopCount,
IN CHAR Device[]
)
{
VOID Create(),Delete(),Mkdir(),Directory(),Read();
CHAR Str[64];
CHAR LoopStr[64];
ULONG i;
LARGE_INTEGER Time;
printf("FatMain %d\n", LoopCount);
NtQuerySystemTime(&Time);
strcpy( Prefix, Device);
Prefix[48] = 0;
RtlIntegerToChar((ULONG)NtCurrentTeb()->ClientId.UniqueProcess, 16, -8, &Prefix[strlen(Device)]);
Mkdir( Prefix );
Directory( Device );
Directory( Prefix );
for (i = 0; i < LoopCount; i += 1) {
NtQuerySystemTime(&Time);
strcpy(LoopStr, "Start loop xxxxxxxx ");
RtlIntegerToChar(i, 16, -8, &LoopStr[11]);
strcat( LoopStr, Prefix );
printf(LoopStr);
printf("\n");
strcpy( Str, Prefix ); Create( strcat( Str, "\\1.tmp" ), Time.LowPart, 1 );
strcpy( Str, Prefix ); Create( strcat( Str, "\\2.tmp" ), Time.LowPart, 2 );
strcpy( Str, Prefix ); Create( strcat( Str, "\\4.tmp" ), Time.LowPart, 4 );
strcpy( Str, Prefix ); Create( strcat( Str, "\\8.tmp" ), Time.LowPart, 8 );
strcpy( Str, Prefix ); Create( strcat( Str, "\\16.tmp" ), Time.LowPart, 16 );
strcpy( Str, Prefix ); Create( strcat( Str, "\\32.tmp" ), Time.LowPart, 32 );
strcpy( Str, Prefix ); Create( strcat( Str, "\\64.tmp" ), Time.LowPart, 64 );
strcpy( Str, Prefix ); Create( strcat( Str, "\\128.tmp" ), Time.LowPart, 128 );
strcpy( Str, Prefix ); Create( strcat( Str, "\\236.tmp" ), Time.LowPart, 256 );
strcpy( Str, Prefix ); Create( strcat( Str, "\\512.tmp" ), Time.LowPart, 512 );
strcpy( Str, Prefix ); Create( strcat( Str, "\\1024.tmp" ), Time.LowPart, 1024 );
strcpy( Str, Prefix ); Create( strcat( Str, "\\2048.tmp" ), Time.LowPart, 2048 );
strcpy( Str, Prefix ); Create( strcat( Str, "\\4096.tmp" ), Time.LowPart, 4096 );
strcpy( Str, Prefix ); Create( strcat( Str, "\\8192.tmp" ), Time.LowPart, 8192 );
strcpy( Str, Prefix ); Create( strcat( Str, "\\16384.tmp" ), Time.LowPart, 16384 );
strcpy( Str, Prefix ); Create( strcat( Str, "\\32768.tmp" ), Time.LowPart, 32768 );
strcpy( Str, Prefix ); Read( strcat( Str, "\\1.tmp" ), Time.LowPart, 1 );
strcpy( Str, Prefix ); Read( strcat( Str, "\\2.tmp" ), Time.LowPart, 2 );
strcpy( Str, Prefix ); Read( strcat( Str, "\\4.tmp" ), Time.LowPart, 4 );
strcpy( Str, Prefix ); Read( strcat( Str, "\\8.tmp" ), Time.LowPart, 8 );
strcpy( Str, Prefix ); Read( strcat( Str, "\\16.tmp" ), Time.LowPart, 16 );
strcpy( Str, Prefix ); Read( strcat( Str, "\\32.tmp" ), Time.LowPart, 32 );
strcpy( Str, Prefix ); Read( strcat( Str, "\\64.tmp" ), Time.LowPart, 64 );
strcpy( Str, Prefix ); Read( strcat( Str, "\\128.tmp" ), Time.LowPart, 128 );
strcpy( Str, Prefix ); Read( strcat( Str, "\\236.tmp" ), Time.LowPart, 256 );
strcpy( Str, Prefix ); Read( strcat( Str, "\\512.tmp" ), Time.LowPart, 512 );
strcpy( Str, Prefix ); Read( strcat( Str, "\\1024.tmp" ), Time.LowPart, 1024 );
strcpy( Str, Prefix ); Read( strcat( Str, "\\2048.tmp" ), Time.LowPart, 2048 );
strcpy( Str, Prefix ); Read( strcat( Str, "\\4096.tmp" ), Time.LowPart, 4096 );
strcpy( Str, Prefix ); Read( strcat( Str, "\\8192.tmp" ), Time.LowPart, 8192 );
strcpy( Str, Prefix ); Read( strcat( Str, "\\16384.tmp" ), Time.LowPart, 16384 );
strcpy( Str, Prefix ); Read( strcat( Str, "\\32768.tmp" ), Time.LowPart, 32768 );
Directory( Device );
Directory( Prefix );
strcpy( Str, Prefix ); Delete( strcat( Str, "\\1.tmp" ) );
strcpy( Str, Prefix ); Delete( strcat( Str, "\\2.tmp" ) );
strcpy( Str, Prefix ); Delete( strcat( Str, "\\4.tmp" ) );
strcpy( Str, Prefix ); Delete( strcat( Str, "\\8.tmp" ) );
strcpy( Str, Prefix ); Delete( strcat( Str, "\\16.tmp" ) );
strcpy( Str, Prefix ); Delete( strcat( Str, "\\32.tmp" ) );
strcpy( Str, Prefix ); Delete( strcat( Str, "\\64.tmp" ) );
strcpy( Str, Prefix ); Delete( strcat( Str, "\\128.tmp" ) );
strcpy( Str, Prefix ); Delete( strcat( Str, "\\236.tmp" ) );
strcpy( Str, Prefix ); Delete( strcat( Str, "\\512.tmp" ) );
strcpy( Str, Prefix ); Delete( strcat( Str, "\\1024.tmp" ) );
strcpy( Str, Prefix ); Delete( strcat( Str, "\\2048.tmp" ) );
strcpy( Str, Prefix ); Delete( strcat( Str, "\\4096.tmp" ) );
strcpy( Str, Prefix ); Delete( strcat( Str, "\\8192.tmp" ) );
strcpy( Str, Prefix ); Delete( strcat( Str, "\\16384.tmp" ) );
strcpy( Str, Prefix ); Delete( strcat( Str, "\\32768.tmp" ) );
Directory( Device );
Directory( Prefix );
}
printf( "Done\n" );
return;
}
VOID Create(
IN PCHAR FileName,
IN ULONG FileTime,
IN ULONG FileCount
)
{
NTSTATUS Status;
HANDLE FileHandle;
OBJECT_ATTRIBUTES ObjectAttributes;
STRING NameString;
IO_STATUS_BLOCK IoStatus;
LARGE_INTEGER AllocationSize;
LARGE_INTEGER ByteOffset;
ULONG Count;
ULONG Pattern[3];
//
// Get the filename
//
simprintf("Create ", 0); simprintf(FileName, 0); simprintf("\n", 0);
//
// Create the new file
//
AllocationSize = LiFromUlong( FileCount * 4 );
RtlInitString( &NameString, FileName );
InitializeObjectAttributes( &ObjectAttributes, &NameString, 0, NULL, NULL );
if (!NT_SUCCESS(Status = NtCreateFile( &FileHandle,
FILE_WRITE_DATA | SYNCHRONIZE,
&ObjectAttributes,
&IoStatus,
&AllocationSize,
FILE_ATTRIBUTE_NORMAL,
0L,
FILE_SUPERSEDE,
WriteThrough,
(PVOID)NULL,
0L ))) {
CreateFileError( Status , FileName );
return;
}
//
// The main loop writes out the test pattern our test pattern
// is <FileTime> <FileSize> <Count> where count is the current
// iteration count for the current test pattern output.
//
Pattern[0] = FileTime;
Pattern[1] = FileCount;
for (Count = 0; Count < FileCount; Count += 1) {
Pattern[2] = Count;
ByteOffset = LiFromUlong( Count * 3 * 4 );
if (!NT_SUCCESS(Status = NtWriteFile( FileHandle,
(HANDLE)NULL,
(PIO_APC_ROUTINE)NULL,
(PVOID)NULL,
&IoStatus,
Pattern,
3 * 4,
&ByteOffset,
(PULONG) NULL ))) {
WriteFileError( Status );
return;
}
if (!NT_SUCCESS(Status = NtWaitForSingleObject(FileHandle, TRUE, NULL))) {
WaitForSingleObjectError( Status );
return;
}
//
// check how the write turned out
//
CheckIoStatus( &IoStatus, 3 * 4, FALSE );
if (!NT_SUCCESS(IoStatus.Status)) {
IoStatusError( IoStatus.Status );
break;
}
}
//
// Now close the file
//
if (!NT_SUCCESS(Status = NtClose( FileHandle ))) {
CloseError( Status );
}
//
// And return to our caller
//
return;
}
VOID Read(
IN PCHAR FileName,
IN ULONG FileTime,
IN ULONG FileCount
)
{
NTSTATUS Status;
HANDLE FileHandle;
OBJECT_ATTRIBUTES ObjectAttributes;
STRING NameString;
IO_STATUS_BLOCK IoStatus;
LARGE_INTEGER AllocationSize;
LARGE_INTEGER ByteOffset;
ULONG Count;
ULONG Pattern[3];
//
// Get the filename
//
simprintf("Read ", 0); simprintf(FileName, 0); simprintf("\n", 0);
//
// Open the existing file
//
AllocationSize = LiFromUlong( FileCount * 4 );
RtlInitString( &NameString, FileName );
InitializeObjectAttributes( &ObjectAttributes, &NameString, 0, NULL, NULL );
if (!NT_SUCCESS(Status = NtOpenFile( &FileHandle,
FILE_READ_DATA | FILE_READ_ATTRIBUTES | SYNCHRONIZE,
&ObjectAttributes,
&IoStatus,
0L,
WriteThrough ))) {
OpenFileError( Status, FileName );
return;
}
//
// The main loop read in the test pattern our test pattern
// is <FileTime> <FileSize> <Count> where count is the current
// iteration count for the current test pattern output.
//
for (Count = 0; Count < FileCount; Count += 1) {
ByteOffset = LiFromUlong( Count * 3 * 4 );
if (!NT_SUCCESS(Status = NtReadFile( FileHandle,
(HANDLE)NULL,
(PIO_APC_ROUTINE)NULL,
(PVOID)NULL,
&IoStatus,
Pattern,
3 * 4,
&ByteOffset,
(PULONG) NULL ))) {
ReadFileError( Status );
return;
}
if (!NT_SUCCESS(Status = NtWaitForSingleObject(FileHandle, TRUE, NULL))) {
WaitForSingleObjectError( Status );
return;
}
//
// check how the read turned out
//
CheckIoStatus( &IoStatus, 3 * 4, TRUE );
if (!NT_SUCCESS(IoStatus.Status)) {
IoStatusError( IoStatus.Status );
break;
}
//
// Now compare the what we read with what we should have read
//
if ((Pattern[0] != FileTime) ||
(Pattern[1] != FileCount) ||
(Pattern[2] != Count)) {
printf("**** Read Error ****\n");
NtPartyByNumber( 50 );
return;
}
}
//
// Now close the file
//
if (!NT_SUCCESS(Status = NtClose( FileHandle ))) {
CloseError( Status );
}
//
// And return to our caller
//
return;
}
VOID Delete(
IN PCHAR FileName
)
{
NTSTATUS Status;
HANDLE FileHandle;
OBJECT_ATTRIBUTES ObjectAttributes;
STRING NameString;
IO_STATUS_BLOCK IoStatus;
//
// Get the filename
//
simprintf("Delete ", 0); simprintf(FileName, 0); simprintf("\n", 0);
//
// Open the file for delete access
//
RtlInitString( &NameString, FileName );
InitializeObjectAttributes( &ObjectAttributes, &NameString, 0, NULL, NULL );
if (!NT_SUCCESS(Status = NtCreateFile( &FileHandle,
DELETE | SYNCHRONIZE,
&ObjectAttributes,
&IoStatus,
(PLARGE_INTEGER)NULL,
0L,
0L,
FILE_OPEN,
WriteThrough,
(PVOID)NULL,
0L ))) {
CreateFileError( Status, FileName );
return;
}
//
// Mark the file for delete
//
((PFILE_DISPOSITION_INFORMATION)&Buffer[0])->DeleteFile = TRUE;
if (!NT_SUCCESS(Status = NtSetInformationFile( FileHandle,
&IoStatus,
Buffer,
sizeof(FILE_DISPOSITION_INFORMATION),
FileDispositionInformation))) {
SetInformationFileError( Status );
return;
}
//
// Now close the file
//
if (!NT_SUCCESS(Status = NtClose( FileHandle ))) {
CloseError( Status );
}
//
// And return to our caller
//
return;
}
VOID Directory(
IN PCHAR String
)
{
NTSTATUS Status;
HANDLE FileHandle;
OBJECT_ATTRIBUTES ObjectAttributes;
STRING NameString;
IO_STATUS_BLOCK IoStatus;
NTSTATUS NtStatus;
PFILE_ADIRECTORY_INFORMATION FileInfo;
ULONG i;
//
// Get the filename
//
simprintf("Directory ", 0);
simprintf(String, 0);
simprintf("\n", 0);
//
// Open the file for list directory access
//
RtlInitString( &NameString, String );
InitializeObjectAttributes( &ObjectAttributes, &NameString, 0, NULL, NULL );
if (!NT_SUCCESS(Status = NtOpenFile( &FileHandle,
FILE_LIST_DIRECTORY | SYNCHRONIZE,
&ObjectAttributes,
&IoStatus,
FILE_SHARE_READ,
WriteThrough | FILE_DIRECTORY_FILE ))) {
OpenFileError( Status , String );
return;
}
//
// zero out the buffer so next time we'll recognize the end of data
//
for (i = 0; i < BUFFERSIZE; i += 1) { Buffer[i] = 0; }
//
// Do the directory loop
//
for (NtStatus = NtQueryDirectoryFile( FileHandle,
(HANDLE)NULL,
(PIO_APC_ROUTINE)NULL,
(PVOID)NULL,
&IoStatus,
Buffer,
BUFFERSIZE,
FileADirectoryInformation,
FALSE,
(PSTRING)NULL,
TRUE);
NT_SUCCESS(NtStatus);
NtStatus = NtQueryDirectoryFile( FileHandle,
(HANDLE)NULL,
(PIO_APC_ROUTINE)NULL,
(PVOID)NULL,
&IoStatus,
Buffer,
BUFFERSIZE,
FileADirectoryInformation,
FALSE,
(PSTRING)NULL,
FALSE) ) {
if (!NT_SUCCESS(Status = NtWaitForSingleObject(FileHandle, TRUE, NULL))) {
// NtPartyByNumber(50);
WaitForSingleObjectError( Status );
return;
}
//
// Check the Irp for success
//
if (!NT_SUCCESS(IoStatus.Status)) {
break;
}
//
// For every record in the buffer type out the directory information
//
//
// Point to the first record in the buffer, we are guaranteed to have
// one otherwise IoStatus would have been No More Files
//
FileInfo = (PFILE_ADIRECTORY_INFORMATION)&Buffer[0];
while (TRUE) {
//
// Print out information about the file
//
simprintf("%8lx ", FileInfo->FileAttributes);
simprintf("%8lx/", FileInfo->EndOfFile.LowPart);
simprintf("%8lx ", FileInfo->AllocationSize.LowPart);
{
CHAR Saved;
Saved = FileInfo->FileName[FileInfo->FileNameLength];
FileInfo->FileName[FileInfo->FileNameLength] = 0;
simprintf(FileInfo->FileName, 0);
FileInfo->FileName[FileInfo->FileNameLength] = Saved;
}
simprintf("\n", 0);
//
// Check if there is another record, if there isn't then we
// simply get out of this loop
//
if (FileInfo->NextEntryOffset == 0) {
break;
}
//
// There is another record so advance FileInfo to the next
// record
//
FileInfo = (PFILE_ADIRECTORY_INFORMATION)(((PUCHAR)FileInfo) + FileInfo->NextEntryOffset);
}
//
// zero out the buffer so next time we'll recognize the end of data
//
for (i = 0; i < BUFFERSIZE; i += 1) { Buffer[i] = 0; }
}
//
// Now close the file
//
if (!NT_SUCCESS(Status = NtClose( FileHandle ))) {
CloseError( Status );
}
//
// And return to our caller
//
return;
}
VOID Mkdir(
IN PCHAR String
)
{
NTSTATUS Status;
HANDLE FileHandle;
OBJECT_ATTRIBUTES ObjectAttributes;
STRING NameString;
IO_STATUS_BLOCK IoStatus;
LARGE_INTEGER AllocationSize;
//
// Get the filename
//
simprintf("Mkdir ", 0);
simprintf(String, 0);
simprintf("\n", 0);
//
// Create the new directory
//
AllocationSize = LiFromLong( 4 );
RtlInitString( &NameString, String );
InitializeObjectAttributes( &ObjectAttributes, &NameString, 0, NULL, NULL );
if (!NT_SUCCESS(Status = NtCreateFile( &FileHandle,
SYNCHRONIZE,
&ObjectAttributes,
&IoStatus,
&AllocationSize,
0L,
0L,
FILE_CREATE,
WriteThrough | FILE_DIRECTORY_FILE,
(PVOID)NULL,
0L ))) {
CreateFileError( Status , String );
return;
}
//
// Now close the directory
//
if (!NT_SUCCESS(Status = NtClose( FileHandle ))) {
CloseError( Status );
}
//
// And return to our caller
//
return;
}
VOID WaitForSingleObjectError(NTSTATUS Status)
{ printf("%s WaitForSingleObject Error %X\n", Prefix, Status); }
VOID CreateFileError(NTSTATUS Status, PCHAR File)
{ printf("%s CreateFile of %s Error %X\n", Prefix, File, Status); }
VOID OpenFileError(NTSTATUS Status, PCHAR File)
{ printf("%s OpenFile of %s Error %X\n", Prefix, File, Status); }
VOID ReadFileError(NTSTATUS Status)
{ printf("%s ReadFile Error %X\n", Prefix, Status); }
VOID WriteFileError(NTSTATUS Status)
{ printf("%s WriteFile Error %X\n", Prefix, Status); }
VOID SetInformationFileError(NTSTATUS Status)
{ printf("%s SetInfoFile Error %X\n", Prefix, Status); }
VOID QueryInformationFileError(NTSTATUS Status)
{ printf("%s QueryInfoFile Error %X\n", Prefix, Status); }
VOID CloseError(NTSTATUS Status)
{ printf("%s Close Error %X\n", Prefix, Status); }
VOID IoStatusError(NTSTATUS Status)
{ printf("%s IoStatus Error %X\n", Prefix, Status); }
VOID CheckIoStatus(PIO_STATUS_BLOCK IoStatus, ULONG Length, BOOLEAN Read)
{
if (!NT_SUCCESS(IoStatus->Status)) {
printf(" IoStatus->Status Error %08lx\n", IoStatus->Status);
}
if ((!Read && (IoStatus->Information != Length))
||
(Read && (IoStatus->Information > Length))) {
printf(" IoStatus->Information Error %08lx\n", IoStatus->Information);
}
}