You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
679 lines
19 KiB
679 lines
19 KiB
#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 );
|
|
}
|
|
|
|
if (!SynchronousCmds) {
|
|
|
|
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;
|
|
}
|
|
|