windows-nt/Source/XPSP1/NT/base/fs/ntfs/tests/bshell/tsetvol.c
2020-09-26 16:20:57 +08:00

677 lines
18 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "brian.h"
typedef struct _ASYNC_SET_VOLUME {
USHORT FileIndex;
FILE_INFORMATION_CLASS FileInfoClass;
ULONG BufferLength;
PULONG BufferLengthPtr;
ULONG LabelLength;
PULONG LabelLengthPtr;
USHORT LabelIndex;
BOOLEAN LabelBufferAllocated;
BOOLEAN DisplayParms;
BOOLEAN VerboseResults;
USHORT AsyncIndex;
} ASYNC_SET_VOLUME, *PASYNC_SET_VOLUME;
#define SET_VOLUME_LENGTH_DEFAULT 100
#define FILE_INFO_CLASS_DEFAULT FileFsLabelInformation
#define DISPLAY_PARMS_DEFAULT FALSE
#define VERBOSE_DEFAULT FALSE
VOID
FullSetVolume(
IN OUT PASYNC_SET_VOLUME AsyncSetVolume
);
VOID
SetFsLabelInformation(
IN OUT PASYNC_SET_VOLUME AsyncSetVolume
);
VOID
InputSetVolume (
IN PCHAR ParamBuffer
)
{
USHORT FileIndex;
FILE_INFORMATION_CLASS FileInfoClass;
ULONG BufferLength;
PULONG BufferLengthPtr;
ANSI_STRING AnsiLabelString;
ULONG LabelLength;
PULONG LabelLengthPtr;
USHORT LabelIndex;
BOOLEAN LabelBufferAllocated;
PUCHAR LabelPtr;
BOOLEAN DisplayParms;
BOOLEAN VerboseResults;
USHORT AsyncIndex;
BOOLEAN ParamReceived;
BOOLEAN LastInput;
//
// Set the defaults.
//
FileInfoClass = FILE_INFO_CLASS_DEFAULT;
BufferLengthPtr = NULL;
LabelLengthPtr = NULL;
LabelBufferAllocated = FALSE;
LabelPtr = NULL;
DisplayParms = DISPLAY_PARMS_DEFAULT;
VerboseResults = VERBOSE_DEFAULT;
ParamReceived = FALSE;
LastInput = TRUE;
//
// While there is more input, analyze the parameter and update the
// query flags.
//
while (TRUE) {
ULONG DummyCount;
//
// Swallow leading white spaces.
//
ParamBuffer = SwallowWhite( ParamBuffer, &DummyCount );
if (*ParamBuffer) {
//
// If the next parameter is legal then check the paramter value.
// Update the parameter value.
//
if ((*ParamBuffer == '-'
|| *ParamBuffer == '/')
&& (ParamBuffer++, *ParamBuffer != '\0')) {
BOOLEAN SwitchBool;
//
// Switch on the next character.
//
switch (*ParamBuffer) {
//
// Update the byte count.
//
case 'l' :
case 'L' :
//
// Move to the next character, as long as there
// are no white spaces continue analyzing letters.
// On the first bad letter, skip to the next
// parameter.
//
ParamBuffer++;
if (*ParamBuffer == '\0') {
break;
}
switch (*ParamBuffer) {
case 'b':
case 'B':
BufferLength = AsciiToInteger( ++ParamBuffer );
BufferLengthPtr = &BufferLength;
break;
case 'l':
case 'L':
LabelLength = AsciiToInteger( ++ParamBuffer );
LabelLengthPtr = &LabelLength;
break;
}
ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
break;
//
// Update the label name.
//
case 'f' :
case 'F' :
//
// Move to the next character, as long as there
// are no white spaces continue analyzing letters.
// On the first bad letter, skip to the next
// parameter.
//
ParamBuffer++;
if (*ParamBuffer == '\0') {
break;
}
switch (*ParamBuffer) {
PUCHAR TempPtr;
case 'l':
case 'L':
//
// Remember the buffer offset and get the filename.
//
ParamBuffer++;
TempPtr = ParamBuffer;
DummyCount = 0;
ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
//
// If the name length is 0, then ignore this entry.
//
if (DummyCount) {
AnsiLabelString.Length = (USHORT) DummyCount;
AnsiLabelString.Buffer = TempPtr;
LabelPtr = TempPtr;
LabelLength = (ULONG) RtlAnsiStringToUnicodeSize( &AnsiLabelString) - sizeof( WCHAR );
LabelLengthPtr = &LabelLength;
}
break;
}
ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
break;
//
// Update the file handle index.
//
case 'i' :
case 'I' :
//
// Move to the next character, as long as there
// are no white spaces continue analyzing letters.
// On the first bad letter, skip to the next
// parameter.
//
ParamBuffer++;
FileIndex = (USHORT) AsciiToInteger( ParamBuffer );
ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
ParamReceived = TRUE;
break;
//
// Update the information class.
//
case 'c' :
case 'C' :
//
// Move to the next character, as long as there
// are no white spaces continue analyzing letters.
// On the first bad letter, skip to the next
// parameter.
//
ParamBuffer++;
SwitchBool = TRUE;
while (*ParamBuffer
&& *ParamBuffer != ' '
&& *ParamBuffer != '\t') {
//
// Perform switch on character.
//
switch (*ParamBuffer) {
case 'a' :
case 'A' :
FileInfoClass = FileFsLabelInformation;
break;
default :
ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
SwitchBool = FALSE;
}
if (!SwitchBool) {
break;
}
ParamBuffer++;
}
break;
case 'v' :
case 'V' :
//
// Legal values for params are T/t or F/f.
//
ParamBuffer++;
if( *ParamBuffer == 'T'
|| *ParamBuffer == 't' ) {
VerboseResults = TRUE;
ParamBuffer++;
} else if( *ParamBuffer == 'F'
|| *ParamBuffer == 'f' ) {
VerboseResults = FALSE;
ParamBuffer++;
}
break;
case 'y' :
case 'Y' :
//
// Set the display parms flag and jump over this
// character.
//
DisplayParms = TRUE;
ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
break;
case 'z' :
case 'Z' :
//
// Set flag for more input and jump over this char.
//
LastInput = FALSE;
ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
break;
default :
//
// Swallow to the next white space and continue the
// loop.
//
ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
}
}
//
// Else the text is invalid, skip the entire block.
//
//
//
// Else if there is no input then exit.
//
} else if( LastInput ) {
break;
//
// Else try to read another line for open parameters.
//
} else {
}
}
//
// If no parameters were received then display the syntax message.
//
if (!ParamReceived) {
printf( "\n Usage: sv [options]* -i<index> [options]*\n" );
printf( "\n Options:" );
printf( "\n -i<digits> File index" );
printf( "\n -lb<digits> Buffer length" );
printf( "\n -c<char> File information class" );
printf( "\n -fl<name> Name for label" );
printf( "\n -ll<digits> Stated length of label" );
printf( "\n -v[t|f] Verbose results" );
printf( "\n -y Display parameters to query" );
printf( "\n -z Additional input line" );
printf( "\n\n" );
//
// Else call our read routine.
//
} else {
NTSTATUS Status;
SIZE_T RegionSize;
ULONG TempIndex;
PASYNC_SET_VOLUME AsyncSetVolume;
HANDLE ThreadHandle;
ULONG ThreadId;
RegionSize = sizeof( ASYNC_SET_VOLUME );
Status = AllocateBuffer( 0, &RegionSize, &TempIndex );
AsyncIndex = (USHORT) TempIndex;
if (!NT_SUCCESS( Status )) {
printf("\n\tInputSetFile: Unable to allocate async structure" );
} else {
UNICODE_STRING UnicodeString;
//
// If we need a buffer for the label, allocate it now.
//
if (LabelPtr == NULL) {
RtlInitAnsiString( &AnsiLabelString, "" );
LabelPtr = AnsiLabelString.Buffer;
LabelLength = 100;
}
RegionSize = LabelLength;
Status = AllocateBuffer( 0, &RegionSize, &TempIndex );
if (!NT_SUCCESS( Status )) {
printf( "\n\tInputSetVolume: Unable to allocate label structure" );
DeallocateBuffer( AsyncIndex );
return;
}
UnicodeString.Buffer = (PWSTR) Buffers[TempIndex].Buffer;
UnicodeString.MaximumLength = (USHORT) Buffers[TempIndex].Length;
LabelIndex = (USHORT) TempIndex;
LabelBufferAllocated = TRUE;
//
// Store the name in the buffer.
//
RtlAnsiStringToUnicodeString( &UnicodeString,
&AnsiLabelString,
FALSE );
AsyncSetVolume = (PASYNC_SET_VOLUME) Buffers[AsyncIndex].Buffer;
AsyncSetVolume->FileIndex = (USHORT) FileIndex;
AsyncSetVolume->BufferLength = BufferLength;
AsyncSetVolume->BufferLengthPtr = BufferLengthPtr ?
&AsyncSetVolume->BufferLength :
NULL;
AsyncSetVolume->FileInfoClass = FileInfoClass;
AsyncSetVolume->LabelLength = LabelLength;
AsyncSetVolume->LabelLengthPtr = LabelLengthPtr
? &AsyncSetVolume->LabelLength
: NULL;
AsyncSetVolume->LabelIndex = LabelIndex;
AsyncSetVolume->LabelBufferAllocated = LabelBufferAllocated;
AsyncSetVolume->DisplayParms = DisplayParms;
AsyncSetVolume->VerboseResults = VerboseResults;
AsyncSetVolume->AsyncIndex = AsyncIndex;
if (!SynchronousCmds) {
ThreadHandle = CreateThread( NULL,
0,
FullSetVolume,
AsyncSetVolume,
0,
&ThreadId );
if (ThreadHandle == 0) {
printf( "\nInputSetVolume: Spawning thread fails -> %d\n", GetLastError() );
if (LabelBufferAllocated) {
DeallocateBuffer( LabelIndex );
}
DeallocateBuffer( AsyncIndex );
return;
}
} else {
FullSetVolume( AsyncSetVolume );
}
}
}
return;
}
VOID
FullSetVolume(
IN OUT PASYNC_SET_VOLUME AsyncSetVolume
)
{
try {
//
// Case on the information type and call the appropriate routine.
//
switch (AsyncSetVolume->FileInfoClass) {
case FileFsLabelInformation:
SetFsLabelInformation( AsyncSetVolume );
break;
default:
bprint "\nFullSetVolume: Unrecognized information class\n" );
}
try_return( NOTHING );
try_exit: NOTHING;
} finally {
if (AsyncSetVolume->LabelBufferAllocated) {
DeallocateBuffer( AsyncSetVolume->LabelIndex );
}
DeallocateBuffer( AsyncSetVolume->AsyncIndex );
}
NtTerminateThread( 0, STATUS_SUCCESS );
}
VOID
SetFsLabelInformation(
IN OUT PASYNC_SET_VOLUME AsyncSetVolume
)
{
NTSTATUS Status;
PFILE_FS_LABEL_INFORMATION LabelInformation;
USHORT BufferIndex;
UNICODE_STRING UniLabel;
ANSI_STRING AnsiLabel;
BOOLEAN UnwindBufferIndex = FALSE;
BOOLEAN UnwindFreeAnsiString = FALSE;
//
// Check that there is a label specified.
//
if (!AsyncSetVolume->LabelBufferAllocated) {
bprint "\nSet Label Information: No label was specified\n" );
return;
}
UniLabel.Buffer = (PWSTR) Buffers[AsyncSetVolume->LabelIndex].Buffer;
UniLabel.MaximumLength =
UniLabel.Length = (USHORT) AsyncSetVolume->LabelLength;
UniLabel.MaximumLength += 2;
Status = RtlUnicodeStringToAnsiString( &AnsiLabel,
&UniLabel,
TRUE );
if (!NT_SUCCESS( Status )) {
bprint "\nSetLabelInfo: Can't allocate ansi buffer -> %08lx\n", Status );
AsyncSetVolume->DisplayParms = FALSE;
} else {
UnwindFreeAnsiString = TRUE;
}
if (AsyncSetVolume->DisplayParms) {
bprint "\nSet LabelInformation Parameters" );
bprint "\n File Handle Index -> %d", AsyncSetVolume->FileIndex );
bprint "\n BufferLengthPtr -> %08lx", AsyncSetVolume->BufferLengthPtr );
if (AsyncSetVolume->BufferLengthPtr) {
bprint "\n BufferLength value -> %08x", AsyncSetVolume->BufferLength );
}
bprint "\n Label length -> %d", AsyncSetVolume->LabelLength );
bprint "\n New label -> %s", AnsiLabel.Buffer );
bprint "\n\n" );
}
try {
SIZE_T RegionSize;
ULONG TempIndex;
IO_STATUS_BLOCK Iosb;
RegionSize = sizeof( FILE_FS_LABEL_INFORMATION ) + AsyncSetVolume->LabelLength;
Status = AllocateBuffer( 0, &RegionSize, &TempIndex );
BufferIndex = (USHORT) TempIndex;
if (!NT_SUCCESS( Status )) {
bprint "\n\tSetLabelInformation: Unable to allocate structure" );
try_return( NOTHING );
}
UnwindBufferIndex = TRUE;
LabelInformation = (PFILE_FS_LABEL_INFORMATION) Buffers[BufferIndex].Buffer;
//
// Fill in the new information.
//
LabelInformation->VolumeLabelLength = AsyncSetVolume->LabelLength;
RtlMoveMemory( LabelInformation->VolumeLabel,
UniLabel.Buffer,
AsyncSetVolume->LabelLength );
Iosb.Status = STATUS_SUCCESS;
Iosb.Information = 0;
Status = NtSetVolumeInformationFile( Handles[AsyncSetVolume->FileIndex].Handle,
&Iosb,
LabelInformation,
AsyncSetVolume->BufferLengthPtr
? AsyncSetVolume->BufferLength
: Buffers[BufferIndex].Length,
FileFsLabelInformation );
if (AsyncSetVolume->VerboseResults) {
bprint "\nSetInformationFile: Status -> %08lx", Status );
if (NT_SUCCESS( Status )) {
bprint "\n Iosb.Information -> %08lx", Iosb.Information );
bprint "\n Iosb.Status -> %08lx", Iosb.Status );
}
bprint "\n" );
}
try_exit: NOTHING;
} finally {
if (UnwindFreeAnsiString) {
RtlFreeAnsiString( &AnsiLabel );
}
if (UnwindBufferIndex) {
DeallocateBuffer( BufferIndex );
}
}
return;
}