696 lines
19 KiB
C
696 lines
19 KiB
C
|
#include "brian.h"
|
|||
|
|
|||
|
typedef struct _ASYNC_NOTIFY {
|
|||
|
|
|||
|
USHORT FileIndex;
|
|||
|
BOOLEAN UseEvent;
|
|||
|
PIO_APC_ROUTINE ApcRoutine;
|
|||
|
PVOID ApcContext;
|
|||
|
PUSHORT BufferIndexPtr;
|
|||
|
USHORT BufferIndex;
|
|||
|
ULONG Length;
|
|||
|
ULONG CompletionFilter;
|
|||
|
BOOLEAN WatchTree;
|
|||
|
BOOLEAN DisplayParms;
|
|||
|
BOOLEAN VerboseResults;
|
|||
|
USHORT AsyncIndex;
|
|||
|
|
|||
|
} ASYNC_NOTIFY, *PASYNC_NOTIFY;
|
|||
|
|
|||
|
#define USE_EVENT_DEFAULT TRUE
|
|||
|
#define APC_ROUTINE_DEFAULT NULL
|
|||
|
#define APC_CONTEXT_DEFAULT NULL
|
|||
|
#define LENGTH_DEFAULT 0
|
|||
|
#define FILTER_DEFAULT FILE_NOTIFY_CHANGE_FILE_NAME
|
|||
|
#define WATCH_TREE_DEFAULT FALSE
|
|||
|
#define DISPLAY_PARMS_DEFAULT FALSE
|
|||
|
#define VERBOSE_RESULTS_DEFAULT FALSE
|
|||
|
|
|||
|
VOID
|
|||
|
FullNotify(
|
|||
|
IN OUT PASYNC_NOTIFY AsyncNotify
|
|||
|
);
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
InputNotifyChange(
|
|||
|
IN PCHAR ParamBuffer
|
|||
|
)
|
|||
|
{
|
|||
|
ULONG FileIndex;
|
|||
|
BOOLEAN UseEvent;
|
|||
|
PIO_APC_ROUTINE ApcRoutine;
|
|||
|
PVOID ApcContext;
|
|||
|
PUSHORT BufferIndexPtr;
|
|||
|
USHORT BufferIndex;
|
|||
|
ULONG Length;
|
|||
|
ULONG CompletionFilter;
|
|||
|
BOOLEAN WatchTree;
|
|||
|
BOOLEAN DisplayParms;
|
|||
|
BOOLEAN VerboseResults;
|
|||
|
USHORT AsyncIndex;
|
|||
|
|
|||
|
BOOLEAN ParamReceived;
|
|||
|
BOOLEAN LastInput;
|
|||
|
|
|||
|
//
|
|||
|
// Set the defaults.
|
|||
|
//
|
|||
|
|
|||
|
UseEvent = USE_EVENT_DEFAULT;
|
|||
|
ApcRoutine = APC_ROUTINE_DEFAULT;
|
|||
|
ApcContext = APC_CONTEXT_DEFAULT;
|
|||
|
BufferIndexPtr = NULL;
|
|||
|
BufferIndex = 0;
|
|||
|
Length = LENGTH_DEFAULT;
|
|||
|
CompletionFilter = FILTER_DEFAULT;
|
|||
|
WatchTree = WATCH_TREE_DEFAULT;
|
|||
|
DisplayParms = DISPLAY_PARMS_DEFAULT;
|
|||
|
VerboseResults = VERBOSE_RESULTS_DEFAULT;
|
|||
|
AsyncIndex = 0;
|
|||
|
|
|||
|
ParamReceived = FALSE;
|
|||
|
LastInput = TRUE;
|
|||
|
|
|||
|
//
|
|||
|
// While there is more input, analyze the parameter and update the
|
|||
|
// query flags.
|
|||
|
//
|
|||
|
|
|||
|
while (TRUE) {
|
|||
|
|
|||
|
ULONG DummyCount;
|
|||
|
ULONG TempIndex;
|
|||
|
|
|||
|
//
|
|||
|
// 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 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 = AsciiToInteger( ParamBuffer );
|
|||
|
|
|||
|
ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
|
|||
|
|
|||
|
ParamReceived = TRUE;
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
//
|
|||
|
// Check whether we should use an event to signal
|
|||
|
// completion.
|
|||
|
//
|
|||
|
|
|||
|
case 'e' :
|
|||
|
case 'E' :
|
|||
|
|
|||
|
//
|
|||
|
// Legal values for use event are T/t or F/f.
|
|||
|
//
|
|||
|
ParamBuffer++;
|
|||
|
|
|||
|
if (*ParamBuffer == 'T'
|
|||
|
|| *ParamBuffer == 't') {
|
|||
|
|
|||
|
UseEvent = TRUE;
|
|||
|
ParamBuffer++;
|
|||
|
|
|||
|
} else if (*ParamBuffer == 'F'
|
|||
|
|| *ParamBuffer == 'f') {
|
|||
|
|
|||
|
UseEvent = FALSE;
|
|||
|
ParamBuffer++;
|
|||
|
}
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
//
|
|||
|
// Check whether we should watch the tree.
|
|||
|
//
|
|||
|
|
|||
|
case 'w' :
|
|||
|
case 'W' :
|
|||
|
|
|||
|
//
|
|||
|
// Legal values for use event are T/t or F/f.
|
|||
|
//
|
|||
|
ParamBuffer++;
|
|||
|
|
|||
|
if (*ParamBuffer == 'T'
|
|||
|
|| *ParamBuffer == 't') {
|
|||
|
|
|||
|
WatchTree = TRUE;
|
|||
|
ParamBuffer++;
|
|||
|
|
|||
|
} else if (*ParamBuffer == 'F'
|
|||
|
|| *ParamBuffer == 'f') {
|
|||
|
|
|||
|
WatchTree = FALSE;
|
|||
|
ParamBuffer++;
|
|||
|
}
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
//
|
|||
|
// Update the buffer index.
|
|||
|
//
|
|||
|
case 'b' :
|
|||
|
case 'B' :
|
|||
|
|
|||
|
//
|
|||
|
// 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++;
|
|||
|
|
|||
|
TempIndex = AsciiToInteger( ParamBuffer );
|
|||
|
BufferIndex = (USHORT) TempIndex;
|
|||
|
BufferIndexPtr = &BufferIndex;
|
|||
|
|
|||
|
Length = Buffers[BufferIndex].Length;
|
|||
|
|
|||
|
ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
//
|
|||
|
// 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++;
|
|||
|
|
|||
|
Length = AsciiToInteger( ParamBuffer );
|
|||
|
|
|||
|
ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
//
|
|||
|
// Update the completion filter.
|
|||
|
//
|
|||
|
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++;
|
|||
|
|
|||
|
SwitchBool = TRUE;
|
|||
|
while (*ParamBuffer
|
|||
|
&& *ParamBuffer != ' '
|
|||
|
&& *ParamBuffer != '\t') {
|
|||
|
|
|||
|
//
|
|||
|
// Perform switch on character.
|
|||
|
//
|
|||
|
switch (*ParamBuffer) {
|
|||
|
|
|||
|
case 'a' :
|
|||
|
case 'A' :
|
|||
|
|
|||
|
CompletionFilter |= FILE_NOTIFY_CHANGE_FILE_NAME;
|
|||
|
break;
|
|||
|
|
|||
|
case 'b' :
|
|||
|
case 'B' :
|
|||
|
|
|||
|
CompletionFilter |= FILE_NOTIFY_CHANGE_DIR_NAME;
|
|||
|
break;
|
|||
|
|
|||
|
case 'c' :
|
|||
|
case 'C' :
|
|||
|
|
|||
|
CompletionFilter |= FILE_NOTIFY_CHANGE_ATTRIBUTES;
|
|||
|
break;
|
|||
|
|
|||
|
case 'd' :
|
|||
|
case 'D' :
|
|||
|
|
|||
|
CompletionFilter |= FILE_NOTIFY_CHANGE_SIZE;
|
|||
|
break;
|
|||
|
|
|||
|
case 'e' :
|
|||
|
case 'E' :
|
|||
|
|
|||
|
CompletionFilter |= FILE_NOTIFY_CHANGE_LAST_WRITE;
|
|||
|
break;
|
|||
|
|
|||
|
case 'f' :
|
|||
|
case 'F' :
|
|||
|
|
|||
|
CompletionFilter |= FILE_NOTIFY_CHANGE_LAST_ACCESS;
|
|||
|
break;
|
|||
|
|
|||
|
case 'g' :
|
|||
|
case 'G' :
|
|||
|
|
|||
|
CompletionFilter |= FILE_NOTIFY_CHANGE_CREATION;
|
|||
|
break;
|
|||
|
|
|||
|
case 'h' :
|
|||
|
case 'H' :
|
|||
|
|
|||
|
CompletionFilter |= FILE_NOTIFY_CHANGE_EA;
|
|||
|
break;
|
|||
|
|
|||
|
case 'i' :
|
|||
|
case 'I' :
|
|||
|
|
|||
|
CompletionFilter |= FILE_NOTIFY_CHANGE_SECURITY;
|
|||
|
break;
|
|||
|
|
|||
|
case 'j' :
|
|||
|
case 'J' :
|
|||
|
|
|||
|
CompletionFilter |= FILE_NOTIFY_CHANGE_STREAM_NAME;
|
|||
|
break;
|
|||
|
|
|||
|
case 'k' :
|
|||
|
case 'K' :
|
|||
|
|
|||
|
CompletionFilter |= FILE_NOTIFY_CHANGE_STREAM_SIZE;
|
|||
|
break;
|
|||
|
|
|||
|
case 'l' :
|
|||
|
case 'L' :
|
|||
|
|
|||
|
CompletionFilter |= FILE_NOTIFY_CHANGE_STREAM_WRITE;
|
|||
|
break;
|
|||
|
|
|||
|
case 'y' :
|
|||
|
case 'Y' :
|
|||
|
|
|||
|
CompletionFilter = FILE_NOTIFY_VALID_MASK;
|
|||
|
break;
|
|||
|
|
|||
|
case 'z' :
|
|||
|
case 'Z' :
|
|||
|
|
|||
|
CompletionFilter = 0;
|
|||
|
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: ncd [options]* -i<index> [options]*\n" );
|
|||
|
printf( "\n Options:" );
|
|||
|
printf( "\n -i<digits> File index" );
|
|||
|
printf( "\n -b<digits> Buffer to store results" );
|
|||
|
printf( "\n -l<digits> Stated length of buffer" );
|
|||
|
printf( "\n -f<chars> Completion filter" );
|
|||
|
printf( "\n -w[t|f] Watch directory tree" );
|
|||
|
printf( "\n -e[t|f] Use event on completion" );
|
|||
|
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 notify routine.
|
|||
|
//
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
NTSTATUS Status;
|
|||
|
SIZE_T RegionSize;
|
|||
|
ULONG TempIndex;
|
|||
|
|
|||
|
PASYNC_NOTIFY AsyncNotify;
|
|||
|
|
|||
|
HANDLE ThreadHandle;
|
|||
|
ULONG ThreadId;
|
|||
|
|
|||
|
RegionSize = sizeof( ASYNC_NOTIFY );
|
|||
|
|
|||
|
Status = AllocateBuffer( 0, &RegionSize, &TempIndex );
|
|||
|
AsyncIndex = (USHORT) TempIndex;
|
|||
|
|
|||
|
if (!NT_SUCCESS( Status )) {
|
|||
|
|
|||
|
printf("\n\tInputRead: Unable to allocate async structure" );
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
AsyncNotify = (PASYNC_NOTIFY) Buffers[AsyncIndex].Buffer;
|
|||
|
|
|||
|
AsyncNotify->FileIndex = (USHORT) FileIndex;
|
|||
|
AsyncNotify->UseEvent = UseEvent;
|
|||
|
AsyncNotify->ApcRoutine = ApcRoutine;
|
|||
|
AsyncNotify->ApcContext = ApcContext;
|
|||
|
|
|||
|
|
|||
|
AsyncNotify->BufferIndex = BufferIndex;
|
|||
|
AsyncNotify->BufferIndexPtr = BufferIndexPtr
|
|||
|
? &AsyncNotify->BufferIndex
|
|||
|
: BufferIndexPtr;
|
|||
|
AsyncNotify->Length = Length;
|
|||
|
|
|||
|
AsyncNotify->CompletionFilter = CompletionFilter;
|
|||
|
AsyncNotify->WatchTree = WatchTree;
|
|||
|
|
|||
|
AsyncNotify->DisplayParms = DisplayParms;
|
|||
|
AsyncNotify->VerboseResults = VerboseResults;
|
|||
|
AsyncNotify->AsyncIndex = AsyncIndex;
|
|||
|
|
|||
|
if (!SynchronousCmds) {
|
|||
|
|
|||
|
ThreadHandle = CreateThread( NULL,
|
|||
|
0,
|
|||
|
FullNotify,
|
|||
|
AsyncNotify,
|
|||
|
0,
|
|||
|
&ThreadId );
|
|||
|
|
|||
|
if (ThreadHandle == 0) {
|
|||
|
|
|||
|
printf( "\nInputNotify: Spawning thread fails -> %d\n", GetLastError() );
|
|||
|
return;
|
|||
|
}
|
|||
|
} else {
|
|||
|
|
|||
|
FullNotify( AsyncNotify );
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
FullNotify(
|
|||
|
IN OUT PASYNC_NOTIFY AsyncNotify
|
|||
|
)
|
|||
|
{
|
|||
|
NTSTATUS Status;
|
|||
|
IO_STATUS_BLOCK Iosb;
|
|||
|
|
|||
|
HANDLE ThisEvent;
|
|||
|
USHORT ThisEventIndex;
|
|||
|
USHORT ThisBufferIndex;
|
|||
|
|
|||
|
BOOLEAN UnwindNotifyBuffer = FALSE;
|
|||
|
|
|||
|
BOOLEAN UnwindEvent = FALSE;
|
|||
|
|
|||
|
Status = STATUS_SUCCESS;
|
|||
|
|
|||
|
if (AsyncNotify->DisplayParms) {
|
|||
|
|
|||
|
bprint "\nNotify Parameters" );
|
|||
|
bprint "\n File Handle Index -> %d", AsyncNotify->FileIndex );
|
|||
|
bprint "\n Buffer Index Ptr -> %08lx", AsyncNotify->BufferIndexPtr );
|
|||
|
if (AsyncNotify->BufferIndexPtr) {
|
|||
|
|
|||
|
bprint "\n BufferIndex value -> %04x", AsyncNotify->BufferIndex );
|
|||
|
}
|
|||
|
|
|||
|
bprint "\n Length -> %08lx", AsyncNotify->Length );
|
|||
|
|
|||
|
bprint "\n CompletionFilter -> %08lx", AsyncNotify->CompletionFilter );
|
|||
|
bprint "\n WatchTree -> %d", AsyncNotify->WatchTree );
|
|||
|
bprint "\n UseEvent -> %d", AsyncNotify->UseEvent );
|
|||
|
bprint "\n ApcRoutine -> %08lx", AsyncNotify->ApcRoutine );
|
|||
|
bprint "\n ApcContext -> %08lx", AsyncNotify->ApcContext );
|
|||
|
|
|||
|
bprint "\n\n" );
|
|||
|
}
|
|||
|
|
|||
|
try {
|
|||
|
|
|||
|
SIZE_T ThisLength;
|
|||
|
|
|||
|
//
|
|||
|
// If we need a buffer, allocate it now.
|
|||
|
//
|
|||
|
|
|||
|
if (AsyncNotify->BufferIndexPtr == NULL ) {
|
|||
|
|
|||
|
ULONG TempIndex;
|
|||
|
|
|||
|
ThisLength = 4096;
|
|||
|
|
|||
|
Status = AllocateBuffer( 0L, &ThisLength, &TempIndex );
|
|||
|
|
|||
|
ThisBufferIndex = (USHORT) TempIndex;
|
|||
|
|
|||
|
if (!NT_SUCCESS( Status )) {
|
|||
|
|
|||
|
bprint "\n\tFullNotify: Unable to allocate a notify buffer" );
|
|||
|
try_return( Status );
|
|||
|
}
|
|||
|
|
|||
|
bprint "\n\tFullNotify: Reading into buffer -> %04x\n", ThisBufferIndex );
|
|||
|
bprint "\n" );
|
|||
|
|
|||
|
UnwindNotifyBuffer = TRUE;
|
|||
|
|
|||
|
AsyncNotify->Length = (ULONG) ThisLength;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
ThisBufferIndex = AsyncNotify->BufferIndex;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Check that the buffer index is valid.
|
|||
|
//
|
|||
|
|
|||
|
if (ThisBufferIndex >= MAX_BUFFERS) {
|
|||
|
|
|||
|
bprint "\n\tFullNotify: The read buffer index is invalid" );
|
|||
|
try_return( Status = STATUS_INVALID_HANDLE );
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Check that the file index is valid.
|
|||
|
//
|
|||
|
|
|||
|
if (AsyncNotify->FileIndex >= MAX_HANDLES) {
|
|||
|
|
|||
|
bprint "\n\tFullNotify: The file index is invalid" );
|
|||
|
try_return( Status = STATUS_INVALID_HANDLE );
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// If we need an event, allocate and set it now.
|
|||
|
//
|
|||
|
|
|||
|
if (AsyncNotify->UseEvent == TRUE) {
|
|||
|
|
|||
|
Status = ObtainEvent( &ThisEventIndex );
|
|||
|
|
|||
|
if (!NT_SUCCESS( Status )) {
|
|||
|
|
|||
|
bprint "\n\tFullNotify: Unable to allocate an event" );
|
|||
|
try_return( Status );
|
|||
|
}
|
|||
|
|
|||
|
UnwindEvent = TRUE;
|
|||
|
ThisEvent = Events[ThisEventIndex].Handle;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
ThisEvent = 0;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Call the read routine.
|
|||
|
//
|
|||
|
|
|||
|
Status = NtNotifyChangeDirectoryFile( Handles[AsyncNotify->FileIndex].Handle,
|
|||
|
ThisEvent,
|
|||
|
AsyncNotify->ApcRoutine,
|
|||
|
AsyncNotify->ApcContext,
|
|||
|
&Iosb,
|
|||
|
Buffers[ThisBufferIndex].Buffer,
|
|||
|
AsyncNotify->Length,
|
|||
|
AsyncNotify->CompletionFilter,
|
|||
|
AsyncNotify->WatchTree );
|
|||
|
|
|||
|
if (AsyncNotify->VerboseResults) {
|
|||
|
|
|||
|
bprint "\nNotifyChangeDir: Status -> %08lx\n", Status );
|
|||
|
|
|||
|
if (AsyncNotify->UseEvent && NT_SUCCESS( Status )) {
|
|||
|
|
|||
|
if ((Status = NtWaitForSingleObject( ThisEvent,
|
|||
|
FALSE,
|
|||
|
NULL )) != STATUS_SUCCESS) {
|
|||
|
|
|||
|
bprint "\n\tNotifyChangeDir: Wait for event failed -> %08lx\n", Status );
|
|||
|
try_return( Status );
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (NT_SUCCESS( Status )) {
|
|||
|
|
|||
|
bprint "\nNotifyChangeDir: Iosb.Information -> %08lx", Iosb.Information );
|
|||
|
bprint "\nNotifyChangeDir: Iosb.Status -> %08lx", Iosb.Status );
|
|||
|
}
|
|||
|
|
|||
|
bprint "\n" );
|
|||
|
}
|
|||
|
|
|||
|
try_return( Status );
|
|||
|
|
|||
|
try_exit: NOTHING;
|
|||
|
} finally {
|
|||
|
|
|||
|
if (UnwindEvent) {
|
|||
|
|
|||
|
FreeEvent( ThisEventIndex );
|
|||
|
}
|
|||
|
|
|||
|
DeallocateBuffer( AsyncNotify->AsyncIndex );
|
|||
|
}
|
|||
|
|
|||
|
NtTerminateThread( 0, STATUS_SUCCESS );
|
|||
|
}
|