829 lines
22 KiB
C
829 lines
22 KiB
C
|
/*++
|
|||
|
|
|||
|
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);
|
|||
|
}
|
|||
|
}
|
|||
|
|