/*++ Copyright (c) 1989 Microsoft Corporation Module Name: querydir.c Abstract: This module implements the mini redirector call down routines pertaining to query directory. Author: joelinn [joelinn] 01-02-97 Revision History: --*/ #include "precomp.h" #pragma hdrstop // // The local debug trace level // #define Dbg (DEBUG_TRACE_DIRCTRL) // // External declartions // NTSTATUS MRxProxyQueryDirOrFlushContinuation( MRXPROXY_ASYNCENGINE_ARGUMENT_SIGNATURE ); RXDT_DefineCategory(DIRCTRL); #define Dbg (DEBUG_TRACE_DIRCTRL) ULONG MRxProxyStopOnLoudCompletion = TRUE; NTSTATUS MRxProxyQueryDirectory( IN PRX_CONTEXT RxContext ) /*++ Routine Description: This routine handles network querydir requests. Arguments: RxContext - the RDBSS context Return Value: RXSTATUS - The return status for the operation --*/ { NTSTATUS Status = STATUS_SUCCESS; RxCaptureFcb; RxCaptureFobx; PAGED_CODE(); RxDbgTrace(+1, Dbg, ("MRxProxyQueryDir %08lx\n", RxContext )); ASSERT( NodeType(capFobx->pSrvOpen) == RDBSS_NTC_SRVOPEN ); MRxProxySetLoud("QueryDir ",RxContext,&(capFobx->UnicodeQueryTemplate)); Status = MRxProxyAsyncEngineOuterWrapper( RxContext, MRXPROXY_ASYNCENG_CTX_FROM_QUERYDIR, MRxProxyQueryDirOrFlushContinuation, "MRxProxyQueryDir", TRUE, //loudprocessing (BOOLEAN)MRxProxyStopOnLoudCompletion ); RxDbgTrace(-1, Dbg, ("MRxProxyQueryDir %08lx exit with status=%08lx\n", RxContext, Status )); return(Status); } // MRxProxyQueryDir NTSTATUS MRxProxyFlush( IN PRX_CONTEXT RxContext ) /*++ Routine Description: This routine handles flush requests. Arguments: RxContext - the RDBSS context Return Value: RXSTATUS - The return status for the operation --*/ { NTSTATUS Status = STATUS_SUCCESS; RxCaptureFcb; RxCaptureFobx; PAGED_CODE(); RxDbgTrace(+1, Dbg, ("MRxProxyFlush %08lx\n", RxContext )); ASSERT( NodeType(capFobx->pSrvOpen) == RDBSS_NTC_SRVOPEN ); //MRxProxySetLoud("QueryDir ",RxContext,&(capFobx->UnicodeQueryTemplate)); Status = MRxProxyAsyncEngineOuterWrapper( RxContext, MRXPROXY_ASYNCENG_CTX_FROM_FLUSH, MRxProxyQueryDirOrFlushContinuation, "MRxProxyFlush", TRUE, //loudprocessing (BOOLEAN)MRxProxyStopOnLoudCompletion ); RxDbgTrace(-1, Dbg, ("MRxProxyFlush %08lx exit with status=%08lx\n", RxContext, Status )); return(Status); } // MRxProxyFlush NTSTATUS MRxProxyQueryDirOrFlushContinuation( MRXPROXY_ASYNCENGINE_ARGUMENT_SIGNATURE ) /*++ Routine Description: This is the start routine for query directiry. Arguments: Return Value: RXSTATUS - The return status for the operation --*/ { NTSTATUS Status; //this is initialized to proxybufstatus on a reenter PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext; ULONG ContinueEntryCount; RxCaptureFcb; RxCaptureFobx; PMRX_SRV_OPEN SrvOpen = capFobx->pSrvOpen; BOOLEAN SynchronousIo = !BooleanFlagOn(RxContext->Flags,RX_CONTEXT_FLAG_ASYNC_OPERATION); PAGED_CODE(); RxDbgTrace(+1, Dbg, ("MRxProxyQueryDirOrFlushContinuation\n", 0 )); ASSERT_ASYNCENG_CONTEXT(AsyncEngineContext); AsyncEngineContext->ContinueEntryCount++; ContinueEntryCount = AsyncEngineContext->ContinueEntryCount; IF_DEBUG { if (AsyncEngineContext->EntryPoint == MRXPROXY_ASYNCENG_CTX_FROM_QUERYDIR) { if (RxContext->LoudCompletionString) { PMRX_PROXY_SRV_OPEN proxySrvOpen = MRxProxyGetSrvOpenExtension(capFobx->pSrvOpen); ULONG t = InterlockedIncrement(&proxySrvOpen->NumberOfQueryDirectories); ASSERT(t==1); } } } for (;;) { // // Case on the current state // switch (AsyncEngineContext->OpSpecificState) { case MRxProxyAsyncEngOEInnerIoStates_Initial: AsyncEngineContext->OpSpecificState = MRxProxyAsyncEngOEInnerIoStates_ReadyToSend; // // If not a synchronous querydir, then continue here when resumed // //CODE.IMPROVEMENT why don't we just use the flag in the rxcontext?? if (!SynchronousIo) { SetFlag(AsyncEngineContext->Flags,MRXPROXY_ASYNCENG_CTX_FLAG_ASYNC_OPERATION); } ASSERT( AsyncEngineContext->Continuation == MRxProxyQueryDirOrFlushContinuation); //lack of break is intentional case MRxProxyAsyncEngOEInnerIoStates_ReadyToSend: AsyncEngineContext->OpSpecificState = MRxProxyAsyncEngOEInnerIoStates_OperationOutstanding; Status = MRxProxyBuildAsynchronousRequest( RxContext, // IN PVOID Context MRxProxyAsyncEngineCalldownIrpCompletion // IN PIO_COMPLETION_ROUTINE CompletionRoutine OPTIONAL, ); if (Status != STATUS_SUCCESS) { goto FINALLY; } Status = MRxProxySubmitAsyncEngRequest( MRXPROXY_ASYNCENGINE_ARGUMENTS, (AsyncEngineContext->EntryPoint == MRXPROXY_ASYNCENG_CTX_FROM_QUERYDIR) ?MRXPROXY_ASYNCENG_AECTXTYPE_QUERYDIR :MRXPROXY_ASYNCENG_AECTXTYPE_FLUSH ); // // If the status is PENDING, then we're done for now. We must // wait until we're re-entered when the receive happens. // if (Status==(STATUS_PENDING)) { ASSERT(FALSE); //shouldn't be coming thru here now........ ASSERT(!SynchronousIo); goto FINALLY; } if ((Status!=STATUS_SUCCESS) && (RxContext->LoudCompletionString)) { DbgPrint("LoudFailure %08lx on %wZ\n",Status,RxContext->LoudCompletionString); if (MRxProxyStopOnLoudCompletion) { DbgBreakPoint(); } } AsyncEngineContext->Status = Status; //lack of break is intentional case MRxProxyAsyncEngOEInnerIoStates_OperationOutstanding: AsyncEngineContext->OpSpecificState = MRxProxyAsyncEngOEInnerIoStates_ReadyToSend; Status = AsyncEngineContext->Status; //RxContext->InformationToReturn += AsyncEngineContext->Information; if (!NT_ERROR(Status)) { RxContext->Info.LengthRemaining -= AsyncEngineContext->CalldownIrp->IoStatus.Information; } goto FINALLY; break; } } FINALLY: //CODE.IMPROVEMENT QueryDirOrFlush_start and write_start and locks_start should be combined.....we use this //macro until then to keep the async stuff identical if ( Status != (STATUS_PENDING) ) { MRxProxyAsyncEngAsyncCompletionIfNecessary(AsyncEngineContext,RxContext); } RxDbgTrace(-1, Dbg, ("MRxProxyQueryDirOrFlushContinuation exit w %08lx\n", Status )); return Status; }