ReactOS 0.4.15-dev-7674-gc0b4db1
mup.c
Go to the documentation of this file.
1/*
2 * ReactOS kernel
3 * Copyright (C) 2002 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: drivers/filesystems/mup/mup.c
23 * PURPOSE: Multi UNC Provider
24 * PROGRAMMER: Eric Kohl
25 * Pierre Schweitzer (pierre@reactos.org)
26 */
27
28/* INCLUDES *****************************************************************/
29
30#include "mup.h"
31
32#define NDEBUG
33#include <debug.h>
34
53
54/* FUNCTIONS ****************************************************************/
55
56CODE_SEG("INIT")
57VOID
59{
69 MupKnownPrefixTimeout.QuadPart = 9000000000LL;
71}
72
73VOID
75{
80}
81
82CODE_SEG("INIT")
83VOID
85{
86 RtlZeroMemory(Vcb, sizeof(MUP_VCB));
87 Vcb->NodeType = NODE_TYPE_VCB;
88 Vcb->NodeStatus = NODE_STATUS_HEALTHY;
89 Vcb->NodeReferences = 1;
90 Vcb->NodeSize = sizeof(MUP_VCB);
91}
92
95{
96 HANDLE Key;
101 struct
102 {
104 ULONG KeyValue;
105 } KeyQueryOutput;
106
107 /* You recognize FsRtlpIsDfsEnabled()! Congratz :-) */
108 KeyName.Buffer = L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\Mup";
109 KeyName.Length = sizeof(L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\Mup") - sizeof(UNICODE_NULL);
110 KeyName.MaximumLength = sizeof(L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\Mup");
111
112 /* Simply query registry to know whether we have to disable DFS.
113 * Unless explicitly stated in registry, we will try to enable DFS.
114 */
116 &KeyName,
118 NULL,
119 NULL);
120
121 Status = ZwOpenKey(&Key, KEY_READ, &ObjectAttributes);
122 if (!NT_SUCCESS(Status))
123 {
124 return TRUE;
125 }
126
127 KeyName.Buffer = L"DisableDfs";
128 KeyName.Length = sizeof(L"DisableDfs") - sizeof(UNICODE_NULL);
129 KeyName.MaximumLength = sizeof(L"DisableDfs");
130
131 Status = ZwQueryValueKey(Key, &KeyName, KeyValuePartialInformation, &KeyQueryOutput, sizeof(KeyQueryOutput), &Length);
132 ZwClose(Key);
133 if (!NT_SUCCESS(Status) || KeyQueryOutput.KeyInfo.Type != REG_DWORD)
134 {
135 return TRUE;
136 }
137
138 return ((ULONG_PTR)KeyQueryOutput.KeyInfo.Data != 1);
139}
140
141VOID
143{
144 LARGE_INTEGER CurrentTime;
145
146 /* Just get now + our allowed timeout */
147 KeQuerySystemTime(&CurrentTime);
148 EntryTime->QuadPart = CurrentTime.QuadPart + MupKnownPrefixTimeout.QuadPart;
149}
150
153{
155
157 if (Ccb == NULL)
158 {
159 return NULL;
160 }
161
162 Ccb->NodeStatus = NODE_STATUS_HEALTHY;
163 Ccb->NodeReferences = 1;
164 Ccb->NodeType = NODE_TYPE_CCB;
165 Ccb->NodeSize = sizeof(MUP_CCB);
166
167 return Ccb;
168}
169
172{
174
176 if (Fcb == NULL)
177 {
178 return NULL;
179 }
180
181 Fcb->NodeStatus = NODE_STATUS_HEALTHY;
182 Fcb->NodeReferences = 1;
183 Fcb->NodeType = NODE_TYPE_FCB;
184 Fcb->NodeSize = sizeof(MUP_FCB);
185 InitializeListHead(&Fcb->CcbList);
186
187 return Fcb;
188}
189
192{
193 PMUP_MIC MasterIoContext;
194
195 MasterIoContext = ExAllocatePoolWithTag(NonPagedPool, sizeof(MUP_MIC), TAG_MUP);
196 if (MasterIoContext == NULL)
197 {
198 return NULL;
199 }
200
201 MasterIoContext->NodeStatus = NODE_STATUS_HEALTHY;
202 MasterIoContext->NodeReferences = 1;
203 MasterIoContext->NodeType = NODE_TYPE_MIC;
204 MasterIoContext->NodeSize = sizeof(MUP_MIC);
205
206 return MasterIoContext;
207}
208
210MupAllocateUncProvider(ULONG RedirectorDeviceNameLength)
211{
212 PMUP_UNC UncProvider;
213
214 UncProvider = ExAllocatePoolWithTag(PagedPool, sizeof(MUP_UNC) + RedirectorDeviceNameLength, TAG_MUP);
215 if (UncProvider == NULL)
216 {
217 return NULL;
218 }
219
220 UncProvider->NodeReferences = 0;
221 UncProvider->NodeType = NODE_TYPE_UNC;
222 UncProvider->NodeStatus = NODE_STATUS_HEALTHY;
223 UncProvider->NodeSize = sizeof(MUP_UNC) + RedirectorDeviceNameLength;
224 UncProvider->Registered = FALSE;
225
226 return UncProvider;
227}
228
231{
233 ULONG PrefixSize;
234
235 PrefixSize = sizeof(MUP_PFX) + PrefixLength;
237 if (Prefix == NULL)
238 {
239 return NULL;
240 }
241
242 RtlZeroMemory(Prefix, PrefixSize);
243 Prefix->NodeType = NODE_TYPE_PFX;
244 Prefix->NodeStatus = NODE_STATUS_HEALTHY;
245 Prefix->NodeReferences = 1;
246 Prefix->NodeSize = PrefixSize;
247
248 /* If we got a prefix, initialize the string */
249 if (PrefixLength != 0)
250 {
251 Prefix->AcceptedPrefix.Buffer = (PVOID)((ULONG_PTR)Prefix + sizeof(MUP_PFX));
252 Prefix->AcceptedPrefix.Length = PrefixLength;
253 Prefix->AcceptedPrefix.MaximumLength = PrefixLength;
254 }
255 /* Otherwise, mark the fact that the allocation will be external */
256 else
257 {
258 Prefix->ExternalAlloc = TRUE;
259 }
260
261 Prefix->KeepExtraRef = FALSE;
262 /* Already init timeout to have one */
263 MupCalculateTimeout(&Prefix->ValidityTimeout);
264
265 return Prefix;
266}
267
270{
271 PMUP_MQC MasterQueryContext;
272
273 MasterQueryContext = ExAllocatePoolWithTag(NonPagedPool, sizeof(MUP_MQC), TAG_MUP);
274 if (MasterQueryContext == NULL)
275 {
276 return NULL;
277 }
278
279 MasterQueryContext->NodeStatus = NODE_STATUS_HEALTHY;
280 MasterQueryContext->NodeReferences = 1;
281 MasterQueryContext->NodeType = NODE_TYPE_MQC;
282 MasterQueryContext->NodeSize = sizeof(MUP_MQC);
283 InitializeListHead(&MasterQueryContext->QueryPathList);
284 InitializeListHead(&MasterQueryContext->MQCListEntry);
285 ExInitializeResourceLite(&MasterQueryContext->QueryPathListLock);
286
287 return MasterQueryContext;
288}
289
290ULONG
292{
293 ULONG Type;
295
297 *pFcb = FileObject->FsContext;
298 *pCcb = FileObject->FsContext2;
299 Fcb = *pFcb;
300
301 if (Fcb == NULL)
302 {
304 return 0;
305 }
306
307 Type = Fcb->NodeType;
308 if ((Type != NODE_TYPE_VCB && Type != NODE_TYPE_FCB) || (Fcb->NodeStatus != NODE_STATUS_HEALTHY && Fcb->NodeStatus != NODE_STATUS_CLEANUP))
309 {
310 *pFcb = 0;
312 return 0;
313 }
314
315 ++Fcb->NodeReferences;
317
318 return Type;
319}
320
321VOID
323{
325}
326
327VOID
329{
330 /* Just dereference and delete if no references left */
331 if (InterlockedDecrement(&Fcb->NodeReferences) == 0)
332 {
334 }
335}
336
337VOID
339{
340 /* Just dereference and delete (and clean) if no references left */
341 if (InterlockedDecrement(&Ccb->NodeReferences) == 0)
342 {
344 RemoveEntryList(&Ccb->CcbListEntry);
349 }
350}
351
352VOID
354{
355 /* We cannot reach the point where no references are left */
356 if (InterlockedDecrement(&Vcb->NodeReferences) == 0)
357 {
358 KeBugCheckEx(FILE_SYSTEM, 3, 0, 0, 0);
359 }
360}
361
364 PNTSTATUS NewStatus)
365{
366 PIRP Irp;
369
371
372 if (NewStatus != NULL)
373 {
374 /* Save last status, depending on whether it failed or not */
375 if (!NT_SUCCESS(*NewStatus))
376 {
377 MasterIoContext->LastFailed = *NewStatus;
378 }
379 else
380 {
381 MasterIoContext->LastSuccess = STATUS_SUCCESS;
382 }
383 }
384
385 if (InterlockedDecrement(&MasterIoContext->NodeReferences) != 0)
386 {
387 return STATUS_PENDING;
388 }
389
390 Irp = MasterIoContext->Irp;
392 if (Stack->MajorFunction == IRP_MJ_WRITE)
393 {
394 Irp->IoStatus.Information = Stack->Parameters.Write.Length;
395 }
396 else
397 {
398 Irp->IoStatus.Information = 0;
399 }
400
401 /* In case we never had any success (init is a failure), get the last failed status */
402 if (!NT_SUCCESS(MasterIoContext->LastSuccess))
403 {
404 Status = MasterIoContext->LastFailed;
405 }
406
407 Irp->IoStatus.Status = Status;
409 MupDereferenceFcb(MasterIoContext->Fcb);
410 MupFreeNode(MasterIoContext);
411
412 return Status;
413}
414
415VOID
417{
418 InterlockedExchangeAdd(&UncProvider->NodeReferences, -1);
419}
420
421VOID
423{
424 /* Just dereference and delete (and clean) if no references left */
425 if (InterlockedDecrement(&Prefix->NodeReferences) == 0)
426 {
427 if (Prefix->InTable)
428 {
429 RtlRemoveUnicodePrefix(&MupPrefixTable, &Prefix->PrefixTableEntry);
430 RemoveEntryList(&Prefix->PrefixListEntry);
431 }
432
433 if (Prefix->ExternalAlloc && Prefix->AcceptedPrefix.Buffer != NULL)
434 {
435 ExFreePoolWithTag(Prefix->AcceptedPrefix.Buffer, TAG_MUP);
436 }
437
438 if (Prefix->UncProvider)
439 {
440 MupDereferenceUncProvider(Prefix->UncProvider);
441 }
442
444 }
445}
446
447VOID
449{
450 RtlRemoveUnicodePrefix(&MupPrefixTable, &Prefix->PrefixTableEntry);
451 RemoveEntryList(&Prefix->PrefixListEntry);
452 Prefix->InTable = FALSE;
454}
455
456VOID
458{
461
462 /* Browse the prefix table */
466 Entry = Entry->Flink)
467 {
468 Prefix = CONTAINING_RECORD(Entry, MUP_PFX, PrefixListEntry);
469
470 /* And remove any entry in it */
471 if (Prefix->InTable)
472 {
474 }
475 }
477}
478
479VOID
481 PIRP Irp,
483{
485
486 /* Check we're not doing anything wrong first */
487 if (Vcb->NodeStatus != NODE_STATUS_HEALTHY || Vcb->NodeType != NODE_TYPE_VCB)
488 {
490 }
491
492 /* Remove share access */
494
496}
497
498VOID
500 PIRP Irp,
502{
505
507 /* Check we're not doing anything wrong first */
508 if (Fcb->NodeStatus != NODE_STATUS_HEALTHY || Fcb->NodeType != NODE_TYPE_FCB)
509 {
511 }
512 Fcb->NodeStatus = NODE_STATUS_CLEANUP;
514
515 /* Dereference any CCB associated with the FCB */
517 for (Entry = Fcb->CcbList.Flink;
518 Entry != &Fcb->CcbList;
519 Entry = Entry->Flink)
520 {
521 Ccb = CONTAINING_RECORD(Entry, MUP_CCB, CcbListEntry);
525 }
527}
528
531 PIRP Irp,
532 PFORWARDED_IO_CONTEXT FwdCtxt)
533{
535
536 Status = Irp->IoStatus.Status;
537
538 /* Just free everything we had allocated */
539 if (Irp->MdlAddress != NULL)
540 {
541 MmUnlockPages(Irp->MdlAddress);
542 IoFreeMdl(Irp->MdlAddress);
543 }
544
545 if (Irp->Flags & IRP_DEALLOCATE_BUFFER)
546 {
547 ExFreePoolWithTag(Irp->AssociatedIrp.SystemBuffer, TAG_MUP);
548 }
549
550 IoFreeIrp(Irp);
551
552 /* Dereference the master context
553 * The upper IRP will be completed once all the lower IRPs are done
554 * (and thus, references count reaches 0)
555 */
556 MupDereferenceCcb(FwdCtxt->Ccb);
558 ExFreePoolWithTag(FwdCtxt, TAG_MUP);
559
561}
562
563VOID
564NTAPI
566{
568
570}
571
573NTAPI
575 PIRP Irp,
577{
578 PFORWARDED_IO_CONTEXT FwdCtxt;
579
580 /* If we're at DISPATCH_LEVEL, we cannot complete, defer completion */
582 {
584 }
585 else
586 {
588
591 }
592
594}
595
599 PMUP_MIC MasterIoContext)
600{
601 PMDL Mdl;
602 PIRP LowerIrp;
606 PFORWARDED_IO_CONTEXT FwdCtxt;
607
609 LowerIrp = NULL;
610 Mdl = NULL;
611
612 /* Allocate a context for the completion routine */
614 if (FwdCtxt == NULL)
615 {
617 goto Cleanup;
618 }
619
620 /* Init it */
621 FwdCtxt->DeviceObject = NULL;
622 FwdCtxt->Irp = NULL;
623
624 /* Allocate the IRP */
626 LowerIrp = IoAllocateIrp(DeviceObject->StackSize, TRUE);
627 if (LowerIrp == NULL)
628 {
630 goto Cleanup;
631 }
632
633 /* Initialize it */
634 LowerIrp->Tail.Overlay.OriginalFileObject = Ccb->FileObject;
635 LowerIrp->Tail.Overlay.Thread = Irp->Tail.Overlay.Thread;
636 LowerIrp->RequestorMode = KernelMode;
637
638 /* Copy the stack of the request we received to the IRP we'll pass below */
641 Stack->FileObject = Ccb->FileObject;
642 /* Setup flags according to the FO */
643 if (Ccb->FileObject->Flags & FO_WRITE_THROUGH)
644 {
645 Stack->Flags = SL_WRITE_THROUGH;
646 }
647
649 {
650 /* Does the device requires we do buffered IOs? */
651 if (DeviceObject->Flags & DO_BUFFERED_IO)
652 {
653 LowerIrp->AssociatedIrp.SystemBuffer = NULL;
654
655 if (Stack->Parameters.Write.Length == 0)
656 {
657 LowerIrp->Flags = IRP_BUFFERED_IO;
658 }
659 /* If we have data to pass */
660 else
661 {
662 /* If it's coming from usermode, probe first */
663 if (Irp->RequestorMode == UserMode)
664 {
665 ProbeForRead(Irp->UserBuffer, Stack->Parameters.Write.Length, sizeof(UCHAR));
666 }
667
668 /* Allocate the buffer */
669 LowerIrp->AssociatedIrp.SystemBuffer = ExAllocatePoolWithQuotaTag(PagedPoolCacheAligned,
670 Stack->Parameters.Write.Length,
671 TAG_MUP);
672 if (LowerIrp->AssociatedIrp.SystemBuffer == NULL)
673 {
675 }
676
677 /* And copy input (remember, we've to free!) */
678 RtlMoveMemory(LowerIrp->AssociatedIrp.SystemBuffer, Irp->UserBuffer, Stack->Parameters.Write.Length);
679 LowerIrp->Flags = IRP_BUFFERED_IO | IRP_DEALLOCATE_BUFFER;
680 }
681 }
682 else
683 {
684 if (!(DeviceObject->Flags & DO_DIRECT_IO))
685 {
686 LowerIrp->UserBuffer = Irp->UserBuffer;
687 }
688 else
689 {
690 /* For direct IOs, allocate an MDL and pass it */
691 if (Stack->Parameters.Write.Length != 0)
692 {
693 Mdl = IoAllocateMdl(Irp->UserBuffer, Stack->Parameters.Write.Length, FALSE, TRUE, LowerIrp);
694 if (Mdl == NULL)
695 {
697 }
698
699 MmProbeAndLockPages(Mdl, Irp->RequestorMode, IoReadAccess);
700 }
701 }
702 }
703
704 /* Fix flags in the IRP */
706 {
707 LowerIrp->Flags |= IRP_WRITE_OPERATION | IRP_NOCACHE;
708 }
709 else
710 {
711 LowerIrp->Flags |= IRP_WRITE_OPERATION;
712 }
713
714 FwdCtxt->Ccb = Ccb;
715 FwdCtxt->MasterIoContext = MasterIoContext;
716
718 ++MasterIoContext->NodeReferences;
720
721 /* Set out completion routine */
723 /* And call the device with our brand new IRP */
724 Status = IoCallDriver(Ccb->DeviceObject, LowerIrp);
725 }
727 {
729 }
730 _SEH2_END;
731
732Cleanup:
733 if (!NT_SUCCESS(Status))
734 {
735 if (FwdCtxt != NULL)
736 {
737 ExFreePoolWithTag(FwdCtxt, TAG_MUP);
738 }
739
740 if (LowerIrp != NULL)
741 {
742 if (LowerIrp->AssociatedIrp.SystemBuffer == NULL)
743 {
744 ExFreePoolWithTag(LowerIrp->AssociatedIrp.SystemBuffer, TAG_MUP);
745 }
746
747 IoFreeIrp(LowerIrp);
748 }
749
750 if (Mdl != NULL)
751 {
752 IoFreeMdl(Mdl);
753 }
754 }
755
756 return Status;
757}
758
760NTAPI
762 PIRP Irp)
763{
768 PMUP_CCB FcbListCcb;
769 BOOLEAN CcbLockAcquired;
770 PMUP_MIC MasterIoContext;
772
773 /* If DFS is enabled, check if that's for DFS and is so relay */
774 if (MupEnableDfs && DeviceObject->DeviceType == FILE_DEVICE_DFS)
775 {
777 }
778
780
782
783 /* Write request is only possible for a mailslot, we need a FCB */
784 MupDecodeFileObject(Stack->FileObject, &Fcb, &Ccb);
785 if (Fcb == NULL || Fcb->NodeType != NODE_TYPE_FCB)
786 {
789 goto Complete;
790 }
791
792 /* Allocate a context */
793 MasterIoContext = MupAllocateMasterIoContext();
794 if (MasterIoContext == NULL)
795 {
798 goto Complete;
799 }
800
801 /* Mark the IRP pending and init the context */
803 MasterIoContext->Irp = Irp;
804 /* Init with a failure to catch if we ever succeed */
805 MasterIoContext->LastSuccess = STATUS_UNSUCCESSFUL;
806 /* Init with the worth failure possible */
807 MasterIoContext->LastFailed = STATUS_BAD_NETWORK_PATH;
808 MasterIoContext->Fcb = Fcb;
809
811 {
813 CcbLockAcquired = TRUE;
814
815 /* For all the CCB (ie, the mailslots) we have */
816 for (Entry = Fcb->CcbList.Flink;
817 Entry != &Fcb->CcbList;
818 Entry = Entry->Flink)
819 {
820 FcbListCcb = CONTAINING_RECORD(Entry, MUP_CCB, CcbListEntry);
822 CcbLockAcquired = FALSE;
823
825 ++FcbListCcb->NodeReferences;
827
828 /* Forward the write request */
829 BuildAndSubmitIrp(Irp, FcbListCcb, MasterIoContext);
831 CcbLockAcquired = TRUE;
832 }
833
835 CcbLockAcquired = FALSE;
836 }
838 {
839 if (CcbLockAcquired)
840 {
842 }
843 }
844 _SEH2_END;
845
846 /* And done */
847 MupDereferenceMasterIoContext(MasterIoContext, NULL);
849
850 return STATUS_PENDING;
851
853 /* Failure case */
854 Irp->IoStatus.Status = Status;
856 return Status;
857}
858
861 ULONG ProviderOrder)
862{
863 PMUP_UNC UncProvider;
864 ULONG StrLen, NameLen;
865
866 /* Just allocate the node */
867 NameLen = wcslen(DeviceName);
868 StrLen = NameLen * sizeof(WCHAR);
869 UncProvider = MupAllocateUncProvider(StrLen);
870 if (UncProvider == NULL)
871 {
872 return NULL;
873 }
874
875 /* And init it */
876 UncProvider->DeviceName.MaximumLength = StrLen;
877 UncProvider->DeviceName.Length = StrLen;
878 UncProvider->DeviceName.Buffer = (PWSTR)((ULONG_PTR)UncProvider + sizeof(MUP_UNC));
879 UncProvider->ProviderOrder = ProviderOrder;
880 RtlMoveMemory(UncProvider->DeviceName.Buffer, DeviceName, StrLen);
881
882 /* And add it to the global list
883 * We're using tail here so that when called from registry init,
884 * the providers with highest priority will be in the head of
885 * the list
886 */
890
891 return UncProvider;
892}
893
894VOID
896 ULONG ProviderOrder)
897{
903 ULONG NameLen, StrLen, ResultLength;
904
905 /* Get the information about the provider from registry */
906 NameLen = wcslen(ProviderName);
907 StrLen = NameLen * sizeof(WCHAR) + sizeof(L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\") + sizeof(L"\\NetworkProvider");
908 Key.Buffer = ExAllocatePoolWithTag(PagedPool, StrLen, TAG_MUP);
909 if (Key.Buffer == NULL)
910 {
911 return;
912 }
913
914 RtlMoveMemory(Key.Buffer, L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\", sizeof(L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\"));
915 Key.MaximumLength = StrLen;
916 Key.Length = sizeof(L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\") - sizeof(UNICODE_NULL);
917 RtlAppendUnicodeToString(&Key, ProviderName);
918 RtlAppendUnicodeToString(&Key, L"\\NetworkProvider");
919
921 &Key,
923 NULL,
924 NULL);
927 if (!NT_SUCCESS(Status))
928 {
929 return;
930 }
931
932 RtlInitUnicodeString(&Value, L"DeviceName");
935 {
937 if (Info == NULL)
938 {
940 return;
941 }
942
944 }
945 else
946 {
947 Info = NULL;
948 }
949
951
952 /* And create the provider
953 * It will remain unregistered until FsRTL receives a registration request and forwards
954 * it to MUP
955 */
956 if (NT_SUCCESS(Status))
957 {
958 ASSERT(Info != NULL);
959 AddUnregisteredProvider((PWSTR)((ULONG_PTR)Info + Info->DataOffset), ProviderOrder);
960 }
961
962 if (Info != NULL)
963 {
965 }
966}
967
968VOID
970{
971 BOOLEAN End;
974 PWSTR Providers, Coma;
976 ULONG ResultLength, ProviderCount;
978 UNICODE_STRING NetworkProvider, ProviderOrder;
979
980 /* Open the registry to get the order of the providers */
981 RtlInitUnicodeString(&NetworkProvider, L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\NetworkProvider\\Order");
983 &NetworkProvider,
985 NULL,
986 NULL);
988 if (!NT_SUCCESS(Status))
989 {
990 return;
991 }
992
993 RtlInitUnicodeString(&ProviderOrder, L"ProviderOrder");
994 Status = ZwQueryValueKey(KeyHandle, &ProviderOrder, KeyValueFullInformation, NULL, 0, &ResultLength);
996 {
998 if (Info == NULL)
999 {
1001 return;
1002 }
1003
1004 Status = ZwQueryValueKey(KeyHandle, &ProviderOrder, KeyValueFullInformation, Info, ResultLength, &ResultLength);
1005 }
1006 else
1007 {
1008 Info = NULL;
1009 }
1010
1012
1013 if (NT_SUCCESS(Status))
1014 {
1015 ASSERT(Info != NULL);
1016
1017 Providers = (PWSTR)((ULONG_PTR)Info + Info->DataOffset);
1018 End = FALSE;
1019 ProviderCount = 0;
1020
1021 /* For all the providers we got (coma-separated list), just create a provider node with the right order
1022 * The order is just the order of the list
1023 * First has highest priority (0) and then, get lower and lower priority
1024 * The highest number is the lowest priority
1025 */
1026 do
1027 {
1028 Coma = wcschr(Providers, L',');
1029 if (Coma != NULL)
1030 {
1031 *Coma = UNICODE_NULL;
1032 }
1033 else
1034 {
1035 End = TRUE;
1036 }
1037
1038 InitializeProvider(Providers, ProviderCount);
1039 ++ProviderCount;
1040
1041 Providers = Coma + 1;
1042 } while (!End);
1043 }
1044
1045 if (Info != NULL)
1046 {
1048 }
1049}
1050
1053{
1055 PMUP_UNC UncProvider;
1056
1057 /* Browse the list of all the providers nodes we have */
1060 {
1061 UncProvider = CONTAINING_RECORD(Entry, MUP_UNC, ProviderListEntry);
1062
1063 /* If one matches the device and is not registered, that's ours! */
1064 if (!UncProvider->Registered && RtlEqualUnicodeString(RedirectorDeviceName, &UncProvider->DeviceName, TRUE))
1065 {
1066 UncProvider->NodeStatus = NODE_STATUS_HEALTHY;
1067 break;
1068 }
1069 }
1070
1071 if (Entry == &MupProviderList)
1072 {
1073 UncProvider = NULL;
1074 }
1076
1077 return UncProvider;
1078}
1079
1082 PIRP Irp)
1083
1084{
1085 BOOLEAN New;
1086 PMUP_FCB Fcb;
1087 PMUP_CCB Ccb;
1092 PMUP_UNC UncProvider, ListEntry;
1095 OBJECT_HANDLE_INFORMATION HandleInfo;
1097
1098 DPRINT1("RegisterUncProvider(%p, %p)\n", DeviceObject, Irp);
1099 New = FALSE;
1100
1101 /* Check whether providers order was already initialized */
1104 {
1106 }
1107 else
1108 {
1109 /* They weren't, so do it */
1113 }
1114
1116
1117 /* This can only happen with a volume open */
1118 if (MupDecodeFileObject(Stack->FileObject, &Fcb, &Ccb) != NODE_TYPE_VCB)
1119 {
1120 Irp->IoStatus.Status = STATUS_INVALID_HANDLE;
1122
1123 return STATUS_INVALID_HANDLE;
1124 }
1125
1126 /* Get the registration information */
1127 RegInfo = (PMUP_PROVIDER_REGISTRATION_INFO)Irp->AssociatedIrp.SystemBuffer;
1128 _SEH2_TRY
1129 {
1133
1134 /* Have we got already a node for it? (Like from previous init) */
1136 if (UncProvider == NULL)
1137 {
1138 /* If we don't, allocate a new one */
1139 New = TRUE;
1140 UncProvider = MupAllocateUncProvider(RegInfo->RedirectorDeviceNameLength);
1141 if (UncProvider == NULL)
1142 {
1145 }
1146
1147 /* Set it up */
1150 UncProvider->DeviceName.Buffer = (PWSTR)((ULONG_PTR)UncProvider + sizeof(MUP_UNC));
1151
1152 /* As it wasn't in registry for order, give the lowest priority possible */
1153 UncProvider->ProviderOrder = MAXLONG;
1155 }
1156
1157 /* Continue registration */
1158 UncProvider->MailslotsSupported = RegInfo->MailslotsSupported;
1159 ++UncProvider->NodeReferences;
1160
1161 /* Open a handle to the device */
1163 &UncProvider->DeviceName,
1165 NULL,
1166 NULL);
1167 Status = NtOpenFile(&UncProvider->DeviceHandle,
1173 if (NT_SUCCESS(Status))
1174 {
1176 }
1177
1178 /* And return the provider (as CCB) */
1179 if (NT_SUCCESS(Status))
1180 {
1181 Stack->FileObject->FsContext2 = UncProvider;
1182 Status = ObReferenceObjectByHandle(UncProvider->DeviceHandle, 0, NULL, KernelMode, (PVOID *)&UncProvider->FileObject, &HandleInfo);
1183 if (!NT_SUCCESS(Status))
1184 {
1185 NtClose(UncProvider->DeviceHandle);
1186 }
1187 }
1188
1189 if (!NT_SUCCESS(Status))
1190 {
1191 MupDereferenceUncProvider(UncProvider);
1192 }
1193 else
1194 {
1195 UncProvider->DeviceObject = IoGetRelatedDeviceObject(UncProvider->FileObject);
1196
1197 /* Now, insert the provider in our global list
1198 * They are sorted by order
1199 */
1202 if (New)
1203 {
1205 {
1206 ListEntry = CONTAINING_RECORD(Entry, MUP_UNC, ProviderListEntry);
1207
1208 if (UncProvider->ProviderOrder < ListEntry->ProviderOrder)
1209 {
1210 break;
1211 }
1212 }
1213
1214 InsertTailList(Entry, &UncProvider->ProviderListEntry);
1215 }
1216 UncProvider->Registered = TRUE;
1219
1220 DPRINT1("UNC provider %wZ registered\n", &UncProvider->DeviceName);
1221 }
1222 }
1224 {
1226 {
1228 }
1229
1231
1232 Irp->IoStatus.Status = Status;
1234 }
1235 _SEH2_END;
1236
1237 return Status;
1238}
1239
1241NTAPI
1243 PIRP Irp)
1244{
1247
1249
1250 _SEH2_TRY
1251 {
1252 /* MUP only understands a single FSCTL code: registering UNC provider */
1253 if (Stack->Parameters.FileSystemControl.FsControlCode == FSCTL_MUP_REGISTER_PROVIDER)
1254 {
1255 /* It obviously has to come from a driver/kernelmode thread */
1256 if (Irp->RequestorMode == UserMode)
1257 {
1259
1260 Irp->IoStatus.Status = Status;
1262
1264 }
1265
1267 }
1268 else
1269 {
1270 /* If that's an unknown FSCTL code, maybe it's for DFS, pass it */
1271 if (!MupEnableDfs)
1272 {
1274
1275 Irp->IoStatus.Status = Status;
1277
1279 }
1280
1282 }
1283 }
1285 {
1287 }
1288 _SEH2_END;
1289
1290 return Status;
1291}
1292
1293VOID
1295 PMUP_FCB Fcb,
1296 PMUP_CCB Ccb)
1297{
1298 FileObject->FsContext = Fcb;
1299 FileObject->FsContext2 = Ccb;
1300}
1301
1304 PMUP_UNC UncProvider)
1305{
1306 PWSTR FullPath;
1308
1309 DPRINT("Rerouting %wZ with %wZ\n", &FileObject->FileName, &UncProvider->DeviceName);
1310
1311 /* Get the full path name (device name first, and requested file name appended) */
1312 TotalLength = UncProvider->DeviceName.Length + FileObject->FileName.Length;
1313 if (TotalLength > MAXUSHORT)
1314 {
1315 return STATUS_NAME_TOO_LONG;
1316 }
1317
1318 /* Allocate a buffer big enough */
1320 if (FullPath == NULL)
1321 {
1323 }
1324
1325 /* Create the full path */
1326 RtlMoveMemory(FullPath, UncProvider->DeviceName.Buffer, UncProvider->DeviceName.Length);
1327 RtlMoveMemory((PWSTR)((ULONG_PTR)FullPath + UncProvider->DeviceName.Length), FileObject->FileName.Buffer, FileObject->FileName.Length);
1328
1329 /* And redo the path in the file object */
1330 ExFreePoolWithTag(FileObject->FileName.Buffer, 0);
1331 FileObject->FileName.Buffer = FullPath;
1332 FileObject->FileName.MaximumLength = TotalLength;
1333 FileObject->FileName.Length = FileObject->FileName.MaximumLength;
1334
1335 /* Ob, please reparse to open the correct file at the right place, thanks! :-) */
1336 return STATUS_REPARSE;
1337}
1338
1341{
1342 PMUP_FCB Fcb;
1343 HANDLE Handle;
1345 PMUP_CCB Ccb = NULL;
1346 PMUP_UNC UncProvider;
1347 UNICODE_STRING FullPath;
1350 NTSTATUS Status, LastFailed;
1351 ULONG TotalLength, LastOrder;
1354 OBJECT_HANDLE_INFORMATION HandleInfo;
1355 BOOLEAN Locked, Referenced, CcbInitialized;
1356
1357 Fcb = MupCreateFcb();
1358 if (Fcb == NULL)
1359 {
1361 }
1362
1364 FileObject = Stack->FileObject;
1365 Locked = FALSE;
1366 Referenced = FALSE;
1367 CcbInitialized = FALSE;
1368 LastFailed = STATUS_NO_SUCH_FILE;
1369 LastOrder = (ULONG)-1;
1370
1371 _SEH2_TRY
1372 {
1374 Locked = TRUE;
1375
1376 /* Associate our FCB with the FO */
1379
1380 /* Now, broadcast the open to any UNC provider that supports mailslots */
1382 {
1383 UncProvider = CONTAINING_RECORD(Entry, MUP_UNC, ProviderListEntry);
1384 ++UncProvider->NodeReferences;
1385 Referenced = TRUE;
1386
1388 Locked = FALSE;
1389
1390 TotalLength = UncProvider->DeviceName.Length + FileObject->FileName.Length;
1391 if (UncProvider->MailslotsSupported && TotalLength <= MAXUSHORT)
1392 {
1393 /* Provide the correct name for the mailslot (ie, happened the device name of the provider) */
1395 if (FullPath.Buffer == NULL)
1396 {
1398 }
1399
1400 FullPath.Length = TotalLength;
1401 FullPath.MaximumLength = TotalLength;
1402 RtlMoveMemory(FullPath.Buffer, UncProvider->DeviceName.Buffer, UncProvider->DeviceName.Length);
1403 RtlMoveMemory((PWSTR)((ULONG_PTR)FullPath.Buffer + UncProvider->DeviceName.Length),
1404 FileObject->FileName.Buffer,
1405 FileObject->FileName.Length);
1406
1407 /* And just forward the creation request */
1409 &FullPath,
1411 NULL,
1412 NULL);
1414 Stack->Parameters.Create.SecurityContext->DesiredAccess & FILE_SIMPLE_RIGHTS_MASK,
1417 NULL,
1418 Stack->Parameters.Create.FileAttributes & FILE_ATTRIBUTE_VALID_FLAGS,
1419 Stack->Parameters.Create.ShareAccess & FILE_SHARE_VALID_FLAGS,
1420 FILE_OPEN,
1421 Stack->Parameters.Create.Options & FILE_VALID_SET_FLAGS,
1422 NULL,
1423 0,
1425 NULL,
1427
1428 ExFreePoolWithTag(FullPath.Buffer, TAG_MUP);
1429
1430 /* If opening succeed */
1431 if (NT_SUCCESS(Status))
1432 {
1434
1435 /* Create a CCB */
1436 Ccb = MupCreateCcb();
1437 if (Ccb == NULL)
1438 {
1440 }
1441
1442 /* And associated a FO to it */
1443 if (NT_SUCCESS(Status))
1444 {
1445 Status = ObReferenceObjectByHandle(Handle, 0, 0, 0, (PVOID *)&Ccb->FileObject, &HandleInfo);
1446 ZwClose(Handle);
1447 }
1448 }
1449
1450 /* If we failed, remember the last failed status of the higher priority provider */
1451 if (!NT_SUCCESS(Status))
1452 {
1453 if (UncProvider->ProviderOrder <= LastOrder)
1454 {
1455 LastOrder = UncProvider->ProviderOrder;
1456 LastFailed = Status;
1457 }
1458 }
1459 /* Otherwise, properly attach our CCB to the mailslot */
1460 else
1461 {
1462 Ccb->DeviceObject = IoGetRelatedDeviceObject(Ccb->FileObject);
1463 Ccb->Fcb = Fcb;
1464
1466 Locked = TRUE;
1467 ++Fcb->NodeReferences;
1469 Locked = FALSE;
1470 CcbInitialized = TRUE;
1471
1472 InsertTailList(&Fcb->CcbList, &Ccb->CcbListEntry);
1473 }
1474 }
1475
1477 Locked = TRUE;
1478 MupDereferenceUncProvider(UncProvider);
1479 Referenced = FALSE;
1480 }
1481
1483 Locked = FALSE;
1484 }
1486 {
1488 }
1489 _SEH2_END;
1490
1491 /* If we at least opened one mailslot, return success */
1492 Status = (CcbInitialized ? STATUS_SUCCESS : LastFailed);
1493
1494 if (Referenced)
1495 {
1496 MupDereferenceUncProvider(UncProvider);
1497 }
1498
1499 if (Locked)
1500 {
1502 }
1503
1504 /* In case of failure, don't leak CCB */
1505 if (!NT_SUCCESS(Status) && Ccb != NULL)
1506 {
1508 }
1509
1510 return Status;
1511}
1512
1513PIRP
1515 PVOID Context,
1519 ULONG InputBufferSize,
1521 ULONG OutputBufferSize,
1523{
1524 PIRP Irp;
1527
1528 if (InputBuffer == NULL)
1529 {
1530 return NULL;
1531 }
1532
1533 /* Get the device object */
1535 /* Allocate the IRP (with one more location for us */
1536 Irp = IoAllocateIrp(DeviceObject->StackSize + 1, FALSE);
1537 if (Irp == NULL)
1538 {
1539 return NULL;
1540 }
1541
1542 /* Skip our location */
1544 /* Setup the IRP */
1545 Irp->Tail.Overlay.OriginalFileObject = FileObject;
1546 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
1548
1549 /* Setup the stack */
1551 Stack->MajorFunction = MajorFunction;
1552 Stack->Parameters.DeviceIoControl.OutputBufferLength = OutputBufferSize;
1553 Stack->Parameters.DeviceIoControl.InputBufferLength = InputBufferSize;
1554 Stack->Parameters.DeviceIoControl.IoControlCode = IoctlCode;
1555 Stack->MinorFunction = 0;
1556 Stack->FileObject = FileObject;
1557 Stack->DeviceObject = DeviceObject;
1558
1560 {
1561 case METHOD_BUFFERED:
1562 /* If it's buffered, just pass the buffers we got */
1563 Irp->MdlAddress = NULL;
1564 Irp->AssociatedIrp.SystemBuffer = InputBuffer;
1565 Irp->UserBuffer = OutputBuffer;
1566 Irp->Flags = IRP_BUFFERED_IO;
1567
1568 if (OutputBuffer != NULL)
1569 {
1570 Irp->Flags |= IRP_INPUT_OPERATION;
1571 }
1572 break;
1573
1574 case METHOD_IN_DIRECT:
1575 case METHOD_OUT_DIRECT:
1576 /* Otherwise, allocate an MDL */
1577 if (IoAllocateMdl(InputBuffer, InputBufferSize, FALSE, FALSE, Irp) == NULL)
1578 {
1579 IoFreeIrp(Irp);
1580 return NULL;
1581 }
1582
1583 Irp->AssociatedIrp.SystemBuffer = InputBuffer;
1584 Irp->Flags = IRP_BUFFERED_IO;
1586 break;
1587
1588 case METHOD_NEITHER:
1589 /* Or pass the buffers */
1590 Irp->UserBuffer = OutputBuffer;
1591 Irp->MdlAddress = NULL;
1592 Irp->AssociatedIrp.SystemBuffer = NULL;
1593 Stack->Parameters.DeviceIoControl.Type3InputBuffer = InputBuffer;
1594 break;
1595 }
1596
1597 return Irp;
1598}
1599
1600VOID
1602{
1603 ExDeleteResourceLite(&MasterQueryContext->QueryPathListLock);
1604 ExFreePoolWithTag(MasterQueryContext, TAG_MUP);
1605}
1606
1609{
1610 LONG References;
1612 BOOLEAN KeepExtraRef;
1613
1615 --MasterQueryContext->NodeReferences;
1616 References = MasterQueryContext->NodeReferences;
1618
1619 if (References != 0)
1620 {
1621 DPRINT("Still having refs (%ld)\n", References);
1622 return STATUS_PENDING;
1623 }
1624
1625 /* We HAVE an IRP to complete. It cannot be NULL
1626 * Please, help preserving kittens, don't provide NULL IRPs.
1627 */
1628 if (MasterQueryContext->Irp == NULL)
1629 {
1631 }
1632
1634 RemoveEntryList(&MasterQueryContext->MQCListEntry);
1636
1638 KeepExtraRef = MasterQueryContext->Prefix->KeepExtraRef;
1639 MupDereferenceKnownPrefix(MasterQueryContext->Prefix);
1640
1641 /* We found a provider? */
1642 if (MasterQueryContext->LatestProvider != NULL)
1643 {
1644 /* With a successful status? */
1645 if (MasterQueryContext->LatestStatus == STATUS_SUCCESS)
1646 {
1647 /* Then, it's time to reroute, someone accepted to handle the file creation request! */
1648 if (!KeepExtraRef)
1649 {
1650 MupDereferenceKnownPrefix(MasterQueryContext->Prefix);
1651 }
1652
1654 /* Reroute & complete :-) */
1655 Status = MupRerouteOpen(MasterQueryContext->FileObject, MasterQueryContext->LatestProvider);
1656 goto Complete;
1657 }
1658 else
1659 {
1660 MupDereferenceUncProvider(MasterQueryContext->LatestProvider);
1661 }
1662 }
1663
1664 MupDereferenceKnownPrefix(MasterQueryContext->Prefix);
1666
1667 /* Return the highest failed status we had */
1668 Status = MasterQueryContext->LatestStatus;
1669
1670Complete:
1671 /* In finally, complete the IRP for real! */
1672 MasterQueryContext->Irp->IoStatus.Status = Status;
1673 IoCompleteRequest(MasterQueryContext->Irp, IO_DISK_INCREMENT);
1674
1675 MasterQueryContext->Irp = NULL;
1676 MupFreeMasterQueryContext(MasterQueryContext);
1677
1678 return Status;
1679}
1680
1682NTAPI
1684 PIRP Irp,
1685 PVOID Context)
1686{
1688 ULONG LatestPos, Pos;
1689 PWSTR AcceptedPrefix;
1690 PMUP_MQC MasterQueryContext;
1691 NTSTATUS Status, TableStatus;
1692 PQUERY_PATH_CONTEXT QueryContext;
1693 PQUERY_PATH_RESPONSE QueryResponse;
1694
1695 /* Get all the data from our query to the provider */
1696 QueryContext = (PQUERY_PATH_CONTEXT)Context;
1697 QueryResponse = (PQUERY_PATH_RESPONSE)QueryContext->QueryPathRequest;
1698 MasterQueryContext = QueryContext->MasterQueryContext;
1699 Status = Irp->IoStatus.Status;
1700
1701 DPRINT("Reply from %wZ: %u (Status: %lx)\n", &QueryContext->UncProvider->DeviceName, QueryResponse->LengthAccepted, Status);
1702
1704 RemoveEntryList(&QueryContext->QueryPathListEntry);
1705
1706 /* If the driver returned a success, and an acceptance length */
1707 if (NT_SUCCESS(Status) && QueryResponse->LengthAccepted > 0)
1708 {
1709 Prefix = MasterQueryContext->Prefix;
1710
1711 /* Check if we already found a provider from a previous iteration */
1712 if (MasterQueryContext->LatestProvider != NULL)
1713 {
1714 /* If the current provider has a lower priority (ie, a greater order), then, bailout and keep previous one */
1715 if (QueryContext->UncProvider->ProviderOrder >= MasterQueryContext->LatestProvider->ProviderOrder)
1716 {
1718 goto Cleanup;
1719 }
1720
1721 /* Otherwise, if the prefix was in the prefix table, just drop it:
1722 * we have a provider which supersedes the accepted prefix, so leave
1723 * room for the new prefix/provider
1724 */
1726 if (Prefix->InTable)
1727 {
1728 RtlRemoveUnicodePrefix(&MupPrefixTable, &Prefix->PrefixTableEntry);
1729 RemoveEntryList(&Prefix->PrefixListEntry);
1730 Prefix->InTable = FALSE;
1731 }
1733
1734 Prefix->KeepExtraRef = FALSE;
1735
1736 /* Release data associated with the current prefix, if any
1737 * We'll renew them with the new accepted prefix
1738 */
1739 if (Prefix->AcceptedPrefix.Length != 0 && Prefix->AcceptedPrefix.Buffer != NULL)
1740 {
1741 ExFreePoolWithTag(Prefix->AcceptedPrefix.Buffer, TAG_MUP);
1742 Prefix->AcceptedPrefix.MaximumLength = 0;
1743 Prefix->AcceptedPrefix.Length = 0;
1744 Prefix->AcceptedPrefix.Buffer = NULL;
1745 Prefix->ExternalAlloc = FALSE;
1746 }
1747
1748 /* If there was also a provider, drop it, the new one
1749 * is different
1750 */
1751 if (Prefix->UncProvider != NULL)
1752 {
1753 MupDereferenceUncProvider(Prefix->UncProvider);
1754 Prefix->UncProvider = NULL;
1755 }
1756 }
1757
1758 /* Now, set our information about the provider that accepted the prefix */
1759 MasterQueryContext->LatestProvider = QueryContext->UncProvider;
1760 MasterQueryContext->LatestStatus = Status;
1761
1762 if (MasterQueryContext->FileObject->FsContext2 != (PVOID)DFS_DOWNLEVEL_OPEN_CONTEXT)
1763 {
1764 /* Allocate a buffer for the prefix */
1765 AcceptedPrefix = ExAllocatePoolWithTag(PagedPool, QueryResponse->LengthAccepted, TAG_MUP);
1766 if (AcceptedPrefix == NULL)
1767 {
1768 Prefix->InTable = FALSE;
1769 }
1770 else
1771 {
1772 /* Set it up to the accepted length */
1773 RtlMoveMemory(AcceptedPrefix, MasterQueryContext->FileObject->FileName.Buffer, QueryResponse->LengthAccepted);
1774 Prefix->UncProvider = MasterQueryContext->LatestProvider;
1775 Prefix->AcceptedPrefix.Buffer = AcceptedPrefix;
1776 Prefix->AcceptedPrefix.Length = QueryResponse->LengthAccepted;
1777 Prefix->AcceptedPrefix.MaximumLength = QueryResponse->LengthAccepted;
1778 Prefix->ExternalAlloc = TRUE;
1779
1780 /* Insert the accepted prefix in the table of known prefixes */
1781 DPRINT("%wZ accepted %wZ\n", &Prefix->UncProvider->DeviceName, &Prefix->AcceptedPrefix);
1783 if (RtlInsertUnicodePrefix(&MupPrefixTable, &Prefix->AcceptedPrefix, &Prefix->PrefixTableEntry))
1784 {
1785 InsertHeadList(&MupPrefixList, &Prefix->PrefixListEntry);
1786 Prefix->InTable = TRUE;
1787 Prefix->KeepExtraRef = TRUE;
1788 }
1789 else
1790 {
1791 Prefix->InTable = FALSE;
1792 }
1794 }
1795 }
1796 }
1797 else
1798 {
1800
1801 /* We failed and didn't find any provider over the latest iterations */
1802 if (MasterQueryContext->LatestProvider == NULL)
1803 {
1804 /* If we had a success though (broken provider?) set our failed status */
1805 if (NT_SUCCESS(MasterQueryContext->LatestStatus))
1806 {
1807 MasterQueryContext->LatestStatus = Status;
1808 }
1809 else
1810 {
1811 TableStatus = MupOrderedErrorList[0];
1812 LatestPos = 0;
1813
1814 /* Otherwise, time to compare statuses, between the latest failed
1815 * and the current failure.
1816 * We have an order table of failed status: the deeper you go in the
1817 * table, the more the error is critical.
1818 * Our goal is to return the most critical status that was returned by
1819 * any of the providers
1820 */
1821
1822 /* Look for latest status position */
1823 while (TableStatus != 0 && TableStatus != MasterQueryContext->LatestStatus)
1824 {
1825 ++LatestPos;
1826 TableStatus = MupOrderedErrorList[LatestPos];
1827 }
1828
1829 /* If at pos 0, the new status is likely more critical */
1830 if (LatestPos == 0)
1831 {
1832 MasterQueryContext->LatestStatus = Status;
1833 }
1834 else
1835 {
1836 /* Otherwise, find position of the new status in the table */
1837 Pos = 0;
1838 do
1839 {
1841 {
1842 break;
1843 }
1844
1845 ++Pos;
1846 }
1847 while (Pos < LatestPos);
1848
1849 /* If it has a higher position (more critical), return it */
1850 if (Pos >= LatestPos)
1851 {
1852 MasterQueryContext->LatestStatus = Status;
1853 }
1854 }
1855 }
1856 }
1857 }
1858
1859Cleanup:
1860 ExFreePoolWithTag(QueryResponse, TAG_MUP);
1861 ExFreePoolWithTag(QueryContext, TAG_MUP);
1862 IoFreeIrp(Irp);
1863
1864 ExReleaseResourceLite(&MasterQueryContext->QueryPathListLock);
1865 MupDereferenceMasterQueryContext(MasterQueryContext);
1866
1868}
1869
1873 PIO_SECURITY_CONTEXT SecurityContext)
1874{
1875 LONG Len;
1876 WCHAR Cur;
1877 PWSTR Name;
1878 PIRP QueryIrp;
1882 PMUP_UNC UncProvider;
1884 LARGE_INTEGER CurrentTime;
1885 PMUP_MQC MasterQueryContext;
1886 PQUERY_PATH_CONTEXT QueryContext;
1887 PQUERY_PATH_REQUEST QueryPathRequest;
1889 BOOLEAN Locked, Referenced, BreakOnFirst;
1890
1891 /* We cannot open a file without a name */
1892 if (FileObject->FileName.Length == 0)
1893 {
1894 Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
1896
1898 }
1899
1900 DPRINT("Request for opening: %wZ\n", &FileObject->FileName);
1901
1902 Referenced = FALSE;
1903 BreakOnFirst = TRUE;
1905
1907 /* First, try to see if that's a prefix we already know */
1909 if (TableEntry != NULL)
1910 {
1912
1913 DPRINT("Matching prefix found: %wZ\n", &Prefix->AcceptedPrefix);
1914
1915 /* If so, check whether the prefix is still valid */
1916 KeQuerySystemTime(&CurrentTime);
1917 if (Prefix->ValidityTimeout.QuadPart < CurrentTime.QuadPart)
1918 {
1919 /* It is: so, update its validity period and reroute file opening */
1920 MupCalculateTimeout(&Prefix->ValidityTimeout);
1921 Status = MupRerouteOpen(FileObject, Prefix->UncProvider);
1923
1924 if (Status == STATUS_REPARSE)
1925 {
1926 Irp->IoStatus.Information = FILE_SUPERSEDED;
1927 }
1928
1929 Irp->IoStatus.Status = Status;
1931
1932 return Status;
1933 }
1934
1935 /* When here, we found a matching prefix, but expired, remove it from the table
1936 * We'll redo a full search
1937 */
1938 if (Prefix->InTable)
1939 {
1941 }
1942 }
1944
1946 /* First of all, start looking for a mailslot */
1947 if (FileObject->FileName.Buffer[0] == L'\\' && Stack->MajorFunction != IRP_MJ_CREATE)
1948 {
1949 Name = &FileObject->FileName.Buffer[1];
1950 Len = FileObject->FileName.Length;
1951
1952 /* Skip the remote destination name */
1953 do
1954 {
1955 Len -= sizeof(WCHAR);
1956 if (Len <= 0)
1957 {
1958 break;
1959 }
1960
1961 Cur = *Name;
1962 ++Name;
1963 } while (Cur != L'\\');
1964 Len -= sizeof(WCHAR);
1965
1966 /* If we still have room for "Mailslot" to fit */
1967 if (Len >= (sizeof(L"Mailslot") - sizeof(UNICODE_NULL)))
1968 {
1969 /* Get the len in terms of chars count */
1970 Len /= sizeof(WCHAR);
1971 if (Len > ((sizeof(L"Mailslot") - sizeof(UNICODE_NULL)) / sizeof(WCHAR)))
1972 {
1973 Len = (sizeof(L"Mailslot") - sizeof(UNICODE_NULL)) / sizeof(WCHAR);
1974 }
1975
1976 /* It's indeed a mailslot opening! */
1977 if (_wcsnicmp(Name, L"Mailslot", Len) == 0)
1978 {
1979 /* Broadcast open */
1981 if (Status == STATUS_REPARSE)
1982 {
1983 Irp->IoStatus.Information = FILE_SUPERSEDED;
1984 }
1985
1986 Irp->IoStatus.Status = Status;
1988
1989 return Status;
1990 }
1991 }
1992 }
1993
1994 /* Ok, at that point, that's a regular MUP opening (if no DFS) */
1996 {
1997 /* We won't complete immediately */
1999
2000 /* Allocate a new prefix for our search */
2002 if (Prefix == NULL)
2003 {
2004 Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
2006
2007 return STATUS_PENDING;
2008 }
2009
2010 /* Allocate a context for our search */
2011 MasterQueryContext = MupAllocateMasterQueryContext();
2012 if (MasterQueryContext == NULL)
2013 {
2015
2016 Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
2018
2019 return STATUS_PENDING;
2020 }
2021
2022 MasterQueryContext->Irp = Irp;
2023 MasterQueryContext->FileObject = FileObject;
2024 MasterQueryContext->LatestProvider = NULL;
2025 MasterQueryContext->Prefix = Prefix;
2026 MasterQueryContext->LatestStatus = STATUS_BAD_NETWORK_PATH;
2028 InsertTailList(&MupMasterQueryList, &MasterQueryContext->MQCListEntry);
2029 ++Prefix->NodeReferences;
2031
2032 _SEH2_TRY
2033 {
2035 Locked = TRUE;
2036
2037 /* Now, we will browse all the providers we know, to ask for their accepted prefix regarding the path */
2039 {
2040 UncProvider = CONTAINING_RECORD(Entry, MUP_UNC, ProviderListEntry);
2041
2042 ++UncProvider->NodeReferences;
2043 Referenced = TRUE;
2044
2046 Locked = FALSE;
2047
2048 /* We will obviously only query registered providers */
2049 if (UncProvider->Registered)
2050 {
2051 /* We will issue an IOCTL_REDIR_QUERY_PATH, so allocate input buffer */
2052 QueryPathRequest = ExAllocatePoolWithTag(PagedPool, FileObject->FileName.Length + sizeof(QUERY_PATH_REQUEST), TAG_MUP);
2053 if (QueryPathRequest == NULL)
2054 {
2056 }
2057
2058 /* Allocate a context for IRP completion routine
2059 * In case a prefix matches the path, the reroute will happen
2060 * in the completion routine, when we have return from the provider
2061 */
2063 if (QueryContext == NULL)
2064 {
2065 ExFreePoolWithTag(QueryPathRequest, TAG_MUP);
2067 }
2068
2069 InitializeListHead(&QueryContext->QueryPathListEntry);
2070 QueryContext->MasterQueryContext = MasterQueryContext;
2071 QueryContext->QueryPathRequest = QueryPathRequest;
2072 QueryPathRequest->PathNameLength = FileObject->FileName.Length;
2073 QueryPathRequest->SecurityContext = SecurityContext;
2074 RtlMoveMemory(QueryPathRequest->FilePathName, FileObject->FileName.Buffer, FileObject->FileName.Length);
2075
2076 /* Build our IRP for the query */
2077 QueryIrp = MupBuildIoControlRequest(UncProvider->FileObject,
2078 QueryContext,
2081 QueryPathRequest,
2082 FileObject->FileName.Length + sizeof(QUERY_PATH_REQUEST),
2083 QueryPathRequest,
2084 sizeof(QUERY_PATH_RESPONSE),
2086 if (QueryIrp == NULL)
2087 {
2088 ExFreePoolWithTag(QueryContext, TAG_MUP);
2089 ExFreePoolWithTag(QueryPathRequest, TAG_MUP);
2091 }
2092
2093 QueryIrp->RequestorMode = KernelMode;
2094 QueryContext->UncProvider = UncProvider;
2095 QueryContext->Irp = QueryIrp;
2096
2098 ++UncProvider->NodeReferences;
2099 ++MasterQueryContext->NodeReferences;
2101
2103 InsertTailList(&MasterQueryContext->QueryPathList, &QueryContext->QueryPathListEntry);
2104 ExReleaseResourceLite(&MasterQueryContext->QueryPathListLock);
2105
2106 /* Query the provider !*/
2107 DPRINT("Requesting UNC provider: %wZ\n", &UncProvider->DeviceName);
2108 DPRINT("Calling: %wZ\n", &UncProvider->DeviceObject->DriverObject->DriverName);
2109 Status = IoCallDriver(UncProvider->DeviceObject, QueryIrp);
2110 }
2111
2113 Locked = TRUE;
2114
2115 /* We're done with that provider */
2116 MupDereferenceUncProvider(UncProvider);
2117 Referenced = FALSE;
2118
2119 /* If query went fine on the first request, just break and leave */
2120 if (BreakOnFirst && Status == STATUS_SUCCESS)
2121 {
2122 break;
2123 }
2124
2125 BreakOnFirst = FALSE;
2126 }
2127 }
2129 {
2131 {
2132 MasterQueryContext->LatestStatus = STATUS_INSUFFICIENT_RESOURCES;
2133 }
2134
2135 if (Referenced)
2136 {
2137 MupDereferenceUncProvider(UncProvider);
2138 }
2139
2140 if (Locked)
2141 {
2143 }
2144
2145 MupDereferenceMasterQueryContext(MasterQueryContext);
2146
2148 }
2149 _SEH2_END;
2150 }
2151 else
2152 {
2155 }
2156
2157 return Status;
2158}
2159
2165{
2167
2168 DPRINT1("Opening MUP\n");
2169
2171 _SEH2_TRY
2172 {
2173 /* Update share access, increase reference count, and associated VCB to the FO, that's it! */
2175 if (NT_SUCCESS(Status))
2176 {
2177 ++Vcb->NodeReferences;
2180 }
2181 }
2183 {
2185 }
2186 _SEH2_END;
2187
2188 return Status;
2189}
2190
2192NTAPI
2194 PIRP Irp)
2195{
2198 PFILE_OBJECT FileObject, RelatedFileObject;
2199
2201
2202 _SEH2_TRY
2203 {
2204 /* If DFS is enabled, check if that's for DFS and is so relay */
2205 if (MupEnableDfs && (DeviceObject->DeviceType == FILE_DEVICE_DFS || DeviceObject->DeviceType == FILE_DEVICE_DFS_FILE_SYSTEM))
2206 {
2208 }
2209 else
2210 {
2212 FileObject = Stack->FileObject;
2213 RelatedFileObject = FileObject->RelatedFileObject;
2214
2215 /* If we have a file name or if the associated FCB of the related FO isn't the VCB, then, it's a regular opening */
2216 if (FileObject->FileName.Length != 0 || (RelatedFileObject != NULL && ((PMUP_FCB)(RelatedFileObject->FsContext))->NodeType != NODE_TYPE_VCB))
2217 {
2218 Status = CreateRedirectedFile(Irp, FileObject, Stack->Parameters.Create.SecurityContext);
2219 }
2220 /* Otherwise, it's just a volume open */
2221 else
2222 {
2223 Status = OpenMupFileSystem(DeviceObject->DeviceExtension,
2224 FileObject,
2225 Stack->Parameters.Create.SecurityContext->DesiredAccess,
2226 Stack->Parameters.Create.ShareAccess);
2227
2228 Irp->IoStatus.Information = FILE_OPENED;
2229 Irp->IoStatus.Status = Status;
2231 }
2232 }
2233 }
2235 {
2237
2238 Irp->IoStatus.Status = Status;
2240 }
2241 _SEH2_END;
2242
2244
2245 return Status;
2246}
2247
2248VOID
2250{
2252
2253 /* If the node was still valid, reregister the UNC provider */
2254 if (UncProvider->NodeStatus == NODE_STATUS_HEALTHY)
2255 {
2256 UncProvider->NodeStatus = NODE_STATUS_CLEANUP;
2257 UncProvider->Registered = FALSE;
2259
2260 if (UncProvider->FileObject != NULL)
2261 {
2262 ZwClose(UncProvider->DeviceHandle);
2263 ObDereferenceObject(UncProvider->FileObject);
2264 }
2265 }
2266 else
2267 {
2269 }
2270}
2271
2273NTAPI
2275 PIRP Irp)
2276{
2277 ULONG Type;
2278 PMUP_FCB Fcb;
2279 PMUP_CCB Ccb;
2282
2283 /* If DFS is enabled, check if that's for DFS and is so relay */
2284 if (MupEnableDfs)
2285 {
2286 if (DeviceObject->DeviceType == FILE_DEVICE_DFS || DeviceObject->DeviceType == FILE_DEVICE_DFS_FILE_SYSTEM)
2287 {
2289 }
2290 }
2291
2293
2294 _SEH2_TRY
2295 {
2297 Type = MupDecodeFileObject(Stack->FileObject, &Fcb, &Ccb);
2298 switch (Type)
2299 {
2300 case NODE_TYPE_VCB:
2301 /* If we got a VCB, clean it up */
2303
2304 Irp->IoStatus.Status = STATUS_SUCCESS;
2306
2308
2309 /* If Ccb is not null, then, it's a UNC provider node */
2310 if (Ccb)
2311 {
2312 /* Close it, and dereference */
2318 }
2319
2321 break;
2322
2323 case NODE_TYPE_FCB:
2324 /* If the node wasn't already cleaned, do it */
2325 if (Fcb->NodeStatus == NODE_STATUS_HEALTHY)
2326 {
2329 }
2330 else
2331 {
2333 }
2334
2335 Irp->IoStatus.Status = STATUS_SUCCESS;
2337
2339 break;
2340
2341 default:
2343
2344 Irp->IoStatus.Status = Status;
2346
2347 break;
2348 }
2349 }
2351 {
2353 }
2354 _SEH2_END;
2355
2357
2358 return Status;
2359}
2360
2363 PIRP Irp,
2364 PMUP_VCB Vcb,
2366{
2368
2369 /* Remove FCB, UNC from FO */
2372
2374
2375 return STATUS_SUCCESS;
2376}
2377
2380 PIRP Irp,
2381 PMUP_FCB Fcb,
2383{
2385
2386 /* Remove FCB, CCB from FO */
2389
2391
2392 return STATUS_SUCCESS;
2393}
2394
2396NTAPI
2398 PIRP Irp)
2399{
2400 PMUP_FCB Fcb;
2401 PMUP_CCB Ccb;
2404
2405 /* If DFS is enabled, check if that's for DFS and is so relay */
2406 if (MupEnableDfs)
2407 {
2408 if (DeviceObject->DeviceType == FILE_DEVICE_DFS || DeviceObject->DeviceType == FILE_DEVICE_DFS_FILE_SYSTEM)
2409 {
2410 return DfsFsdClose(DeviceObject, Irp);
2411 }
2412 }
2413
2415
2416 _SEH2_TRY
2417 {
2418 /* Get our internal structures from FO */
2420 MupDecodeFileObject(Stack->FileObject, &Fcb, &Ccb);
2421 if (Fcb == NULL)
2422 {
2424
2425 Irp->IoStatus.Status = Status;
2427
2429 }
2430
2431 /* If we got the VCB, that's a volume close */
2432 if (Fcb->NodeType == NODE_TYPE_VCB)
2433 {
2435 }
2436 /* Otherwise close the FCB */
2437 else if (Fcb->NodeType == NODE_TYPE_FCB)
2438 {
2441 }
2442 else
2443 {
2445
2446 Irp->IoStatus.Status = Status;
2448
2450 }
2451
2452 Irp->IoStatus.Status = STATUS_SUCCESS;
2454 }
2456 {
2458 }
2459 _SEH2_END;
2460
2462
2463 return Status;
2464}
2465
2466VOID
2467NTAPI
2469{
2471
2472 if (MupEnableDfs)
2473 {
2475 }
2476
2478}
2479
2480/*
2481 * FUNCTION: Called by the system to initialize the driver
2482 * ARGUMENTS:
2483 * DriverObject = object describing this driver
2484 * RegistryPath = path to our configuration entries
2485 * RETURNS: Success or failure
2486 */
2487CODE_SEG("INIT")
2489NTAPI
2492{
2494 UNICODE_STRING MupString;
2496
2497 /* Only initialize global state of the driver
2498 * Other inits will happen when required
2499 */
2501
2502 /* Check if DFS is disabled */
2504 /* If it's not disabled but when cannot init, disable it */
2506 {
2508 }
2509
2510 /* Create the MUP device */
2511 RtlInitUnicodeString(&MupString, L"\\Device\\Mup");
2513 if (!NT_SUCCESS(Status))
2514 {
2515 if (MupEnableDfs)
2516 {
2518 }
2519
2521
2522 return Status;
2523 }
2524
2525 /* Set our MJ */
2526 DriverObject->DriverUnload = MupUnload;
2527 DriverObject->MajorFunction[IRP_MJ_CREATE] = MupCreate;
2532 DriverObject->MajorFunction[IRP_MJ_CLEANUP] = MupCleanup;
2533 DriverObject->MajorFunction[IRP_MJ_CLOSE] = MupClose;
2534
2535 /* And finish init */
2537 MupInitializeVcb(DeviceObject->DeviceExtension);
2538
2539 return STATUS_SUCCESS;
2540}
unsigned char BOOLEAN
Type
Definition: Type.h:7
struct NameRec_ * Name
Definition: cdprocs.h:460
#define InterlockedDecrement
Definition: armddk.h:52
LONG NTSTATUS
Definition: precomp.h:26
#define FILE_DIRECTORY_FILE
Definition: constants.h:491
#define DPRINT1
Definition: precomp.h:8
#define UNIMPLEMENTED
Definition: debug.h:115
DECLSPEC_NORETURN VOID NTAPI KeBugCheck(ULONG BugCheckCode)
Definition: bug.c:1431
_In_ PFCB Fcb
Definition: cdprocs.h:159
_Inout_ PFILE_OBJECT _In_ TYPE_OF_OPEN PFCB _In_opt_ PCCB Ccb
Definition: cdprocs.h:592
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:36
_In_ PIRP Irp
Definition: csq.h:116
#define Len
Definition: deflate.h:82
ush Pos
Definition: deflate.h:92
#define DFS_DOWNLEVEL_OPEN_CONTEXT
Definition: dfs.h:7
#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
#define wcschr
Definition: compat.h:17
#define FILE_SHARE_READ
Definition: compat.h:136
static const WCHAR Cleanup[]
Definition: register.c:80
DRIVER_INITIALIZE DriverEntry
Definition: condrv.c:21
_In_ PIO_STACK_LOCATION _Inout_ PFILE_OBJECT _Inout_ PVCB _Outptr_result_maybenull_ PDCB _In_ PDCB _In_ PDIRENT _In_ ULONG _In_ ULONG _In_ PUNICODE_STRING _In_ PACCESS_MASK _In_ USHORT ShareAccess
Definition: create.c:4147
NTSTATUS DfsFsdClose(PDEVICE_OBJECT DeviceObject, PIRP Irp)
Definition: dfs.c:68
NTSTATUS DfsDriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
Definition: dfs.c:83
NTSTATUS DfsFsdCleanup(PDEVICE_OBJECT DeviceObject, PIRP Irp)
Definition: dfs.c:60
NTSTATUS DfsFsdCreate(PDEVICE_OBJECT DeviceObject, PIRP Irp)
Definition: dfs.c:52
NTSTATUS DfsFsdFileSystemControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
Definition: dfs.c:45
VOID DfsUnload(PDRIVER_OBJECT DriverObject)
Definition: dfs.c:76
NTSTATUS NTAPI DfsVolumePassThrough(PDEVICE_OBJECT DeviceObject, PIRP Irp)
Definition: dfs.c:38
#define ULONG_PTR
Definition: config.h:101
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define InsertTailList(ListHead, Entry)
#define InsertHeadList(ListHead, Entry)
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define DO_BUFFERED_IO
Definition: env_spec_w32.h:394
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
NTSTATUS ExInitializeResourceLite(PULONG res)
Definition: env_spec_w32.h:641
NTSTATUS RtlAppendUnicodeToString(IN PUNICODE_STRING Str1, IN PWSTR Str2)
Definition: string_lib.cpp:62
#define KeQuerySystemTime(t)
Definition: env_spec_w32.h:570
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
#define DO_DIRECT_IO
Definition: env_spec_w32.h:396
#define ExAcquireResourceExclusiveLite(res, wait)
Definition: env_spec_w32.h:615
#define ExDeleteResourceLite(res)
Definition: env_spec_w32.h:647
#define NonPagedPool
Definition: env_spec_w32.h:307
ULONG ERESOURCE
Definition: env_spec_w32.h:594
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
#define PagedPool
Definition: env_spec_w32.h:308
VOID NTAPI ProbeForRead(IN CONST VOID *Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:102
#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
#define FILE_OPEN
Definition: from_kernel.h:54
#define FsRtlEnterFileSystem
#define FsRtlExitFileSystem
#define IoFreeMdl
Definition: fxmdl.h:89
#define IoAllocateMdl
Definition: fxmdl.h:88
pRequest Complete(RequestStatus)
ULONG Handle
Definition: gdb_input.c:15
Status
Definition: gdiplustypes.h:25
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
#define OBJ_KERNEL_HANDLE
Definition: winternl.h:231
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
#define InterlockedExchangeAdd
Definition: interlocked.h:181
IoMarkIrpPending(Irp)
#define IoSetCompletionRoutine(_Irp, _CompletionRoutine, _Context, _InvokeOnSuccess, _InvokeOnError, _InvokeOnCancel)
Definition: irp.cpp:490
static CODE_SEG("PAGE")
Definition: isapnp.c:1482
VOID NTAPI MmProbeAndLockPages(IN PMDL Mdl, IN KPROCESSOR_MODE AccessMode, IN LOCK_OPERATION Operation)
Definition: mdlsup.c:931
VOID NTAPI MmUnlockPages(IN PMDL Mdl)
Definition: mdlsup.c:1435
#define ASSERT(a)
Definition: mode.c:44
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
* PNTSTATUS
Definition: strlen.c:14
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
BOOLEAN MupOrderInitialized
Definition: mup.c:45
NTSTATUS MupOrderedErrorList[]
Definition: mup.c:48
VOID MupGetProviderInformation(VOID)
Definition: mup.c:969
PMUP_MIC MupAllocateMasterIoContext(VOID)
Definition: mup.c:191
PMUP_UNC MupCheckForUnregisteredProvider(PUNICODE_STRING RedirectorDeviceName)
Definition: mup.c:1052
VOID MupCalculateTimeout(PLARGE_INTEGER EntryTime)
Definition: mup.c:142
ERESOURCE MupPrefixTableLock
Definition: mup.c:36
PMUP_PFX MupAllocatePrefixEntry(ULONG PrefixLength)
Definition: mup.c:230
PDEVICE_OBJECT mupDeviceObject
Definition: mup.c:47
NTSTATUS NTAPI MupCreate(PDEVICE_OBJECT DeviceObject, PIRP Irp)
Definition: mup.c:2193
VOID MupSetFileObject(PFILE_OBJECT FileObject, PMUP_FCB Fcb, PMUP_CCB Ccb)
Definition: mup.c:1294
ULONG MupProviderCount
Definition: mup.c:44
VOID MupRemoveKnownPrefixEntry(PMUP_PFX Prefix)
Definition: mup.c:448
LIST_ENTRY MupMasterQueryList
Definition: mup.c:41
NTSTATUS MupCloseFcb(PDEVICE_OBJECT DeviceObject, PIRP Irp, PMUP_FCB Fcb, PFILE_OBJECT FileObject)
Definition: mup.c:2379
NTSTATUS NTAPI ForwardedIoCompletionRoutine(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context)
Definition: mup.c:574
NTSTATUS NTAPI MupFsControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
Definition: mup.c:1242
VOID NTAPI DeferredForwardedIoCompletionRoutine(PVOID Context)
Definition: mup.c:565
PMUP_MQC MupAllocateMasterQueryContext(VOID)
Definition: mup.c:269
VOID MupCleanupFcb(PDEVICE_OBJECT DeviceObject, PIRP Irp, PMUP_FCB Fcb)
Definition: mup.c:499
VOID MupUninitializeData()
Definition: mup.c:74
VOID MupInitializeVcb(PMUP_VCB Vcb)
Definition: mup.c:84
ERESOURCE MupGlobalLock
Definition: mup.c:35
LIST_ENTRY MupProviderList
Definition: mup.c:39
PMUP_UNC AddUnregisteredProvider(PCWSTR DeviceName, ULONG ProviderOrder)
Definition: mup.c:860
NTSTATUS CommonForwardedIoCompletionRoutine(PDEVICE_OBJECT DeviceObject, PIRP Irp, PFORWARDED_IO_CONTEXT FwdCtxt)
Definition: mup.c:530
VOID MupCleanupVcb(PDEVICE_OBJECT DeviceObject, PIRP Irp, PMUP_VCB Vcb)
Definition: mup.c:480
VOID MupDereferenceCcb(PMUP_CCB Ccb)
Definition: mup.c:338
NTSTATUS MupCloseVcb(PDEVICE_OBJECT DeviceObject, PIRP Irp, PMUP_VCB Vcb, PFILE_OBJECT FileObject)
Definition: mup.c:2362
NTSTATUS BuildAndSubmitIrp(PIRP Irp, PMUP_CCB Ccb, PMUP_MIC MasterIoContext)
Definition: mup.c:597
ERESOURCE MupVcbLock
Definition: mup.c:38
LIST_ENTRY MupPrefixList
Definition: mup.c:40
ERESOURCE MupCcbListLock
Definition: mup.c:37
BOOLEAN MupEnableDfs
Definition: mup.c:46
NTSTATUS CreateRedirectedFile(PIRP Irp, PFILE_OBJECT FileObject, PIO_SECURITY_CONTEXT SecurityContext)
Definition: mup.c:1871
PMUP_CCB MupCreateCcb(VOID)
Definition: mup.c:152
NTSTATUS NTAPI QueryPathCompletionRoutine(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context)
Definition: mup.c:1683
NTSTATUS MupDereferenceMasterQueryContext(PMUP_MQC MasterQueryContext)
Definition: mup.c:1608
PMUP_UNC MupAllocateUncProvider(ULONG RedirectorDeviceNameLength)
Definition: mup.c:210
VOID MupFreeMasterQueryContext(PMUP_MQC MasterQueryContext)
Definition: mup.c:1601
VOID MupInvalidatePrefixTable(VOID)
Definition: mup.c:457
VOID NTAPI MupUnload(PDRIVER_OBJECT DriverObject)
Definition: mup.c:2468
NTSTATUS NTAPI MupForwardIoRequest(PDEVICE_OBJECT DeviceObject, PIRP Irp)
Definition: mup.c:761
NTSTATUS MupRerouteOpen(PFILE_OBJECT FileObject, PMUP_UNC UncProvider)
Definition: mup.c:1303
NTSTATUS OpenMupFileSystem(PMUP_VCB Vcb, PFILE_OBJECT FileObject, ACCESS_MASK DesiredAccess, USHORT ShareAccess)
Definition: mup.c:2161
LARGE_INTEGER MupKnownPrefixTimeout
Definition: mup.c:43
NTSTATUS NTAPI MupClose(PDEVICE_OBJECT DeviceObject, PIRP Irp)
Definition: mup.c:2397
BOOLEAN MuppIsDfsEnabled(VOID)
Definition: mup.c:94
PIRP MupBuildIoControlRequest(PFILE_OBJECT FileObject, PVOID Context, ULONG MajorFunction, ULONG IoctlCode, PVOID InputBuffer, ULONG InputBufferSize, PVOID OutputBuffer, ULONG OutputBufferSize, PIO_COMPLETION_ROUTINE CompletionRoutine)
Definition: mup.c:1514
VOID MupDereferenceFcb(PMUP_FCB Fcb)
Definition: mup.c:328
UNICODE_PREFIX_TABLE MupPrefixTable
Definition: mup.c:42
NTSTATUS MupDereferenceMasterIoContext(PMUP_MIC MasterIoContext, PNTSTATUS NewStatus)
Definition: mup.c:363
NTSTATUS BroadcastOpen(PIRP Irp)
Definition: mup.c:1340
VOID MupDereferenceUncProvider(PMUP_UNC UncProvider)
Definition: mup.c:416
ULONG MupDecodeFileObject(PFILE_OBJECT FileObject, PMUP_FCB *pFcb, PMUP_CCB *pCcb)
Definition: mup.c:291
VOID MupDereferenceKnownPrefix(PMUP_PFX Prefix)
Definition: mup.c:422
VOID InitializeProvider(PCWSTR ProviderName, ULONG ProviderOrder)
Definition: mup.c:895
VOID MupDereferenceVcb(PMUP_VCB Vcb)
Definition: mup.c:353
VOID MupFreeNode(PVOID Node)
Definition: mup.c:322
PMUP_FCB MupCreateFcb(VOID)
Definition: mup.c:171
VOID MupInitializeData(VOID)
Definition: mup.c:58
NTSTATUS RegisterUncProvider(PDEVICE_OBJECT DeviceObject, PIRP Irp)
Definition: mup.c:1081
VOID MupCloseUncProvider(PMUP_UNC UncProvider)
Definition: mup.c:2249
NTSTATUS NTAPI MupCleanup(PDEVICE_OBJECT DeviceObject, PIRP Irp)
Definition: mup.c:2274
struct _QUERY_PATH_CONTEXT * PQUERY_PATH_CONTEXT
struct _FORWARDED_IO_CONTEXT * PFORWARDED_IO_CONTEXT
#define NODE_TYPE_CCB
Definition: mup.h:21
#define NODE_TYPE_PFX
Definition: mup.h:19
#define NODE_TYPE_UNC
Definition: mup.h:18
#define NODE_TYPE_MIC
Definition: mup.h:22
struct _MUP_UNC MUP_UNC
#define NODE_STATUS_CLEANUP
Definition: mup.h:26
struct _MUP_PFX MUP_PFX
#define FILE_SIMPLE_RIGHTS_MASK
Definition: mup.h:15
struct _MUP_VCB MUP_VCB
#define NODE_TYPE_FCB
Definition: mup.h:20
#define NODE_STATUS_HEALTHY
Definition: mup.h:25
struct _MUP_CCB MUP_CCB
#define TAG_MUP
Definition: mup.h:13
#define NODE_TYPE_VCB
Definition: mup.h:17
#define IO_METHOD_FROM_CTL_CODE(C)
Definition: mup.h:11
#define NODE_TYPE_MQC
Definition: mup.h:23
struct _MUP_MIC MUP_MIC
struct _MUP_FCB MUP_FCB
struct _MUP_MQC MUP_MQC
#define FSCTL_MUP_REGISTER_PROVIDER
Definition: muptypes.h:12
struct _MUP_PROVIDER_REGISTRATION_INFO * PMUP_PROVIDER_REGISTRATION_INFO
_Must_inspect_result_ _Out_ PNDIS_STATUS _In_ NDIS_HANDLE _In_ ULONG _Out_ PNDIS_STRING _Out_ PNDIS_HANDLE KeyHandle
Definition: ndis.h:4715
#define KernelMode
Definition: asm.h:34
#define UserMode
Definition: asm.h:35
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
_In_ PMEMORY_AREA _In_ PVOID _In_ BOOLEAN Locked
Definition: newmm.h:209
NTSYSAPI NTSTATUS NTAPI NtOpenFile(OUT PHANDLE phFile, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, OUT PIO_STATUS_BLOCK pIoStatusBlock, IN ULONG ShareMode, IN ULONG OpenMode)
Definition: file.c:3952
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
#define METHOD_NEITHER
Definition: nt_native.h:597
#define FILE_ATTRIBUTE_VALID_FLAGS
Definition: nt_native.h:714
@ KeyValuePartialInformation
Definition: nt_native.h:1182
@ KeyValueFullInformation
Definition: nt_native.h:1181
ULONG ACCESS_MASK
Definition: nt_native.h:40
#define KEY_READ
Definition: nt_native.h:1023
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
NTSYSAPI BOOLEAN NTAPI RtlEqualUnicodeString(PUNICODE_STRING String1, PUNICODE_STRING String2, BOOLEAN CaseInSensitive)
#define KEY_QUERY_VALUE
Definition: nt_native.h:1016
#define FILE_SHARE_VALID_FLAGS
Definition: nt_native.h:683
#define FILE_SUPERSEDED
Definition: nt_native.h:768
#define FILE_TRAVERSE
Definition: nt_native.h:643
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3402
#define METHOD_OUT_DIRECT
Definition: nt_native.h:596
#define METHOD_BUFFERED
Definition: nt_native.h:594
#define FILE_OPENED
Definition: nt_native.h:769
#define FILE_VALID_SET_FLAGS
Definition: nt_native.h:762
#define METHOD_IN_DIRECT
Definition: nt_native.h:595
#define UNICODE_NULL
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
#define IOCTL_REDIR_QUERY_PATH
struct _QUERY_PATH_RESPONSE * PQUERY_PATH_RESPONSE
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1822
#define ExRaiseStatus
Definition: ntoskrnl.h:114
NTSTATUS NTAPI IoCreateDevice(IN PDRIVER_OBJECT DriverObject, IN ULONG DeviceExtensionSize, IN PUNICODE_STRING DeviceName, IN DEVICE_TYPE DeviceType, IN ULONG DeviceCharacteristics, IN BOOLEAN Exclusive, OUT PDEVICE_OBJECT *DeviceObject)
Definition: device.c:1031
PDEVICE_OBJECT NTAPI IoGetRelatedDeviceObject(IN PFILE_OBJECT FileObject)
Definition: device.c:1539
VOID NTAPI IoDeleteDevice(IN PDEVICE_OBJECT DeviceObject)
Definition: device.c:1251
NTSTATUS NTAPI IoCreateFile(OUT PHANDLE FileHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, OUT PIO_STATUS_BLOCK IoStatusBlock, IN PLARGE_INTEGER AllocationSize OPTIONAL, IN ULONG FileAttributes, IN ULONG ShareAccess, IN ULONG Disposition, IN ULONG CreateOptions, IN PVOID EaBuffer OPTIONAL, IN ULONG EaLength, IN CREATE_FILE_TYPE CreateFileType, IN PVOID ExtraCreateParameters OPTIONAL, IN ULONG Options)
Definition: file.c:3010
NTSTATUS NTAPI IoCheckShareAccess(IN ACCESS_MASK DesiredAccess, IN ULONG DesiredShareAccess, IN PFILE_OBJECT FileObject, IN PSHARE_ACCESS ShareAccess, IN BOOLEAN Update)
Definition: file.c:3390
VOID NTAPI IoRemoveShareAccess(IN PFILE_OBJECT FileObject, IN PSHARE_ACCESS ShareAccess)
Definition: file.c:3478
#define IoCompleteRequest
Definition: irp.c:1240
PIRP NTAPI IoAllocateIrp(IN CCHAR StackSize, IN BOOLEAN ChargeQuota)
Definition: irp.c:615
#define IoCallDriver
Definition: irp.c:1225
VOID NTAPI IoFreeIrp(IN PIRP Irp)
Definition: irp.c:1666
#define STATUS_INVALID_HANDLE
Definition: ntstatus.h:245
#define STATUS_REPARSE
Definition: ntstatus.h:83
#define STATUS_BAD_NETWORK_NAME
Definition: ntstatus.h:440
#define STATUS_PENDING
Definition: ntstatus.h:82
#define STATUS_BAD_NETWORK_PATH
Definition: ntstatus.h:426
#define STATUS_REDIRECTOR_NOT_STARTED
Definition: ntstatus.h:487
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:239
#define STATUS_NAME_TOO_LONG
Definition: ntstatus.h:498
#define L(x)
Definition: ntvdm.h:50
NTSTATUS NTAPI ObReferenceObjectByHandle(IN HANDLE Handle, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, OUT PVOID *Object, OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL)
Definition: obref.c:494
long LONG
Definition: pedump.c:60
unsigned short USHORT
Definition: pedump.c:61
#define Vcb
Definition: cdprocs.h:1415
#define FILE_DEVICE_DFS
Definition: winioctl.h:112
#define FILE_DEVICE_DFS_FILE_SYSTEM
Definition: winioctl.h:159
#define FILE_DEVICE_MULTI_UNC_PROVIDER
Definition: winioctl.h:122
#define _SEH2_AbnormalTermination()
Definition: pseh2_64.h:160
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:159
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:34
#define IRP_MJ_CLOSE
Definition: rdpdr.c:45
#define IRP_MJ_DEVICE_CONTROL
Definition: rdpdr.c:52
#define IRP_MJ_WRITE
Definition: rdpdr.c:47
#define IRP_MJ_CREATE
Definition: rdpdr.c:44
#define New(t)
Definition: rtf.h:1086
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
#define REG_DWORD
Definition: sdbapi.c:596
_Check_return_ _CRTIMP int __cdecl _wcsnicmp(_In_reads_or_z_(_MaxCount) const wchar_t *_Str1, _In_reads_or_z_(_MaxCount) const wchar_t *_Str2, _In_ size_t _MaxCount)
#define STATUS_MORE_PROCESSING_REQUIRED
Definition: shellext.h:68
#define STATUS_SUCCESS
Definition: shellext.h:65
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
#define DPRINT
Definition: sndvol32.h:71
base of all file and directory entries
Definition: entries.h:83
struct _FCB::@720::@723 Fcb
PFILE_OBJECT FileObject
Definition: ntfs.h:520
PMUP_CCB Ccb
Definition: mup.h:123
WORK_QUEUE_ITEM WorkQueueItem
Definition: mup.h:125
PMUP_MIC MasterIoContext
Definition: mup.h:124
PDEVICE_OBJECT DeviceObject
Definition: mup.h:126
IO_STATUS_BLOCK IoStatus
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
Definition: mup.h:48
LONG NodeReferences
Definition: mup.h:51
Definition: mup.h:38
Definition: mup.h:60
ULONG NodeSize
Definition: mup.h:64
LONG NodeReferences
Definition: mup.h:63
ULONG NodeStatus
Definition: mup.h:62
PIRP Irp
Definition: mup.h:65
PMUP_FCB Fcb
Definition: mup.h:68
ULONG NodeType
Definition: mup.h:61
NTSTATUS LastFailed
Definition: mup.h:67
NTSTATUS LastSuccess
Definition: mup.h:66
Definition: mup.h:106
LONG NodeReferences
Definition: mup.h:109
PFILE_OBJECT FileObject
Definition: mup.h:112
PMUP_UNC LatestProvider
Definition: mup.h:113
ULONG NodeSize
Definition: mup.h:110
NTSTATUS LatestStatus
Definition: mup.h:116
PMUP_PFX Prefix
Definition: mup.h:115
PIRP Irp
Definition: mup.h:111
LIST_ENTRY MQCListEntry
Definition: mup.h:118
LIST_ENTRY QueryPathList
Definition: mup.h:117
ULONG NodeType
Definition: mup.h:107
ERESOURCE QueryPathListLock
Definition: mup.h:114
ULONG NodeStatus
Definition: mup.h:108
Definition: mup.h:88
BOOLEAN KeepExtraRef
Definition: mup.h:100
Definition: mup.h:72
LIST_ENTRY ProviderListEntry
Definition: mup.h:77
HANDLE DeviceHandle
Definition: mup.h:79
BOOLEAN Registered
Definition: mup.h:84
PFILE_OBJECT FileObject
Definition: mup.h:81
BOOLEAN MailslotsSupported
Definition: mup.h:83
LONG NodeReferences
Definition: mup.h:75
PDEVICE_OBJECT DeviceObject
Definition: mup.h:80
ULONG NodeStatus
Definition: mup.h:74
ULONG NodeType
Definition: mup.h:73
ULONG NodeSize
Definition: mup.h:76
UNICODE_STRING DeviceName
Definition: mup.h:78
ULONG ProviderOrder
Definition: mup.h:82
Definition: mup.h:29
PMUP_UNC UncProvider
Definition: mup.h:133
PMUP_MQC MasterQueryContext
Definition: mup.h:132
PQUERY_PATH_REQUEST QueryPathRequest
Definition: mup.h:134
LIST_ENTRY QueryPathListEntry
Definition: mup.h:135
PIO_SECURITY_CONTEXT SecurityContext
unsigned short Length
Definition: sprintf.c:451
void * Buffer
Definition: sprintf.c:453
unsigned short MaximumLength
Definition: sprintf.c:452
Definition: rtltypes.h:627
USHORT MaximumLength
Definition: env_spec_w32.h:370
uint16_t * PWSTR
Definition: typedefs.h:56
const uint16_t * PCWSTR
Definition: typedefs.h:57
#define NTAPI
Definition: typedefs.h:36
void * PVOID
Definition: typedefs.h:50
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define MAXUSHORT
Definition: typedefs.h:83
uint32_t ULONG_PTR
Definition: typedefs.h:65
#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 STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
#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_NO_SUCH_FILE
Definition: udferr_usr.h:137
#define STATUS_INVALID_USER_BUFFER
Definition: udferr_usr.h:166
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define MAXLONG
Definition: umtypes.h:116
UNICODE_STRING RedirectorDeviceName
Definition: unc.c:23
VOID NTAPI RtlRemoveUnicodePrefix(PUNICODE_PREFIX_TABLE PrefixTable, PUNICODE_PREFIX_TABLE_ENTRY PrefixTableEntry)
BOOLEAN NTAPI RtlInsertUnicodePrefix(PUNICODE_PREFIX_TABLE PrefixTable, PUNICODE_STRING Prefix, PUNICODE_PREFIX_TABLE_ENTRY PrefixTableEntry)
PUNICODE_PREFIX_TABLE_ENTRY NTAPI RtlFindUnicodePrefix(PUNICODE_PREFIX_TABLE PrefixTable, PUNICODE_STRING FullName, ULONG CaseInsensitiveIndex)
VOID NTAPI RtlInitializeUnicodePrefix(PUNICODE_PREFIX_TABLE PrefixTable)
LONGLONG QuadPart
Definition: typedefs.h:114
Definition: dlist.c:348
_In_ ULONG TotalLength
Definition: usbdlib.h:158
_Must_inspect_result_ _In_ WDFCHILDLIST _In_ PWDF_CHILD_LIST_ITERATOR _Out_ WDFDEVICE _Inout_opt_ PWDF_CHILD_RETRIEVE_INFO Info
Definition: wdfchildlist.h:690
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
_Must_inspect_result_ _In_ WDFDEVICE _In_ DEVICE_REGISTRY_PROPERTY _In_ ULONG _Out_ PULONG ResultLength
Definition: wdfdevice.h:3776
_Must_inspect_result_ _In_ WDFDEVICE _In_ ULONG _In_ ACCESS_MASK DesiredAccess
Definition: wdfdevice.h:2658
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:550
_In_ UCHAR MajorFunction
Definition: wdfdevice.h:1697
_Must_inspect_result_ _In_ WDFDEVICE _In_ PCUNICODE_STRING KeyName
Definition: wdfdevice.h:2699
_Must_inspect_result_ _In_ PWDFDEVICE_INIT _In_opt_ PCUNICODE_STRING DeviceName
Definition: wdfdevice.h:3275
_In_ WDFDEVICE _In_ PVOID _In_opt_ PMDL Mdl
_Must_inspect_result_ _In_ PDRIVER_OBJECT _In_ PCUNICODE_STRING RegistryPath
Definition: wdfdriver.h:215
_Must_inspect_result_ _In_ PDRIVER_OBJECT DriverObject
Definition: wdfdriver.h:213
_Must_inspect_result_ _In_ WDFIOTARGET _In_opt_ WDFREQUEST _In_opt_ PWDF_MEMORY_DESCRIPTOR OutputBuffer
Definition: wdfiotarget.h:863
_Must_inspect_result_ _In_ WDFIOTARGET _In_opt_ WDFREQUEST _In_ ULONG IoctlCode
Definition: wdfiotarget.h:1043
_Must_inspect_result_ _In_ WDFIOTARGET _In_opt_ WDFREQUEST _In_opt_ PWDF_MEMORY_DESCRIPTOR InputBuffer
Definition: wdfiotarget.h:953
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
Definition: wdfregistry.h:413
_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
VOID NTAPI ExQueueWorkItem(IN PWORK_QUEUE_ITEM WorkItem, IN WORK_QUEUE_TYPE QueueType)
Definition: work.c:723
#define ExInitializeWorkItem(Item, Routine, Context)
Definition: exfuncs.h:265
#define ExAllocatePoolWithQuotaTag(a, b, c)
Definition: exfuncs.h:530
@ CriticalWorkQueue
Definition: extypes.h:189
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetNextIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2695
FORCEINLINE VOID IoSetNextIrpStackLocation(_Inout_ PIRP Irp)
Definition: iofuncs.h:2680
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2793
#define IRP_DEALLOCATE_BUFFER
#define IRP_INPUT_OPERATION
#define IRP_MJ_CREATE_NAMED_PIPE
#define IRP_MJ_CREATE_MAILSLOT
#define IO_NO_PARAMETER_CHECKING
Definition: iotypes.h:541
#define IRP_MJ_FILE_SYSTEM_CONTROL
#define IRP_WRITE_OPERATION
#define FO_WRITE_THROUGH
Definition: iotypes.h:1779
IO_COMPLETION_ROUTINE * PIO_COMPLETION_ROUTINE
Definition: iotypes.h:2835
_Must_inspect_result_ typedef _In_ ULONG TableEntry
Definition: iotypes.h:4303
* PFILE_OBJECT
Definition: iotypes.h:1998
#define IO_DISK_INCREMENT
Definition: iotypes.h:600
#define FO_NO_INTERMEDIATE_BUFFERING
Definition: iotypes.h:1778
@ CreateFileTypeNone
Definition: iotypes.h:535
#define SL_WRITE_THROUGH
Definition: iotypes.h:1824
#define IRP_BUFFERED_IO
#define IRP_NOCACHE
#define IRP_MJ_CLEANUP
@ PagedPoolCacheAligned
Definition: ketypes.h:883
@ IoReadAccess
Definition: ketypes.h:863
#define ObDereferenceObject
Definition: obfuncs.h:203
_In_ __drv_aliasesMem PSTRING Prefix
Definition: rtlfuncs.h:1630
_In_ __drv_aliasesMem PSTRING _Out_ PPREFIX_TABLE_ENTRY PrefixTableEntry
Definition: rtlfuncs.h:1631
unsigned char UCHAR
Definition: xmlstorage.h:181
__wchar_t WCHAR
Definition: xmlstorage.h:180