From: Pierre Schweitzer Date: Sat, 15 Jul 2017 10:05:32 +0000 (+0000) Subject: [RDBSS] X-Git-Tag: ReactOS-0.4.6~80 X-Git-Url: https://git.reactos.org/?p=reactos.git;a=commitdiff_plain;h=8f00170a9325073861e0f2604d44364abce383c3;ds=sidebyside [RDBSS] Implement RxNotifyChangeDirectory(), RxLowIoNotifyChangeDirectoryCompletion(), RxCancelNotifyChangeDirectoryRequestsForVNetRoot() This means the first parts of the directory watch are here. Though, NFS driver doesn't support these, but at least, it reduces the UNIMPLEMENTED spam! CORE-11327 svn path=/trunk/; revision=75353 --- diff --git a/reactos/sdk/include/ddk/mrx.h b/reactos/sdk/include/ddk/mrx.h index 21156463858..fa486f6c86e 100644 --- a/reactos/sdk/include/ddk/mrx.h +++ b/reactos/sdk/include/ddk/mrx.h @@ -1,6 +1,9 @@ #ifndef _RXMINIRDR_ #define _RXMINIRDR_ +#define RxSetIoStatusStatus(R, S) (R)->CurrentIrp->IoStatus.Status = (S) +#define RxSetIoStatusInfo(R, I) (R)->CurrentIrp->IoStatus.Information = (I) + #define RxShouldPostCompletion() ((KeGetCurrentIrql() >= DISPATCH_LEVEL)) #define RX_REGISTERMINI_FLAG_DONT_PROVIDE_UNCS 0x00000001 diff --git a/reactos/sdk/lib/drivers/rdbsslib/rdbss.c b/reactos/sdk/lib/drivers/rdbsslib/rdbss.c index bc810d503a1..722d0a66614 100644 --- a/reactos/sdk/lib/drivers/rdbsslib/rdbss.c +++ b/reactos/sdk/lib/drivers/rdbsslib/rdbss.c @@ -913,13 +913,100 @@ RxCancelNotifyChangeDirectoryRequestsForFobx( UNIMPLEMENTED; } +/* + * @implemented + */ NTSTATUS RxCancelNotifyChangeDirectoryRequestsForVNetRoot( PV_NET_ROOT VNetRoot, BOOLEAN ForceFilesClosed) { - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; + KIRQL OldIrql; + NTSTATUS Status; + PLIST_ENTRY Entry; + PRX_CONTEXT Context; + LIST_ENTRY ContextsToCancel; + + /* Init a list for the contexts to cancel */ + InitializeListHead(&ContextsToCancel); + + /* Lock our list lock */ + KeAcquireSpinLock(&RxStrucSupSpinLock, &OldIrql); + + /* Now, browse all the active contexts, to find the associated ones */ + Entry = RxActiveContexts.Flink; + while (Entry != &RxActiveContexts) + { + Context = CONTAINING_RECORD(Entry, RX_CONTEXT, ContextListEntry); + Entry = Entry->Flink; + + /* Not the IRP we're looking for, ignore */ + if (Context->MajorFunction != IRP_MJ_DIRECTORY_CONTROL || + Context->MinorFunction != IRP_MN_NOTIFY_CHANGE_DIRECTORY) + { + continue; + } + + /* Not the VNetRoot we're looking for, ignore */ + if (Context->pFcb == NULL || + (PV_NET_ROOT)Context->NotifyChangeDirectory.pVNetRoot != VNetRoot) + { + continue; + } + + /* No cancel routine (can't be cancel, then), ignore */ + if (Context->MRxCancelRoutine == NULL) + { + continue; + } + + /* At that point, we found a matching context + * If we're not asked to force close, then fail - it's still open + */ + if (!ForceFilesClosed) + { + Status = STATUS_FILES_OPEN; + break; + } + + /* Mark our context as cancelled */ + SetFlag(Context->Flags, RX_CONTEXT_FLAG_CANCELLED); + + /* Move it to our list */ + RemoveEntryList(&Context->ContextListEntry); + InsertTailList(&ContextsToCancel, &Context->ContextListEntry); + + InterlockedIncrement((volatile long *)&Context->ReferenceCount); + } + + /* Done with the contexts */ + KeReleaseSpinLock(&RxStrucSupSpinLock, OldIrql); + + if (Status != STATUS_SUCCESS) + { + return Status; + } + + /* Now, handle all our "extracted" contexts */ + while (!IsListEmpty(&ContextsToCancel)) + { + Entry = RemoveHeadList(&ContextsToCancel); + Context = CONTAINING_RECORD(Entry, RX_CONTEXT, ContextListEntry); + + /* If they had an associated IRP (should be always true) */ + if (Context->CurrentIrp != NULL) + { + /* Then, call cancel routine */ + ASSERT(Context->MRxCancelRoutine != NULL); + DPRINT1("Canceling %p with %p\n", Context, Context->MRxCancelRoutine); + Context->MRxCancelRoutine(Context); + } + + /* And delete the context */ + RxDereferenceAndDeleteRxContext(Context); + } + + return Status; } VOID @@ -5325,6 +5412,25 @@ RxLowIoLockControlShell( return STATUS_NOT_IMPLEMENTED; } +/* + * @implemented + */ +NTSTATUS +NTAPI +RxLowIoNotifyChangeDirectoryCompletion( + PRX_CONTEXT RxContext) +{ + PAGED_CODE(); + + DPRINT("Completing NCD with: %lx, %lx\n", RxContext->IoStatusBlock.Status, RxContext->IoStatusBlock.Information); + + /* Just copy back the IO_STATUS to the IRP */ + RxSetIoStatusStatus(RxContext, RxContext->IoStatusBlock.Status); + RxSetIoStatusInfo(RxContext, RxContext->IoStatusBlock.Information); + + return RxContext->IoStatusBlock.Status; +} + /* * @implemented */ @@ -5469,12 +5575,63 @@ RxLowIoReadShellCompletion( return Status; } +/* + * @implemented + */ NTSTATUS RxNotifyChangeDirectory( PRX_CONTEXT RxContext) { - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; + PIRP Irp; + NTSTATUS Status; + PIO_STACK_LOCATION Stack; + + PAGED_CODE(); + + /* The IRP can abviously wait */ + SetFlag(RxContext->Flags, RX_CONTEXT_FLAG_WAIT); + + /* Initialize its lowio */ + RxInitializeLowIoContext(&RxContext->LowIoContext, LOWIO_OP_NOTIFY_CHANGE_DIRECTORY); + + _SEH2_TRY + { + /* Lock user buffer */ + Stack = RxContext->CurrentIrpSp; + RxLockUserBuffer(RxContext, IoWriteAccess, Stack->Parameters.NotifyDirectory.Length); + + /* Copy parameters from IO_STACK */ + RxContext->LowIoContext.ParamsFor.NotifyChangeDirectory.WatchTree = BooleanFlagOn(Stack->Flags, SL_WATCH_TREE); + RxContext->LowIoContext.ParamsFor.NotifyChangeDirectory.CompletionFilter = Stack->Parameters.NotifyDirectory.CompletionFilter; + RxContext->LowIoContext.ParamsFor.NotifyChangeDirectory.NotificationBufferLength = Stack->Parameters.NotifyDirectory.Length; + + /* If we have an associated MDL */ + Irp = RxContext->CurrentIrp; + if (Irp->MdlAddress != NULL) + { + /* Then, call mini-rdr */ + RxContext->LowIoContext.ParamsFor.NotifyChangeDirectory.pNotificationBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority); + if (RxContext->LowIoContext.ParamsFor.NotifyChangeDirectory.pNotificationBuffer != NULL) + { + Status = RxLowIoSubmit(RxContext, RxLowIoNotifyChangeDirectoryCompletion); + } + else + { + Status = STATUS_INSUFFICIENT_RESOURCES; + } + } + else + { + Status = STATUS_INVALID_PARAMETER; + } + } + _SEH2_FINALLY + { + /* All correct */ + } + _SEH2_END; + + return Status; } NTSTATUS