ReactOS 0.4.15-dev-7958-gcd0bb1a
rxce.c
Go to the documentation of this file.
1/*
2 * ReactOS kernel
3 * Copyright (C) 2017 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19/*
20 * COPYRIGHT: See COPYING in the top level directory
21 * PROJECT: ReactOS kernel
22 * FILE: sdk/lib/drivers/rxce/rxce.c
23 * PURPOSE: RXCE library
24 * PROGRAMMER: Pierre Schweitzer (pierre@reactos.org)
25 */
26
27/* INCLUDES *****************************************************************/
28
29#include <rx.h>
30#include <pseh/pseh2.h>
31#include <dfs.h>
32
33#define NDEBUG
34#include <debug.h>
35
36VOID
39 PVOID File,
40 ULONG Line,
42
43VOID
47
51
52VOID
56
59 PRDBSS_DEVICE_OBJECT pMRxDeviceObject,
60 WORK_QUEUE_TYPE WorkQueueType,
61 PRX_WORK_QUEUE_ITEM WorkQueueItem);
62
65 PRX_CONTEXT RxContext);
66
67VOID
71
72VOID
74 PSRV_CALL SrvCall,
75 PSRV_OPEN SrvOpen,
76 PLIST_ENTRY DiscardedRequests);
77
78VOID
82
83VOID
86 _In_ struct _KDPC *Dpc,
90
91VOID
95
101 _In_ ULONG Tag);
102
103VOID
104NTAPI
107
108VOID
109NTAPI
112 _In_ ULONG Tag);
113
115
124#if 0
129#else
131#endif
147#if DBG
149#else
151#endif
152
153#if RDBSS_ASSERTS
154#ifdef ASSERT
155#undef ASSERT
156#endif
157
158#define ASSERT(exp) \
159 if (!(exp)) \
160 { \
161 RxAssert(#exp, __FILE__, __LINE__, NULL); \
162 }
163#endif
164
165#if RX_POOL_WRAPPER
166#undef RxAllocatePool
167#undef RxAllocatePoolWithTag
168#undef RxFreePool
169
170#define RxAllocatePool(P, S) _RxAllocatePoolWithTag(P, S, 0)
171#define RxAllocatePoolWithTag _RxAllocatePoolWithTag
172#define RxFreePool _RxFreePool
173#define RxFreePoolWithTag _RxFreePoolWithTag
174#endif
175
176/* FUNCTIONS ****************************************************************/
177
178/*
179 * @implemented
180 */
182NTAPI
185{
187}
188
189/*
190 * @implemented
191 */
193NTAPI
197{
198 PFCB Fcb;
199 BOOLEAN Ret;
200
201 PAGED_CODE();
202
203 Fcb = Context;
204 /* The received context is a FCB */
207 ASSERT(Fcb->Specific.Fcb.LazyWriteThread == NULL);
208
209 /* Acquire the paging resource (shared) */
210 Ret = ExAcquireResourceSharedLite(Fcb->Header.PagingIoResource, Wait);
211 if (Ret)
212 {
213 /* Update tracker information */
214 Fcb->PagingIoResourceFile = __FILE__;
215 Fcb->PagingIoResourceLine = __LINE__;
216 /* Lazy writer thread is the current one */
217 Fcb->Specific.Fcb.LazyWriteThread = PsGetCurrentThread();
218
219 /* There is no top level IRP */
221 /* Now, there will be! */
224 /* In case of failure, release the lock and reset everything */
225 if (!Ret)
226 {
229 ExReleaseResourceLite(Fcb->Header.PagingIoResource);
230 Fcb->Specific.Fcb.LazyWriteThread = NULL;
231 }
232 }
233
234 return Ret;
235}
236
237/*
238 * @implemented
239 */
241NTAPI
245{
246 PFCB Fcb;
247 BOOLEAN Ret;
248
249 PAGED_CODE();
250
251 Fcb = Context;
252 /* The received context is a FCB */
255
256 Ret = ExAcquireResourceSharedLite(Fcb->Header.Resource, Wait);
257 if (Ret)
258 {
259 /* There is no top level IRP */
261 /* Now, there will be! */
264 /* In case of failure, release the lock and reset everything */
265 if (!Ret)
266 {
268 }
269 }
270
271 return Ret;
272}
273
274VOID
275NTAPI
278{
280}
281
283NTAPI
287{
290}
291
292/*
293 * @implemented
294 */
295VOID
297 PNET_ROOT NetRoot,
298 PV_NET_ROOT VNetRoot)
299{
300 PAGED_CODE();
301
302 DPRINT("RxAddVirtualNetRootToNetRoot(%p, %p)\n", NetRoot, VNetRoot);
303
304 /* Insert in the VNetRoot list - make sure lock is held */
305 ASSERT(RxIsPrefixTableLockExclusive(NetRoot->SrvCall->RxDeviceObject->pRxNetNameTable));
306
307 VNetRoot->pNetRoot = (PMRX_NET_ROOT)NetRoot;
308 ++NetRoot->NumberOfVirtualNetRoots;
309 InsertTailList(&NetRoot->VirtualNetRoots, &VNetRoot->NetRootListEntry);
310}
311
312/*
313 * @implemented
314 */
315PVOID
317 PRDBSS_DEVICE_OBJECT RxDeviceObject,
320 ULONG NameSize,
321 PVOID AlreadyAllocatedObject)
322{
323 PFCB Fcb;
324 PFOBX Fobx;
325 PSRV_OPEN SrvOpen;
326 PVOID Buffer, PAPNBuffer;
327 PNON_PAGED_FCB NonPagedFcb;
329 ULONG NonPagedSize, FobxSize, SrvOpenSize, FcbSize;
330
331 PAGED_CODE();
332
333 Dispatch = RxDeviceObject->Dispatch;
334
335 NonPagedSize = 0;
336 FobxSize = 0;
337 SrvOpenSize = 0;
338 FcbSize = 0;
339
340 Fcb = NULL;
341 Fobx = NULL;
342 SrvOpen = NULL;
343 NonPagedFcb = NULL;
344 PAPNBuffer = NULL;
345
346 /* If we ask for FOBX, just allocate FOBX and its extension if asked */
348 {
349 FobxSize = sizeof(FOBX);
351 {
352 FobxSize += QuadAlign(Dispatch->MRxFobxSize);
353 }
354 }
355 /* If we ask for SRV_OPEN, also allocate the "internal" FOBX and the extensions if asked */
357 {
358 SrvOpenSize = sizeof(SRV_OPEN);
360 {
361 SrvOpenSize += QuadAlign(Dispatch->MRxSrvOpenSize);
362 }
363
364 FobxSize = sizeof(FOBX);
366 {
367 FobxSize += QuadAlign(Dispatch->MRxFobxSize);
368 }
369 }
370 /* Otherwise, we're asked to allocate a FCB */
371 else
372 {
373 /* So, allocate the FCB and its extension if asked */
374 FcbSize = sizeof(FCB);
376 {
377 FcbSize += QuadAlign(Dispatch->MRxFcbSize);
378 }
379
380 /* If we're asked to allocate from nonpaged, also allocate the NON_PAGED_FCB
381 * Otherwise, it will be allocated later on, specifically
382 */
383 if (PoolType == NonPagedPool)
384 {
385 NonPagedSize = sizeof(NON_PAGED_FCB);
386 }
387
388 /* And if it's not for a rename operation also allcoate the internal SRV_OPEN and FOBX and their extensions */
390 {
391 SrvOpenSize = sizeof(SRV_OPEN);
393 {
394 SrvOpenSize += QuadAlign(Dispatch->MRxSrvOpenSize);
395 }
396
397 FobxSize = sizeof(FOBX);
399 {
400 FobxSize += QuadAlign(Dispatch->MRxFobxSize);
401 }
402 }
403 }
404
405 /* If we already have a buffer, go ahead */
406 if (AlreadyAllocatedObject != NULL)
407 {
408 Buffer = AlreadyAllocatedObject;
409 }
410 /* Otherwise, allocate it */
411 else
412 {
413 Buffer = RxAllocatePoolWithTag(PoolType, NameSize + FcbSize + SrvOpenSize + FobxSize + NonPagedSize, RX_FCB_POOLTAG);
414 if (Buffer == NULL)
415 {
416 return NULL;
417 }
418 }
419
420 /* Now, get the pointers - FOBX is easy */
422 {
423 Fobx = Buffer;
424 }
425 /* SRV_OPEN first, FOBX next */
426 else if (NodeType == RDBSS_NTC_SRVOPEN)
427 {
428 SrvOpen = Buffer;
429 Fobx = Add2Ptr(Buffer, SrvOpenSize);
430 }
432 {
433 SrvOpen = Buffer;
434 }
435 else
436 {
437 /* FCB first, and if needed, SRV_OPEN next, FOBX last */
438 Fcb = Buffer;
440 {
441 SrvOpen = Add2Ptr(Buffer, FcbSize);
442 Fobx = Add2Ptr(Buffer, FcbSize + SrvOpenSize);
443 }
444
445 /* If we were not allocated from non paged, allocate the NON_PAGED_FCB now */
446 if (PoolType != NonPagedPool)
447 {
449 if (NonPagedFcb == NULL)
450 {
451 RxFreePoolWithTag(Buffer, RX_FCB_POOLTAG);
452 return NULL;
453 }
454
455 PAPNBuffer = Add2Ptr(Buffer, FcbSize + SrvOpenSize + FobxSize);
456 }
457 /* Otherwise, just point at the right place in what has been allocated previously */
458 else
459 {
460 NonPagedFcb = Add2Ptr(Fobx, FobxSize);
461 PAPNBuffer = Add2Ptr(Fobx, FobxSize + NonPagedSize);
462 }
463 }
464
465 /* If we have allocated a SRV_OPEN, initialize it */
466 if (SrvOpen != NULL)
467 {
468 ZeroAndInitializeNodeType(SrvOpen, RDBSS_NTC_SRVOPEN, SrvOpenSize);
469
471 {
472 SrvOpen->InternalFobx = Fobx;
473 }
474 else
475 {
476 SrvOpen->InternalFobx = NULL;
477 SrvOpen->Flags |= SRVOPEN_FLAG_FOBX_USED;
478 }
479
481 {
482 SrvOpen->Context = Add2Ptr(SrvOpen, sizeof(SRV_OPEN));
483 }
484
485 InitializeListHead(&SrvOpen->SrvOpenQLinks);
486 }
487
488 /* If we have allocated a FOBX, initialize it */
489 if (Fobx != NULL)
490 {
492
494 {
495 Fobx->Context = Add2Ptr(Fobx, sizeof(FOBX));
496 }
497 }
498
499 /* If we have allocated a FCB, initialize it */
500 if (Fcb != NULL)
501 {
503
504 Fcb->NonPaged = NonPagedFcb;
506#if DBG
507 Fcb->CopyOfNonPaged = NonPagedFcb;
508 NonPagedFcb->FcbBackPointer = Fcb;
509#endif
510
511 Fcb->InternalSrvOpen = SrvOpen;
512 Fcb->InternalFobx = Fobx;
513
517
519 {
520 Fcb->Context = Add2Ptr(Fcb, sizeof(FCB));
521 }
522
524
526 InterlockedIncrement((volatile long *)&RxDeviceObject->NumberOfActiveFcbs);
527
529 FsRtlSetupAdvancedHeader(Fcb, &NonPagedFcb->AdvancedFcbHeaderMutex);
530 }
531
532 DPRINT("Allocated %p\n", Buffer);
533
534 return Buffer;
535}
536
537/*
538 * @implemented
539 */
540PVOID
543 PMINIRDR_DISPATCH MRxDispatch,
544 ULONG NameLength)
545{
546 ULONG Tag, ObjectSize;
548 PRX_PREFIX_ENTRY PrefixEntry;
549 USHORT StructSize, ExtensionSize;
550
551 PAGED_CODE();
552
553 /* Select the node to allocate and always deal with the fact we may have to manage its extension */
554 ExtensionSize = 0;
555 switch (NodeType)
556 {
559 StructSize = sizeof(SRV_CALL);
560 if (MRxDispatch != NULL && BooleanFlagOn(MRxDispatch->MRxFlags, RDBSS_MANAGE_SRV_CALL_EXTENSION))
561 {
562 ExtensionSize = QuadAlign(MRxDispatch->MRxSrvCallSize);
563 }
564 break;
565
568 StructSize = sizeof(NET_ROOT);
570 {
571 ExtensionSize = QuadAlign(MRxDispatch->MRxNetRootSize);
572 }
573 break;
574
577 StructSize = sizeof(V_NET_ROOT);
579 {
580 ExtensionSize = QuadAlign(MRxDispatch->MRxVNetRootSize);
581 }
582 break;
583
584 default:
585 ASSERT(FALSE);
586 break;
587 }
588
589 /* Now, allocate the object */
590 ObjectSize = ExtensionSize + StructSize + NameLength;
592 if (Object == NULL)
593 {
594 return NULL;
595 }
596 /* Initialize it */
598
599 /* For SRV_CALL and NETROOT, the name points to the prefix table name */
600 switch (NodeType)
601 {
603 PrefixEntry = &((PSRV_CALL)Object)->PrefixEntry;
604 Extension = &((PSRV_CALL)Object)->Context;
605 ((PSRV_CALL)Object)->pSrvCallName = &PrefixEntry->Prefix;
606 break;
607
609 PrefixEntry = &((PNET_ROOT)Object)->PrefixEntry;
610 Extension = &((PNET_ROOT)Object)->Context;
611 ((PNET_ROOT)Object)->pNetRootName = &PrefixEntry->Prefix;
612 break;
613
615 PrefixEntry = &((PV_NET_ROOT)Object)->PrefixEntry;
616 Extension = &((PV_NET_ROOT)Object)->Context;
617 break;
618
619 default:
620 ASSERT(FALSE);
621 break;
622 }
623
624 /* Set the prefix table unicode string */
625 RtlZeroMemory(PrefixEntry, sizeof(RX_PREFIX_ENTRY));
627 PrefixEntry->NodeByteSize = sizeof(RX_PREFIX_ENTRY);
628 PrefixEntry->Prefix.Length = NameLength;
629 PrefixEntry->Prefix.MaximumLength = NameLength;
630 PrefixEntry->Prefix.Buffer = Add2Ptr(Object, ExtensionSize + StructSize);
631
632 /* Return the extension if we are asked to manage it */
633 if (ExtensionSize != 0)
634 {
635 *Extension = Add2Ptr(Object, StructSize);
636 }
637
638 return Object;
639}
640
641/*
642 * @implemented
643 */
644VOID
647 PVOID File,
648 ULONG Line,
650{
651 CHAR Response[2];
653
654 /* If we're not asked to continue, just stop the system */
656 {
657 KeBugCheckEx(RDBSS_FILE_SYSTEM, RDBSS_BUG_CHECK_ASSERT | Line, 0, 0, 0);
658 }
659
660 /* Otherwise, capture context to offer the user to dump it */
662
663 /* Loop until the user hits 'i' */
664 while (TRUE)
665 {
666 /* If no file provided, use empty name */
667 if (File == NULL)
668 {
669 File = "";
670 }
671
672 /* If no message provided, use empty one */
673 if (Message == NULL)
674 {
675 Message = "";
676 }
677
678 /* Display the message */
679 DbgPrint("\n*** Assertion failed: %s%s\n*** Source File: %s, line %ld\n\n", Message, Assert, File, Line);
680 /* And ask the user */
681 DbgPrompt("Break, Ignore (bi)? ", Response, sizeof(Response));
682 /* If he asks for ignore, quit
683 * In case of invalid input, ask again
684 */
685 if (Response[0] != 'B' && Response[0] != 'b')
686 {
687 if (Response[0] == 'I' || Response[0] == 'i')
688 {
689 return;
690 }
691
692 continue;
693 }
694
695 /* Break: offer the user to dump the context and break */
696 DbgPrint("Execute '!cxr %lx' to dump context\n", &Context);
698
699 /* Continue looping, so that after dump, execution can continue (with ignore) */
700 }
701}
702
703/*
704 * @implemented
705 */
706VOID
707NTAPI
710{
711 PRX_WORK_QUEUE RxWorkQueue;
712
713 PAGED_CODE();
714
715 RxWorkQueue = WorkQueue;
716 RxpWorkerThreadDispatcher(RxWorkQueue, NULL);
717}
718
719/*
720 * @implemented
721 */
722VOID
724 IN OUT PRX_CONTEXT RxContext)
725{
726 PFOBX Fobx;
727 BOOLEAN PostRequest;
728
729 PAGED_CODE();
730
731 Fobx = (PFOBX)RxContext->pFobx;
732 PostRequest = FALSE;
733
734 /* Acquire the pipe mutex */
736
737 /* If that's a blocking pipe operation which is not the CCB one, then handle it */
738 if (BooleanFlagOn(RxContext->FlagsForLowIo, RXCONTEXT_FLAG4LOWIO_PIPE_SYNC_OPERATION) &&
739 RxContext->RxContextSerializationQLinks.Flink != NULL &&
740 RxContext != CONTAINING_RECORD(&Fobx->Specific.NamedPipe.ReadSerializationQueue, RX_CONTEXT, RxContextSerializationQLinks) &&
741 RxContext != CONTAINING_RECORD(&Fobx->Specific.NamedPipe.WriteSerializationQueue, RX_CONTEXT, RxContextSerializationQLinks))
742 {
743 /* Clear it! */
744 ClearFlag(RxContext->FlagsForLowIo, RXCONTEXT_FLAG4LOWIO_PIPE_SYNC_OPERATION);
745
746 /* Drop it off the list */
747 RemoveEntryList(&RxContext->RxContextSerializationQLinks);
748 RxContext->RxContextSerializationQLinks.Flink = NULL;
749 RxContext->RxContextSerializationQLinks.Blink = NULL;
750
751 /* Set we've been cancelled */
752 RxContext->IoStatusBlock.Status = STATUS_CANCELLED;
753
754 /*
755 * If it's async, we'll post completion, otherwise, we signal to waiters
756 * it's being cancelled
757 */
758 if (BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_ASYNC_OPERATION))
759 {
760 PostRequest = TRUE;
761 }
762 else
763 {
764 RxSignalSynchronousWaiter(RxContext);
765 }
766 }
767
768 /* Done */
770
771 /* Post if async */
772 if (PostRequest)
773 {
774 RxFsdPostRequest(RxContext);
775 }
776}
777
778/*
779 * @implemented
780 */
782NTAPI
784 PSRV_OPEN SrvOpen,
786 BOOLEAN ComputeNewState)
787{
788 PFCB Fcb;
790 ULONG NewBufferingState, OldBufferingState;
791
792 PAGED_CODE();
793
794 DPRINT("RxChangeBufferingState(%p, %p, %d)\n", SrvOpen, Context, ComputeNewState);
795
796 Fcb = (PFCB)SrvOpen->pFcb;
798 /* First of all, mark that buffering state is changing */
800
801 /* Assume success */
804 {
805 /* If we're asked to compute a new state, ask the mini-rdr for it */
806 if (ComputeNewState)
807 {
808 MINIRDR_CALL_THROUGH(MiniStatus, Fcb->MRxDispatch, MRxComputeNewBufferingState,
809 ((PMRX_SRV_OPEN)SrvOpen, Context, &NewBufferingState));
811 {
812 NewBufferingState = 0;
813 }
814 }
815 else
816 {
817 /* If not, use SRV_OPEN state */
818 NewBufferingState = SrvOpen->BufferingFlags;
819 }
820
821 /* If no shared access, and if we're not asked to compute a new state, use maximum flags set */
822 if ((Fcb->ShareAccess.SharedRead + Fcb->ShareAccess.SharedWrite + Fcb->ShareAccess.SharedDelete) == 0 && !ComputeNewState)
823 {
824 SetFlag(NewBufferingState, FCB_STATE_BUFFERING_STATE_WITH_NO_SHARES);
825 }
826
827 /* If there's a lock operation to complete, clear that flag */
828 if (Fcb->OutstandingLockOperationsCount != 0)
829 {
831 }
832
833 /* Get the old state */
834 OldBufferingState = Fcb->FcbState & FCB_STATE_BUFFERING_STATE_MASK;
835 DPRINT("ChangeBufferingState %x -> %x (%x)\n", OldBufferingState, NewBufferingState, SrvOpen->BufferingFlags);
836
837 /* If we're dropping write cache, then flush the FCB */
838 if (BooleanFlagOn(OldBufferingState, FCB_STATE_WRITECACHING_ENABLED) &&
840 {
841 DPRINT("Flushing\n");
842
844 }
845
846 /* If we're dropping read cache, then purge */
847 if (Fcb->UncleanCount == 0 ||
848 (BooleanFlagOn(OldBufferingState, FCB_STATE_READCACHING_ENABLED) &&
849 !BooleanFlagOn(NewBufferingState, FCB_STATE_READCACHING_ENABLED)) ||
850 BooleanFlagOn(NewBufferingState, FCB_STATE_DELETE_ON_CLOSE))
851 {
852 DPRINT("Purging\n");
853
854 if (!NT_SUCCESS(Status))
855 {
856 DPRINT("Previous flush failed with status: %lx\n", Status);
857 }
858
860 }
861
862 /* If there's already a change pending in SRV_OPEN */
863 if (ComputeNewState && BooleanFlagOn(SrvOpen->Flags, SRVOPEN_FLAG_BUFFERING_STATE_CHANGE_PENDING))
864 {
865 /* If there's a FOBX at least */
866 if (!IsListEmpty(&SrvOpen->FobxList))
867 {
868 PRX_CONTEXT RxContext;
869
870 /* Create a fake context to pass to the mini-rdr */
872 if (RxContext != NULL)
873 {
874 PFOBX Fobx;
875
876 RxContext->pFcb = RX_GET_MRX_FCB(Fcb);
877
878 /* Give the first FOBX */
879 Fobx = CONTAINING_RECORD(SrvOpen->FobxList.Flink, FOBX, FobxQLinks);
880 RxContext->pFobx = (PMRX_FOBX)Fobx;
881 RxContext->pRelevantSrvOpen = Fobx->pSrvOpen;
882
883 /* If there was a delayed close, perform it */
884 if (BooleanFlagOn(SrvOpen->Flags, SRVOPEN_FLAG_CLOSE_DELAYED))
885 {
886 DPRINT("Oplock break close for %p\n", SrvOpen);
887
888 RxCloseAssociatedSrvOpen(Fobx, RxContext);
889 }
890 /* Otherwise, inform the mini-rdr about completion */
891 else
892 {
893 MINIRDR_CALL_THROUGH(MiniStatus, Fcb->MRxDispatch, MRxCompleteBufferingStateChangeRequest,
894 (RxContext, (PMRX_SRV_OPEN)SrvOpen, Context));
896 }
897
899 }
900 }
901 }
902
903 /* Set the new state */
904 Fcb->FcbState ^= (NewBufferingState ^ Fcb->FcbState) & FCB_STATE_BUFFERING_STATE_MASK;
905 }
907 {
908 /* Job done, clear the flag */
910
911 if (!BooleanFlagOn(NewBufferingState, FCB_STATE_FILETIMECACHEING_ENABLED))
912 {
914 }
915 }
916 _SEH2_END;
917
918 return Status;
919}
920
923 PRX_CONTEXT RxContext,
924 PV_NET_ROOT VNetRoot,
926 PUNICODE_STRING UserName,
927 PUNICODE_STRING UserDomain,
929 ULONG Flags)
930{
931 PAGED_CODE();
932
933 /* If that's a UNC name, there's nothing to process */
936 Flags != 0))
937 {
939 }
940
941 /* Compare the logon ID in the VNetRoot with the one provided */
942 if (RtlCompareMemory(&VNetRoot->LogonId, LogonId, sizeof(LUID)) != sizeof(LUID))
943 {
945 }
946
947 /* No credential provided? That's OK */
948 if (UserName == NULL && UserDomain == NULL && Password == NULL)
949 {
950 return STATUS_SUCCESS;
951 }
952
953 /* Left to do! */
956}
957
962{
963 PIRP Irp;
964
965 PAGED_CODE();
966
967 DPRINT("RxCompleteRequest(%p, %lx)\n", Context, Status);
968
969 ASSERT(Context != NULL);
970 ASSERT(Context->CurrentIrp != NULL);
971 Irp = Context->CurrentIrp;
972
973 /* Debug what the caller asks for */
974 if (Context->LoudCompletionString != NULL)
975 {
976 DPRINT("LoudCompletion: %lx/%lx with %wZ\n", Status, Irp->IoStatus.Information, Context->LoudCompletionString);
977 /* Does the user asks to stop on failed completion */
979 {
980 DPRINT1("LoudFailure: %lx/%lx with %wZ\n", Status, Irp->IoStatus.Information, Context->LoudCompletionString);
981 }
982 }
983
984 /* Complete for real */
985 Context->CurrentIrp = NULL;
987
988 DPRINT("Status: %lx\n", Status);
989 return Status;
990}
991
992/*
993 * @implemented
994 */
995VOID
997 IN PRX_CONTEXT RxContext,
998 IN PIRP Irp,
1000{
1001 CCHAR Boost;
1002 KIRQL OldIrql;
1004
1005 DPRINT("RxCompleteRequest_Real(%p, %p, %lx)\n", RxContext, Irp, Status);
1006
1007 /* Nothing to complete, just free context */
1008 if (Irp == NULL)
1009 {
1010 DPRINT("NULL IRP for %p\n", RxContext);
1011 if (RxContext != NULL)
1012 {
1014 }
1015
1016 return;
1017 }
1018
1019 /* Remove cancel routine */
1023
1024 /* Select the boost, given the success/paging operation */
1026 {
1027 Boost = IO_DISK_INCREMENT;
1028 }
1029 else
1030 {
1031 Irp->IoStatus.Information = 0;
1032 Boost = IO_NO_INCREMENT;
1033 }
1034 Irp->IoStatus.Status = Status;
1035
1036 if (RxContext != NULL)
1037 {
1038 ASSERT(RxContext->MajorFunction <= IRP_MJ_MAXIMUM_FUNCTION);
1039 if (RxContext->MajorFunction != IRP_MJ_DEVICE_CONTROL)
1040 {
1041 DPRINT("Completing: MN: %d, Context: %p, IRP: %p, Status: %lx, Info: %lx, #%lx\n",
1042 RxContext->MinorFunction, RxContext, Irp,
1043 Status, Irp->IoStatus.Information, RxContext->SerialNumber);
1044 }
1045 }
1046
1047 /* If that's an opening, there might be a canonical name allocated,
1048 * if completion isn't pending, release it
1049 */
1051 if (Stack->MajorFunction == IRP_MJ_CREATE && Status != STATUS_PENDING &&
1052 RxContext != NULL)
1053 {
1054 if (BooleanFlagOn(RxContext->Create.Flags, 2))
1055 {
1056 Stack->FileObject->FileName.Length += sizeof(WCHAR);
1057 }
1058
1060 ASSERT(RxContext->Create.CanonicalNameBuffer == NULL);
1061 }
1062
1063 /* If it's a write, validate the correct behavior of the operation */
1064 if (Stack->MajorFunction == IRP_MJ_WRITE)
1065 {
1066 if (NT_SUCCESS(Irp->IoStatus.Status))
1067 {
1068 ASSERT(Irp->IoStatus.Information <= Stack->Parameters.Write.Length);
1069 }
1070 }
1071
1072 /* If it's pending, make sure IRP is marked as such */
1073 if (RxContext != NULL)
1074 {
1075 if (RxContext->PendingReturned)
1076 {
1078 }
1079 }
1080
1081 /* Complete now */
1082 DPRINT("Completing IRP with %x/%x\n", Irp->IoStatus.Status, Irp->IoStatus.Information);
1083 IoCompleteRequest(Irp, Boost);
1084
1085 /* If there's a context, dereference it */
1086 if (RxContext != NULL)
1087 {
1089 }
1090}
1091
1092/*
1093 * @implemented
1094 */
1095VOID
1097 IN OUT PSRV_OPEN SrvOpen)
1098{
1099 PSRV_CALL SrvCall;
1100
1101 SrvCall = (PSRV_CALL)((PFCB)SrvOpen->pFcb)->VNetRoot->pNetRoot->pSrvCall;
1102 /* Only handle requests if opening was a success */
1103 if (SrvOpen->Condition == Condition_Good)
1104 {
1105 KIRQL OldIrql;
1106 BOOLEAN ProcessChange;
1107 LIST_ENTRY DiscardedRequests;
1108
1109 /* Initialize our discarded requests list */
1110 InitializeListHead(&DiscardedRequests);
1111
1113
1114 /* Transfer our requests in the SRV_CALL */
1115 RxTransferList(&SrvCall->BufferingManager.SrvOpenLists[0], &SrvOpen->SrvOpenKeyList);
1116
1117 /* Was increased in RxInitiateSrvOpenKeyAssociation(), opening is done */
1119
1120 /* Dispatch requests and get the discarded ones */
1121 RxpDispatchChangeBufferingStateRequests(SrvCall, SrvOpen, &DiscardedRequests);
1122
1124
1125 /* Is there still anything to process? */
1128 {
1129 ProcessChange = FALSE;
1130 }
1131 else
1132 {
1133 ProcessChange = (SrvCall->BufferingManager.HandlerInactive == FALSE);
1134 if (ProcessChange)
1135 {
1137 }
1138 }
1140
1141 /* Yes? Go ahead! */
1142 if (ProcessChange)
1143 {
1144 RxReferenceSrvCall(SrvCall);
1148 }
1149
1150 /* And discard left requests */
1151 RxpDiscardChangeBufferingStateRequests(&DiscardedRequests);
1152 }
1153 else
1154 {
1156 }
1157}
1158
1159/*
1160 * @implemented
1161 */
1164 IN PRX_CONTEXT RxContext,
1165 IN PSRV_CALL SrvCall,
1166 IN PNET_ROOT NetRoot,
1167 IN PV_NET_ROOT VirtualNetRoot,
1168 OUT PLOCK_HOLDING_STATE LockHoldingState)
1169{
1171 PRX_PREFIX_TABLE PrefixTable;
1173 RX_BLOCK_CONDITION RootCondition, VRootCondition;
1174
1175 PAGED_CODE();
1176
1177 DPRINT("RxConstructNetRoot(%p, %p, %p, %p, %p)\n", RxContext, SrvCall, NetRoot,
1178 VirtualNetRoot, LockHoldingState);
1179
1180 /* Validate the lock is exclusively held */
1181 PrefixTable = RxContext->RxDeviceObject->pRxNetNameTable;
1182 ASSERT(*LockHoldingState == LHS_ExclusiveLockHeld);
1183
1184 /* Allocate the context */
1186 if (Context == NULL)
1187 {
1189 }
1190
1191 /* We can release lock now */
1192 RxReleasePrefixTableLock(PrefixTable);
1193 *LockHoldingState = LHS_LockNotHeld;
1194
1195 RootCondition = Condition_Bad;
1196 VRootCondition = Condition_Bad;
1197
1198 /* Initialize the context */
1201 Context->RxContext = RxContext;
1202 Context->pVNetRoot = VirtualNetRoot;
1203 Context->Callback = RxCreateNetRootCallBack;
1204
1205 /* And call the mini-rdr */
1206 MINIRDR_CALL_THROUGH(Status, SrvCall->RxDeviceObject->Dispatch, MRxCreateVNetRoot, (Context));
1207 if (Status == STATUS_PENDING)
1208 {
1209 /* Wait for the mini-rdr to be done */
1211 /* Update the structures condition according to mini-rdr return */
1212 if (NT_SUCCESS(Context->NetRootStatus))
1213 {
1214 if (NT_SUCCESS(Context->VirtualNetRootStatus))
1215 {
1216 RootCondition = Condition_Good;
1217 VRootCondition = Condition_Good;
1219 }
1220 else
1221 {
1222 RootCondition = Condition_Good;
1223 Status = Context->VirtualNetRootStatus;
1224 }
1225 }
1226 else
1227 {
1228 Status = Context->VirtualNetRootStatus;
1229 if (NT_SUCCESS(Status))
1230 {
1231 Status = Context->NetRootStatus;
1232 }
1233 }
1234 }
1235 else
1236 {
1237 /* It has to return STATUS_PENDING! */
1238 ASSERT(FALSE);
1239 }
1240
1241 /* Acquire lock again - for caller lock status will remain unchanged */
1242 ASSERT(*LockHoldingState == LHS_LockNotHeld);
1244 *LockHoldingState = LHS_ExclusiveLockHeld;
1245
1246 /* Do the transition to the condition got from mini-rdr */
1247 RxTransitionNetRoot(NetRoot, RootCondition);
1248 RxTransitionVNetRoot(VirtualNetRoot, VRootCondition);
1249
1250 /* Context is not longer needed */
1251 RxFreePoolWithTag(Context, RX_SRVCALL_POOLTAG);
1252
1253 DPRINT("Status: %x\n", Status);
1254
1255 return Status;
1256}
1257
1258/*
1259 * @implemented
1260 */
1263 IN PRX_CONTEXT RxContext,
1264 IN PSRV_CALL SrvCall,
1265 OUT PLOCK_HOLDING_STATE LockHoldingState)
1266{
1268 PRX_PREFIX_TABLE PrefixTable;
1269 PRDBSS_DEVICE_OBJECT RxDeviceObject;
1272
1273 PAGED_CODE();
1274
1275 DPRINT("RxConstructSrvCall(%p, %p, %p)\n", RxContext, SrvCall, LockHoldingState);
1276
1277 /* Validate the lock is exclusively held */
1278 RxDeviceObject = RxContext->RxDeviceObject;
1279 PrefixTable = RxDeviceObject->pRxNetNameTable;
1280 ASSERT(*LockHoldingState == LHS_ExclusiveLockHeld);
1281
1282 /* Allocate the context for mini-rdr */
1284 if (Calldown == NULL)
1285 {
1286 SrvCall->Context = NULL;
1287 SrvCall->Condition = Condition_Bad;
1288 RxReleasePrefixTableLock(PrefixTable);
1289 *LockHoldingState = LHS_LockNotHeld;
1291 }
1292
1293 /* Initialize it */
1294 RtlZeroMemory(Calldown, sizeof(MRX_SRVCALLDOWN_STRUCTURE));
1295
1296 SrvCall->Context = NULL;
1297 SrvCall->Condition = Condition_InTransition;
1298
1299 RxReleasePrefixTableLock(PrefixTable);
1300 *LockHoldingState = LHS_LockNotHeld;
1301
1302 CallbackContext = &Calldown->CallbackContexts[0];
1303 DPRINT("CalldownContext %p for %wZ\n", CallbackContext, &RxDeviceObject->DeviceName);
1304 DPRINT("With calldown %p and SrvCall %p\n", Calldown, SrvCall);
1305 CallbackContext->SrvCalldownStructure = Calldown;
1306 CallbackContext->CallbackContextOrdinal = 0;
1307 CallbackContext->RxDeviceObject = RxDeviceObject;
1308
1309 RxReferenceSrvCall(SrvCall);
1310
1311 /* If we're async, we'll post, otherwise, we'll have to wait for completion */
1312 if (BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_ASYNC_OPERATION))
1313 {
1314 RxPrePostIrp(RxContext, RxContext->CurrentIrp);
1315 }
1316 else
1317 {
1319 }
1320
1321 Calldown->NumberToWait = 1;
1322 Calldown->NumberRemaining = 1;
1323 Calldown->RxContext = RxContext;
1324 Calldown->SrvCall = (PMRX_SRV_CALL)SrvCall;
1326 Calldown->BestFinisher = NULL;
1329
1330 /* Call the mini-rdr */
1331 ASSERT(RxDeviceObject->Dispatch != NULL);
1333 ASSERT(RxDeviceObject->Dispatch->MRxCreateSrvCall != NULL);
1334 Status = RxDeviceObject->Dispatch->MRxCreateSrvCall((PMRX_SRV_CALL)SrvCall, CallbackContext);
1335 /* It has to return STATUS_PENDING! */
1337
1338 /* No async, start completion */
1339 if (!BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_ASYNC_OPERATION))
1340 {
1342
1343 /* Finish construction - we'll notify mini-rdr it's the winner */
1345 if (!NT_SUCCESS(Status))
1346 {
1347 RxReleasePrefixTableLock(PrefixTable);
1348 *LockHoldingState = LHS_LockNotHeld;
1349 }
1350 else
1351 {
1352 ASSERT(RxIsPrefixTableLockAcquired(PrefixTable));
1353 *LockHoldingState = LHS_ExclusiveLockHeld;
1354 }
1355 }
1356
1357 DPRINT("RxConstructSrvCall() = Status: %x\n", Status);
1358 return Status;
1359}
1360
1361/*
1362 * @implemented
1363 */
1366 IN PRX_CONTEXT RxContext,
1367 IN PUNICODE_STRING CanonicalName,
1368 IN NET_ROOT_TYPE NetRootType,
1369 OUT PV_NET_ROOT *VirtualNetRootPointer,
1370 OUT PLOCK_HOLDING_STATE LockHoldingState,
1371 OUT PRX_CONNECTION_ID RxConnectionId)
1372{
1374 PV_NET_ROOT VNetRoot;
1376 UNICODE_STRING LocalNetRootName, FilePathName;
1377
1378 PAGED_CODE();
1379
1380 ASSERT(*LockHoldingState != LHS_LockNotHeld);
1381
1382 VNetRoot = NULL;
1384 /* Before creating the VNetRoot, try to find the appropriate connection */
1385 Status = RxFindOrCreateConnections(RxContext, CanonicalName, NetRootType,
1386 &LocalNetRootName, &FilePathName,
1387 LockHoldingState, RxConnectionId);
1388 /* Found and active */
1390 {
1391 /* We need a new VNetRoot */
1392 VNetRoot = RxCreateVNetRoot(RxContext, (PNET_ROOT)RxContext->Create.pVNetRoot->pNetRoot,
1393 CanonicalName, &LocalNetRootName, &FilePathName, RxConnectionId);
1394 if (VNetRoot != NULL)
1395 {
1396 RxReferenceVNetRoot(VNetRoot);
1397 }
1398
1399 /* Dereference previous VNetRoot */
1400 RxDereferenceVNetRoot(RxContext->Create.pVNetRoot->pNetRoot, *LockHoldingState);
1401 /* Reset and start construct (new structures will replace old ones) */
1402 RxContext->Create.pSrvCall = NULL;
1403 RxContext->Create.pNetRoot = NULL;
1404 RxContext->Create.pVNetRoot = NULL;
1405
1406 /* Construct new NetRoot */
1407 if (VNetRoot != NULL)
1408 {
1409 Status = RxConstructNetRoot(RxContext, (PSRV_CALL)VNetRoot->pNetRoot->pSrvCall,
1410 (PNET_ROOT)VNetRoot->pNetRoot, VNetRoot, LockHoldingState);
1411 if (NT_SUCCESS(Status))
1412 {
1414 }
1415 }
1416 else
1417 {
1419 }
1420 }
1421 else
1422 {
1423 /* If it failed creating the connection, leave */
1424 if (Status != STATUS_SUCCESS)
1425 {
1426 if (*LockHoldingState != LHS_LockNotHeld)
1427 {
1428 RxReleasePrefixTableLock(RxContext->RxDeviceObject->pRxNetNameTable);
1429 *LockHoldingState = LHS_LockNotHeld;
1430 }
1431
1432 *VirtualNetRootPointer = VNetRoot;
1433 DPRINT("RxConstructVirtualNetRoot() = Status: %x\n", Status);
1434 return Status;
1435 }
1436
1437 *LockHoldingState = LHS_ExclusiveLockHeld;
1438
1439 VNetRoot = (PV_NET_ROOT)RxContext->Create.pVNetRoot;
1441 }
1442
1443 /* We have a non stable VNetRoot - transition it */
1444 if (VNetRoot != NULL && !StableCondition(VNetRoot->Condition))
1445 {
1447 }
1448
1449 /* If recreation failed */
1450 if (Status != STATUS_SUCCESS)
1451 {
1452 /* Dereference potential VNetRoot */
1453 if (VNetRoot != NULL)
1454 {
1455 ASSERT(*LockHoldingState != LHS_LockNotHeld);
1456 RxDereferenceVNetRoot(VNetRoot, *LockHoldingState);
1457 VNetRoot = NULL;
1458 }
1459
1460 /* Release lock */
1461 if (*LockHoldingState != LHS_LockNotHeld)
1462 {
1463 RxReleasePrefixTableLock(RxContext->RxDeviceObject->pRxNetNameTable);
1464 *LockHoldingState = LHS_LockNotHeld;
1465 }
1466
1467 /* Set NULL ptr */
1468 *VirtualNetRootPointer = VNetRoot;
1469 return Status;
1470 }
1471
1472 /* Return the allocated VNetRoot */
1473 *VirtualNetRootPointer = VNetRoot;
1474 return Status;
1475}
1476
1477/*
1478 * @implemented
1479 */
1480PFCB
1482 IN PRX_CONTEXT RxContext,
1483 IN PV_NET_ROOT VNetRoot,
1485{
1486 PFCB Fcb;
1487 BOOLEAN FakeFcb;
1488 PNET_ROOT NetRoot;
1492 PRDBSS_DEVICE_OBJECT RxDeviceObject;
1493
1494 PAGED_CODE();
1495
1496 /* We need a decent VNetRoot */
1497 ASSERT(VNetRoot != NULL && NodeType(VNetRoot) == RDBSS_NTC_V_NETROOT);
1498
1499 NetRoot = (PNET_ROOT)VNetRoot->pNetRoot;
1500 ASSERT(NodeType(NetRoot) == RDBSS_NTC_NETROOT);
1501 ASSERT((PMRX_NET_ROOT)NetRoot == RxContext->Create.pNetRoot);
1502
1503 RxDeviceObject = NetRoot->pSrvCall->RxDeviceObject;
1504 ASSERT(RxDeviceObject == RxContext->RxDeviceObject);
1505
1506 Stack = RxContext->CurrentIrpSp;
1507
1508 /* Do we need to create a fake FCB? Like for renaming */
1509 FakeFcb = BooleanFlagOn(Stack->Flags, SL_OPEN_TARGET_DIRECTORY) &&
1511 ASSERT(FakeFcb || RxIsFcbTableLockExclusive(&NetRoot->FcbTable));
1512
1515
1516 /* Allocate the FCB */
1517 Fcb = RxAllocateFcbObject(RxDeviceObject, NodeType, PoolType,
1518 NetRoot->InnerNamePrefix.Length + Name->Length, NULL);
1519 if (Fcb == NULL)
1520 {
1521 return NULL;
1522 }
1523
1524 /* Initialize the FCB */
1525 Fcb->CachedNetRootType = NetRoot->Type;
1526 Fcb->RxDeviceObject = RxDeviceObject;
1527 Fcb->MRxDispatch = RxDeviceObject->Dispatch;
1528 Fcb->VNetRoot = VNetRoot;
1529 Fcb->pNetRoot = VNetRoot->pNetRoot;
1530
1531 InitializeListHead(&Fcb->SrvOpenList);
1532 Fcb->SrvOpenListVersion = 0;
1533
1534 Fcb->FcbTableEntry.Path.Length = Name->Length;
1536 Fcb->FcbTableEntry.Path.Buffer = Add2Ptr(Fcb->PrivateAlreadyPrefixedName.Buffer, NetRoot->InnerNamePrefix.Length);
1537 RtlMoveMemory(Fcb->PrivateAlreadyPrefixedName.Buffer, NetRoot->InnerNamePrefix.Buffer,
1538 NetRoot->InnerNamePrefix.Length);
1539 RtlMoveMemory(Fcb->FcbTableEntry.Path.Buffer, Name->Buffer, Name->Length);
1540
1541 /* Copy back parameters from RxContext */
1542 if (BooleanFlagOn(RxContext->Create.Flags, RX_CONTEXT_CREATE_FLAG_ADDEDBACKSLASH))
1543 {
1545 }
1546
1548
1550 {
1552 }
1553
1554 if (RxContext->MajorFunction == IRP_MJ_CREATE && BooleanFlagOn(RxContext->Create.Flags, RX_CONTEXT_CREATE_FLAG_SPECIAL_PATH))
1555 {
1557 }
1558
1559 Fcb->Header.Resource = &Fcb->NonPaged->HeaderResource;
1561
1562 Fcb->Header.PagingIoResource = &Fcb->NonPaged->PagingIoResource;
1563 ExInitializeResourceLite(Fcb->Header.PagingIoResource);
1564
1567
1568 /* Fake FCB doesn't go in prefix table */
1569 if (FakeFcb)
1570 {
1573 DPRINT("Fake FCB: %p\n", Fcb);
1574 }
1575 else
1576 {
1577 RxFcbTableInsertFcb(&NetRoot->FcbTable, Fcb);
1578 }
1579
1580 RxReferenceVNetRoot(VNetRoot);
1581 InterlockedIncrement((volatile long *)&Fcb->pNetRoot->NumberOfFcbs);
1582
1584
1585 DPRINT("FCB %p for %wZ\n", Fcb, &Fcb->FcbTableEntry.Path);
1587
1588 return Fcb;
1589}
1590
1591/*
1592 * @implemented
1593 */
1595NTAPI
1597 OUT PRX_CONTEXT RxContext,
1598 IN PMRX_SRV_OPEN MrxSrvOpen)
1599{
1600 PFCB Fcb;
1601 PFOBX Fobx;
1602 ULONG Flags;
1603 PNET_ROOT NetRoot;
1604 PSRV_OPEN SrvOpen;
1606
1607 PAGED_CODE();
1608
1609 SrvOpen = (PSRV_OPEN)MrxSrvOpen;
1610 ASSERT(NodeType(SrvOpen) == RDBSS_NTC_SRVOPEN);
1611 ASSERT(NodeTypeIsFcb(SrvOpen->Fcb));
1613
1614 Fcb = SrvOpen->Fcb;
1616 /* Can we use pre-allocated FOBX? */
1618 {
1619 Fobx = Fcb->InternalFobx;
1620 /* Call allocate to initialize the FOBX */
1622 /* Mark it used now */
1625 }
1626 else if (!BooleanFlagOn(SrvOpen->Flags, SRVOPEN_FLAG_FOBX_USED))
1627 {
1628 Fobx = SrvOpen->InternalFobx;
1629 /* Call allocate to initialize the FOBX */
1631 /* Mark it used now */
1632 SrvOpen->Flags |= SRVOPEN_FLAG_FOBX_USED;
1634 }
1635 else
1636 {
1637 /* Last case, we cannot, allocate a FOBX */
1639 Flags = 0;
1640 }
1641
1642 /* Allocation failed! */
1643 if (Fobx == NULL)
1644 {
1645 return NULL;
1646 }
1647
1648 /* Set flags */
1649 Fobx->Flags = Flags;
1650
1651 /* Initialize throttling */
1652 NetRoot = (PNET_ROOT)RxContext->Create.pNetRoot;
1653 if (NetRoot != NULL)
1654 {
1655 if (NetRoot->DeviceType == FILE_DEVICE_DISK)
1656 {
1657 RxInitializeThrottlingState(&Fobx->Specific.DiskFile.LockThrottlingState,
1658 NetRoot->DiskParameters.LockThrottlingParameters.Increment,
1659 NetRoot->DiskParameters.LockThrottlingParameters.MaximumDelay);
1660 }
1661 else if (NetRoot->DeviceType == FILE_DEVICE_NAMED_PIPE)
1662 {
1663 RxInitializeThrottlingState(&Fobx->Specific.NamedPipe.ThrottlingState,
1664 NetRoot->NamedPipeParameters.PipeReadThrottlingParameters.Increment,
1665 NetRoot->NamedPipeParameters.PipeReadThrottlingParameters.MaximumDelay);
1666 }
1667 }
1668
1669 /* Propagate flags fron RxContext */
1670 if (BooleanFlagOn(RxContext->Create.Flags, RX_CONTEXT_CREATE_FLAG_UNC_NAME))
1671 {
1672 Fobx->Flags |= FOBX_FLAG_UNC_NAME;
1673 }
1674
1675 if (BooleanFlagOn(RxContext->Create.NtCreateParameters.CreateOptions, FILE_OPEN_FOR_BACKUP_INTENT))
1676 {
1677 Fobx->Flags |= FOBX_FLAG_BACKUP_INTENT;
1678 }
1679
1680 /* Continue init */
1681 Fobx->FobxSerialNumber = 0;
1682 Fobx->SrvOpen = (PSRV_OPEN)MrxSrvOpen;
1683 Fobx->NodeReferenceCount = 1;
1685
1686 RxReferenceSrvOpen(SrvOpen);
1687 InterlockedIncrement((volatile long *)&SrvOpen->pVNetRoot->NumberOfFobxs);
1688
1689 InsertTailList(&SrvOpen->FobxList, &Fobx->FobxQLinks);
1692
1693 Fobx->CloseTime.QuadPart = 0;
1695
1696 DPRINT("FOBX %p for SRV_OPEN %p FCB %p\n", Fobx, Fobx->SrvOpen, Fobx->SrvOpen->pFcb);
1697
1698 return (PMRX_FOBX)Fobx;
1699}
1700
1701/*
1702 * @implemented
1703 */
1706 IN PSRV_CALL SrvCall,
1708 IN ULONG NetRootFlags,
1709 IN PRX_CONNECTION_ID OPTIONAL RxConnectionId)
1710{
1711 PNET_ROOT NetRoot;
1712 USHORT CaseInsensitiveLength;
1713 PRX_PREFIX_TABLE PrefixTable;
1714
1715 DPRINT("RxCreateNetRoot(%p, %wZ, %x, %p)\n", SrvCall, Name, NetRootFlags, RxConnectionId);
1716
1717 PAGED_CODE();
1718
1719 /* We need a SRV_CALL */
1720 ASSERT(SrvCall != NULL);
1721
1722 PrefixTable = SrvCall->RxDeviceObject->pRxNetNameTable;
1724
1725 /* Get name length */
1726 CaseInsensitiveLength = SrvCall->PrefixEntry.Prefix.Length + Name->Length;
1727 if (CaseInsensitiveLength > MAXUSHORT)
1728 {
1729 return NULL;
1730 }
1731
1732 /* Allocate the NetRoot */
1733 NetRoot = RxAllocateObject(RDBSS_NTC_NETROOT, SrvCall->RxDeviceObject->Dispatch,
1734 CaseInsensitiveLength);
1735 if (NetRoot == NULL)
1736 {
1737 return NULL;
1738 }
1739
1740 /* Construct name */
1741 RtlMoveMemory(Add2Ptr(NetRoot->PrefixEntry.Prefix.Buffer, SrvCall->PrefixEntry.Prefix.Length),
1742 Name->Buffer, Name->Length);
1743 if (SrvCall->PrefixEntry.Prefix.Length != 0)
1744 {
1745 RtlMoveMemory(NetRoot->PrefixEntry.Prefix.Buffer, SrvCall->PrefixEntry.Prefix.Buffer,
1746 SrvCall->PrefixEntry.Prefix.Length);
1747 }
1748
1750 {
1751 CaseInsensitiveLength = SrvCall->PrefixEntry.CaseInsensitiveLength;
1752 }
1753 /* Inisert in prefix table */
1754 RxPrefixTableInsertName(PrefixTable, &NetRoot->PrefixEntry, NetRoot,
1755 (PULONG)&NetRoot->NodeReferenceCount, CaseInsensitiveLength,
1756 RxConnectionId);
1757
1758 /* Prepare the FCB table */
1760
1764
1766
1767 NetRoot->SerialNumberForEnum = SerialNumber++;
1768 NetRoot->Flags |= NetRootFlags;
1769 NetRoot->DiskParameters.ClusterSize = 1;
1770 NetRoot->DiskParameters.ReadAheadGranularity = ReadAheadGranularity;
1771 NetRoot->SrvCall = SrvCall;
1772
1773 RxReferenceSrvCall(SrvCall);
1774
1775 DPRINT("NetRootName: %wZ (%p)\n", NetRoot->pNetRootName, NetRoot);
1776 return NetRoot;
1777}
1778
1779/*
1780 * @implemented
1781 */
1782VOID
1783NTAPI
1785 IN PMRX_CREATENETROOT_CONTEXT CreateNetRootContext)
1786{
1787 PAGED_CODE();
1788
1789 KeSetEvent(&CreateNetRootContext->FinishEvent, IO_NETWORK_INCREMENT, FALSE);
1790}
1791
1792/*
1793 * @implemented
1794 */
1796NTAPI
1798 IN PIRP Irp,
1799 IN PRDBSS_DEVICE_OBJECT RxDeviceObject,
1800 IN ULONG InitialContextFlags)
1801{
1802 KIRQL OldIrql;
1804
1805 ASSERT(RxDeviceObject != NULL);
1806
1807 DPRINT("RxCreateRxContext(%p, %p, %u)\n", Irp, RxDeviceObject, InitialContextFlags);
1808
1809#if DBG
1811#endif
1812 InterlockedIncrement((volatile LONG *)&RxDeviceObject->NumberOfActiveContexts);
1813
1814 /* Allocate the context from our lookaside list */
1815 Context = ExAllocateFromNPagedLookasideList(&RxContextLookasideList);
1816 if (Context == NULL)
1817 {
1818 return NULL;
1819 }
1820
1821 /* Zero it */
1823
1824 /* It was allocated on NP pool, keep track of it! */
1826 /* And initialize it */
1827 RxInitializeContext(Irp, RxDeviceObject, InitialContextFlags, Context);
1829
1830 /* Add it to our global list */
1832 InsertTailList(&RxActiveContexts, &Context->ContextListEntry);
1834
1835 DPRINT("Context: %p\n", Context);
1836 return Context;
1837}
1838
1839/*
1840 * @implemented
1841 */
1844 IN PRX_CONTEXT RxContext,
1846 IN PUNICODE_STRING InnerNamePrefix OPTIONAL,
1847 IN PRX_CONNECTION_ID RxConnectionId)
1848{
1849 ULONG NameLength;
1850 PSRV_CALL SrvCall;
1851
1852 PAGED_CODE();
1853
1854 DPRINT("RxCreateSrvCall(%p, %wZ, %wZ, %p)\n", RxContext, Name, InnerNamePrefix, RxConnectionId);
1855
1856 ASSERT(RxIsPrefixTableLockExclusive(RxContext->RxDeviceObject->pRxNetNameTable));
1857
1858 /* Get the name length */
1859 NameLength = Name->Length + 2 * sizeof(WCHAR);
1860 if (InnerNamePrefix != NULL)
1861 {
1862 NameLength += InnerNamePrefix->Length;
1863 }
1864
1865 /* Allocate the object */
1866 SrvCall = RxAllocateObject(RDBSS_NTC_SRVCALL, NULL, NameLength);
1867 if (SrvCall == NULL)
1868 {
1869 return NULL;
1870 }
1871
1872 /* Initialize it */
1873 SrvCall->SerialNumberForEnum = SerialNumber++;
1874 SrvCall->RxDeviceObject = RxContext->RxDeviceObject;
1879 RxInitializeSrvCallParameters(RxContext, SrvCall);
1880 RtlMoveMemory(SrvCall->PrefixEntry.Prefix.Buffer, Name->Buffer, Name->Length);
1881 SrvCall->PrefixEntry.Prefix.MaximumLength = Name->Length + 2 * sizeof(WCHAR);
1882 SrvCall->PrefixEntry.Prefix.Length = Name->Length;
1883 RxPrefixTableInsertName(RxContext->RxDeviceObject->pRxNetNameTable, &SrvCall->PrefixEntry,
1884 SrvCall, (PULONG)&SrvCall->NodeReferenceCount, Name->Length, RxConnectionId);
1885
1886 DPRINT("SrvCallName: %wZ (%p)\n", SrvCall->pSrvCallName, SrvCall);
1887 return SrvCall;
1888}
1889
1890/*
1891 * @implemented
1892 */
1893VOID
1894NTAPI
1897{
1898 KIRQL OldIrql;
1899 PSRV_CALL SrvCall;
1900 PRX_CONTEXT RxContext;
1901 ULONG NumberRemaining;
1902 BOOLEAN StartDispatcher;
1904
1905 DPRINT("RxCreateSrvCallCallBack(%p)\n", Context);
1906
1907 /* Get our context structures */
1908 Calldown = Context->SrvCalldownStructure;
1909 SrvCall = (PSRV_CALL)Calldown->SrvCall;
1910
1911 /* If it is a success, that's the winner */
1913 if (Context->Status == STATUS_SUCCESS)
1914 {
1915 Calldown->BestFinisherOrdinal = Context->CallbackContextOrdinal;
1916 Calldown->BestFinisher = Context->RxDeviceObject;
1917 }
1918 NumberRemaining = --Calldown->NumberRemaining;
1919 SrvCall->Status = Context->Status;
1921
1922 /* Still some to ask, keep going */
1923 if (NumberRemaining != 0)
1924 {
1925 return;
1926 }
1927
1928 /* If that's not async, signal we're done */
1929 RxContext = Calldown->RxContext;
1931 {
1933 return;
1934 }
1935 /* If that's a mailslot, finish construction, no more to do */
1937 {
1939 return;
1940 }
1941
1942 /* Queue our finish call for delayed completion */
1943 DPRINT("Queuing RxFinishSrvCallConstruction() call\n");
1946 StartDispatcher = !RxSrvCallConstructionDispatcherActive;
1948
1949 /* If we have to start dispatcher, go ahead */
1950 if (StartDispatcher)
1951 {
1953
1956 if (!NT_SUCCESS(Status))
1957 {
1958 /* It failed - run it manually.... */
1960 }
1961 }
1962}
1963
1964/*
1965 * @implemented
1966 */
1969 IN PV_NET_ROOT VNetRoot,
1970 IN OUT PFCB Fcb)
1971{
1972 ULONG Flags;
1973 PSRV_OPEN SrvOpen;
1975
1976 PAGED_CODE();
1977
1980
1982
1983 _SEH2_TRY
1984 {
1985 SrvOpen = Fcb->InternalSrvOpen;
1986 /* Check whethet we have to allocate a new SRV_OPEN */
1989 !IsListEmpty(&Fcb->InternalSrvOpen->SrvOpenQLinks))
1990 {
1991 /* Proceed */
1992 SrvOpen = RxAllocateFcbObject(Fcb->VNetRoot->NetRoot->pSrvCall->RxDeviceObject,
1994 Flags = 0;
1995 }
1996 else
1997 {
1998 /* Otherwise, just use internal one and initialize it */
1999 RxAllocateFcbObject(Fcb->VNetRoot->NetRoot->pSrvCall->RxDeviceObject,
2004 }
2005
2006 /* If SrvOpen was properly allocated, initialize it */
2007 if (SrvOpen != NULL)
2008 {
2009 SrvOpen->Flags = Flags;
2010 SrvOpen->pFcb = RX_GET_MRX_FCB(Fcb);
2011 SrvOpen->pAlreadyPrefixedName = &Fcb->PrivateAlreadyPrefixedName;
2012 SrvOpen->pVNetRoot = (PMRX_V_NET_ROOT)VNetRoot;
2013 SrvOpen->ulFileSizeVersion = Fcb->ulFileSizeVersion;
2014 SrvOpen->NodeReferenceCount = 1;
2015
2016 RxReferenceVNetRoot(VNetRoot);
2018
2019 InsertTailList(&Fcb->SrvOpenList, &SrvOpen->SrvOpenQLinks);
2020 ++Fcb->SrvOpenListVersion;
2021
2024 InitializeListHead(&SrvOpen->FobxList);
2026 }
2027 }
2029 {
2031 {
2032 if (SrvOpen != NULL)
2033 {
2034 RxFinalizeSrvOpen(SrvOpen, TRUE, TRUE);
2035 SrvOpen = NULL;
2036 }
2037 }
2038 else
2039 {
2040 DPRINT("SrvOpen %p for FCB %p\n", SrvOpen, SrvOpen->pFcb);
2041 }
2042 }
2043 _SEH2_END;
2044
2045 return SrvOpen;
2046}
2047
2048/*
2049 * @implemented
2050 */
2053 IN PRX_CONTEXT RxContext,
2054 IN PNET_ROOT NetRoot,
2055 IN PUNICODE_STRING CanonicalName,
2056 IN PUNICODE_STRING LocalNetRootName,
2058 IN PRX_CONNECTION_ID RxConnectionId)
2059{
2061 PV_NET_ROOT VNetRoot;
2062 USHORT CaseInsensitiveLength;
2063
2064 PAGED_CODE();
2065
2066 DPRINT("RxCreateVNetRoot(%p, %p, %wZ, %wZ, %wZ, %p)\n", RxContext, NetRoot, CanonicalName,
2067 LocalNetRootName, FilePath, RxConnectionId);
2068
2069 /* Lock must be held exclusively */
2070 ASSERT(RxIsPrefixTableLockExclusive(RxContext->RxDeviceObject->pRxNetNameTable));
2071
2072 /* Check for overflow */
2073 if (LocalNetRootName->Length + NetRoot->PrefixEntry.Prefix.Length > MAXUSHORT)
2074 {
2075 return NULL;
2076 }
2077
2078 /* Get name length and allocate VNetRoot */
2079 CaseInsensitiveLength = LocalNetRootName->Length + NetRoot->PrefixEntry.Prefix.Length;
2080 VNetRoot = RxAllocateObject(RDBSS_NTC_V_NETROOT, NetRoot->SrvCall->RxDeviceObject->Dispatch,
2081 CaseInsensitiveLength);
2082 if (VNetRoot == NULL)
2083 {
2084 return NULL;
2085 }
2086
2087 /* Initialize its connection parameters */
2088 Status = RxInitializeVNetRootParameters(RxContext, &VNetRoot->LogonId, &VNetRoot->SessionId,
2089 &VNetRoot->pUserName, &VNetRoot->pUserDomainName,
2090 &VNetRoot->pPassword, &VNetRoot->Flags);
2091 if (!NT_SUCCESS(Status))
2092 {
2093 RxUninitializeVNetRootParameters(VNetRoot->pUserName, VNetRoot->pUserDomainName,
2094 VNetRoot->pPassword, &VNetRoot->Flags);
2095 RxFreeObject(VNetRoot);
2096
2097 return NULL;
2098 }
2099
2100 /* Set name */
2101 RtlMoveMemory(VNetRoot->PrefixEntry.Prefix.Buffer, CanonicalName->Buffer, VNetRoot->PrefixEntry.Prefix.Length);
2102
2103 VNetRoot->PrefixOffsetInBytes = LocalNetRootName->Length + NetRoot->PrefixEntry.Prefix.Length;
2104 VNetRoot->NamePrefix.Buffer = Add2Ptr(VNetRoot->PrefixEntry.Prefix.Buffer, VNetRoot->PrefixOffsetInBytes);
2105 VNetRoot->NamePrefix.Length = VNetRoot->PrefixEntry.Prefix.Length - VNetRoot->PrefixOffsetInBytes;
2106 VNetRoot->NamePrefix.MaximumLength = VNetRoot->PrefixEntry.Prefix.Length - VNetRoot->PrefixOffsetInBytes;
2107
2110
2111 if (!BooleanFlagOn(NetRoot->SrvCall->Flags, SRVCALL_FLAG_CASE_INSENSITIVE_FILENAMES))
2112 {
2113 USHORT i;
2114
2115 if (BooleanFlagOn(NetRoot->SrvCall->Flags, SRVCALL_FLAG_CASE_INSENSITIVE_NETROOTS))
2116 {
2117 CaseInsensitiveLength = NetRoot->PrefixEntry.CaseInsensitiveLength;
2118 }
2119 else
2120 {
2121 CaseInsensitiveLength = NetRoot->SrvCall->PrefixEntry.CaseInsensitiveLength;
2122 }
2123
2124 for (i = 1; i < CanonicalName->Length / sizeof(WCHAR); ++i)
2125 {
2126 if (CanonicalName->Buffer[i] != OBJ_NAME_PATH_SEPARATOR)
2127 {
2128 break;
2129 }
2130 }
2131
2132 CaseInsensitiveLength += (i * sizeof(WCHAR));
2133 }
2134
2135 /* Insert in prefix table */
2136 RxPrefixTableInsertName(RxContext->RxDeviceObject->pRxNetNameTable, &VNetRoot->PrefixEntry,
2137 VNetRoot, (PULONG)&VNetRoot->NodeReferenceCount, CaseInsensitiveLength,
2138 RxConnectionId);
2139
2140 RxReferenceNetRoot(NetRoot);
2141 RxAddVirtualNetRootToNetRoot(NetRoot, VNetRoot);
2142
2143 /* Finish init */
2144 VNetRoot->SerialNumberForEnum = SerialNumber++;
2145 VNetRoot->UpperFinalizationDone = FALSE;
2148
2149 DPRINT("NamePrefix: %wZ\n", &VNetRoot->NamePrefix);
2150 DPRINT("PrefixEntry: %wZ\n", &VNetRoot->PrefixEntry.Prefix);
2151
2152 return VNetRoot;
2153}
2154
2155/*
2156 * @implemented
2157 */
2158VOID
2161 IN LOCK_HOLDING_STATE LockHoldingState)
2162{
2163 LONG RefCount;
2166
2167 PAGED_CODE();
2168
2170
2171 /* Check we have a node we can handle */
2176
2178 RefCount = InterlockedDecrement((volatile long *)&Node->NodeReferenceCount);
2179 ASSERT(RefCount >= 0);
2180
2181 /* Trace refcount */
2182 switch (NodeType)
2183 {
2184 case RDBSS_NTC_SRVCALL:
2185 PRINT_REF_COUNT(SRVCALL, Node->NodeReferenceCount);
2186 break;
2187
2188 case RDBSS_NTC_NETROOT:
2189 PRINT_REF_COUNT(NETROOT, Node->NodeReferenceCount);
2190 break;
2191
2193 PRINT_REF_COUNT(VNETROOT, Node->NodeReferenceCount);
2194 break;
2195
2196 case RDBSS_NTC_SRVOPEN:
2197 PRINT_REF_COUNT(SRVOPEN, Node->NodeReferenceCount);
2198 break;
2199
2200 case RDBSS_NTC_FOBX:
2201 PRINT_REF_COUNT(NETFOBX, Node->NodeReferenceCount);
2202 break;
2203
2204 default:
2205 ASSERT(FALSE);
2206 break;
2207 }
2208
2209 /* No need to free - still in use */
2210 if (RefCount > 1)
2211 {
2213 return;
2214 }
2215
2216 /* We have to be locked exclusively */
2217 if (LockHoldingState != LHS_ExclusiveLockHeld)
2218 {
2219 if ((NodeType == RDBSS_NTC_FOBX && RefCount == 0) ||
2221 {
2223 }
2224
2226 return;
2227 }
2228 else
2229 {
2231 {
2233 }
2234 }
2235
2237
2238 /* Now, deallocate the memory */
2239 switch (NodeType)
2240 {
2241 case RDBSS_NTC_SRVCALL:
2242 {
2243 PSRV_CALL SrvCall;
2244
2245 SrvCall = (PSRV_CALL)Instance;
2246
2247 ASSERT(SrvCall->RxDeviceObject != NULL);
2248 ASSERT(RxIsPrefixTableLockAcquired(SrvCall->RxDeviceObject->pRxNetNameTable));
2249 RxFinalizeSrvCall(SrvCall, TRUE, TRUE);
2250 break;
2251 }
2252
2253 case RDBSS_NTC_NETROOT:
2254 {
2255 PNET_ROOT NetRoot;
2256
2257 NetRoot = (PNET_ROOT)Instance;
2258
2259 ASSERT(NetRoot->pSrvCall->RxDeviceObject != NULL);
2260 ASSERT(RxIsPrefixTableLockAcquired(NetRoot->pSrvCall->RxDeviceObject->pRxNetNameTable));
2261 RxFinalizeNetRoot(NetRoot, TRUE, TRUE);
2262 break;
2263 }
2264
2266 {
2267 PV_NET_ROOT VNetRoot;
2268
2269 VNetRoot = (PV_NET_ROOT)Instance;
2270
2271 ASSERT(VNetRoot->pNetRoot->pSrvCall->RxDeviceObject != NULL);
2272 ASSERT(RxIsPrefixTableLockAcquired(VNetRoot->pNetRoot->pSrvCall->RxDeviceObject->pRxNetNameTable));
2273 RxFinalizeVNetRoot(VNetRoot, TRUE, TRUE);
2274 break;
2275 }
2276
2277 case RDBSS_NTC_SRVOPEN:
2278 {
2279 PSRV_OPEN SrvOpen;
2280
2281 SrvOpen = (PSRV_OPEN)Instance;
2282
2283 ASSERT(RxIsFcbAcquired(SrvOpen->Fcb));
2284 if (SrvOpen->OpenCount == 0)
2285 {
2286 RxFinalizeSrvOpen(SrvOpen, FALSE, FALSE);
2287 }
2288 break;
2289 }
2290
2291 case RDBSS_NTC_FOBX:
2292 {
2293 PFOBX Fobx;
2294
2295 Fobx = (PFOBX)Instance;
2296
2299 break;
2300 }
2301 }
2302}
2303
2304/*
2305 * @implemented
2306 */
2307VOID
2308NTAPI
2310 IN PRX_CONTEXT RxContext)
2311{
2312 KIRQL OldIrql;
2313 ULONG RefCount;
2315 PRX_CONTEXT StopContext = NULL;
2316
2317 /* Make sure we really have a context */
2319 ASSERT(RxContext->NodeTypeCode == RDBSS_NTC_RX_CONTEXT);
2320 RefCount = InterlockedDecrement((volatile LONG *)&RxContext->ReferenceCount);
2321 /* If refcount is 0, start releasing stuff that needs spinlock held */
2322 if (RefCount == 0)
2323 {
2324 PRDBSS_DEVICE_OBJECT RxDeviceObject;
2325
2327
2328 /* If that's stop context from DO, remove it */
2329 RxDeviceObject = RxContext->RxDeviceObject;
2330 if (RxDeviceObject->StartStopContext.pStopContext == RxContext)
2331 {
2332 RxDeviceObject->StartStopContext.pStopContext = NULL;
2333 }
2334 else
2335 {
2336 /* Remove it from the list */
2337 ASSERT((RxContext->ContextListEntry.Flink->Blink == &RxContext->ContextListEntry) &&
2338 (RxContext->ContextListEntry.Blink->Flink == &RxContext->ContextListEntry));
2339 RemoveEntryList(&RxContext->ContextListEntry);
2340
2341 /* If that was the last active context, save the stop context */
2342 if (InterlockedExchangeAdd((volatile LONG *)&RxDeviceObject->NumberOfActiveContexts, -1) == 0)
2343 {
2344 if (RxDeviceObject->StartStopContext.pStopContext != NULL)
2345 {
2346 StopContext = RxDeviceObject->StartStopContext.pStopContext;
2347 }
2348 }
2349 }
2350 }
2352
2353 /* Now, deal with what can be done without spinlock held */
2354 if (RefCount == 0)
2355 {
2356 /* Refcount shouldn't have changed */
2357 ASSERT(RxContext->ReferenceCount == 0);
2358 /* Reset everything that can be */
2359 RxPrepareContextForReuse(RxContext);
2360
2361#ifdef RDBSS_TRACKER
2362 ASSERT(RxContext->AcquireReleaseFcbTrackerX == 0);
2363#endif
2364 /* If that was the last active, set the event */
2365 if (StopContext != NULL)
2366 {
2367 StopContext->Flags &= ~RX_CONTEXT_FLAG_RECURSIVE_CALL;
2368 KeSetEvent(&StopContext->SyncEvent, IO_NO_INCREMENT, FALSE);
2369 }
2370
2371#if DBG
2372 /* Is ShadowCrit still owned? Shouldn't happen! */
2373 if (RxContext->ShadowCritOwner != 0)
2374 {
2375 DPRINT1("ShadowCritOwner not null! %lx\n", RxContext->ShadowCritOwner);
2376 ASSERT(FALSE);
2377 }
2378#endif
2379
2380 /* If it was allocated, free it */
2381 if (Allocated)
2382 {
2383 ExFreeToNPagedLookasideList(&RxContextLookasideList, RxContext);
2384 }
2385 }
2386}
2387
2388VOID
2389NTAPI
2391 PVOID Context)
2392{
2394}
2395
2396/*
2397 * @implemented
2398 */
2400NTAPI
2402 IN PRDBSS_DEVICE_OBJECT pMRxDeviceObject,
2403 IN WORK_QUEUE_TYPE WorkQueueType,
2405 IN PVOID pContext)
2406{
2408 PRX_WORK_DISPATCH_ITEM DispatchItem;
2409
2410 /* Allocate a bit of context */
2412 if (DispatchItem == NULL)
2413 {
2415 }
2416
2417 /* Set all the routines, the one our dispatcher will call, the one ntoskrnl will call */
2418 DispatchItem->DispatchRoutine = Routine;
2419 DispatchItem->DispatchRoutineParameter = pContext;
2420 DispatchItem->WorkQueueItem.WorkerRoutine = RxWorkItemDispatcher;
2421 DispatchItem->WorkQueueItem.Parameter = DispatchItem;
2422
2423 /* Insert item */
2424 Status = RxInsertWorkQueueItem(pMRxDeviceObject, WorkQueueType, &DispatchItem->WorkQueueItem);
2425 if (!NT_SUCCESS(Status))
2426 {
2427 RxFreePoolWithTag(DispatchItem, RX_WORKQ_POOLTAG);
2428 DPRINT1("RxInsertWorkQueueItem failed! Queue: %ld, Routine: %p, Context: %p, Status: %lx\n", WorkQueueType, Routine, pContext, Status);
2429 }
2430
2431 DPRINT("Dispatching: %p, %p\n", Routine, pContext);
2432
2433 return Status;
2434}
2435
2436/*
2437 * @implemented
2438 */
2439VOID
2442{
2443 PAGED_CODE();
2444
2446}
2447
2448/*
2449 * @implemented
2450 */
2451VOID
2453 IN PUNICODE_STRING FilePathName,
2454 OUT PUNICODE_STRING SrvCallName,
2455 OUT PUNICODE_STRING RestOfName)
2456{
2457 USHORT i, Length;
2458
2459 PAGED_CODE();
2460
2461 ASSERT(SrvCallName != NULL);
2462
2463 /* SrvCall name will start from the begin up to the first separator */
2464 SrvCallName->Buffer = FilePathName->Buffer;
2465 for (i = 1; i < FilePathName->Length / sizeof(WCHAR); ++i)
2466 {
2467 if (FilePathName->Buffer[i] == OBJ_NAME_PATH_SEPARATOR)
2468 {
2469 break;
2470 }
2471 }
2472
2473 /* Compute length */
2474 Length = (USHORT)((ULONG_PTR)&FilePathName->Buffer[i] - (ULONG_PTR)FilePathName->Buffer);
2475 SrvCallName->MaximumLength = Length;
2476 SrvCallName->Length = Length;
2477
2478 /* Return the rest if asked */
2479 if (RestOfName != NULL)
2480 {
2481 Length = (USHORT)((ULONG_PTR)&FilePathName->Buffer[FilePathName->Length / sizeof(WCHAR)] - (ULONG_PTR)FilePathName->Buffer[i]);
2482 RestOfName->Buffer = &FilePathName->Buffer[i];
2483 RestOfName->MaximumLength = Length;
2484 RestOfName->Length = Length;
2485 }
2486}
2487
2488/*
2489 * @implemented
2490 */
2493 IN OUT PRX_FCB_TABLE FcbTable,
2494 IN OUT PFCB Fcb)
2495{
2496 PAGED_CODE();
2497
2498 /* We deal with the table, make sure it's locked */
2500
2501 /* Compute the hash */
2503
2505
2506 /* If no length, it will be our null entry */
2507 if (Fcb->FcbTableEntry.Path.Length == 0)
2508 {
2509 FcbTable->TableEntryForNull = &Fcb->FcbTableEntry;
2510 }
2511 /* Otherwise, insert in the appropriate bucket */
2512 else
2513 {
2514 InsertTailList(FCB_HASH_BUCKET(FcbTable, Fcb->FcbTableEntry.HashValue),
2516 }
2517
2518 /* Propagate the change by incrementing the version number */
2519 InterlockedIncrement((volatile long *)&FcbTable->Version);
2520
2521 return STATUS_SUCCESS;
2522}
2523
2524/*
2525 * @implemented
2526 */
2527PFCB
2529 IN PRX_FCB_TABLE FcbTable,
2531{
2532 PFCB Fcb;
2534
2535 PAGED_CODE();
2536
2537 /* No path - easy, that's null entry */
2538 if (Path == NULL)
2539 {
2540 TableEntry = FcbTable->TableEntryForNull;
2541 }
2542 else
2543 {
2544 ULONG Hash;
2545 PLIST_ENTRY HashBucket, ListEntry;
2546
2547 /* Otherwise, compute the hash value and find the associated bucket */
2549 HashBucket = FCB_HASH_BUCKET(FcbTable, Hash);
2550 /* If the bucket is empty, it means there's no entry yet */
2551 if (IsListEmpty(HashBucket))
2552 {
2553 TableEntry = NULL;
2554 }
2555 else
2556 {
2557 /* Otherwise, browse all the entry */
2558 for (ListEntry = HashBucket->Flink;
2559 ListEntry != HashBucket;
2560 ListEntry = ListEntry->Flink)
2561 {
2562 TableEntry = CONTAINING_RECORD(ListEntry, RX_FCB_TABLE_ENTRY, HashLinks);
2563 InterlockedIncrement(&FcbTable->Compares);
2564
2565 /* If entry hash and string are equal, thatt's the one! */
2566 if (TableEntry->HashValue == Hash &&
2567 TableEntry->Path.Length == Path->Length &&
2568 RtlEqualUnicodeString(Path, &TableEntry->Path, FcbTable->CaseInsensitiveMatch))
2569 {
2570 break;
2571 }
2572 }
2573
2574 /* We reached the end? Not found */
2575 if (ListEntry == HashBucket)
2576 {
2577 TableEntry = NULL;
2578 }
2579 }
2580 }
2581
2582 InterlockedIncrement(&FcbTable->Lookups);
2583
2584 /* If table entry isn't null, return the FCB */
2585 if (TableEntry != NULL)
2586 {
2587 Fcb = CONTAINING_RECORD(TableEntry, FCB, FcbTableEntry);
2589 }
2590 else
2591 {
2592 Fcb = NULL;
2593 InterlockedIncrement(&FcbTable->FailedLookups);
2594 }
2595
2596 return Fcb;
2597}
2598
2599/*
2600 * @implemented
2601 */
2604 IN OUT PRX_FCB_TABLE FcbTable,
2605 IN OUT PFCB Fcb)
2606{
2607 PAGED_CODE();
2608
2610
2611 /* If no path, then remove entry for null */
2612 if (Fcb->FcbTableEntry.Path.Length == 0)
2613 {
2614 FcbTable->TableEntryForNull = NULL;
2615 }
2616 /* Otherwise, remove from the bucket */
2617 else
2618 {
2620 }
2621
2622 /* Reset its list entry */
2624
2625 /* Propagate the change by incrementing the version number */
2626 InterlockedIncrement((volatile long *)&FcbTable->Version);
2627
2628 return STATUS_SUCCESS;
2629}
2630
2631/*
2632 * @implemented
2633 */
2635NTAPI
2637 IN OUT PNET_ROOT NetRoot,
2638 IN OUT PV_NET_ROOT VNetRoot OPTIONAL,
2639 IN LOGICAL ForceFilesClosed)
2640{
2642 PRX_PREFIX_TABLE PrefixTable;
2643 ULONG UncleanAny, UncleanDir;
2644 LONG FilesOpen, AdditionalRef;
2645 BOOLEAN PrefixLocked, FcbTableLocked, ForceClose;
2646
2647 PAGED_CODE();
2648
2649 ASSERT(NodeType(NetRoot) == RDBSS_NTC_NETROOT);
2650
2651 /* Get a BOOLEAN out of LOGICAL
2652 * -1 is like FALSE but also drops extra V_NET_ROOT reference in case of failure
2653 */
2654 ForceClose = (ForceFilesClosed == TRUE ? TRUE : FALSE);
2655
2656 /* First, delete any notification change */
2658 /* If it failed, continue if forced */
2659 if (Status != STATUS_SUCCESS && !ForceFilesClosed)
2660 {
2661 return Status;
2662 }
2663 /* Reset status, in case notification deletion failed */
2665
2666 PrefixTable = NetRoot->pSrvCall->RxDeviceObject->pRxNetNameTable;
2667
2668 PrefixLocked = FALSE;
2669 FcbTableLocked = FALSE;
2670 FilesOpen = 0;
2671 AdditionalRef = 0;
2672 UncleanAny = 0;
2673 UncleanDir = 0;
2674 _SEH2_TRY
2675 {
2677 PrefixLocked = TRUE;
2678
2679 RxReferenceNetRoot(NetRoot);
2680
2681 RxAcquireFcbTableLockExclusive(&NetRoot->FcbTable, TRUE);
2682 FcbTableLocked = TRUE;
2683
2684 /* If our V_NET_ROOT wasn't finalized yet, proceed! */
2685 if (!VNetRoot->ConnectionFinalizationDone)
2686 {
2687 USHORT Bucket;
2688 PRX_FCB_TABLE FcbTable;
2689
2690 DPRINT("Finalizing connection %p: %wZ\n", NetRoot, &NetRoot->PrefixEntry.Prefix);
2691
2692 /* We'll browse all its associated FCB to check whether they're open/orphaned */
2693 FcbTable = &NetRoot->FcbTable;
2694 for (Bucket = 0; Bucket < FcbTable->NumberOfBuckets; ++Bucket)
2695 {
2696 PLIST_ENTRY BucketList, Entry;
2697
2698 BucketList = &FcbTable->HashBuckets[Bucket];
2699 Entry = BucketList->Flink;
2700 while (Entry != BucketList)
2701 {
2702 PFCB Fcb;
2703
2704 Fcb = CONTAINING_RECORD(Entry, FCB, FcbTableEntry.HashLinks);
2705 Entry = Entry->Flink;
2706
2707 /* FCB for this connection, go ahead */
2708 if (Fcb->VNetRoot == VNetRoot)
2709 {
2710 /* It's still open, and no force? Fail and keep track */
2711 if (Fcb->UncleanCount > 0 && !ForceClose)
2712 {
2715 {
2716 ++UncleanDir;
2717 }
2718 else
2719 {
2720 ++UncleanAny;
2721 }
2722 }
2723 else
2724 {
2725 /* Else, force purge */
2727
2730
2732
2734 RxPurgeFcb(Fcb);
2735
2736 /* We don't need to release FCB lock, FCB finalize will take care of it */
2737 }
2738 }
2739 }
2740 }
2741
2742 /* No files left, our V_NET_ROOT is finalized */
2743 if (VNetRoot->NumberOfFobxs == 0)
2744 {
2745 VNetRoot->ConnectionFinalizationDone = TRUE;
2746 }
2747 }
2748
2749 /* Keep Number of open files and track of the extra reference */
2750 FilesOpen = VNetRoot->NumberOfFobxs;
2751 AdditionalRef = VNetRoot->AdditionalReferenceForDeleteFsctlTaken;
2752 /* If force close, caller doesn't want to keep connection alive
2753 * and wants it totally close, so drop the V_NET_ROOT too
2754 */
2755 if (ForceClose)
2756 {
2757 RxFinalizeVNetRoot(VNetRoot, FALSE, TRUE);
2758 }
2759 }
2761 {
2762 /* Release what was acquired */
2763 if (FcbTableLocked)
2764 {
2765 RxReleaseFcbTableLock(&NetRoot->FcbTable);
2766 }
2767
2768 /* If close is forced, only fix status if there are open files */
2769 if (ForceClose)
2770 {
2771 if (Status != STATUS_SUCCESS && UncleanAny != 0)
2772 {
2774 }
2775 }
2776 /* Else, fix status and fail closing if there are open files */
2777 else
2778 {
2779 if ((Status != STATUS_SUCCESS && UncleanAny != 0) || FilesOpen > 0)
2780 {
2782 }
2783 }
2784
2785 DPRINT("UncleanAny: %ld, UncleanDir: %ld, FilesOpen: %ld\n", UncleanAny, UncleanDir, FilesOpen);
2786
2787 /* If we're are asked to remove the extra ref, or if closing was a success, do it;
2788 * only if it was still referenced!
2789 */
2790 if ((ForceFilesClosed == 0xFF || Status == STATUS_SUCCESS) && AdditionalRef != 0)
2791 {
2792 VNetRoot->AdditionalReferenceForDeleteFsctlTaken = 0;
2794 }
2795
2796 if (PrefixLocked)
2797 {
2799 RxReleasePrefixTableLock(PrefixTable);
2800 }
2801 }
2802 _SEH2_END;
2803
2804 return Status;
2805}
2806
2807/*
2808 * @implemented
2809 */
2810VOID
2812 IN OUT PRX_FCB_TABLE FcbTable)
2813{
2814 USHORT Bucket;
2815
2816 PAGED_CODE();
2817
2818 /* Just delete the lock */
2819 ExDeleteResourceLite(&FcbTable->TableLock);
2820
2821 /* And make sure (checked) that the table is really empty... */
2822 for (Bucket = 0; Bucket < FcbTable->NumberOfBuckets; ++Bucket)
2823 {
2824 ASSERT(IsListEmpty(&FcbTable->HashBuckets[Bucket]));
2825 }
2826}
2827
2828/*
2829 * @implemented
2830 */
2831BOOLEAN
2833 OUT PFCB ThisFcb,
2834 IN BOOLEAN RecursiveFinalize,
2835 IN BOOLEAN ForceFinalize,
2836 IN LONG ReferenceCount)
2837{
2838 PAGED_CODE();
2839
2840 DPRINT("RxFinalizeNetFcb(%p, %d, %d, %d)\n", ThisFcb, RecursiveFinalize, ForceFinalize, ReferenceCount);
2841 DPRINT("Finalize: %wZ\n", &ThisFcb->FcbTableEntry.Path);
2842
2843 /* Make sure we have an exclusively acquired FCB */
2846
2847 /* We shouldn't force finalization... */
2848 ASSERT(!ForceFinalize);
2849
2850 /* If recurisve, finalize all the associated SRV_OPEN */
2851 if (RecursiveFinalize)
2852 {
2853 PLIST_ENTRY ListEntry;
2854
2855 for (ListEntry = ThisFcb->SrvOpenList.Flink;
2856 ListEntry != &ThisFcb->SrvOpenList;
2857 ListEntry = ListEntry->Flink)
2858 {
2859 PSRV_OPEN SrvOpen;
2860
2861 SrvOpen = CONTAINING_RECORD(ListEntry, SRV_OPEN, SrvOpenQLinks);
2862 RxFinalizeSrvOpen(SrvOpen, TRUE, ForceFinalize);
2863 }
2864 }
2865 /* If FCB is still in use, that's over */
2866 else
2867 {
2868 if (ThisFcb->OpenCount != 0 || ThisFcb->UncleanCount != 0)
2869 {
2870 ASSERT(ReferenceCount > 0);
2871
2872 return FALSE;
2873 }
2874 }
2875
2876 ASSERT(ReferenceCount >= 1);
2877
2878 /* If FCB is still referenced, that's over - unless you force it and want to BSOD somewhere */
2879 if (ReferenceCount != 1 && !ForceFinalize)
2880 {
2881 return FALSE;
2882 }
2883
2884 ASSERT(ForceFinalize || ((ThisFcb->OpenCount == 0) && (ThisFcb->UncleanCount == 0)));
2885
2886 DPRINT("Finalizing FCB open: %d (%d)\n", ThisFcb->OpenCount, ForceFinalize);
2887
2888 /* If finalization was not already initiated, go ahead */
2889 if (!ThisFcb->UpperFinalizationDone)
2890 {
2891 /* Free any FCB_LOCK */
2892 if (NodeType(ThisFcb) == RDBSS_NTC_STORAGE_TYPE_FILE)
2893 {
2894 FsRtlUninitializeFileLock(&ThisFcb->Specific.Fcb.FileLock);
2895
2896 while (ThisFcb->BufferedLocks.List != NULL)
2897 {
2899
2900 Entry = ThisFcb->BufferedLocks.List;
2901 ThisFcb->BufferedLocks.List = Entry->Next;
2902
2904 }
2905 }
2906
2907 /* If not orphaned, it still has a NET_ROOT and potentially is still in a table */
2908 if (!BooleanFlagOn(ThisFcb->FcbState, FCB_STATE_ORPHANED))
2909 {
2910 PNET_ROOT NetRoot;
2911
2912 NetRoot = (PNET_ROOT)ThisFcb->pNetRoot;
2913
2915 /* So, remove it */
2916 if (!BooleanFlagOn(ThisFcb->FcbState, FCB_STATE_NAME_ALREADY_REMOVED))
2917 {
2918 RxFcbTableRemoveFcb(&NetRoot->FcbTable, ThisFcb);
2919 }
2920 }
2921
2922 ThisFcb->UpperFinalizationDone = TRUE;
2923 }
2924
2925 ASSERT(ReferenceCount >= 1);
2926
2927 /* Even if forced, don't allow broken free */
2928 if (ReferenceCount != 1)
2929 {
2930 return FALSE;
2931 }
2932
2933 /* Now, release everything */
2934 if (ThisFcb->pBufferingStateChangeCompletedEvent != NULL)
2935 {
2936 RxFreePool(ThisFcb->pBufferingStateChangeCompletedEvent);
2937 }
2938
2939 if (ThisFcb->MRxDispatch != NULL)
2940 {
2941 ThisFcb->MRxDispatch->MRxDeallocateForFcb(RX_GET_MRX_FCB(ThisFcb));
2942 }
2943
2944 ExDeleteResourceLite(ThisFcb->BufferedLocks.Resource);
2945 ExDeleteResourceLite(ThisFcb->Header.Resource);
2946 ExDeleteResourceLite(ThisFcb->Header.PagingIoResource);
2947
2948 InterlockedDecrement((volatile long *)&ThisFcb->pNetRoot->NumberOfFcbs);
2949 RxDereferenceVNetRoot(ThisFcb->VNetRoot, LHS_LockNotHeld);
2950
2951 ASSERT(IsListEmpty(&ThisFcb->FcbTableEntry.HashLinks));
2952 ASSERT(!ThisFcb->fMiniInited);
2953
2954 /* And free the object */
2955 RxFreeFcbObject(ThisFcb);
2956
2957 return TRUE;
2958}
2959
2960/*
2961 * @implemented
2962 */
2963BOOLEAN
2965 _Out_ PFOBX ThisFobx,
2966 _In_ BOOLEAN RecursiveFinalize,
2967 _In_ BOOLEAN ForceFinalize)
2968{
2969 PFCB Fcb;
2970 PSRV_OPEN SrvOpen;
2971
2972 PAGED_CODE();
2973
2974 ASSERT(NodeType(ThisFobx) == RDBSS_NTC_FOBX);
2975
2976 /* Only finalize if forced or if there's no ref left */
2977 if (ThisFobx->NodeReferenceCount != 0 &&
2978 !ForceFinalize)
2979 {
2980 return FALSE;
2981 }
2982
2983 DPRINT("Finalize Fobx: %p (with %d ref), forced: %d\n", ThisFobx, ThisFobx->NodeReferenceCount, ForceFinalize);
2984
2985 SrvOpen = ThisFobx->SrvOpen;
2986 Fcb = SrvOpen->Fcb;
2987 /* If it wasn't finalized yet, do it */
2988 if (!ThisFobx->UpperFinalizationDone)
2989 {
2992
2993 /* Remove it from the SRV_OPEN */
2994 RemoveEntryList(&ThisFobx->FobxQLinks);
2995
2996 /* If we were used to browse a directory, free the query buffer */
2997 if (BooleanFlagOn(ThisFobx->Flags, FOBX_FLAG_FREE_UNICODE))
2998 {
2999 RxFreePoolWithTag(ThisFobx->UnicodeQueryTemplate.Buffer, RX_DIRCTL_POOLTAG);
3000 }
3001
3002 /* Notify the mini-rdr */
3004 {
3006 }
3007
3008 /* If the SRV_OPEN wasn't closed yet, do it */
3009 if (!BooleanFlagOn(ThisFobx->Flags, FOBX_FLAG_SRVOPEN_CLOSED))
3010 {
3012
3014 DPRINT("Closing SRV_OPEN %p for %p: %x\n", SrvOpen, ThisFobx, Status);
3015 }
3016
3017 /* Finalization done */
3018 ThisFobx->UpperFinalizationDone = TRUE;
3019 }
3020
3021 /* If we're still referenced, don't go any further! */
3022 if (ThisFobx->NodeReferenceCount != 0)
3023 {
3024 return FALSE;
3025 }
3026
3027 /* At that point, everything should be closed */
3028 ASSERT(IsListEmpty(&ThisFobx->ClosePendingList));
3029
3030 /* Was the FOBX allocated with another object?
3031 * If so, mark the buffer free in said object
3032 */
3033 if (ThisFobx == Fcb->InternalFobx)
3034 {
3036 }
3037 else if (ThisFobx == SrvOpen->InternalFobx)
3038 {
3039 ClearFlag(SrvOpen->Flags, SRVOPEN_FLAG_FOBX_USED);
3040 }
3041
3042 ThisFobx->pSrvOpen = NULL;
3043
3044 /* A FOBX less */
3045 InterlockedDecrement((volatile long *)&SrvOpen->pVNetRoot->NumberOfFobxs);
3046
3048
3049 /* If it wasn't allocated with another object, free the FOBX */
3050 if (!BooleanFlagOn(ThisFobx->Flags, FOBX_FLAG_ENCLOSED_ALLOCATED))
3051 {
3052 RxFreeFcbObject(ThisFobx);
3053 }
3054
3055 return TRUE;
3056}
3057
3058/*
3059 * @implemented
3060 */
3061BOOLEAN
3063 OUT PNET_ROOT ThisNetRoot,
3064 IN BOOLEAN RecursiveFinalize,
3065 IN BOOLEAN ForceFinalize)
3066{
3067 PSRV_CALL SrvCall;
3068 PRX_FCB_TABLE FcbTable;
3069 PRX_PREFIX_TABLE PrefixTable;
3070
3071 PAGED_CODE();
3072
3073 ASSERT(NodeType(ThisNetRoot) == RDBSS_NTC_NETROOT);
3074
3075 PrefixTable = ThisNetRoot->pSrvCall->RxDeviceObject->pRxNetNameTable;
3076 ASSERT(RxIsPrefixTableLockAcquired(PrefixTable));
3077
3078 /* If sme finalization is already ongoing, leave */
3080 {
3081 return FALSE;
3082 }
3083
3084 /* Mark we're finalizing */
3086
3087 FcbTable = &ThisNetRoot->FcbTable;
3088 /* Did caller asked us to finalize any associated FCB? */
3089 if (RecursiveFinalize)
3090 {
3091 USHORT Bucket;
3092
3093 /* Browse all the FCBs in our FCB table */
3095 for (Bucket = 0; Bucket < FcbTable->NumberOfBuckets; ++Bucket)
3096 {
3097 PLIST_ENTRY HashBucket, ListEntry;
3098
3099 HashBucket = &FcbTable->HashBuckets[Bucket];
3100 ListEntry = HashBucket->Flink;
3101 while (ListEntry != HashBucket)
3102 {
3103 PFCB Fcb;
3104
3105 Fcb = CONTAINING_RECORD(ListEntry, FCB, FcbTableEntry.HashLinks);
3107
3108 ListEntry = ListEntry->Flink;
3109
3110 /* If the FCB isn't orphaned, then, it's time to purge it */
3112 {
3114
3117 RxPurgeFcb(Fcb);
3118 }
3119 }
3120 }
3121 RxReleaseFcbTableLock(FcbTable);
3122 }
3123
3124 /* Only finalize if forced or if there's a single ref left */
3125 if (ThisNetRoot->NodeReferenceCount != 1 && !ForceFinalize)
3126 {
3127 return FALSE;
3128 }
3129
3130 DPRINT("Finalizing NetRoot %p for %wZ\n", ThisNetRoot, &ThisNetRoot->PrefixEntry.Prefix);
3131
3132 /* If we're still referenced, don't go any further! */
3133 if (ThisNetRoot->NodeReferenceCount != 1)
3134 {
3135 return FALSE;
3136 }
3137
3138 /* Finalize the FCB table (and make sure it's empty!) */
3139 RxFinalizeFcbTable(FcbTable);
3140
3141 /* If name wasn't remove already, do it now */
3142 if (!BooleanFlagOn(ThisNetRoot->Flags, NETROOT_FLAG_NAME_ALREADY_REMOVED))
3143 {
3144 RxRemovePrefixTableEntry(PrefixTable, &ThisNetRoot->PrefixEntry);
3145 }
3146
3147 /* Delete the object */
3148 SrvCall = (PSRV_CALL)ThisNetRoot->pSrvCall;
3149 RxFreeObject(ThisNetRoot);
3150
3151 /* And dereference the associated SRV_CALL */
3152 if (SrvCall != NULL)
3153 {
3155 }
3156
3157 return TRUE;
3158}
3159
3160/*
3161 * @implemented
3162 */
3163BOOLEAN
3165 OUT PSRV_CALL ThisSrvCall,
3166 IN BOOLEAN RecursiveFinalize,
3167 IN BOOLEAN ForceFinalize)
3168{
3169 PRX_PREFIX_TABLE PrefixTable;
3170
3171 PAGED_CODE();
3172
3173 ASSERT(NodeType(ThisSrvCall) == RDBSS_NTC_SRVCALL);
3174
3175 PrefixTable = ThisSrvCall->RxDeviceObject->pRxNetNameTable;
3176 ASSERT(RxIsPrefixTableLockAcquired(PrefixTable));
3177
3178 /* Only finalize if forced or if there's a single ref left */
3179 if (ThisSrvCall->NodeReferenceCount != 1 &&
3180 !ForceFinalize)
3181 {
3182 return FALSE;
3183 }
3184
3185 DPRINT("Finalizing SrvCall %p for %wZ\n", ThisSrvCall, &ThisSrvCall->PrefixEntry.Prefix);
3186
3187 /* If it wasn't finalized yet, do it */
3188 if (!ThisSrvCall->UpperFinalizationDone)
3189 {
3190 BOOLEAN WillFree;
3191
3192 /* Remove ourselves from prefix table */
3193 RxRemovePrefixTableEntry(PrefixTable, &ThisSrvCall->PrefixEntry);
3194
3195 /* Remember our third arg, in case we get queued for later execution */
3196 if (ForceFinalize)
3197 {
3198 SetFlag(ThisSrvCall->Flags, SRVCALL_FLAG_FORCE_FINALIZED);
3199 }
3200
3201 /* And done */
3202 ThisSrvCall->UpperFinalizationDone = TRUE;
3203
3204 /* Would defered execution free the object? */
3205 WillFree = (ThisSrvCall->NodeReferenceCount == 1);
3206
3207 /* If we have a device object */
3208 if (ThisSrvCall->RxDeviceObject != NULL)
3209 {
3211
3212 /* If we're not executing in the RDBSS thread, queue for execution within the thread */
3214 {
3215 /* Extra ref, as usual */
3216 InterlockedIncrement((volatile long *)&ThisSrvCall->NodeReferenceCount);
3217 /* And dispatch */
3218 RxDispatchToWorkerThread(ThisSrvCall->RxDeviceObject, DelayedWorkQueue, RxpDestroySrvCall, ThisSrvCall);
3219
3220 /* Return to the caller, in advance, whether we're freeing the object or not */
3221 return WillFree;
3222 }
3223
3224 /* If in the right thread already, call the mini-rdr */
3225 MINIRDR_CALL_THROUGH(Status, ThisSrvCall->RxDeviceObject->Dispatch,
3226 MRxFinalizeSrvCall, ((PMRX_SRV_CALL)ThisSrvCall, ForceFinalize));
3227 (void)Status;
3228 }
3229 }
3230
3231 /* If we're still referenced, don't go any further! */
3232 if (ThisSrvCall->NodeReferenceCount != 1)
3233 {
3234 return FALSE;
3235 }
3236
3237 /* Don't leak */
3238 if (ThisSrvCall->pDomainName != NULL)
3239 {
3240 RxFreePool(ThisSrvCall->pDomainName);
3241 }
3242
3243 /* And free! */
3244 RxTearDownBufferingManager(ThisSrvCall);
3245 RxFreeObject(ThisSrvCall);
3246
3247 return TRUE;
3248}
3249
3250/*
3251 * @implemented
3252 */
3253BOOLEAN
3255 OUT PSRV_OPEN ThisSrvOpen,
3256 IN BOOLEAN RecursiveFinalize,
3257 IN BOOLEAN ForceFinalize)
3258{
3259 PFCB Fcb;
3260
3261 PAGED_CODE();
3262
3263 /* We have to have a SRV_OPEN */
3264 ASSERT(NodeType(ThisSrvOpen) == RDBSS_NTC_SRVOPEN);
3265
3266 /* If that's a recursive finalization, finalize any related FOBX */
3267 if (RecursiveFinalize)
3268 {
3269 PLIST_ENTRY ListEntry;
3270
3271 ListEntry = ThisSrvOpen->FobxList.Flink;
3272 while (ListEntry != &ThisSrvOpen->FobxList)
3273 {
3274 PFOBX Fobx;
3275
3276 Fobx = CONTAINING_RECORD(ListEntry, FOBX, FobxQLinks);
3277 ListEntry = ListEntry->Flink;
3278 RxFinalizeNetFobx(Fobx, TRUE, ForceFinalize);
3279 }
3280 }
3281
3282 /* If we have still references, don't finalize unless forced */
3283 if (ThisSrvOpen->NodeReferenceCount != 0 &&
3284 !ForceFinalize)
3285 {
3286 return FALSE;
3287 }
3288
3289 DPRINT("Finalize SRV_OPEN: %p (with %d ref), forced: %d\n", ThisSrvOpen, ThisSrvOpen->NodeReferenceCount, ForceFinalize);
3290
3291 /* Only finalize if closed, or if it wasn't already done and SRV_OPEN is in a bad shape */
3292 Fcb = (PFCB)ThisSrvOpen->pFcb;
3293 if ((!ThisSrvOpen->UpperFinalizationDone && ThisSrvOpen->Condition != Condition_Good) ||
3294 BooleanFlagOn(ThisSrvOpen->Flags, SRVOPEN_FLAG_CLOSED))
3295 {
3296 PV_NET_ROOT VNetRoot;
3297
3298 /* Associated FCB can't be fake one */
3301
3302 /* Purge any pending operation */
3304
3305 /* If the FCB wasn't orphaned, inform the mini-rdr about close */
3307 {
3309
3310 MINIRDR_CALL_THROUGH(Status, Fcb->MRxDispatch, MRxForceClosed, ((PMRX_SRV_OPEN)ThisSrvOpen));
3311 (void)Status;
3312 }
3313
3314 /* Remove ourselves from the FCB */
3315 RemoveEntryList(&ThisSrvOpen->SrvOpenQLinks);
3316 InitializeListHead(&ThisSrvOpen->SrvOpenQLinks);
3317 ++Fcb->SrvOpenListVersion;
3318
3319 /* If we have a V_NET_ROOT, dereference it */
3320 VNetRoot = (PV_NET_ROOT)ThisSrvOpen->pVNetRoot;
3321 if (VNetRoot != NULL)
3322 {
3323 InterlockedDecrement((volatile long *)&VNetRoot->pNetRoot->NumberOfSrvOpens);
3325 ThisSrvOpen->pVNetRoot = NULL;
3326 }
3327
3328 /* Finalization done */
3329 ThisSrvOpen->UpperFinalizationDone = TRUE;
3330 }
3331
3332 /* Don't free memory if still referenced */
3333 if (ThisSrvOpen->NodeReferenceCount != 0)
3334 {
3335 return FALSE;
3336 }
3337
3338 /* No key association left */
3339 ASSERT(IsListEmpty(&ThisSrvOpen->SrvOpenKeyList));
3340
3341 /* If we're still in some FCB, remove us */
3342 if (!IsListEmpty(&ThisSrvOpen->SrvOpenQLinks))
3343 {
3344 RemoveEntryList(&ThisSrvOpen->SrvOpenQLinks);
3345 }
3346
3347 /* If enclosed allocation, mark the memory zone free */
3348 if (BooleanFlagOn(ThisSrvOpen->Flags, SRVOPEN_FLAG_ENCLOSED_ALLOCATED))
3349 {
3351 }
3352 /* Otherwise, free the memory */
3353 else
3354 {
3355 RxFreeFcbObject(ThisSrvOpen);
3356 }
3357
3359
3360 return TRUE;
3361}
3362
3363/*
3364 * @implemented
3365 */
3366BOOLEAN
3368 OUT PV_NET_ROOT ThisVNetRoot,
3369 IN BOOLEAN RecursiveFinalize,
3370 IN BOOLEAN ForceFinalize)
3371{
3372 PNET_ROOT NetRoot;
3373 PRX_PREFIX_TABLE PrefixTable;
3374
3375 PAGED_CODE();
3376
3377 ASSERT(NodeType(ThisVNetRoot) == RDBSS_NTC_V_NETROOT);
3378
3379 PrefixTable = ThisVNetRoot->pNetRoot->pSrvCall->RxDeviceObject->pRxNetNameTable;
3380 ASSERT(RxIsPrefixTableLockAcquired(PrefixTable));
3381
3382 /* Only finalize if forced or if there's a single ref left */
3383 if (ThisVNetRoot->NodeReferenceCount != 1 &&
3384 !ForceFinalize)
3385 {
3386 return FALSE;
3387 }
3388
3389 DPRINT("Finalizing VNetRoot %p for %wZ\n", ThisVNetRoot, &ThisVNetRoot->PrefixEntry.Prefix);
3390
3391 NetRoot = (PNET_ROOT)ThisVNetRoot->pNetRoot;
3392 /* If it wasn't finalized yet, do it */
3393 if (!ThisVNetRoot->UpperFinalizationDone)
3394 {
3395 ASSERT(NodeType(NetRoot) == RDBSS_NTC_NETROOT);
3396
3397 /* Reference the NetRoot so that it doesn't disappear */
3398 RxReferenceNetRoot(NetRoot);
3399 RxOrphanSrvOpens(ThisVNetRoot);
3400 /* Remove us from the available VNetRoot for NetRoot */
3401 RxRemoveVirtualNetRootFromNetRoot(NetRoot, ThisVNetRoot);
3402 /* Remove extra ref */
3404
3405 /* Remove ourselves from prefix table */
3406 RxRemovePrefixTableEntry(PrefixTable, &ThisVNetRoot->PrefixEntry);
3407
3408 /* Finalization done */
3409 ThisVNetRoot->UpperFinalizationDone = TRUE;
3410 }
3411
3412 /* If we're still referenced, don't go any further! */
3413 if (ThisVNetRoot->NodeReferenceCount != 1)
3414 {
3415 return FALSE;
3416 }
3417
3418 /* If there's an associated device, notify mini-rdr */
3419 if (NetRoot->pSrvCall->RxDeviceObject != NULL)
3420 {
3422
3423 MINIRDR_CALL_THROUGH(Status, NetRoot->pSrvCall->RxDeviceObject->Dispatch,
3424 MRxFinalizeVNetRoot, ((PMRX_V_NET_ROOT)ThisVNetRoot, FALSE));
3425 (void)Status;
3426 }
3427
3428 /* Free parameters */
3429 RxUninitializeVNetRootParameters(ThisVNetRoot->pUserName, ThisVNetRoot->pUserDomainName,
3430 ThisVNetRoot->pPassword, &ThisVNetRoot->Flags);
3431 /* Dereference our NetRoot, we won't reference it anymore */
3433
3434 /* And free the object! */
3435 RxFreePoolWithTag(ThisVNetRoot, RX_V_NETROOT_POOLTAG);
3436
3437 return TRUE;
3438}
3439
3442 IN PRX_CONTEXT RxContext,
3443 IN PUNICODE_STRING CanonicalName,
3444 IN NET_ROOT_TYPE NetRootType,
3446{
3447 ULONG Flags;
3449 PVOID Container;
3450 BOOLEAN Construct;
3451 PV_NET_ROOT VNetRoot;
3452 RX_CONNECTION_ID ConnectionID;
3453 PRDBSS_DEVICE_OBJECT RxDeviceObject;
3454 LOCK_HOLDING_STATE LockHoldingState;
3455
3456 PAGED_CODE();
3457
3458 RxDeviceObject = RxContext->RxDeviceObject;
3459 ASSERT(RxDeviceObject->Dispatch != NULL);
3461
3462 /* Ask the mini-rdr for connection ID */
3463 ConnectionID.SessionID = 0;
3464 if (RxDeviceObject->Dispatch->MRxGetConnectionId != NULL)
3465 {
3466 Status = RxDeviceObject->Dispatch->MRxGetConnectionId(RxContext, &ConnectionID);
3468 {
3469 /* mini-rdr is expected not to fail - unless it's not implemented */
3470 DPRINT1("Failed to initialize connection ID\n");
3471 ASSERT(FALSE);
3472 }
3473 }
3474
3475 RxContext->Create.NetNamePrefixEntry = NULL;
3476
3479 LockHoldingState = LHS_SharedLockHeld;
3480 Construct = TRUE;
3481 Flags = 0;
3482
3483 /* We will try twice to find a matching VNetRoot: shared locked and then exlusively locked */
3484 while (TRUE)
3485 {
3486 PNET_ROOT NetRoot;
3487 PV_NET_ROOT SavedVNetRoot;
3488
3489 /* Look in prefix table */
3490 Container = RxPrefixTableLookupName(RxDeviceObject->pRxNetNameTable, CanonicalName, RemainingName, &ConnectionID);
3491 if (Container != NULL)
3492 {
3493 /* If that's not a VNetRoot, that's a SrvCall, not interesting, loop again */
3494 if (NodeType(Container) != RDBSS_NTC_V_NETROOT)
3495 {
3496 ASSERT(NodeType(Container) == RDBSS_NTC_SRVCALL);
3497 RxDereferenceSrvCall(Container, LockHoldingState);
3498 }
3499 else
3500 {
3501 VNetRoot = Container;
3502 NetRoot = VNetRoot->NetRoot;
3503
3504 /* If the matching VNetRoot isn't in a good shape, there's something wrong - fail */
3505 if ((NetRoot->Condition != Condition_InTransition && NetRoot->Condition != Condition_Good) ||
3506 NetRoot->SrvCall->RxDeviceObject != RxContext->RxDeviceObject)
3507 {
3509 SavedVNetRoot = NULL;
3510 }
3511 else
3512 {
3513 LUID LogonId;
3515 PUNICODE_STRING UserName, UserDomain, Password;
3516
3517 /* We can reuse if we use same credentials */
3519 &SessionId, &UserName,
3520 &UserDomain, &Password,
3521 &Flags);
3522 if (NT_SUCCESS(Status))
3523 {
3524 SavedVNetRoot = VNetRoot;
3525 Status = RxCheckVNetRootCredentials(RxContext, VNetRoot,
3526 &LogonId, UserName,
3527 UserDomain, Password,
3528 Flags);
3530 {
3531 PLIST_ENTRY ListEntry;
3532
3533 for (ListEntry = NetRoot->VirtualNetRoots.Flink;
3534 ListEntry != &NetRoot->VirtualNetRoots;
3535 ListEntry = ListEntry->Flink)
3536 {
3537 SavedVNetRoot = CONTAINING_RECORD(ListEntry, V_NET_ROOT, NetRootListEntry);
3538 Status = RxCheckVNetRootCredentials(RxContext, SavedVNetRoot,
3539 &LogonId, UserName,
3540 UserDomain, Password,
3541 Flags);
3543 {
3544 break;
3545 }
3546 }
3547
3548 if (ListEntry == &NetRoot->VirtualNetRoots)
3549 {
3550 SavedVNetRoot = NULL;
3551 }
3552 }
3553
3554 if (!NT_SUCCESS(Status))
3555 {
3556 SavedVNetRoot = NULL;
3557 }
3558
3559 RxUninitializeVNetRootParameters(UserName, UserDomain, Password, &Flags);
3560 }
3561 }
3562
3563 /* We'll fail, if we had referenced a VNetRoot, dereference it */
3565 {
3566 if (SavedVNetRoot == NULL)
3567 {
3568 RxDereferenceVNetRoot(VNetRoot, LockHoldingState);
3569 }
3570 }
3571 /* Reference VNetRoot we'll keep, and dereference current */
3572 else if (SavedVNetRoot != VNetRoot)
3573 {
3574 RxDereferenceVNetRoot(VNetRoot, LockHoldingState);
3575 if (SavedVNetRoot != NULL)
3576 {
3577 RxReferenceVNetRoot(SavedVNetRoot);
3578 }
3579 }
3580 }
3581
3582 /* We may have found something, or we fail hard, so don't attempt to create a VNetRoot */
3584 {
3585 Construct = FALSE;
3586 break;
3587 }
3588 }
3589
3590 /* If we're locked exclusive, we won't loop again, it was the second pass */
3591 if (LockHoldingState != LHS_SharedLockHeld)
3592 {
3593 break;
3594 }
3595
3596 /* Otherwise, prepare for second pass, exclusive, making sure we can acquire without delay */
3598 {
3600 LockHoldingState = LHS_ExclusiveLockHeld;
3601 break;
3602 }
3603
3606 LockHoldingState = LHS_ExclusiveLockHeld;
3607 }
3608
3609 /* We didn't fail, and didn't find any VNetRoot, construct one */
3610 if (Construct)
3611 {
3612 ASSERT(LockHoldingState == LHS_ExclusiveLockHeld);
3613
3614 Status = RxConstructVirtualNetRoot(RxContext, CanonicalName, NetRootType, &VNetRoot, &LockHoldingState, &ConnectionID);
3615 ASSERT(Status != STATUS_SUCCESS || LockHoldingState != LHS_LockNotHeld);
3616
3617 if (Status == STATUS_SUCCESS)
3618 {
3619 DPRINT("CanonicalName: %wZ (%d)\n", CanonicalName, CanonicalName->Length);
3620 DPRINT("VNetRoot: %wZ (%d)\n", &VNetRoot->PrefixEntry.Prefix, VNetRoot->PrefixEntry.Prefix.Length);
3621 ASSERT(CanonicalName->Length >= VNetRoot->PrefixEntry.Prefix.Length);
3622
3623 RemainingName->Buffer = Add2Ptr(CanonicalName->Buffer, VNetRoot->PrefixEntry.Prefix.Length);
3624 RemainingName->Length = CanonicalName->Length - VNetRoot->PrefixEntry.Prefix.Length;
3625 RemainingName->MaximumLength = RemainingName->Length;
3626
3628 {
3629 DPRINT("CSC instance, VNetRoot: %p\n", VNetRoot);
3630 }
3631 VNetRoot->Flags |= Flags;
3632 }
3633 }
3634
3635 /* Release the prefix table - caller expects it to be released */
3636 if (LockHoldingState != LHS_LockNotHeld)
3637 {
3639 }
3640
3641 /* If we failed creating, quit */
3642 if (Status != STATUS_SUCCESS)
3643 {
3644 DPRINT1("RxFindOrConstructVirtualNetRoot() = Status: %x\n", Status);
3645 return Status;
3646 }
3647
3648 /* Otherwise, wait until the VNetRoot is stable */
3649 DPRINT("Waiting for stable condition for: %p\n", VNetRoot);
3650 RxWaitForStableVNetRoot(VNetRoot, RxContext);
3651 /* It's all good, update the RX_CONTEXT with all our structs */
3652 if (VNetRoot->Condition == Condition_Good)
3653 {
3654 PNET_ROOT NetRoot;
3655
3656 NetRoot = VNetRoot->NetRoot;
3657 RxContext->Create.pVNetRoot = (PMRX_V_NET_ROOT)VNetRoot;
3658 RxContext->Create.pNetRoot = (PMRX_NET_ROOT)NetRoot;
3659 RxContext->Create.pSrvCall = (PMRX_SRV_CALL)NetRoot->SrvCall;
3660 }
3661 else
3662 {
3664 RxContext->Create.pVNetRoot = NULL;
3666 }
3667
3668 return Status;
3669}
3670
3671/*
3672 * @implemented
3673 */
3676 _In_ PRX_CONTEXT RxContext,
3677 _In_ PUNICODE_STRING CanonicalName,
3678 _In_ NET_ROOT_TYPE NetRootType,
3679 _Out_ PUNICODE_STRING LocalNetRootName,
3680 _Out_ PUNICODE_STRING FilePathName,
3682 _In_ PRX_CONNECTION_ID RxConnectionId)
3683{
3684 PVOID Container;
3685 PSRV_CALL SrvCall;
3686 PNET_ROOT NetRoot;
3687 PV_NET_ROOT VNetRoot;
3689 PRX_PREFIX_TABLE PrefixTable;
3690 UNICODE_STRING RemainingName, NetRootName;
3691
3692 PAGED_CODE();
3693
3694 DPRINT("RxFindOrCreateConnections(%p, %wZ, %x, %p, %p, %p, %p)\n",
3695 RxContext, CanonicalName, NetRootType, LocalNetRootName,
3696 FilePathName, LockState, RxConnectionId);
3697
3698 *FilePathName = *CanonicalName;
3699 LocalNetRootName->Length = 0;
3700 LocalNetRootName->MaximumLength = 0;
3701 LocalNetRootName->Buffer = CanonicalName->Buffer;
3702
3703 /* UNC path, split it */
3704 if (FilePathName->Buffer[1] == ';')
3705 {
3706 BOOLEAN Slash;
3707 USHORT i, Length;
3708
3709 Slash = FALSE;
3710 for (i = 2; i < FilePathName->Length / sizeof(WCHAR); ++i)
3711 {
3712 if (FilePathName->Buffer[i] == OBJ_NAME_PATH_SEPARATOR)
3713 {
3714 Slash = TRUE;
3715 break;
3716 }
3717 }
3718
3719 if (!Slash)
3720 {
3722 }
3723
3724 FilePathName->Buffer = &FilePathName->Buffer[i];
3725 Length = (USHORT)((ULONG_PTR)FilePathName->Buffer - (ULONG_PTR)LocalNetRootName->Buffer);
3726 LocalNetRootName->Length = Length;
3727 LocalNetRootName->MaximumLength = Length;
3728 FilePathName->Length -= Length;
3729
3730 DPRINT("CanonicalName: %wZ\n", CanonicalName);
3731 DPRINT(" -> FilePathName: %wZ\n", FilePathName);
3732 DPRINT(" -> LocalNetRootName: %wZ\n", LocalNetRootName);
3733 }
3734
3735 Container = NULL;
3736 PrefixTable = RxContext->RxDeviceObject->pRxNetNameTable;
3737
3738 _SEH2_TRY
3739 {
3740RetryLookup:
3742
3743 /* If previous lookup left something, dereference it */
3744 if (Container != NULL)
3745 {
3746 switch (NodeType(Container))
3747 {
3748 case RDBSS_NTC_SRVCALL:
3749 RxDereferenceSrvCall(Container, *LockState);
3750 break;
3751
3752 case RDBSS_NTC_NETROOT:
3753 RxDereferenceNetRoot(Container, *LockState);
3754 break;
3755
3757 RxDereferenceVNetRoot(Container, *LockState);
3758 break;
3759
3760 default:
3761 /* Should never happen */
3762 ASSERT(FALSE);
3763 break;
3764 }
3765 }
3766
3767 /* Look for our NetRoot in prefix table */
3768 Container = RxPrefixTableLookupName(PrefixTable, FilePathName, &RemainingName, RxConnectionId);
3769 DPRINT("Container %p for path %wZ\n", Container, FilePathName);
3770
3771 while (TRUE)
3772 {
3773 UNICODE_STRING SrvCallName;
3774
3775 SrvCall = NULL;
3776 NetRoot = NULL;
3777 VNetRoot = NULL;
3778
3779 /* Assume we didn't succeed */
3780 RxContext->Create.pVNetRoot = NULL;
3781 RxContext->Create.pNetRoot = NULL;
3782 RxContext->Create.pSrvCall = NULL;
3783 RxContext->Create.Type = NetRootType;
3784
3785 /* If we found something */
3786 if (Container != NULL)
3787 {
3788 /* A VNetRoot */
3789 if (NodeType(Container) == RDBSS_NTC_V_NETROOT)
3790 {
3791 VNetRoot = Container;
3792 /* Use its NetRoot */
3793 NetRoot = VNetRoot->NetRoot;
3794
3795 /* If it's not stable, wait for it to be stable */
3796 if (NetRoot->Condition == Condition_InTransition)
3797 {
3798 RxReleasePrefixTableLock(PrefixTable);
3799 DPRINT("Waiting for stable condition for: %p\n", NetRoot);
3800 RxWaitForStableNetRoot(NetRoot, RxContext);
3803
3804 /* Now that's it's ok, retry lookup to find what we want */
3805 if (NetRoot->Condition == Condition_Good)
3806 {
3807 goto RetryLookup;
3808 }
3809 }
3810
3811 /* Is the associated netroot good? */
3812 if (NetRoot->Condition == Condition_Good)
3813 {
3814 SrvCall = (PSRV_CALL)NetRoot->pSrvCall;
3815
3816 /* If it is, and SrvCall as well, then, we have our active connection */
3817 if (SrvCall->Condition == Condition_Good &&
3818 SrvCall->RxDeviceObject == RxContext->RxDeviceObject)
3819 {
3820 RxContext->Create.pVNetRoot = (PMRX_V_NET_ROOT)VNetRoot;
3821 RxContext->Create.pNetRoot = (PMRX_NET_ROOT)NetRoot;
3822 RxContext->Create.pSrvCall = (PMRX_SRV_CALL)SrvCall;
3823
3826 }
3827 }
3828
3829 /* If VNetRoot was well constructed, it means the connection is active */
3830 if (VNetRoot->ConstructionStatus == STATUS_SUCCESS)
3831 {
3833 }
3834 else
3835 {
3836 Status = VNetRoot->ConstructionStatus;
3837 }
3838
3839 RxDereferenceVNetRoot(VNetRoot, *LockState);
3841 }
3842 /* Can only be a SrvCall */
3843 else
3844 {
3845 ASSERT(NodeType(Container) == RDBSS_NTC_SRVCALL);
3846 SrvCall = Container;
3847
3848 /* Wait for the SRV_CALL to be stable */
3849 if (SrvCall->Condition == Condition_InTransition)
3850 {
3851 RxReleasePrefixTableLock(PrefixTable);
3852 DPRINT("Waiting for stable condition for: %p\n", SrvCall);
3853 RxWaitForStableSrvCall(SrvCall, RxContext);
3856
3857 /* It went good, loop again to find what we look for */
3858 if (SrvCall->Condition == Condition_Good)
3859 {
3860 goto RetryLookup;
3861 }
3862 }
3863
3864 /* If it's not good... */
3865 if (SrvCall->Condition != Condition_Good)
3866 {
3867 /* But SRV_CALL was well constructed, assume a connection was active */
3868 if (SrvCall->Status == STATUS_SUCCESS)
3869 {
3871 }
3872 else
3873 {
3874 Status = SrvCall->Status;
3875 }
3876
3879 }
3880 }
3881 }
3882
3883 /* If we found a SRV_CALL not matching our DO, quit */
3884 if (SrvCall != NULL && SrvCall->Condition == Condition_Good &&
3885 SrvCall->RxDeviceObject != RxContext->RxDeviceObject)
3886 {
3890 }
3891
3892 /* Now, we want exclusive lock */
3894 {
3895 if (!RxAcquirePrefixTableLockExclusive(PrefixTable, FALSE))
3896 {
3897 RxReleasePrefixTableLock(PrefixTable);
3900 goto RetryLookup;
3901 }
3902
3903 RxReleasePrefixTableLock(PrefixTable);
3905 }
3906
3908
3909 /* If we reach that point, we found something, no need to create something */
3910 if (Container != NULL)
3911 {
3912 break;
3913 }
3914
3915 /* Get the name for the SRV_CALL */
3916 RxExtractServerName(FilePathName, &SrvCallName, NULL);
3917 DPRINT(" -> SrvCallName: %wZ\n", &SrvCallName);
3918 /* And create the SRV_CALL */
3919 SrvCall = RxCreateSrvCall(RxContext, &SrvCallName, NULL, RxConnectionId);
3920 if (SrvCall == NULL)
3921 {
3924 }
3925
3926 /* Reset RX_CONTEXT, so far, connection creation isn't a success */
3927 RxReferenceSrvCall(SrvCall);
3928 RxContext->Create.pVNetRoot = NULL;
3929 RxContext->Create.pNetRoot = NULL;
3930 RxContext->Create.pSrvCall = NULL;
3931 RxContext->Create.Type = NetRootType;
3932 Container = SrvCall;
3933
3934 /* Construct SRV_CALL, ie, use mini-rdr */
3935 Status = RxConstructSrvCall(RxContext, SrvCall, LockState);
3937 if (Status != STATUS_SUCCESS)
3938 {
3939 DPRINT1("RxConstructSrvCall() = Status: %x\n", Status);
3942 RxReleasePrefixTableLock(PrefixTable);
3944 }
3945
3946 /* Loop again to make use of SRV_CALL stable condition wait */
3947 }
3948
3949 /* At that point, we have a stable SRV_CALL (either found or constructed) */
3950 ASSERT((NodeType(SrvCall) == RDBSS_NTC_SRVCALL) && (SrvCall->Condition == Condition_Good));
3951 ASSERT(NetRoot == NULL && VNetRoot == NULL);
3952 ASSERT(SrvCall->RxDeviceObject == RxContext->RxDeviceObject);
3953
3954 /* Call mini-rdr to get NetRoot name */
3955 SrvCall->RxDeviceObject->Dispatch->MRxExtractNetRootName(FilePathName, (PMRX_SRV_CALL)SrvCall, &NetRootName, NULL);
3956 /* And create the NetRoot with that name */
3957 NetRoot = RxCreateNetRoot(SrvCall, &NetRootName, 0, RxConnectionId);
3958 if (NetRoot == NULL)
3959 {
3962 }
3963 NetRoot->Type = NetRootType;
3964
3966
3967 /* Finally, create the associated VNetRoot */
3968 VNetRoot = RxCreateVNetRoot(RxContext, NetRoot, CanonicalName, LocalNetRootName, FilePathName, RxConnectionId);
3969 if (VNetRoot == NULL)
3970 {
3971 RxFinalizeNetRoot(NetRoot, TRUE, TRUE);
3974 }
3975 RxReferenceVNetRoot(VNetRoot);
3976
3977 /* We're get closer! */
3979 RxContext->Create.pSrvCall = (PMRX_SRV_CALL)SrvCall;
3980 RxContext->Create.pNetRoot = (PMRX_NET_ROOT)NetRoot;
3981 RxContext->Create.pVNetRoot = (PMRX_V_NET_ROOT)VNetRoot;
3982
3983 /* Construct the NetRoot, involving the mini-rdr now that we have our three control structs */
3984 Status = RxConstructNetRoot(RxContext, SrvCall, NetRoot, VNetRoot, LockState);
3985 if (!NT_SUCCESS(Status))
3986 {
3988 DPRINT1("RxConstructNetRoot failed Ctxt: %p, VNet: %p, Status: %lx, Condition: %d\n", RxContext, VNetRoot, Status, VNetRoot->Condition);
3989 RxDereferenceVNetRoot(VNetRoot, *LockState);
3990
3991 RxContext->Create.pNetRoot = NULL;
3992 RxContext->Create.pVNetRoot = NULL;
3993 }
3994 else
3995 {
3997
3999
4000 Stack = RxContext->CurrentIrpSp;
4001 if (BooleanFlagOn(Stack->Parameters.Create.Options, FILE_CREATE_TREE_CONNECTION))
4002 {
4005 }
4006 }
4007 }
4009 {
4011 {
4012 if (*LockState != LHS_LockNotHeld)
4013 {
4014 RxReleasePrefixTableLock(PrefixTable);
4016 }
4017 }
4018 }
4019 _SEH2_END;
4020
4021 DPRINT("RxFindOrCreateConnections() = Status: %x\n", Status);
4022 return Status;
4023}
4024
4025/*
4026 * @implemented
4027 */
4028VOID
4029NTAPI
4033 IN PFCB_INIT_PACKET InitPacket OPTIONAL)
4034{
4035 RX_FILE_TYPE OldType;
4036
4037 PAGED_CODE();
4038
4039 DPRINT("RxFinishFcbInitialization(%p, %x, %p)\n", Fcb, FileType, InitPacket);
4040
4041 OldType = NodeType(Fcb);
4043 /* If mini-rdr already did the job for mailslot attributes, 0 the rest */
4045 {
4046 FILL_IN_FCB((PFCB)Fcb, 0, 0, 0, 0, 0, 0, 0, 0, 0);
4047 }
4048 /* Otherwise, if mini-rdr provided us with an init packet, copy its data */
4049 else if (InitPacket != NULL)
4050 {
4051 FILL_IN_FCB((PFCB)Fcb, *InitPacket->pAttributes, *InitPacket->pNumLinks,
4052 InitPacket->pCreationTime->QuadPart, InitPacket->pLastAccessTime->QuadPart,
4053 InitPacket->pLastWriteTime->QuadPart, InitPacket->pLastChangeTime->QuadPart,
4054 InitPacket->pAllocationSize->QuadPart, InitPacket->pFileSize->QuadPart,
4055 InitPacket->pValidDataLength->QuadPart);
4056 }
4057
4060 {
4061 /* If our FCB newly points to a file, initiliaze everything related */
4063
4064 {
4065 if (OldType != RDBSS_NTC_STORAGE_TYPE_FILE)
4066 {
4067 RxInitializeLowIoPerFcbInfo(&((PFCB)Fcb)->Specific.Fcb.LowIoPerFcbInfo);
4068 FsRtlInitializeFileLock(&((PFCB)Fcb)->Specific.Fcb.FileLock, RxLockOperationCompletion,
4070
4071 ((PFCB)Fcb)->BufferedLocks.List = NULL;
4072 ((PFCB)Fcb)->BufferedLocks.PendingLockOps = 0;
4073
4074 Fcb->Header.IsFastIoPossible = FastIoIsQuestionable;
4075 }
4076 }
4077 /* If not a file, validate type */
4078 else
4079 {
4081 }
4082 }
4083}
4084
4085/*
4086 * @implemented
4087 */
4091{
4093 PSRV_CALL SrvCall;
4096 PRX_PREFIX_TABLE PrefixTable;
4097
4098 DPRINT("RxFinishSrvCallConstruction(%p)\n", Calldown);
4099
4100 SrvCall = (PSRV_CALL)Calldown->SrvCall;
4101 Context = Calldown->RxContext;
4102 PrefixTable = Context->RxDeviceObject->pRxNetNameTable;
4103
4104 /* We have a winner, notify him */
4105 if (Calldown->BestFinisher != NULL)
4106 {
4107 DPRINT("Notify the winner: %p (%wZ)\n", Calldown->BestFinisher, &Calldown->BestFinisher->DeviceName);
4108
4109 ASSERT(SrvCall->RxDeviceObject == Calldown->BestFinisher);
4110
4112 MRxSrvCallWinnerNotify,
4113 ((PMRX_SRV_CALL)SrvCall, TRUE,
4115 if (Status != STATUS_SUCCESS)
4116 {
4118 }
4119 else
4120 {
4122 }
4123 }
4124 /* Otherwise, just fail our SRV_CALL */
4125 else
4126 {
4127 Status = Calldown->CallbackContexts[0].Status;
4129 }
4130
4133 RxFreePoolWithTag(Calldown, RX_SRVCALL_POOLTAG);
4134
4135 /* If async, finish it here, otherwise, caller has already finished the stuff */
4137 {
4138 DPRINT("Finishing async call\n");
4139
4140 RxReleasePrefixTableLock(PrefixTable);
4141
4142 /* Make sure we weren't cancelled in-between */
4144 {
4146 }
4147
4148 /* In case that was a create, context can be reused */
4149 if (Context->MajorFunction == IRP_MJ_CREATE)
4150 {
4152 }
4153
4154 /* If that's a failure, reset everything and return failure */
4155 if (Status != STATUS_SUCCESS)
4156 {
4157 Context->MajorFunction = Context->CurrentIrpSp->MajorFunction;
4158 if (Context->MajorFunction == IRP_MJ_DEVICE_CONTROL)
4159 {
4160 if (Context->Info.Buffer != NULL)
4161 {
4162 RxFreePool(Context->Info.Buffer);
4163 Context->Info.Buffer = NULL;
4164 }
4165 }
4166 Context->CurrentIrp->IoStatus.Information = 0;
4167 Context->CurrentIrp->IoStatus.Status = Status;
4169 }
4170 /* Otherwise, call resume routine and done! */
4171 else
4172 {
4173 Status = Context->ResumeRoutine(Context);
4174 if (Status != STATUS_PENDING)
4175 {
4177 }
4178
4179 DPRINT("Not completing, pending\n");
4180 }
4181 }
4182
4184 return Status;
4185}
4186
4187/*
4188 * @implemented
4189 */
4190VOID
4191NTAPI
4194{
4195 KIRQL OldIrql;
4196 BOOLEAN Direct, KeepLoop;
4197
4198 DPRINT("RxFinishSrvCallConstructionDispatcher(%p)\n", Context);
4199
4200 /* In case of failure of starting dispatcher, context is not set
4201 * We keep track of it to fail associated SRV_CALL
4202 */
4203 Direct = (Context == NULL);
4204
4205 /* Separated thread, loop forever */
4206 while (TRUE)
4207 {
4208 PLIST_ENTRY ListEntry;
4210
4211 /* If there are no SRV_CALL to finalize left, just finish thread */
4214 {
4215 KeepLoop = FALSE;
4217 }
4218 /* Otherwise, get the SRV_CALL to finish construction */
4219 else
4220 {
4221 ListEntry = RemoveHeadList(&RxSrvCalldownList);
4222 KeepLoop = TRUE;
4223 }
4225
4226 /* Nothing to do */
4227 if (!KeepLoop)
4228 {
4229 break;
4230 }
4231
4232 /* If direct is set, reset the finisher to avoid electing a winner
4233 * and fail SRV_CALL (see upper comment)
4234 */
4235 Calldown = CONTAINING_RECORD(ListEntry, MRX_SRVCALLDOWN_STRUCTURE, SrvCalldownList);
4236 if (Direct)
4237 {
4238 Calldown->BestFinisher = NULL;
4239 }
4240 /* Finish SRV_CALL construction */
4242 }
4243}
4244
4245/*
4246 * @implemented
4247 */
4250 IN PFCB Fcb,
4251 IN BOOLEAN SynchronizeWithLazyWriter)
4252{
4254
4255 PAGED_CODE();
4256
4257 /* Deal with Cc */
4259 /* If we're asked to sync with LW, do it in case of success */
4260 if (SynchronizeWithLazyWriter && NT_SUCCESS(IoStatus.Status))
4261 {
4264 }
4265
4266 DPRINT("Flushing for FCB %p returns %lx\n", Fcb, IoStatus.Status);
4267 return IoStatus.Status;
4268}
4269
4270/*
4271 * @implemented
4272 */
4273VOID
4275 PVOID Object)
4276{
4277 PAGED_CODE();
4278
4279 DPRINT("Freeing %p\n", Object);
4280
4281 /* If that's a FOBX/SRV_OPEN, nothing to do, just free it */
4283 {
4284 RxFreePoolWithTag(Object, RX_FCB_POOLTAG);
4285 }
4286 /* If that's a FCB... */
4287 else if (NodeTypeIsFcb(Object))
4288 {
4289 PFCB Fcb;
4291
4292 Fcb = (PFCB)Object;
4294
4295 /* Delete per stream contexts */
4297
4299
4300 /* If there was a non-paged FCB allocated, free it */
4302 {
4303 RxFreePoolWithTag(Fcb->NonPaged, RX_NONPAGEDFCB_POOLTAG);
4304 }
4305
4306 /* Free the FCB */
4307 RxFreePool(Fcb);
4308
4309 /* Update statistics */
4311 InterlockedDecrement((volatile long *)&DeviceObject->NumberOfActiveFcbs);
4312 }
4313}
4314
4315/*
4316 * @implemented
4317 */
4318VOID
4320 PVOID pObject)
4321{
4322 PAGED_CODE();
4323
4324 /* First, perform a few sanity checks if we're dealing with a SRV_CALL or a NET_ROOT */
4326 {
4327 PSRV_CALL SrvCall;
4329
4330 SrvCall = (PSRV_CALL)pObject;
4331 DeviceObject = SrvCall->RxDeviceObject;
4332 if (DeviceObject != NULL)
4333 {
4335 {
4336 ASSERT(SrvCall->Context == NULL);
4337 }
4338
4339 ASSERT(SrvCall->Context2 == NULL);
4340
4341 SrvCall->RxDeviceObject = NULL;
4342 }
4343 }
4344 else if (NodeType(pObject) == RDBSS_NTC_NETROOT)
4345 {
4346 PNET_ROOT NetRoot;
4347
4348 NetRoot = (PNET_ROOT)pObject;
4349 NetRoot->pSrvCall = NULL;
4350 NetRoot->NodeTypeCode = NodeType(pObject) | 0xF000;
4351 }
4352
4353 /* And just free the object */
4355}
4356
4357/*
4358 * @implemented
4359 */
4360VOID
4362 IN OUT PSRV_CALL SrvCall,
4363 IN PSRV_OPEN SrvOpen,
4364 IN OUT PLIST_ENTRY RequestsListHead)
4365{
4366 KIRQL OldIrql;
4367 LIST_ENTRY Discarded, *Entry;
4369
4370 /* Dispatch any pending operation first */
4371 RxpDispatchChangeBufferingStateRequests(SrvCall, SrvOpen, &Discarded);
4372
4373 /* Then, get any entry related to our key and SRV_OPEN */
4374 KeAcquireSpinLock(&SrvCall->BufferingManager.SpinLock, &OldIrql);
4375 Entry = SrvCall->BufferingManager.HandlerList.Flink;
4376 while (Entry != &SrvCall->BufferingManager.HandlerList)
4377 {
4379 Entry = Entry->Flink;
4380 if (Request->SrvOpenKey == SrvOpen->Key && Request->SrvOpen == SrvOpen)
4381 {
4382 RemoveEntryList(&Request->ListEntry);
4383 InsertTailList(RequestsListHead, &Request->ListEntry);
4384 }
4385 }
4386 KeReleaseSpinLock(&SrvCall->BufferingManager.SpinLock, OldIrql);
4387
4388 /* Perform the same search in the last change list */
4389 Entry = SrvCall->BufferingManager.LastChanceHandlerList.Flink;
4390 while (Entry != &SrvCall->BufferingManager.LastChanceHandlerList)
4391 {
4393 Entry = Entry->Flink;
4394 if (Request->SrvOpenKey == SrvOpen->Key && Request->SrvOpen == SrvOpen)
4395 {
4396 RemoveEntryList(&Request->ListEntry);
4397 InsertTailList(RequestsListHead, &Request->ListEntry);
4398 }
4399 }
4400
4401 /* Discard the discarded requests */
4403}
4404
4405/*
4406 * @implemented
4407 */
4411{
4414
4415 PAGED_CODE();
4416
4417 /* We only handle a few object types */
4421
4422 /* Get the device object depending on the object */
4423 switch (NodeType)
4424 {
4425 case RDBSS_NTC_FOBX:
4426 {
4427 PFOBX Fobx;
4428
4429 Fobx = (PFOBX)Instance;
4431 break;
4432 }
4433
4434 case RDBSS_NTC_SRVCALL:
4435 {
4436 PSRV_CALL SrvCall;
4437
4438 SrvCall = (PSRV_CALL)Instance;
4439 DeviceObject = SrvCall->RxDeviceObject;
4440 break;
4441 }
4442
4443 case RDBSS_NTC_NETROOT:
4444 {
4445 PNET_ROOT NetRoot;
4446
4447 NetRoot = (PNET_ROOT)Instance;
4448 DeviceObject = NetRoot->pSrvCall->RxDeviceObject;
4449 break;
4450 }
4451
4453 {
4454 PV_NET_ROOT VNetRoot;
4455
4456 VNetRoot = (PV_NET_ROOT)Instance;
4457 DeviceObject = VNetRoot->pNetRoot->pSrvCall->RxDeviceObject;
4458 break;
4459 }
4460
4461 case RDBSS_NTC_SRVOPEN:
4462 {
4463 PSRV_OPEN SrvOpen;
4464
4465 SrvOpen = (PSRV_OPEN)Instance;
4466 DeviceObject = ((PFCB)SrvOpen->pFcb)->RxDeviceObject;
4467 break;
4468 }
4469
4470 default:
4472 break;
4473 }
4474
4475 /* Job done */
4476 return DeviceObject;
4477}
4478
4479/*
4480 * @implemented
4481 */
4482VOID
4484 IN PFCB Fcb,
4486{
4487 PAGED_CODE();
4488
4489 *FileSize = Fcb->Header.FileSize.QuadPart;
4490}
4491
4492/*
4493 * @implemented
4494 */
4496NTAPI
4498 VOID)
4499{
4500 return RxData.OurProcess;
4501}
4502
4503/*
4504 * @implemented
4505 */
4508 PSRV_CALL SrvCall)
4509{
4520
4521 return STATUS_SUCCESS;
4522}
4523
4524/*
4525 * @implemented
4526 */
4527VOID
4528NTAPI
4530 IN PIRP Irp,
4531 IN PRDBSS_DEVICE_OBJECT RxDeviceObject,
4532 IN ULONG InitialContextFlags,
4533 IN OUT PRX_CONTEXT RxContext)
4534{
4536
4537 /* Initialize our various fields */
4538 RxContext->NodeTypeCode = RDBSS_NTC_RX_CONTEXT;
4539 RxContext->NodeByteSize = sizeof(RX_CONTEXT);
4540 RxContext->ReferenceCount = 1;
4541 RxContext->SerialNumber = InterlockedExchangeAdd((volatile LONG *)&RxContextSerialNumberCounter, 1);
4542 RxContext->RxDeviceObject = RxDeviceObject;
4543 KeInitializeEvent(&RxContext->SyncEvent, SynchronizationEvent, FALSE);
4544 RxInitializeScavengerEntry(&RxContext->ScavengerEntry);
4545 InitializeListHead(&RxContext->BlockedOperations);
4546 RxContext->MRxCancelRoutine = NULL;
4547 RxContext->ResumeRoutine = NULL;
4548 RxContext->Flags |= InitialContextFlags;
4549 RxContext->CurrentIrp = Irp;
4550 RxContext->LastExecutionThread = PsGetCurrentThread();
4551 RxContext->OriginalThread = RxContext->LastExecutionThread;
4552
4553 /* If've got no IRP, mark RX_CONTEXT */
4554 if (Irp == NULL)
4555 {
4556 RxContext->CurrentIrpSp = NULL;
4557 RxContext->MajorFunction = IRP_MJ_MAXIMUM_FUNCTION + 1;
4558 RxContext->MinorFunction = 0;
4559 }
4560 else
4561 {
4562 /* Otherwise, first determine whether we are performing async operation */
4564 if (Stack->FileObject != NULL)
4565 {
4566 PFCB Fcb;
4567
4568 Fcb = Stack->FileObject->FsContext;
4570 ((Fcb != NULL && NodeTypeIsFcb(Fcb)) &&
4571 (Stack->MajorFunction == IRP_MJ_READ || Stack->MajorFunction == IRP_MJ_WRITE || Stack->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL) &&
4572 (Fcb->pNetRoot != NULL && (Fcb->pNetRoot->Type == NET_ROOT_PIPE))))
4573 {
4574 RxContext->Flags |= RX_CONTEXT_FLAG_ASYNC_OPERATION;
4575 }
4576 }
4577
4578 if (Stack->MajorFunction == IRP_MJ_DIRECTORY_CONTROL && Stack->MinorFunction == IRP_MN_NOTIFY_CHANGE_DIRECTORY)
4579 {
4580 RxContext->Flags |= RX_CONTEXT_FLAG_ASYNC_OPERATION;
4581 }
4582 if (Stack->MajorFunction == IRP_MJ_DEVICE_CONTROL)
4583 {
4584 RxContext->Flags |= RX_CONTEXT_FLAG_ASYNC_OPERATION;
4585 }
4586
4587 /* Set proper flags if TopLevl IRP/Device */
4589 {
4590 RxContext->Flags |= RX_CONTEXT_FLAG_RECURSIVE_CALL;
4591 }
4592 if (RxGetTopDeviceObjectIfRdbssIrp() == RxDeviceObject)
4593 {
4594 RxContext->Flags |= RX_CONTEXT_FLAG_THIS_DEVICE_TOP_LEVEL;
4595 }
4596
4597 /* Copy stack information */
4598 RxContext->MajorFunction = Stack->MajorFunction;
4599 RxContext->MinorFunction = Stack->MinorFunction;
4600 ASSERT(RxContext->MajorFunction <= IRP_MJ_MAXIMUM_FUNCTION);
4601 RxContext->CurrentIrpSp = Stack;
4602
4603 /* If we have a FO associated, learn for more */
4604 if (Stack->FileObject != NULL)
4605 {
4606 PFCB Fcb;
4607 PFOBX Fobx;
4608
4609 /* Get the FCB and CCB (FOBX) */
4610 Fcb = Stack->FileObject->FsContext;
4611 Fobx = Stack->FileObject->FsContext2;
4612 RxContext->pFcb = (PMRX_FCB)Fcb;
4613 if (Fcb != NULL && NodeTypeIsFcb(Fcb))
4614 {
4615 RxContext->NonPagedFcb = Fcb->NonPaged;
4616 }
4617
4618 /* We have a FOBX, this not a DFS opening, keep track of it */
4619 if (Fobx != NULL && Fobx != UIntToPtr(DFS_OPEN_CONTEXT) && Fobx != UIntToPtr(DFS_DOWNLEVEL_OPEN_CONTEXT))
4620 {
4621 RxContext->pFobx = (PMRX_FOBX)Fobx;
4622 RxContext->pRelevantSrvOpen = Fobx->pSrvOpen;
4623 if (Fobx->NodeTypeCode == RDBSS_NTC_FOBX)
4624 {
4625 RxContext->FobxSerialNumber = InterlockedIncrement((volatile LONG *)&Fobx->FobxSerialNumber);
4626 }
4627 }
4628 else
4629 {
4630 RxContext->pFobx = NULL;
4631 }
4632
4633 /* In case of directory change notification, Fobx may be a VNetRoot, take note of that */
4634 if (RxContext->MajorFunction == IRP_MJ_DIRECTORY_CONTROL && RxContext->MinorFunction == IRP_MN_NOTIFY_CHANGE_DIRECTORY &&
4635 Fobx != NULL)
4636 {
4637 PV_NET_ROOT VNetRoot = NULL;
4638
4639 if (Fobx->NodeTypeCode == RDBSS_NTC_FOBX)
4640 {
4641 VNetRoot = Fcb->VNetRoot;
4642 }
4643 else if (Fobx->NodeTypeCode == RDBSS_NTC_V_NETROOT)
4644 {
4645 VNetRoot = (PV_NET_ROOT)Fobx;
4646 }
4647
4648 if (VNetRoot != NULL)
4649 {
4650 RxContext->NotifyChangeDirectory.pVNetRoot = (PMRX_V_NET_ROOT)VNetRoot;
4651 }
4652 }
4653
4654 /* Remember if that's a write through file */
4655 RxContext->RealDevice = Stack->FileObject->DeviceObject;
4656 if (BooleanFlagOn(Stack->FileObject->Flags, FO_WRITE_THROUGH))
4657 {
4658 RxContext->Flags |= RX_CONTEXT_FLAG_WRITE_THROUGH;
4659 }
4660 }
4661 }
4662
4663 if (RxContext->MajorFunction != IRP_MJ_DEVICE_CONTROL)
4664 {
4665 DPRINT("New Ctxt: %p for MN: %d, IRP: %p, THRD: %p, FCB: %p, FOBX:%p #%lx\n",
4666 RxContext, RxContext->MinorFunction, Irp,
4667 PsGetCurrentThread(), RxContext->pFcb, RxContext->pFobx,
4668 RxContext->SerialNumber);
4669 }
4670}
4671
4672/*
4673 * @implemented
4674 */
4675VOID
4676NTAPI
4678 VOID)
4679{
4680 /* Nothing to do */
4681}
4682
4683/*
4684 * @implemented
4685 */
4687NTAPI
4689 VOID)
4690{
4692 HANDLE ThreadHandle;
4693
4694 PAGED_CODE();
4695
4698
4699 /* Set appropriate timeouts: 10s & 60s */
4700 RxWorkQueueWaitInterval[CriticalWorkQueue].QuadPart = -10 * 1000 * 1000 * 10;
4701 RxWorkQueueWaitInterval[DelayedWorkQueue].QuadPart = -10 * 1000 * 1000 * 10;
4703 RxSpinUpDispatcherWaitInterval.QuadPart = -60 * 1000 * 1000 * 10;
4704
4708
4709 /* Initialize our dispatchers */
4711 if (!NT_SUCCESS(Status))
4712 {
4713 return Status;
4714 }
4715
4717 if (!NT_SUCCESS(Status))
4718 {
4719 return Status;
4720 }
4721
4722 /* And start them */
4730 if (NT_SUCCESS(Status))
4731 {
4732 ZwClose(ThreadHandle);
4733 }
4734
4735 return Status;
4736}
4737
4738/*
4739 * @implemented
4740 */
4741VOID
4743 IN OUT PRX_FCB_TABLE FcbTable,
4744 IN BOOLEAN CaseInsensitiveMatch)
4745{
4746 USHORT i;
4747
4748 PAGED_CODE();
4749
4750 FcbTable->NodeTypeCode = RDBSS_NTC_FCB_TABLE;
4751 FcbTable->NodeByteSize = sizeof(RX_FCB_TABLE);
4752
4753 ExInitializeResourceLite(&FcbTable->TableLock);
4754 FcbTable->CaseInsensitiveMatch = CaseInsensitiveMatch;
4755 FcbTable->Version = 0;
4756 FcbTable->TableEntryForNull = NULL;
4757
4758 FcbTable->NumberOfBuckets = RX_FCB_TABLE_NUMBER_OF_HASH_BUCKETS;
4759 for (i = 0; i < FcbTable->NumberOfBuckets; ++i)
4760 {
4761 InitializeListHead(&FcbTable->HashBuckets[i]);
4762 }
4763
4764 FcbTable->Lookups = 0;
4765 FcbTable->FailedLookups = 0;
4766 FcbTable->Compares = 0;
4767}
4768
4769/*
4770 * @implemented
4771 */
4772VOID
4773NTAPI
4775 OUT PLOWIO_CONTEXT LowIoContext,
4777{
4778 PRX_CONTEXT RxContext;
4780
4781 PAGED_CODE();
4782
4783 RxContext = CONTAINING_RECORD(LowIoContext, RX_CONTEXT, LowIoContext);
4784 ASSERT(LowIoContext == &RxContext->LowIoContext);
4785
4786 Stack = RxContext->CurrentIrpSp;
4787
4790 RxContext->LowIoContext.Operation = Operation;
4791
4792 switch (Operation)
4793 {
4794 case LOWIO_OP_READ:
4795 case LOWIO_OP_WRITE:
4796 /* In case of RW, set a canary, to make sure these fields are properly set
4797 * they will be asserted when lowio request will be submit to mini-rdr
4798 * See LowIoSubmit()
4799 */
4800 RxContext->LowIoContext.ParamsFor.ReadWrite.ByteOffset = 0xFFFFFFEE;
4801 RxContext->LowIoContext.ParamsFor.ReadWrite.ByteCount = 0xEEEEEEEE;
4802 RxContext->LowIoContext.ParamsFor.ReadWrite.Key = Stack->Parameters.Read.Key;
4803
4804 /* Keep track of paging IOs */
4805 if (BooleanFlagOn(RxContext->CurrentIrp->Flags, IRP_PAGING_IO))
4806 {
4808 }
4809 else
4810 {
4811 RxContext->LowIoContext.ParamsFor.ReadWrite.Flags = 0;
4812 }
4813
4814 break;
4815
4816 case LOWIO_OP_FSCTL:
4817 case LOWIO_OP_IOCTL:
4818 /* This will be initialized later on with a call to RxLowIoPopulateFsctlInfo() */
4819 RxContext->LowIoContext.ParamsFor.FsCtl.Flags = 0;
4825 break;
4826
4827 /* Nothing to do for these */
4830 case LOWIO_OP_UNLOCK:
4833 case LOWIO_OP_CLEAROUT:
4834 break;
4835
4836 default:
4837 /* Should never happen */
4838 ASSERT(FALSE);
4839 break;
4840 }
4841}
4842
4843/*
4844 * @implemented
4845 */
4846VOID
4848 PLOWIO_PER_FCB_INFO LowIoPerFcbInfo)
4849{
4850 PAGED_CODE();
4851
4854}
4855
4856/*
4857 * @implemented
4858 */
4861 IN OUT PRDBSS_DEVICE_OBJECT pMRxDeviceObject)
4862{
4863 PAGED_CODE();
4864
4865 pMRxDeviceObject->DispatcherContext.NumberOfWorkerThreads = 0;
4866 pMRxDeviceObject->DispatcherContext.pTearDownEvent = NULL;
4867
4868 return STATUS_SUCCESS;
4869}
4870
4871/*
4872 * @implemented
4873 */
4874VOID
4876 IN OUT PRX_PREFIX_TABLE ThisTable,
4878 IN BOOLEAN CaseInsensitiveMatch)
4879{
4880 PAGED_CODE();
4881
4882 if (TableSize == 0)
4883 {
4885 }
4886
4887 ThisTable->NodeTypeCode = RDBSS_NTC_PREFIX_TABLE;
4888 ThisTable->NodeByteSize = sizeof(RX_PREFIX_TABLE);
4889 InitializeListHead(&ThisTable->MemberQueue);
4890 ThisTable->Version = 0;
4891 ThisTable->TableEntryForNull = NULL;
4892 ThisTable->IsNetNameTable = FALSE;
4893 ThisTable->CaseInsensitiveMatch = CaseInsensitiveMatch;
4894 ThisTable->TableSize = TableSize;
4895
4896 if (TableSize > 0)
4897 {
4898 USHORT i;
4899
4900 for (i = 0; i < RX_PREFIX_TABLE_DEFAULT_LENGTH; ++i)
4901 {
4902 InitializeListHead(&ThisTable->HashBuckets[i]);
4903 }
4904 }
4905}
4906
4907/*
4908 * @implemented
4909 */
4910VOID
4912 PPURGE_SYNCHRONIZATION_CONTEXT PurgeSyncronizationContext)
4913{
4914 PAGED_CODE();
4915
4916 InitializeListHead(&PurgeSyncronizationContext->ContextsAwaitingPurgeCompletion);
4917 PurgeSyncronizationContext->PurgeInProgress = FALSE;
4918}
4919
4922 IN PRX_CONTEXT RxContext,
4923 IN OUT PSRV_CALL SrvCall)
4924{
4925 PAGED_CODE();
4926
4927 SrvCall->pPrincipalName = NULL;
4928
4929 /* We only have stuff to initialize for file opening from DFS */
4930 if (RxContext->MajorFunction != IRP_MJ_CREATE || RxContext->Create.EaLength == 0)
4931 {
4932 return STATUS_SUCCESS;
4933 }
4934
4935 ASSERT(RxContext->Create.EaBuffer != NULL);
4936
4939}
4940
4941/*
4942 * @implemented
4943 */
4945NTAPI
4947 VOID)
4948{
4949 PAGED_CODE();
4950
4951 RxTimerInterval.QuadPart = -550000;
4957 RxTimerTickCount = 0;
4958
4959 return STATUS_SUCCESS;
4960}
4961
4964 PRX_CONTEXT RxContext,
4965 OUT LUID *LogonId,
4967 OUT PUNICODE_STRING *UserNamePtr,
4968 OUT PUNICODE_STRING *UserDomainNamePtr,
4969 OUT PUNICODE_STRING *PasswordPtr,
4971{
4974
4975 PAGED_CODE();
4976
4977 DPRINT("RxInitializeVNetRootParameters(%p, %p, %p, %p, %p, %p, %p)\n", RxContext,
4978 LogonId, SessionId, UserNamePtr, UserDomainNamePtr, PasswordPtr, Flags);
4979
4980 *UserNamePtr = NULL;
4981 *UserDomainNamePtr = NULL;
4982 *PasswordPtr = NULL;
4983 /* By default, that's not CSC instance */
4984 *Flags &= ~VNETROOT_FLAG_CSCAGENT_INSTANCE;
4985
4986 Token = SeQuerySubjectContextToken(&RxContext->Create.NtCreateParameters.SecurityContext->AccessState->SubjectSecurityContext);
4988 {
4989 return STATUS_ACCESS_DENIED;
4990 }
4991
4992 /* Get LogonId */
4994 if (!NT_SUCCESS(Status))
4995 {
4996 return Status;
4997 }
4998
4999 /* And SessionId */
5001 if (!NT_SUCCESS(Status))
5002 {
5003 return Status;
5004 }
5005
5006 if (RxContext->Create.UserName.Buffer != NULL)
5007 {
5010 goto Leave;
5011 }
5012
5013 /* Deal with connection credentials */
5014 if (RxContext->Create.UserDomainName.Buffer != NULL)
5015 {
5018 goto Leave;
5019 }
5020
5021 if (RxContext->Create.Password.Buffer != NULL)
5022 {
5025 goto Leave;
5026 }
5027
5028Leave:
5029 if (NT_SUCCESS(Status))
5030 {
5031 /* If that's a CSC instance, mark it as such */
5032 if (RxIsThisACscAgentOpen(RxContext))
5033 {
5035 }
5036 return Status;
5037 }
5038
5039 return Status;
5040}
5041
5042/*
5043 * @implemented
5044 */
5045VOID
5048 WORK_QUEUE_TYPE WorkQueueType,
5049 ULONG MaximumNumberOfWorkerThreads,
5050 ULONG MinimumNumberOfWorkerThreads)
5051{
5052 PAGED_CODE();
5053
5054 WorkQueue->Type = WorkQueueType;
5055 WorkQueue->MaximumNumberOfWorkerThreads = MaximumNumberOfWorkerThreads;
5056 WorkQueue->MinimumNumberOfWorkerThreads = MinimumNumberOfWorkerThreads;
5057
5059 WorkQueue->SpinUpRequestPending = FALSE;
5060 WorkQueue->pRundownContext = NULL;
5061 WorkQueue->NumberOfWorkItemsDispatched = 0;
5062 WorkQueue->NumberOfWorkItemsToBeDispatched = 0;
5063 WorkQueue->CumulativeQueueLength = 0;
5064 WorkQueue->NumberOfSpinUpRequests = 0;
5065 WorkQueue->NumberOfActiveWorkerThreads = 0;
5066 WorkQueue->NumberOfIdleWorkerThreads = 0;
5067 WorkQueue->NumberOfFailedSpinUpRequests = 0;
5068 WorkQueue->WorkQueueItemForSpinUpWorkerThreadInUse = 0;
5069 WorkQueue->WorkQueueItemForTearDownWorkQueue.List.Flink = NULL;
5070 WorkQueue->WorkQueueItemForTearDownWorkQueue.WorkerRoutine = NULL;
5071 WorkQueue->WorkQueueItemForTearDownWorkQueue.Parameter = NULL;
5072 WorkQueue->WorkQueueItemForTearDownWorkQueue.pDeviceObject = NULL;
5073 WorkQueue->WorkQueueItemForSpinUpWorkerThread.List.Flink = NULL;
5074 WorkQueue->WorkQueueItemForSpinUpWorkerThread.WorkerRoutine = NULL;
5075 WorkQueue->WorkQueueItemForSpinUpWorkerThread.Parameter = NULL;
5076 WorkQueue->WorkQueueItemForSpinUpWorkerThread.pDeviceObject = NULL;
5077 WorkQueue->WorkQueueItemForSpinDownWorkerThread.List.Flink = NULL;
5078 WorkQueue->WorkQueueItemForSpinDownWorkerThread.WorkerRoutine = NULL;
5079 WorkQueue->WorkQueueItemForSpinDownWorkerThread.Parameter = NULL;
5080 WorkQueue->WorkQueueItemForSpinDownWorkerThread.pDeviceObject = NULL;
5081
5082 KeInitializeQueue(&WorkQueue->Queue, MaximumNumberOfWorkerThreads);
5083 KeInitializeSpinLock(&WorkQueue->SpinLock);
5084}
5085
5086/*
5087 * @implemented
5088 */
5091 PRX_WORK_QUEUE_DISPATCHER Dispatcher)
5092{
5094 ULONG MaximumNumberOfWorkerThreads;
5095
5096 PAGED_CODE();
5097
5098 /* Number of threads will depend on system capacity */
5100 {
5101 MaximumNumberOfWorkerThreads = 5;
5102 }
5103 else
5104 {
5105 MaximumNumberOfWorkerThreads = 10;
5106 }
5107
5108 /* Initialize the work queues */
5110 MaximumNumberOfWorkerThreads, 1);
5113
5114 /* And start the worker threads */
5117 &Dispatcher->WorkQueue[HyperCriticalWorkQueue]);
5118 if (!NT_SUCCESS(Status))
5119 {
5120 return Status;
5121 }
5122
5125 &Dispatcher->WorkQueue[CriticalWorkQueue]);
5126 if (!NT_SUCCESS(Status))
5127 {
5128 return Status;
5129 }
5130
5133 &Dispatcher->WorkQueue[DelayedWorkQueue]);
5134 return Status;
5135}
5136
5137/*
5138 * @implemented
5139 */
5140VOID
5142 IN OUT PSRV_OPEN SrvOpen)
5143{
5144 PRX_BUFFERING_MANAGER BufferingManager;
5145
5146 PAGED_CODE();
5147
5148 SrvOpen->Key = NULL;
5149
5150 /* Just keep track of the opening request */
5151 BufferingManager = &((PSRV_CALL)((PFCB)SrvOpen->pFcb)->VNetRoot->pNetRoot->pSrvCall)->BufferingManager;
5153
5154 InitializeListHead(&SrvOpen->SrvOpenKeyList);
5155}
5156
5157/*
5158 * @implemented
5159 */
5162 PRDBSS_DEVICE_OBJECT pMRxDeviceObject,
5163 WORK_QUEUE_TYPE WorkQueueType,
5164 PRX_WORK_QUEUE_ITEM WorkQueueItem)
5165{
5166 KIRQL OldIrql;
5168 BOOLEAN SpinUpThreads;
5170
5171 /* No dispatcher, nothing to insert */
5173 {
5174 return STATUS_UNSUCCESSFUL;
5175 }
5176
5177 /* Get the work queue */
5179
5180 KeAcquireSpinLock(&WorkQueue->SpinLock, &OldIrql);
5181 /* Only insert if the work queue is in decent state */
5182 if (WorkQueue->State != RxWorkQueueActive || pMRxDeviceObject->DispatcherContext.pTearDownEvent != NULL)
5183 {
5185 }
5186 else
5187 {
5188 SpinUpThreads = FALSE;
5189 WorkQueueItem->pDeviceObject = pMRxDeviceObject;
5191 WorkQueue->CumulativeQueueLength += WorkQueue->NumberOfWorkItemsToBeDispatched;
5192 InterlockedIncrement(&WorkQueue->NumberOfWorkItemsToBeDispatched);
5193
5194 /* If required (and possible!), spin up a new worker thread */
5195 if (WorkQueue->NumberOfIdleWorkerThreads < WorkQueue->NumberOfWorkItemsToBeDispatched &&
5196 WorkQueue->NumberOfActiveWorkerThreads < WorkQueue->MaximumNumberOfWorkerThreads &&
5197 !WorkQueue->SpinUpRequestPending)
5198 {
5199 WorkQueue->SpinUpRequestPending = TRUE;
5200 SpinUpThreads = TRUE;
5201 }
5202
5204 }
5205 KeReleaseSpinLock(&WorkQueue->SpinLock, OldIrql);
5206
5207 /* If we failed, return and still not insert item */
5208 if (!NT_SUCCESS(Status))
5209 {
5210 return Status;
5211 }
5212
5213 /* All fine, insert the item */
5214 KeInsertQueue(&WorkQueue->Queue, &WorkQueueItem->List);
5215
5216 /* And start a new worker thread if needed */
5217 if (SpinUpThreads)
5218 {
5220 }
5221
5222 return Status;
5223}
5224
5225BOOLEAN
5227 IN PRX_CONTEXT RxContext)
5228{
5229 BOOLEAN CscAgent;
5230
5231 CscAgent = FALSE;
5232
5233 /* Client Side Caching is DFS stuff - we don't support it */
5234 if (RxContext->Create.EaLength != 0)
5235 {
5237 }
5238
5239 if (RxContext->Create.NtCreateParameters.DfsNameContext != NULL &&
5240 ((PDFS_NAME_CONTEXT)RxContext->Create.NtCreateParameters.DfsNameContext)->NameContextType == 0xAAAAAAAA)
5241 {
5242 CscAgent = TRUE;
5243 }
5244
5245 return CscAgent;
5246}
5247
5248VOID
5250 IN PRX_CONTEXT RxContext,
5253{
5254 PIRP Irp;
5255 PMDL Mdl = NULL;
5256
5257 PAGED_CODE();
5258
5259 _SEH2_TRY
5260 {
5261 Irp = RxContext->CurrentIrp;
5262 /* If we already have a MDL, make sure it's locked */
5263 if (Irp->MdlAddress != NULL)
5264 {
5265 ASSERT(RxLowIoIsMdlLocked(Irp->MdlAddress));
5266 }
5267 else
5268 {
5269 /* That likely means the driver asks for buffered IOs - we don't support it! */
5271
5272 /* If we have a real length */
5273 if (BufferLength > 0)
5274 {
5275 /* Allocate a MDL and lock it */
5276 Mdl = IoAllocateMdl(Irp->UserBuffer, BufferLength, FALSE, FALSE, Irp);
5277 if (Mdl == NULL)
5278 {
5279 RxContext->StoredStatus = STATUS_INSUFFICIENT_RESOURCES;
5281 }
5282
5283 MmProbeAndLockPages(Mdl, Irp->RequestorMode, Operation);
5284 }
5285 }
5286 }
5288 {
5290
5292
5293 /* Free the possible MDL we have allocated */
5294 IoFreeMdl(Mdl);
5295 Irp->MdlAddress = NULL;
5296
5297 RxContext->Flags |= RX_CONTEXT_FLAG_NO_EXCEPTION_BREAKPOINT;
5298
5299 /* Fix status */
5301 {
5303 }
5304
5305 RxContext->IoStatusBlock.Status = Status;
5307 }
5308 _SEH2_END;
5309}
5310
5311/*
5312 * @implemented
5313 */
5316 IN PRX_CONTEXT RxContext)
5317{
5320
5321 PAGED_CODE();
5322
5323 DPRINT("RxLowIoCompletionTail(%p)\n", RxContext);
5324
5325 /* Only continue if we're at APC_LEVEL or lower */
5326 if (RxShouldPostCompletion() &&
5327 !BooleanFlagOn(RxContext->LowIoContext.Flags, LOWIO_CONTEXT_FLAG_CAN_COMPLETE_AT_DPC_LEVEL))
5328 {
5330 }
5331
5332 /* Call the completion routine */
5333 DPRINT("Calling completion routine: %p\n", RxContext->LowIoContext.CompletionRoutine);
5334 Status = RxContext->LowIoContext.CompletionRoutine(RxContext);
5336 {
5337 return Status;
5338 }
5339
5340 /* If it was a RW operation, for a paging file ... */
5341 Operation = RxContext->LowIoContext.Operation;
5343 {
5344 /* Remove ourselves from the list and resume operations */
5345 if (BooleanFlagOn(RxContext->LowIoContext.ParamsFor.ReadWrite.Flags, LOWIO_READWRITEFLAG_PAGING_IO))
5346 {
5348 RemoveEntryList(&RxContext->RxContextSerializationQLinks);
5349 RxContext->RxContextSerializationQLinks.Flink = NULL;
5350 RxContext->RxContextSerializationQLinks.Blink = NULL;
5353 }
5354 }
5355 else
5356 {
5357 /* Sanity check: we had known operation */
5359 }
5360
5361 /* If not sync operation, complete now. Otherwise, caller has already completed */
5362 if (!BooleanFlagOn(RxContext->LowIoContext.Flags, LOWIO_CONTEXT_FLAG_SYNCCALL))
5363 {
5364 RxCompleteRequest(RxContext, Status);
5365 }
5366
5367 DPRINT("Status: %x\n", Status);
5368 return Status;
5369}
5370
5371/*
5372 * @implemented
5373 */
5375NTAPI
5377 IN PRX_CONTEXT RxContext)
5378{
5379 PMDL Mdl;
5380 PIRP Irp;
5381 UCHAR Method;
5383
5384 PAGED_CODE();
5385
5386 DPRINT("RxLowIoPopulateFsctlInfo(%p)\n", RxContext);
5387
5388 Irp = RxContext->CurrentIrp;
5389 Stack = RxContext->CurrentIrpSp;
5390
5391 /* Copy stack parameters */
5392 RxContext->LowIoContext.ParamsFor.FsCtl.FsControlCode = Stack->Parameters.FileSystemControl.FsControlCode;
5393 RxContext->LowIoContext.ParamsFor.FsCtl.InputBufferLength = Stack->Parameters.FileSystemControl.InputBufferLength;
5394 RxContext->LowIoContext.ParamsFor.FsCtl.OutputBufferLength = Stack->Parameters.FileSystemControl.OutputBufferLength;
5395 RxContext->LowIoContext.ParamsFor.FsCtl.MinorFunction = Stack->MinorFunction;
5396 Method = METHOD_FROM_CTL_CODE(RxContext->LowIoContext.ParamsFor.FsCtl.FsControlCode);
5397
5398 /* Same buffer in case of buffered */
5399 if (Method == METHOD_BUFFERED)
5400 {
5401 RxContext->LowIoContext.ParamsFor.FsCtl.pInputBuffer = Irp->AssociatedIrp.SystemBuffer;
5402 RxContext->LowIoContext.ParamsFor.FsCtl.pOutputBuffer = Irp->AssociatedIrp.SystemBuffer;
5403
5404 return STATUS_SUCCESS;
5405 }
5406
5407 /* Two buffers for neither */
5408 if (Method == METHOD_NEITHER)
5409 {
5410 RxContext->LowIoContext.ParamsFor.FsCtl.pInputBuffer = Stack->Parameters.FileSystemControl.Type3InputBuffer;
5411 RxContext->LowIoContext.ParamsFor.FsCtl.pOutputBuffer = Irp->UserBuffer;
5412
5413 return STATUS_SUCCESS;
5414 }
5415
5416 /* Only IN/OUT remain */
5417 ASSERT(Method == METHOD_IN_DIRECT || Method == METHOD_OUT_DIRECT);
5418
5419 /* Use system buffer for input */
5420 RxContext->LowIoContext.ParamsFor.FsCtl.pInputBuffer = Irp->AssociatedIrp.SystemBuffer;
5421 /* And MDL for output */
5422 Mdl = Irp->MdlAddress;
5423 if (Mdl != NULL)
5424 {
5425 RxContext->LowIoContext.ParamsFor.FsCtl.pOutputBuffer = MmGetSystemAddressForMdlSafe(Mdl, NormalPagePriority);
5426 if (RxContext->LowIoContext.ParamsFor.FsCtl.pOutputBuffer == NULL)
5427 {
5429 }
5430 }
5431 else
5432 {
5433 RxContext->LowIoContext.ParamsFor.FsCtl.pOutputBuffer = NULL;
5434 }
5435
5436 return STATUS_SUCCESS;
5437}
5438
5440NTAPI
5442 IN PRX_CONTEXT RxContext,
5444{
5447 BOOLEAN Synchronous;
5448 PLOWIO_CONTEXT LowIoContext;
5449
5450 DPRINT("RxLowIoSubmit(%p, %p)\n", RxContext, CompletionRoutine);
5451
5452 PAGED_CODE();
5453
5454 LowIoContext = &RxContext->LowIoContext;
5455 Synchronous = !BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_ASYNC_OPERATION);
5456
5457 LowIoContext->CompletionRoutine = CompletionRoutine;
5458
5460 Operation = LowIoContext->Operation;
5461 switch (Operation)
5462 {
5463 case LOWIO_OP_READ:
5464 case LOWIO_OP_WRITE:
5465 /* Check that the parameters were properly set by caller
5466 * See comment in RxInitializeLowIoContext()
5467 */
5468 ASSERT(LowIoContext->ParamsFor.ReadWrite.ByteOffset != 0xFFFFFFEE);
5469 ASSERT(LowIoContext->ParamsFor.ReadWrite.ByteCount != 0xEEEEEEEE);
5470
5471 /* Lock the buffer */
5472 RxLockUserBuffer(RxContext,
5474 LowIoContext->ParamsFor.ReadWrite.ByteCount);
5475 if (RxNewMapUserBuffer(RxContext) == NULL)
5476 {
5478 }
5479 LowIoContext->ParamsFor.ReadWrite.Buffer = RxContext->CurrentIrp->MdlAddress;
5480
5481 /* If that's a paging IO, initialize serial operation */
5483 {
5484 PFCB Fcb;
5485
5486 Fcb = (PFCB)RxContext->pFcb;
5487
5489 RxContext->BlockedOpsMutex = &RxLowIoPagingIoSyncMutex;
5490 if (Operation == LOWIO_OP_READ)
5491 {
5492 InsertTailList(&Fcb->Specific.Fcb.PagingIoReadsOutstanding, &RxContext->RxContextSerializationQLinks);
5493 }
5494 else
5495 {
5496 InsertTailList(&Fcb->Specific.Fcb.PagingIoWritesOutstanding, &RxContext->RxContextSerializationQLinks);
5497 }
5498
5500 }
5501
5502 break;
5503
5504 case LOWIO_OP_FSCTL:
5505 case LOWIO_OP_IOCTL:
5506 /* Set FSCTL/IOCTL parameters */
5507 Status = RxLowIoPopulateFsctlInfo(RxContext);
5508 /* Check whether we're consistent: a length means a buffer */
5509 if (NT_SUCCESS(Status))
5510 {
5511 if ((LowIoContext->ParamsFor.FsCtl.InputBufferLength > 0 &&
5512 LowIoContext->ParamsFor.FsCtl.pInputBuffer == NULL) ||
5513 (LowIoContext->ParamsFor.FsCtl.OutputBufferLength > 0 &&
5514 LowIoContext->ParamsFor.FsCtl.pOutputBuffer == NULL))
5515 {
5517 }
5518 }
5519 break;
5520
5521 /* Nothing to do */
5524 case LOWIO_OP_UNLOCK:
5527 case LOWIO_OP_CLEAROUT:
5528 break;
5529
5530 default:
5531 ASSERT(FALSE);
5533 break;
5534 }
5535
5536 /* No need to perform extra init in case of posting */
5537 RxContext->Flags |= RX_CONTEXT_FLAG_NO_PREPOSTING_NEEDED;
5538
5539 /* Preflight checks were OK, time to submit */
5540 if (NT_SUCCESS(Status))
5541 {
5543
5544 if (!Synchronous)
5545 {
5546 InterlockedIncrement((volatile long *)&RxContext->ReferenceCount);
5547 /* If not synchronous, we're likely to return before the operation is finished */
5548 if (!BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_IN_FSP))
5549 {
5550 IoMarkIrpPending(RxContext->CurrentIrp);
5551 }
5552 }
5553
5554 Dispatch = RxContext->RxDeviceObject->Dispatch;
5555 if (Dispatch != NULL)
5556 {
5557 /* We'll try to execute until the mini-rdr doesn't return pending */
5558 do
5559 {
5560 RxContext->IoStatusBlock.Information = 0;
5561
5562 MINIRDR_CALL(Status, RxContext, Dispatch, MRxLowIOSubmit[Operation], (RxContext));
5563 if (Status == STATUS_PENDING)
5564 {
5565 /* Unless it's not synchronous, caller will be happy with pending op */
5566 if (!Synchronous)
5567 {
5568 return Status;
5569 }
5570
5571 RxWaitSync(RxContext);
5572 Status = RxContext->IoStatusBlock.Status;
5573 }
5574 else
5575 {
5576 if (!Synchronous)
5577 {
5578 /* We had marked the IRP pending, whereas the operation finished, drop that */
5579 if (Status != STATUS_RETRY)
5580 {
5581 if (!BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_IN_FSP))
5582 {
5583 RxContext->CurrentIrpSp->Flags &= ~SL_PENDING_RETURNED;
5584 }
5585
5586 InterlockedDecrement((volatile long *)&RxContext->ReferenceCount);
5587 }
5588 }
5589 }
5590 } while (Status == STATUS_PENDING);
5591 }
5592 else
5593 {
5595 }
5596 }
5597
5598 /* Call completion and return */
5599 RxContext->IoStatusBlock.Status = Status;
5600 LowIoContext->Flags |= LOWIO_CONTEXT_FLAG_SYNCCALL;
5601 return RxLowIoCompletionTail(RxContext);
5602}
5603
5604/*
5605 * @implemented
5606 */
5607PVOID
5609 IN PRX_CONTEXT RxContext)
5610{
5611 PIRP Irp;
5612
5613 PAGED_CODE();
5614
5615 Irp = RxContext->CurrentIrp;
5616 /* We should have a MDL (buffered IOs are not supported!) */
5617 if (Irp->MdlAddress != NULL)
5618 {
5619 ASSERT(FALSE);
5621 }
5622
5623 /* Just return system buffer */
5624 return Irp->AssociatedIrp.SystemBuffer;
5625}
5626
5627/*
5628 * @implemented
5629 */
5630VOID
5632 PFOBX pFobx,
5633 PBOOLEAN NeedPurge)
5634{
5635 PFCB Fcb;
5636 PFOBX ScavengerFobx;
5637 LARGE_INTEGER TickCount;
5638 PRDBSS_SCAVENGER Scavenger;
5639
5640 PAGED_CODE();
5641
5642 /* No FOBX, nothing to mark */
5643 if (pFobx == NULL)
5644 {
5645 return;
5646 }
5647
5648 /* Query time for close */
5649 KeQueryTickCount(&TickCount);
5650
5651 Fcb = (PFCB)pFobx->pSrvOpen->pFcb;
5653
5654 Scavenger = Fcb->RxDeviceObject->pRdbssScavenger;
5656
5657 ScavengerFobx = NULL;
5658 /* If that's not a file, or even not a disk resource, just mark as dormant */
5659 if (NodeType(Fcb) != RDBSS_NTC_STORAGE_TYPE_FILE || Fcb->VNetRoot->pNetRoot->DeviceType != FILE_DEVICE_DISK)
5660 {
5661 SetFlag(pFobx->Flags, FOBX_FLAG_MARKED_AS_DORMANT);
5663 ++Scavenger->NumberOfDormantFiles;
5664 }
5665 else
5666 {
5667 ASSERT(Scavenger->NumberOfDormantFiles >= 0);
5668 /* If we're about to reach the maximum dormant of FOBX */
5669 if (Scavenger->NumberOfDormantFiles >= Scavenger->MaximumNumberOfDormantFiles)
5670 {
5671 /* This should never be wrong... */
5672 if (!IsListEmpty(&Scavenger->ClosePendingFobxsList))
5673 {
5674 /* Then, take the first from the list (oldest) and save it for later purge */
5675 ScavengerFobx = CONTAINING_RECORD(Scavenger->ClosePendingFobxsList.Flink, FOBX, ClosePendingList);
5676 if (ScavengerFobx->pSrvOpen != NULL && ScavengerFobx->pSrvOpen->pFcb == RX_GET_MRX_FCB(Fcb))
5677 {
5678 *NeedPurge = TRUE;
5679 ScavengerFobx = NULL;
5680 }
5681 else
5682 {
5683 RxReferenceNetFobx(ScavengerFobx);
5684 }
5685 }
5686 }
5687
5688 /* Mark ourselves as dormant */
5689 SetFlag(pFobx->Flags, FOBX_FLAG_MARKED_AS_DORMANT);
5690 pFobx->CloseTime.QuadPart = TickCount.QuadPart;
5691
5692 /* And insert us in the list of dormant files */
5694 /* If scavenger was inactive, start it */
5695 if (Scavenger->NumberOfDormantFiles++ == 0 && Scavenger->State == RDBSS_SCAVENGER_INACTIVE)
5696 {
5697 Scavenger->State = RDBSS_SCAVENGER_DORMANT;
5699 Fcb->RxDeviceObject, Scavenger->TimeLimit);
5700 }
5701 }
5702
5704
5705 /* If we had reached max */
5706 if (ScavengerFobx != NULL)
5707 {
5709
5710 /* Purge the oldest FOBX */
5711 Status = RxPurgeFobxFromCache(ScavengerFobx);
5712 if (Status != STATUS_SUCCESS)
5713 {
5714 *NeedPurge = TRUE;
5715 }
5716 }
5717}
5718
5719/*
5720 * @implemented
5721 */
5722VOID
5724 PFOBX Fobx)
5725{
5726 PFCB Fcb;
5727 PRDBSS_SCAVENGER Scavenger;
5728
5729 PAGED_CODE();
5730
5731 /* No FOBX, nothing to mark */
5732 if (Fobx == NULL)
5733 {
5734 return;
5735 }
5736
5737 Fcb = (PFCB)Fobx->pSrvOpen->pFcb;
5739
5740 Scavenger = Fcb->RxDeviceObject->pRdbssScavenger;
5741
5743 /* Only mark it if it was already marked as dormant */
5745 {
5746 /* If FCB wasn't already decrement, do it now */
5747 if (!Fobx->fOpenCountDecremented)
5748 {
5749 Fcb = (PFCB)Fobx->pSrvOpen->pFcb;
5751 InterlockedDecrement((volatile long *)&Fcb->OpenCount);
5752
5754 }
5755
5756 /* We're no longer dormant */
5759 }
5760
5761 /* If we were inserted in the scavenger, drop ourselves out */
5762 if (!IsListEmpty(&Fobx->ClosePendingList))
5763 {
5766 }
5767
5769}
5770
5771/*
5772 * @implemented
5773 */
5774PVOID
5776 PRX_CONTEXT RxContext)
5777{
5778 PIRP Irp;
5779
5780 PAGED_CODE();
5781
5782 Irp = RxContext->CurrentIrp;
5783 if (Irp->MdlAddress != NULL)
5784 {
5786 }
5787
5788 return Irp->UserBuffer;
5789}
5790
5791BOOLEAN
5792NTAPI
5794 IN PVOID Fcb,
5795 IN BOOLEAN Wait)
5796{
5798 return FALSE;
5799}
5800
5801VOID
5802NTAPI
5804 IN PVOID Fcb)
5805{
5807}
5808
5809VOID
5811 PFCB Fcb)
5812{
5814}
5815
5816VOID
5818 IN PV_NET_ROOT ThisVNetRoot)
5819{
5820 PFCB Fcb;
5821 USHORT Bucket;
5822 PNET_ROOT NetRoot;
5823 PRX_FCB_TABLE FcbTable;
5824 PRX_PREFIX_TABLE PrefixTable;
5825
5826 PAGED_CODE();
5827
5828 /* Mailslot won't have any SRV_OPEN (to orphan) */
5829 NetRoot = (PNET_ROOT)ThisVNetRoot->pNetRoot;
5830 if (NetRoot->Type == NET_ROOT_MAILSLOT)
5831 {
5832 return;
5833 }
5834
5835 PrefixTable = NetRoot->pSrvCall->RxDeviceObject->pRxNetNameTable;
5837
5838 FcbTable = &NetRoot->FcbTable;
5840
5841 _SEH2_TRY
5842 {
5843 /* Now, we'll browse all the FCBs attached, and orphan related SRV_OPENs */
5844 for (Bucket = 0; Bucket < FcbTable->NumberOfBuckets; ++Bucket)
5845 {
5846 PLIST_ENTRY BucketList, Entry;
5847
5848 BucketList = &FcbTable->HashBuckets[Bucket];
5849 Entry = BucketList->Flink;
5850 while (Entry != BucketList)
5851 {
5852 Fcb = CONTAINING_RECORD(Entry, FCB, FcbTableEntry.HashLinks);
5853 Entry = Entry->Flink;
5854
5856 RxOrphanSrvOpensForThisFcb(Fcb, ThisVNetRoot, FALSE);
5857 }
5858 }
5859
5860 /* Of course, don't forget about NULL-entry */
5861 if (FcbTable->TableEntryForNull != NULL)
5862 {
5863 Fcb = CONTAINING_RECORD(FcbTable->TableEntryForNull, FCB, FcbTableEntry.HashLinks);
5865 RxOrphanSrvOpensForThisFcb(Fcb, ThisVNetRoot, FALSE);
5866 }
5867 }
5869 {
5870 RxReleaseFcbTableLock(FcbTable);
5871 }
5872 _SEH2_END;
5873}
5874
5875VOID
5877 IN PFCB Fcb,
5878 IN PV_NET_ROOT ThisVNetRoot,
5879 IN BOOLEAN OrphanAll)
5880{
5882}
5883
5884/*
5885 * @implemented
5886 */
5887BOOLEAN
5890 BOOLEAN Wait,
5891 BOOLEAN ProcessBufferingStateChangeRequests)
5892{
5893 PAGED_CODE();
5894
5895 DPRINT("RxpAcquirePrefixTableLockShared(%p, %d, %d) -> %d\n", pTable, Wait, ProcessBufferingStateChangeRequests,
5896 pTable->TableLock.ActiveEntries);
5897
5898 return ExAcquireResourceSharedLite(&pTable->TableLock, Wait);
5899}
5900
5901/*
5902 * @implemented
5903 */
5904BOOLEAN
5907 BOOLEAN Wait,
5908 BOOLEAN ProcessBufferingStateChangeRequests)
5909{
5910 PAGED_CODE();
5911
5912 DPRINT("RxpAcquirePrefixTableLockExclusive(%p, %d, %d) -> %d\n", pTable, Wait, ProcessBufferingStateChangeRequests,
5913 pTable->TableLock.ActiveEntries);
5914
5915 return ExAcquireResourceExclusiveLite(&pTable->TableLock, Wait);
5916}
5917
5918/*
5919 * @implemented
5920 */
5921BOOLEAN
5923 OUT PFCB ThisFcb,
5924 IN PRX_CONTEXT RxContext,
5925 IN BOOLEAN RecursiveFinalize,
5926 IN BOOLEAN ForceFinalize)
5927{
5929 ULONG References;
5930 PNET_ROOT NetRoot;
5931 BOOLEAN ResourceAcquired, NetRootReferenced, Freed;
5932
5933 PAGED_CODE();
5934
5935 ASSERT(!ForceFinalize);
5936 ASSERT(NodeTypeIsFcb(ThisFcb));
5938
5939 /* Unless we're recursively finalizing, or forcing, if FCB is still in use, quit */
5940 References = InterlockedDecrement((volatile long *)&ThisFcb->NodeReferenceCount);
5941 if (!ForceFinalize && !RecursiveFinalize && (ThisFcb->OpenCount != 0 || ThisFcb->UncleanCount != 0 || References > 1))
5942 {
5943 return FALSE;
5944 }
5945
5946 Freed = FALSE;
5948 NetRoot = (PNET_ROOT)ThisFcb->VNetRoot->pNetRoot;
5949 ResourceAcquired = FALSE;
5950 NetRootReferenced = FALSE;
5951 /* If FCB isn't orphaned, it still have context attached */
5952 if (!BooleanFlagOn(ThisFcb->FcbState, FCB_STATE_ORPHANED))
5953 {
5954 /* Don't let NetRoot go away before we're done */
5955 RxReferenceNetRoot(NetRoot);
5956 NetRootReferenced = TRUE;
5957
5958 /* Try to acquire the table lock exclusively */
5959 if (!RxIsFcbTableLockExclusive(&NetRoot->FcbTable))
5960 {
5961 RxReferenceNetFcb(ThisFcb);
5962
5964 {
5965 if (RxContext != NULL && RxContext != CHANGE_BUFFERING_STATE_CONTEXT &&
5967 {
5968 RxContext->Flags |= RX_CONTEXT_FLAG_BYPASS_VALIDOP_CHECK;
5969 }
5970
5971 RxReleaseFcb(RxContext, ThisFcb);
5972
5974
5975 Status = RxAcquireExclusiveFcb(RxContext, ThisFcb);
5976 }
5977
5978 References = RxDereferenceNetFcb(ThisFcb);
5979
5980 ResourceAcquired = TRUE;
5981 }
5982 }
5983
5984 /* If locking was OK (or not needed!), attempt finalization */
5985 if (Status == STATUS_SUCCESS)
5986 {
5987 Freed = RxFinalizeNetFcb(ThisFcb, RecursiveFinalize, ForceFinalize, References);
5988 }
5989
5990 /* Release table lock if acquired */
5991 if (ResourceAcquired)
5992 {
5994 }
5995
5996 /* We don't need the NetRoot anylonger */
5997 if (NetRootReferenced)
5998 {
6000 }
6001
6002 return Freed;
6003}
6004
6005/*
6006 * @implemented
6007 */
6008LONG
6010 PFCB Fcb)
6011{
6012 LONG NewCount;
6013
6014 PAGED_CODE();
6015
6017
6018 NewCount = InterlockedDecrement((volatile long *)&Fcb->NodeReferenceCount);
6019 ASSERT(NewCount >= 0);
6020
6021 PRINT_REF_COUNT(NETFCB, NewCount);
6022
6023 return NewCount;
6024}
6025
6026/*
6027 * @implemented
6028 */
6029VOID
6030NTAPI
6033{
6035 PSRV_CALL SrvCall;
6036 BOOLEAN ForceFinalize;
6037 PRX_PREFIX_TABLE PrefixTable;
6038
6039 SrvCall = (PSRV_CALL)Context;
6040 /* At this step, RxFinalizeSrvCall already cleaned some fields */
6041 ASSERT(SrvCall->UpperFinalizationDone);
6042
6043 PrefixTable = SrvCall->RxDeviceObject->pRxNetNameTable;
6044 /* Were we called with ForceFinalize? */
6045 ForceFinalize = BooleanFlagOn(SrvCall->Flags, SRVCALL_FLAG_FORCE_FINALIZED);
6046
6047 /* Notify mini-rdr */
6048 MINIRDR_CALL_THROUGH(Status, SrvCall->RxDeviceObject->Dispatch,
6049 MRxFinalizeSrvCall, ((PMRX_SRV_CALL)SrvCall,
6050 ForceFinalize));
6051 (void)Status;
6052
6053 /* Dereference our extra reference (set before queueing) */
6055 InterlockedDecrement((volatile long *)&SrvCall->NodeReferenceCount);
6056 /* And finalize for real, with the right context */
6057 RxFinalizeSrvCall(SrvCall, FALSE, ForceFinalize);
6058 RxReleasePrefixTableLock(PrefixTable);
6059}
6060
6061/*
6062 * @implemented
6063 */
6064VOID
6066 _Inout_ PLIST_ENTRY DiscardedRequests)
6067{
6069
6070 PAGED_CODE();
6071
6072 /* No requests to discard */
6073 if (IsListEmpty(DiscardedRequests))
6074 {
6075 return;
6076 }
6077
6078 /* Free all the discarded requests */
6079 Entry = DiscardedRequests->Flink;
6080 while (Entry != DiscardedRequests)
6081 {
6083
6085 Entry = Entry->Flink;
6086
6087 DPRINT("Req %p for %p (%p) discarded\n", Request, Request->SrvOpenKey, Request->SrvOpen);
6088
6091 }
6092}
6093
6094/*
6095 * @implemented
6096 */
6097VOID
6099 PSRV_CALL SrvCall,
6100 PSRV_OPEN SrvOpen,
6101 PLIST_ENTRY DiscardedRequests)
6102{
6103 KIRQL OldIrql;
6105 BOOLEAN StartDispatcher;
6106 LIST_ENTRY AcceptedReqs;
6107 LIST_ENTRY DispatcherList;
6108 PRX_BUFFERING_MANAGER BufferingManager;
6109
6110 /* Initialize our lists */
6111 InitializeListHead(&AcceptedReqs);
6112 InitializeListHead(DiscardedRequests);
6113
6114 /* Transfer the requests to dispatch locally */
6115 BufferingManager = &SrvCall->BufferingManager;
6116 KeAcquireSpinLock(&BufferingManager->SpinLock, &OldIrql);
6117 RxTransferList(&DispatcherList, &BufferingManager->DispatcherList);
6118 KeReleaseSpinLock(&BufferingManager->SpinLock, OldIrql);
6119
6120 /* If there were requests */
6121 if (!IsListEmpty(&DispatcherList))
6122 {
6124
6125 /* For each of the entries... */
6126 Entry = DispatcherList.Flink;
6127 while (Entry != &DispatcherList)
6128 {
6130
6132 Entry = Entry->Flink;
6133
6134 /* If we have been provided a SRV_OPEN, see whether it matches */
6135 if (SrvOpen != NULL)
6136 {
6137 /* Match, the request is accepted */
6138 if (Request->SrvOpenKey == SrvOpen->Key)
6139 {
6140 Request->SrvOpen = SrvOpen;
6141 RxReferenceSrvOpen(SrvOpen);
6142
6143 RemoveEntryList(&Request->ListEntry);
6144 InsertTailList(&AcceptedReqs, &Request->ListEntry);
6145
6146 /* Move to the next entry */
6147 continue;
6148 }
6149 else
6150 {
6152 }
6153 }
6154 else
6155 {
6156 /* No SRV_OPEN provided, try to find one */
6158 }
6159
6160 /* We found a matching SRV_OPEN, accept the request */
6161 if (Status == STATUS_SUCCESS)
6162 {
6163 RemoveEntryList(&Request->ListEntry);
6164 InsertTailList(&AcceptedReqs, &Request->ListEntry);
6165 }
6166 /* Another run might help handling it, don't discard it */
6167 else if (Status == STATUS_PENDING)
6168 {
6169 continue;
6170 }
6171 /* Otherwise, discard the request */
6172 else
6173 {
6175
6176 RemoveEntryList(&Request->ListEntry);
6177 InsertTailList(DiscardedRequests, &Request->ListEntry);
6178 }
6179 }
6180 }
6181
6182 KeAcquireSpinLock(&BufferingManager->SpinLock, &OldIrql);
6183 /* Nothing to dispatch, no need to start dispatcher */
6184 if (IsListEmpty(&DispatcherList))
6185 {
6186 StartDispatcher = FALSE;
6187 }
6188 else
6189 {
6190 /* Transfer back the list of the not treated entries to the buffering manager */
6191 RxTransferList(&BufferingManager->DispatcherList, &DispatcherList);
6192 StartDispatcher = (BufferingManager->DispatcherActive == FALSE);
6193 /* If the dispatcher isn't active, start it */
6194 if (StartDispatcher)
6195 {
6196 BufferingManager->DispatcherActive = TRUE;
6197 }
6198 }
6199
6200 /* If there were accepted requests, move them to the buffering manager */
6201 if (!IsListEmpty(&AcceptedReqs))
6202 {
6203 RxTransferList(&BufferingManager->HandlerList, &AcceptedReqs);
6204 }
6205 KeReleaseSpinLock(&BufferingManager->SpinLock, OldIrql);
6206
6207 /* If we're to start the dispatcher, do it */
6208 if (StartDispatcher)
6209 {
6210 RxReferenceSrvCall(SrvCall);
6211 DPRINT("Starting dispatcher\n");
6213 &BufferingManager->DispatcherWorkItem,
6215 }
6216}
6217
6218/*
6219 * @implemented
6220 */
6223 IN PSRV_CALL SrvCall,
6225{
6228 PSRV_OPEN SrvOpen;
6229
6230 PAGED_CODE();
6231
6233 /* Browse all our associated SRV_OPENs to find the one! */
6234 for (Entry = SrvCall->BufferingManager.SrvOpenLists[0].Flink;
6235 Entry != &SrvCall->BufferingManager.SrvOpenLists[0];
6236 Entry = Entry->Flink)
6237 {
6238 /* Same key, not orphaned, this is ours */
6239 SrvOpen = CONTAINING_RECORD(Entry, SRV_OPEN, SrvOpenKeyList);
6240 if (SrvOpen->Key == Request->SrvOpenKey)
6241 {
6242 if (!BooleanFlagOn(SrvOpen->pFcb->FcbState, FCB_STATE_ORPHANED))
6243 {
6244 RxReferenceSrvOpen(SrvOpen);
6245 break;
6246 }
6247 }
6248 }
6249
6250 /* We didn't manage to find a SRV_OPEN */
6251 if (Entry == &SrvCall->BufferingManager.SrvOpenLists[0])
6252 {
6253 SrvOpen = NULL;
6254
6255 /* The coming open might help, mark as pending for later retry */
6256 if (SrvCall->BufferingManager.NumberOfOutstandingOpens != 0)
6257 {
6259 }
6260 /* Else, it's a complete failure */
6261 else
6262 {
6264 }
6265 }
6266
6267 /* Return the (not) found SRV_OPEN */
6268 Request->SrvOpen = SrvOpen;
6269
6270 return Status;
6271}
6272
6273/*
6274 * @implemented
6275 */
6276VOID
6279{
6282 PRDBSS_SCAVENGER Scavenger;
6284 PLIST_ENTRY ScavengerHead, InstEntry;
6285
6286 PAGED_CODE();
6287
6288 /* If still referenced, don't mark it (broken caller) */
6290 if (Node->NodeReferenceCount > 1)
6291 {
6292 return;
6293 }
6294
6296 Scavenger = DeviceObject->pRdbssScavenger;
6297
6298 /* Mark the node */
6301 DPRINT("Node %p has now the scavenger mark!\n", Instance);
6302
6303 /* Increase the count in the scavenger, and queue it */
6304 ScavengerHead = NULL;
6305 switch (NodeType)
6306 {
6307 case RDBSS_NTC_FOBX:
6308 ++Scavenger->FobxsToBeFinalized;
6309 ScavengerHead = &Scavenger->FobxFinalizationList;
6310 InstEntry = &((PFOBX)Instance)->ScavengerFinalizationList;
6311 break;
6312
6313 case RDBSS_NTC_SRVCALL:
6314 ++Scavenger->SrvCallsToBeFinalized;
6315 ScavengerHead = &Scavenger->SrvCallFinalizationList;
6316 InstEntry = &((PSRV_CALL)Instance)->ScavengerFinalizationList;
6317 break;
6318
6319 case RDBSS_NTC_NETROOT:
6320 ++Scavenger->NetRootsToBeFinalized;
6321 ScavengerHead = &Scavenger->NetRootFinalizationList;
6322 InstEntry = &((PNET_ROOT)Instance)->ScavengerFinalizationList;
6323 break;
6324
6326 ++Scavenger->VNetRootsToBeFinalized;
6327 ScavengerHead = &Scavenger->VNetRootFinalizationList;
6328 InstEntry = &((PV_NET_ROOT)Instance)->ScavengerFinalizationList;
6329 break;
6330
6331 case RDBSS_NTC_SRVOPEN:
6332 ++Scavenger->SrvOpensToBeFinalized;
6333 ScavengerHead = &Scavenger->SrvOpenFinalizationList;
6334 InstEntry = &((PSRV_OPEN)Instance)->ScavengerFinalizationList;
6335 break;
6336 }
6337
6338 /* Extra ref for scavenger */
6339 InterlockedIncrement((volatile long *)&Node->NodeReferenceCount);
6340
6341 /* If matching type */
6342 if (ScavengerHead != NULL)
6343 {
6344 /* Insert in the scavenger list */
6345 InsertTailList(ScavengerHead, InstEntry);
6346
6347 /* And if it wasn't started, start it */
6348 if (Scavenger->State == RDBSS_SCAVENGER_INACTIVE)
6349 {
6350 Scavenger->State = RDBSS_SCAVENGER_DORMANT;
6353 }
6354 }
6355}
6356
6357/*
6358 * @implemented
6359 */
6361NTAPI
6364 IN PRX_WORK_ITEM pWorkItem,
6366 IN PVOID pContext,
6367 IN LARGE_INTEGER TimeInterval)
6368{
6369 KIRQL OldIrql;
6370
6371 ASSERT(pWorkItem != NULL);
6372
6373 /* Prepare the work item */
6374 ExInitializeWorkItem(&pWorkItem->WorkQueueItem, Routine, pContext);
6375 pWorkItem->WorkQueueItem.pDeviceObject = pDeviceObject;
6376
6377 /* Last tick can be computed with the number of times it was caller (timertickcount)
6378 * and the interval between calls
6379 */
6381 pWorkItem->LastTick = (TimeInterval.QuadPart / 550000) + RxTimerTickCount + 1;
6382 /* Insert in work queue */
6383 InsertTailList(&RxTimerQueueHead, &pWorkItem->WorkQueueItem.List);
6385
6386 /* If there are queued events, queue an execution */
6388 {
6390 }
6391
6392 return STATUS_SUCCESS;
6393}
6394
6395/*
6396 * @implemented
6397 */
6399NTAPI
6401 _In_ PRDBSS_DEVICE_OBJECT pMRxDeviceObject,
6402 _In_ WORK_QUEUE_TYPE WorkQueueType,
6403 _In_ PRX_WORK_QUEUE_ITEM pWorkQueueItem,
6405 _In_ PVOID pContext)
6406{
6407 /* Initialize work queue item */
6408 pWorkQueueItem->List.Flink = NULL;
6409 pWorkQueueItem->WorkerRoutine = Routine;
6410 pWorkQueueItem->Parameter = pContext;
6411
6412 /* And insert it in the work queue */
6413 return RxInsertWorkQueueItem(pMRxDeviceObject, WorkQueueType, pWorkQueueItem);
6414}
6415
6416VOID
6418 PSRV_CALL SrvCall,
6419 BOOLEAN UpdateHandlerState)
6420{
6422}
6423
6424/*
6425 * @implemented
6426 */
6429 IN OUT PRX_PREFIX_TABLE ThisTable,
6430 IN OUT PRX_PREFIX_ENTRY ThisEntry,
6431 IN PVOID Container,
6432 IN PULONG ContainerRefCount,
6433 IN USHORT CaseInsensitiveLength,
6434 IN PRX_CONNECTION_ID ConnectionId
6435 )
6436{
6437 PAGED_CODE();
6438
6439 DPRINT("Insert: %wZ\n", &ThisEntry->Prefix);
6440
6442 ASSERT(CaseInsensitiveLength <= ThisEntry->Prefix.Length);
6443
6444 /* Copy parameters and compute hash */
6445 ThisEntry->CaseInsensitiveLength = CaseInsensitiveLength;
6446 ThisEntry->ContainingRecord = Container;
6447 ThisEntry->ContainerRefCount = ContainerRefCount;
6448 InterlockedIncrement((volatile long *)ContainerRefCount);
6449 ThisEntry->SavedHashValue = RxTableComputeHashValue(&ThisEntry->Prefix);
6450 DPRINT("Associated hash: %x\n", ThisEntry->SavedHashValue);
6451
6452 /* If no path length: this is entry for null path */
6453 if (ThisEntry->Prefix.Length == 0)
6454 {
6455 ThisTable->TableEntryForNull = ThisEntry;
6456 }
6457 /* Otherwise, insert in the appropriate bucket */
6458 else
6459 {
6460 InsertTailList(HASH_BUCKET(ThisTable, ThisEntry->SavedHashValue), &ThisEntry->HashLinks);
6461 }
6462
6463 /* If we had a connection ID, keep track of it */
6464 if (ConnectionId != NULL)
6465 {
6466 ThisEntry->ConnectionId.Luid = ConnectionId->Luid;
6467 }
6468 else
6469 {
6470 ThisEntry->ConnectionId.Luid.LowPart = 0;
6471 ThisEntry->ConnectionId.Luid.HighPart = 0;
6472 }
6473
6474 InsertTailList(&ThisTable->MemberQueue, &ThisEntry->MemberQLinks);
6475 /* Reflect the changes */
6476 ++ThisTable->Version;
6477
6478 DPRINT("Inserted in bucket: %p\n", HASH_BUCKET(ThisTable, ThisEntry->SavedHashValue));
6479
6480 return ThisEntry;
6481}
6482
6483/*
6484 * @implemented
6485 */
6486PVOID
6488 IN PRX_PREFIX_TABLE ThisTable,
6489 IN PUNICODE_STRING CanonicalName,
6491 IN PRX_CONNECTION_ID ConnectionId)
6492{
6493 PVOID Container;
6494
6495 PAGED_CODE();
6496
6498 ASSERT(CanonicalName->Length > 0);
6499
6500 /* Call the internal helper */
6501 Container = RxTableLookupName(ThisTable, CanonicalName, RemainingName, ConnectionId);
6502 if (Container == NULL)
6503 {
6504 return NULL;
6505 }
6506
6507 /* Reference our container before returning it */
6509 {
6511
6512 Type = (NodeType(Container) & ~RX_SCAVENGER_MASK);
6513 switch (Type)
6514 {
6515 case RDBSS_NTC_SRVCALL:
6516 RxReferenceSrvCall(Container);
6517 break;
6518
6519 case RDBSS_NTC_NETROOT:
6520 RxReferenceNetRoot(Container);
6521 break;
6522
6524 RxReferenceVNetRoot(Container);
6525 break;
6526
6527 default:
6528 DPRINT1("Invalid node type: %x\n", Type);
6529 ASSERT(FALSE);
6530 RxReference(Container);
6531 break;
6532 }
6533 }
6534 else
6535 {
6536 RxReference(Container);
6537 }
6538
6539 return Container;
6540}
6541
6542/*
6543 * @implemented
6544 */
6545LONG
6547 PFCB Fcb)
6548{
6549 LONG NewCount;
6550
6551 PAGED_CODE();
6552
6554
6555 NewCount = InterlockedIncrement((volatile long *)&Fcb->NodeReferenceCount);
6556
6557 PRINT_REF_COUNT(NETFCB, Fcb->NodeReferenceCount);
6558
6559 return NewCount;
6560}
6561
6562/*
6563 * @implemented
6564 */
6565VOID
6568 BOOLEAN ProcessBufferingStateChangeRequests)
6569{
6570 PAGED_CODE();
6571
6572 DPRINT("RxpReleasePrefixTableLock(%p, %d) -> %d\n", pTable, ProcessBufferingStateChangeRequests,
6573 pTable->TableLock.ActiveEntries);
6574
6575 ExReleaseResourceLite(&pTable->TableLock);
6576}
6577
6578/*
6579 * @implemented
6580 */
6581VOID
6582NTAPI
6584 IN OUT PRX_CONTEXT RxContext)
6585{
6586 PAGED_CODE();
6587
6588 /* When we reach that point, make sure mandatory parts are null-ed */
6589 if (RxContext->MajorFunction == IRP_MJ_CREATE)
6590 {
6591 ASSERT(RxContext->Create.CanonicalNameBuffer == NULL);
6592 RxContext->Create.RdrFlags = 0;
6593 }
6594 else if (RxContext->MajorFunction == IRP_MJ_READ || RxContext->MajorFunction == IRP_MJ_WRITE)
6595 {
6596 ASSERT(RxContext->RxContextSerializationQLinks.Flink == NULL);
6597 ASSERT(RxContext->RxContextSerializationQLinks.Blink == NULL);
6598 }
6599
6600 RxContext->ReferenceCount = 0;
6601}
6602
6603/*
6604 * @implemented
6605 */
6606VOID
6609{
6610 PSRV_OPEN SrvOpen;
6611
6612 PAGED_CODE();
6613
6614 SrvOpen = Request->SrvOpen;
6615
6616 /* If the request was already prepared for service */
6618 {
6619 /* We have to dereference the associated SRV_OPEN depending on the lock */
6620 if (RxIsFcbAcquiredExclusive(SrvOpen->pFcb))
6621 {
6623 }
6624 else
6625 {
6627 }
6628 }
6629 /* Otherwise, just dereference */
6630 else if (SrvOpen != NULL)
6631 {
6633 }
6634
6635 Request->SrvOpen = NULL;
6636}
6637
6638/*
6639 * @implemented
6640 */
6641VOID
6642NTAPI
6644 _In_ PVOID SrvCall)
6645{
6646 /* Call internal routine */
6649}
6650
6651/*
6652 * @implemented
6653 */
6654VOID
6656 PSRV_OPEN SrvOpen)
6657{
6658 LONG NumberOfBufferingChangeRequests, LockedOldBufferingToken, OldBufferingToken;
6659
6660 /* Get the current number of change requests */
6661 NumberOfBufferingChangeRequests = ((PSRV_CALL)SrvOpen->pVNetRoot->pNetRoot->pSrvCall)->BufferingManager.CumulativeNumberOfBufferingChangeRequests;
6662 /* Get our old token */
6663 OldBufferingToken = SrvOpen->BufferingToken;
6664 LockedOldBufferingToken = InterlockedCompareExchange(&SrvOpen->BufferingToken,
6665 NumberOfBufferingChangeRequests,
6666 NumberOfBufferingChangeRequests);
6667 /* If buffering state changed in between, process changes */
6668 if (OldBufferingToken != LockedOldBufferingToken)
6669 {
6670 PFCB Fcb;
6672
6673 /* Acquire the FCB and start processing */
6674 Fcb = (PFCB)SrvOpen->pFcb;
6676 if (Status == STATUS_SUCCESS)
6677 {
6680 }
6681 }
6682}
6683
6684VOID
6686 PFCB Fcb)
6687{
6689}
6690
6691/*
6692 * @implemented
6693 */
6694VOID
6696 PRDBSS_SCAVENGER Scavenger,
6697 PLIST_ENTRY FobxToScavenge)
6698{
6699 /* Explore the whole list of FOBX to scavenge */
6700 while (!IsListEmpty(FobxToScavenge))
6701 {
6702 PFCB Fcb;
6703 PFOBX Fobx;
6705
6706 Entry = RemoveHeadList(FobxToScavenge);
6707 Fobx = CONTAINING_RECORD(Entry, FOBX, ScavengerFinalizationList);
6708 Fcb = (PFCB)Fobx->SrvOpen->pFcb;
6709
6710 /* Try to acquire the lock exclusively to perform finalization */
6712 {
6714 }
6715 else
6716 {
6719
6721 {
6723 }
6724 }
6725 }
6726}
6727
6728BOOLEAN
6730 _In_ ULONG TraceType,
6732 _In_ ULONG Line,
6734{
6735 PCSTR InstanceType;
6736 ULONG ReferenceCount;
6737
6738 PAGED_CODE();
6739
6741 {
6742 return TRUE;
6743 }
6744
6745 switch (TraceType)
6746 {
6748 InstanceType = "SrvCall";
6749 ReferenceCount = ((PSRV_CALL)Instance)->NodeReferenceCount;
6750 break;
6751
6753 InstanceType = "NetRoot";
6754 ReferenceCount = ((PNET_ROOT)Instance)->NodeReferenceCount;
6755 break;
6756
6758 InstanceType = "VNetRoot";
6759 ReferenceCount = ((PV_NET_ROOT)Instance)->NodeReferenceCount;
6760 break;
6761
6763 InstanceType = "NetFobx";
6764 ReferenceCount = ((PFOBX)Instance)->NodeReferenceCount;
6765 break;
6766
6768 InstanceType = "NetFcb";
6769 ReferenceCount = ((PFCB)Instance)->NodeReferenceCount;
6770 break;
6771
6773 InstanceType = "SrvOpen";
6774 ReferenceCount = ((PSRV_OPEN)Instance)->NodeReferenceCount;
6775 break;
6776
6777 default:
6778 DPRINT1("Invalid node type!\n");
6779 return TRUE;
6780 }
6781
6783 {
6785 }
6786
6788 {
6789 DbgPrint("(%s:%d) %p (%s) dereferenced from %d\n", FileName, Line, Instance, InstanceType, ReferenceCount);
6790 }
6791
6792 return TRUE;
6793}
6794
6795VOID
6797 _In_ ULONG TraceType,
6799 _In_ ULONG Line,
6801{
6802 PCSTR InstanceType;
6803 ULONG ReferenceCount;
6804
6806 {
6807 return;
6808 }
6809
6810 switch (TraceType)
6811 {
6813 InstanceType = "SrvCall";
6814 ReferenceCount = ((PSRV_CALL)Instance)->NodeReferenceCount;
6815 break;
6816
6818 InstanceType = "NetRoot";
6819 ReferenceCount = ((PNET_ROOT)Instance)->NodeReferenceCount;
6820 break;
6821
6823 InstanceType = "VNetRoot";
6824 ReferenceCount = ((PV_NET_ROOT)Instance)->NodeReferenceCount;
6825 break;
6826
6828 InstanceType = "NetFobx";
6829 ReferenceCount = ((PFOBX)Instance)->NodeReferenceCount;
6830 break;
6831
6833 InstanceType = "NetFcb";
6834 ReferenceCount = ((PFCB)Instance)->NodeReferenceCount;
6835 break;
6836
6838 InstanceType = "SrvOpen";
6839 ReferenceCount = ((PSRV_OPEN)Instance)->NodeReferenceCount;
6840 break;
6841
6842 default:
6843 DPRINT1("Invalid node type!\n");
6844 return;
6845 }
6846
6848 {
6850 }
6851
6853 {
6854 DbgPrint("(%s:%d) %p (%s) referenced from %d\n", FileName, Line, Instance, InstanceType, ReferenceCount);
6855 }
6856}
6857
6858/*
6859 * @implemented
6860 */
6861VOID
6864{
6865 PLIST_ENTRY ListEntry;
6867 PRDBSS_SCAVENGER Scavenger;
6868
6869 PAGED_CODE();
6870
6872 /* There's no marking - nothing to do */
6874 {
6875 return;
6876 }
6877
6878 /* First of all, remove the mark */
6880 DPRINT("Node %p no longer has the scavenger mark\n");
6881
6882 /* And now, remove from the scavenger */
6884 switch (NodeType(Node))
6885 {
6886 case RDBSS_NTC_FOBX:
6887 --Scavenger->FobxsToBeFinalized;
6888 ListEntry = &((PFOBX)Instance)->ScavengerFinalizationList;
6889 break;
6890
6891 case RDBSS_NTC_SRVCALL:
6892 --Scavenger->SrvCallsToBeFinalized;
6893 ListEntry = &((PSRV_CALL)Instance)->ScavengerFinalizationList;
6894 break;
6895
6896 case RDBSS_NTC_NETROOT:
6897 --Scavenger->NetRootsToBeFinalized;
6898 ListEntry = &((PNET_ROOT)Instance)->ScavengerFinalizationList;
6899 break;
6900
6902 --Scavenger->VNetRootsToBeFinalized;
6903 ListEntry = &((PV_NET_ROOT)Instance)->ScavengerFinalizationList;
6904 break;
6905
6906 case RDBSS_NTC_SRVOPEN:
6907 --Scavenger->SrvOpensToBeFinalized;
6908 ListEntry = &((PSRV_OPEN)Instance)->ScavengerFinalizationList;
6909 break;
6910
6911 default:
6912 return;
6913 }
6914
6915 /* Also, remove the extra ref from the scavenger */
6916 RemoveEntryList(ListEntry);
6917 InterlockedDecrement((volatile long *)&Node->NodeReferenceCount);
6918}
6919
6920/*
6921 * @implemented
6922 */
6923VOID
6925 PSRV_OPEN SrvOpen)
6926{
6927 PSRV_CALL SrvCall;
6928 LIST_ENTRY Discarded;
6929
6930 PAGED_CODE();
6931
6933
6934 /* Initialize our discarded list */
6935 InitializeListHead(&Discarded);
6936
6937 SrvCall = (PSRV_CALL)SrvOpen->Fcb->VNetRoot->pNetRoot->pSrvCall;
6939
6940 /* Set the flag, and get the requests */
6943 RxGatherRequestsForSrvOpen(SrvCall, SrvOpen, &Discarded);
6944
6946
6947 /* If there were discarded requests */
6948 if (!IsListEmpty(&Discarded))
6949 {
6950 /* And a pending buffering state change */
6952 {
6953 /* Clear the flag, and set the associated event - job done */
6957 {
6959 }
6961 }
6962
6963 /* Drop the discarded requests */
6965 }
6966}
6967
6968/*
6969 * @implemented
6970 */
6971VOID
6973 IN PFCB Fcb)
6974{
6975 PAGED_CODE();
6976
6978
6979 /* Reference our FCB so that it doesn't disappear */
6981 /* Purge Cc if required */
6982 if (Fcb->OpenCount != 0)
6983 {
6985 }
6986
6987 /* If it wasn't freed, release the lock */
6989 {
6991 }
6992}
6993
6994/*
6995 * @implemented
6996 */
6999 IN PFCB Fcb,
7001 IN ULONG Length,
7002 IN BOOLEAN UninitializeCacheMaps,
7003 IN BOOLEAN FlushFile)
7004{
7005 BOOLEAN Purged;
7007
7008 PAGED_CODE();
7009
7011
7012 /* Try to flush first, if asked */
7013 if (FlushFile)
7014 {
7015 /* If flushing failed, just make some noise */
7017 if (!NT_SUCCESS(Status))
7018 {
7019 PVOID CallersAddress, CallersCaller;
7020
7021 RtlGetCallersAddress(&CallersAddress, &CallersCaller);
7022 DPRINT1("Flush failed with status %lx for FCB %p\n", Status, Fcb);
7023 DPRINT1("Caller was %p %p\n", CallersAddress, CallersCaller);
7024 }
7025 }
7026
7027 /* Deal with Cc for purge */
7029 Length, UninitializeCacheMaps);
7030 /* If purge failed, force section closing */
7031 if (!Purged)
7032 {
7034
7038 }
7039
7040 /* Return appropriate status */
7042 DPRINT("Purge for FCB %p returns %lx\n", Fcb, Status);
7043
7044 return Status;
7045}
7046
7047/*
7048 * @implemented
7049 */
7050BOOLEAN
7052 PFOBX pFobx)
7053{
7055 PFCB FcbToBePurged;
7056
7057 PAGED_CODE();
7058
7059 /* Get the associated FCB */
7060 FcbToBePurged = (PFCB)pFobx->pSrvOpen->pFcb;
7061 Status = RxAcquireExclusiveFcb(NULL, FcbToBePurged);
7063
7064 /* Purge it */
7065 Status = RxPurgeFcbInSystemCache(FcbToBePurged, NULL, 0, FALSE, TRUE);
7066 if (Status != STATUS_SUCCESS)
7067 {
7068 DPRINT1("Purge failed for %p (%p)\n", FcbToBePurged, pFobx);
7069 return FALSE;
7070 }
7071
7072 /* And flush */
7073 if (!MmFlushImageSection(&FcbToBePurged->NonPaged->SectionObjectPointers, MmFlushForWrite))
7074 {
7075 DPRINT1("Image section flush failed for %p (%p)\n", FcbToBePurged, pFobx);
7076 return FALSE;
7077 }
7078
7079 DPRINT("Purge OK for %p (%p)\n", FcbToBePurged, pFobx);
7080 return TRUE;
7081}
7082
7083/*
7084 * @implemented
7085 */
7088 PFOBX FobxToBePurged)
7089{
7091 PFCB FcbToBePurged;
7092
7093 PAGED_CODE();
7094
7095 FcbToBePurged = (PFCB)FobxToBePurged->pSrvOpen->pFcb;
7096 ASSERT(FcbToBePurged != NULL);
7097
7098 /* If we cannot have our FCB exclusively, give up */
7099 Status = RxAcquireExclusiveFcb(NULL, FcbToBePurged);
7100 if (Status != STATUS_SUCCESS)
7101 {
7102 RxDereferenceNetFobx(FobxToBePurged, LHS_LockNotHeld);
7103 return Status;
7104 }
7105
7106 /* Don't let the FCB disappear */
7107 RxReferenceNetFcb(FcbToBePurged);
7108
7109 /* If the SRV_OPEN was already closed, or if there are unclean FOBX, give up */
7110 if (BooleanFlagOn(FobxToBePurged->Flags, FOBX_FLAG_SRVOPEN_CLOSED) || FobxToBePurged->pSrvOpen->UncleanFobxCount != 0)
7111 {
7112 DPRINT("FCB purge skipped\n");
7113 }
7114 else
7115 {
7116 Status = RxPurgeFcbInSystemCache(FcbToBePurged, NULL, 0, FALSE, TRUE);
7117 }
7118
7120 /* Drop our extra reference */
7121 if (!RxDereferenceAndFinalizeNetFcb(FcbToBePurged, NULL, FALSE, FALSE))
7122 {
7123 RxReleaseFcb(NULL, FcbToBePurged);
7124 }
7125
7126 return Status;
7127}
7128
7129/*
7130 * @implemented
7131 */
7134 PNET_ROOT NetRoot,
7135 PRX_CONTEXT RxContext,
7136 BOOLEAN AttemptFinalization,
7137 PFCB PurgingFcb)
7138{
7140 ULONG SuccessfullPurge;
7141 PRDBSS_SCAVENGER Scavenger;
7142 PRDBSS_DEVICE_OBJECT RxDeviceObject;
7143 PPURGE_SYNCHRONIZATION_CONTEXT PurgeSyncCtx;
7144
7145 PAGED_CODE();
7146
7147 RxDeviceObject = RxContext->RxDeviceObject;
7148 Scavenger = RxDeviceObject->pRdbssScavenger;
7149 PurgeSyncCtx = &NetRoot->PurgeSyncronizationContext;
7150
7152
7153 /* If there's already a purge in progress */
7154 if (PurgeSyncCtx->PurgeInProgress)
7155 {
7156 /* Add our RX_CONTEXT to the current run */
7158 &RxContext->RxContextSerializationQLinks);
7159
7160 /* And wait until it's done */
7162 RxWaitSync(RxContext);
7164 }
7165
7166 /* Start the purge */
7167 PurgeSyncCtx->PurgeInProgress = TRUE;
7168
7169 /* While the purge is still handling our NET_ROOT, do nothing but wait */
7170 while (Scavenger->CurrentNetRootForClosePendingProcessing == NetRoot)
7171 {
7174 KernelMode, TRUE, NULL);
7176 }
7177
7178 /* Now, for all the entries */
7179 SuccessfullPurge = 0;
7180 Entry = Scavenger->ClosePendingFobxsList.Flink;
7181 while (Entry != &Scavenger->ClosePendingFobxsList)
7182 {
7183 PFCB Fcb;
7184 PFOBX Fobx;
7186
7187 Fobx = CONTAINING_RECORD(Entry, FOBX, ClosePendingList);
7188 DPRINT("Dealing with FOBX: %p\n", Fobx);
7189
7190 Entry = Entry->Flink;
7191
7192 /* If it's not matching our NET_ROOT, ignore */
7193 if (Fobx->pSrvOpen == NULL ||
7194 Fobx->pSrvOpen->pFcb == NULL ||
7195 ((PFCB)Fobx->pSrvOpen->pFcb)->VNetRoot == NULL ||
7196 (PNET_ROOT)((PFCB)Fobx->pSrvOpen->pFcb)->VNetRoot->pNetRoot != NetRoot)
7197 {
7198 continue;
7199 }
7200
7201 /* Determine if it matches our FCB */
7202 Fcb = (PFCB)Fobx->pSrvOpen->pFcb;
7203 if (PurgingFcb != NULL && NodeType(PurgingFcb) != RDBSS_NTC_STORAGE_TYPE_DIRECTORY &&
7204 PurgingFcb != Fcb)
7205 {
7207
7208 MINIRDR_CALL_THROUGH(Status, RxDeviceObject->Dispatch, MRxAreFilesAliased, (Fcb, PurgingFcb));
7209 if (Status == STATUS_SUCCESS)
7210 {
7211 continue;
7212 }
7213 }
7214
7215 /* Matching, we'll purge it */
7217
7218 /* Reference it so that it doesn't disappear */
7219 RxReferenceNetFobx(Fobx);
7220
7222
7223 /* And purge */
7224 Success = RxPurgeFobx(Fobx);
7225 if (Success)
7226 {
7227 ++SuccessfullPurge;
7228 }
7229
7230 /* If we don't have to finalize it (or if we cannot acquire lock exclusively
7231 * Just normally dereference
7232 */
7233 if ((AttemptFinalization == DONT_ATTEMPT_FINALIZE_ON_PURGE) ||
7235 {
7237 }
7238 /* Otherwise, finalize */
7239 else
7240 {
7244 {
7246 }
7247 }
7248
7249 if (!Success)
7250 {
7251 DPRINT1("Failed purging %p (%p)\n", Fcb, Fobx);
7252 }
7253
7255 }
7256
7257 /* If no contexts left, purge is not running */
7258 if (IsListEmpty(&PurgeSyncCtx->ContextsAwaitingPurgeCompletion))
7259 {
7260 PurgeSyncCtx->PurgeInProgress = FALSE;
7261 }
7262 /* Otherwise, notify a waiter it can start */
7263 else
7264 {
7266
7268 Context = CONTAINING_RECORD(Entry, RX_CONTEXT, RxContextSerializationQLinks);
7269
7271 }
7272
7274
7275 return (SuccessfullPurge > 0 ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL);
7276}
7277
7278/*
7279 * @implemented
7280 */
7281VOID
7284 IN PLARGE_INTEGER WaitInterval)
7285{
7288 PETHREAD CurrentThread;
7289 BOOLEAN KillThread, Dereference;
7290 PRX_WORK_QUEUE_ITEM WorkQueueItem;
7292
7293 InterlockedIncrement(&WorkQueue->NumberOfIdleWorkerThreads);
7294
7295 /* Reference ourselves */
7296 CurrentThread = PsGetCurrentThread();
7299
7300 /* Infinite loop for worker */
7301 KillThread = FALSE;
7302 Dereference = FALSE;
7303 do
7304 {
7305 KIRQL OldIrql;
7306 PLIST_ENTRY ListEntry;
7307
7308 /* Remove an entry from the work queue */
7309 ListEntry = KeRemoveQueue(&WorkQueue->Queue, KernelMode, WaitInterval);
7310 if ((ULONG_PTR)ListEntry != STATUS_TIMEOUT)
7311 {
7313
7314 WorkQueueItem = CONTAINING_RECORD(ListEntry, RX_WORK_QUEUE_ITEM, List);
7315
7316 InterlockedIncrement(&WorkQueue->NumberOfWorkItemsDispatched);
7317 InterlockedDecrement(&WorkQueue->NumberOfWorkItemsToBeDispatched);
7318 InterlockedDecrement(&WorkQueue->NumberOfIdleWorkerThreads);
7319
7320 /* Get the parameters, and null-them in the struct */
7321 WorkerRoutine = WorkQueueItem->WorkerRoutine;
7322 Parameter = WorkQueueItem->Parameter;
7323 DeviceObject = WorkQueueItem->pDeviceObject;
7324
7325 WorkQueueItem->List.Flink = NULL;
7326 WorkQueueItem->WorkerRoutine = NULL;
7327 WorkQueueItem->Parameter = NULL;
7328 WorkQueueItem->pDeviceObject = NULL;
7329
7330 /* Call the routine */
7331 DPRINT("Calling: %p(%p)\n", WorkerRoutine, Parameter);
7333
7334 /* Are we going down now? */
7335 if (InterlockedDecrement(&DeviceObject->DispatcherContext.NumberOfWorkerThreads) == 0)
7336 {
7337 PKEVENT TearDownEvent;
7338
7339 TearDownEvent = InterlockedExchangePointer((void * volatile*)&DeviceObject->DispatcherContext.pTearDownEvent, NULL);
7340 if (TearDownEvent != NULL)
7341 {
7342 KeSetEvent(TearDownEvent, IO_NO_INCREMENT, FALSE);
7343 }
7344 }
7345
7346 InterlockedIncrement(&WorkQueue->NumberOfIdleWorkerThreads);
7347 }
7348
7349 /* Shall we shutdown... */
7350 KeAcquireSpinLock(&WorkQueue->SpinLock, &OldIrql);
7351 switch (WorkQueue->State)
7352 {
7353 /* Our queue is active, kill it if we have no more items to dispatch
7354 * and more threads than the required minimum
7355 */
7356 case RxWorkQueueActive:
7357 if (WorkQueue->NumberOfWorkItemsToBeDispatched <= 0)
7358 {
7359 ASSERT(WorkQueue->NumberOfActiveWorkerThreads > 0);
7360 if (WorkQueue->NumberOfActiveWorkerThreads > WorkQueue->MinimumNumberOfWorkerThreads)
7361 {
7362 KillThread = TRUE;
7363 Dereference = TRUE;
7364 InterlockedDecrement(&WorkQueue->NumberOfActiveWorkerThreads);
7365 }
7366
7367 if (KillThread)
7368 {
7369 InterlockedDecrement(&WorkQueue->NumberOfIdleWorkerThreads);
7370 }
7371 }
7372 break;
7373
7374 /* The queue is inactive: kill it we have more threads than the required minimum */
7376 ASSERT(WorkQueue->NumberOfActiveWorkerThreads > 0);
7377 if (WorkQueue->NumberOfActiveWorkerThreads > WorkQueue->MinimumNumberOfWorkerThreads)
7378 {
7379 KillThread = TRUE;
7380 Dereference = TRUE;
7381 InterlockedDecrement(&WorkQueue->NumberOfActiveWorkerThreads);
7382 }
7383
7384 if (KillThread)
7385 {
7386 InterlockedDecrement(&WorkQueue->NumberOfIdleWorkerThreads);
7387 }
7388 break;
7389
7390 /* Rundown in progress..., kill it for sure! */
7392 {
7393 PRX_WORK_QUEUE_RUNDOWN_CONTEXT RundownContext;
7394
7395 ASSERT(WorkQueue->pRundownContext != NULL);
7396
7397 RundownContext = WorkQueue->pRundownContext;
7398 RundownContext->ThreadPointers[RundownContext->NumberOfThreadsSpunDown++] = CurrentThread;
7399
7400 InterlockedDecrement(&WorkQueue->NumberOfActiveWorkerThreads);
7401 KillThread = TRUE;
7402 Dereference = FALSE;
7403
7404 if (WorkQueue->NumberOfActiveWorkerThreads == 0)
7405 {
7407 }
7408
7409 InterlockedDecrement(&WorkQueue->NumberOfIdleWorkerThreads);
7410 }
7411 break;
7412
7413 default:
7414 break;
7415 }
7416 KeReleaseSpinLock(&WorkQueue->SpinLock, OldIrql);
7417 } while (!KillThread);
7418
7419 DPRINT("Killed worker thread\n");
7420
7421 /* Do we have to dereference ourselves? */
7422 if (Dereference)
7423 {
7424 ObDereferenceObject(CurrentThread);
7425 }
7426
7427 /* Dump last executed routine */
7429 {
7430 DPRINT("Dispatch routine %p(%p) taken from %p\n", WorkerRoutine, Parameter, WorkQueueItem);
7431 }
7432
7434}
7435
7436VOID
7439{
7442
7443 PAGED_CODE();
7444
7446
7447 /* We can only reference a few structs */
7448 NodeType = NodeType(Instance) & ~RX_SCAVENGER_MASK;
7452
7454 InterlockedIncrement((volatile long *)&Node->NodeReferenceCount);
7455
7456 /* Trace refcount if asked */
7457 switch (NodeType)
7458 {
7459 case RDBSS_NTC_SRVCALL:
7460 PRINT_REF_COUNT(SRVCALL, Node->NodeReferenceCount);
7461 break;
7462
7463 case RDBSS_NTC_NETROOT:
7464 PRINT_REF_COUNT(NETROOT, Node->NodeReferenceCount);
7465 break;
7466
7468 PRINT_REF_COUNT(VNETROOT, Node->NodeReferenceCount);
7469 break;
7470
7471 case RDBSS_NTC_SRVOPEN:
7472 PRINT_REF_COUNT(SRVOPEN, Node->NodeReferenceCount);
7473 break;
7474
7475 case RDBSS_NTC_FOBX:
7476 PRINT_REF_COUNT(NETFOBX, Node->NodeReferenceCount);
7477 break;
7478
7479 default:
7480 ASSERT(FALSE);
7481 break;
7482 }
7483
7486}
7487
7488/*
7489 * @implemented
7490 */
7491VOID
7492NTAPI
7494 IN OUT PRX_CONTEXT RxContext)
7495{
7496 PIRP Irp;
7497 PRDBSS_DEVICE_OBJECT RxDeviceObject;
7498 ULONG InitialContextFlags, SavedFlags;
7499
7500 PAGED_CODE();
7501
7502 /* Backup a few flags */
7503 Irp = RxContext->CurrentIrp;
7504 RxDeviceObject = RxContext->RxDeviceObject;
7505 SavedFlags = RxContext->Flags & RX_CONTEXT_PRESERVED_FLAGS;
7506 InitialContextFlags = RxContext->Flags & RX_CONTEXT_INITIALIZATION_FLAGS;
7507
7508 /* Reset our context */
7509 RxPrepareContextForReuse(RxContext);
7510
7511 /* Zero everything */
7512 RtlZeroMemory(&RxContext->MajorFunction, sizeof(RX_CONTEXT) - FIELD_OFFSET(RX_CONTEXT, MajorFunction));
7513
7514 /* Restore saved flags */
7515 RxContext->Flags = SavedFlags;
7516 /* And reinit the context */
7517 RxInitializeContext(Irp, RxDeviceObject, InitialContextFlags, RxContext);
7518}
7519
7520/*
7521 * @implemented
7522 */
7523VOID
7524NTAPI
7526 PVOID Context)
7527{
7528 PFCB Fcb;
7529
7530 PAGED_CODE();
7531
7532 Fcb = Context;
7533 /* The received context is a FCB */
7536
7537 /* Lazy writer is releasing lock, so forget about it */
7538 Fcb->Specific.Fcb.LazyWriteThread = NULL;
7539
7540 /* If we were top level IRP, unwind */
7542 {
7544 }
7545
7546 /* And finally, release the lock */
7549 ExReleaseResourceLite(Fcb->Header.PagingIoResource);
7550}
7551
7552/*
7553 * @implemented
7554 */
7555VOID
7556NTAPI
7558 PVOID Context)
7559{
7560 PFCB Fcb;
7561
7562 PAGED_CODE();
7563
7564 Fcb = Context;
7565 /* The received context is a FCB */
7568
7569 /* Top Level IRP is CC */
7572
7573 ExReleaseResourceLite(Fcb->Header.Resource);
7574}
7575
7576VOID
7577NTAPI
7580{
7582}
7583
7585NTAPI
7589{
7592}
7593
7594/*
7595 * @implemented
7596 */
7597VOID
7599 OUT PFCB ThisFcb)
7600{
7601 PNET_ROOT NetRoot;
7602
7603 PAGED_CODE();
7604
7605 ASSERT(NodeTypeIsFcb(ThisFcb));
7606
7607 /* Just remove the entry from the FCB_TABLE */
7608 NetRoot = (PNET_ROOT)ThisFcb->VNetRoot->pNetRoot;
7611
7612#ifdef __REACTOS__
7613 if (!BooleanFlagOn(ThisFcb->FcbState, FCB_STATE_NAME_ALREADY_REMOVED))
7614 {
7615#endif
7616 RxFcbTableRemoveFcb(&NetRoot->FcbTable, ThisFcb);
7617 DPRINT("FCB (%p) %wZ removed\n", ThisFcb, &ThisFcb->FcbTableEntry.Path);
7618 /* Mark, so that we don't try to do it twice */
7619 SetFlag(ThisFcb->FcbState, FCB_STATE_NAME_ALREADY_REMOVED);
7620#ifdef __REACTOS__
7621 }
7622#endif
7623}
7624
7625/*
7626 * @implemented
7627 */
7628VOID
7630 IN OUT PRX_CONTEXT RxContext)
7631{
7632 /* Acquire the pipe mutex */
7634
7635 /* Is that a blocking serial operation? */
7636 if (BooleanFlagOn(RxContext->FlagsForLowIo, RXCONTEXT_FLAG4LOWIO_PIPE_SYNC_OPERATION))
7637 {
7638 /* Clear it! */
7639 ClearFlag(RxContext->FlagsForLowIo, RXCONTEXT_FLAG4LOWIO_PIPE_SYNC_OPERATION);
7640
7641 /* Drop it off the list */
7642 RemoveEntryList(&RxContext->RxContextSerializationQLinks);
7643 RxContext->RxContextSerializationQLinks.Flink = NULL;
7644 RxContext->RxContextSerializationQLinks.Blink = NULL;
7645 }
7646
7647 /* Done */
7649}
7650
7651/*
7652 * @implemented
7653 */
7654VOID
7656 IN OUT PRX_PREFIX_TABLE ThisTable,
7658{
7659 PAGED_CODE();
7660
7663
7664 /* Check whether we're asked to remove null entry */
7665 if (Entry->Prefix.Length == 0)
7666 {
7667 ThisTable->TableEntryForNull = NULL;
7668 }
7669 else
7670 {
7671 RemoveEntryList(&Entry->HashLinks);
7672 }
7673
7674 Entry->ContainingRecord = NULL;
7675
7676 /* Also remove it from global list */
7677 RemoveEntryList(&Entry->MemberQLinks);
7678
7679 ++ThisTable->Version;
7680}
7681
7682/*
7683 * @implemented
7684 */
7685VOID
7687 PNET_ROOT NetRoot,
7688 PV_NET_ROOT VNetRoot)
7689{
7690 PRX_PREFIX_TABLE PrefixTable;
7691
7692 PAGED_CODE();
7693
7694 PrefixTable = NetRoot->pSrvCall->RxDeviceObject->pRxNetNameTable;
7695 ASSERT(RxIsPrefixTableLockAcquired(PrefixTable));
7696
7697 /* Remove the VNetRoot from the list in the NetRoot */
7698 --NetRoot->NumberOfVirtualNetRoots;
7700
7701 /* Fix the NetRoot if we were the default VNetRoot */
7702 if (NetRoot->DefaultVNetRoot == VNetRoot)
7703 {
7704 /* Put the first one available */
7705 if (!IsListEmpty(&NetRoot->VirtualNetRoots))
7706 {
7707 NetRoot->DefaultVNetRoot = CONTAINING_RECORD(NetRoot->VirtualNetRoots.Flink, V_NET_ROOT, NetRootListEntry);
7708 }
7709 /* Otherwise, none */
7710 else
7711 {
7712 NetRoot->DefaultVNetRoot = NULL;
7713 }
7714 }
7715
7716 /* If there are still other VNetRoot available, we're done */
7717 if (!IsListEmpty(&NetRoot->VirtualNetRoots))
7718 {
7719 return;
7720 }
7721
7722 /* Otherwise, initiate NetRoot finalization */
7724 {
7725 RxRemovePrefixTableEntry(PrefixTable, &NetRoot->PrefixEntry);
7727 }
7728
7729 /* Notify mini-rdr */
7730 if (NetRoot->pSrvCall != NULL && NetRoot->pSrvCall->RxDeviceObject != NULL)
7731 {
7733
7734 MINIRDR_CALL_THROUGH(Status, NetRoot->pSrvCall->RxDeviceObject->Dispatch,
7735 MRxFinalizeNetRoot, ((PMRX_NET_ROOT)NetRoot, FALSE));
7736 (void)Status;
7737 }
7738}
7739
7740VOID
7742 IN OUT PRX_CONTEXT RxContext)
7743{
7744 LIST_ENTRY BlockedOps;
7745
7746 PAGED_CODE();
7747
7748 /* Get the blocked operations */
7749 RxTransferListWithMutex(&BlockedOps, &RxContext->BlockedOperations, RxContext->BlockedOpsMutex);
7750
7751 if (!IsListEmpty(&BlockedOps))
7752 {
7754 }
7755}
7756
7757VOID
7758NTAPI
7760 IN OUT PRX_CONTEXT RxContext,
7761 IN OUT PLIST_ENTRY BlockingIoQ)
7762{
7763 PAGED_CODE();
7764
7766
7767 /* This can only happen on pipes */
7768 if (!BooleanFlagOn(RxContext->FlagsForLowIo, RXCONTEXT_FLAG4LOWIO_PIPE_SYNC_OPERATION))
7769 {
7771 return;
7772 }
7773
7775
7777}
7778
7779/*
7780 * @implemented
7781 */
7782VOID
7784 IN OUT PFCB Fcb,
7786{
7787 PAGED_CODE();
7788
7789 /* Set attribute and increase version */
7790 Fcb->Header.FileSize.QuadPart = *FileSize;
7792}
7793
7794/*
7795 * @implemented
7796 */
7797VOID
7799 PNET_ROOT NetRoot,
7800 PFCB PurgingFcb,
7801 BOOLEAN SynchronizeWithScavenger)
7802{
7803 PRDBSS_SCAVENGER Scavenger;
7804 PRDBSS_DEVICE_OBJECT RxDeviceObject;
7805
7806 PAGED_CODE();
7807
7808 RxDeviceObject = NetRoot->pSrvCall->RxDeviceObject;
7809 Scavenger = RxDeviceObject->pRdbssScavenger;
7810
7811 /* Wait for the scavenger, if asked to */
7812 if (SynchronizeWithScavenger)
7813 {
7815 }
7816
7818
7819 /* If there's nothing left to do... */
7820 if (Scavenger->FobxsToBeFinalized <= 0)
7821 {
7823 }
7824 else
7825 {
7827 LIST_ENTRY FobxToScavenge;
7828
7829 InitializeListHead(&FobxToScavenge);
7830
7831 /* Browse all the FOBXs to finalize */
7832 Entry = Scavenger->FobxFinalizationList.Flink;
7833 while (Entry != &Scavenger->FobxFinalizationList)
7834 {
7835 PFOBX Fobx;
7836
7837 Fobx = CONTAINING_RECORD(Entry, FOBX, ScavengerFinalizationList);
7838 Entry = Entry->Flink;
7839
7840 if (Fobx->SrvOpen != NULL)
7841 {
7842 PFCB Fcb;
7843
7844 Fcb = (PFCB)Fobx->SrvOpen->pFcb;
7845
7846 /* If it matches our NET_ROOT */
7847 if ((PNET_ROOT)Fcb->pNetRoot == NetRoot)
7848 {
7850
7851 /* Check whether it matches our FCB */
7853 if (PurgingFcb != NULL && PurgingFcb != Fcb)
7854 {
7855 MINIRDR_CALL_THROUGH(Status, RxDeviceObject->Dispatch, MRxAreFilesAliased, (Fcb, PurgingFcb));
7856 }
7857
7858 /* If so, add it to the list of the FOBXs to scavenge */
7859 if (Status != STATUS_SUCCESS)
7860 {
7861 RxReferenceNetFobx(Fobx);
7862 ASSERT(NodeType(Fobx) == RDBSS_NTC_FOBX);
7863
7865 InsertTailList(&FobxToScavenge, &Fobx->ScavengerFinalizationList);
7866 }
7867 }
7868 }
7869 }
7870
7872
7873 /* Now, scavenge all the extracted FOBX */
7874 RxpScavengeFobxs(Scavenger, &FobxToScavenge);
7875 }
7876
7877 if (SynchronizeWithScavenger)
7878 {
7880 }
7881}
7882
7883/*
7884 * @implemented
7885 */
7886BOOLEAN
7888 PFCB Fcb)
7889{
7890 PFOBX Fobx;
7891 LIST_ENTRY LocalList;
7892 PLIST_ENTRY NextEntry;
7893 PRDBSS_SCAVENGER Scavenger;
7894
7895 PAGED_CODE();
7896
7897 /* First of all, check whether there are FOBX to scavenge */
7898 Scavenger = Fcb->RxDeviceObject->pRdbssScavenger;
7900 if (Scavenger->FobxsToBeFinalized <= 0)
7901 {
7903 return FALSE;
7904 }
7905
7906 /* Initialize our local list which will hold all the FOBX to scavenge so
7907 * that we don't acquire the scavenger mutex too long
7908 */
7909 InitializeListHead(&LocalList);
7910
7911 /* Technically, that condition should all be true... */
7912 if (!IsListEmpty(&Scavenger->FobxFinalizationList))
7913 {
7914 PLIST_ENTRY NextEntry, LastEntry;
7915
7916 /* Browse all the FCBs to find the matching ones */
7917 NextEntry = Scavenger->FobxFinalizationList.Flink;
7918 LastEntry = &Scavenger->FobxFinalizationList;
7919 while (NextEntry != LastEntry)
7920 {
7921 Fobx = CONTAINING_RECORD(NextEntry, FOBX, ScavengerFinalizationList);
7922 NextEntry = NextEntry->Flink;
7923 /* Matching our FCB? Let's finalize it */
7924 if (Fobx->pSrvOpen != NULL && Fobx->pSrvOpen->pFcb == RX_GET_MRX_FCB(Fcb))
7925 {
7927 ASSERT(NodeType(Fobx) == RDBSS_NTC_FOBX);
7928 InsertTailList(&LocalList, &Fobx->ScavengerFinalizationList);
7929 }
7930 }
7931 }
7932
7934
7935 /* Nothing to scavenge? Quit */
7936 if (IsListEmpty(&LocalList))
7937 {
7938 return FALSE;
7939 }
7940
7941 /* Now, finalize all the extracted FOBX */
7942 while (!IsListEmpty(&LocalList))
7943 {
7944 NextEntry = RemoveHeadList(&LocalList);
7945 Fobx = CONTAINING_RECORD(NextEntry, FOBX, ScavengerFinalizationList);
7946 RxFinalizeNetFobx(Fobx, TRUE, TRUE);
7947 }
7948
7949 return TRUE;
7950}
7951
7952VOID
7955{
7957}
7958
7959/*
7960 * @implemented
7961 */
7962VOID
7963NTAPI
7965 PVOID Context)
7966{
7969 PRDBSS_SCAVENGER Scavenger;
7970
7971 PAGED_CODE();
7972
7974 Scavenger = DeviceObject->pRdbssScavenger;
7975
7976 Requeue = FALSE;
7978 /* If the scavenger was dormant, wake it up! */
7979 if (Scavenger->State == RDBSS_SCAVENGER_DORMANT)
7980 {
7981 /* Done */
7982 Scavenger->State = RDBSS_SCAVENGER_ACTIVE;
7983 KeClearEvent(&Scavenger->ScavengeEvent);
7984
7985 /* Scavenger the entries */
7989
7990 /* If we're still active (race) */
7991 if (Scavenger->State == RDBSS_SCAVENGER_ACTIVE)
7992 {
7993 /* If there are new entries to scavenge, stay dormant and requeue a run */
7994 if (Scavenger->NumberOfDormantFiles + Scavenger->SrvCallsToBeFinalized +
7995 Scavenger->NetRootsToBeFinalized + Scavenger->VNetRootsToBeFinalized +
7996 Scavenger->FcbsToBeFinalized + Scavenger->SrvOpensToBeFinalized +
7997 Scavenger->FobxsToBeFinalized != 0)
7998 {
7999 Requeue = TRUE;
8000 Scavenger->State = RDBSS_SCAVENGER_DORMANT;
8001 }
8002 /* Otherwise, we're inactive again */
8003 else
8004 {
8005 Scavenger->State = RDBSS_SCAVENGER_INACTIVE;
8006 }
8007 }
8008
8010
8011 /* Requeue an execution */
8012 if (Requeue)
8013 {
8016 }
8017 }
8018 else
8019 {
8021 }
8022
8024}
8025
8026BOOLEAN
8028 PRDBSS_DEVICE_OBJECT RxDeviceObject)
8029{
8031 return FALSE;
8032}
8033
8034/*
8035 * @implemented
8036 */
8037VOID
8038NTAPI
8040 PVOID Dispatcher)
8041{
8044
8046 if (!NT_SUCCESS(Status))
8047 {
8049 }
8050
8051 RxDispatcher = Dispatcher;
8052
8053 do
8054 {
8055 KIRQL OldIrql;
8056 PLIST_ENTRY ListEntry;
8057
8061
8064 {
8066 }
8067 else
8068 {
8069 ListEntry = &RxDispatcher->SpinUpRequests;
8070 }
8073
8074 while (ListEntry != &RxDispatcher->SpinUpRequests)
8075 {
8078
8080 WorkQueue = WorkItem->Parameter;
8081
8082 InterlockedDecrement(&WorkQueue->WorkQueueItemForSpinUpWorkerThreadInUse);
8083
8084 DPRINT("Workqueue: calling %p(%p)\n", WorkItem->WorkerRoutine, WorkItem->Parameter);
8085 WorkItem->WorkerRoutine(WorkItem->Parameter);
8086 }
8088
8091}
8092
8093/*
8094 * @implemented
8095 */
8101{
8102 KIRQL OldIrql;
8104 HANDLE ThreadHandle;
8105
8106 PAGED_CODE();
8107
8108 /* If work queue is inactive, that cannot work */
8109 KeAcquireSpinLock(&WorkQueue->SpinLock, &OldIrql);
8110 if (WorkQueue->State != RxWorkQueueActive)
8111 {
8113 DPRINT("Workqueue not active! WorkQ: %p, State: %d, Active: %d\n", WorkQueue, WorkQueue->State, WorkQueue->NumberOfActiveWorkerThreads);
8114 }
8115 else
8116 {
8117 ++WorkQueue->NumberOfActiveWorkerThreads;
8119 }
8120 KeReleaseSpinLock(&WorkQueue->SpinLock, OldIrql);
8121
8122 /* Quit on failure */
8123 if (!NT_SUCCESS(Status))
8124 {
8125 return Status;
8126 }
8127
8128 /* Spin up the worker thread */
8129 Status = PsCreateSystemThread(&ThreadHandle, PROCESS_ALL_ACCESS, NULL, NULL, NULL, Routine, Parameter);
8130 if (NT_SUCCESS(Status))
8131 {
8132 ZwClose(ThreadHandle);
8133 return Status;
8134 }
8135 /* Read well: we reached that point because it failed! */
8136 DPRINT("WorkQ: %p, Status: %lx\n", WorkQueue, Status);
8137
8138 KeAcquireSpinLock(&WorkQueue->SpinLock, &OldIrql);
8139 --WorkQueue->NumberOfActiveWorkerThreads;
8140 ++WorkQueue->NumberOfFailedSpinUpRequests;
8141
8142 /* Rundown, no more active threads, set the event! */
8143 if (WorkQueue->NumberOfActiveWorkerThreads == 0 &&
8145 {
8146 KeSetEvent(&WorkQueue->pRundownContext->RundownCompletionEvent, IO_NO_INCREMENT, FALSE);
8147 }
8148
8149 DPRINT("Workqueue not active! WorkQ: %p, State: %d, Active: %d\n", WorkQueue, WorkQueue->State, WorkQueue->NumberOfActiveWorkerThreads);
8150
8151 KeReleaseSpinLock(&WorkQueue->SpinLock, OldIrql);
8152
8153 return Status;
8154}
8155
8156VOID
8159{
8161}
8162
8163VOID
8165 IN PRX_CONTEXT RxContext)
8166{
8168}
8169
8170/*
8171 * @implemented
8172 */
8173ULONG
8176{
8177 ULONG Hash;
8178 SHORT Loops[8];
8179 USHORT MaxChar, i;
8180
8181 PAGED_CODE();
8182
8183 MaxChar = Name->Length / sizeof(WCHAR);
8184
8185 Loops[0] = 1;
8186 Loops[1] = MaxChar - 1;
8187 Loops[2] = MaxChar - 2;
8188 Loops[3] = MaxChar - 3;
8189 Loops[4] = MaxChar - 4;
8190 Loops[5] = MaxChar / 4;
8191 Loops[6] = 2 * MaxChar / 4;
8192 Loops[7] = 3 * MaxChar / 4;
8193
8194 Hash = 0;
8195 for (i = 0; i < 8; ++i)
8196 {
8197 SHORT Idx;
8198
8199 Idx = Loops[i];
8200 if (Idx >= 0 && Idx < MaxChar)
8201 {
8202 Hash = RtlUpcaseUnicodeChar(Name->Buffer[Idx]) + 8 * Hash;
8203 }
8204 }
8205
8206 return Hash;
8207}
8208
8209/*
8210 * @implemented
8211 */
8212ULONG
8215{
8216 ULONG Hash;
8217 SHORT Loops[8];
8218 USHORT MaxChar, i;
8219
8220 PAGED_CODE();
8221
8222 MaxChar = Name->Length / sizeof(WCHAR);
8223
8224 Loops[0] = 1;
8225 Loops[1] = MaxChar - 1;
8226 Loops[2] = MaxChar - 2;
8227 Loops[3] = MaxChar - 3;
8228 Loops[4] = MaxChar - 4;
8229 Loops[5] = MaxChar / 4;
8230 Loops[6] = 2 * MaxChar / 4;
8231 Loops[7] = 3 * MaxChar / 4;
8232
8233 Hash = 0;
8234 for (i = 0; i < 8; ++i)
8235 {
8236 SHORT Idx;
8237
8238 Idx = Loops[i];
8239 if (Idx >= 0 && Idx < MaxChar)
8240 {
8241 Hash = RtlUpcaseUnicodeChar(Name->Buffer[Idx]) + 8 * Hash;
8242 }
8243 }
8244
8245 return Hash;
8246}
8247
8248/*
8249 * @implemented
8250 */
8251PVOID
8253 IN PRX_PREFIX_TABLE ThisTable,
8256 IN PRX_CONNECTION_ID OPTIONAL RxConnectionId)
8257{
8258 PVOID Container;
8259 USHORT i, MaxChar;
8261 RX_CONNECTION_ID NullId;
8262 UNICODE_STRING LookupString;
8263
8264 PAGED_CODE();
8265
8266 /* If caller didn't provide a connection ID, setup one */
8267 if (ThisTable->IsNetNameTable && RxConnectionId == NULL)
8268 {
8269 NullId.Luid.LowPart = 0;
8270 NullId.Luid.HighPart = 0;
8271 RxConnectionId = &NullId;
8272 }
8273
8274 /* Validate name */
8275 ASSERT(Name->Buffer[0] == OBJ_NAME_PATH_SEPARATOR);
8276
8277 Entry = NULL;
8278 Container = NULL;
8279 LookupString.Buffer = Name->Buffer;
8280 MaxChar = Name->Length / sizeof(WCHAR);
8281 /* We'll perform the lookup, path component after another */
8282 for (i = 1; i < MaxChar; ++i)
8283 {
8284 ULONG Hash;
8285 PRX_PREFIX_ENTRY CurEntry;
8286
8287 /* Don't cut in the middle of a path element */
8288 if (Name->Buffer[i] != OBJ_NAME_PATH_SEPARATOR && Name->Buffer[i] != ':')
8289 {
8290 continue;
8291 }
8292
8293 /* Perform lookup in the table */
8294 LookupString.Length = i * sizeof(WCHAR);
8295 Hash = RxTableComputeHashValue(&LookupString);
8296 CurEntry = RxTableLookupName_ExactLengthMatch(ThisTable, &LookupString, Hash, RxConnectionId);
8297#if DBG
8298 ++ThisTable->Lookups;
8299#endif
8300 /* Entry not found, move to the next component */
8301 if (CurEntry == NULL)
8302 {
8303#if DBG
8304 ++ThisTable->FailedLookups;
8305#endif
8306 continue;
8307 }
8308
8309 Entry = CurEntry;
8310 ASSERT(Entry->ContainingRecord != NULL);
8311 Container = Entry->ContainingRecord;
8312
8313 /* If we have a NET_ROOT, let's return a V_NET_ROOT */
8314 if ((NodeType(Entry->ContainingRecord) & ~RX_SCAVENGER_MASK) == RDBSS_NTC_NETROOT)
8315 {
8316 PNET_ROOT NetRoot;
8317
8318 NetRoot = (PNET_ROOT)Entry->ContainingRecord;
8319 /* If there's a default one, perfect, that's a match */
8320 if (NetRoot->DefaultVNetRoot != NULL)
8321 {
8322 Container = NetRoot->DefaultVNetRoot;
8323 }
8324 /* If none (that shouldn't happen!), try to find one */
8325 else
8326 {
8327 /* Use the first one in the list */
8328 if (!IsListEmpty(&NetRoot->VirtualNetRoots))
8329 {
8330 Container = CONTAINING_RECORD(NetRoot->VirtualNetRoots.Flink, V_NET_ROOT, NetRootListEntry);
8331 }
8332 /* Really, really, shouldn't happen */
8333 else
8334 {
8335 ASSERT(FALSE);
8336 Entry = NULL;
8337 Container = NULL;
8338 }
8339 }
8340
8341 break;
8342 }
8343 else if ((NodeType(Entry->ContainingRecord) & ~RX_SCAVENGER_MASK) == RDBSS_NTC_V_NETROOT)
8344 {
8345 break;
8346 }
8347 else
8348 {
8349 ASSERT((NodeType(Entry->ContainingRecord) & ~RX_SCAVENGER_MASK) == RDBSS_NTC_SRVCALL);
8350 }
8351 }
8352
8353 /* Entry was found */
8354 if (Entry != NULL)
8355 {
8356 DPRINT("Found\n");
8357
8358 ASSERT(Name->Length >= Entry->Prefix.Length);
8359
8360 /* Setup remaining name */
8361 RemainingName->Buffer = Add2Ptr(Name->Buffer, Entry->Prefix.Length);
8362 RemainingName->Length = Name->Length - Entry->Prefix.Length;
8363 RemainingName->MaximumLength = Name->Length - Entry->Prefix.Length;
8364 }
8365 else
8366 {
8367 /* Otherwise, that's the whole name */
8369 }
8370
8371 return Container;
8372}
8373
8374/*
8375 * @implemented
8376 */
8379 IN PRX_PREFIX_TABLE ThisTable,
8382 IN PRX_CONNECTION_ID OPTIONAL RxConnectionId)
8383{
8384 PLIST_ENTRY ListEntry, HashBucket;
8385
8386 PAGED_CODE();
8387
8388 ASSERT(RxConnectionId != NULL);
8389
8390 /* Select the right bucket */
8391 HashBucket = HASH_BUCKET(ThisTable, HashValue);
8392 DPRINT("Looking in bucket: %p for %x\n", HashBucket, HashValue);
8393 /* If bucket is empty, no match */
8394 if (IsListEmpty(HashBucket))
8395 {
8396 return NULL;
8397 }
8398
8399 /* Browse all the entries in the bucket */
8400 for (ListEntry = HashBucket->Flink;
8401 ListEntry != HashBucket;
8402 ListEntry = ListEntry->Flink)
8403 {
8404 PVOID Container;
8407 PUNICODE_STRING CmpName, CmpPrefix;
8408 UNICODE_STRING InsensitiveName, InsensitivePrefix;
8409
8410 Entry = CONTAINING_RECORD(ListEntry, RX_PREFIX_ENTRY, HashLinks);
8411#if DBG
8412 ++ThisTable->Considers;
8413#endif
8414 ASSERT(HashBucket == HASH_BUCKET(ThisTable, Entry->SavedHashValue));
8415
8416 Container = Entry->ContainingRecord;
8417 ASSERT(Container != NULL);
8418
8419 /* Not the same hash, not the same length, move on */
8420 if (Entry->SavedHashValue != HashValue || Entry->Prefix.Length != Name->Length)
8421 {
8422 continue;
8423 }
8424
8425#if DBG
8426 ++ThisTable->Compares;
8427#endif
8428 /* If we have to perform a case insensitive compare on a portion... */
8429 if (Entry->CaseInsensitiveLength != 0)
8430 {
8431 ASSERT(Entry->CaseInsensitiveLength <= Name->Length);
8432
8433 /* Perform the case insensitive check on the asked length */
8434 InsensitiveName.Buffer = Name->Buffer;
8435 InsensitivePrefix.Buffer = Entry->Prefix.Buffer;
8436 InsensitiveName.Length = Entry->CaseInsensitiveLength;
8437 InsensitivePrefix.Length = Entry->CaseInsensitiveLength;
8438 /* No match, move to the next entry */
8439 if (!RtlEqualUnicodeString(&InsensitiveName, &InsensitivePrefix, TRUE))
8440 {
8441 continue;
8442 }
8443
8444 /* Was the case insensitive covering the whole name? */
8445 if (Name->Length == Entry->CaseInsensitiveLength)
8446 {
8447 /* If connection ID also matches, that a complete match! */
8448 if (!ThisTable->IsNetNameTable || RxEqualConnectionId(RxConnectionId, &Entry->ConnectionId))
8449 {
8450 return Entry;
8451 }
8452 }
8453
8454 /* Otherwise, we have to continue with the sensitive match.... */
8455 InsensitiveName.Buffer = Add2Ptr(InsensitiveName.Buffer, Entry->CaseInsensitiveLength);
8456 InsensitivePrefix.Buffer = Add2Ptr(InsensitivePrefix.Buffer, Entry->CaseInsensitiveLength);
8457 InsensitiveName.Length = Name->Length - Entry->CaseInsensitiveLength;
8458 InsensitivePrefix.Length = Entry->Prefix.Length - Entry->CaseInsensitiveLength;
8459
8460 CmpName = &InsensitiveName;
8461 CmpPrefix = &InsensitivePrefix;
8463 }
8464 else
8465 {
8466 CmpName = Name;
8467 CmpPrefix = &Entry->Prefix;
8468 CaseInsensitive = ThisTable->CaseInsensitiveMatch;
8469 }
8470
8471 /* Perform the compare, if there's a match, also check for connection ID */
8472 if (RtlEqualUnicodeString(CmpName, CmpPrefix, CaseInsensitive))
8473 {
8474 if (!ThisTable->IsNetNameTable || RxEqualConnectionId(RxConnectionId, &Entry->ConnectionId))
8475 {
8476 return Entry;
8477 }
8478 }
8479 }
8480
8481 return NULL;
8482}
8483
8484/*
8485 * @implemented
8486 */
8489 PSRV_CALL SrvCall)
8490{
8491 PAGED_CODE();
8492
8493 /* Nothing to do */
8494 return STATUS_SUCCESS;
8495}
8496
8497/*
8498 * @implemented
8499 */
8500VOID
8501NTAPI
8503 _In_ struct _KDPC *Dpc,
8507{
8508 BOOLEAN Set;
8509 LIST_ENTRY LocalList;
8510 PLIST_ENTRY ListEntry;
8512
8513 InitializeListHead(&LocalList);
8514
8517
8518 /* Find any entry matching */
8520 {
8521 ListEntry = RxTimerQueueHead.Flink;
8522 do
8523 {
8524 WorkItem = CONTAINING_RECORD(ListEntry, RX_WORK_ITEM, WorkQueueItem.List);
8525 if (WorkItem->LastTick == RxTimerTickCount)
8526 {
8527 ListEntry = ListEntry->Flink;
8528
8529 RemoveEntryList(&WorkItem->WorkQueueItem.List);
8530 InsertTailList(&LocalList, &WorkItem->WorkQueueItem.List);
8531 }
8532 else
8533 {
8534 ListEntry = ListEntry->Flink;
8535 }
8536 } while (ListEntry != &RxTimerQueueHead);
8537 }
8538 /* Do we have to requeue a later execution? */
8540
8542
8543 /* Requeue if list wasn't empty */
8544 if (Set)
8545 {
8547 }
8548
8549 /* If we had matching entries */
8550 if (!IsListEmpty(&LocalList))
8551 {
8552 /* Post them, one after another */
8553 ListEntry = LocalList.Flink;
8554 do
8555 {
8556 WorkItem = CONTAINING_RECORD(ListEntry, RX_WORK_ITEM, WorkQueueItem.List);
8557 ListEntry = ListEntry->Flink;
8558
8559 WorkItem->WorkQueueItem.List.Flink = NULL;
8560 WorkItem->WorkQueueItem.List.Blink = NULL;
8561 RxPostToWorkerThread(WorkItem->WorkQueueItem.pDeviceObject, CriticalWorkQueue,
8562 &WorkItem->WorkQueueItem, WorkItem->WorkQueueItem.WorkerRoutine,
8563 WorkItem->WorkQueueItem.Parameter);
8564 }
8565 while (ListEntry != &LocalList);
8566 }
8567}
8568
8569#ifdef RDBSS_TRACKER
8570/*
8571 * @implemented
8572 */
8573VOID
8575 _Inout_opt_ PRX_CONTEXT RxContext,
8576 _Inout_ PMRX_FCB MrxFcb,
8581{
8582 PFCB Fcb;
8584
8585 /* Check for null or special context */
8586 if (RxContext == NULL)
8587 {
8589 }
8590 else if (RxContext == CHANGE_BUFFERING_STATE_CONTEXT)
8591 {
8593 }
8594 else if (RxContext == CHANGE_BUFFERING_STATE_CONTEXT_WAIT)
8595 {
8597 }
8598 else
8599 {
8600 ASSERT(NodeType(RxContext) == RDBSS_NTC_RX_CONTEXT);
8602 }
8603
8604 /* If caller provided a FCB, update its history */
8605 if (MrxFcb != NULL)
8606 {
8607 Fcb = (PFCB)MrxFcb;
8609
8610 /* Only one acquire operation, so many release operations... */
8611 if (Operation == TRACKER_ACQUIRE_FCB)
8612 {
8613 ++Fcb->FcbAcquires[Case];
8614 }
8615 else
8616 {
8617 ++Fcb->FcbReleases[Case];
8618 }
8619 }
8620
8621 /* If we have a normal context, update its history about this function calls */
8622 if (Case == RX_FCBTRACKER_CASE_NORMAL)
8623 {
8624 ULONG TrackerHistoryPointer;
8625
8626 /* Only one acquire operation, so many release operations... */
8627 if (Operation == TRACKER_ACQUIRE_FCB)
8628 {
8629 InterlockedIncrement(&RxContext->AcquireReleaseFcbTrackerX);
8630 }
8631 else
8632 {
8633 InterlockedDecrement(&RxContext->AcquireReleaseFcbTrackerX);
8634 }
8635
8636 /* We only keep track of the 32 first calls */
8637 TrackerHistoryPointer = InterlockedExchangeAdd((volatile long *)&RxContext->TrackerHistoryPointer, 1);
8638 if (TrackerHistoryPointer < RDBSS_TRACKER_HISTORY_SIZE)
8639 {
8640 RxContext->TrackerHistory[TrackerHistoryPointer].AcquireRelease = Operation;
8641 RxContext->TrackerHistory[TrackerHistoryPointer].LineNumber = LineNumber;
8642 RxContext->TrackerHistory[TrackerHistoryPointer].FileName = (PSZ)FileName;
8643 RxContext->TrackerHistory[TrackerHistoryPointer].SavedTrackerValue = RxContext->AcquireReleaseFcbTrackerX;
8644 RxContext->TrackerHistory[TrackerHistoryPointer].Flags = RxContext->Flags;
8645 }
8646
8647 /* If it's negative, then we released once more than we acquired it?! */
8648 ASSERT(RxContext->AcquireReleaseFcbTrackerX >= 0);
8649 }
8650}
8651#endif
8652
8653VOID
8656 _In_ ULONG Type,
8657 _In_ ULONG Line,
8658 _In_ PCSTR File)
8659{
8661}
8662
8663/*
8664 * @implemented
8665 */
8666VOID
8669{
8670 /* Just call internal routine with mutex held */
8674}
8675
8676/*
8677 * @implemented
8678 */
8679VOID
8681 IN PUNICODE_STRING UserName,
8682 IN PUNICODE_STRING UserDomainName,
8685{
8686 PAGED_CODE();
8687
8688 /* Only free what could have been allocated */
8689 if (UserName != NULL)
8690 {
8691 RxFreePool(UserName);
8692 }
8693
8694 if (UserDomainName != NULL)
8695 {
8696 RxFreePool(UserDomainName);
8697 }
8698
8699 if (Password != NULL)
8700 {
8702 }
8703
8704 /* And remove the possibly set CSC agent flag */
8705 if (Flags != NULL)
8706 {
8707 (*Flags) &= ~VNETROOT_FLAG_CSCAGENT_INSTANCE;
8708 }
8709}
8710
8711/*
8712 * @implemented
8713 */
8714VOID
8716 IN RX_BLOCK_CONDITION NewConditionValue,
8718 IN OUT PLIST_ENTRY TransitionWaitList)
8719{
8721 LIST_ENTRY SerializationQueue;
8722
8723 PAGED_CODE();
8724
8725 DPRINT("RxUpdateCondition(%d, %p, %p)\n", NewConditionValue, Condition, TransitionWaitList);
8726
8727 /* Set the new condition */
8729 ASSERT(NewConditionValue != Condition_InTransition);
8730 *Condition = NewConditionValue;
8731 /* And get the serialization queue for treatment */
8732 RxTransferList(&SerializationQueue, TransitionWaitList);
8734
8735 /* Handle the serialization queue */
8737 while (Context != NULL)
8738 {
8739 /* If the caller asked for post, post the request */
8741 {
8742 Context->Flags &= ~RX_CONTEXT_FLAG_POST_ON_STABLE_CONDITION;
8744 }
8745 /* Otherwise, wake up sleeping waiters */
8746 else
8747 {
8749 }
8750
8752 }
8753}
8754
8755/*
8756 * @implemented
8757 */
8758VOID
8760 IN PRX_CONTEXT RxContext)
8761{
8762 PIRP Irp;
8763 PMRX_FOBX Fobx;
8764 BOOLEAN FlagSet;
8767
8768 PAGED_CODE();
8769
8770 Irp = RxContext->CurrentIrp;
8771 Stack = RxContext->CurrentIrpSp;
8772 FileObject = Stack->FileObject;
8773
8774 /* We'll only check stuff on opened files, this requires an IRP and a FO */
8775 if (Irp == NULL || FileObject == NULL)
8776 {
8777 return;
8778 }
8779
8780 /* Set no exception for breakpoint - remember whether is was already set */
8781 FlagSet = BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_NO_EXCEPTION_BREAKPOINT);
8783
8784 /* If we have a CCB, perform a few checks on opened file */
8785 Fobx = RxContext->pFobx;
8786 if (Fobx != NULL)
8787 {
8788 PMRX_SRV_OPEN SrvOpen;
8789
8790 SrvOpen = Fobx->pSrvOpen;
8791 if (SrvOpen != NULL)
8792 {
8794
8795 MajorFunction = RxContext->MajorFunction;
8796 /* Only allow closing/cleanup operations on renamed files */
8799 {
8800 RxContext->IoStatusBlock.Status = STATUS_FILE_RENAMED;
8802 }
8803
8804 /* Only allow closing/cleanup operations on deleted files */
8807 {
8808 RxContext->IoStatusBlock.Status = STATUS_FILE_DELETED;
8810 }
8811 }
8812 }
8813
8814 /* If that's an open operation */
8815 if (RxContext->MajorFunction == IRP_MJ_CREATE)
8816 {
8817 PFILE_OBJECT RelatedFileObject;
8818
8819 /* We won't allow an open operation relative to a file to be deleted */
8820 RelatedFileObject = FileObject->RelatedFileObject;
8821 if (RelatedFileObject != NULL)
8822 {
8823 PMRX_FCB Fcb;
8824
8825 Fcb = RelatedFileObject->FsContext;
8827 {
8828 RxContext->IoStatusBlock.Status = STATUS_DELETE_PENDING;
8830 }
8831 }
8832 }
8833
8834 /* If cleanup was completed */
8836 {
8837 if (!BooleanFlagOn(Irp->Flags, IRP_PAGING_IO))
8838 {
8840
8841 /* We only allow a subset of operations (see FatVerifyOperationIsLegal for instance) */
8842 MajorFunction = Stack->MajorFunction;
8845 {
8847 !BooleanFlagOn(Stack->MinorFunction, IRP_MN_COMPLETE))
8848 {
8849 RxContext->IoStatusBlock.Status = STATUS_FILE_CLOSED;
8851 }
8852 }
8853 }
8854 }
8855
8856 /* If flag was already set, don't clear it */
8857 if (!FlagSet)
8858 {
8860 }
8861}
8862
8863/*
8864 * @implemented
8865 */
8866VOID
8869 IN OUT PLIST_ENTRY TransitionWaitList,
8870 IN OUT PRX_CONTEXT RxContext,
8871 OUT NTSTATUS *AsyncStatus OPTIONAL)
8872{
8873 BOOLEAN Wait;
8874 NTSTATUS LocalStatus;
8875
8876 PAGED_CODE();
8877
8878 /* Make sure to always get status */
8879 if (AsyncStatus == NULL)
8880 {
8881 AsyncStatus = &LocalStatus;
8882 }
8883
8884 /* By default, it's a success */
8885 *AsyncStatus = STATUS_SUCCESS;
8886
8887 Wait = FALSE;
8888 /* If it's not stable, we've to wait */
8890 {
8891 /* Lock the mutex */
8893 /* Still not stable? */
8895 {
8896 /* Insert us in the wait list for processing on stable condition */
8897 RxInsertContextInSerializationQueue(TransitionWaitList, RxContext);
8898
8899 /* If we're asked to post on stable, don't wait, and just return pending */
8901 {
8902 *AsyncStatus = STATUS_PENDING;
8903 }
8904 else
8905 {
8906 Wait = TRUE;
8907 }
8908 }
8910
8911 /* We don't post on stable, so, just wait... */
8912 if (Wait)
8913 {
8914 RxWaitSync(RxContext);
8915 }
8916 }
8917}
8918
8919/*
8920 * @implemented
8921 */
8922VOID
8923NTAPI
8925 PVOID Context)
8926{
8927 PRX_WORK_DISPATCH_ITEM DispatchItem = Context;
8928
8929 DPRINT("Calling: %p, %p\n", DispatchItem->DispatchRoutine, DispatchItem->DispatchRoutineParameter);
8930
8931 DispatchItem->DispatchRoutine(DispatchItem->DispatchRoutineParameter);
8932
8933 RxFreePoolWithTag(DispatchItem, RX_WORKQ_POOLTAG);
8934}
8935
8936/*
8937 * @implemented
8938 */
8939PVOID
8940NTAPI
8944 _In_ ULONG Tag)
8945{
8947}
8948
8949/*
8950 * @implemented
8951 */
8952VOID
8953NTAPI
8956{
8958}
8959
8960/*
8961 * @implemented
8962 */
8963VOID
8964NTAPI
8967 _In_ ULONG Tag)
8968{
8970}
8971
8977#ifdef RDBSS_TRACKER
8978 ,
8982#endif
8983 )
8984{
8986 BOOLEAN SpecialContext, CanWait, Acquired, ContextIsPresent;
8987
8988 PAGED_CODE();
8989
8990 DPRINT("__RxAcquireFcb(%p, %p, %d, %d, %s, %d)\n", Fcb, RxContext, Mode, LineNumber, FileName, SerialNumber);
8991
8992 SpecialContext = FALSE;
8993 ContextIsPresent = FALSE;
8994 /* Check for special context */
8996 {
8997 SpecialContext = TRUE;
8998 }
8999
9000 /* We don't handle buffering state change yet... */
9001 if (!RxIsFcbAcquired(Fcb) && !SpecialContext &&
9003 {
9005 }
9006
9007 /* Nor special contexts */
9008 if (SpecialContext)
9009 {
9011 }
9012
9013 /* If we don't have a context, assume we can wait! */
9014 if (RxContext == NULL)
9015 {
9016 CanWait = TRUE;
9017 }
9018 else
9019 {
9020 /* That said: we have a real context! */
9021 ContextIsPresent = TRUE;
9022
9023 /* If we've been cancelled in between, give up */
9025 if (!NT_SUCCESS(Status))
9026 {
9027 return Status;
9028 }
9029
9030 /* Can we wait? */
9031 CanWait = BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_WAIT);
9032 }
9033
9034 while (TRUE)
9035 {
9036 /* Assume we cannot lock */
9038
9039 /* Lock according to what the caller asked */
9040 switch (Mode)
9041 {
9042 case FCB_MODE_EXCLUSIVE:
9043 Acquired = ExAcquireResourceExclusiveLite(Fcb->Header.Resource, CanWait);
9044 break;
9045
9046 case FCB_MODE_SHARED:
9047 Acquired = ExAcquireResourceSharedLite(Fcb->Header.Resource, CanWait);
9048 break;
9049
9051 Acquired = ExAcquireSharedWaitForExclusive(Fcb->Header.Resource, CanWait);
9052 break;
9053
9054 default:
9056 Acquired = ExAcquireSharedStarveExclusive(Fcb->Header.Resource, CanWait);
9057 break;
9058 }
9059
9060 /* Lock granted! */
9061 if (Acquired)
9062 {
9065
9066 /* Handle paging write - not implemented */
9068 {
9070 }
9071 }
9072
9073 /* And break, that cool! */
9074 if (Acquired)
9075 {
9076 break;
9077 }
9078
9079 /* If it failed, return immediately */
9080 if (!NT_SUCCESS(Status))
9081 {
9082 return Status;
9083 }
9084 }
9085
9086 /* If we don't have to check for valid operation, job done, nothing more to do */
9087 if (!ContextIsPresent || BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_BYPASS_VALIDOP_CHECK))
9088 {
9089 if (NT_SUCCESS(Status))
9090 {
9091 RxTrackerUpdateHistory(RxContext, RX_GET_MRX_FCB(Fcb), TRACKER_ACQUIRE_FCB, LineNumber, FileName, SerialNumber);
9092 }
9093
9094 return Status;
9095 }
9096
9097 /* Verify operation */
9098 _SEH2_TRY
9099 {
9100 RxVerifyOperationIsLegal(RxContext);
9101 }
9103 {
9104 /* If it failed, release lock and fail */
9106 {
9107 ExReleaseResourceLite(Fcb->Header.Resource);
9109 }
9110 }
9111 _SEH2_END;
9112
9113 if (NT_SUCCESS(Status))
9114 {
9115 RxTrackerUpdateHistory(RxContext, RX_GET_MRX_FCB(Fcb), TRACKER_ACQUIRE_FCB, LineNumber, FileName, SerialNumber);
9116 }
9117
9118 DPRINT("Status: %x\n", Status);
9119 return Status;
9120}
9121
9122/*
9123 * @implemented
9124 */
9125VOID
9127 _In_ PRX_CONTEXT RxContext,
9128 _In_ ULONG CapturedRxContextSerialNumber,
9129 _In_ ULONG Line,
9130 _In_ PCSTR File)
9131{
9132 /* Check we have a context with the same serial number */
9133 if (NodeType(RxContext) != RDBSS_NTC_RX_CONTEXT ||
9134 RxContext->SerialNumber != CapturedRxContextSerialNumber)
9135 {
9136 /* Just be noisy */
9137 DPRINT1("Context %p has changed at line %d in file %s\n", RxContext, Line, File);
9138 }
9139}
9140
9141VOID
9143 _Inout_opt_ PRX_CONTEXT RxContext,
9144 _Inout_ PMRX_FCB MrxFcb
9145#ifdef RDBSS_TRACKER
9146 ,
9150#endif
9151 )
9152{
9153 BOOLEAN IsExclusive, BufferingPending;
9154
9156
9157 BufferingPending = BooleanFlagOn(MrxFcb->FcbState, FCB_STATE_BUFFERING_STATE_CHANGE_PENDING);
9158 IsExclusive = !!RxIsResourceOwnershipStateExclusive(MrxFcb->Header.Resource);
9159
9160 /* If no buffering pending, or no exclusive lock (we can only handle with an exclusive lock),
9161 * then just release the FCB
9162 */
9163 if (!BufferingPending || !IsExclusive)
9164 {
9165 RxTrackerUpdateHistory(RxContext, MrxFcb, (!BufferingPending ? TRACKER_RELEASE_FCB_NO_BUFF_PENDING : TRACKER_RELEASE_NON_EXCL_FCB_BUFF_PENDING),
9167 ExReleaseResourceLite(MrxFcb->Header.Resource);
9168 }
9169
9171
9172 /* And finally leave */
9173 if (!BufferingPending || !IsExclusive)
9174 {
9175 return;
9176 }
9177
9179
9180 /* Otherwise, handle buffering state and release */
9182
9183 RxTrackerUpdateHistory(RxContext, MrxFcb, TRACKER_RELEASE_EXCL_FCB_BUFF_PENDING, LineNumber, FileName, SerialNumber);
9184 ExReleaseResourceLite(MrxFcb->Header.Resource);
9185}
9186
9187VOID
9189 _Inout_opt_ PRX_CONTEXT RxContext,
9190 _Inout_ PMRX_FCB MrxFcb,
9192#ifdef RDBSS_TRACKER
9193 ,
9197#endif
9198 )
9199{
9200 BOOLEAN IsExclusive, BufferingPending;
9201
9203
9204 BufferingPending = BooleanFlagOn(MrxFcb->FcbState, FCB_STATE_BUFFERING_STATE_CHANGE_PENDING);
9205 IsExclusive = !!RxIsResourceOwnershipStateExclusive(MrxFcb->Header.Resource);
9206
9207 /* If no buffering pending, or no exclusive lock (we can only handle with an exclusive lock),
9208 * then just release the FCB
9209 */
9210 if (!BufferingPending || !IsExclusive)
9211 {
9212 RxTrackerUpdateHistory(RxContext, MrxFcb,
9213 (!BufferingPending ? TRACKER_RELEASE_FCB_FOR_THRD_NO_BUFF_PENDING : TRACKER_RELEASE_NON_EXCL_FCB_FOR_THRD_BUFF_PENDING),
9215 ExReleaseResourceForThreadLite(MrxFcb->Header.Resource, ResourceThreadId);
9216 }
9217
9219
9220 /* And finally leave */
9221 if (!BufferingPending || !IsExclusive)
9222 {
9223 return;
9224 }
9225
9226 /* Otherwise, handle buffering state and release */
9227 RxTrackerUpdateHistory(RxContext, MrxFcb, TRACKER_RELEASE_EXCL_FCB_FOR_THRD_BUFF_PENDING, LineNumber, FileName, SerialNumber);
9229 ExReleaseResourceForThreadLite(MrxFcb->Header.Resource, ResourceThreadId);
9230}
BOOLEAN NTAPI MmForceSectionClosed(IN PSECTION_OBJECT_POINTERS SectionObjectPointer, IN BOOLEAN DelayClose)
Definition: section.c:3042
static PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(PIRP Irp)
#define PAGED_CODE()
NodeType
Definition: Node.h:6
PCWSTR FilePath
unsigned char BOOLEAN
PRTL_UNICODE_STRING_BUFFER Path
Type
Definition: Type.h:7
ACPI_BUFFER *RetBuffer ACPI_BUFFER *RetBuffer char ACPI_WALK_RESOURCE_CALLBACK void *Context ACPI_BUFFER *RetBuffer UINT16 ACPI_RESOURCE **ResourcePtr ACPI_GENERIC_ADDRESS *Reg UINT32 *ReturnValue UINT8 UINT8 *Slp_TypB ACPI_PHYSICAL_ADDRESS PhysicalAddress64 UINT32 UINT32 *TimeElapsed UINT32 LineNumber
Definition: acpixf.h:1220
struct NameRec_ * Name
Definition: cdprocs.h:460
#define OBJ_NAME_PATH_SEPARATOR
Definition: arcname_tests.c:25
#define InterlockedIncrement
Definition: armddk.h:53
#define InterlockedDecrement
Definition: armddk.h:52
#define RxInitializeThrottlingState(BP, Inc, MaxDelay)
Definition: backpack.h:13
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
#define UIntToPtr(ui)
Definition: basetsd.h:90
#define UNIMPLEMENTED
Definition: debug.h:115
#define RX_REQUEST_PREPARED_FOR_HANDLING
Definition: buffring.h:4
#define RxReleaseBufferingManagerMutex(BufMan)
Definition: buffring.h:50
#define RxAcquireBufferingManagerMutex(BufMan)
Definition: buffring.h:42
VOID NTAPI CcFlushCache(IN PSECTION_OBJECT_POINTERS SectionObjectPointer, IN OPTIONAL PLARGE_INTEGER FileOffset, IN ULONG Length, OUT OPTIONAL PIO_STATUS_BLOCK IoStatus)
Definition: cachesub.c:222
_In_ PFCB _In_ LONGLONG FileOffset
Definition: cdprocs.h:160
_Inout_ PFCB _Inout_ PUNICODE_STRING RemainingName
Definition: cdprocs.h:802
#define QuadAlign(Ptr)
Definition: cdprocs.h:1572
_In_ PFCB Fcb
Definition: cdprocs.h:159
FCB * PFCB
Definition: cdstruc.h:1040
struct _FCB FCB
Definition: bufpool.h:45
Definition: File.h:16
_In_ PIRP Irp
Definition: csq.h:116
#define DFS_DOWNLEVEL_OPEN_CONTEXT
Definition: dfs.h:7
#define DFS_OPEN_CONTEXT
Definition: dfs.h:6
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
union node Node
Definition: types.h:1255
#define Assert(cond, msg)
Definition: inflate.c:41
ULONG SessionId
Definition: dllmain.c:28
static int Hash(const char *)
Definition: reader.c:2257
static const WCHAR Message[]
Definition: register.c:74
VOID NTAPI KeInitializeDpc(IN PKDPC Dpc, IN PKDEFERRED_ROUTINE DeferredRoutine, IN PVOID DeferredContext)
Definition: dpc.c:712
USHORT NODE_TYPE_CODE
Definition: nodetype.h:22
#define NodeType(P)
Definition: nodetype.h:51
#define IO_NETWORK_INCREMENT
Definition: tcpip.h:43
#define ULONG_PTR
Definition: config.h:101
#define InterlockedExchangePointer(Target, Value)
Definition: dshow.h:45
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define InsertTailList(ListHead, Entry)
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
#define ExReleaseResourceForThreadLite(res, thrdID)
Definition: env_spec_w32.h:635
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
NTSTATUS ExInitializeResourceLite(PULONG res)
Definition: env_spec_w32.h:641
#define KeWaitForSingleObject(pEvt, foo, a, b, c)
Definition: env_spec_w32.h:478
#define RtlCompareMemory(s1, s2, l)
Definition: env_spec_w32.h:465
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
#define ExConvertExclusiveToSharedLite(res)
Definition: env_spec_w32.h:652
#define KeSetEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:476
#define KeAcquireSpinLock(sl, irql)
Definition: env_spec_w32.h:609
#define ExAcquireResourceExclusiveLite(res, wait)
Definition: env_spec_w32.h:615
#define ExDeleteResourceLite(res)
Definition: env_spec_w32.h:647
#define RemoveHeadList(ListHead)
Definition: env_spec_w32.h:964
#define NonPagedPool
Definition: env_spec_w32.h:307
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define ExAcquireResourceSharedLite(res, wait)
Definition: env_spec_w32.h:621
#define KeInitializeSpinLock(sl)
Definition: env_spec_w32.h:604
#define PagedPool
Definition: env_spec_w32.h:308
@ Success
Definition: eventcreate.c:712
VOID NTAPI KeClearEvent(IN PKEVENT Event)
Definition: eventobj.c:22
PVOID NTAPI ExAllocatePoolWithTagPriority(IN POOL_TYPE PoolType, IN SIZE_T NumberOfBytes, IN ULONG Tag, IN EX_POOL_PRIORITY Priority)
Definition: expool.c:2963
#define ClearFlag(_F, _SF)
Definition: ext2fs.h:191
#define SetFlag(_F, _SF)
Definition: ext2fs.h:187
#define BooleanFlagOn(F, SF)
Definition: ext2fs.h:183
IN PFCB IN VBO OUT PLBO OUT PULONG OUT PBOOLEAN Allocated
Definition: fatprocs.h:310
struct _NON_PAGED_FCB NON_PAGED_FCB
#define FCB_STATE_DELETE_ON_CLOSE
Definition: fatstruc.h:1193
#define FCB_STATE_PAGING_FILE
Definition: fatstruc.h:1195
struct _SRV_OPEN SRV_OPEN
#define FCB_STATE_WRITECACHING_ENABLED
Definition: fcb.h:226
#define FCB_STATE_BUFFERING_STATE_CHANGE_PENDING
Definition: fcb.h:207
struct _NET_ROOT NET_ROOT
struct _FOBX FOBX
#define RxDereferenceNetRoot(NetRoot, LockHoldingState)
Definition: fcb.h:403
#define RxReferenceNetFobx(Fobx)
Definition: fcb.h:415
#define RxTransitionSrvCall(S, C)
Definition: fcb.h:451
struct _SRV_CALL * PSRV_CALL
#define RxDereferenceSrvOpen(SrvOpen, LockHoldingState)
Definition: fcb.h:427
#define RxTransitionVNetRoot(V, C)
Definition: fcb.h:515
#define RDBSS_REF_TRACK_SRVOPEN
Definition: fcb.h:354
#define RxWaitForStableSrvCall(S, R)
Definition: fcb.h:450
#define RxReferenceVNetRoot(VNetRoot)
Definition: fcb.h:407
#define FCB_STATE_TIME_AND_SIZE_ALREADY_SET
Definition: fcb.h:217
#define RxDereferenceNetFcb(Fcb)
Definition: fcb.h:435
struct _FOBX * PFOBX
#define FCB_STATE_SPECIAL_PATH
Definition: fcb.h:216
struct _V_NET_ROOT V_NET_ROOT
#define RxReferenceNetRoot(NetRoot)
Definition: fcb.h:399
#define SRVOPEN_FLAG_ENCLOSED_ALLOCATED
Definition: fcb.h:256
#define FCB_STATE_BUFFERSTATE_CHANGING
Definition: fcb.h:215
#define FOBX_FLAG_MARKED_AS_DORMANT
Definition: fcb.h:299
#define NETROOT_FLAG_NAME_ALREADY_REMOVED
Definition: fcb.h:31
#define SRVOPEN_FLAG_FOBX_USED
Definition: fcb.h:257
#define FCB_STATE_NAME_ALREADY_REMOVED
Definition: fcb.h:227
#define FOBX_FLAG_ENCLOSED_ALLOCATED
Definition: fcb.h:298
#define FCB_STATE_READCACHING_ENABLED
Definition: fcb.h:224
#define FCB_STATE_ORPHANED
Definition: fcb.h:208
@ RX_FCBTRACKER_CASE_NULLCONTEXT
Definition: fcb.h:106
@ RX_FCBTRACKER_CASE_NORMAL
Definition: fcb.h:105
@ RX_FCBTRACKER_CASE_CBS_WAIT_CONTEXT
Definition: fcb.h:108
@ RX_FCBTRACKER_CASE_CBS_CONTEXT
Definition: fcb.h:107
#define RDBSS_REF_TRACK_NETFCB
Definition: fcb.h:353
struct _V_NET_ROOT * PV_NET_ROOT
#define PRINT_REF_COUNT(TYPE, Count)
Definition: fcb.h:376
#define FCB_STATE_FAKEFCB
Definition: fcb.h:211
#define FCB_STATE_SRVOPEN_USED
Definition: fcb.h:230
#define RDBSS_REF_TRACK_SRVCALL
Definition: fcb.h:349
#define RxReferenceNetFcb(Fcb)
Definition: fcb.h:431
#define FCB_STATE_FOBX_USED
Definition: fcb.h:229
struct _SRV_OPEN * PSRV_OPEN
#define RDBSS_REF_TRACK_NETROOT
Definition: fcb.h:350
#define RxTransitionNetRoot(N, C)
Definition: fcb.h:474
struct _SRV_CALL SRV_CALL
#define FCB_STATE_FILETIMECACHEING_ENABLED
Definition: fcb.h:218
#define RxWaitForStableNetRoot(N, R)
Definition: fcb.h:473
#define FOBX_FLAG_UNC_NAME
Definition: fcb.h:297
#define RDBSS_REF_TRACK_NETFOBX
Definition: fcb.h:352
#define RDBSS_REF_TRACK_VNETROOT
Definition: fcb.h:351
#define RxDereferenceAndFinalizeNetFcb(Fcb, RxContext, RecursiveFinalize, ForceFinalize)
Definition: fcb.h:439
struct _NET_ROOT * PNET_ROOT
enum _RX_FCBTRACKER_CASES RX_FCBTRACKER_CASES
#define RxReferenceSrvOpen(SrvOpen)
Definition: fcb.h:423
#define FOBX_FLAG_FREE_UNICODE
Definition: fcb.h:290
#define FCB_STATE_BUFFERING_STATE_MASK
Definition: fcb.h:232
#define RX_PRINT_REF_TRACKING
Definition: fcb.h:355
#define FCB_STATE_ADDEDBACKSLASH
Definition: fcb.h:228
#define FCB_STATE_COLLAPSING_ENABLED
Definition: fcb.h:221
#define ASSERT_CORRECT_FCB_STRUCTURE(Fcb)
Definition: fcb.h:562
#define RxWaitForStableVNetRoot(V, R)
Definition: fcb.h:514
#define FOBX_FLAG_SRVOPEN_CLOSED
Definition: fcb.h:296
#define RxReferenceSrvCall(SrvCall)
Definition: fcb.h:391
#define RX_LOG_REF_TRACKING
Definition: fcb.h:356
#define FCB_STATE_LOCK_BUFFERING_ENABLED
Definition: fcb.h:220
#define NETROOT_FLAG_FINALIZATION_IN_PROGRESS
Definition: fcb.h:30
#define RxDereferenceNetFobx(Fobx, LockHoldingState)
Definition: fcb.h:419
#define RxDereferenceVNetRoot(VNetRoot, LockHoldingState)
Definition: fcb.h:411
#define RxDereferenceSrvCall(SrvCall, LockHoldingState)
Definition: fcb.h:395
#define RxAcquireFcbTableLockExclusive(T, W)
Definition: fcbtable.h:55
#define RX_FCB_TABLE_NUMBER_OF_HASH_BUCKETS
Definition: fcbtable.h:13
#define RxIsFcbTableLockExclusive(T)
Definition: fcbtable.h:58
struct _RX_FCB_TABLE RX_FCB_TABLE
#define RxReleaseFcbTableLock(T)
Definition: fcbtable.h:56
VOID NTAPI FsRtlInitializeFileLock(IN PFILE_LOCK FileLock, IN PCOMPLETE_LOCK_IRP_ROUTINE CompleteLockIrpRoutine OPTIONAL, IN PUNLOCK_ROUTINE UnlockRoutine OPTIONAL)
Definition: filelock.c:1262
VOID NTAPI FsRtlUninitializeFileLock(IN PFILE_LOCK FileLock)
Definition: filelock.c:1279
#define _SEH2_FINALLY
Definition: filesup.c:21
#define _SEH2_END
Definition: filesup.c:22
#define _SEH2_TRY
Definition: filesup.c:19
#define _SEH2_LEAVE
Definition: filesup.c:20
IN OUT PLONG IN OUT PLONG Addend IN OUT PLONG IN LONG IN OUT PLONG IN LONG Increment IN PNDIS_RW_LOCK Lock IN PNDIS_RW_LOCK IN PLOCK_STATE LockState
Definition: CrNtStubs.h:104
VOID NTAPI FsRtlTeardownPerStreamContexts(IN PFSRTL_ADVANCED_FCB_HEADER AdvFcbHeader)
Definition: filtrctx.c:368
_Inout_opt_ PUNICODE_STRING Extension
Definition: fltkernel.h:1092
_Must_inspect_result_ _In_ PFLT_CALLBACK_DATA _In_ PFLT_DEFERRED_IO_WORKITEM_ROUTINE WorkerRoutine
Definition: fltkernel.h:1977
FP_OP Operation
Definition: fpcontrol.c:150
#define FILE_CREATE_TREE_CONNECTION
Definition: from_kernel.h:33
#define FILE_OPEN_FOR_BACKUP_INTENT
Definition: from_kernel.h:42
_Must_inspect_result_ _Out_ PLARGE_INTEGER FileSize
Definition: fsrtlfuncs.h:108
#define FSRTL_CACHE_TOP_LEVEL_IRP
Definition: fsrtltypes.h:60
@ FastIoIsQuestionable
Definition: fsrtltypes.h:242
#define FSRTL_FLAG_ACQUIRE_MAIN_RSRC_SH
Definition: fsrtltypes.h:49
BOOLEAN NTAPI CcPurgeCacheSection(IN PSECTION_OBJECT_POINTERS SectionObjectPointer, IN OPTIONAL PLARGE_INTEGER FileOffset, IN ULONG Length, IN BOOLEAN UninitializeCacheMaps)
Definition: fssup.c:386
#define IoFreeMdl
Definition: fxmdl.h:89
#define IoAllocateMdl
Definition: fxmdl.h:88
FxObject * pObject
Status
Definition: gdiplustypes.h:25
ASMGENDATA Table[]
Definition: genincdata.c:61
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
VOID FASTCALL ExAcquireFastMutex(IN PFAST_MUTEX FastMutex)
Definition: fmutex.c:23
VOID FASTCALL ExReleaseFastMutex(IN PFAST_MUTEX FastMutex)
Definition: fmutex.c:31
#define DbgPrint
Definition: hal.h:12
_In_ ULONG Mode
Definition: hubbusif.h:303
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
NTSYSAPI void WINAPI DbgBreakPoint(void)
#define InterlockedExchangeAdd
Definition: interlocked.h:181
#define InterlockedCompareExchange
Definition: interlocked.h:104
#define Add2Ptr(PTR, INC)
IoMarkIrpPending(Irp)
IoSetCancelRoutine(Irp, CancelRoutine)
if(dx< 0)
Definition: linetemp.h:194
#define RxLowIoIsMdlLocked(MDL)
Definition: lowio.h:8
VOID NTAPI MmProbeAndLockPages(IN PMDL Mdl, IN KPROCESSOR_MODE AccessMode, IN LOCK_OPERATION Operation)
Definition: mdlsup.c:931
MM_SYSTEMSIZE NTAPI MmQuerySystemSize(VOID)
Definition: mmsup.c:257
#define ASSERT(a)
Definition: mode.c:44
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
@ NormalPagePriority
Definition: imports.h:56
enum _RX_BLOCK_CONDITION RX_BLOCK_CONDITION
@ Condition_InTransition
Definition: mrx.h:74
@ Condition_Good
Definition: mrx.h:76
@ Condition_Bad
Definition: mrx.h:77
#define RDBSS_MANAGE_SRV_OPEN_EXTENSION
Definition: mrx.h:333
NTSTATUS(NTAPI * PLOWIO_COMPLETION_ROUTINE)(_In_ PRX_CONTEXT RxContext)
Definition: mrx.h:249
#define RxShouldPostCompletion()
Definition: mrx.h:7
enum _RX_BLOCK_CONDITION * PRX_BLOCK_CONDITION
#define RDBSS_MANAGE_FOBX_EXTENSION
Definition: mrx.h:334
@ LOWIO_OP_FSCTL
Definition: mrx.h:240
@ LOWIO_OP_MAXIMUM
Definition: mrx.h:244
@ LOWIO_OP_EXCLUSIVELOCK
Definition: mrx.h:237
@ LOWIO_OP_WRITE
Definition: mrx.h:235
@ LOWIO_OP_CLEAROUT
Definition: mrx.h:243
@ LOWIO_OP_READ
Definition: mrx.h:234
@ LOWIO_OP_NOTIFY_CHANGE_DIRECTORY
Definition: mrx.h:242
@ LOWIO_OP_UNLOCK
Definition: mrx.h:238
@ LOWIO_OP_UNLOCK_MULTIPLE
Definition: mrx.h:239
@ LOWIO_OP_SHAREDLOCK
Definition: mrx.h:236
@ LOWIO_OP_IOCTL
Definition: mrx.h:241
#define RDBSS_MANAGE_FCB_EXTENSION
Definition: mrx.h:332
#define LOWIO_CONTEXT_FLAG_SYNCCALL
Definition: mrx.h:320
#define RDBSS_MANAGE_V_NET_ROOT_EXTENSION
Definition: mrx.h:331
#define StableCondition(X)
Definition: mrx.h:81
#define LOWIO_READWRITEFLAG_PAGING_IO
Definition: mrx.h:325
#define RDBSS_MANAGE_NET_ROOT_EXTENSION
Definition: mrx.h:330
#define RDBSS_MANAGE_SRV_CALL_EXTENSION
Definition: mrx.h:329
#define LOWIO_CONTEXT_FLAG_CAN_COMPLETE_AT_DPC_LEVEL
Definition: mrx.h:323
struct _MRX_FOBX_ * PMRX_FOBX
#define SRVOPEN_FLAG_BUFFERING_STATE_CHANGE_PENDING
Definition: mrxfcb.h:136
#define SRVCALL_FLAG_CASE_INSENSITIVE_FILENAMES
Definition: mrxfcb.h:12
#define VNETROOT_FLAG_CSCAGENT_INSTANCE
Definition: mrxfcb.h:88
struct _MRX_NET_ROOT_ * PMRX_NET_ROOT
#define NETROOT_FLAG_SUPPORTS_SYMBOLIC_LINKS
Definition: mrxfcb.h:44
#define SRVCALL_FLAG_CASE_INSENSITIVE_NETROOTS
Definition: mrxfcb.h:11
#define SRVCALL_FLAG_FORCE_FINALIZED
Definition: mrxfcb.h:14
#define NET_ROOT_PIPE
Definition: mrxfcb.h:31
#define SRVOPEN_FLAG_FILE_DELETED
Definition: mrxfcb.h:135
struct _MRX_V_NET_ROOT_ * PMRX_V_NET_ROOT
#define SRVOPEN_FLAG_CLOSED
Definition: mrxfcb.h:132
#define FOBX_FLAG_BACKUP_INTENT
Definition: mrxfcb.h:183
struct _MRX_FCB_ * PMRX_FCB
struct _MRX_SRV_CALL_ * PMRX_SRV_CALL
#define NET_ROOT_MAILSLOT
Definition: mrxfcb.h:34
#define SRVOPEN_FLAG_BUFFERING_STATE_CHANGE_REQUESTS_PURGED
Definition: mrxfcb.h:138
#define SRVOPEN_FLAG_CLOSE_DELAYED
Definition: mrxfcb.h:133
UCHAR NET_ROOT_TYPE
Definition: mrxfcb.h:36
#define SRVOPEN_FLAG_FILE_RENAMED
Definition: mrxfcb.h:134
#define _Inout_
Definition: ms_sal.h:378
#define _Inout_opt_
Definition: ms_sal.h:379
#define _Out_
Definition: ms_sal.h:345
#define _In_
Definition: ms_sal.h:308
#define _In_opt_
Definition: ms_sal.h:309
__in UCHAR __in POWER_STATE __in_opt PVOID __in PIO_STATUS_BLOCK IoStatus
Definition: mxum.h:159
_In_ PNDIS_STRING _In_ PNDIS_STRING _Out_ PDEVICE_OBJECT * pDeviceObject
Definition: ndis.h:4679
#define KernelMode
Definition: asm.h:34
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
_In_ const STRING _In_ BOOLEAN CaseInsensitive
Definition: rtlfuncs.h:2359
NTSYSAPI ULONG NTAPI DbgPrompt(_In_z_ PCCH Prompt, _Out_writes_bytes_(MaximumResponseLength) PCH Response, _In_ ULONG MaximumResponseLength)
NTSYSAPI VOID NTAPI RtlCaptureContext(_Out_ PCONTEXT ContextRecord)
VOID NTAPI MiniStatus(IN NDIS_HANDLE MiniportHandle, IN NDIS_STATUS GeneralStatus, IN PVOID StatusBuffer, IN UINT StatusBufferSize)
Definition: miniport.c:1384
WCHAR NTAPI RtlUpcaseUnicodeChar(_In_ WCHAR Source)
Definition: nlsboot.c:176
#define THREAD_ALL_ACCESS
Definition: nt_native.h:1339
#define METHOD_NEITHER
Definition: nt_native.h:597
#define PROCESS_ALL_ACCESS
Definition: nt_native.h:1324
NTSYSAPI BOOLEAN NTAPI RtlEqualUnicodeString(PUNICODE_STRING String1, PUNICODE_STRING String2, BOOLEAN CaseInSensitive)
#define METHOD_OUT_DIRECT
Definition: nt_native.h:596
#define METHOD_BUFFERED
Definition: nt_native.h:594
#define METHOD_IN_DIRECT
Definition: nt_native.h:595
__GNU_EXTENSION typedef __int64 * PLONGLONG
Definition: ntbasedef.h:382
IN ULONG IN UCHAR Condition
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
@ NotificationEvent
@ SynchronizationEvent
_IRQL_requires_same_ _In_ PLSA_STRING _In_ SECURITY_LOGON_TYPE _In_ ULONG _In_ ULONG _In_opt_ PTOKEN_GROUPS _In_ PTOKEN_SOURCE _Out_ PVOID _Out_ PULONG _Inout_ PLUID LogonId
VOID FASTCALL ExReleaseFastMutexUnsafe(IN OUT PFAST_MUTEX FastMutex)
Definition: fmutex.c:86
VOID FASTCALL ExAcquireFastMutexUnsafe(IN OUT PFAST_MUTEX FastMutex)
Definition: fmutex.c:75
BOOLEAN NTAPI ExAcquireSharedWaitForExclusive(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:1222
BOOLEAN NTAPI ExAcquireSharedStarveExclusive(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:1068
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1822
BOOLEAN NTAPI FsRtlIsNtstatusExpected(IN NTSTATUS NtStatus)
Definition: filter.c:61
#define ExRaiseStatus
Definition: ntoskrnl.h:114
#define IoCompleteRequest
Definition: irp.c:1240
BOOLEAN NTAPI IoIsOperationSynchronous(IN PIRP Irp)
Definition: irp.c:1882
VOID NTAPI IoReleaseCancelSpinLock(IN KIRQL Irql)
Definition: util.c:150
PEPROCESS NTAPI IoGetCurrentProcess(VOID)
Definition: util.c:139
VOID NTAPI IoAcquireCancelSpinLock(OUT PKIRQL Irql)
Definition: util.c:56
LONG NTAPI KeInsertQueue(IN PKQUEUE Queue, IN PLIST_ENTRY Entry)
Definition: queue.c:198
VOID NTAPI KeInitializeQueue(IN PKQUEUE Queue, IN ULONG Count OPTIONAL)
Definition: queue.c:148
PLIST_ENTRY NTAPI KeRemoveQueue(IN PKQUEUE Queue, IN KPROCESSOR_MODE WaitMode, IN PLARGE_INTEGER Timeout OPTIONAL)
Definition: queue.c:238
NTSTATUS NTAPI PsTerminateSystemThread(IN NTSTATUS ExitStatus)
Definition: kill.c:1145
POBJECT_TYPE PsThreadType
Definition: thread.c:20
NTSTATUS NTAPI PsCreateSystemThread(OUT PHANDLE ThreadHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, IN HANDLE ProcessHandle, IN PCLIENT_ID ClientId, IN PKSTART_ROUTINE StartRoutine, IN PVOID StartContext)
Definition: thread.c:602
NTSTATUS NTAPI SeQueryAuthenticationIdToken(_In_ PACCESS_TOKEN Token, _Out_ PLUID LogonId)
Queries the authentication ID of an access token.
Definition: token.c:2036
NTSTATUS NTAPI SeQuerySessionIdToken(_In_ PACCESS_TOKEN Token, _Out_ PULONG pSessionId)
Queries the session ID of an access token.
Definition: token.c:2004
BOOLEAN NTAPI SeTokenIsRestricted(_In_ PACCESS_TOKEN Token)
Determines if a token is restricted or not, based upon the token flags.
Definition: token.c:2126
#define RxIsResourceOwnershipStateExclusive(Resource)
Definition: ntrxdef.h:28
#define RxAllocatePoolWithTag
Definition: ntrxdef.h:25
#define RxFreePool
Definition: ntrxdef.h:26
#define STATUS_TIMEOUT
Definition: ntstatus.h:81
#define STATUS_CONNECTION_IN_USE
Definition: ntstatus.h:500
#define STATUS_DELETE_PENDING
Definition: ntstatus.h:322
#define STATUS_BAD_NETWORK_NAME
Definition: ntstatus.h:440
#define STATUS_FILE_CLOSED
Definition: ntstatus.h:532
#define STATUS_PENDING
Definition: ntstatus.h:82
#define STATUS_FILE_RENAMED
Definition: ntstatus.h:449
#define STATUS_BAD_NETWORK_PATH
Definition: ntstatus.h:426
#define STATUS_CONNECTION_ACTIVE
Definition: ntstatus.h:703
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:239
#define STATUS_LOCK_NOT_GRANTED
Definition: ntstatus.h:321
#define STATUS_FILES_OPEN
Definition: ntstatus.h:499
NTSTATUS NTAPI ObReferenceObjectByPointer(IN PVOID Object, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode)
Definition: obref.c:381
static BOOL Set
Definition: pageheap.c:10
short SHORT
Definition: pedump.c:59
long LONG
Definition: pedump.c:60
unsigned short USHORT
Definition: pedump.c:61
struct _RX_PREFIX_ENTRY RX_PREFIX_ENTRY
struct _RX_PREFIX_TABLE RX_PREFIX_TABLE
#define RX_PREFIX_TABLE_DEFAULT_LENGTH
Definition: prefix.h:60
#define RxAcquirePrefixTableLockShared(T, W)
Definition: prefix.h:82
#define RxIsPrefixTableLockAcquired(T)
Definition: prefix.h:113
#define RxIsPrefixTableLockExclusive(T)
Definition: prefix.h:112
#define RxAcquirePrefixTableLockExclusive(T, W)
Definition: prefix.h:83
#define RxReleasePrefixTableLock(T)
Definition: prefix.h:84
#define FILE_DEVICE_NAMED_PIPE
Definition: winioctl.h:123
#define FILE_DEVICE_DISK
Definition: winioctl.h:113
#define _SEH2_AbnormalTermination()
Definition: pseh2_64.h:160
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:159
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:34
ULONG RxFsdEntryCount
Definition: rdbss.c:605
#define IRP_MJ_DIRECTORY_CONTROL
Definition: rdpdr.c:51
#define IRP_MJ_CLOSE
Definition: rdpdr.c:45
#define IRP_MN_NOTIFY_CHANGE_DIRECTORY
Definition: rdpdr.c:56
#define IRP_MJ_READ
Definition: rdpdr.c:46
#define IRP_MJ_DEVICE_CONTROL
Definition: rdpdr.c:52
#define IRP_MJ_WRITE
Definition: rdpdr.c:47
#define IRP_MJ_SET_INFORMATION
Definition: rdpdr.c:49
#define IRP_MJ_CREATE
Definition: rdpdr.c:44
#define IRP_MJ_QUERY_INFORMATION
Definition: rdpdr.c:48
VOID NTAPI KeBugCheckEx(_In_ ULONG BugCheckCode, _In_ ULONG_PTR BugCheckParameter1, _In_ ULONG_PTR BugCheckParameter2, _In_ ULONG_PTR BugCheckParameter3, _In_ ULONG_PTR BugCheckParameter4)
Definition: rtlcompat.c:108
VOID RxExclusivePrefixTableLockToShared(PRX_PREFIX_TABLE Table)
Definition: rxce.c:2440
VOID __RxItsTheSameContext(_In_ PRX_CONTEXT RxContext, _In_ ULONG CapturedRxContextSerialNumber, _In_ ULONG Line, _In_ PCSTR File)
Definition: rxce.c:9126
VOID RxpDiscardChangeBufferingStateRequests(_Inout_ PLIST_ENTRY DiscardedRequests)
Definition: rxce.c:6065
VOID RxPurgeFcb(IN PFCB Fcb)
Definition: rxce.c:6972
RX_SPIN_LOCK RxStrucSupSpinLock
Definition: rxce.c:123
PV_NET_ROOT RxCreateVNetRoot(IN PRX_CONTEXT RxContext, IN PNET_ROOT NetRoot, IN PUNICODE_STRING CanonicalName, IN PUNICODE_STRING LocalNetRootName, IN PUNICODE_STRING FilePath, IN PRX_CONNECTION_ID RxConnectionId)
Definition: rxce.c:2052
VOID RxpTrackReference(_In_ ULONG TraceType, _In_ PCSTR FileName, _In_ ULONG Line, _In_ PVOID Instance)
Definition: rxce.c:6796
VOID NTAPI RxProcessChangeBufferingStateRequests(_In_ PVOID SrvCall)
Definition: rxce.c:6643
NTSTATUS RxFindOrConstructVirtualNetRoot(IN PRX_CONTEXT RxContext, IN PUNICODE_STRING CanonicalName, IN NET_ROOT_TYPE NetRootType, IN PUNICODE_STRING RemainingName)
Definition: rxce.c:3441
NTSTATUS NTAPI RxInitializeRxTimer(VOID)
Definition: rxce.c:4946
PRX_PREFIX_ENTRY RxTableLookupName_ExactLengthMatch(IN PRX_PREFIX_TABLE ThisTable, IN PUNICODE_STRING Name, IN ULONG HashValue, IN PRX_CONNECTION_ID OPTIONAL RxConnectionId)
Definition: rxce.c:8378
BOOLEAN RxFinalizeNetFobx(_Out_ PFOBX ThisFobx, _In_ BOOLEAN RecursiveFinalize, _In_ BOOLEAN ForceFinalize)
Definition: rxce.c:2964
VOID RxAddVirtualNetRootToNetRoot(PNET_ROOT NetRoot, PV_NET_ROOT VNetRoot)
Definition: rxce.c:296
NTSTATUS __RxAcquireFcb(_Inout_ PFCB Fcb, _Inout_opt_ PRX_CONTEXT RxContext OPTIONAL, _In_ ULONG Mode)
Definition: rxce.c:8973
NTSTATUS NTAPI RxLowIoSubmit(IN PRX_CONTEXT RxContext, IN PLOWIO_COMPLETION_ROUTINE CompletionRoutine)
Definition: rxce.c:5441
VOID RxVerifyOperationIsLegal(IN PRX_CONTEXT RxContext)
Definition: rxce.c:8759
NTSTATUS RxPurgeFobxFromCache(PFOBX FobxToBePurged)
Definition: rxce.c:7087
VOID NTAPI RxResumeBlockedOperations_Serially(IN OUT PRX_CONTEXT RxContext, IN OUT PLIST_ENTRY BlockingIoQ)
Definition: rxce.c:7759
NTSTATUS RxCheckVNetRootCredentials(PRX_CONTEXT RxContext, PV_NET_ROOT VNetRoot, PLUID LogonId, PUNICODE_STRING UserName, PUNICODE_STRING UserDomain, PUNICODE_STRING Password, ULONG Flags)
Definition: rxce.c:922
VOID RxInitializeLowIoPerFcbInfo(PLOWIO_PER_FCB_INFO LowIoPerFcbInfo)
Definition: rxce.c:4847
NTSTATUS RxFindOrCreateConnections(_In_ PRX_CONTEXT RxContext, _In_ PUNICODE_STRING CanonicalName, _In_ NET_ROOT_TYPE NetRootType, _Out_ PUNICODE_STRING LocalNetRootName, _Out_ PUNICODE_STRING FilePathName, _Inout_ PLOCK_HOLDING_STATE LockState, _In_ PRX_CONNECTION_ID RxConnectionId)
Definition: rxce.c:3675
VOID RxLockUserBuffer(IN PRX_CONTEXT RxContext, IN LOCK_OPERATION Operation, IN ULONG BufferLength)
Definition: rxce.c:5249
NTSTATUS RxInitializeSrvCallParameters(IN PRX_CONTEXT RxContext, IN OUT PSRV_CALL SrvCall)
Definition: rxce.c:4921
VOID RxUndoScavengerFinalizationMarking(PVOID Instance)
Definition: rxce.c:8667
BOOLEAN RxIsThisACscAgentOpen(IN PRX_CONTEXT RxContext)
Definition: rxce.c:5226
BOOLEAN DumpDispatchRoutine
Definition: rxce.c:150
VOID RxSynchronizeWithScavenger(IN PRX_CONTEXT RxContext)
Definition: rxce.c:8164
VOID RxProcessChangeBufferingStateRequestsForSrvOpen(PSRV_OPEN SrvOpen)
Definition: rxce.c:6655
VOID RxUninitializeVNetRootParameters(IN PUNICODE_STRING UserName, IN PUNICODE_STRING UserDomainName, IN PUNICODE_STRING Password, OUT PULONG Flags)
Definition: rxce.c:8680
BOOLEAN NTAPI RxAcquireFcbForLazyWrite(PVOID Context, BOOLEAN Wait)
Definition: rxce.c:194
VOID RxExtractServerName(IN PUNICODE_STRING FilePathName, OUT PUNICODE_STRING SrvCallName, OUT PUNICODE_STRING RestOfName)
Definition: rxce.c:2452
BOOLEAN RxContinueFromAssert
Definition: rxce.c:137
VOID RxpReleasePrefixTableLock(PRX_PREFIX_TABLE pTable, BOOLEAN ProcessBufferingStateChangeRequests)
Definition: rxce.c:6566
FAST_MUTEX RxLowIoPagingIoSyncMutex
Definition: rxce.c:136
VOID RxOrphanSrvOpensForThisFcb(IN PFCB Fcb, IN PV_NET_ROOT ThisVNetRoot, IN BOOLEAN OrphanAll)
Definition: rxce.c:5876
BOOLEAN NTAPI RxNoOpAcquire(IN PVOID Fcb, IN BOOLEAN Wait)
Definition: rxce.c:5793
VOID NTAPI RxDereferenceAndDeleteRxContext_Real(IN PRX_CONTEXT RxContext)
Definition: rxce.c:2309
VOID RxFinalizeFcbTable(IN OUT PRX_FCB_TABLE FcbTable)
Definition: rxce.c:2811
FAST_MUTEX RxContextPerFileSerializationMutex
Definition: rxce.c:146
NTSTATUS RxInsertWorkQueueItem(PRDBSS_DEVICE_OBJECT pMRxDeviceObject, WORK_QUEUE_TYPE WorkQueueType, PRX_WORK_QUEUE_ITEM WorkQueueItem)
Definition: rxce.c:5161
PNET_ROOT RxCreateNetRoot(IN PSRV_CALL SrvCall, IN PUNICODE_STRING Name, IN ULONG NetRootFlags, IN PRX_CONNECTION_ID OPTIONAL RxConnectionId)
Definition: rxce.c:1705
RX_SPIN_LOCK RxTimerLock
Definition: rxce.c:140
NTSTATUS RxFcbTableRemoveFcb(IN OUT PRX_FCB_TABLE FcbTable, IN OUT PFCB Fcb)
Definition: rxce.c:2603
BOOLEAN RxFinalizeSrvCall(OUT PSRV_CALL ThisSrvCall, IN BOOLEAN RecursiveFinalize, IN BOOLEAN ForceFinalize)
Definition: rxce.c:3164
VOID RxDereference(IN OUT PVOID Instance, IN LOCK_HOLDING_STATE LockHoldingState)
Definition: rxce.c:2159
NTSTATUS RxLowIoCompletionTail(IN PRX_CONTEXT RxContext)
Definition: rxce.c:5315
NTSTATUS RxSpinUpWorkerThread(PRX_WORK_QUEUE WorkQueue, PRX_WORKERTHREAD_ROUTINE Routine, PVOID Parameter)
Definition: rxce.c:8097
VOID RxAssert(PVOID Assert, PVOID File, ULONG Line, PVOID Message)
Definition: rxce.c:645
NTSTATUS RxInitializeBufferingManager(PSRV_CALL SrvCall)
Definition: rxce.c:4507
BOOLEAN RxStopOnLoudCompletion
Definition: rxce.c:120
NTSTATUS RxInitializeWorkQueueDispatcher(PRX_WORK_QUEUE_DISPATCHER Dispatcher)
Definition: rxce.c:5090
VOID RxSetFileSizeWithLock(IN OUT PFCB Fcb, IN PLONGLONG FileSize)
Definition: rxce.c:7783
BOOLEAN RxFinalizeNetRoot(OUT PNET_ROOT ThisNetRoot, IN BOOLEAN RecursiveFinalize, IN BOOLEAN ForceFinalize)
Definition: rxce.c:3062
NTSTATUS RxpLookupSrvOpenForRequestLite(IN PSRV_CALL SrvCall, IN OUT PCHANGE_BUFFERING_STATE_REQUEST Request)
Definition: rxce.c:6222
VOID NTAPI RxSpinUpRequestsDispatcher(PVOID Dispatcher)
Definition: rxce.c:8039
VOID NTAPI RxInitializeContext(IN PIRP Irp, IN PRDBSS_DEVICE_OBJECT RxDeviceObject, IN ULONG InitialContextFlags, IN OUT PRX_CONTEXT RxContext)
Definition: rxce.c:4529
ULONG ReadAheadGranularity
Definition: rdbss.c:534
VOID RxResumeBlockedOperations_ALL(IN OUT PRX_CONTEXT RxContext)
Definition: rxce.c:7741
VOID NTAPI RxCreateNetRootCallBack(IN PMRX_CREATENETROOT_CONTEXT CreateNetRootContext)
Definition: rxce.c:1784
BOOLEAN RxSrvCallConstructionDispatcherActive
Definition: rxce.c:121
LARGE_INTEGER RxTimerInterval
Definition: rxce.c:139
NTSTATUS RxCompleteRequest(PRX_CONTEXT Context, NTSTATUS Status)
Definition: rxce.c:959
VOID NTAPI RxFinishSrvCallConstructionDispatcher(IN PVOID Context)
Definition: rxce.c:4192
VOID RxInitializePrefixTable(IN OUT PRX_PREFIX_TABLE ThisTable, IN ULONG TableSize OPTIONAL, IN BOOLEAN CaseInsensitiveMatch)
Definition: rxce.c:4875
VOID RxMarkFobxOnClose(PFOBX Fobx)
Definition: rxce.c:5723
VOID RxScavengeFobxsForNetRoot(PNET_ROOT NetRoot, PFCB PurgingFcb, BOOLEAN SynchronizeWithScavenger)
Definition: rxce.c:7798
VOID RxOrphanSrvOpens(IN PV_NET_ROOT ThisVNetRoot)
Definition: rxce.c:5817
VOID NTAPI RxCreateSrvCallCallBack(IN OUT PMRX_SRVCALL_CALLBACK_CONTEXT Context)
Definition: rxce.c:1895
LARGE_INTEGER RxWorkQueueWaitInterval[RxMaximumWorkQueue]
Definition: rxce.c:132
VOID RxRemoveVirtualNetRootFromNetRoot(PNET_ROOT NetRoot, PV_NET_ROOT VNetRoot)
Definition: rxce.c:7686
VOID NTAPI RxReleaseFileForNtCreateSection(PFILE_OBJECT FileObject)
Definition: rxce.c:7578
NTSTATUS NTAPI RxAcquireExclusiveFcbResourceInMRx(_Inout_ PMRX_FCB Fcb)
Definition: rxce.c:183
PVOID RxNewMapUserBuffer(PRX_CONTEXT RxContext)
Definition: rxce.c:5775
PVOID RxAllocateObject(NODE_TYPE_CODE NodeType, PMINIRDR_DISPATCH MRxDispatch, ULONG NameLength)
Definition: rxce.c:541
NTSTATUS RxPurgeFcbInSystemCache(IN PFCB Fcb, IN PLARGE_INTEGER FileOffset OPTIONAL, IN ULONG Length, IN BOOLEAN UninitializeCacheMaps, IN BOOLEAN FlushFile)
Definition: rxce.c:6998
PVOID RxPrefixTableLookupName(IN PRX_PREFIX_TABLE ThisTable, IN PUNICODE_STRING CanonicalName, OUT PUNICODE_STRING RemainingName, IN PRX_CONNECTION_ID ConnectionId)
Definition: rxce.c:6487
VOID __RxReleaseFcbForThread(_Inout_opt_ PRX_CONTEXT RxContext, _Inout_ PMRX_FCB MrxFcb, _In_ ERESOURCE_THREAD ResourceThreadId)
Definition: rxce.c:9188
VOID RxpMarkInstanceForScavengedFinalization(PVOID Instance)
Definition: rxce.c:6277
VOID NTAPI RxReinitializeContext(IN OUT PRX_CONTEXT RxContext)
Definition: rxce.c:7493
NTSTATUS RxInitializeMRxDispatcher(IN OUT PRDBSS_DEVICE_OBJECT pMRxDeviceObject)
Definition: rxce.c:4860
NTSTATUS NTAPI RxReleaseForCcFlush(PFILE_OBJECT FileObject, PDEVICE_OBJECT DeviceObject)
Definition: rxce.c:7586
PVOID RxAllocateFcbObject(PRDBSS_DEVICE_OBJECT RxDeviceObject, NODE_TYPE_CODE NodeType, POOL_TYPE PoolType, ULONG NameSize, PVOID AlreadyAllocatedObject)
Definition: rxce.c:316
NTSTATUS NTAPI RxPostToWorkerThread(_In_ PRDBSS_DEVICE_OBJECT pMRxDeviceObject, _In_ WORK_QUEUE_TYPE WorkQueueType, _In_ PRX_WORK_QUEUE_ITEM pWorkQueueItem, _In_ PRX_WORKERTHREAD_ROUTINE Routine, _In_ PVOID pContext)
Definition: rxce.c:6400
VOID RxGatherRequestsForSrvOpen(IN OUT PSRV_CALL SrvCall, IN PSRV_OPEN SrvOpen, IN OUT PLIST_ENTRY RequestsListHead)
Definition: rxce.c:4361
VOID RxScavengerFinalizeEntries(PRDBSS_DEVICE_OBJECT DeviceObject)
Definition: rxce.c:7953
VOID RxTrackPagingIoResource(_Inout_ PVOID Instance, _In_ ULONG Type, _In_ ULONG Line, _In_ PCSTR File)
Definition: rxce.c:8654
NTSTATUS NTAPI RxChangeBufferingState(PSRV_OPEN SrvOpen, PVOID Context, BOOLEAN ComputeNewState)
Definition: rxce.c:783
VOID RxInitializeFcbTable(IN OUT PRX_FCB_TABLE FcbTable, IN BOOLEAN CaseInsensitiveMatch)
Definition: rxce.c:4742
BOOLEAN RxpAcquirePrefixTableLockExclusive(PRX_PREFIX_TABLE pTable, BOOLEAN Wait, BOOLEAN ProcessBufferingStateChangeRequests)
Definition: rxce.c:5905
VOID RxReference(IN OUT PVOID Instance)
Definition: rxce.c:7437
PEPROCESS NTAPI RxGetRDBSSProcess(VOID)
Definition: rxce.c:4497
VOID RxCompleteSrvOpenKeyAssociation(IN OUT PSRV_OPEN SrvOpen)
Definition: rxce.c:1096
PSRV_CALL RxCreateSrvCall(IN PRX_CONTEXT RxContext, IN PUNICODE_STRING Name, IN PUNICODE_STRING InnerNamePrefix OPTIONAL, IN PRX_CONNECTION_ID RxConnectionId)
Definition: rxce.c:1843
RX_DISPATCHER RxDispatcher
Definition: rxce.c:134
VOID RxInitializePurgeSyncronizationContext(PPURGE_SYNCHRONIZATION_CONTEXT PurgeSyncronizationContext)
Definition: rxce.c:4911
BOOLEAN RxFinalizeNetFcb(OUT PFCB ThisFcb, IN BOOLEAN RecursiveFinalize, IN BOOLEAN ForceFinalize, IN LONG ReferenceCount)
Definition: rxce.c:2832
PRDBSS_DEVICE_OBJECT RxGetDeviceObjectOfInstance(PVOID Instance)
Definition: rxce.c:4409
ULONG RxTimerTickCount
Definition: rxce.c:145
VOID RxCancelBlockingOperation(IN OUT PRX_CONTEXT RxContext)
Definition: rxce.c:723
VOID RxpProcessChangeBufferingStateRequests(PSRV_CALL SrvCall, BOOLEAN UpdateHandlerState)
Definition: rxce.c:6417
PFCB RxCreateNetFcb(IN PRX_CONTEXT RxContext, IN PV_NET_ROOT VNetRoot, IN PUNICODE_STRING Name)
Definition: rxce.c:1481
VOID RxpDispatchChangeBufferingStateRequests(PSRV_CALL SrvCall, PSRV_OPEN SrvOpen, PLIST_ENTRY DiscardedRequests)
Definition: rxce.c:6098
VOID RxMarkFobxOnCleanup(PFOBX pFobx, PBOOLEAN NeedPurge)
Definition: rxce.c:5631
ULONG RxTableComputeHashValue(IN PUNICODE_STRING Name)
Definition: rxce.c:8174
BOOLEAN RxpTrackDereference(_In_ ULONG TraceType, _In_ PCSTR FileName, _In_ ULONG Line, _In_ PVOID Instance)
Definition: rxce.c:6729
VOID NTAPI RxReleaseFcbFromLazyWrite(PVOID Context)
Definition: rxce.c:7525
VOID RxPurgeChangeBufferingStateRequestsForSrvOpen(PSRV_OPEN SrvOpen)
Definition: rxce.c:6924
BOOLEAN RxpDereferenceAndFinalizeNetFcb(OUT PFCB ThisFcb, IN PRX_CONTEXT RxContext, IN BOOLEAN RecursiveFinalize, IN BOOLEAN ForceFinalize)
Definition: rxce.c:5922
PFCB RxFcbTableLookupFcb(IN PRX_FCB_TABLE FcbTable, IN PUNICODE_STRING Path)
Definition: rxce.c:2528
ULONG SerialNumber
Definition: rxce.c:117
VOID RxOrphanThisFcb(PFCB Fcb)
Definition: rxce.c:5810
volatile ULONG RxContextSerialNumberCounter
Definition: rxce.c:119
NTSTATUS NTAPI RxInitializeDispatcher(VOID)
Definition: rxce.c:4688
RX_WORK_QUEUE_DISPATCHER RxDispatcherWorkQueues
Definition: rxce.c:135
VOID NTAPI RxNoOpRelease(IN PVOID Fcb)
Definition: rxce.c:5803
NTSTATUS RxConstructNetRoot(IN PRX_CONTEXT RxContext, IN PSRV_CALL SrvCall, IN PNET_ROOT NetRoot, IN PV_NET_ROOT VirtualNetRoot, OUT PLOCK_HOLDING_STATE LockHoldingState)
Definition: rxce.c:1163
VOID NTAPI RxBootstrapWorkerThreadDispatcher(IN PVOID WorkQueue)
Definition: rxce.c:708
VOID RxGetFileSizeWithLock(IN PFCB Fcb, OUT PLONGLONG FileSize)
Definition: rxce.c:4483
LIST_ENTRY RxRecurrentWorkItemsList
Definition: rxce.c:142
PMRX_FOBX NTAPI RxCreateNetFobx(OUT PRX_CONTEXT RxContext, IN PMRX_SRV_OPEN MrxSrvOpen)
Definition: rxce.c:1596
VOID RxRemovePrefixTableEntry(IN OUT PRX_PREFIX_TABLE ThisTable, IN OUT PRX_PREFIX_ENTRY Entry)
Definition: rxce.c:7655
NTSTATUS RxPurgeRelatedFobxs(PNET_ROOT NetRoot, PRX_CONTEXT RxContext, BOOLEAN AttemptFinalization, PFCB PurgingFcb)
Definition: rxce.c:7133
ULONG RdbssReferenceTracingValue
Definition: rxce.c:130
VOID RxpWorkerThreadDispatcher(IN PRX_WORK_QUEUE WorkQueue, IN PLARGE_INTEGER WaitInterval)
Definition: rxce.c:7282
NTSTATUS RxFlushFcbInSystemCache(IN PFCB Fcb, IN BOOLEAN SynchronizeWithLazyWriter)
Definition: rxce.c:4249
NTSTATUS NTAPI RxDispatchToWorkerThread(IN PRDBSS_DEVICE_OBJECT pMRxDeviceObject, IN WORK_QUEUE_TYPE WorkQueueType, IN PRX_WORKERTHREAD_ROUTINE Routine, IN PVOID pContext)
Definition: rxce.c:2401
VOID RxFreeFcbObject(PVOID Object)
Definition: rxce.c:4274
VOID RxpScavengeFobxs(PRDBSS_SCAVENGER Scavenger, PLIST_ENTRY FobxToScavenge)
Definition: rxce.c:6695
PVOID NTAPI _RxAllocatePoolWithTag(_In_ POOL_TYPE PoolType, _In_ SIZE_T NumberOfBytes, _In_ ULONG Tag)
Definition: rxce.c:8941
VOID NTAPI RxAcquireFileForNtCreateSection(PFILE_OBJECT FileObject)
Definition: rxce.c:276
VOID RxRemoveNameNetFcb(OUT PFCB ThisFcb)
Definition: rxce.c:7598
NTSTATUS RxFinishSrvCallConstruction(PMRX_SRVCALLDOWN_STRUCTURE Calldown)
Definition: rxce.c:4089
NTSTATUS RxInitializeVNetRootParameters(PRX_CONTEXT RxContext, OUT LUID *LogonId, OUT PULONG SessionId, OUT PUNICODE_STRING *UserNamePtr, OUT PUNICODE_STRING *UserDomainNamePtr, OUT PUNICODE_STRING *PasswordPtr, OUT PULONG Flags)
Definition: rxce.c:4963
PRX_PREFIX_ENTRY RxPrefixTableInsertName(IN OUT PRX_PREFIX_TABLE ThisTable, IN OUT PRX_PREFIX_ENTRY ThisEntry, IN PVOID Container, IN PULONG ContainerRefCount, IN USHORT CaseInsensitiveLength, IN PRX_CONNECTION_ID ConnectionId)
Definition: rxce.c:6428
VOID RxSpinUpWorkerThreads(PRX_WORK_QUEUE WorkQueue)
Definition: rxce.c:8157
VOID NTAPI RxpDestroySrvCall(IN PVOID Context)
Definition: rxce.c:6031
PVOID RxNull
Definition: rxce.c:118
VOID RxRemoveOperationFromBlockingQueue(IN OUT PRX_CONTEXT RxContext)
Definition: rxce.c:7629
LIST_ENTRY RxSrvCalldownList
Definition: rxce.c:122
VOID RxpUndoScavengerFinalizationMarking(PVOID Instance)
Definition: rxce.c:6862
VOID RxUpdateCondition(IN RX_BLOCK_CONDITION NewConditionValue, OUT PRX_BLOCK_CONDITION Condition, IN OUT PLIST_ENTRY TransitionWaitList)
Definition: rxce.c:8715
volatile LONG RxNumberOfActiveFcbs
Definition: rxce.c:116
VOID RxWaitForStableCondition(IN PRX_BLOCK_CONDITION Condition, IN OUT PLIST_ENTRY TransitionWaitList, IN OUT PRX_CONTEXT RxContext, OUT NTSTATUS *AsyncStatus OPTIONAL)
Definition: rxce.c:8867
VOID NTAPI RxInitializeDebugSupport(VOID)
Definition: rxce.c:4677
NTSTATUS NTAPI RxLowIoPopulateFsctlInfo(IN PRX_CONTEXT RxContext)
Definition: rxce.c:5376
VOID NTAPI _RxFreePool(_In_ PVOID Buffer)
Definition: rxce.c:8954
BOOLEAN RxScavengeRelatedFobxs(PFCB Fcb)
Definition: rxce.c:7887
LARGE_INTEGER RxSpinUpDispatcherWaitInterval
Definition: rxce.c:133
VOID __RxReleaseFcb(_Inout_opt_ PRX_CONTEXT RxContext, _Inout_ PMRX_FCB MrxFcb)
Definition: rxce.c:9142
BOOLEAN RxFinalizeSrvOpen(OUT PSRV_OPEN ThisSrvOpen, IN BOOLEAN RecursiveFinalize, IN BOOLEAN ForceFinalize)
Definition: rxce.c:3254
BOOLEAN RxPurgeFobx(PFOBX pFobx)
Definition: rxce.c:7051
KTIMER RxTimer
Definition: rxce.c:144
VOID RxInitiateSrvOpenKeyAssociation(IN OUT PSRV_OPEN SrvOpen)
Definition: rxce.c:5141
NTSTATUS RxFcbTableInsertFcb(IN OUT PRX_FCB_TABLE FcbTable, IN OUT PFCB Fcb)
Definition: rxce.c:2492
VOID NTAPI RxDispatchChangeBufferingStateRequests(PVOID Context)
Definition: rxce.c:2390
LONG RxpReferenceNetFcb(PFCB Fcb)
Definition: rxce.c:6546
NTSTATUS RxConstructVirtualNetRoot(IN PRX_CONTEXT RxContext, IN PUNICODE_STRING CanonicalName, IN NET_ROOT_TYPE NetRootType, OUT PV_NET_ROOT *VirtualNetRootPointer, OUT PLOCK_HOLDING_STATE LockHoldingState, OUT PRX_CONNECTION_ID RxConnectionId)
Definition: rxce.c:1365
LIST_ENTRY RxTimerQueueHead
Definition: rxce.c:141
VOID RxPrepareRequestForReuse(PCHANGE_BUFFERING_STATE_REQUEST Request)
Definition: rxce.c:6607
BOOLEAN NTAPI RxAcquireFcbForReadAhead(PVOID Context, BOOLEAN Wait)
Definition: rxce.c:242
NTSTATUS RxTearDownBufferingManager(PSRV_CALL SrvCall)
Definition: rxce.c:8488
VOID NTAPI RxWorkItemDispatcher(PVOID Context)
Definition: rxce.c:8924
VOID NTAPI RxReleaseFcbFromReadAhead(PVOID Context)
Definition: rxce.c:7557
NTSTATUS NTAPI RxPostOneShotTimerRequest(IN PRDBSS_DEVICE_OBJECT pDeviceObject, IN PRX_WORK_ITEM pWorkItem, IN PRX_WORKERTHREAD_ROUTINE Routine, IN PVOID pContext, IN LARGE_INTEGER TimeInterval)
Definition: rxce.c:6362
VOID RxCompleteRequest_Real(IN PRX_CONTEXT RxContext, IN PIRP Irp, IN NTSTATUS Status)
Definition: rxce.c:996
PVOID RxMapSystemBuffer(IN PRX_CONTEXT RxContext)
Definition: rxce.c:5608
KDPC RxTimerDpc
Definition: rxce.c:143
BOOLEAN RxScavengeVNetRoots(PRDBSS_DEVICE_OBJECT RxDeviceObject)
Definition: rxce.c:8027
NTSTATUS NTAPI RxFinalizeConnection(IN OUT PNET_ROOT NetRoot, IN OUT PV_NET_ROOT VNetRoot OPTIONAL, IN LOGICAL ForceFilesClosed)
Definition: rxce.c:2636
PSRV_OPEN RxCreateSrvOpen(IN PV_NET_ROOT VNetRoot, IN OUT PFCB Fcb)
Definition: rxce.c:1968
ULONG RxExplodePoolTags
Definition: rxce.c:138
VOID NTAPI RxInitializeLowIoContext(OUT PLOWIO_CONTEXT LowIoContext, IN ULONG Operation)
Definition: rxce.c:4774
NTSTATUS RxConstructSrvCall(IN PRX_CONTEXT RxContext, IN PSRV_CALL SrvCall, OUT PLOCK_HOLDING_STATE LockHoldingState)
Definition: rxce.c:1262
VOID NTAPI RxPrepareContextForReuse(IN OUT PRX_CONTEXT RxContext)
Definition: rxce.c:6583
VOID NTAPI _RxFreePoolWithTag(_In_ PVOID Buffer, _In_ ULONG Tag)
Definition: rxce.c:8965
VOID RxFreeObject(PVOID pObject)
Definition: rxce.c:4319
LONG RxpDereferenceNetFcb(PFCB Fcb)
Definition: rxce.c:6009
VOID NTAPI RxFinishFcbInitialization(IN OUT PMRX_FCB Fcb, IN RX_FILE_TYPE FileType, IN PFCB_INIT_PACKET InitPacket OPTIONAL)
Definition: rxce.c:4030
VOID NTAPI RxTimerDispatch(_In_ struct _KDPC *Dpc, _In_opt_ PVOID DeferredContext, _In_opt_ PVOID SystemArgument1, _In_opt_ PVOID SystemArgument2)
Definition: rxce.c:8502
VOID RxInitializeWorkQueue(PRX_WORK_QUEUE WorkQueue, WORK_QUEUE_TYPE WorkQueueType, ULONG MaximumNumberOfWorkerThreads, ULONG MinimumNumberOfWorkerThreads)
Definition: rxce.c:5046
VOID NTAPI RxScavengerTimerRoutine(PVOID Context)
Definition: rxce.c:7964
ULONG RxTableComputePathHashValue(IN PUNICODE_STRING Name)
Definition: rxce.c:8213
VOID RxProcessFcbChangeBufferingStateRequest(PFCB Fcb)
Definition: rxce.c:6685
NTSTATUS NTAPI RxAcquireForCcFlush(PFILE_OBJECT FileObject, PDEVICE_OBJECT DeviceObject)
Definition: rxce.c:284
PVOID RxTableLookupName(IN PRX_PREFIX_TABLE ThisTable, IN PUNICODE_STRING Name, OUT PUNICODE_STRING RemainingName, IN PRX_CONNECTION_ID OPTIONAL RxConnectionId)
Definition: rxce.c:8252
BOOLEAN RxpAcquirePrefixTableLockShared(PRX_PREFIX_TABLE pTable, BOOLEAN Wait, BOOLEAN ProcessBufferingStateChangeRequests)
Definition: rxce.c:5888
BOOLEAN RxFinalizeVNetRoot(OUT PV_NET_ROOT ThisVNetRoot, IN BOOLEAN RecursiveFinalize, IN BOOLEAN ForceFinalize)
Definition: rxce.c:3367
PRX_CONTEXT NTAPI RxCreateRxContext(IN PIRP Irp, IN PRDBSS_DEVICE_OBJECT RxDeviceObject, IN ULONG InitialContextFlags)
Definition: rxce.c:1797
#define RxWaitSync(RxContext)
Definition: rxcontx.h:412
NPAGED_LOOKASIDE_LIST RxContextLookasideList
Definition: rdbss.c:536
@ RX_CONTEXT_FLAG_RECURSIVE_CALL
Definition: rxcontx.h:285
@ RX_CONTEXT_FLAG_CREATE_MAILSLOT
Definition: rxcontx.h:291
@ RX_CONTEXT_FLAG_THIS_DEVICE_TOP_LEVEL
Definition: rxcontx.h:286
@ RX_CONTEXT_FLAG_NO_PREPOSTING_NEEDED
Definition: rxcontx.h:302
@ RX_CONTEXT_FLAG_FROM_POOL
Definition: rxcontx.h:281
@ RX_CONTEXT_FLAG_CANCELLED
Definition: rxcontx.h:300
@ RX_CONTEXT_FLAG_POST_ON_STABLE_CONDITION
Definition: rxcontx.h:295
@ RX_CONTEXT_FLAG_MUST_SUCCEED_ALLOCATED
Definition: rxcontx.h:310
@ RX_CONTEXT_FLAG_WRITE_THROUGH
Definition: rxcontx.h:283
@ RX_CONTEXT_FLAG_MUST_SUCCEED_NONBLOCKING
Definition: rxcontx.h:309
@ RX_CONTEXT_FLAG_BYPASS_VALIDOP_CHECK
Definition: rxcontx.h:303
@ RX_CONTEXT_FLAG_IN_FSP
Definition: rxcontx.h:290
@ RX_CONTEXT_FLAG_WAIT
Definition: rxcontx.h:282
@ RX_CONTEXT_FLAG_ASYNC_OPERATION
Definition: rxcontx.h:293
@ RX_CONTEXT_FLAG_NO_EXCEPTION_BREAKPOINT
Definition: rxcontx.h:306
@ RXCONTEXT_FLAG4LOWIO_PIPE_SYNC_OPERATION
Definition: rxcontx.h:333
FORCEINLINE PRX_CONTEXT RxRemoveFirstContextFromSerializationQueue(PLIST_ENTRY SerializationQueue)
Definition: rxcontx.h:427
#define RxSignalSynchronousWaiter(RxContext)
Definition: rxcontx.h:417
struct _RX_CONTEXT RX_CONTEXT
#define MINIRDR_CALL_THROUGH(STATUS, DISPATCH, FUNC, ARGLIST)
Definition: rxcontx.h:375
PIRP RxGetTopIrpIfRdbssIrp(VOID)
Definition: rdbss.c:6845
#define RxTransferListWithMutex(Destination, Source, Mutex)
Definition: rxcontx.h:460
#define MINIRDR_CALL(STATUS, CONTEXT, DISPATCH, FUNC, ARGLIST)
Definition: rxcontx.h:389
#define RX_CONTEXT_PRESERVED_FLAGS
Definition: rxcontx.h:314
BOOLEAN RxIsThisTheTopLevelIrp(_In_ PIRP Irp)
#define RX_CONTEXT_INITIALIZATION_FLAGS
Definition: rxcontx.h:318
NTSTATUS RxCancelNotifyChangeDirectoryRequestsForVNetRoot(PV_NET_ROOT VNetRoot, BOOLEAN ForceFilesClosed)
Definition: rdbss.c:1040
BOOLEAN RxTryToBecomeTheTopLevelIrp(_Inout_ PRX_TOPLEVELIRP_CONTEXT TopLevelContext, _In_ PIRP Irp, _In_ PRDBSS_DEVICE_OBJECT RxDeviceObject, _In_ BOOLEAN ForceTopLevel)
#define RxInsertContextInSerializationQueue(SerializationQueue, RxContext)
Definition: rxcontx.h:421
VOID RxUnwindTopLevelIrp(_Inout_ PRX_TOPLEVELIRP_CONTEXT TopLevelContext)
#define RxTransferList(Destination, Source)
Definition: rxcontx.h:449
PRDBSS_DEVICE_OBJECT RxGetTopDeviceObjectIfRdbssIrp(VOID)
Definition: rdbss.c:6826
#define RxDereferenceAndDeleteRxContext(RXCONTEXT)
Definition: rxcontx.h:514
@ RX_CONTEXT_CREATE_FLAG_SPECIAL_PATH
Definition: rxcontx.h:328
@ RX_CONTEXT_CREATE_FLAG_UNC_NAME
Definition: rxcontx.h:324
@ RX_CONTEXT_CREATE_FLAG_ADDEDBACKSLASH
Definition: rxcontx.h:326
PRDBSS_DEVICE_OBJECT RxFileSystemDeviceObject
Definition: rdbss.c:573
LIST_ENTRY RxActiveContexts
Definition: rdbss.c:535
#define RxReleaseSerializationMutex()
Definition: rxdata.h:9
#define RxAcquireSerializationMutex()
Definition: rxdata.h:8
#define RX_WORKQ_POOLTAG
Definition: rxpooltg.h:9
#define RX_DIRCTL_POOLTAG
Definition: rxpooltg.h:20
#define RX_FCB_POOLTAG
Definition: rxpooltg.h:7
#define RX_NETROOT_POOLTAG
Definition: rxpooltg.h:5
#define RX_NONPAGEDFCB_POOLTAG
Definition: rxpooltg.h:8
#define RX_V_NETROOT_POOLTAG
Definition: rxpooltg.h:6
#define RX_SRVCALL_POOLTAG
Definition: rxpooltg.h:4
#define RxIsFcbAcquiredExclusive(Fcb)
Definition: rxprocs.h:229
VOID RxPrePostIrp(_In_ PVOID Context, _In_ PIRP Irp)
VOID RxpPrepareCreateContextForReuse(_In_ PRX_CONTEXT RxContext)
#define RxAcquireExclusiveFcb(R, F)
Definition: rxprocs.h:154
#define RxEqualConnectionId(C1, C2)
Definition: rxprocs.h:774
VOID NTAPI RxUnlockOperation(_In_ PVOID Context, _In_ PFILE_LOCK_INFO LockInfo)
NTSTATUS RxFsdPostRequest(_In_ PRX_CONTEXT RxContext)
#define FCB_MODE_EXCLUSIVE
Definition: rxprocs.h:130
#define RxReleasePagingIoResource(RxContext, Fcb)
Definition: rxprocs.h:268
#define CHANGE_BUFFERING_STATE_CONTEXT
Definition: rxprocs.h:135
#define FCB_MODE_SHARED_WAIT_FOR_EXCLUSIVE
Definition: rxprocs.h:132
#define RxReleaseFcb(R, F)
Definition: rxprocs.h:186
#define FCB_MODE_SHARED_STARVE_EXCLUSIVE
Definition: rxprocs.h:133
#define RX_GET_MRX_FCB(F)
Definition: rxprocs.h:157
#define RxTrackerUpdateHistory(R, F, O, L, F, S)
Definition: rxprocs.h:218
#define CHANGE_BUFFERING_STATE_CONTEXT_WAIT
Definition: rxprocs.h:136
#define RxIsFcbAcquired(Fcb)
Definition: rxprocs.h:230
#define RxAcquirePagingIoResource(RxContext, Fcb)
Definition: rxprocs.h:233
NTSTATUS NTAPI RxLockOperationCompletion(_In_ PVOID Context, _In_ PIRP Irp)
#define FCB_MODE_SHARED
Definition: rxprocs.h:131
NTSTATUS RxCloseAssociatedSrvOpen(_In_ PFOBX Fobx, _In_opt_ PRX_CONTEXT RxContext)
RDBSS_DATA RxData
Definition: rdbss.c:537
enum _LOCK_HOLDING_STATE * PLOCK_HOLDING_STATE
@ LHS_LockNotHeld
Definition: rxstruc.h:20
@ LHS_SharedLockHeld
Definition: rxstruc.h:21
@ LHS_ExclusiveLockHeld
Definition: rxstruc.h:22
enum _LOCK_HOLDING_STATE LOCK_HOLDING_STATE
#define RxMaximumWorkQueue
Definition: rxtypes.h:6
KSPIN_LOCK RX_SPIN_LOCK
Definition: rxtypes.h:8
@ RxWorkQueueRundownInProgress
Definition: rxworkq.h:26
@ RxWorkQueueActive
Definition: rxworkq.h:24
@ RxWorkQueueInactive
Definition: rxworkq.h:25
@ RxDispatcherActive
Definition: rxworkq.h:67
VOID(NTAPI * PRX_WORKERTHREAD_ROUTINE)(_In_ PVOID Context)
Definition: rxworkq.h:6
@ RDBSS_SCAVENGER_INACTIVE
Definition: scavengr.h:50
@ RDBSS_SCAVENGER_ACTIVE
Definition: scavengr.h:52
@ RDBSS_SCAVENGER_DORMANT
Definition: scavengr.h:51
#define RxInitializeScavengerEntry(ScavengerEntry)
Definition: scavengr.h:18
#define DONT_ATTEMPT_FINALIZE_ON_PURGE
Definition: scavengr.h:45
#define RxReleaseScavengerMutex()
Definition: scavengr.h:27
#define RxAcquireScavengerMutex()
Definition: scavengr.h:26
#define RDBSS_NTC_NETROOT
Definition: nodetype.h:49
#define RDBSS_NTC_STORAGE_TYPE_UNKNOWN
Definition: nodetype.h:41
#define RDBSS_NTC_STORAGE_TYPE_DIRECTORY
Definition: nodetype.h:42
#define RX_SCAVENGER_MASK
Definition: nodetype.h:70
#define RDBSS_NTC_OPENTARGETDIR_FCB
Definition: nodetype.h:44
struct _NODE_TYPE_CODE_AND_SIZE * PNODE_TYPE_AND_SIZE
#define RDBSS_NTC_INTERNAL_SRVOPEN
Definition: nodetype.h:53
#define RDBSS_NTC_SRVCALL
Definition: nodetype.h:48
#define RDBSS_NTC_RX_CONTEXT
Definition: nodetype.h:58
#define RDBSS_NTC_FCB_TABLE
Definition: nodetype.h:61
#define RDBSS_NTC_FOBX
Definition: nodetype.h:57
#define RDBSS_NTC_STORAGE_TYPE_FILE
Definition: nodetype.h:43
#define RDBSS_NTC_MINIRDR_DISPATCH
Definition: nodetype.h:64
#define RDBSS_NTC_PREFIX_TABLE
Definition: nodetype.h:59
enum _RX_FILE_TYPE RX_FILE_TYPE
#define RDBSS_STORAGE_NTC(x)
Definition: nodetype.h:32
#define RDBSS_NTC_MAILSLOT
Definition: nodetype.h:46
@ FileTypeNotYetKnown
Definition: nodetype.h:36
#define RDBSS_NTC_SPOOLFILE
Definition: nodetype.h:47
#define RDBSS_NTC_V_NETROOT
Definition: nodetype.h:50
#define RDBSS_NTC_FCB
Definition: nodetype.h:66
#define RDBSS_NTC_SRVOPEN
Definition: nodetype.h:52
#define NodeTypeIsFcb(FCB)
Definition: nodetype.h:68
#define RDBSS_FILE_SYSTEM
Definition: nodetype.h:84
#define RDBSS_NTC_FCB_TABLE_ENTRY
Definition: nodetype.h:62
#define RDBSS_NTC_PREFIX_ENTRY
Definition: nodetype.h:60
#define ZeroAndInitializeNodeType(Node, Type, Size)
Definition: nodetype.h:25
#define RDBSS_NTC_NONPAGED_FCB
Definition: nodetype.h:63
#define KeQueryTickCount(CurrentCount)
Definition: ke.h:43
#define KeAcquireSpinLockAtDpcLevel(SpinLock)
Definition: ke.h:125
#define KeReleaseSpinLockFromDpcLevel(SpinLock)
Definition: ke.h:135
BOOLEAN NTAPI MmFlushImageSection(IN PSECTION_OBJECT_POINTERS SectionObjectPointer, IN MMFLUSH_TYPE FlushType)
Definition: section.c:4356
#define STATUS_MORE_PROCESSING_REQUIRED
Definition: shellext.h:68
#define STATUS_SUCCESS
Definition: shellext.h:65
#define STATUS_NOT_FOUND
Definition: shellext.h:72
#define DPRINT
Definition: sndvol32.h:71
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
base of all file and directory entries
Definition: entries.h:83
Definition: ncftp.h:79
Definition: ncftp.h:89
PERESOURCE Resource
Definition: fcb.h:125
Definition: fcb.h:113
Definition: cdstruc.h:902
PKEVENT pBufferingStateChangeCompletedEvent
Definition: fcb.h:142
union _FCB::@720 Specific
SHARE_ACCESS ShareAccess
Definition: cdstruc.h:1009
PSRV_OPEN InternalSrvOpen
Definition: fcb.h:152
struct _FCB::@720::@723 Fcb
ULONG ulFileSizeVersion
Definition: fcb.h:164
PMINIRDR_DISPATCH MRxDispatch
Definition: fcb.h:150
CLONG OpenCount
Definition: fatstruc.h:881
PV_NET_ROOT VNetRoot
Definition: fcb.h:139
CLONG UncleanCount
Definition: fatstruc.h:873
PFOBX InternalFobx
Definition: fcb.h:153
FSRTL_ADVANCED_FCB_HEADER Header
Definition: cdstruc.h:925
ULONG FcbState
Definition: cdstruc.h:971
FCB_BUFFERED_LOCKS BufferedLocks
Definition: fcb.h:188
PRDBSS_DEVICE_OBJECT RxDeviceObject
Definition: fcb.h:149
RX_FCB_TABLE_ENTRY FcbTableEntry
Definition: fcb.h:144
PNON_PAGED_FCB NonPaged
Definition: fatstruc.h:811
PCHAR PagingIoResourceFile
Definition: fcb.h:198
UNICODE_STRING PrivateAlreadyPrefixedName
Definition: fcb.h:145
ULONG PagingIoResourceLine
Definition: fcb.h:199
PFILE_OBJECT FileObject
Definition: ntfs.h:520
Definition: fcb.h:305
volatile ULONG FobxSerialNumber
Definition: fcb.h:315
LIST_ENTRY FobxQLinks
Definition: fcb.h:316
LIST_ENTRY ClosePendingList
Definition: fcb.h:318
struct _FOBX::@1958::@1962 DiskFile
BOOLEAN fOpenCountDecremented
Definition: fcb.h:322
PSRV_OPEN SrvOpen
Definition: fcb.h:312
struct _FOBX::@1958::@1961 NamedPipe
LARGE_INTEGER CloseTime
Definition: fcb.h:319
LIST_ENTRY ScavengerFinalizationList
Definition: fcb.h:317
PRDBSS_DEVICE_OBJECT RxDeviceObject
Definition: fcb.h:346
union _FOBX::@1958 Specific
Definition: ketypes.h:699
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
struct _LOWIO_CONTEXT::@2065::@2066 ReadWrite
XXCTL_LOWIO_COMPONENT FsCtl
Definition: mrx.h:308
USHORT Operation
Definition: mrx.h:281
union _LOWIO_CONTEXT::@2065 ParamsFor
ERESOURCE_THREAD ResourceThreadId
Definition: mrx.h:285
USHORT Flags
Definition: mrx.h:282
PLOWIO_COMPLETION_ROUTINE CompletionRoutine
Definition: mrx.h:283
LIST_ENTRY PagingIoReadsOutstanding
Definition: lowio.h:19
LIST_ENTRY PagingIoWritesOutstanding
Definition: lowio.h:20
LONG HighPart
DWORD LowPart
PMRX_GET_CONNECTION_ID MRxGetConnectionId
Definition: mrx.h:399
ULONG MRxSrvCallSize
Definition: mrx.h:342
ULONG MRxNetRootSize
Definition: mrx.h:343
ULONG MRxVNetRootSize
Definition: mrx.h:344
PMRX_DEALLOCATE_FOR_FOBX MRxDeallocateForFobx
Definition: mrx.h:360
PMRX_CREATE_SRVCALL MRxCreateSrvCall
Definition: mrx.h:393
ULONG MRxFlags
Definition: mrx.h:341
PMRX_SRV_OPEN pSrvOpen
Definition: mrxfcb.h:195
PMRX_SRV_CALL SrvCall
Definition: mrx.h:136
PRX_CONTEXT RxContext
Definition: mrx.h:135
PRDBSS_DEVICE_OBJECT BestFinisher
Definition: mrx.h:142
PMRX_SRVCALL_CALLBACK CallBack
Definition: mrx.h:137
MRX_SRVCALL_CALLBACK_CONTEXT CallbackContexts[1]
Definition: mrx.h:143
LIST_ENTRY SrvCalldownList
Definition: mrx.h:134
ULONG Flags
Definition: mrxfcb.h:168
Definition: fcb.h:34
PV_NET_ROOT DefaultVNetRoot
Definition: fcb.h:49
LIST_ENTRY ScavengerFinalizationList
Definition: fcb.h:47
RX_FCB_TABLE FcbTable
Definition: fcb.h:54
PSRV_CALL SrvCall
Definition: fcb.h:41
PURGE_SYNCHRONIZATION_CONTEXT PurgeSyncronizationContext
Definition: fcb.h:48
ULONG NumberOfVirtualNetRoots
Definition: fcb.h:51
RX_BLOCK_CONDITION Condition
Definition: fcb.h:45
ULONG SerialNumberForEnum
Definition: fcb.h:52
LIST_ENTRY TransitionWaitList
Definition: fcb.h:46
RX_PREFIX_ENTRY PrefixEntry
Definition: fcb.h:53
LIST_ENTRY VirtualNetRoots
Definition: fcb.h:50
ERESOURCE BufferedLocksResource
Definition: fcb.h:97
ULONG OutstandingAsyncWrites
Definition: fatstruc.h:737
ERESOURCE HeaderResource
Definition: fcb.h:86
ERESOURCE PagingIoResource
Definition: fcb.h:87
FAST_MUTEX AdvancedFcbHeaderMutex
Definition: fatstruc.h:750
LIST_ENTRY TransitionWaitList
Definition: fcb.h:91
SECTION_OBJECT_POINTERS SectionObjectPointers
Definition: fatstruc.h:729
LIST_ENTRY ContextsAwaitingPurgeCompletion
Definition: scavengr.h:117
PEPROCESS OurProcess
Definition: rxstruc.h:34
RDBSS_STARTSTOP_CONTEXT StartStopContext
Definition: rxstruc.h:125
PMINIRDR_DISPATCH Dispatch
Definition: rxstruc.h:89
PRDBSS_SCAVENGER pRdbssScavenger
Definition: rxstruc.h:129
volatile ULONG NumberOfActiveContexts
Definition: rxstruc.h:99
RX_DISPATCHER_CONTEXT DispatcherContext
Definition: rxstruc.h:126
PRX_PREFIX_TABLE pRxNetNameTable
Definition: rxstruc.h:127
volatile ULONG NumberOfActiveFcbs
Definition: rxstruc.h:98
UNICODE_STRING DeviceName
Definition: rxstruc.h:90
PNET_ROOT CurrentNetRootForClosePendingProcessing
Definition: scavengr.h:79
ULONG NetRootsToBeFinalized
Definition: scavengr.h:63
RX_WORK_ITEM WorkItem
Definition: scavengr.h:75
LIST_ENTRY FobxFinalizationList
Definition: scavengr.h:73
ULONG SrvCallsToBeFinalized
Definition: scavengr.h:62
LARGE_INTEGER TimeLimit
Definition: scavengr.h:61
LIST_ENTRY ClosePendingFobxsList
Definition: scavengr.h:74
KEVENT ClosePendingProcessingSyncEvent
Definition: scavengr.h:81
volatile LONG NumberOfDormantFiles
Definition: scavengr.h:60
LIST_ENTRY VNetRootFinalizationList
Definition: scavengr.h:70
LIST_ENTRY SrvOpenFinalizationList
Definition: scavengr.h:72
ULONG FcbsToBeFinalized
Definition: scavengr.h:65
ULONG FobxsToBeFinalized
Definition: scavengr.h:67
ULONG SrvOpensToBeFinalized
Definition: scavengr.h:66
LONG MaximumNumberOfDormantFiles
Definition: scavengr.h:59
RDBSS_SCAVENGER_STATE State
Definition: scavengr.h:58
LIST_ENTRY NetRootFinalizationList
Definition: scavengr.h:69
KEVENT ScavengeEvent
Definition: scavengr.h:77
ULONG VNetRootsToBeFinalized
Definition: scavengr.h:64
LIST_ENTRY SrvCallFinalizationList
Definition: scavengr.h:68
PRX_CONTEXT pStopContext
Definition: rxstruc.h:61
BOOLEAN DispatcherActive
Definition: buffring.h:20
FAST_MUTEX Mutex
Definition: buffring.h:35
BOOLEAN HandlerInactive
Definition: buffring.h:21
RX_WORK_QUEUE_ITEM DispatcherWorkItem
Definition: buffring.h:32
LIST_ENTRY LastChanceHandlerList
Definition: buffring.h:31
LIST_ENTRY DispatcherList
Definition: buffring.h:29
BOOLEAN LastChanceHandlerActive
Definition: buffring.h:22
LIST_ENTRY HandlerList
Definition: buffring.h:30
volatile LONG NumberOfOutstandingOpens
Definition: buffring.h:28
LIST_ENTRY SrvOpenLists[1]
Definition: buffring.h:36
RX_WORK_QUEUE_ITEM HandlerWorkItem
Definition: buffring.h:33
KSPIN_LOCK SpinLock
Definition: buffring.h:24
ULONG SessionID
Definition: prefix.h:8
ULONG Flags
Definition: rxcontx.h:124
KEVENT SyncEvent
Definition: rxcontx.h:151
PIRP CurrentIrp
Definition: rxcontx.h:110
LOWIO_CONTEXT LowIoContext
Definition: rxcontx.h:263
PMRX_FOBX pFobx
Definition: rxcontx.h:113
PIO_STACK_LOCATION CurrentIrpSp
Definition: rxcontx.h:111
PRDBSS_DEVICE_OBJECT RxDeviceObject
Definition: rxcontx.h:116
PMRX_SRV_OPEN pRelevantSrvOpen
Definition: rxcontx.h:114
LIST_ENTRY RxContextSerializationQLinks
Definition: rxcontx.h:154
struct _RX_CONTEXT::@2148::@2160 Create
PMRX_FCB pFcb
Definition: rxcontx.h:112
volatile PKEVENT pTearDownEvent
Definition: rxstruc.h:67
volatile LONG NumberOfWorkerThreads
Definition: rxstruc.h:66
LONG NumberOfProcessors
Definition: rxworkq.h:73
PRX_WORK_QUEUE_DISPATCHER pWorkQueueDispatcher
Definition: rxworkq.h:75
PEPROCESS OwnerProcess
Definition: rxworkq.h:74
KEVENT SpinUpRequestsTearDownEvent
Definition: rxworkq.h:80
RX_DISPATCHER_STATE State
Definition: rxworkq.h:76
LIST_ENTRY SpinUpRequests
Definition: rxworkq.h:77
KSPIN_LOCK SpinUpRequestsLock
Definition: rxworkq.h:78
KEVENT SpinUpRequestsEvent
Definition: rxworkq.h:79
Definition: fcbtable.h:4
ULONG HashValue
Definition: fcbtable.h:7
LIST_ENTRY HashLinks
Definition: fcbtable.h:9
UNICODE_STRING Path
Definition: fcbtable.h:8
PRX_FCB_TABLE_ENTRY TableEntryForNull
Definition: fcbtable.h:26
LIST_ENTRY HashBuckets[RX_FCB_TABLE_NUMBER_OF_HASH_BUCKETS]
Definition: fcbtable.h:27
USHORT NumberOfBuckets
Definition: fcbtable.h:21
Definition: prefix.h:45
NODE_TYPE_CODE NodeTypeCode
Definition: prefix.h:46
UNICODE_STRING Prefix
Definition: prefix.h:53
NODE_BYTE_SIZE NodeByteSize
Definition: prefix.h:47
RX_WORK_QUEUE_ITEM WorkQueueItem
Definition: rxworkq.h:17
PRX_WORKERTHREAD_ROUTINE DispatchRoutine
Definition: rxworkq.h:18
PVOID DispatchRoutineParameter
Definition: rxworkq.h:19
RX_WORK_QUEUE WorkQueue[RxMaximumWorkQueue]
Definition: rxworkq.h:62
PRDBSS_DEVICE_OBJECT pDeviceObject
Definition: rxworkq.h:12
ULONG SharedRead
Definition: iotypes.h:529
ULONG SharedWrite
Definition: iotypes.h:530
ULONG SharedDelete
Definition: iotypes.h:531
Definition: fcb.h:10
LIST_ENTRY TransitionWaitList
Definition: fcb.h:24
RX_BUFFERING_MANAGER BufferingManager
Definition: fcb.h:27
LIST_ENTRY ScavengerFinalizationList
Definition: fcb.h:25
BOOLEAN UpperFinalizationDone
Definition: fcb.h:19
RX_PREFIX_ENTRY PrefixEntry
Definition: fcb.h:20
PURGE_SYNCHRONIZATION_CONTEXT PurgeSyncronizationContext
Definition: fcb.h:26
RX_BLOCK_CONDITION Condition
Definition: fcb.h:21
ULONG SerialNumberForEnum
Definition: fcb.h:22
Definition: fcb.h:261
LIST_ENTRY ScavengerFinalizationList
Definition: fcb.h:277
LIST_ENTRY SrvOpenKeyList
Definition: fcb.h:283
LIST_ENTRY FobxList
Definition: fcb.h:279
PFCB Fcb
Definition: fcb.h:268
volatile LONG BufferingToken
Definition: fcb.h:276
PFOBX InternalFobx
Definition: fcb.h:280
LIST_ENTRY TransitionWaitList
Definition: fcb.h:278
unsigned short Length
Definition: sprintf.c:451
USHORT MaximumLength
Definition: env_spec_w32.h:370
PNET_ROOT NetRoot
Definition: fcb.h:65
ULONG SerialNumberForEnum
Definition: fcb.h:76
LIST_ENTRY NetRootListEntry
Definition: fcb.h:75
BOOLEAN UpperFinalizationDone
Definition: fcb.h:68
BOOLEAN ConnectionFinalizationDone
Definition: fcb.h:69
ULONG PrefixOffsetInBytes
Definition: fcb.h:74
LIST_ENTRY ScavengerFinalizationList
Definition: fcb.h:78
UNICODE_STRING NamePrefix
Definition: fcb.h:73
RX_PREFIX_ENTRY PrefixEntry
Definition: fcb.h:72
volatile LONG AdditionalReferenceForDeleteFsctlTaken
Definition: fcb.h:71
RX_BLOCK_CONDITION Condition
Definition: fcb.h:70
LIST_ENTRY TransitionWaitList
Definition: fcb.h:77
ULONG OutputBufferLength
Definition: mrx.h:274
ULONG InputBufferLength
Definition: mrx.h:272
PVOID pInputBuffer
Definition: mrx.h:273
UCHAR MinorFunction
Definition: mrx.h:276
PVOID pOutputBuffer
Definition: mrx.h:275
@ Password
Definition: telnetd.h:65
BOOLEAN NTAPI KeSetTimer(IN OUT PKTIMER Timer, IN LARGE_INTEGER DueTime, IN PKDPC Dpc OPTIONAL)
Definition: timerobj.c:281
VOID NTAPI KeInitializeTimer(OUT PKTIMER Timer)
Definition: timerobj.c:233
uint32_t * PULONG
Definition: typedefs.h:59
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
unsigned char * PBOOLEAN
Definition: typedefs.h:53
INT POOL_TYPE
Definition: typedefs.h:78
#define NTAPI
Definition: typedefs.h:36
ULONG_PTR SIZE_T
Definition: typedefs.h:80
const char * PCSTR
Definition: typedefs.h:52
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define MAXUSHORT
Definition: typedefs.h:83
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define IN
Definition: typedefs.h:39
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:264
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
char CCHAR
Definition: typedefs.h:51
#define STATUS_RETRY
Definition: udferr_usr.h:182
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define STATUS_FILE_DELETED
Definition: udferr_usr.h:172
#define STATUS_INVALID_USER_BUFFER
Definition: udferr_usr.h:166
#define STATUS_OBJECT_NAME_INVALID
Definition: udferr_usr.h:148
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define STATUS_CANCELLED
Definition: udferr_usr.h:170
LONGLONG QuadPart
Definition: typedefs.h:114
Definition: dlist.c:348
static const EHCI_PERIOD pTable[]
Definition: usbehci.c:29
_Must_inspect_result_ _In_ WDFCOLLECTION _In_ WDFOBJECT Object
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
_Must_inspect_result_ _In_ WDFDEVICE _In_ BOOLEAN _In_opt_ PVOID Tag
Definition: wdfdevice.h:4065
_Must_inspect_result_ _In_ WDFDEVICE _In_ DEVICE_REGISTRY_PROPERTY _In_ _Strict_type_match_ POOL_TYPE PoolType
Definition: wdfdevice.h:3815
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:550
_In_ WDFDEVICE _In_ WDF_SPECIAL_FILE_TYPE FileType
Definition: wdfdevice.h:2741
_In_ UCHAR MajorFunction
Definition: wdfdevice.h:1697
_Must_inspect_result_ _In_ WDFDEVICE _In_ DEVICE_REGISTRY_PROPERTY _In_ ULONG BufferLength
Definition: wdfdevice.h:3771
_In_ PWDFDEVICE_INIT _In_ BOOLEAN IsExclusive
Definition: wdfdevice.h:3112
_In_ WDFREQUEST Request
Definition: wdfdevice.h:547
_In_ WDFDEVICE _In_ PVOID _In_opt_ PMDL Mdl
_Must_inspect_result_ _In_ PWDF_DPC_CONFIG _In_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFDPC * Dpc
Definition: wdfdpc.h:112
_In_ WDFDPC _In_ BOOLEAN Wait
Definition: wdfdpc.h:170
_In_ WDFREQUEST _In_ BOOLEAN Requeue
Definition: wdfrequest.h:1654
_In_ WDFREQUEST _In_ PIO_STACK_LOCATION Stack
Definition: wdfrequest.h:639
_In_ WDFREQUEST _In_opt_ PFN_WDF_REQUEST_COMPLETION_ROUTINE CompletionRoutine
Definition: wdfrequest.h:895
_Must_inspect_result_ _In_ WDFCMRESLIST List
Definition: wdfresource.h:550
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_WMI_INSTANCE_CONFIG _In_opt_ PWDF_OBJECT_ATTRIBUTES _Out_opt_ WDFWMIINSTANCE * Instance
Definition: wdfwmi.h:481
_Must_inspect_result_ _In_ PWDF_WORKITEM_CONFIG _In_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFWORKITEM * WorkItem
Definition: wdfworkitem.h:115
char * PSZ
Definition: windef.h:57
_IRQL_requires_same_ typedef _In_ ULONG _In_ UCHAR _In_ ULONGLONG _In_ ULONGLONG _In_opt_ PEVENT_FILTER_DESCRIPTOR _Inout_opt_ PVOID CallbackContext
Definition: wmitypes.h:60
LIST_ENTRY WorkQueue
Definition: workqueue.c:16
_In_ USHORT _In_ ULONG _In_ PSOCKADDR _In_ PSOCKADDR _Reserved_ ULONG _In_opt_ PVOID _In_opt_ const WSK_CLIENT_CONNECTION_DISPATCH * Dispatch
Definition: wsk.h:188
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
_In_ ERESOURCE_THREAD ResourceThreadId
Definition: exfuncs.h:1052
#define ExInitializeWorkItem(Item, Routine, Context)
Definition: exfuncs.h:265
FORCEINLINE VOID ExInitializeFastMutex(_Out_ PFAST_MUTEX FastMutex)
Definition: exfuncs.h:274
enum _WORK_QUEUE_TYPE WORK_QUEUE_TYPE
@ LowPoolPriority
Definition: extypes.h:40
FAST_MUTEX
Definition: extypes.h:17
@ DelayedWorkQueue
Definition: extypes.h:190
@ CriticalWorkQueue
Definition: extypes.h:189
@ HyperCriticalWorkQueue
Definition: extypes.h:191
WORKER_THREAD_ROUTINE * PWORKER_THREAD_ROUTINE
Definition: extypes.h:200
ULONG_PTR ERESOURCE_THREAD
Definition: extypes.h:208
#define SL_PENDING_RETURNED
Definition: iotypes.h:3325
#define IRP_MN_COMPLETE
Definition: iotypes.h:4420
#define SL_OPEN_PAGING_FILE
Definition: iotypes.h:1817
_Must_inspect_result_ typedef _Out_ PULONG TableSize
Definition: iotypes.h:4327
#define IRP_INPUT_OPERATION
#define IO_NO_INCREMENT
Definition: iotypes.h:598
#define IRP_MJ_FILE_SYSTEM_CONTROL
#define IRP_PAGING_IO
#define FO_WRITE_THROUGH
Definition: iotypes.h:1779
_Must_inspect_result_ typedef _In_ ULONG TableEntry
Definition: iotypes.h:4303
#define METHOD_FROM_CTL_CODE(ctrlCode)
#define FO_CLEANUP_COMPLETE
Definition: iotypes.h:1790
* PFILE_OBJECT
Definition: iotypes.h:1998
#define IO_DISK_INCREMENT
Definition: iotypes.h:600
#define IRP_SYNCHRONOUS_PAGING_IO
#define SL_OPEN_TARGET_DIRECTORY
Definition: iotypes.h:1818
_Must_inspect_result_ typedef _In_ PHYSICAL_ADDRESS _Inout_ PLARGE_INTEGER NumberOfBytes
Definition: iotypes.h:1036
#define IRP_MJ_CLEANUP
#define IRP_MJ_MAXIMUM_FUNCTION
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:778
@ Executive
Definition: ketypes.h:415
enum _LOCK_OPERATION LOCK_OPERATION
@ IoReadAccess
Definition: ketypes.h:863
@ IoWriteAccess
Definition: ketypes.h:864
_In_opt_ PVOID _In_opt_ PVOID SystemArgument1
Definition: ketypes.h:688
_In_opt_ PVOID DeferredContext
Definition: ketypes.h:687
_In_opt_ PVOID _In_opt_ PVOID _In_opt_ PVOID SystemArgument2
Definition: ketypes.h:689
#define MmGetSystemAddressForMdlSafe(_Mdl, _Priority)
@ MmLargeSystem
Definition: mmtypes.h:147
#define ObDereferenceObject
Definition: obfuncs.h:203
NTSYSAPI VOID NTAPI RtlGetCallersAddress(_Out_ PVOID *CallersAddress, _Out_ PVOID *CallersCaller)
Definition: except.c:22
_In_ BOOLEAN _In_ ULONG _Out_ PULONG HashValue
Definition: rtlfuncs.h:2039
_In_ __drv_aliasesMem PSTRING Prefix
Definition: rtlfuncs.h:1630
_Inout_opt_ PVOID Parameter
Definition: rtltypes.h:323
#define SeQuerySubjectContextToken(SubjectContext)
Definition: sefuncs.h:583
unsigned char UCHAR
Definition: xmlstorage.h:181
__wchar_t WCHAR
Definition: xmlstorage.h:180
char CHAR
Definition: xmlstorage.h:175