[RDBSS]
[reactos.git] / reactos / sdk / lib / drivers / rdbsslib / rdbss.c
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/rdbsslib/rdbss.c
23 * PURPOSE: RDBSS library
24 * PROGRAMMER: Pierre Schweitzer (pierre@reactos.org)
25 */
26
27 /* INCLUDES *****************************************************************/
28
29 #include <rx.h>
30 #include <pseh/pseh2.h>
31 #include <limits.h>
32 #include <dfs.h>
33
34 #define NDEBUG
35 #include <debug.h>
36
37 #define RX_TOPLEVELCTX_FLAG_FROM_POOL 1
38
39 typedef
40 NTSTATUS
41 (NTAPI *PRX_FSD_DISPATCH) (
42 PRX_CONTEXT Context);
43
44 typedef struct _RX_FSD_DISPATCH_VECTOR
45 {
46 PRX_FSD_DISPATCH CommonRoutine;
47 } RX_FSD_DISPATCH_VECTOR, *PRX_FSD_DISPATCH_VECTOR;
48
49 VOID
50 NTAPI
51 RxAcquireFileForNtCreateSection(
52 PFILE_OBJECT FileObject);
53
54 NTSTATUS
55 NTAPI
56 RxAcquireForCcFlush(
57 PFILE_OBJECT FileObject,
58 PDEVICE_OBJECT DeviceObject);
59
60 VOID
61 RxAddToTopLevelIrpAllocatedContextsList(
62 PRX_TOPLEVELIRP_CONTEXT TopLevelContext);
63
64 VOID
65 RxAssert(
66 PVOID Assert,
67 PVOID File,
68 ULONG Line,
69 PVOID Message);
70
71 NTSTATUS
72 NTAPI
73 RxCommonCleanup(
74 PRX_CONTEXT Context);
75
76 NTSTATUS
77 NTAPI
78 RxCommonClose(
79 PRX_CONTEXT Context);
80
81 NTSTATUS
82 NTAPI
83 RxCommonCreate(
84 PRX_CONTEXT Context);
85
86 NTSTATUS
87 NTAPI
88 RxCommonDevFCBCleanup(
89 PRX_CONTEXT Context);
90
91 NTSTATUS
92 NTAPI
93 RxCommonDevFCBClose(
94 PRX_CONTEXT Context);
95
96 NTSTATUS
97 NTAPI
98 RxCommonDevFCBFsCtl(
99 PRX_CONTEXT Context);
100
101 NTSTATUS
102 NTAPI
103 RxCommonDevFCBIoCtl(
104 PRX_CONTEXT Context);
105
106 NTSTATUS
107 NTAPI
108 RxCommonDevFCBQueryVolInfo(
109 PRX_CONTEXT Context);
110
111 NTSTATUS
112 NTAPI
113 RxCommonDeviceControl(
114 PRX_CONTEXT Context);
115
116 NTSTATUS
117 NTAPI
118 RxCommonDirectoryControl(
119 PRX_CONTEXT Context);
120
121 NTSTATUS
122 NTAPI
123 RxCommonDispatchProblem(
124 PRX_CONTEXT Context);
125
126 NTSTATUS
127 NTAPI
128 RxCommonFileSystemControl(
129 PRX_CONTEXT Context);
130
131 NTSTATUS
132 NTAPI
133 RxCommonFlushBuffers(
134 PRX_CONTEXT Context);
135
136 NTSTATUS
137 NTAPI
138 RxCommonLockControl(
139 PRX_CONTEXT Context);
140
141 NTSTATUS
142 NTAPI
143 RxCommonQueryEa(
144 PRX_CONTEXT Context);
145
146 NTSTATUS
147 NTAPI
148 RxCommonQueryInformation(
149 PRX_CONTEXT Context);
150
151 NTSTATUS
152 NTAPI
153 RxCommonQueryQuotaInformation(
154 PRX_CONTEXT Context);
155
156 NTSTATUS
157 NTAPI
158 RxCommonQuerySecurity(
159 PRX_CONTEXT Context);
160
161 NTSTATUS
162 NTAPI
163 RxCommonQueryVolumeInformation(
164 PRX_CONTEXT Context);
165
166 NTSTATUS
167 NTAPI
168 RxCommonRead(
169 PRX_CONTEXT Context);
170
171 NTSTATUS
172 NTAPI
173 RxCommonSetEa(
174 PRX_CONTEXT Context);
175
176 NTSTATUS
177 NTAPI
178 RxCommonSetInformation(
179 PRX_CONTEXT Context);
180
181 NTSTATUS
182 NTAPI
183 RxCommonSetQuotaInformation(
184 PRX_CONTEXT Context);
185
186 NTSTATUS
187 NTAPI
188 RxCommonSetSecurity(
189 PRX_CONTEXT Context);
190
191 NTSTATUS
192 NTAPI
193 RxCommonSetVolumeInformation(
194 PRX_CONTEXT Context);
195
196 NTSTATUS
197 NTAPI
198 RxCommonUnimplemented(
199 PRX_CONTEXT Context);
200
201 NTSTATUS
202 NTAPI
203 RxCommonWrite(
204 PRX_CONTEXT Context);
205
206 VOID
207 RxCopyCreateParameters(
208 IN PRX_CONTEXT RxContext);
209
210 NTSTATUS
211 RxCreateFromNetRoot(
212 PRX_CONTEXT Context,
213 PUNICODE_STRING NetRootName);
214
215 NTSTATUS
216 RxCreateTreeConnect(
217 IN PRX_CONTEXT RxContext);
218
219 BOOLEAN
220 NTAPI
221 RxFastIoCheckIfPossible(
222 PFILE_OBJECT FileObject,
223 PLARGE_INTEGER FileOffset,
224 ULONG Length, BOOLEAN Wait,
225 ULONG LockKey, BOOLEAN CheckForReadOperation,
226 PIO_STATUS_BLOCK IoStatus,
227 PDEVICE_OBJECT DeviceObject);
228
229 BOOLEAN
230 NTAPI
231 RxFastIoDeviceControl(
232 PFILE_OBJECT FileObject,
233 BOOLEAN Wait,
234 PVOID InputBuffer OPTIONAL,
235 ULONG InputBufferLength,
236 PVOID OutputBuffer OPTIONAL,
237 ULONG OutputBufferLength,
238 ULONG IoControlCode,
239 PIO_STATUS_BLOCK IoStatus,
240 PDEVICE_OBJECT DeviceObject);
241
242 BOOLEAN
243 NTAPI
244 RxFastIoRead(
245 PFILE_OBJECT FileObject,
246 PLARGE_INTEGER FileOffset,
247 ULONG Length,
248 BOOLEAN Wait,
249 ULONG LockKey,
250 PVOID Buffer,
251 PIO_STATUS_BLOCK IoStatus,
252 PDEVICE_OBJECT DeviceObject);
253
254 BOOLEAN
255 NTAPI
256 RxFastIoWrite(
257 PFILE_OBJECT FileObject,
258 PLARGE_INTEGER FileOffset,
259 ULONG Length,
260 BOOLEAN Wait,
261 ULONG LockKey,
262 PVOID Buffer,
263 PIO_STATUS_BLOCK IoStatus,
264 PDEVICE_OBJECT DeviceObject);
265
266 NTSTATUS
267 RxFindOrCreateFcb(
268 PRX_CONTEXT RxContext,
269 PUNICODE_STRING NetRootName);
270
271 NTSTATUS
272 RxFirstCanonicalize(
273 PRX_CONTEXT RxContext,
274 PUNICODE_STRING FileName,
275 PUNICODE_STRING CanonicalName,
276 PNET_ROOT_TYPE NetRootType);
277
278 VOID
279 RxFreeCanonicalNameBuffer(
280 PRX_CONTEXT Context);
281
282 VOID
283 NTAPI
284 RxFspDispatch(
285 IN PVOID Context);
286
287 VOID
288 NTAPI
289 RxGetRegistryParameters(
290 IN PUNICODE_STRING RegistryPath);
291
292 NTSTATUS
293 NTAPI
294 RxGetStringRegistryParameter(
295 IN HANDLE KeyHandle,
296 IN PCWSTR KeyName,
297 OUT PUNICODE_STRING OutString,
298 IN PUCHAR Buffer,
299 IN ULONG BufferLength,
300 IN BOOLEAN LogFailure);
301
302 VOID
303 NTAPI
304 RxInitializeDebugSupport(
305 VOID);
306
307 VOID
308 NTAPI
309 RxInitializeDispatchVectors(
310 PDRIVER_OBJECT DriverObject);
311
312 NTSTATUS
313 NTAPI
314 RxInitializeRegistrationStructures(
315 VOID);
316
317 VOID
318 NTAPI
319 RxInitializeTopLevelIrpPackage(
320 VOID);
321
322 VOID
323 NTAPI
324 RxInitUnwind(
325 PDRIVER_OBJECT DriverObject,
326 USHORT State);
327
328 BOOLEAN
329 RxIsThisAnRdbssTopLevelContext(
330 PRX_TOPLEVELIRP_CONTEXT TopLevelContext);
331
332 NTSTATUS
333 NTAPI
334 RxLowIoIoCtlShellCompletion(
335 PRX_CONTEXT RxContext);
336
337 NTSTATUS
338 RxLowIoReadShell(
339 PRX_CONTEXT RxContext);
340
341 NTSTATUS
342 NTAPI
343 RxLowIoReadShellCompletion(
344 PRX_CONTEXT RxContext);
345
346 PVOID
347 RxNewMapUserBuffer(
348 PRX_CONTEXT RxContext);
349
350 NTSTATUS
351 RxNotifyChangeDirectory(
352 PRX_CONTEXT RxContext);
353
354 NTSTATUS
355 RxpQueryInfoMiniRdr(
356 PRX_CONTEXT RxContext,
357 FILE_INFORMATION_CLASS FileInfoClass,
358 PVOID Buffer);
359
360 NTSTATUS
361 RxQueryAlternateNameInfo(
362 PRX_CONTEXT RxContext,
363 PFILE_NAME_INFORMATION AltNameInfo);
364
365 NTSTATUS
366 RxQueryBasicInfo(
367 PRX_CONTEXT RxContext,
368 PFILE_BASIC_INFORMATION BasicInfo);
369
370 NTSTATUS
371 RxQueryCompressedInfo(
372 PRX_CONTEXT RxContext,
373 PFILE_COMPRESSION_INFORMATION CompressionInfo);
374
375 NTSTATUS
376 RxQueryDirectory(
377 PRX_CONTEXT RxContext);
378
379 NTSTATUS
380 RxQueryEaInfo(
381 PRX_CONTEXT RxContext,
382 PFILE_EA_INFORMATION EaInfo);
383
384 NTSTATUS
385 RxQueryInternalInfo(
386 PRX_CONTEXT RxContext,
387 PFILE_INTERNAL_INFORMATION InternalInfo);
388
389 NTSTATUS
390 RxQueryNameInfo(
391 PRX_CONTEXT RxContext,
392 PFILE_NAME_INFORMATION NameInfo);
393
394 NTSTATUS
395 RxQueryPipeInfo(
396 PRX_CONTEXT RxContext,
397 PFILE_PIPE_INFORMATION PipeInfo);
398
399 NTSTATUS
400 RxQueryPositionInfo(
401 PRX_CONTEXT RxContext,
402 PFILE_POSITION_INFORMATION PositionInfo);
403
404 NTSTATUS
405 RxQueryStandardInfo(
406 PRX_CONTEXT RxContext,
407 PFILE_STANDARD_INFORMATION StandardInfo);
408
409 VOID
410 NTAPI
411 RxReadRegistryParameters(
412 VOID);
413
414 VOID
415 NTAPI
416 RxReleaseFileForNtCreateSection(
417 PFILE_OBJECT FileObject);
418
419 NTSTATUS
420 NTAPI
421 RxReleaseForCcFlush(
422 PFILE_OBJECT FileObject,
423 PDEVICE_OBJECT DeviceObject);
424
425 PRX_CONTEXT
426 RxRemoveOverflowEntry(
427 PRDBSS_DEVICE_OBJECT DeviceObject,
428 WORK_QUEUE_TYPE Queue);
429
430 NTSTATUS
431 RxSearchForCollapsibleOpen(
432 PRX_CONTEXT RxContext,
433 ACCESS_MASK DesiredAccess,
434 ULONG ShareAccess);
435
436 VOID
437 RxSetupNetFileObject(
438 PRX_CONTEXT RxContext);
439
440 NTSTATUS
441 RxSystemControl(
442 IN PRDBSS_DEVICE_OBJECT RxDeviceObject,
443 IN PIRP Irp);
444
445 VOID
446 RxUninitializeCacheMap(
447 PRX_CONTEXT RxContext,
448 PFILE_OBJECT FileObject,
449 PLARGE_INTEGER TruncateSize);
450
451 VOID
452 RxUnstart(
453 PRX_CONTEXT Context,
454 PRDBSS_DEVICE_OBJECT DeviceObject);
455
456 NTSTATUS
457 RxXXXControlFileCallthru(
458 PRX_CONTEXT Context);
459
460 PVOID
461 NTAPI
462 _RxAllocatePoolWithTag(
463 _In_ POOL_TYPE PoolType,
464 _In_ SIZE_T NumberOfBytes,
465 _In_ ULONG Tag);
466
467 VOID
468 NTAPI
469 _RxFreePool(
470 _In_ PVOID Buffer);
471
472 VOID
473 NTAPI
474 _RxFreePoolWithTag(
475 _In_ PVOID Buffer,
476 _In_ ULONG Tag);
477
478 WCHAR RxStarForTemplate = '*';
479 WCHAR Rx8QMdot3QM[] = L">>>>>>>>.>>>*";
480 BOOLEAN DisableByteRangeLockingOnReadOnlyFiles = FALSE;
481 BOOLEAN DisableFlushOnCleanup = FALSE;
482 ULONG ReadAheadGranularity = 1 << PAGE_SHIFT;
483 LIST_ENTRY RxActiveContexts;
484 NPAGED_LOOKASIDE_LIST RxContextLookasideList;
485 FAST_MUTEX RxContextPerFileSerializationMutex;
486 RDBSS_DATA RxData;
487 FCB RxDeviceFCB;
488 RX_FSD_DISPATCH_VECTOR RxDeviceFCBVector[IRP_MJ_MAXIMUM_FUNCTION + 1] =
489 {
490 { RxCommonDispatchProblem },
491 { RxCommonDispatchProblem },
492 { RxCommonDevFCBClose },
493 { RxCommonDispatchProblem },
494 { RxCommonDispatchProblem },
495 { RxCommonDispatchProblem },
496 { RxCommonDispatchProblem },
497 { RxCommonDispatchProblem },
498 { RxCommonDispatchProblem },
499 { RxCommonDispatchProblem },
500 { RxCommonDevFCBQueryVolInfo },
501 { RxCommonDispatchProblem },
502 { RxCommonDispatchProblem },
503 { RxCommonDevFCBFsCtl },
504 { RxCommonDevFCBIoCtl },
505 { RxCommonDevFCBIoCtl },
506 { RxCommonDispatchProblem },
507 { RxCommonDispatchProblem },
508 { RxCommonDevFCBCleanup },
509 { RxCommonDispatchProblem },
510 { RxCommonDispatchProblem },
511 { RxCommonDispatchProblem },
512 { RxCommonUnimplemented },
513 { RxCommonUnimplemented },
514 { RxCommonUnimplemented },
515 { RxCommonUnimplemented },
516 { RxCommonUnimplemented },
517 { RxCommonUnimplemented },
518 };
519 RDBSS_EXPORTS RxExports;
520 FAST_IO_DISPATCH RxFastIoDispatch;
521 PRDBSS_DEVICE_OBJECT RxFileSystemDeviceObject;
522 RX_FSD_DISPATCH_VECTOR RxFsdDispatchVector[IRP_MJ_MAXIMUM_FUNCTION + 1] =
523 {
524 { RxCommonCreate },
525 { RxCommonUnimplemented },
526 { RxCommonClose },
527 { RxCommonRead },
528 { RxCommonWrite },
529 { RxCommonQueryInformation },
530 { RxCommonSetInformation },
531 { RxCommonQueryEa },
532 { RxCommonSetEa },
533 { RxCommonFlushBuffers },
534 { RxCommonQueryVolumeInformation },
535 { RxCommonSetVolumeInformation },
536 { RxCommonDirectoryControl },
537 { RxCommonFileSystemControl },
538 { RxCommonDeviceControl },
539 { RxCommonDeviceControl },
540 { RxCommonUnimplemented },
541 { RxCommonLockControl },
542 { RxCommonCleanup },
543 { RxCommonUnimplemented },
544 { RxCommonQuerySecurity },
545 { RxCommonSetSecurity },
546 { RxCommonUnimplemented },
547 { RxCommonUnimplemented },
548 { RxCommonUnimplemented },
549 { RxCommonQueryQuotaInformation },
550 { RxCommonSetQuotaInformation },
551 { RxCommonUnimplemented },
552 };
553 ULONG RxFsdEntryCount;
554 LIST_ENTRY RxIrpsList;
555 KSPIN_LOCK RxIrpsListSpinLock;
556 KMUTEX RxScavengerMutex;
557 KMUTEX RxSerializationMutex;
558 UCHAR RxSpaceForTheWrappersDeviceObject[sizeof(*RxFileSystemDeviceObject)];
559 KSPIN_LOCK TopLevelIrpSpinLock;
560 LIST_ENTRY TopLevelIrpAllocatedContextsList;
561 BOOLEAN RxForceQFIPassThrough = FALSE;
562
563 DECLARE_CONST_UNICODE_STRING(unknownId, L"???");
564
565 #if RDBSS_ASSERTS
566 #ifdef ASSERT
567 #undef ASSERT
568 #endif
569
570 #define ASSERT(exp) \
571 if (!(exp)) \
572 { \
573 RxAssert(#exp, __FILE__, __LINE__, NULL); \
574 }
575 #endif
576
577 #if RX_POOL_WRAPPER
578 #undef RxAllocatePool
579 #undef RxAllocatePoolWithTag
580 #undef RxFreePool
581
582 #define RxAllocatePool(P, S) _RxAllocatePoolWithTag(P, S, 0)
583 #define RxAllocatePoolWithTag _RxAllocatePoolWithTag
584 #define RxFreePool _RxFreePool
585 #define RxFreePoolWithTag _RxFreePoolWithTag
586 #endif
587
588 /* FUNCTIONS ****************************************************************/
589
590 VOID
591 CheckForLoudOperations(
592 PRX_CONTEXT RxContext)
593 {
594 UNIMPLEMENTED;
595 }
596
597 /*
598 * @implemented
599 */
600 VOID
601 __RxInitializeTopLevelIrpContext(
602 IN OUT PRX_TOPLEVELIRP_CONTEXT TopLevelContext,
603 IN PIRP Irp,
604 IN PRDBSS_DEVICE_OBJECT RxDeviceObject,
605 IN ULONG Flags)
606 {
607 DPRINT("__RxInitializeTopLevelIrpContext(%p, %p, %p, %u)\n", TopLevelContext, Irp, RxDeviceObject, Flags);
608
609 RtlZeroMemory(TopLevelContext, sizeof(RX_TOPLEVELIRP_CONTEXT));
610 TopLevelContext->Irp = Irp;
611 TopLevelContext->Flags = (Flags ? RX_TOPLEVELCTX_FLAG_FROM_POOL : 0);
612 TopLevelContext->Signature = RX_TOPLEVELIRP_CONTEXT_SIGNATURE;
613 TopLevelContext->RxDeviceObject = RxDeviceObject;
614 TopLevelContext->Previous = IoGetTopLevelIrp();
615 TopLevelContext->Thread = PsGetCurrentThread();
616
617 /* We cannot add to list something that'd come from stack */
618 if (BooleanFlagOn(TopLevelContext->Flags, RX_TOPLEVELCTX_FLAG_FROM_POOL))
619 {
620 RxAddToTopLevelIrpAllocatedContextsList(TopLevelContext);
621 }
622 }
623
624 NTSTATUS
625 NTAPI
626 RxAcquireExclusiveFcbResourceInMRx(
627 _Inout_ PMRX_FCB Fcb)
628 {
629 UNIMPLEMENTED;
630 return STATUS_NOT_IMPLEMENTED;
631 }
632
633 BOOLEAN
634 NTAPI
635 RxAcquireFcbForLazyWrite(
636 PVOID Context,
637 BOOLEAN Wait)
638 {
639 UNIMPLEMENTED;
640 return FALSE;
641 }
642
643 BOOLEAN
644 NTAPI
645 RxAcquireFcbForReadAhead(
646 PVOID Context,
647 BOOLEAN Wait)
648 {
649 UNIMPLEMENTED;
650 return FALSE;
651 }
652
653 VOID
654 NTAPI
655 RxAcquireFileForNtCreateSection(
656 PFILE_OBJECT FileObject)
657 {
658 UNIMPLEMENTED;
659 }
660
661 NTSTATUS
662 NTAPI
663 RxAcquireForCcFlush(
664 PFILE_OBJECT FileObject,
665 PDEVICE_OBJECT DeviceObject)
666 {
667 UNIMPLEMENTED;
668 return STATUS_NOT_IMPLEMENTED;
669 }
670
671 /*
672 * @implemented
673 */
674 VOID
675 RxAddToTopLevelIrpAllocatedContextsList(
676 PRX_TOPLEVELIRP_CONTEXT TopLevelContext)
677 {
678 KIRQL OldIrql;
679
680 DPRINT("RxAddToTopLevelIrpAllocatedContextsList(%p)\n", TopLevelContext);
681
682 ASSERT(TopLevelContext->Signature == RX_TOPLEVELIRP_CONTEXT_SIGNATURE);
683 ASSERT(BooleanFlagOn(TopLevelContext->Flags, RX_TOPLEVELCTX_FLAG_FROM_POOL));
684
685 KeAcquireSpinLock(&TopLevelIrpSpinLock, &OldIrql);
686 InsertTailList(&TopLevelIrpAllocatedContextsList, &TopLevelContext->ListEntry);
687 KeReleaseSpinLock(&TopLevelIrpSpinLock, OldIrql);
688 }
689
690 /*
691 * @implemented
692 */
693 VOID
694 RxAddToWorkque(
695 IN PRX_CONTEXT RxContext,
696 IN PIRP Irp)
697 {
698 ULONG Queued;
699 KIRQL OldIrql;
700 WORK_QUEUE_TYPE Queue;
701 PIO_STACK_LOCATION Stack;
702
703 Stack = RxContext->CurrentIrpSp;
704 RxContext->PostRequest = FALSE;
705
706 /* First of all, select the appropriate queue - delayed for prefix claim, critical for the rest */
707 if (RxContext->MajorFunction == IRP_MJ_DEVICE_CONTROL &&
708 Stack->Parameters.DeviceIoControl.IoControlCode == IOCTL_REDIR_QUERY_PATH)
709 {
710 Queue = DelayedWorkQueue;
711 SetFlag(RxContext->Flags, RX_CONTEXT_FLAG_FSP_DELAYED_OVERFLOW_QUEUE);
712 }
713 else
714 {
715 Queue = CriticalWorkQueue;
716 SetFlag(RxContext->Flags, RX_CONTEXT_FLAG_FSP_CRITICAL_OVERFLOW_QUEUE);
717 }
718
719 /* Check for overflow */
720 if (Stack->FileObject != NULL)
721 {
722 KeAcquireSpinLock(&RxFileSystemDeviceObject->OverflowQueueSpinLock, &OldIrql);
723
724 Queued = InterlockedIncrement(&RxFileSystemDeviceObject->PostedRequestCount[Queue]);
725 /* In case of an overflow, add the new queued call to the overflow list */
726 if (Queued > 1)
727 {
728 InterlockedDecrement(&RxFileSystemDeviceObject->PostedRequestCount[Queue]);
729 InsertTailList(&RxFileSystemDeviceObject->OverflowQueue[Queue], &RxContext->OverflowListEntry);
730 ++RxFileSystemDeviceObject->OverflowQueueCount[Queue];
731
732 KeReleaseSpinLock(&RxFileSystemDeviceObject->OverflowQueueSpinLock, OldIrql);
733 return;
734 }
735
736 KeReleaseSpinLock(&RxFileSystemDeviceObject->OverflowQueueSpinLock, OldIrql);
737 }
738
739 ExInitializeWorkItem(&RxContext->WorkQueueItem, RxFspDispatch, RxContext);
740 ExQueueWorkItem((PWORK_QUEUE_ITEM)&RxContext->WorkQueueItem, Queue);
741 }
742
743 /*
744 * @implemented
745 */
746 NTSTATUS
747 RxAllocateCanonicalNameBuffer(
748 PRX_CONTEXT RxContext,
749 PUNICODE_STRING CanonicalName,
750 USHORT CanonicalLength)
751 {
752 PAGED_CODE();
753
754 DPRINT("RxContext: %p - CanonicalNameBuffer: %p\n", RxContext, RxContext->Create.CanonicalNameBuffer);
755
756 /* Context must be free of any already allocated name */
757 ASSERT(RxContext->Create.CanonicalNameBuffer == NULL);
758
759 /* Validate string length */
760 if (CanonicalLength > USHRT_MAX - 1)
761 {
762 CanonicalName->Buffer = NULL;
763 return STATUS_OBJECT_PATH_INVALID;
764 }
765
766 CanonicalName->Buffer = RxAllocatePoolWithTag(PagedPool | POOL_COLD_ALLOCATION, CanonicalLength, RX_MISC_POOLTAG);
767 if (CanonicalName->Buffer == NULL)
768 {
769 return STATUS_INSUFFICIENT_RESOURCES;
770 }
771
772 CanonicalName->Length = 0;
773 CanonicalName->MaximumLength = CanonicalLength;
774
775 /* Set the two places - they must always be identical */
776 RxContext->Create.CanonicalNameBuffer = CanonicalName->Buffer;
777 RxContext->AlsoCanonicalNameBuffer = CanonicalName->Buffer;
778
779 return STATUS_SUCCESS;
780 }
781
782 VOID
783 NTAPI
784 RxCancelRoutine(
785 PDEVICE_OBJECT DeviceObject,
786 PIRP Irp)
787 {
788 UNIMPLEMENTED;
789 }
790
791 /*
792 * @implemented
793 */
794 NTSTATUS
795 RxCanonicalizeFileNameByServerSpecs(
796 PRX_CONTEXT RxContext,
797 PUNICODE_STRING NetRootName)
798 {
799 USHORT NextChar, CurChar;
800 USHORT MaxChars;
801
802 PAGED_CODE();
803
804 /* Validate file name is not empty */
805 MaxChars = NetRootName->Length / sizeof(WCHAR);
806 if (MaxChars == 0)
807 {
808 return STATUS_MORE_PROCESSING_REQUIRED;
809 }
810
811 /* Validate name is correct */
812 for (NextChar = 0, CurChar = 0; CurChar + 1 < MaxChars; NextChar = CurChar + 1)
813 {
814 USHORT i;
815
816 for (i = NextChar + 1; i < MaxChars; ++i)
817 {
818 if (NetRootName->Buffer[i] == '\\' || NetRootName->Buffer[i] == ':')
819 {
820 break;
821 }
822 }
823
824 CurChar = i - 1;
825 if (CurChar == NextChar)
826 {
827 if (((NetRootName->Buffer[NextChar] != '\\' && NetRootName->Buffer[NextChar] != ':') || NextChar == (MaxChars - 1)) && NetRootName->Buffer[NextChar] != '.')
828 {
829 continue;
830 }
831
832 if (CurChar != 0)
833 {
834 if (CurChar >= MaxChars - 1)
835 {
836 continue;
837 }
838
839 if (NetRootName->Buffer[CurChar + 1] != ':')
840 {
841 return STATUS_OBJECT_PATH_SYNTAX_BAD;
842 }
843 }
844 else
845 {
846 if (NetRootName->Buffer[1] != ':')
847 {
848 return STATUS_OBJECT_PATH_SYNTAX_BAD;
849 }
850 }
851 }
852 else
853 {
854 if ((CurChar - NextChar) == 1)
855 {
856 if (NetRootName->Buffer[NextChar + 2] != '.')
857 {
858 continue;
859 }
860
861 if (NetRootName->Buffer[NextChar] == '\\' || NetRootName->Buffer[NextChar] == ':' || NetRootName->Buffer[NextChar] == '.')
862 {
863 return STATUS_OBJECT_PATH_SYNTAX_BAD;
864 }
865 }
866 else
867 {
868 if ((CurChar - NextChar) != 2 || (NetRootName->Buffer[NextChar] != '\\' && NetRootName->Buffer[NextChar] != ':')
869 || NetRootName->Buffer[NextChar + 1] != '.')
870 {
871 continue;
872 }
873
874 if (NetRootName->Buffer[NextChar + 2] == '.')
875 {
876 return STATUS_OBJECT_PATH_SYNTAX_BAD;
877 }
878 }
879 }
880 }
881
882 return STATUS_MORE_PROCESSING_REQUIRED;
883 }
884
885 NTSTATUS
886 RxCanonicalizeNameAndObtainNetRoot(
887 PRX_CONTEXT RxContext,
888 PUNICODE_STRING FileName,
889 PUNICODE_STRING NetRootName)
890 {
891 NTSTATUS Status;
892 NET_ROOT_TYPE NetRootType;
893 UNICODE_STRING CanonicalName;
894
895 PAGED_CODE();
896
897 NetRootType = NET_ROOT_WILD;
898
899 RtlInitEmptyUnicodeString(NetRootName, NULL, 0);
900 RtlInitEmptyUnicodeString(&CanonicalName, NULL, 0);
901
902 /* if not relative opening, just handle the passed name */
903 if (RxContext->CurrentIrpSp->FileObject->RelatedFileObject == NULL)
904 {
905 Status = RxFirstCanonicalize(RxContext, FileName, &CanonicalName, &NetRootType);
906 if (!NT_SUCCESS(Status))
907 {
908 return Status;
909 }
910 }
911 else
912 {
913 PFCB Fcb;
914
915 /* Make sure we have a valid FCB and a FOBX */
916 Fcb = RxContext->CurrentIrpSp->FileObject->RelatedFileObject->FsContext;
917 if (Fcb == NULL ||
918 RxContext->CurrentIrpSp->FileObject->RelatedFileObject->FsContext2 == NULL)
919 {
920 return STATUS_INVALID_PARAMETER;
921 }
922
923 if (!NodeTypeIsFcb(Fcb))
924 {
925 return STATUS_INVALID_PARAMETER;
926 }
927
928 UNIMPLEMENTED;
929 }
930
931 /* Get/Create the associated VNetRoot for opening */
932 Status = RxFindOrConstructVirtualNetRoot(RxContext, &CanonicalName, NetRootType, NetRootName);
933 if (!NT_SUCCESS(Status) && Status != STATUS_PENDING &&
934 BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_MAILSLOT_REPARSE))
935 {
936 ASSERT(CanonicalName.Buffer == RxContext->Create.CanonicalNameBuffer);
937
938 RxFreeCanonicalNameBuffer(RxContext);
939 Status = RxFirstCanonicalize(RxContext, FileName, &CanonicalName, &NetRootType);
940 if (NT_SUCCESS(Status))
941 {
942 Status = RxFindOrConstructVirtualNetRoot(RxContext, &CanonicalName, NetRootType, NetRootName);
943 }
944 }
945
946 /* Filename cannot contain wildcards */
947 if (FsRtlDoesNameContainWildCards(NetRootName))
948 {
949 Status = STATUS_OBJECT_NAME_INVALID;
950 }
951
952 /* Make sure file name is correct */
953 if (NT_SUCCESS(Status))
954 {
955 Status = RxCanonicalizeFileNameByServerSpecs(RxContext, NetRootName);
956 }
957
958 /* Give the mini-redirector a chance to prepare the name */
959 if (NT_SUCCESS(Status) || Status == STATUS_MORE_PROCESSING_REQUIRED)
960 {
961 if (RxContext->Create.pNetRoot != NULL)
962 {
963 NTSTATUS IgnoredStatus;
964
965 MINIRDR_CALL(IgnoredStatus, RxContext, RxContext->Create.pNetRoot->pSrvCall->RxDeviceObject->Dispatch,
966 MRxPreparseName, (RxContext, NetRootName));
967 (void)IgnoredStatus;
968 }
969 }
970
971 return Status;
972 }
973
974 NTSTATUS
975 NTAPI
976 RxChangeBufferingState(
977 PSRV_OPEN SrvOpen,
978 PVOID Context,
979 BOOLEAN ComputeNewState)
980 {
981 UNIMPLEMENTED;
982 return STATUS_NOT_IMPLEMENTED;
983 }
984
985 VOID
986 NTAPI
987 RxCheckFcbStructuresForAlignment(
988 VOID)
989 {
990 UNIMPLEMENTED;
991 }
992
993 NTSTATUS
994 RxCheckShareAccess(
995 _In_ ACCESS_MASK DesiredAccess,
996 _In_ ULONG DesiredShareAccess,
997 _Inout_ PFILE_OBJECT FileObject,
998 _Inout_ PSHARE_ACCESS ShareAccess,
999 _In_ BOOLEAN Update,
1000 _In_ PSZ where,
1001 _In_ PSZ wherelogtag)
1002 {
1003 PAGED_CODE();
1004
1005 RxDumpWantedAccess(where, "", wherelogtag, DesiredAccess, DesiredShareAccess);
1006 RxDumpCurrentAccess(where, "", wherelogtag, ShareAccess);
1007
1008 return IoCheckShareAccess(DesiredAccess, DesiredShareAccess, FileObject, ShareAccess, Update);
1009 }
1010
1011 /*
1012 * @implemented
1013 */
1014 NTSTATUS
1015 RxCheckShareAccessPerSrvOpens(
1016 IN PFCB Fcb,
1017 IN ACCESS_MASK DesiredAccess,
1018 IN ULONG DesiredShareAccess)
1019 {
1020 BOOLEAN ReadAccess;
1021 BOOLEAN WriteAccess;
1022 BOOLEAN DeleteAccess;
1023 PSHARE_ACCESS ShareAccess;
1024
1025 PAGED_CODE();
1026
1027 ShareAccess = &Fcb->ShareAccessPerSrvOpens;
1028
1029 RxDumpWantedAccess("RxCheckShareAccessPerSrvOpens", "", "RxCheckShareAccessPerSrvOpens", DesiredAccess, DesiredShareAccess);
1030 RxDumpCurrentAccess("RxCheckShareAccessPerSrvOpens", "", "RxCheckShareAccessPerSrvOpens", ShareAccess);
1031
1032 /* Check if any access wanted */
1033 ReadAccess = (DesiredAccess & (FILE_READ_DATA | FILE_EXECUTE)) != 0;
1034 WriteAccess = (DesiredAccess & (FILE_WRITE_DATA | FILE_APPEND_DATA)) != 0;
1035 DeleteAccess = (DesiredAccess & DELETE) != 0;
1036
1037 if (ReadAccess || WriteAccess || DeleteAccess)
1038 {
1039 BOOLEAN SharedRead = (DesiredShareAccess & FILE_SHARE_READ) != 0;
1040 BOOLEAN SharedWrite = (DesiredShareAccess & FILE_SHARE_WRITE) != 0;
1041 BOOLEAN SharedDelete = (DesiredShareAccess & FILE_SHARE_DELETE) != 0;
1042
1043 /* Check whether there's a violation */
1044 if ((ReadAccess &&
1045 (ShareAccess->SharedRead < ShareAccess->OpenCount)) ||
1046 (WriteAccess &&
1047 (ShareAccess->SharedWrite < ShareAccess->OpenCount)) ||
1048 (DeleteAccess &&
1049 (ShareAccess->SharedDelete < ShareAccess->OpenCount)) ||
1050 ((ShareAccess->Readers != 0) && !SharedRead) ||
1051 ((ShareAccess->Writers != 0) && !SharedWrite) ||
1052 ((ShareAccess->Deleters != 0) && !SharedDelete))
1053 {
1054 return STATUS_SHARING_VIOLATION;
1055 }
1056 }
1057
1058 return STATUS_SUCCESS;
1059 }
1060
1061 NTSTATUS
1062 RxCloseAssociatedSrvOpen(
1063 IN PFOBX Fobx,
1064 IN PRX_CONTEXT RxContext OPTIONAL)
1065 {
1066 UNIMPLEMENTED;
1067 return STATUS_NOT_IMPLEMENTED;
1068 }
1069
1070 /*
1071 * @implemented
1072 */
1073 NTSTATUS
1074 RxCollapseOrCreateSrvOpen(
1075 PRX_CONTEXT RxContext)
1076 {
1077 PFCB Fcb;
1078 NTSTATUS Status;
1079 ULONG Disposition;
1080 PSRV_OPEN SrvOpen;
1081 USHORT ShareAccess;
1082 PIO_STACK_LOCATION Stack;
1083 ACCESS_MASK DesiredAccess;
1084 RX_BLOCK_CONDITION FcbCondition;
1085
1086 PAGED_CODE();
1087
1088 DPRINT("RxCollapseOrCreateSrvOpen(%p)\n", RxContext);
1089
1090 Fcb = (PFCB)RxContext->pFcb;
1091 ASSERT(RxIsFcbAcquiredExclusive(Fcb));
1092 ++Fcb->UncleanCount;
1093
1094 Stack = RxContext->CurrentIrpSp;
1095 DesiredAccess = Stack->Parameters.Create.SecurityContext->DesiredAccess & FILE_ALL_ACCESS;
1096 ShareAccess = Stack->Parameters.Create.ShareAccess & FILE_SHARE_VALID_FLAGS;
1097
1098 Disposition = RxContext->Create.NtCreateParameters.Disposition;
1099
1100 /* Try to find a reusable SRV_OPEN */
1101 Status = RxSearchForCollapsibleOpen(RxContext, DesiredAccess, ShareAccess);
1102 if (Status == STATUS_NOT_FOUND)
1103 {
1104 /* If none found, create one */
1105 SrvOpen = RxCreateSrvOpen((PV_NET_ROOT)RxContext->Create.pVNetRoot, Fcb);
1106 if (SrvOpen == NULL)
1107 {
1108 Status = STATUS_INSUFFICIENT_RESOURCES;
1109 }
1110 else
1111 {
1112 SrvOpen->DesiredAccess = DesiredAccess;
1113 SrvOpen->ShareAccess = ShareAccess;
1114 Status = STATUS_SUCCESS;
1115 }
1116
1117 RxContext->pRelevantSrvOpen = (PMRX_SRV_OPEN)SrvOpen;
1118
1119 if (Status != STATUS_SUCCESS)
1120 {
1121 FcbCondition = Condition_Bad;
1122 }
1123 else
1124 {
1125 RxInitiateSrvOpenKeyAssociation(SrvOpen);
1126
1127 /* Cookie to check the mini-rdr doesn't mess with RX_CONTEXT */
1128 RxContext->CurrentIrp->IoStatus.Information = 0xABCDEF;
1129 /* Inform the mini-rdr we're handling a create */
1130 MINIRDR_CALL(Status, RxContext, Fcb->MRxDispatch, MRxCreate, (RxContext));
1131 ASSERT(RxContext->CurrentIrp->IoStatus.Information == 0xABCDEF);
1132
1133 DPRINT("MRxCreate returned: %x\n", Status);
1134 if (Status == STATUS_SUCCESS)
1135 {
1136 /* In case of overwrite, reset file size */
1137 if (Disposition == FILE_OVERWRITE || Disposition == FILE_OVERWRITE_IF)
1138 {
1139 RxAcquirePagingIoResource(RxContext, Fcb);
1140 Fcb->Header.AllocationSize.QuadPart = 0LL;
1141 Fcb->Header.FileSize.QuadPart = 0LL;
1142 Fcb->Header.ValidDataLength.QuadPart = 0LL;
1143 RxContext->CurrentIrpSp->FileObject->SectionObjectPointer = &Fcb->NonPaged->SectionObjectPointers;
1144 CcSetFileSizes(RxContext->CurrentIrpSp->FileObject, (PCC_FILE_SIZES)&Fcb->Header.AllocationSize);
1145 RxReleasePagingIoResource(RxContext, Fcb);
1146 }
1147 else
1148 {
1149 /* Otherwise, adjust sizes */
1150 RxContext->CurrentIrpSp->FileObject->SectionObjectPointer = &Fcb->NonPaged->SectionObjectPointers;
1151 if (CcIsFileCached(RxContext->CurrentIrpSp->FileObject))
1152 {
1153 RxAdjustAllocationSizeforCC(Fcb);
1154 }
1155 CcSetFileSizes(RxContext->CurrentIrpSp->FileObject, (PCC_FILE_SIZES)&Fcb->Header.AllocationSize);
1156 }
1157 }
1158
1159 /* Set the IoStatus with information returned by mini-rdr */
1160 RxContext->CurrentIrp->IoStatus.Information = RxContext->Create.ReturnedCreateInformation;
1161
1162 SrvOpen->OpenStatus = Status;
1163 /* Set SRV_OPEN state - good or bad - depending on whether create succeed */
1164 RxTransitionSrvOpen(SrvOpen, (Status == STATUS_SUCCESS ? Condition_Good : Condition_Bad));
1165
1166 ASSERT(RxIsFcbAcquiredExclusive(Fcb));
1167
1168 RxCompleteSrvOpenKeyAssociation(SrvOpen);
1169
1170 if (Status == STATUS_SUCCESS)
1171 {
1172 if (BooleanFlagOn(Stack->Parameters.Create.Options, FILE_DELETE_ON_CLOSE))
1173 {
1174 ClearFlag(Fcb->FcbState, FCB_STATE_COLLAPSING_ENABLED);
1175 }
1176 SrvOpen->CreateOptions = RxContext->Create.NtCreateParameters.CreateOptions;
1177 FcbCondition = Condition_Good;
1178 }
1179 else
1180 {
1181 FcbCondition = Condition_Bad;
1182 RxDereferenceSrvOpen(SrvOpen, LHS_ExclusiveLockHeld);
1183 RxContext->pRelevantSrvOpen = NULL;
1184
1185 if (RxContext->pFobx != NULL)
1186 {
1187 RxDereferenceNetFobx(RxContext->pFobx, LHS_ExclusiveLockHeld);
1188 RxContext->pFobx = NULL;
1189 }
1190 }
1191 }
1192
1193 /* Set FCB state - good or bad - depending on whether create succeed */
1194 DPRINT("Transitioning FCB %p to condition %lx\n", Fcb, Fcb->Condition);
1195 RxTransitionNetFcb(Fcb, FcbCondition);
1196 }
1197 else if (Status == STATUS_SUCCESS)
1198 {
1199 BOOLEAN IsGood, ExtraOpen;
1200
1201 /* A reusable SRV_OPEN was found */
1202 RxContext->CurrentIrp->IoStatus.Information = FILE_OPENED;
1203 ExtraOpen = FALSE;
1204
1205 SrvOpen = (PSRV_OPEN)RxContext->pRelevantSrvOpen;
1206
1207 IsGood = (SrvOpen->Condition == Condition_Good);
1208 /* If the SRV_OPEN isn't in a stable situation, wait for it to become stable */
1209 if (!StableCondition(SrvOpen->Condition))
1210 {
1211 RxReferenceSrvOpen(SrvOpen);
1212 ++SrvOpen->OpenCount;
1213 ExtraOpen = TRUE;
1214
1215 RxReleaseFcb(RxContext, Fcb);
1216 RxContext->Create.FcbAcquired = FALSE;
1217
1218 RxWaitForStableSrvOpen(SrvOpen, RxContext);
1219
1220 if (NT_SUCCESS(RxAcquireExclusiveFcb(RxContext, Fcb)))
1221 {
1222 RxContext->Create.FcbAcquired = TRUE;
1223 }
1224
1225 IsGood = (SrvOpen->Condition == Condition_Good);
1226 }
1227
1228 /* Inform the mini-rdr we do an opening with a reused SRV_OPEN */
1229 if (IsGood)
1230 {
1231 MINIRDR_CALL(Status, RxContext, Fcb->MRxDispatch, MRxCollapseOpen, (RxContext));
1232
1233 ASSERT(RxIsFcbAcquiredExclusive(Fcb));
1234 }
1235 else
1236 {
1237 Status = SrvOpen->OpenStatus;
1238 }
1239
1240 if (ExtraOpen)
1241 {
1242 --SrvOpen->OpenCount;
1243 RxDereferenceSrvOpen(SrvOpen, LHS_ExclusiveLockHeld);
1244 }
1245 }
1246
1247 --Fcb->UncleanCount;
1248
1249 DPRINT("Status: %x\n", Status);
1250 return Status;
1251 }
1252
1253 NTSTATUS
1254 NTAPI
1255 RxCommonCleanup(
1256 PRX_CONTEXT Context)
1257 {
1258 #define BugCheckFileId RDBSS_BUG_CHECK_CLEANUP
1259 PFCB Fcb;
1260 PFOBX Fobx;
1261 NTSTATUS Status;
1262 BOOLEAN NeedPurge;
1263 PFILE_OBJECT FileObject;
1264
1265 PAGED_CODE();
1266
1267 Fcb = (PFCB)Context->pFcb;
1268 Fobx = (PFOBX)Context->pFobx;
1269 DPRINT("RxCommonCleanup(%p); FOBX: %p, FCB: %p\n", Context, Fobx, Fcb);
1270
1271 /* File system closing, it's OK */
1272 if (Fobx == NULL)
1273 {
1274 if (Fcb->UncleanCount > 0)
1275 {
1276 InterlockedDecrement((volatile long *)&Fcb->UncleanCount);
1277 }
1278
1279 return STATUS_SUCCESS;
1280 }
1281
1282 /* Check we have a correct FCB type */
1283 if (NodeType(Fcb) != RDBSS_NTC_STORAGE_TYPE_FILE &&
1284 NodeType(Fcb) != RDBSS_NTC_STORAGE_TYPE_DIRECTORY &&
1285 NodeType(Fcb) != RDBSS_NTC_STORAGE_TYPE_UNKNOWN &&
1286 NodeType(Fcb) != RDBSS_NTC_SPOOLFILE)
1287 {
1288 DPRINT1("Invalid Fcb type for %p\n", Fcb);
1289 RxBugCheck(Fcb->Header.NodeTypeCode, 0, 0);
1290 }
1291
1292 FileObject = Context->CurrentIrpSp->FileObject;
1293 ASSERT(!BooleanFlagOn(FileObject->Flags, FO_CLEANUP_COMPLETE));
1294
1295 RxMarkFobxOnCleanup(Fobx, &NeedPurge);
1296
1297 Status = RxAcquireExclusiveFcb(Context, Fcb);
1298 if (!NT_SUCCESS(Status))
1299 {
1300 return Status;
1301 }
1302
1303 Fobx->AssociatedFileObject = NULL;
1304
1305 /* In case SRV_OPEN used is part of FCB */
1306 if (BooleanFlagOn(Fcb->FcbState, FCB_STATE_SRVOPEN_USED))
1307 {
1308 ASSERT(Fcb->UncleanCount != 0);
1309 InterlockedDecrement((volatile long *)&Fcb->UncleanCount);
1310
1311 if (BooleanFlagOn(FileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING))
1312 {
1313 --Fcb->UncachedUncleanCount;
1314 }
1315
1316 /* Inform mini-rdr */
1317 MINIRDR_CALL(Status, Context, Fcb->MRxDispatch, MRxCleanupFobx, (Context));
1318
1319 ASSERT(Fobx->SrvOpen->UncleanFobxCount != 0);
1320 --Fobx->SrvOpen->UncleanFobxCount;
1321
1322 RxUninitializeCacheMap(Context, FileObject, NULL);
1323
1324 RxReleaseFcb(Context, Fcb);
1325
1326 return STATUS_SUCCESS;
1327 }
1328
1329 UNIMPLEMENTED;
1330 return STATUS_NOT_IMPLEMENTED;
1331 #undef BugCheckFileId
1332 }
1333
1334 NTSTATUS
1335 NTAPI
1336 RxCommonClose(
1337 PRX_CONTEXT Context)
1338 {
1339 #define BugCheckFileId RDBSS_BUG_CHECK_CLOSE
1340 PFCB Fcb;
1341 PFOBX Fobx;
1342 NTSTATUS Status;
1343 PFILE_OBJECT FileObject;
1344 BOOLEAN DereferenceFobx, AcquiredFcb;
1345
1346 PAGED_CODE();
1347
1348 Fcb = (PFCB)Context->pFcb;
1349 Fobx = (PFOBX)Context->pFobx;
1350 FileObject = Context->CurrentIrpSp->FileObject;
1351 DPRINT("RxCommonClose(%p); FOBX: %p, FCB: %p, FO: %p\n", Context, Fobx, Fcb, FileObject);
1352
1353 Status = RxAcquireExclusiveFcb(Context, Fcb);
1354 if (!NT_SUCCESS(Status))
1355 {
1356 return Status;
1357 }
1358
1359 AcquiredFcb = TRUE;
1360 _SEH2_TRY
1361 {
1362 BOOLEAN Freed;
1363
1364 /* Check our FCB type is expected */
1365 if (NodeType(Fcb) != RDBSS_NTC_STORAGE_TYPE_UNKNOWN &&
1366 (NodeType(Fcb) < RDBSS_NTC_STORAGE_TYPE_DIRECTORY || (NodeType(Fcb) > RDBSS_NTC_STORAGE_TYPE_FILE &&
1367 (NodeType(Fcb) < RDBSS_NTC_SPOOLFILE || NodeType(Fcb) > RDBSS_NTC_OPENTARGETDIR_FCB))))
1368 {
1369 RxBugCheck(NodeType(Fcb), 0, 0);
1370 }
1371
1372 RxReferenceNetFcb(Fcb);
1373
1374 DereferenceFobx = FALSE;
1375 /* If we're not closing FS */
1376 if (Fobx != NULL)
1377 {
1378 PSRV_OPEN SrvOpen;
1379 PSRV_CALL SrvCall;
1380
1381 SrvOpen = (PSRV_OPEN)Fobx->pSrvOpen;
1382 SrvCall = (PSRV_CALL)Fcb->pNetRoot->pSrvCall;
1383 /* Handle delayed close */
1384 if (NodeType(Fcb) != RDBSS_NTC_STORAGE_TYPE_DIRECTORY)
1385 {
1386 if (!BooleanFlagOn(Fcb->FcbState, FCB_STATE_DELETE_ON_CLOSE | FCB_STATE_ORPHANED))
1387 {
1388 if (BooleanFlagOn(Fcb->FcbState, FCB_STATE_COLLAPSING_ENABLED))
1389 {
1390 DPRINT("Delay close for FOBX: %p, SrvOpen %p\n", Fobx, SrvOpen);
1391
1392 if (SrvOpen->OpenCount == 1 && !BooleanFlagOn(SrvOpen->Flags, SRVOPEN_FLAG_COLLAPSING_DISABLED))
1393 {
1394 if (InterlockedIncrement(&SrvCall->NumberOfCloseDelayedFiles) >= SrvCall->MaximumNumberOfCloseDelayedFiles)
1395 {
1396 InterlockedDecrement(&SrvCall->NumberOfCloseDelayedFiles);
1397 }
1398 else
1399 {
1400 DereferenceFobx = TRUE;
1401 SetFlag(SrvOpen->Flags, SRVOPEN_FLAG_CLOSE_DELAYED);
1402 }
1403 }
1404 }
1405 }
1406 }
1407
1408 /* If we reach maximum of delayed close/or if there are no delayed close */
1409 if (!DereferenceFobx)
1410 {
1411 PNET_ROOT NetRoot;
1412
1413 NetRoot = (PNET_ROOT)Fcb->pNetRoot;
1414 if (NetRoot->Type != NET_ROOT_PRINT)
1415 {
1416 /* Delete if asked */
1417 if (BooleanFlagOn(Fobx->Flags, FOBX_FLAG_DELETE_ON_CLOSE))
1418 {
1419 RxScavengeRelatedFobxs(Fcb);
1420 RxSynchronizeWithScavenger(Context);
1421
1422 RxReleaseFcb(Context, Fcb);
1423
1424 RxAcquireFcbTableLockExclusive(&NetRoot->FcbTable, TRUE);
1425 RxOrphanThisFcb(Fcb);
1426 RxReleaseFcbTableLock(&NetRoot->FcbTable);
1427
1428 Status = RxAcquireExclusiveFcb(Context, Fcb);
1429 ASSERT(NT_SUCCESS(Status));
1430 }
1431 }
1432 }
1433
1434 RxMarkFobxOnClose(Fobx);
1435 }
1436
1437 if (DereferenceFobx)
1438 {
1439 ASSERT(Fobx != NULL);
1440 RxDereferenceNetFobx(Fobx, LHS_SharedLockHeld);
1441 }
1442 else
1443 {
1444 RxCloseAssociatedSrvOpen(Fobx, Context);
1445 if (Fobx != NULL)
1446 {
1447 RxDereferenceNetFobx(Fobx, LHS_ExclusiveLockHeld);
1448 }
1449 }
1450
1451 Freed = RxDereferenceAndFinalizeNetFcb(Fcb, Context, FALSE, FALSE);
1452 AcquiredFcb = !Freed;
1453
1454 FileObject->FsContext = (PVOID)-1;
1455
1456 if (Freed)
1457 {
1458 RxTrackerUpdateHistory(Context, NULL, TRACKER_FCB_FREE, __LINE__, __FILE__, 0);
1459 }
1460 else
1461 {
1462 RxReleaseFcb(Context, Fcb);
1463 AcquiredFcb = FALSE;
1464 }
1465 }
1466 _SEH2_FINALLY
1467 {
1468 if (_SEH2_AbnormalTermination())
1469 {
1470 if (AcquiredFcb)
1471 {
1472 RxReleaseFcb(Context, Fcb);
1473 }
1474 }
1475 else
1476 {
1477 ASSERT(!AcquiredFcb);
1478 }
1479 }
1480 _SEH2_END;
1481
1482 DPRINT("Status: %x\n", Status);
1483 return Status;
1484 #undef BugCheckFileId
1485 }
1486
1487 NTSTATUS
1488 NTAPI
1489 RxCommonCreate(
1490 PRX_CONTEXT Context)
1491 {
1492 PIRP Irp;
1493 NTSTATUS Status;
1494 PFILE_OBJECT FileObject;
1495 PIO_STACK_LOCATION Stack;
1496
1497 PAGED_CODE();
1498
1499 DPRINT("RxCommonCreate(%p)\n", Context);
1500
1501 Irp = Context->CurrentIrp;
1502 Stack = Context->CurrentIrpSp;
1503 FileObject = Stack->FileObject;
1504
1505 /* Check whether that's a device opening */
1506 if (FileObject->FileName.Length == 0 && FileObject->RelatedFileObject == NULL)
1507 {
1508 FileObject->FsContext = &RxDeviceFCB;
1509 FileObject->FsContext2 = NULL;
1510
1511 ++RxDeviceFCB.NodeReferenceCount;
1512 ++RxDeviceFCB.OpenCount;
1513
1514 Irp->IoStatus.Information = FILE_OPENED;
1515 DPRINT("Device opening FO: %p, DO: %p, Name: %wZ\n", FileObject, Context->RxDeviceObject, &Context->RxDeviceObject->DeviceName);
1516
1517 Status = STATUS_SUCCESS;
1518 }
1519 else
1520 {
1521 PFCB RelatedFcb = NULL;
1522
1523 /* Make sure caller is consistent */
1524 if (FlagOn(Stack->Parameters.Create.Options, FILE_DIRECTORY_FILE | FILE_NON_DIRECTORY_FILE | FILE_OPEN_REMOTE_INSTANCE) ==
1525 (FILE_DIRECTORY_FILE | FILE_NON_DIRECTORY_FILE | FILE_OPEN_REMOTE_INSTANCE))
1526 {
1527 DPRINT1("Create.Options: %x\n", Stack->Parameters.Create.Options);
1528 return STATUS_INVALID_PARAMETER;
1529 }
1530
1531 DPRINT("Ctxt: %p, FO: %p, Options: %lx, Flags: %lx, Attr: %lx, ShareAccess: %lx, DesiredAccess: %lx\n",
1532 Context, FileObject, Stack->Parameters.Create.Options, Stack->Flags, Stack->Parameters.Create.FileAttributes,
1533 Stack->Parameters.Create.ShareAccess, Stack->Parameters.Create.SecurityContext->DesiredAccess);
1534 DPRINT("FileName: %wZ\n", &FileObject->FileName);
1535
1536 if (FileObject->RelatedFileObject != NULL)
1537 {
1538 RelatedFcb = FileObject->RelatedFileObject->FsContext;
1539 DPRINT("Rel FO: %p, path: %wZ\n", FileObject->RelatedFileObject, RelatedFcb->FcbTableEntry.Path);
1540 }
1541
1542 /* Going to rename? */
1543 if (BooleanFlagOn(Stack->Flags, SL_OPEN_TARGET_DIRECTORY))
1544 {
1545 DPRINT("TargetDir!\n");
1546 }
1547
1548 /* Copy create parameters to the context */
1549 RxCopyCreateParameters(Context);
1550
1551 /* If the caller wants to establish a connection, go ahead */
1552 if (BooleanFlagOn(Stack->Parameters.Create.Options, FILE_CREATE_TREE_CONNECTION))
1553 {
1554 Status = RxCreateTreeConnect(Context);
1555 }
1556 else
1557 {
1558 /* Validate file name */
1559 if (FileObject->FileName.Length > sizeof(WCHAR) &&
1560 FileObject->FileName.Buffer[1] == OBJ_NAME_PATH_SEPARATOR &&
1561 FileObject->FileName.Buffer[0] == OBJ_NAME_PATH_SEPARATOR)
1562 {
1563 FileObject->FileName.Length -= sizeof(WCHAR);
1564 RtlMoveMemory(&FileObject->FileName.Buffer[0], &FileObject->FileName.Buffer[1],
1565 FileObject->FileName.Length);
1566
1567 if (FileObject->FileName.Length > sizeof(WCHAR) &&
1568 FileObject->FileName.Buffer[1] == OBJ_NAME_PATH_SEPARATOR &&
1569 FileObject->FileName.Buffer[0] == OBJ_NAME_PATH_SEPARATOR)
1570 {
1571 return STATUS_OBJECT_NAME_INVALID;
1572 }
1573 }
1574
1575 /* Attempt to open the file */
1576 do
1577 {
1578 UNICODE_STRING NetRootName;
1579
1580 /* Strip last \ if required */
1581 if (FileObject->FileName.Length != 0 &&
1582 FileObject->FileName.Buffer[FileObject->FileName.Length / sizeof(WCHAR) - 1] == OBJ_NAME_PATH_SEPARATOR)
1583 {
1584 if (BooleanFlagOn(Stack->Parameters.Create.Options, FILE_NON_DIRECTORY_FILE))
1585 {
1586 return STATUS_OBJECT_NAME_INVALID;
1587 }
1588
1589 FileObject->FileName.Length -= sizeof(WCHAR);
1590 Context->Create.Flags |= RX_CONTEXT_CREATE_FLAG_STRIPPED_TRAILING_BACKSLASH;
1591 }
1592
1593 if (BooleanFlagOn(Context->Flags, RX_CONTEXT_FLAG_WRITE_THROUGH))
1594 {
1595 FileObject->Flags |= FO_WRITE_THROUGH;
1596 }
1597
1598 /* Get the associated net root to opening */
1599 Status = RxCanonicalizeNameAndObtainNetRoot(Context, &FileObject->FileName, &NetRootName);
1600 if (Status != STATUS_MORE_PROCESSING_REQUIRED)
1601 {
1602 break;
1603 }
1604
1605 /* And attempt to open */
1606 Status = RxCreateFromNetRoot(Context, &NetRootName);
1607 if (Status == STATUS_SHARING_VIOLATION)
1608 {
1609 UNIMPLEMENTED;
1610 }
1611 else if (Status == STATUS_REPARSE)
1612 {
1613 Context->CurrentIrp->IoStatus.Information = 0;
1614 }
1615 else
1616 {
1617 ASSERT(!BooleanFlagOn(Context->Create.Flags, RX_CONTEXT_CREATE_FLAG_REPARSE));
1618 }
1619 }
1620 while (Status == STATUS_MORE_PROCESSING_REQUIRED);
1621 }
1622
1623 if (Status == STATUS_RETRY)
1624 {
1625 RxpPrepareCreateContextForReuse(Context);
1626 }
1627 ASSERT(Status != STATUS_PENDING);
1628 }
1629
1630 DPRINT("Status: %lx\n", Status);
1631 return Status;
1632 }
1633
1634 /*
1635 * @implemented
1636 */
1637 NTSTATUS
1638 NTAPI
1639 RxCommonDevFCBCleanup(
1640 PRX_CONTEXT Context)
1641 {
1642 PMRX_FCB Fcb;
1643 NTSTATUS Status;
1644
1645 PAGED_CODE();
1646
1647 DPRINT("RxCommonDevFCBCleanup(%p)\n", Context);
1648
1649 Fcb = Context->pFcb;
1650 Status = STATUS_SUCCESS;
1651 ASSERT(NodeType(Fcb) == RDBSS_NTC_DEVICE_FCB);
1652
1653 /* Our FOBX if set, has to be a VNetRoot */
1654 if (Context->pFobx != NULL)
1655 {
1656 RxAcquirePrefixTableLockShared(Context->RxDeviceObject->pRxNetNameTable, TRUE);
1657 if (Context->pFobx->NodeTypeCode != RDBSS_NTC_V_NETROOT)
1658 {
1659 Status = STATUS_INVALID_DEVICE_REQUEST;
1660 }
1661 RxReleasePrefixTableLock(Context->RxDeviceObject->pRxNetNameTable);
1662 }
1663 else
1664 {
1665 --Fcb->UncleanCount;
1666 }
1667
1668 return Status;
1669 }
1670
1671 /*
1672 * @implemented
1673 */
1674 NTSTATUS
1675 NTAPI
1676 RxCommonDevFCBClose(
1677 PRX_CONTEXT Context)
1678 {
1679 PMRX_FCB Fcb;
1680 NTSTATUS Status;
1681 PMRX_V_NET_ROOT NetRoot;
1682
1683 PAGED_CODE();
1684
1685 DPRINT("RxCommonDevFCBClose(%p)\n", Context);
1686
1687 Fcb = Context->pFcb;
1688 NetRoot = (PMRX_V_NET_ROOT)Context->pFobx;
1689 Status = STATUS_SUCCESS;
1690 ASSERT(NodeType(Fcb) == RDBSS_NTC_DEVICE_FCB);
1691
1692 /* Our FOBX if set, has to be a VNetRoot */
1693 if (NetRoot != NULL)
1694 {
1695 RxAcquirePrefixTableLockShared(Context->RxDeviceObject->pRxNetNameTable, TRUE);
1696 if (NetRoot->NodeTypeCode == RDBSS_NTC_V_NETROOT)
1697 {
1698 --NetRoot->NumberOfOpens;
1699 RxDereferenceVNetRoot(NetRoot, LHS_ExclusiveLockHeld);
1700 }
1701 else
1702 {
1703 Status = STATUS_NOT_IMPLEMENTED;
1704 }
1705 RxReleasePrefixTableLock(Context->RxDeviceObject->pRxNetNameTable);
1706 }
1707 else
1708 {
1709 --Fcb->OpenCount;
1710 }
1711
1712 return Status;
1713 }
1714
1715 NTSTATUS
1716 NTAPI
1717 RxCommonDevFCBFsCtl(
1718 PRX_CONTEXT Context)
1719 {
1720 UNIMPLEMENTED;
1721 return STATUS_NOT_IMPLEMENTED;
1722 }
1723
1724 /*
1725 * @implemented
1726 */
1727 NTSTATUS
1728 NTAPI
1729 RxCommonDevFCBIoCtl(
1730 PRX_CONTEXT Context)
1731 {
1732 NTSTATUS Status;
1733
1734 PAGED_CODE();
1735
1736 DPRINT("RxCommonDevFCBIoCtl(%p)\n", Context);
1737
1738 if (Context->pFobx != NULL)
1739 {
1740 return STATUS_INVALID_HANDLE;
1741 }
1742
1743 /* Is that a prefix claim from MUP? */
1744 if (Context->CurrentIrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_REDIR_QUERY_PATH)
1745 {
1746 return RxPrefixClaim(Context);
1747 }
1748
1749 /* Otherwise, pass through the mini-rdr */
1750 Status = RxXXXControlFileCallthru(Context);
1751 if (Status != STATUS_PENDING)
1752 {
1753 if (Context->PostRequest)
1754 {
1755 Context->ResumeRoutine = RxCommonDevFCBIoCtl;
1756 Status = RxFsdPostRequest(Context);
1757 }
1758 }
1759
1760 DPRINT("Status: %lx\n", Status);
1761 return Status;
1762 }
1763
1764 NTSTATUS
1765 NTAPI
1766 RxCommonDevFCBQueryVolInfo(
1767 PRX_CONTEXT Context)
1768 {
1769 UNIMPLEMENTED;
1770 return STATUS_NOT_IMPLEMENTED;
1771 }
1772
1773 /*
1774 * @implemented
1775 */
1776 NTSTATUS
1777 NTAPI
1778 RxCommonDeviceControl(
1779 PRX_CONTEXT Context)
1780 {
1781 NTSTATUS Status;
1782
1783 PAGED_CODE();
1784
1785 /* Prefix claim is only allowed for device, not files */
1786 if (Context->CurrentIrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_REDIR_QUERY_PATH)
1787 {
1788 return STATUS_INVALID_DEVICE_REQUEST;
1789 }
1790
1791 /* Submit to mini-rdr */
1792 RxInitializeLowIoContext(&Context->LowIoContext, LOWIO_OP_IOCTL);
1793 Status = RxLowIoSubmit(Context, RxLowIoIoCtlShellCompletion);
1794 if (Status == STATUS_PENDING)
1795 {
1796 RxDereferenceAndDeleteRxContext_Real(Context);
1797 }
1798
1799 return Status;
1800 }
1801
1802 /*
1803 * @implemented
1804 */
1805 NTSTATUS
1806 NTAPI
1807 RxCommonDirectoryControl(
1808 PRX_CONTEXT Context)
1809 {
1810 PFCB Fcb;
1811 PFOBX Fobx;
1812 NTSTATUS Status;
1813 PIO_STACK_LOCATION Stack;
1814
1815 PAGED_CODE();
1816
1817 Fcb = (PFCB)Context->pFcb;
1818 Fobx = (PFOBX)Context->pFobx;
1819 Stack = Context->CurrentIrpSp;
1820 DPRINT("RxCommonDirectoryControl(%p) FOBX: %p, FCB: %p, Minor: %d\n", Context, Fobx, Fcb, Stack->MinorFunction);
1821
1822 /* Call the appropriate helper */
1823 if (Stack->MinorFunction == IRP_MN_QUERY_DIRECTORY)
1824 {
1825 Status = RxQueryDirectory(Context);
1826 }
1827 else if (Stack->MinorFunction == IRP_MN_NOTIFY_CHANGE_DIRECTORY)
1828 {
1829 Status = RxNotifyChangeDirectory(Context);
1830 if (Status == STATUS_PENDING)
1831 {
1832 RxDereferenceAndDeleteRxContext_Real(Context);
1833 }
1834 }
1835 else
1836 {
1837 Status = STATUS_INVALID_DEVICE_REQUEST;
1838 }
1839
1840 return Status;
1841 }
1842
1843 NTSTATUS
1844 NTAPI
1845 RxCommonDispatchProblem(
1846 PRX_CONTEXT Context)
1847 {
1848 UNIMPLEMENTED;
1849 return STATUS_NOT_IMPLEMENTED;
1850 }
1851
1852 NTSTATUS
1853 NTAPI
1854 RxCommonFileSystemControl(
1855 PRX_CONTEXT Context)
1856 {
1857 UNIMPLEMENTED;
1858 return STATUS_NOT_IMPLEMENTED;
1859 }
1860
1861 NTSTATUS
1862 NTAPI
1863 RxCommonFlushBuffers(
1864 PRX_CONTEXT Context)
1865 {
1866 UNIMPLEMENTED;
1867 return STATUS_NOT_IMPLEMENTED;
1868 }
1869
1870 NTSTATUS
1871 NTAPI
1872 RxCommonLockControl(
1873 PRX_CONTEXT Context)
1874 {
1875 UNIMPLEMENTED;
1876 return STATUS_NOT_IMPLEMENTED;
1877 }
1878
1879 NTSTATUS
1880 NTAPI
1881 RxCommonQueryEa(
1882 PRX_CONTEXT Context)
1883 {
1884 UNIMPLEMENTED;
1885 return STATUS_NOT_IMPLEMENTED;
1886 }
1887
1888 /*
1889 * @implemented
1890 */
1891 NTSTATUS
1892 NTAPI
1893 RxCommonQueryInformation(
1894 PRX_CONTEXT Context)
1895 {
1896 #define SET_SIZE_AND_QUERY(AlreadyConsummed, Function) \
1897 Context->Info.Length = Stack->Parameters.QueryFile.Length - (AlreadyConsummed); \
1898 Status = Function(Context, Add2Ptr(Buffer, AlreadyConsummed))
1899
1900 PFCB Fcb;
1901 PIRP Irp;
1902 PFOBX Fobx;
1903 BOOLEAN Locked;
1904 NTSTATUS Status;
1905 PIO_STACK_LOCATION Stack;
1906 FILE_INFORMATION_CLASS FileInfoClass;
1907
1908 PAGED_CODE();
1909
1910 Fcb = (PFCB)Context->pFcb;
1911 Fobx = (PFOBX)Context->pFobx;
1912 DPRINT("RxCommonQueryInformation(%p) FCB: %p, FOBX: %p\n", Context, Fcb, Fobx);
1913
1914 Irp = Context->CurrentIrp;
1915 Stack = Context->CurrentIrpSp;
1916 DPRINT("Buffer: %p, Length: %lx, Class: %ld\n", Irp->AssociatedIrp.SystemBuffer,
1917 Stack->Parameters.QueryFile.Length, Stack->Parameters.QueryFile.FileInformationClass);
1918
1919 Context->Info.Length = Stack->Parameters.QueryFile.Length;
1920 FileInfoClass = Stack->Parameters.QueryFile.FileInformationClass;
1921
1922 Locked = FALSE;
1923 _SEH2_TRY
1924 {
1925 PVOID Buffer;
1926
1927 /* Get a writable buffer */
1928 Buffer = RxMapSystemBuffer(Context);
1929 if (Buffer == NULL)
1930 {
1931 Status = STATUS_INSUFFICIENT_RESOURCES;
1932 _SEH2_LEAVE;
1933 }
1934 /* Zero it */
1935 RtlZeroMemory(Buffer, Context->Info.Length);
1936
1937 /* Validate file type */
1938 if (NodeType(Fcb) != RDBSS_NTC_STORAGE_TYPE_UNKNOWN)
1939 {
1940 if (NodeType(Fcb) < RDBSS_NTC_STORAGE_TYPE_DIRECTORY)
1941 {
1942 Status = STATUS_INVALID_PARAMETER;
1943 _SEH2_LEAVE;
1944 }
1945 else if (NodeType(Fcb) > RDBSS_NTC_STORAGE_TYPE_FILE)
1946 {
1947 if (NodeType(Fcb) == RDBSS_NTC_MAILSLOT)
1948 {
1949 Status = STATUS_NOT_IMPLEMENTED;
1950 }
1951 else
1952 {
1953 Status = STATUS_INVALID_PARAMETER;
1954 }
1955
1956 _SEH2_LEAVE;
1957 }
1958 }
1959
1960 /* Acquire the right lock */
1961 if (!BooleanFlagOn(Fcb->FcbState, FCB_STATE_PAGING_FILE) &&
1962 FileInfoClass != FileNameInformation)
1963 {
1964 if (FileInfoClass == FileCompressionInformation)
1965 {
1966 Status = RxAcquireExclusiveFcb(Context, Fcb);
1967 }
1968 else
1969 {
1970 Status = RxAcquireSharedFcb(Context, Fcb);
1971 }
1972
1973 if (Status == STATUS_LOCK_NOT_GRANTED)
1974 {
1975 Status = STATUS_PENDING;
1976 _SEH2_LEAVE;
1977 }
1978 else if (!NT_SUCCESS(Status))
1979 {
1980 _SEH2_LEAVE;
1981 }
1982
1983 Locked = TRUE;
1984 }
1985
1986 /* Dispatch to the right helper */
1987 switch (FileInfoClass)
1988 {
1989 case FileBasicInformation:
1990 Status = RxQueryBasicInfo(Context, Buffer);
1991 break;
1992
1993 case FileStandardInformation:
1994 Status = RxQueryStandardInfo(Context, Buffer);
1995 break;
1996
1997 case FileInternalInformation:
1998 Status = RxQueryInternalInfo(Context, Buffer);
1999 break;
2000
2001 case FileEaInformation:
2002 Status = RxQueryEaInfo(Context, Buffer);
2003 break;
2004
2005 case FileNameInformation:
2006 Status = RxQueryNameInfo(Context, Buffer);
2007 break;
2008
2009 case FileAllInformation:
2010 SET_SIZE_AND_QUERY(0, RxQueryBasicInfo);
2011 if (!NT_SUCCESS(Status))
2012 {
2013 break;
2014 }
2015
2016 SET_SIZE_AND_QUERY(sizeof(FILE_BASIC_INFORMATION), RxQueryStandardInfo);
2017 if (!NT_SUCCESS(Status))
2018 {
2019 break;
2020 }
2021
2022 SET_SIZE_AND_QUERY(sizeof(FILE_BASIC_INFORMATION) +
2023 sizeof(FILE_STANDARD_INFORMATION), RxQueryInternalInfo);
2024 if (!NT_SUCCESS(Status))
2025 {
2026 break;
2027 }
2028
2029 SET_SIZE_AND_QUERY(sizeof(FILE_BASIC_INFORMATION) +
2030 sizeof(FILE_STANDARD_INFORMATION) +
2031 sizeof(FILE_INTERNAL_INFORMATION), RxQueryEaInfo);
2032 if (!NT_SUCCESS(Status))
2033 {
2034 break;
2035 }
2036
2037 SET_SIZE_AND_QUERY(sizeof(FILE_BASIC_INFORMATION) +
2038 sizeof(FILE_STANDARD_INFORMATION) +
2039 sizeof(FILE_INTERNAL_INFORMATION) +
2040 sizeof(FILE_EA_INFORMATION), RxQueryPositionInfo);
2041 if (!NT_SUCCESS(Status))
2042 {
2043 break;
2044 }
2045
2046 SET_SIZE_AND_QUERY(sizeof(FILE_BASIC_INFORMATION) +
2047 sizeof(FILE_STANDARD_INFORMATION) +
2048 sizeof(FILE_INTERNAL_INFORMATION) +
2049 sizeof(FILE_EA_INFORMATION) +
2050 sizeof(FILE_POSITION_INFORMATION), RxQueryNameInfo);
2051 break;
2052
2053 case FileAlternateNameInformation:
2054 Status = RxQueryAlternateNameInfo(Context, Buffer);
2055 break;
2056
2057 case FilePipeInformation:
2058 case FilePipeLocalInformation:
2059 case FilePipeRemoteInformation:
2060 Status = RxQueryPipeInfo(Context, Buffer);
2061 break;
2062
2063 case FileCompressionInformation:
2064 Status = RxQueryCompressedInfo(Context, Buffer);
2065 break;
2066
2067 default:
2068 Context->IoStatusBlock.Status = RxpQueryInfoMiniRdr(Context, FileInfoClass, Buffer);
2069 Status = Context->IoStatusBlock.Status;
2070 break;
2071 }
2072
2073 if (Context->Info.Length < 0)
2074 {
2075 Status = STATUS_BUFFER_OVERFLOW;
2076 Context->Info.Length = Stack->Parameters.QueryFile.Length;
2077 }
2078
2079 Irp->IoStatus.Information = Stack->Parameters.QueryFile.Length - Context->Info.Length;
2080 }
2081 _SEH2_FINALLY
2082 {
2083 if (Locked)
2084 {
2085 RxReleaseFcb(Context, Fcb);
2086 }
2087 }
2088 _SEH2_END;
2089
2090 DPRINT("Status: %x\n", Status);
2091 return Status;
2092
2093 #undef SET_SIZE_AND_QUERY
2094 }
2095
2096 NTSTATUS
2097 NTAPI
2098 RxCommonQueryQuotaInformation(
2099 PRX_CONTEXT Context)
2100 {
2101 UNIMPLEMENTED;
2102 return STATUS_NOT_IMPLEMENTED;
2103 }
2104
2105 NTSTATUS
2106 NTAPI
2107 RxCommonQuerySecurity(
2108 PRX_CONTEXT Context)
2109 {
2110 UNIMPLEMENTED;
2111 return STATUS_NOT_IMPLEMENTED;
2112 }
2113
2114 /*
2115 * @implemented
2116 */
2117 NTSTATUS
2118 NTAPI
2119 RxCommonQueryVolumeInformation(
2120 PRX_CONTEXT Context)
2121 {
2122 PIRP Irp;
2123 PFCB Fcb;
2124 PFOBX Fobx;
2125 NTSTATUS Status;
2126 PIO_STACK_LOCATION Stack;
2127
2128 PAGED_CODE();
2129
2130 Fcb = (PFCB)Context->pFcb;
2131 Fobx = (PFOBX)Context->pFobx;
2132
2133 DPRINT("RxCommonQueryVolumeInformation(%p) FCB: %p, FOBX: %p\n", Context, Fcb, Fobx);
2134
2135 Irp = Context->CurrentIrp;
2136 Stack = Context->CurrentIrpSp;
2137 DPRINT("Length: %lx, Class: %lx, Buffer %p\n", Stack->Parameters.QueryVolume.Length,
2138 Stack->Parameters.QueryVolume.FsInformationClass, Irp->AssociatedIrp.SystemBuffer);
2139
2140 Context->Info.FsInformationClass = Stack->Parameters.QueryVolume.FsInformationClass;
2141 Context->Info.Buffer = Irp->AssociatedIrp.SystemBuffer;
2142 Context->Info.Length = Stack->Parameters.QueryVolume.Length;
2143
2144 /* Forward to mini-rdr */
2145 MINIRDR_CALL(Status, Context, Fcb->MRxDispatch, MRxQueryVolumeInfo, (Context));
2146
2147 /* Post request if mini-rdr asked to */
2148 if (Context->PostRequest)
2149 {
2150 Status = RxFsdPostRequest(Context);
2151 }
2152 else
2153 {
2154 Irp->IoStatus.Information = Stack->Parameters.QueryVolume.Length - Context->Info.Length;
2155 }
2156
2157 DPRINT("Status: %x\n", Status);
2158 return Status;
2159 }
2160
2161 NTSTATUS
2162 NTAPI
2163 RxCommonRead(
2164 PRX_CONTEXT RxContext)
2165 {
2166 PFCB Fcb;
2167 PIRP Irp;
2168 PFOBX Fobx;
2169 NTSTATUS Status;
2170 PNET_ROOT NetRoot;
2171 PVOID SystemBuffer;
2172 PFILE_OBJECT FileObject;
2173 LARGE_INTEGER ByteOffset;
2174 PIO_STACK_LOCATION Stack;
2175 PLOWIO_CONTEXT LowIoContext;
2176 PRDBSS_DEVICE_OBJECT RxDeviceObject;
2177 ULONG ReadLength, CapturedRxContextSerialNumber = RxContext->SerialNumber;
2178 BOOLEAN CanWait, PagingIo, NoCache, Sync, PostRequest, IsPipe, ReadCachingEnabled, ReadCachingDisabled, InFsp, OwnerSet;
2179
2180 PAGED_CODE();
2181
2182 Fcb = (PFCB)RxContext->pFcb;
2183 Fobx = (PFOBX)RxContext->pFobx;
2184 DPRINT("RxCommonRead(%p) FOBX: %p, FCB: %p\n", RxContext, Fobx, Fcb);
2185
2186 /* Get some parameters */
2187 Irp = RxContext->CurrentIrp;
2188 Stack = RxContext->CurrentIrpSp;
2189 CanWait = BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_WAIT);
2190 PagingIo = BooleanFlagOn(Irp->Flags, IRP_PAGING_IO);
2191 NoCache = BooleanFlagOn(Irp->Flags, IRP_NOCACHE);
2192 Sync = !BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_ASYNC_OPERATION);
2193 InFsp = BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_IN_FSP);
2194 ReadLength = Stack->Parameters.Read.Length;
2195 ByteOffset.QuadPart = Stack->Parameters.Read.ByteOffset.QuadPart;
2196 DPRINT("Reading: %lx@%I64x %s %s %s %s\n", ReadLength, ByteOffset.QuadPart,
2197 (CanWait ? "CW" : "!CW"), (PagingIo ? "PI" : "!PI"), (NoCache ? "NC" : "!NC"), (Sync ? "S" : "!S"));
2198
2199 RxItsTheSameContext();
2200
2201 Irp->IoStatus.Information = 0;
2202
2203 /* Should the read be loud - so far, it's just ignored on ReactOS:
2204 * s/DPRINT/DPRINT1/g will make it loud
2205 */
2206 LowIoContext = &RxContext->LowIoContext;
2207 CheckForLoudOperations(RxContext);
2208 if (BooleanFlagOn(LowIoContext->Flags, LOWIO_CONTEXT_FLAG_LOUDOPS))
2209 {
2210 DPRINT("LoudRead %I64x/%lx on %lx vdl/size/alloc %I64x/%I64x/%I64x\n",
2211 ByteOffset, ReadLength,
2212 Fcb, Fcb->Header.ValidDataLength, Fcb->Header.FileSize, Fcb->Header.AllocationSize);
2213 }
2214
2215 RxDeviceObject = RxContext->RxDeviceObject;
2216 /* Update stats */
2217 if (!BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_IN_FSP) && Fcb->CachedNetRootType == NET_ROOT_DISK)
2218 {
2219 InterlockedIncrement((volatile long *)&RxDeviceObject->ReadOperations);
2220
2221 if (ByteOffset.QuadPart != Fobx->Specific.DiskFile.PredictedReadOffset)
2222 {
2223 InterlockedIncrement((volatile long *)&RxDeviceObject->RandomReadOperations);
2224 }
2225 Fobx->Specific.DiskFile.PredictedReadOffset = ByteOffset.QuadPart + ReadLength;
2226
2227 if (PagingIo)
2228 {
2229 ExInterlockedAddLargeStatistic(&RxDeviceObject->PagingReadBytesRequested, ReadLength);
2230 }
2231 else if (NoCache)
2232 {
2233 ExInterlockedAddLargeStatistic(&RxDeviceObject->NonPagingReadBytesRequested, ReadLength);
2234 }
2235 else
2236 {
2237 ExInterlockedAddLargeStatistic(&RxDeviceObject->CacheReadBytesRequested, ReadLength);
2238 }
2239 }
2240
2241 /* A pagefile cannot be a pipe */
2242 IsPipe = Fcb->NetRoot->Type == NET_ROOT_PIPE;
2243 if (IsPipe && PagingIo)
2244 {
2245 return STATUS_INVALID_DEVICE_REQUEST;
2246 }
2247
2248 /* Null-length read is no-op */
2249 if (ReadLength == 0)
2250 {
2251 return STATUS_SUCCESS;
2252 }
2253
2254 /* Validate FCB type */
2255 if (NodeType(Fcb) != RDBSS_NTC_STORAGE_TYPE_FILE && NodeType(Fcb) != RDBSS_NTC_VOLUME_FCB)
2256 {
2257 return STATUS_INVALID_DEVICE_REQUEST;
2258 }
2259
2260 /* Init the lowio context for possible forward */
2261 RxInitializeLowIoContext(LowIoContext, LOWIO_OP_READ);
2262
2263 PostRequest = FALSE;
2264 ReadCachingDisabled = FALSE;
2265 OwnerSet = FALSE;
2266 ReadCachingEnabled = BooleanFlagOn(Fcb->FcbState, FCB_STATE_READCACHING_ENABLED);
2267 FileObject = Stack->FileObject;
2268 NetRoot = (PNET_ROOT)Fcb->pNetRoot;
2269 _SEH2_TRY
2270 {
2271 LONGLONG FileSize;
2272
2273 /* If no caching, make sure current Cc data have been flushed */
2274 if (!PagingIo && NoCache && !ReadCachingEnabled && FileObject->SectionObjectPointer != NULL)
2275 {
2276 Status = RxAcquireExclusiveFcb(RxContext, Fcb);
2277 if (Status == STATUS_LOCK_NOT_GRANTED)
2278 {
2279 PostRequest = TRUE;
2280 _SEH2_LEAVE;
2281 }
2282 else if (Status != STATUS_SUCCESS)
2283 {
2284 _SEH2_LEAVE;
2285 }
2286
2287 ExAcquireResourceSharedLite(Fcb->Header.PagingIoResource, TRUE);
2288 CcFlushCache(FileObject->SectionObjectPointer, &ByteOffset, ReadLength, &Irp->IoStatus);
2289 RxReleasePagingIoResource(RxContext, Fcb);
2290
2291 if (!NT_SUCCESS(Irp->IoStatus.Status))
2292 {
2293 _SEH2_LEAVE;
2294 }
2295
2296 RxAcquirePagingIoResource(RxContext, Fcb);
2297 RxReleasePagingIoResource(RxContext, Fcb);
2298 }
2299
2300 /* Acquire the appropriate lock */
2301 if (PagingIo && !ReadCachingEnabled)
2302 {
2303 ASSERT(!IsPipe);
2304
2305 if (!ExAcquireResourceSharedLite(Fcb->Header.PagingIoResource, CanWait))
2306 {
2307 PostRequest = TRUE;
2308 _SEH2_LEAVE;
2309 }
2310
2311 if (!CanWait)
2312 {
2313 LowIoContext->Resource = Fcb->Header.PagingIoResource;
2314 }
2315 }
2316 else
2317 {
2318 if (!ReadCachingEnabled)
2319 {
2320 if (!CanWait && NoCache)
2321 {
2322 Status = RxAcquireSharedFcbWaitForEx(RxContext, Fcb);
2323 if (Status == STATUS_LOCK_NOT_GRANTED)
2324 {
2325 DPRINT1("RdAsyLNG %x\n", RxContext);
2326 PostRequest = TRUE;
2327 _SEH2_LEAVE;
2328 }
2329 if (Status != STATUS_SUCCESS)
2330 {
2331 DPRINT1("RdAsyOthr %x\n", RxContext);
2332 _SEH2_LEAVE;
2333 }
2334
2335 if (RxIsFcbAcquiredShared(Fcb) <= 0xF000)
2336 {
2337 LowIoContext->Resource = Fcb->Header.Resource;
2338 }
2339 else
2340 {
2341 PostRequest = TRUE;
2342 _SEH2_LEAVE;
2343 }
2344 }
2345 else
2346 {
2347 Status = RxAcquireSharedFcb(RxContext, Fcb);
2348 if (Status == STATUS_LOCK_NOT_GRANTED)
2349 {
2350 PostRequest = TRUE;
2351 _SEH2_LEAVE;
2352 }
2353 else if (Status != STATUS_SUCCESS)
2354 {
2355 _SEH2_LEAVE;
2356 }
2357 }
2358 }
2359 }
2360
2361 RxItsTheSameContext();
2362
2363 ReadCachingDisabled = (ReadCachingEnabled == FALSE);
2364 if (IsPipe)
2365 {
2366 UNIMPLEMENTED;
2367 }
2368
2369 RxGetFileSizeWithLock(Fcb, &FileSize);
2370
2371 /* Make sure FLOCK doesn't conflict */
2372 if (!PagingIo)
2373 {
2374 if (!FsRtlCheckLockForReadAccess(&Fcb->Specific.Fcb.FileLock, Irp))
2375 {
2376 Status = STATUS_FILE_LOCK_CONFLICT;
2377 _SEH2_LEAVE;
2378 }
2379 }
2380
2381 /* Validate byteoffset vs length */
2382 if (BooleanFlagOn(Fcb->FcbState, FCB_STATE_READCACHING_ENABLED))
2383 {
2384 if (ByteOffset.QuadPart >= FileSize)
2385 {
2386 Status = STATUS_END_OF_FILE;
2387 _SEH2_LEAVE;
2388 }
2389
2390 if (ReadLength > FileSize - ByteOffset.QuadPart)
2391 {
2392 ReadLength = FileSize - ByteOffset.QuadPart;
2393 }
2394 }
2395
2396 /* Read with Cc! */
2397 if (!PagingIo && !NoCache && ReadCachingEnabled &&
2398 !BooleanFlagOn(Fobx->pSrvOpen->Flags, SRVOPEN_FLAG_DONTUSE_READ_CACHING))
2399 {
2400 /* File was not cached yet, do it */
2401 if (FileObject->PrivateCacheMap == NULL)
2402 {
2403 if (BooleanFlagOn(FileObject->Flags, FO_CLEANUP_COMPLETE))
2404 {
2405 Status = STATUS_FILE_CLOSED;
2406 _SEH2_LEAVE;
2407 }
2408
2409 RxAdjustAllocationSizeforCC(Fcb);
2410
2411 CcInitializeCacheMap(FileObject, (PCC_FILE_SIZES)&Fcb->Header.AllocationSize,
2412 FALSE, &RxData.CacheManagerCallbacks, Fcb);
2413
2414 if (BooleanFlagOn(Fcb->MRxDispatch->MRxFlags, RDBSS_NO_DEFERRED_CACHE_READAHEAD))
2415 {
2416 CcSetAdditionalCacheAttributes(FileObject, FALSE, FALSE);
2417 }
2418 else
2419 {
2420 CcSetAdditionalCacheAttributes(FileObject, TRUE, FALSE);
2421 SetFlag(Fcb->FcbState, FCB_STATE_READAHEAD_DEFERRED);
2422 }
2423
2424 CcSetReadAheadGranularity(FileObject, NetRoot->DiskParameters.ReadAheadGranularity);
2425 }
2426
2427 /* This should never happen - fix your RDR */
2428 if (BooleanFlagOn(RxContext->MinorFunction, IRP_MN_MDL))
2429 {
2430 ASSERT(FALSE);
2431 ASSERT(CanWait);
2432
2433 CcMdlRead(FileObject, &ByteOffset, ReadLength, &Irp->MdlAddress, &Irp->IoStatus);
2434 Status = Irp->IoStatus.Status;
2435 ASSERT(NT_SUCCESS(Status));
2436 }
2437 else
2438 {
2439 /* Map buffer */
2440 SystemBuffer = RxNewMapUserBuffer(RxContext);
2441 if (SystemBuffer == NULL)
2442 {
2443 Status = STATUS_INSUFFICIENT_RESOURCES;
2444 _SEH2_LEAVE;
2445 }
2446
2447 SetFlag(Fcb->FcbState, FCB_STATE_READCACHING_ENABLED);
2448
2449 RxItsTheSameContext();
2450
2451 /* Perform the read */
2452 if (!CcCopyRead(FileObject, &ByteOffset, ReadLength, CanWait, SystemBuffer, &Irp->IoStatus))
2453 {
2454 if (!ReadCachingEnabled)
2455 {
2456 ClearFlag(Fcb->FcbState, FCB_STATE_READCACHING_ENABLED);
2457 }
2458
2459 RxItsTheSameContext();
2460
2461 PostRequest = TRUE;
2462 _SEH2_LEAVE;
2463 }
2464
2465 if (!ReadCachingEnabled)
2466 {
2467 ClearFlag(Fcb->FcbState, FCB_STATE_READCACHING_ENABLED);
2468 }
2469
2470 Status = Irp->IoStatus.Status;
2471 ASSERT(NT_SUCCESS(Status));
2472 }
2473 }
2474 else
2475 {
2476 /* Validate the reading */
2477 if (FileObject->PrivateCacheMap != NULL && BooleanFlagOn(Fcb->FcbState, FCB_STATE_READAHEAD_DEFERRED) &&
2478 ByteOffset.QuadPart >= 4096)
2479 {
2480 CcSetAdditionalCacheAttributes(FileObject, FALSE, FALSE);
2481 ClearFlag(Fcb->FcbState, FCB_STATE_READAHEAD_DEFERRED);
2482 }
2483
2484 /* If it's consistent, forward to mini-rdr */
2485 if (Fcb->CachedNetRootType != NET_ROOT_DISK || BooleanFlagOn(Fcb->FcbState, FCB_STATE_READAHEAD_DEFERRED) ||
2486 ByteOffset.QuadPart < Fcb->Header.ValidDataLength.QuadPart)
2487 {
2488 LowIoContext->ParamsFor.ReadWrite.ByteCount = ReadLength;
2489 LowIoContext->ParamsFor.ReadWrite.ByteOffset = ByteOffset.QuadPart;
2490
2491 RxItsTheSameContext();
2492
2493 if (InFsp && ReadCachingDisabled)
2494 {
2495 ExSetResourceOwnerPointer((PagingIo ? Fcb->Header.PagingIoResource : Fcb->Header.Resource),
2496 (PVOID)((ULONG_PTR)RxContext | 3));
2497 OwnerSet = TRUE;
2498 }
2499
2500 Status = RxLowIoReadShell(RxContext);
2501
2502 RxItsTheSameContext();
2503 }
2504 else
2505 {
2506 if (ByteOffset.QuadPart > FileSize)
2507 {
2508 ReadLength = 0;
2509 Irp->IoStatus.Information = ReadLength;
2510 _SEH2_LEAVE;
2511 }
2512
2513 if (ByteOffset.QuadPart + ReadLength > FileSize)
2514 {
2515 ReadLength = FileSize - ByteOffset.QuadPart;
2516 }
2517
2518 SystemBuffer = RxNewMapUserBuffer(RxContext);
2519 RtlZeroMemory(SystemBuffer, ReadLength);
2520 Irp->IoStatus.Information = ReadLength;
2521 }
2522 }
2523 }
2524 _SEH2_FINALLY
2525 {
2526 RxItsTheSameContext();
2527
2528 /* Post if required */
2529 if (PostRequest)
2530 {
2531 InterlockedIncrement((volatile long *)&RxContext->ReferenceCount);
2532 Status = RxFsdPostRequest(RxContext);
2533 }
2534 else
2535 {
2536 /* Update FO in case of sync IO */
2537 if (!IsPipe && !PagingIo)
2538 {
2539 if (BooleanFlagOn(FileObject->Flags, FO_SYNCHRONOUS_IO))
2540 {
2541 FileObject->CurrentByteOffset.QuadPart = ByteOffset.QuadPart + Irp->IoStatus.Information;
2542 }
2543 }
2544 }
2545
2546 /* Set FastIo if read was a success */
2547 if (NT_SUCCESS(Status) && Status != STATUS_PENDING)
2548 {
2549 if (!IsPipe && !PagingIo)
2550 {
2551 SetFlag(FileObject->Flags, FO_FILE_FAST_IO_READ);
2552 }
2553 }
2554
2555 /* In case we're done (not expected any further processing */
2556 if (_SEH2_AbnormalTermination() || Status != STATUS_PENDING || PostRequest)
2557 {
2558 /* Release everything that can be */
2559 if (ReadCachingDisabled)
2560 {
2561 if (PagingIo)
2562 {
2563 if (OwnerSet)
2564 {
2565 RxReleasePagingIoResourceForThread(RxContext, Fcb, LowIoContext->ResourceThreadId);
2566 }
2567 else
2568 {
2569 RxReleasePagingIoResource(RxContext, Fcb);
2570 }
2571 }
2572 else
2573 {
2574 if (OwnerSet)
2575 {
2576 RxReleaseFcbForThread(RxContext, Fcb, LowIoContext->ResourceThreadId);
2577 }
2578 else
2579 {
2580 RxReleaseFcb(RxContext, Fcb);
2581 }
2582 }
2583 }
2584
2585 /* Dereference/Delete context */
2586 if (PostRequest)
2587 {
2588 RxDereferenceAndDeleteRxContext(RxContext);
2589 }
2590 else
2591 {
2592 if (BooleanFlagOn(RxContext->FlagsForLowIo, RXCONTEXT_FLAG4LOWIO_PIPE_SYNC_OPERATION))
2593 {
2594 RxResumeBlockedOperations_Serially(RxContext, &Fobx->Specific.NamedPipe.ReadSerializationQueue);
2595 }
2596 }
2597
2598 /* We cannot return more than asked */
2599 if (Status == STATUS_SUCCESS)
2600 {
2601 ASSERT(Irp->IoStatus.Information <= Stack->Parameters.Read.Length);
2602 }
2603 }
2604 else
2605 {
2606 ASSERT(!Sync);
2607
2608 RxDereferenceAndDeleteRxContext(RxContext);
2609 }
2610 }
2611 _SEH2_END;
2612
2613 return Status;
2614 }
2615
2616 NTSTATUS
2617 NTAPI
2618 RxCommonSetEa(
2619 PRX_CONTEXT Context)
2620 {
2621 UNIMPLEMENTED;
2622 return STATUS_NOT_IMPLEMENTED;
2623 }
2624
2625 NTSTATUS
2626 NTAPI
2627 RxCommonSetInformation(
2628 PRX_CONTEXT Context)
2629 {
2630 UNIMPLEMENTED;
2631 return STATUS_NOT_IMPLEMENTED;
2632 }
2633
2634 NTSTATUS
2635 NTAPI
2636 RxCommonSetQuotaInformation(
2637 PRX_CONTEXT Context)
2638 {
2639 UNIMPLEMENTED;
2640 return STATUS_NOT_IMPLEMENTED;
2641 }
2642
2643 NTSTATUS
2644 NTAPI
2645 RxCommonSetSecurity(
2646 PRX_CONTEXT Context)
2647 {
2648 UNIMPLEMENTED;
2649 return STATUS_NOT_IMPLEMENTED;
2650 }
2651
2652 NTSTATUS
2653 NTAPI
2654 RxCommonSetVolumeInformation(
2655 PRX_CONTEXT Context)
2656 {
2657 UNIMPLEMENTED;
2658 return STATUS_NOT_IMPLEMENTED;
2659 }
2660
2661 NTSTATUS
2662 NTAPI
2663 RxCommonUnimplemented(
2664 PRX_CONTEXT Context)
2665 {
2666 UNIMPLEMENTED;
2667 return STATUS_NOT_IMPLEMENTED;
2668 }
2669
2670 NTSTATUS
2671 NTAPI
2672 RxCommonWrite(
2673 PRX_CONTEXT Context)
2674 {
2675 UNIMPLEMENTED;
2676 return STATUS_NOT_IMPLEMENTED;
2677 }
2678
2679 NTSTATUS
2680 NTAPI
2681 RxCompleteMdl(
2682 IN PRX_CONTEXT RxContext)
2683 {
2684 PAGED_CODE();
2685
2686 UNIMPLEMENTED;
2687 return STATUS_NOT_IMPLEMENTED;
2688 }
2689
2690 /*
2691 * @implemented
2692 */
2693 VOID
2694 RxCopyCreateParameters(
2695 IN PRX_CONTEXT RxContext)
2696 {
2697 PIRP Irp;
2698 PVOID DfsContext;
2699 PFILE_OBJECT FileObject;
2700 PIO_STACK_LOCATION Stack;
2701 PDFS_NAME_CONTEXT DfsNameContext;
2702 PIO_SECURITY_CONTEXT SecurityContext;
2703
2704 Irp = RxContext->CurrentIrp;
2705 Stack = RxContext->CurrentIrpSp;
2706 FileObject = Stack->FileObject;
2707 SecurityContext = Stack->Parameters.Create.SecurityContext;
2708
2709 RxContext->Create.NtCreateParameters.SecurityContext = SecurityContext;
2710 if (SecurityContext->AccessState != NULL && SecurityContext->AccessState->SecurityDescriptor != NULL)
2711 {
2712 RxContext->Create.SdLength = RtlLengthSecurityDescriptor(SecurityContext->AccessState->SecurityDescriptor);
2713 DPRINT("SD Ctxt: %p, Length: %lx\n", RxContext->Create.NtCreateParameters.SecurityContext,
2714 RxContext->Create.SdLength);
2715 }
2716 if (SecurityContext->SecurityQos != NULL)
2717 {
2718 RxContext->Create.NtCreateParameters.ImpersonationLevel = SecurityContext->SecurityQos->ImpersonationLevel;
2719 }
2720 else
2721 {
2722 RxContext->Create.NtCreateParameters.ImpersonationLevel = SecurityImpersonation;
2723 }
2724 RxContext->Create.NtCreateParameters.DesiredAccess = SecurityContext->DesiredAccess;
2725
2726 RxContext->Create.NtCreateParameters.AllocationSize.QuadPart = Irp->Overlay.AllocationSize.QuadPart;
2727 RxContext->Create.NtCreateParameters.FileAttributes = Stack->Parameters.Create.FileAttributes & FILE_ATTRIBUTE_VALID_FLAGS;
2728 RxContext->Create.NtCreateParameters.ShareAccess = Stack->Parameters.Create.ShareAccess & FILE_SHARE_VALID_FLAGS;
2729 RxContext->Create.NtCreateParameters.Disposition = (Stack->Parameters.Create.Options >> 24) & 0x000000FF;
2730 RxContext->Create.NtCreateParameters.CreateOptions = Stack->Parameters.Create.Options & 0xFFFFFF;
2731
2732 DfsContext = FileObject->FsContext2;
2733 DfsNameContext = FileObject->FsContext;
2734 RxContext->Create.NtCreateParameters.DfsContext = DfsContext;
2735 RxContext->Create.NtCreateParameters.DfsNameContext = DfsNameContext;
2736 ASSERT(DfsContext == NULL || DfsContext == UIntToPtr(DFS_OPEN_CONTEXT) ||
2737 DfsContext == UIntToPtr(DFS_DOWNLEVEL_OPEN_CONTEXT) ||
2738 DfsContext == UIntToPtr(DFS_CSCAGENT_NAME_CONTEXT) ||
2739 DfsContext == UIntToPtr(DFS_USER_NAME_CONTEXT));
2740 ASSERT(DfsNameContext == NULL || DfsNameContext->NameContextType == DFS_OPEN_CONTEXT ||
2741 DfsNameContext->NameContextType == DFS_DOWNLEVEL_OPEN_CONTEXT ||
2742 DfsNameContext->NameContextType == DFS_CSCAGENT_NAME_CONTEXT ||
2743 DfsNameContext->NameContextType == DFS_USER_NAME_CONTEXT);
2744 FileObject->FsContext2 = NULL;
2745 FileObject->FsContext = NULL;
2746
2747 RxContext->pFcb = NULL;
2748 RxContext->Create.ReturnedCreateInformation = 0;
2749
2750 /* if we stripped last \, it has to be a directory! */
2751 if (BooleanFlagOn(RxContext->Create.Flags, RX_CONTEXT_CREATE_FLAG_STRIPPED_TRAILING_BACKSLASH))
2752 {
2753 SetFlag(RxContext->Create.NtCreateParameters.CreateOptions, FILE_DIRECTORY_FILE);
2754 }
2755
2756 RxContext->Create.EaLength = Stack->Parameters.Create.EaLength;
2757 if (RxContext->Create.EaLength == 0)
2758 {
2759 RxContext->Create.EaBuffer = NULL;
2760 }
2761 else
2762 {
2763 RxContext->Create.EaBuffer = Irp->AssociatedIrp.SystemBuffer;
2764 DPRINT("EA Buffer: %p, Length: %lx\n", Irp->AssociatedIrp.SystemBuffer, RxContext->Create.EaLength);
2765 }
2766 }
2767
2768 NTSTATUS
2769 RxCreateFromNetRoot(
2770 PRX_CONTEXT Context,
2771 PUNICODE_STRING NetRootName)
2772 {
2773 PFCB Fcb;
2774 NTSTATUS Status;
2775 PNET_ROOT NetRoot;
2776 PFILE_OBJECT FileObject;
2777 PIO_STACK_LOCATION Stack;
2778 ACCESS_MASK DesiredAccess;
2779 USHORT DesiredShareAccess;
2780
2781 PAGED_CODE();
2782
2783 /* Validate that the context is consistent */
2784 if (Context->Create.pNetRoot == NULL)
2785 {
2786 return STATUS_BAD_NETWORK_PATH;
2787 }
2788
2789 NetRoot = (PNET_ROOT)Context->Create.pNetRoot;
2790 if (Context->RxDeviceObject != NetRoot->pSrvCall->RxDeviceObject)
2791 {
2792 return STATUS_BAD_NETWORK_PATH;
2793 }
2794
2795 if (Context->Create.NtCreateParameters.DfsContext == UIntToPtr(DFS_OPEN_CONTEXT) &&
2796 !BooleanFlagOn(NetRoot->pSrvCall->Flags, SRVCALL_FLAG_DFS_AWARE_SERVER))
2797 {
2798 return STATUS_DFS_UNAVAILABLE;
2799 }
2800
2801 if (Context->Create.NtCreateParameters.DfsContext == UIntToPtr(DFS_DOWNLEVEL_OPEN_CONTEXT) &&
2802 BooleanFlagOn(NetRoot->Flags, NETROOT_FLAG_DFS_AWARE_NETROOT))
2803 {
2804 return STATUS_OBJECT_TYPE_MISMATCH;
2805 }
2806
2807 Stack = Context->CurrentIrpSp;
2808 DesiredShareAccess = Stack->Parameters.Create.ShareAccess & FILE_SHARE_VALID_FLAGS;
2809 if (NetRoot->Type == NET_ROOT_PRINT)
2810 {
2811 DesiredShareAccess = FILE_SHARE_VALID_FLAGS;
2812 }
2813
2814 DesiredAccess = Stack->Parameters.Create.SecurityContext->DesiredAccess & FILE_ALL_ACCESS;
2815
2816 /* We don't support renaming yet */
2817 if (BooleanFlagOn(Stack->Flags, SL_OPEN_TARGET_DIRECTORY))
2818 {
2819 UNIMPLEMENTED;
2820 return STATUS_NOT_IMPLEMENTED;
2821 }
2822
2823 /* Try to find (or create) the FCB for the file */
2824 Status = RxFindOrCreateFcb(Context, NetRootName);
2825 Fcb = (PFCB)Context->pFcb;
2826 if (Fcb == NULL)
2827 {
2828 ASSERT(!NT_SUCCESS(Status));
2829 }
2830 if (!NT_SUCCESS(Status) || Fcb == NULL)
2831 {
2832 return Status;
2833 }
2834
2835 if (BooleanFlagOn(Context->Flags, RX_CONTEXT_FLAG_CREATE_MAILSLOT))
2836 {
2837 Fcb->Header.NodeTypeCode = RDBSS_NTC_MAILSLOT;
2838 }
2839 else
2840 {
2841 Status = STATUS_MORE_PROCESSING_REQUIRED;
2842 }
2843
2844 /* If finding FCB worked (mailslot case), mark the FCB as good and quit */
2845 if (NT_SUCCESS(Status))
2846 {
2847 RxTransitionNetFcb(Fcb, Condition_Good);
2848 DPRINT("Transitioning FCB %lx Condition %lx\n", Fcb, Fcb->Condition);
2849 ++Fcb->OpenCount;
2850 RxSetupNetFileObject(Context);
2851 return STATUS_SUCCESS;
2852 }
2853
2854 /* Not mailslot! */
2855 FileObject = Stack->FileObject;
2856 /* Check SA for conflict */
2857 if (Fcb->OpenCount > 0)
2858 {
2859 Status = RxCheckShareAccess(DesiredAccess, DesiredShareAccess, FileObject,
2860 &Fcb->ShareAccess, FALSE, "early check per useropens", "EarlyPerUO");
2861 if (!NT_SUCCESS(Status))
2862 {
2863 RxDereferenceNetFcb(Fcb);
2864 return Status;
2865 }
2866 }
2867
2868 if (BooleanFlagOn(Context->Create.NtCreateParameters.CreateOptions, FILE_DELETE_ON_CLOSE) &&
2869 !BooleanFlagOn(Context->Create.NtCreateParameters.DesiredAccess, ~SYNCHRONIZE))
2870 {
2871 UNIMPLEMENTED;
2872 }
2873
2874 _SEH2_TRY
2875 {
2876 /* Find a SRV_OPEN that suits the opening */
2877 Status = RxCollapseOrCreateSrvOpen(Context);
2878 if (Status == STATUS_SUCCESS)
2879 {
2880 PFOBX Fobx;
2881 PSRV_OPEN SrvOpen;
2882
2883 SrvOpen = (PSRV_OPEN)Context->pRelevantSrvOpen;
2884 Fobx = (PFOBX)Context->pFobx;
2885 /* There are already opens, check for conflict */
2886 if (Fcb->OpenCount != 0)
2887 {
2888 if (!NT_SUCCESS(RxCheckShareAccess(DesiredAccess, DesiredShareAccess,
2889 FileObject, &Fcb->ShareAccess,
2890 FALSE, "second check per useropens",
2891 "2ndAccPerUO")))
2892 {
2893 ++SrvOpen->UncleanFobxCount;
2894 RxDereferenceNetFobx(Fobx, LHS_LockNotHeld);
2895
2896 _SEH2_LEAVE;
2897 }
2898 }
2899 else
2900 {
2901 if (NetRoot->Type != NET_ROOT_PIPE)
2902 {
2903 RxSetShareAccess(DesiredAccess, DesiredShareAccess, FileObject,
2904 &Fcb->ShareAccess, "initial shareaccess setup", "InitShrAcc");
2905 }
2906 }
2907
2908 RxSetupNetFileObject(Context);
2909
2910 /* No conflict? Set up SA */
2911 if (Fcb->OpenCount != 0 && NetRoot->Type != NET_ROOT_PIPE)
2912 {
2913 RxUpdateShareAccess(FileObject, &Fcb->ShareAccess, "update share access", "UpdShrAcc");
2914 }
2915
2916 ++Fcb->UncleanCount;
2917 if (BooleanFlagOn(FileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING))
2918 {
2919 ++Fcb->UncachedUncleanCount;
2920 }
2921
2922 if (SrvOpen->UncleanFobxCount == 0 && Fcb->UncleanCount == 1 &&
2923 !BooleanFlagOn(SrvOpen->Flags, SRVOPEN_FLAG_NO_BUFFERING_STATE_CHANGE))
2924 {
2925 RxChangeBufferingState(SrvOpen, NULL, FALSE);
2926 }
2927
2928 /* No pending close, we're active */
2929 ClearFlag(Fcb->FcbState, FCB_STATE_DELAY_CLOSE);
2930
2931 ++Fcb->OpenCount;
2932 ++SrvOpen->UncleanFobxCount;
2933 ++SrvOpen->OpenCount;
2934 SrvOpen->ulFileSizeVersion = Fcb->ulFileSizeVersion;
2935
2936 if (BooleanFlagOn(Stack->Parameters.Create.Options, FILE_NO_INTERMEDIATE_BUFFERING))
2937 {
2938 SetFlag(SrvOpen->Flags, SRVOPEN_FLAG_DONTUSE_READ_CACHING);
2939 SetFlag(SrvOpen->Flags, SRVOPEN_FLAG_DONTUSE_WRITE_CACHING);
2940
2941 ClearFlag(Fcb->FcbState, FCB_STATE_WRITECACHING_ENABLED);
2942 ClearFlag(Fcb->FcbState, FCB_STATE_READCACHING_ENABLED);
2943
2944 RxPurgeFcbInSystemCache(Fcb, NULL, 0, TRUE, TRUE);
2945 }
2946
2947 /* Now, update SA for the SRV_OPEN */
2948 RxUpdateShareAccessPerSrvOpens(SrvOpen);
2949
2950 if (BooleanFlagOn(Stack->Parameters.Create.Options, FILE_DELETE_ON_CLOSE))
2951 {
2952 SetFlag(Fobx->Flags, FOBX_FLAG_DELETE_ON_CLOSE);
2953 }
2954
2955 /* Update the FOBX info */
2956 if (Fobx != NULL)
2957 {
2958 if (Context->Create.pNetRoot->Type == NET_ROOT_PIPE)
2959 {
2960 SetFlag(FileObject->Flags, FO_NAMED_PIPE);
2961 }
2962
2963 if (Context->Create.pNetRoot->Type == NET_ROOT_PRINT ||
2964 Context->Create.pNetRoot->Type == NET_ROOT_PIPE)
2965 {
2966 Fobx->PipeHandleInformation = &Fobx->Specific.NamedPipe.PipeHandleInformation;
2967
2968 Fobx->Specific.NamedPipe.CollectDataTime.QuadPart = 0;
2969 Fobx->Specific.NamedPipe.CollectDataSize = Context->Create.pNetRoot->NamedPipeParameters.DataCollectionSize;
2970
2971 Fobx->Specific.NamedPipe.PipeHandleInformation.TypeOfPipe = Context->Create.PipeType;
2972 Fobx->Specific.NamedPipe.PipeHandleInformation.ReadMode = Context->Create.PipeReadMode;
2973 Fobx->Specific.NamedPipe.PipeHandleInformation.CompletionMode = Context->Create.PipeCompletionMode;
2974
2975 InitializeListHead(&Fobx->Specific.NamedPipe.ReadSerializationQueue);
2976 InitializeListHead(&Fobx->Specific.NamedPipe.WriteSerializationQueue);
2977 }
2978 }
2979
2980 Status = STATUS_SUCCESS;
2981 }
2982 }
2983 _SEH2_FINALLY
2984 {
2985 if (Fcb->OpenCount == 0)
2986 {
2987 if (Context->Create.FcbAcquired)
2988 {
2989 Context->Create.FcbAcquired = (RxDereferenceAndFinalizeNetFcb(Fcb,
2990 Context,
2991 FALSE,
2992 FALSE) == 0);
2993 if (!Context->Create.FcbAcquired)
2994 {
2995 RxTrackerUpdateHistory(Context, NULL, TRACKER_FCB_FREE, __LINE__, __FILE__, 0);
2996 }
2997 }
2998 }
2999 else
3000 {
3001 RxDereferenceNetFcb(Fcb);
3002 }
3003 }
3004 _SEH2_END;
3005
3006 return Status;
3007 }
3008
3009 /*
3010 * @implemented
3011 */
3012 NTSTATUS
3013 RxCreateTreeConnect(
3014 IN PRX_CONTEXT RxContext)
3015 {
3016 NTSTATUS Status;
3017 PV_NET_ROOT VNetRoot;
3018 PFILE_OBJECT FileObject;
3019 PIO_STACK_LOCATION Stack;
3020 NET_ROOT_TYPE NetRootType;
3021 UNICODE_STRING CanonicalName, RemainingName;
3022
3023 PAGED_CODE();
3024
3025 Stack = RxContext->CurrentIrpSp;
3026 FileObject = Stack->FileObject;
3027
3028 RtlInitEmptyUnicodeString(&CanonicalName, NULL, 0);
3029 /* As long as we don't know connection type, mark it wild */
3030 NetRootType = NET_ROOT_WILD;
3031 /* Get the type by parsing the name */
3032 Status = RxFirstCanonicalize(RxContext, &FileObject->FileName, &CanonicalName, &NetRootType);
3033 if (!NT_SUCCESS(Status))
3034 {
3035 return Status;
3036 }
3037
3038 RxContext->Create.ThisIsATreeConnectOpen = TRUE;
3039 RxContext->Create.TreeConnectOpenDeferred = FALSE;
3040 RtlInitEmptyUnicodeString(&RxContext->Create.TransportName, NULL, 0);
3041 RtlInitEmptyUnicodeString(&RxContext->Create.UserName, NULL, 0);
3042 RtlInitEmptyUnicodeString(&RxContext->Create.Password, NULL, 0);
3043 RtlInitEmptyUnicodeString(&RxContext->Create.UserDomainName, NULL, 0);
3044
3045 /* We don't handle EA - they come from DFS, don't care */
3046 if (Stack->Parameters.Create.EaLength > 0)
3047 {
3048 UNIMPLEMENTED;
3049 }
3050
3051 /* Mount if required */
3052 Status = RxFindOrConstructVirtualNetRoot(RxContext, &CanonicalName, NetRootType, &RemainingName);
3053 if (Status == STATUS_NETWORK_CREDENTIAL_CONFLICT)
3054 {
3055 RxScavengeVNetRoots(RxContext->RxDeviceObject);
3056 Status = RxFindOrConstructVirtualNetRoot(RxContext, &CanonicalName, NetRootType, &RemainingName);
3057 }
3058
3059 if (!NT_SUCCESS(Status))
3060 {
3061 return Status;
3062 }
3063
3064 /* Validate the rest of the name with mini-rdr */
3065 if (RemainingName.Length > 0)
3066 {
3067 MINIRDR_CALL(Status, RxContext,
3068 RxContext->Create.pNetRoot->pSrvCall->RxDeviceObject->Dispatch,
3069 MRxIsValidDirectory, (RxContext, &RemainingName));
3070 }
3071
3072 if (!NT_SUCCESS(Status))
3073 {
3074 return Status;
3075 }
3076
3077 VNetRoot = (PV_NET_ROOT)RxContext->Create.pVNetRoot;
3078 RxReferenceVNetRoot(VNetRoot);
3079 if (InterlockedCompareExchange(&VNetRoot->AdditionalReferenceForDeleteFsctlTaken, 1, 0) != 0)
3080 {
3081 RxDereferenceVNetRoot(VNetRoot, LHS_LockNotHeld);
3082 }
3083
3084 FileObject->FsContext = &RxDeviceFCB;
3085 FileObject->FsContext2 = VNetRoot;
3086
3087 VNetRoot->ConstructionStatus = STATUS_SUCCESS;
3088 ++VNetRoot->NumberOfOpens;
3089
3090 /* Create is over - clear context */
3091 RxContext->Create.pSrvCall = NULL;
3092 RxContext->Create.pNetRoot = NULL;
3093 RxContext->Create.pVNetRoot = NULL;
3094
3095 return Status;
3096 }
3097
3098 VOID
3099 NTAPI
3100 RxDebugControlCommand(
3101 _In_ PSTR ControlString)
3102 {
3103 UNIMPLEMENTED;
3104 }
3105
3106 NTSTATUS
3107 NTAPI
3108 RxDriverEntry(
3109 IN PDRIVER_OBJECT DriverObject,
3110 IN PUNICODE_STRING RegistryPath)
3111 {
3112 NTSTATUS Status;
3113 USHORT i, State = 0;
3114
3115 DPRINT("RxDriverEntry(%p, %p)\n", DriverObject, RegistryPath);
3116
3117 _SEH2_TRY
3118 {
3119 RxCheckFcbStructuresForAlignment();
3120
3121 RtlZeroMemory(&RxData, sizeof(RxData));
3122 RxData.NodeTypeCode = RDBSS_NTC_DATA_HEADER;
3123 RxData.NodeByteSize = sizeof(RxData);
3124 RxData.DriverObject = DriverObject;
3125
3126 RtlZeroMemory(&RxDeviceFCB, sizeof(RxDeviceFCB));
3127 RxDeviceFCB.spacer.NodeTypeCode = RDBSS_NTC_DEVICE_FCB;
3128 RxDeviceFCB.spacer.NodeByteSize = sizeof(RxDeviceFCB);
3129
3130 KeInitializeSpinLock(&RxStrucSupSpinLock);
3131 RxExports.pRxStrucSupSpinLock = &RxStrucSupSpinLock;
3132
3133 RxInitializeDebugSupport();
3134
3135 RxFileSystemDeviceObject = (PRDBSS_DEVICE_OBJECT)&RxSpaceForTheWrappersDeviceObject;
3136 RtlZeroMemory(&RxSpaceForTheWrappersDeviceObject, sizeof(RxSpaceForTheWrappersDeviceObject));
3137
3138 RxInitializeLog();
3139 State = 2;
3140
3141 RxGetRegistryParameters(RegistryPath);
3142 RxReadRegistryParameters();
3143
3144 Status = RxInitializeRegistrationStructures();
3145 if (!NT_SUCCESS(Status))
3146 {
3147 _SEH2_LEAVE;
3148 }
3149 State = 1;
3150
3151 RxInitializeDispatcher();
3152
3153 ExInitializeNPagedLookasideList(&RxContextLookasideList, RxAllocatePoolWithTag, RxFreePool, 0, sizeof(RX_CONTEXT), RX_IRPC_POOLTAG, 4);
3154
3155 InitializeListHead(&RxIrpsList);
3156 KeInitializeSpinLock(&RxIrpsListSpinLock);
3157
3158 InitializeListHead(&RxActiveContexts);
3159 InitializeListHead(&RxSrvCalldownList);
3160
3161 ExInitializeFastMutex(&RxContextPerFileSerializationMutex);
3162 ExInitializeFastMutex(&RxLowIoPagingIoSyncMutex);
3163 KeInitializeMutex(&RxScavengerMutex, 1);
3164 KeInitializeMutex(&RxSerializationMutex, 1);
3165
3166 for (i = 0; i < RxMaximumWorkQueue; ++i)
3167 {
3168 RxFileSystemDeviceObject->PostedRequestCount[i] = 0;
3169 RxFileSystemDeviceObject->OverflowQueueCount[i] = 0;
3170 InitializeListHead(&RxFileSystemDeviceObject->OverflowQueue[i]);
3171 }
3172
3173 KeInitializeSpinLock(&RxFileSystemDeviceObject->OverflowQueueSpinLock);
3174
3175 RxInitializeDispatchVectors(DriverObject);
3176
3177 ExInitializeResourceLite(&RxData.Resource);
3178 RxData.OurProcess = IoGetCurrentProcess();
3179
3180 RxInitializeRxTimer();
3181 }
3182 _SEH2_FINALLY
3183 {
3184 if (!NT_SUCCESS(Status))
3185 {
3186 RxLogFailure(RxFileSystemDeviceObject, NULL, 0x80000BC4, Status);
3187 RxInitUnwind(DriverObject, State);
3188 }
3189 } _SEH2_END;
3190
3191 /* There are still bits to init - be consider it's fine for now */
3192 #if 0
3193 UNIMPLEMENTED;
3194 return STATUS_NOT_IMPLEMENTED;
3195 #else
3196 return STATUS_SUCCESS;
3197 #endif
3198 }
3199
3200 /*
3201 * @implemented
3202 */
3203 VOID
3204 RxDumpCurrentAccess(
3205 _In_ PSZ where1,
3206 _In_ PSZ where2,
3207 _In_ PSZ wherelogtag,
3208 _In_ PSHARE_ACCESS ShareAccess)
3209 {
3210 PAGED_CODE();
3211 }
3212
3213 /*
3214 * @implemented
3215 */
3216 VOID
3217 RxDumpWantedAccess(
3218 _In_ PSZ where1,
3219 _In_ PSZ where2,
3220 _In_ PSZ wherelogtag,
3221 _In_ ACCESS_MASK DesiredAccess,
3222 _In_ ULONG DesiredShareAccess)
3223 {
3224 PAGED_CODE();
3225 }
3226
3227 BOOLEAN
3228 NTAPI
3229 RxFastIoCheckIfPossible(
3230 PFILE_OBJECT FileObject,
3231 PLARGE_INTEGER FileOffset,
3232 ULONG Length, BOOLEAN Wait,
3233 ULONG LockKey, BOOLEAN CheckForReadOperation,
3234 PIO_STATUS_BLOCK IoStatus,
3235 PDEVICE_OBJECT DeviceObject)
3236 {
3237 UNIMPLEMENTED;
3238 return FALSE;
3239 }
3240
3241 BOOLEAN
3242 NTAPI
3243 RxFastIoDeviceControl(
3244 PFILE_OBJECT FileObject,
3245 BOOLEAN Wait,
3246 PVOID InputBuffer OPTIONAL,
3247 ULONG InputBufferLength,
3248 PVOID OutputBuffer OPTIONAL,
3249 ULONG OutputBufferLength,
3250 ULONG IoControlCode,
3251 PIO_STATUS_BLOCK IoStatus,
3252 PDEVICE_OBJECT DeviceObject)
3253 {
3254 /* Only supported IOCTL */
3255 if (IoControlCode == IOCTL_LMR_ARE_FILE_OBJECTS_ON_SAME_SERVER)
3256 {
3257 UNIMPLEMENTED;
3258 return FALSE;
3259 }
3260 else
3261 {
3262 return FALSE;
3263 }
3264 }
3265
3266 BOOLEAN
3267 NTAPI
3268 RxFastIoRead(
3269 PFILE_OBJECT FileObject,
3270 PLARGE_INTEGER FileOffset,
3271 ULONG Length,
3272 BOOLEAN Wait,
3273 ULONG LockKey,
3274 PVOID Buffer,
3275 PIO_STATUS_BLOCK IoStatus,
3276 PDEVICE_OBJECT DeviceObject)
3277 {
3278 UNIMPLEMENTED;
3279 return FALSE;
3280 }
3281
3282 BOOLEAN
3283 NTAPI
3284 RxFastIoWrite(
3285 PFILE_OBJECT FileObject,
3286 PLARGE_INTEGER FileOffset,
3287 ULONG Length,
3288 BOOLEAN Wait,
3289 ULONG LockKey,
3290 PVOID Buffer,
3291 PIO_STATUS_BLOCK IoStatus,
3292 PDEVICE_OBJECT DeviceObject)
3293 {
3294 UNIMPLEMENTED;
3295 return FALSE;
3296 }
3297
3298 NTSTATUS
3299 NTAPI
3300 RxFinalizeConnection(
3301 IN OUT PNET_ROOT NetRoot,
3302 IN OUT PV_NET_ROOT VNetRoot OPTIONAL,
3303 IN LOGICAL ForceFilesClosed)
3304 {
3305 UNIMPLEMENTED;
3306 return STATUS_NOT_IMPLEMENTED;
3307 }
3308
3309 NTSTATUS
3310 RxFindOrCreateFcb(
3311 PRX_CONTEXT RxContext,
3312 PUNICODE_STRING NetRootName)
3313 {
3314 PFCB Fcb;
3315 ULONG Version;
3316 NTSTATUS Status;
3317 PNET_ROOT NetRoot;
3318 PV_NET_ROOT VNetRoot;
3319 BOOLEAN TableAcquired, AcquiredExclusive;
3320
3321 PAGED_CODE();
3322
3323 NetRoot = (PNET_ROOT)RxContext->Create.pNetRoot;
3324 VNetRoot = (PV_NET_ROOT)RxContext->Create.pVNetRoot;
3325 ASSERT(NetRoot == VNetRoot->NetRoot);
3326
3327 Status = STATUS_SUCCESS;
3328 AcquiredExclusive = FALSE;
3329
3330 RxAcquireFcbTableLockShared(&NetRoot->FcbTable, TRUE);
3331 TableAcquired = TRUE;
3332 Version = NetRoot->FcbTable.Version;
3333
3334 /* Look for a cached FCB */
3335 Fcb = RxFcbTableLookupFcb(&NetRoot->FcbTable, NetRootName);
3336 if (Fcb == NULL)
3337 {
3338 DPRINT("RxFcbTableLookupFcb returned NULL fcb for %wZ\n", NetRootName);
3339 }
3340 else
3341 {
3342 DPRINT("FCB found for %wZ\n", &Fcb->FcbTableEntry.Path);
3343 /* If FCB was to be orphaned, consider it as not suitable */
3344 if (Fcb->fShouldBeOrphaned)
3345 {
3346 RxDereferenceNetFcb(Fcb);
3347 RxReleaseFcbTableLock(&NetRoot->FcbTable);
3348
3349 RxAcquireFcbTableLockExclusive(&NetRoot->FcbTable, TRUE);
3350 TableAcquired = TRUE;
3351 AcquiredExclusive = TRUE;
3352
3353 Fcb = RxFcbTableLookupFcb(&NetRoot->FcbTable, NetRootName);
3354 if (Fcb != NULL && Fcb->fShouldBeOrphaned)
3355 {
3356 RxOrphanThisFcb(Fcb);
3357 RxDereferenceNetFcb(Fcb);
3358 Fcb = NULL;
3359 }
3360 }
3361 }
3362
3363 /* If FCB was not found or is not covering full path, prepare for more work */
3364 if (Fcb == NULL || Fcb->FcbTableEntry.Path.Length != NetRootName->Length)
3365 {
3366 if (!AcquiredExclusive)
3367 {
3368 RxReleaseFcbTableLock(&NetRoot->FcbTable);
3369 RxAcquireFcbTableLockExclusive(&NetRoot->FcbTable, TRUE);
3370 TableAcquired = TRUE;
3371 }
3372
3373 /* If FCB table was updated in between, re-attempt a lookup */
3374 if (NetRoot->FcbTable.Version != Version)
3375 {
3376 Fcb = RxFcbTableLookupFcb(&NetRoot->FcbTable, NetRootName);
3377 if (Fcb != NULL && Fcb->FcbTableEntry.Path.Length != NetRootName->Length)
3378 {
3379 Fcb = NULL;
3380 }
3381 }
3382 }
3383
3384 /* Allocate the FCB */
3385 _SEH2_TRY
3386 {
3387 if (Fcb == NULL)
3388 {
3389 Fcb = RxCreateNetFcb(RxContext, VNetRoot, NetRootName);
3390 if (Fcb == NULL)
3391 {
3392 Status = STATUS_INSUFFICIENT_RESOURCES;
3393 }
3394 else
3395 {
3396 Status = RxAcquireExclusiveFcb(RxContext, Fcb);
3397 RxContext->Create.FcbAcquired = NT_SUCCESS(Status);
3398 }
3399 }
3400 }
3401 _SEH2_FINALLY
3402 {
3403 if (_SEH2_AbnormalTermination())
3404 {
3405 RxReleaseFcbTableLock(&NetRoot->FcbTable);
3406 TableAcquired = FALSE;
3407
3408 if (Fcb != NULL)
3409 {
3410 RxTransitionNetFcb(Fcb, Condition_Bad);
3411
3412 ExAcquireResourceExclusiveLite(Fcb->Header.Resource, TRUE);
3413 if (RxDereferenceAndFinalizeNetFcb(Fcb, NULL, FALSE, FALSE) != 0)
3414 {
3415 ExReleaseResourceLite(Fcb->Header.Resource);
3416 }
3417 }
3418 }
3419 }
3420 _SEH2_END;
3421
3422 if (TableAcquired)
3423 {
3424 RxReleaseFcbTableLock(&NetRoot->FcbTable);
3425 }
3426
3427 if (!NT_SUCCESS(Status))
3428 {
3429 return Status;
3430 }
3431
3432 RxContext->pFcb = RX_GET_MRX_FCB(Fcb);
3433 DPRINT("FCB %p is in condition %lx\n", Fcb, Fcb->Condition);
3434
3435 if (!RxContext->Create.FcbAcquired)
3436 {
3437 RxWaitForStableNetFcb(Fcb, RxContext);
3438 Status = RxAcquireExclusiveFcb(RxContext, Fcb);
3439 RxContext->Create.FcbAcquired = NT_SUCCESS(Status);
3440 }
3441
3442 return Status;
3443 }
3444
3445 NTSTATUS
3446 RxFirstCanonicalize(
3447 PRX_CONTEXT RxContext,
3448 PUNICODE_STRING FileName,
3449 PUNICODE_STRING CanonicalName,
3450 PNET_ROOT_TYPE NetRootType)
3451 {
3452 NTSTATUS Status;
3453 NET_ROOT_TYPE Type;
3454 BOOLEAN UncName, PrependString, IsSpecial;
3455 USHORT CanonicalLength;
3456 UNICODE_STRING SessionIdString;
3457 WCHAR SessionIdBuffer[16];
3458
3459 PAGED_CODE();
3460
3461 Type = NET_ROOT_WILD;
3462 PrependString = FALSE;
3463 IsSpecial = FALSE;
3464 UncName = FALSE;
3465 Status = STATUS_SUCCESS;
3466
3467 /* Name has to contain at least \\ */
3468 if (FileName->Length < 2 * sizeof(WCHAR))
3469 {
3470 return STATUS_OBJECT_NAME_INVALID;
3471 }
3472
3473 /* First easy check, is that a path with a name? */
3474 CanonicalLength = FileName->Length;
3475 if (FileName->Length > 5 * sizeof(WCHAR))
3476 {
3477 if (FileName->Buffer[0] == '\\' && FileName->Buffer[1] == ';')
3478 {
3479 if (FileName->Buffer[3] == ':')
3480 {
3481 Type = NET_ROOT_DISK;
3482 }
3483 else
3484 {
3485 Type = NET_ROOT_PRINT;
3486 }
3487 }
3488 }
3489
3490 /* Nope, attempt deeper parsing */
3491 if (FileName->Buffer[0] == OBJ_NAME_PATH_SEPARATOR && FileName->Buffer[1] != ';')
3492 {
3493 ULONG SessionId;
3494 PWSTR FirstSlash, EndOfString;
3495
3496 SetFlag(RxContext->Create.Flags, RX_CONTEXT_CREATE_FLAG_UNC_NAME);
3497 UncName = TRUE;
3498
3499 /* The lack of drive letter will be replaced by session ID */
3500 SessionId = RxGetSessionId(RxContext->CurrentIrpSp);
3501 RtlInitEmptyUnicodeString(&SessionIdString, SessionIdBuffer, sizeof(SessionIdBuffer));
3502 RtlIntegerToUnicodeString(SessionId, 10, &SessionIdString);
3503
3504 EndOfString = Add2Ptr(FileName->Buffer, FileName->Length);
3505 for (FirstSlash = &FileName->Buffer[1]; FirstSlash != EndOfString; ++FirstSlash)
3506 {
3507 if (*FirstSlash == OBJ_NAME_PATH_SEPARATOR)
3508 {
3509 break;
3510 }
3511 }
3512
3513 if (EndOfString - FirstSlash <= sizeof(WCHAR))
3514 {
3515 Status = STATUS_OBJECT_NAME_INVALID;
3516 }
3517 else
3518 {
3519 UNIMPLEMENTED;
3520 DPRINT1("WARNING: Assuming not special + disk!\n");
3521 Type = NET_ROOT_DISK;
3522 Status = STATUS_SUCCESS;
3523 //Status = STATUS_NOT_IMPLEMENTED;
3524 /* Should be check against IPC, mailslot, and so on */
3525 }
3526 }
3527
3528 /* Update net root type with our deduced one */
3529 *NetRootType = Type;
3530 DPRINT("Returning type: %x\n", Type);
3531
3532 if (!NT_SUCCESS(Status))
3533 {
3534 return Status;
3535 }
3536
3537 /* Do we have to prepend session ID? */
3538 if (UncName)
3539 {
3540 if (!IsSpecial)
3541 {
3542 PrependString = TRUE;
3543 CanonicalLength += SessionIdString.Length + 3 * sizeof(WCHAR);
3544 }
3545 }
3546
3547 /* If not UNC path, we should preprend stuff */
3548 if (!PrependString && !IsSpecial && FileName->Buffer[0] != '\\')
3549 {
3550 return STATUS_OBJECT_PATH_INVALID;
3551 }
3552
3553 /* Allocate the buffer */
3554 Status = RxAllocateCanonicalNameBuffer(RxContext, CanonicalName, CanonicalLength);
3555 if (!NT_SUCCESS(Status))
3556 {
3557 return Status;
3558 }
3559
3560 /* We don't support that case, we always return disk */
3561 if (IsSpecial)
3562 {
3563 ASSERT(CanonicalName->Length == CanonicalLength);
3564 UNIMPLEMENTED;
3565 Status = STATUS_NOT_IMPLEMENTED;
3566 }
3567 else
3568 {
3569 /* If we have to prepend, go ahead */
3570 if (PrependString)
3571 {
3572 CanonicalName->Buffer[0] = '\\';
3573 CanonicalName->Buffer[1] = ';';
3574 CanonicalName->Buffer[2] = ':';
3575 CanonicalName->Length = 3 * sizeof(WCHAR);
3576 RtlAppendUnicodeStringToString(CanonicalName, &SessionIdString);
3577 RtlAppendUnicodeStringToString(CanonicalName, FileName);
3578
3579 DPRINT1("CanonicalName: %wZ\n", CanonicalName);
3580 }
3581 /* Otherwise, that's a simple copy */
3582 else
3583 {
3584 RtlCopyUnicodeString(CanonicalName, FileName);
3585 }
3586 }
3587
3588 return Status;
3589 }
3590
3591 /*
3592 * @implemented
3593 */
3594 VOID
3595 RxFreeCanonicalNameBuffer(
3596 PRX_CONTEXT Context)
3597 {
3598 /* These two buffers are always the same */
3599 ASSERT(Context->Create.CanonicalNameBuffer == Context->AlsoCanonicalNameBuffer);
3600
3601 if (Context->Create.CanonicalNameBuffer != NULL)
3602 {
3603 RxFreePoolWithTag(Context->Create.CanonicalNameBuffer, RX_MISC_POOLTAG);
3604 Context->Create.CanonicalNameBuffer = NULL;
3605 Context->AlsoCanonicalNameBuffer = NULL;
3606 }
3607
3608 ASSERT(Context->AlsoCanonicalNameBuffer == NULL);
3609 }
3610
3611 NTSTATUS
3612 RxFsdCommonDispatch(
3613 PRX_FSD_DISPATCH_VECTOR DispatchVector,
3614 UCHAR MajorFunction,
3615 PIO_STACK_LOCATION Stack,
3616 PFILE_OBJECT FileObject,
3617 PIRP Irp,
3618 PRDBSS_DEVICE_OBJECT RxDeviceObject)
3619 {
3620 KIRQL OldIrql;
3621 NTSTATUS Status;
3622 PRX_CONTEXT Context;
3623 UCHAR MinorFunction;
3624 PFILE_OBJECT StackFileObject;
3625 PRX_FSD_DISPATCH DispatchFunc;
3626 RX_TOPLEVELIRP_CONTEXT TopLevelContext;
3627 BOOLEAN TopLevel, Closing, PassToDriver, SetCancelRoutine, PostRequest, CanWait;
3628
3629 Status = STATUS_SUCCESS;
3630
3631 DPRINT("RxFsdCommonDispatch(%p, %d, %p, %p, %p, %p)\n", DispatchVector, MajorFunction, Stack, FileObject, Irp, RxDeviceObject);
3632
3633 FsRtlEnterFileSystem();
3634
3635 TopLevel = RxTryToBecomeTheTopLevelIrp(&TopLevelContext, Irp, RxDeviceObject, FALSE);
3636
3637 _SEH2_TRY
3638 {
3639 CanWait = TRUE;
3640 Closing = FALSE;
3641 PostRequest = FALSE;
3642 SetCancelRoutine = TRUE;
3643 MinorFunction = Stack->MinorFunction;
3644 /* Can we wait? */
3645 switch (MajorFunction)
3646 {
3647 case IRP_MJ_FILE_SYSTEM_CONTROL:
3648 if (FileObject != NULL)
3649 {
3650 CanWait = IoIsOperationSynchronous(Irp);
3651 }
3652 else
3653 {
3654 CanWait = TRUE;
3655 }
3656 break;
3657
3658 case IRP_MJ_READ:
3659 case IRP_MJ_WRITE:
3660 case IRP_MJ_QUERY_INFORMATION:
3661 case IRP_MJ_SET_INFORMATION:
3662 case IRP_MJ_QUERY_EA:
3663 case IRP_MJ_SET_EA:
3664 case IRP_MJ_FLUSH_BUFFERS:
3665 case IRP_MJ_QUERY_VOLUME_INFORMATION:
3666 case IRP_MJ_SET_VOLUME_INFORMATION:
3667 case IRP_MJ_DIRECTORY_CONTROL:
3668 case IRP_MJ_DEVICE_CONTROL:
3669 case IRP_MJ_LOCK_CONTROL:
3670 case IRP_MJ_QUERY_SECURITY:
3671 case IRP_MJ_SET_SECURITY:
3672 CanWait = IoIsOperationSynchronous(Irp);
3673 break;
3674
3675 case IRP_MJ_CLOSE:
3676 case IRP_MJ_CLEANUP:
3677 Closing = TRUE;
3678 SetCancelRoutine = FALSE;
3679 break;
3680
3681 default:
3682 break;
3683 }
3684
3685 KeAcquireSpinLock(&RxStrucSupSpinLock, &OldIrql);
3686 /* Should we stop it right now, or mini-rdr deserves to know? */
3687 PassToDriver = TRUE;
3688 if (RxGetRdbssState(RxDeviceObject) != RDBSS_STARTABLE)
3689 {
3690 if (RxGetRdbssState(RxDeviceObject) == RDBSS_STOP_IN_PROGRESS && !Closing)
3691 {
3692 PassToDriver = FALSE;
3693 Status = STATUS_REDIRECTOR_NOT_STARTED;
3694 DPRINT1("Not started!\n");
3695 }
3696 }
3697 else
3698 {
3699 if (DispatchVector != RxDeviceFCBVector && (FileObject->FileName.Length != 0 || FileObject->RelatedFileObject != NULL))
3700 {
3701 PassToDriver = FALSE;
3702 Status = STATUS_REDIRECTOR_NOT_STARTED;
3703 DPRINT1("Not started!\n");
3704 }
3705 }
3706 KeReleaseSpinLock(&RxStrucSupSpinLock, OldIrql);
3707
3708 StackFileObject = Stack->FileObject;
3709 /* Make sure we don't deal with orphaned stuff */
3710 if (StackFileObject != NULL && StackFileObject->FsContext != NULL)
3711 {
3712 if (StackFileObject->FsContext2 != UIntToPtr(DFS_OPEN_CONTEXT) &&
3713 StackFileObject->FsContext2 != UIntToPtr(DFS_DOWNLEVEL_OPEN_CONTEXT) &&
3714 StackFileObject->FsContext != &RxDeviceFCB)
3715 {
3716 PFCB Fcb;
3717 PFOBX Fobx;
3718
3719 Fcb = StackFileObject->FsContext;
3720 Fobx = StackFileObject->FsContext2;
3721
3722 if (BooleanFlagOn(Fcb->FcbState, FCB_STATE_ORPHANED) ||
3723 BooleanFlagOn(Fobx->pSrvOpen->Flags, SRVOPEN_FLAG_ORPHANED))
3724 {
3725 if (Closing)
3726 {
3727 PassToDriver = TRUE;
3728 }
3729 else
3730 {
3731 PassToDriver = FALSE;
3732 Status = STATUS_UNEXPECTED_NETWORK_ERROR;
3733 DPRINT1("Operation on orphaned FCB: %p\n", Fcb);
3734 }
3735 }
3736 }
3737 }
3738
3739 /* Did we receive a close request whereas we're stopping? */
3740 if (RxGetRdbssState(RxDeviceObject) == RDBSS_STOP_IN_PROGRESS && Closing)
3741 {
3742 PFCB Fcb;
3743
3744 Fcb = StackFileObject->FsContext;
3745
3746 DPRINT1("Close received after stop\n");
3747 DPRINT1("Irp: %p %d:%d FO: %p FCB: %p\n",
3748 Irp, Stack->MajorFunction, Stack->MinorFunction, StackFileObject, Fcb);
3749
3750 if (Fcb != NULL && Fcb != &RxDeviceFCB &&
3751 NodeTypeIsFcb(Fcb))
3752 {
3753 DPRINT1("OpenCount: %ld, UncleanCount: %ld, Name: %wZ\n",
3754 Fcb->OpenCount, Fcb->UncleanCount, &Fcb->FcbTableEntry.Path);
3755 }
3756 }
3757
3758 /* Should we stop the whole thing now? */
3759 if (!PassToDriver)
3760 {
3761 if (MajorFunction != IRP_MJ_DIRECTORY_CONTROL || MinorFunction != IRP_MN_REMOVE_DEVICE)
3762 {
3763 IoMarkIrpPending(Irp);
3764 Irp->IoStatus.Status = Status;
3765 Irp->IoStatus.Information = 0;
3766 IoCompleteRequest(Irp, IO_NO_INCREMENT);
3767 Status = STATUS_PENDING;
3768 }
3769 else
3770 {
3771 Irp->IoStatus.Status = Status;
3772 Irp->IoStatus.Information = 0;
3773 IoCompleteRequest(Irp, IO_NO_INCREMENT);
3774 }
3775
3776 _SEH2_LEAVE;
3777 }
3778
3779 /* No? Allocate a context to deal with the mini-rdr */
3780 Context = RxCreateRxContext(Irp, RxDeviceObject, (CanWait ? RX_CONTEXT_FLAG_WAIT : 0));
3781 if (Context == NULL)
3782 {
3783 Status = STATUS_INSUFFICIENT_RESOURCES;
3784 RxCompleteRequest_Real(RxNull, Irp, STATUS_INSUFFICIENT_RESOURCES);
3785 _SEH2_LEAVE;
3786 }
3787
3788 /* Set cancel routine if required */
3789 if (SetCancelRoutine)
3790 {
3791 IoAcquireCancelSpinLock(&OldIrql);
3792 IoSetCancelRoutine(Irp, RxCancelRoutine);
3793 }
3794 else
3795 {
3796 IoAcquireCancelSpinLock(&OldIrql);
3797 IoSetCancelRoutine(Irp, NULL);
3798 }
3799 IoReleaseCancelSpinLock(OldIrql);
3800
3801 ASSERT(MajorFunction <= IRP_MJ_MAXIMUM_FUNCTION);
3802
3803 Irp->IoStatus.Status = STATUS_SUCCESS;
3804 Irp->IoStatus.Information = 0;
3805 /* Get the dispatch routine */
3806 DispatchFunc = DispatchVector[MajorFunction].CommonRoutine;
3807
3808 if (MajorFunction == IRP_MJ_READ || MajorFunction == IRP_MJ_WRITE)
3809 {
3810 /* Handle the complete MDL case */
3811 if (BooleanFlagOn(MinorFunction, IRP_MN_COMPLETE))
3812 {
3813 DispatchFunc = RxCompleteMdl;
3814 }
3815 else
3816 {
3817 /* Do we have to post request? */
3818 if (BooleanFlagOn(MinorFunction, IRP_MN_DPC))
3819 {
3820 PostRequest = TRUE;
3821 }
3822 else
3823 {
3824 /* Our read function needs stack, make sure we won't overflow,
3825 * otherwise, post the request
3826 */
3827 if (MajorFunction == IRP_MJ_READ)
3828 {
3829 if (IoGetRemainingStackSize() < 0xE00)
3830 {
3831 Context->PendingReturned = TRUE;
3832 Status = RxPostStackOverflowRead(Context);
3833 if (Status != STATUS_PENDING)
3834 {
3835 Context->PendingReturned = FALSE;
3836 RxCompleteAsynchronousRequest(Context, Status);
3837 }
3838
3839 _SEH2_LEAVE;
3840 }
3841 }
3842 }
3843 }
3844 }
3845
3846 Context->ResumeRoutine = DispatchFunc;
3847 /* There's a dispatch routine? Time to dispatch! */
3848 if (DispatchFunc != NULL)
3849 {
3850 Context->PendingReturned = TRUE;
3851 if (PostRequest)
3852 {
3853 Status = RxFsdPostRequest(Context);
3854 }
3855 else
3856 {
3857 /* Retry as long as we have */
3858 do
3859 {
3860 Status = DispatchFunc(Context);
3861 }
3862 while (Status == STATUS_RETRY);
3863
3864 if (Status == STATUS_PENDING)
3865 {
3866 _SEH2_LEAVE;
3867 }
3868
3869 /* Sanity check: did someone mess with our context? */
3870 if (Context->CurrentIrp != Irp || Context->CurrentIrpSp != Stack ||
3871 Context->MajorFunction != MajorFunction || Stack->MinorFunction != MinorFunction)
3872 {
3873 DPRINT1("RX_CONTEXT %p has been contaminated!\n", Context);
3874 DPRINT1("->CurrentIrp %p %p\n", Context->CurrentIrp, Irp);
3875 DPRINT1("->CurrentIrpSp %p %p\n", Context->CurrentIrpSp, Stack);
3876 DPRINT1("->MajorFunction %d %d\n", Context->MajorFunction, MajorFunction);
3877 DPRINT1("->MinorFunction %d %d\n", Context->MinorFunction, MinorFunction);
3878 }
3879 Context->PendingReturned = FALSE;
3880 Status = RxCompleteAsynchronousRequest(Context, Status);
3881 }
3882 }
3883 else
3884 {
3885 Status = STATUS_NOT_IMPLEMENTED;
3886 }
3887 }
3888 _SEH2_FINALLY
3889 {
3890 if (TopLevel)
3891 {
3892 RxUnwindTopLevelIrp(&TopLevelContext);
3893 }
3894
3895 FsRtlExitFileSystem();
3896 }
3897 _SEH2_END;
3898
3899 DPRINT("RxFsdDispatch, Status: %lx\n", Status);
3900 return Status;
3901 }
3902
3903 /*
3904 * @implemented
3905 */
3906 NTSTATUS
3907 NTAPI
3908 RxFsdDispatch(
3909 IN PRDBSS_DEVICE_OBJECT RxDeviceObject,
3910 IN PIRP Irp)
3911 {
3912 PFCB Fcb;
3913 PIO_STACK_LOCATION Stack;
3914 PRX_FSD_DISPATCH_VECTOR DispatchVector;
3915
3916 PAGED_CODE();
3917
3918 DPRINT("RxFsdDispatch(%p, %p)\n", RxDeviceObject, Irp);
3919
3920 Stack = IoGetCurrentIrpStackLocation(Irp);
3921
3922 /* Dispatch easy case */
3923 if (Stack->MajorFunction == IRP_MJ_SYSTEM_CONTROL)
3924 {
3925 return RxSystemControl(RxDeviceObject, Irp);
3926 }
3927
3928 /* Bail out broken cases */
3929 if (Stack->MajorFunction == IRP_MJ_CREATE_MAILSLOT ||
3930 Stack->MajorFunction == IRP_MJ_CREATE_NAMED_PIPE)
3931 {
3932 IoMarkIrpPending(Irp);
3933 Irp->IoStatus.Information = 0;
3934 Irp->IoStatus.Status = STATUS_OBJECT_NAME_INVALID;
3935 IoCompleteRequest(Irp, IO_NO_INCREMENT);
3936 return STATUS_PENDING;
3937 }
3938
3939 /* Immediately handle create */
3940 if (Stack->MajorFunction == IRP_MJ_CREATE)
3941 {
3942 return RxFsdCommonDispatch(&RxFsdDispatchVector[0], Stack->MajorFunction, Stack, Stack->FileObject, Irp, RxDeviceObject);
3943 }
3944
3945 /* If not a creation, we must have at least a FO with a FCB */
3946 if (Stack->FileObject == NULL || Stack->FileObject->FsContext == NULL)
3947 {
3948 IoMarkIrpPending(Irp);
3949 Irp->IoStatus.Information = 0;
3950 Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
3951 IoCompleteRequest(Irp, IO_NO_INCREMENT);
3952 return STATUS_PENDING;
3953 }
3954
3955 /* Set the dispatch vector if required */
3956 Fcb = Stack->FileObject->FsContext;
3957 if (!NodeTypeIsFcb(Fcb) || Fcb->PrivateDispatchVector == NULL)
3958 {
3959 DispatchVector = &RxFsdDispatchVector[0];
3960 }
3961 else
3962 {
3963 DispatchVector = Fcb->PrivateDispatchVector;
3964 }
3965
3966 /* Device cannot accept such requests */
3967 if (RxDeviceObject == RxFileSystemDeviceObject)
3968 {
3969 IoMarkIrpPending(Irp);
3970 Irp->IoStatus.Information = 0;
3971 Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
3972 IoCompleteRequest(Irp, IO_NO_INCREMENT);
3973 return STATUS_PENDING;
3974 }
3975
3976 /* Dispatch for real! */
3977 return RxFsdCommonDispatch(DispatchVector, Stack->MajorFunction, Stack, Stack->FileObject, Irp, RxDeviceObject);
3978 }
3979
3980 /*
3981 * @implemented
3982 */
3983 NTSTATUS
3984 RxFsdPostRequest(
3985 IN PRX_CONTEXT RxContext)
3986 {
3987 /* Initialize posting if required */
3988 if (!BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_NO_PREPOSTING_NEEDED))
3989 {
3990 RxPrePostIrp(RxContext, RxContext->CurrentIrp);
3991 }
3992
3993 DPRINT("Posting MN: %d, Ctxt: %p, IRP: %p, Thrd: %lx #%lx\n",
3994 RxContext->MinorFunction, RxContext,
3995 RxContext->CurrentIrp, RxContext->LastExecutionThread,
3996 RxContext->SerialNumber);
3997
3998 RxAddToWorkque(RxContext, RxContext->CurrentIrp);
3999 return STATUS_PENDING;
4000 }
4001
4002 /*
4003 * @implemented
4004 */
4005 VOID
4006 NTAPI
4007 RxFspDispatch(
4008 IN PVOID Context)
4009 {
4010 KIRQL EntryIrql;
4011 WORK_QUEUE_TYPE Queue;
4012 PRDBSS_DEVICE_OBJECT VolumeDO;
4013 PRX_CONTEXT RxContext, EntryContext;
4014
4015 PAGED_CODE();
4016
4017 RxContext = Context;
4018 EntryContext = Context;
4019 /* Save IRQL at entry for later checking */
4020 EntryIrql = KeGetCurrentIrql();
4021
4022 /* No FO, deal with device */
4023 if (RxContext->CurrentIrpSp->FileObject != NULL)
4024 {
4025 VolumeDO = RxFileSystemDeviceObject;
4026 }
4027 else
4028 {
4029 VolumeDO = NULL;
4030 }
4031
4032 /* Which queue to used for delayed? */
4033 if (BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_FSP_DELAYED_OVERFLOW_QUEUE))
4034 {
4035 Queue = DelayedWorkQueue;
4036 }
4037 else
4038 {
4039 ASSERT(BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_FSP_CRITICAL_OVERFLOW_QUEUE));
4040 Queue = CriticalWorkQueue;
4041 }
4042
4043 do
4044 {
4045 PIRP Irp;
4046 NTSTATUS Status;
4047 BOOLEAN RecursiveCall;
4048 RX_TOPLEVELIRP_CONTEXT TopLevelContext;
4049
4050 ASSERT(RxContext->MajorFunction <= IRP_MJ_MAXIMUM_FUNCTION);
4051 ASSERT(!RxContext->PostRequest);
4052
4053 RxContext->LastExecutionThread = PsGetCurrentThread();
4054 SetFlag(RxContext->Flags, (RX_CONTEXT_FLAG_IN_FSP | RX_CONTEXT_FLAG_WAIT));
4055
4056 DPRINT("Dispatch: MN: %d, Ctxt: %p, IRP: %p, THRD: %lx #%lx", RxContext->MinorFunction,
4057 RxContext, RxContext->CurrentIrp, RxContext->LastExecutionThread,
4058 RxContext->SerialNumber);
4059
4060 Irp = RxContext->CurrentIrp;
4061
4062 FsRtlEnterFileSystem();
4063
4064 RecursiveCall = BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_RECURSIVE_CALL);
4065 RxTryToBecomeTheTopLevelIrp(&TopLevelContext,
4066 (RecursiveCall ? (PIRP)FSRTL_FSP_TOP_LEVEL_IRP : RxContext->CurrentIrp),
4067 RxContext->RxDeviceObject, TRUE);
4068
4069 ASSERT(RxContext->ResumeRoutine != NULL);
4070
4071 if (BooleanFlagOn(RxContext->MinorFunction, IRP_MN_DPC) && Irp->Tail.Overlay.Thread == NULL)
4072 {
4073 ASSERT((RxContext->MajorFunction == IRP_MJ_WRITE) || (RxContext->MajorFunction == IRP_MJ_READ));
4074 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
4075 }
4076
4077 /* Call the resume routine */
4078 do
4079 {
4080 BOOLEAN NoComplete;
4081
4082 NoComplete = BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_NO_COMPLETE_FROM_FSP);
4083
4084 Status = RxContext->ResumeRoutine(RxContext);
4085 if (!NoComplete && Status != STATUS_PENDING)
4086 {
4087 if (Status != STATUS_RETRY)
4088 {
4089 Status = RxCompleteRequest(RxContext, Status);
4090 }
4091 }
4092 }
4093 while (Status == STATUS_RETRY);
4094
4095 RxUnwindTopLevelIrp(&TopLevelContext);
4096 FsRtlExitFileSystem();
4097
4098 if (VolumeDO != NULL)
4099 {
4100 RxContext = RxRemoveOverflowEntry(VolumeDO, Queue);
4101 }
4102 else
4103 {
4104 RxContext = NULL;
4105 }
4106 } while (RxContext != NULL);
4107
4108 /* Did we mess with IRQL? */
4109 if (KeGetCurrentIrql() >= APC_LEVEL)
4110 {
4111 DPRINT1("High IRQL for Ctxt %p, on entry: %x\n", EntryContext, EntryIrql);
4112 }
4113 }
4114
4115 /*
4116 * @implemented
4117 */
4118 ULONG
4119 RxGetNetworkProviderPriority(
4120 PUNICODE_STRING DeviceName)
4121 {
4122 PAGED_CODE();
4123 return 1;
4124 }
4125
4126 /*
4127 * @implemented
4128 */
4129 VOID
4130 NTAPI
4131 RxGetRegistryParameters(
4132 IN PUNICODE_STRING RegistryPath)
4133 {
4134 USHORT i;
4135 NTSTATUS Status;
4136 UCHAR Buffer[0x400];
4137 HANDLE DriverHandle, KeyHandle;
4138 UNICODE_STRING KeyName, OutString;
4139 OBJECT_ATTRIBUTES ObjectAttributes;
4140
4141 PAGED_CODE();
4142
4143 InitializeObjectAttributes(&ObjectAttributes, RegistryPath, OBJ_CASE_INSENSITIVE, NULL, NULL);
4144 Status = ZwOpenKey(&DriverHandle, READ_CONTROL | KEY_NOTIFY | KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE, &ObjectAttributes);
4145 if (!NT_SUCCESS(Status))
4146 {
4147 return;
4148 }
4149
4150 RtlInitUnicodeString(&KeyName, L"Parameters");
4151 InitializeObjectAttributes(&ObjectAttributes, &KeyName, OBJ_CASE_INSENSITIVE, DriverHandle, FALSE);
4152 Status = ZwOpenKey(&KeyHandle, READ_CONTROL | KEY_NOTIFY | KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE, &ObjectAttributes);
4153 if (NT_SUCCESS(Status))
4154 {
4155 /* The only parameter we deal with is InitialDebugString */
4156 RxGetStringRegistryParameter(KeyHandle, L"InitialDebugString", &OutString, Buffer, sizeof(Buffer), 0);
4157 if (OutString.Length != 0 && OutString.Length < 0x140)
4158 {
4159 PWSTR Read;
4160 PSTR Write;
4161
4162 Read = OutString.Buffer;
4163 Write = (PSTR)OutString.Buffer;
4164 for (i = 0; i < OutString.Length; ++i)
4165 {
4166 *Read = *Write;
4167 ++Write;
4168 *Write = ANSI_NULL;
4169 ++Read;
4170 }
4171
4172 /* Which is a string we'll just write out */
4173 DPRINT("InitialDebugString read from registry: '%s'\n", OutString.Buffer);
4174 RxDebugControlCommand((PSTR)OutString.Buffer);
4175 }
4176
4177 ZwClose(KeyHandle);
4178 }
4179
4180 ZwClose(DriverHandle);
4181 }
4182
4183 /*
4184 * @implemented
4185 */
4186 ULONG
4187 RxGetSessionId(
4188 IN PIO_STACK_LOCATION IrpSp)
4189 {
4190 ULONG SessionId;
4191 PACCESS_TOKEN Token;
4192 PIO_SECURITY_CONTEXT SecurityContext;
4193
4194 PAGED_CODE();
4195
4196 /* If that's not a prefix claim, not an open request, session id will be 0 */
4197 if (IrpSp->MajorFunction != IRP_MJ_DEVICE_CONTROL || IrpSp->Parameters.DeviceIoControl.IoControlCode != IOCTL_REDIR_QUERY_PATH)
4198 {
4199 if (IrpSp->MajorFunction != IRP_MJ_CREATE || IrpSp->Parameters.Create.SecurityContext == NULL)
4200 {
4201 return 0;
4202 }
4203
4204 SecurityContext = IrpSp->Parameters.Create.SecurityContext;
4205 }
4206 else
4207 {
4208 SecurityContext = ((PQUERY_PATH_REQUEST)IrpSp->Parameters.DeviceIoControl.Type3InputBuffer)->SecurityContext;
4209 }
4210
4211 /* Query the session id */
4212 Token = SeQuerySubjectContextToken(&SecurityContext->AccessState->SubjectSecurityContext);
4213 SeQuerySessionIdToken(Token, &SessionId);
4214
4215 return SessionId;
4216 }
4217
4218 /*
4219 * @implemented
4220 */
4221 NTSTATUS
4222 NTAPI
4223 RxGetStringRegistryParameter(
4224 IN HANDLE KeyHandle,
4225 IN PCWSTR KeyName,
4226 OUT PUNICODE_STRING OutString,
4227 IN PUCHAR Buffer,
4228 IN ULONG BufferLength,
4229 IN BOOLEAN LogFailure)
4230 {
4231 NTSTATUS Status;
4232 ULONG ResultLength;
4233 UNICODE_STRING KeyString;
4234
4235 PAGED_CODE();
4236
4237 RtlInitUnicodeString(&KeyString, KeyName);
4238 Status = ZwQueryValueKey(KeyHandle, &KeyString, KeyValuePartialInformation, Buffer, BufferLength, &ResultLength);
4239 OutString->Length = 0;
4240 OutString->Buffer = 0;
4241 if (!NT_SUCCESS(Status))
4242 {
4243 if (LogFailure)
4244 {
4245 RxLogFailure(RxFileSystemDeviceObject, NULL, 0x80000BD3, Status);
4246 }
4247
4248 return Status;
4249 }
4250
4251 OutString->Buffer = (PWSTR)(((PKEY_VALUE_PARTIAL_INFORMATION)Buffer)->Data);
4252 OutString->Length = ((PKEY_VALUE_PARTIAL_INFORMATION)Buffer)->DataLength - sizeof(UNICODE_NULL);
4253 OutString->MaximumLength = OutString->Length;
4254
4255 return STATUS_SUCCESS;
4256 }
4257
4258 /*
4259 * @implemented
4260 */
4261 PRDBSS_DEVICE_OBJECT
4262 RxGetTopDeviceObjectIfRdbssIrp(
4263 VOID)
4264 {
4265 PIRP TopLevelIrp;
4266 PRDBSS_DEVICE_OBJECT TopDevice = NULL;
4267
4268 TopLevelIrp = IoGetTopLevelIrp();
4269 if (RxIsThisAnRdbssTopLevelContext((PRX_TOPLEVELIRP_CONTEXT)TopLevelIrp))
4270 {
4271 TopDevice = ((PRX_TOPLEVELIRP_CONTEXT)TopLevelIrp)->RxDeviceObject;
4272 }
4273
4274 return TopDevice;
4275 }
4276
4277 /*
4278 * @implemented
4279 */
4280 LUID
4281 RxGetUid(
4282 IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext)
4283 {
4284 LUID Luid;
4285 PACCESS_TOKEN Token;
4286
4287 PAGED_CODE();
4288
4289 Token = SeQuerySubjectContextToken(SubjectSecurityContext);
4290 SeQueryAuthenticationIdToken(Token, &Luid);
4291
4292 return Luid;
4293 }
4294
4295 VOID
4296 NTAPI
4297 RxIndicateChangeOfBufferingStateForSrvOpen(
4298 PMRX_SRV_CALL SrvCall,
4299 PMRX_SRV_OPEN SrvOpen,
4300 PVOID SrvOpenKey,
4301 PVOID Context)
4302 {
4303 UNIMPLEMENTED;
4304 }
4305
4306 VOID
4307 NTAPI
4308 RxInitializeDebugSupport(
4309 VOID)
4310 {
4311 UNIMPLEMENTED;
4312 }
4313
4314 /*
4315 * @implemented
4316 */
4317 VOID
4318 NTAPI
4319 RxInitializeDispatchVectors(
4320 PDRIVER_OBJECT DriverObject)
4321 {
4322 USHORT i;
4323
4324 PAGED_CODE();
4325
4326 for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; ++i)
4327 {
4328 DriverObject->MajorFunction[i] = (PDRIVER_DISPATCH)RxFsdDispatch;
4329 }
4330
4331 RxDeviceFCB.PrivateDispatchVector = RxDeviceFCBVector;
4332 ASSERT(RxFsdDispatchVector[IRP_MJ_MAXIMUM_FUNCTION].CommonRoutine != NULL);
4333 ASSERT(RxDeviceFCBVector[IRP_MJ_MAXIMUM_FUNCTION].CommonRoutine != NULL);
4334
4335 DriverObject->FastIoDispatch = &RxFastIoDispatch;
4336 RxFastIoDispatch.SizeOfFastIoDispatch = sizeof(RxFastIoDispatch);
4337 RxFastIoDispatch.FastIoCheckIfPossible = RxFastIoCheckIfPossible;
4338 RxFastIoDispatch.FastIoRead = RxFastIoRead;
4339 RxFastIoDispatch.FastIoWrite = RxFastIoWrite;
4340 RxFastIoDispatch.FastIoQueryBasicInfo = NULL;
4341 RxFastIoDispatch.FastIoQueryStandardInfo = NULL;
4342 RxFastIoDispatch.FastIoLock = NULL;
4343 RxFastIoDispatch.FastIoUnlockSingle = NULL;
4344 RxFastIoDispatch.FastIoUnlockAll = NULL;
4345 RxFastIoDispatch.FastIoUnlockAllByKey = NULL;
4346 RxFastIoDispatch.FastIoDeviceControl = RxFastIoDeviceControl;
4347 RxFastIoDispatch.AcquireFileForNtCreateSection = RxAcquireFileForNtCreateSection;
4348 RxFastIoDispatch.ReleaseFileForNtCreateSection = RxReleaseFileForNtCreateSection;
4349 RxFastIoDispatch.AcquireForCcFlush = RxAcquireForCcFlush;
4350 RxFastIoDispatch.ReleaseForCcFlush = RxReleaseForCcFlush;
4351
4352 RxInitializeTopLevelIrpPackage();
4353
4354 RxData.CacheManagerCallbacks.AcquireForLazyWrite = RxAcquireFcbForLazyWrite;
4355 RxData.CacheManagerCallbacks.ReleaseFromLazyWrite = RxReleaseFcbFromLazyWrite;
4356 RxData.CacheManagerCallbacks.AcquireForReadAhead = RxAcquireFcbForReadAhead;
4357 RxData.CacheManagerCallbacks.ReleaseFromReadAhead = RxReleaseFcbFromReadAhead;
4358
4359 RxData.CacheManagerNoOpCallbacks.AcquireForLazyWrite = RxNoOpAcquire;
4360 RxData.CacheManagerNoOpCallbacks.ReleaseFromLazyWrite = RxNoOpRelease;
4361 RxData.CacheManagerNoOpCallbacks.AcquireForReadAhead = RxNoOpAcquire;
4362 RxData.CacheManagerNoOpCallbacks.ReleaseFromReadAhead = RxNoOpRelease;
4363 }
4364
4365 NTSTATUS
4366 NTAPI
4367 RxInitializeLog(
4368 VOID)
4369 {
4370 UNIMPLEMENTED;
4371 return STATUS_NOT_IMPLEMENTED;
4372 }
4373
4374 /*
4375 * @implemented
4376 */
4377 VOID
4378 RxInitializeMinirdrDispatchTable(
4379 IN PDRIVER_OBJECT DriverObject)
4380 {
4381 PAGED_CODE();
4382 }
4383
4384 /*
4385 * @implemented
4386 */
4387 NTSTATUS
4388 NTAPI
4389 RxInitializeRegistrationStructures(
4390 VOID)
4391 {
4392 PAGED_CODE();
4393
4394 ExInitializeFastMutex(&RxData.MinirdrRegistrationMutex);
4395 RxData.NumberOfMinirdrsRegistered = 0;
4396 RxData.NumberOfMinirdrsStarted = 0;
4397 InitializeListHead(&RxData.RegisteredMiniRdrs);
4398
4399 return STATUS_SUCCESS;
4400 }
4401
4402 NTSTATUS
4403 NTAPI
4404 RxInitializeRxTimer(
4405 VOID)
4406 {
4407 UNIMPLEMENTED;
4408 return STATUS_NOT_IMPLEMENTED;
4409 }
4410
4411 /*
4412 * @implemented
4413 */
4414 VOID
4415 NTAPI
4416 RxInitializeTopLevelIrpPackage(
4417 VOID)
4418 {
4419 KeInitializeSpinLock(&TopLevelIrpSpinLock);
4420 InitializeListHead(&TopLevelIrpAllocatedContextsList);
4421 }
4422
4423 VOID
4424 NTAPI
4425 RxInitUnwind(
4426 PDRIVER_OBJECT DriverObject,
4427 USHORT State)
4428 {
4429 UNIMPLEMENTED;
4430 }
4431
4432 /*
4433 * @implemented
4434 */
4435 BOOLEAN
4436 RxIsMemberOfTopLevelIrpAllocatedContextsList(
4437 PRX_TOPLEVELIRP_CONTEXT TopLevelContext)
4438 {
4439 KIRQL OldIrql;
4440 PLIST_ENTRY NextEntry;
4441 BOOLEAN Found = FALSE;
4442 PRX_TOPLEVELIRP_CONTEXT ListContext;
4443
4444 /* Browse all the allocated TLC to find ours */
4445 KeAcquireSpinLock(&TopLevelIrpSpinLock, &OldIrql);
4446 for (NextEntry = TopLevelIrpAllocatedContextsList.Flink;
4447 NextEntry != &TopLevelIrpAllocatedContextsList;
4448 NextEntry = NextEntry->Flink)
4449 {
4450 ListContext = CONTAINING_RECORD(NextEntry, RX_TOPLEVELIRP_CONTEXT, ListEntry);
4451 ASSERT(ListContext->Signature == RX_TOPLEVELIRP_CONTEXT_SIGNATURE);
4452 ASSERT(BooleanFlagOn(ListContext->Flags, RX_TOPLEVELCTX_FLAG_FROM_POOL));
4453
4454 /* Found! */
4455 if (ListContext == TopLevelContext)
4456 {
4457 Found = TRUE;
4458 break;
4459 }
4460 }
4461 KeReleaseSpinLock(&TopLevelIrpSpinLock, OldIrql);
4462
4463 return Found;
4464 }
4465
4466 BOOLEAN
4467 RxIsOkToPurgeFcb(
4468 PFCB Fcb)
4469 {
4470 UNIMPLEMENTED;
4471 return FALSE;
4472 }
4473
4474 /*
4475 * @implemented
4476 */
4477 BOOLEAN
4478 RxIsThisAnRdbssTopLevelContext(
4479 PRX_TOPLEVELIRP_CONTEXT TopLevelContext)
4480 {
4481 ULONG_PTR StackTop, StackBottom;
4482
4483 /* Bail out for flags */
4484 if ((ULONG_PTR)TopLevelContext <= FSRTL_FAST_IO_TOP_LEVEL_IRP)
4485 {
4486 return FALSE;
4487 }
4488
4489 /* Is our provided TLC allocated on stack? */
4490 IoGetStackLimits(&StackTop, &StackBottom);
4491 if ((ULONG_PTR)TopLevelContext <= StackBottom - sizeof(RX_TOPLEVELIRP_CONTEXT) &&
4492 (ULONG_PTR)TopLevelContext >= StackTop)
4493 {
4494 /* Yes, so check whether it's really a TLC by checking alignement & signature */
4495 if (!BooleanFlagOn((ULONG_PTR)TopLevelContext, 0x3) && TopLevelContext->Signature == RX_TOPLEVELIRP_CONTEXT_SIGNATURE)
4496 {
4497 return TRUE;
4498 }
4499
4500 return FALSE;
4501 }
4502
4503 /* No, use the helper function */
4504 return RxIsMemberOfTopLevelIrpAllocatedContextsList(TopLevelContext);
4505 }
4506
4507 /*
4508 * @implemented
4509 */
4510 BOOLEAN
4511 RxIsThisTheTopLevelIrp(
4512 IN PIRP Irp)
4513 {
4514 PIRP TopLevelIrp;
4515
4516 /* When we put oursleves as top level, we set TLC as 'IRP', so look for it */
4517 TopLevelIrp = IoGetTopLevelIrp();
4518 if (RxIsThisAnRdbssTopLevelContext((PRX_TOPLEVELIRP_CONTEXT)TopLevelIrp))
4519 {
4520 TopLevelIrp = ((PRX_TOPLEVELIRP_CONTEXT)TopLevelIrp)->Irp;
4521 }
4522
4523 return (TopLevelIrp == Irp);
4524 }
4525
4526 NTSTATUS
4527 NTAPI
4528 RxLockOperationCompletion(
4529 IN PVOID Context,
4530 IN PIRP Irp)
4531 {
4532 UNIMPLEMENTED;
4533 return STATUS_NOT_IMPLEMENTED;
4534 }
4535
4536 /*
4537 * @implemented
4538 */
4539 VOID
4540 NTAPI
4541 RxLogEventDirect(
4542 IN PRDBSS_DEVICE_OBJECT DeviceObject,
4543 IN PUNICODE_STRING OriginatorId,
4544 IN ULONG EventId,
4545 IN NTSTATUS Status,
4546 IN ULONG Line)
4547 {
4548 PUNICODE_STRING Originator = OriginatorId;
4549 LARGE_INTEGER LargeLine;
4550
4551 /* Set optional parameters */
4552 LargeLine.QuadPart = Line;
4553 if (OriginatorId == NULL || OriginatorId->Length == 0)
4554 {
4555 Originator = (PUNICODE_STRING)&unknownId;
4556 }
4557
4558 /* And log */
4559 RxLogEventWithAnnotation(DeviceObject, EventId, Status, &LargeLine, sizeof(LargeLine), Originator, 1);
4560 }
4561
4562 VOID
4563 NTAPI
4564 RxLogEventWithAnnotation(
4565 IN PRDBSS_DEVICE_OBJECT DeviceObject,
4566 IN ULONG EventId,
4567 IN NTSTATUS Status,
4568 IN PVOID DataBuffer,
4569 IN USHORT DataBufferLength,
4570 IN PUNICODE_STRING Annotation,
4571 IN ULONG AnnotationCount)
4572 {
4573 UNIMPLEMENTED;
4574 }
4575
4576 NTSTATUS
4577 NTAPI
4578 RxLowIoCompletion(
4579 PRX_CONTEXT RxContext)
4580 {
4581 UNIMPLEMENTED;
4582 return STATUS_NOT_IMPLEMENTED;
4583 }
4584
4585 /*
4586 * @implemented
4587 */
4588 NTSTATUS
4589 NTAPI
4590 RxLowIoIoCtlShellCompletion(
4591 PRX_CONTEXT RxContext)
4592 {
4593 PIRP Irp;
4594 NTSTATUS Status;
4595
4596 PAGED_CODE();
4597
4598 DPRINT("RxLowIoIoCtlShellCompletion(%p)\n", RxContext);
4599
4600 Irp = RxContext->CurrentIrp;
4601 Status = RxContext->IoStatusBlock.Status;
4602
4603 /* Set information and status */
4604 if (NT_SUCCESS(Status) || Status == STATUS_BUFFER_OVERFLOW)
4605 {
4606 Irp->IoStatus.Information = RxContext->IoStatusBlock.Information;
4607 }
4608
4609 Irp->IoStatus.Status = Status;
4610
4611 return Status;
4612 }
4613
4614 /*
4615 * @implemented
4616 */
4617 NTSTATUS
4618 RxLowIoReadShell(
4619 PRX_CONTEXT RxContext)
4620 {
4621 PFCB Fcb;
4622 NTSTATUS Status;
4623
4624 PAGED_CODE();
4625
4626 DPRINT("RxLowIoReadShell(%p)\n", RxContext);
4627
4628 Fcb = (PFCB)RxContext->pFcb;
4629 if (BooleanFlagOn(Fcb->FcbState, FCB_STATE_FILE_IS_SHADOWED))
4630 {
4631 return STATUS_MORE_PROCESSING_REQUIRED;
4632 }
4633
4634 /* Always update stats for disks */
4635 if (Fcb->CachedNetRootType == NET_ROOT_DISK)
4636 {
4637 ExInterlockedAddLargeStatistic(&RxContext->RxDeviceObject->NetworkReadBytesRequested, RxContext->LowIoContext.ParamsFor.ReadWrite.ByteCount);
4638 }
4639
4640 /* And forward the read to the mini-rdr */
4641 Status = RxLowIoSubmit(RxContext, RxLowIoReadShellCompletion);
4642 DPRINT("RxLowIoReadShell(%p), Status: %lx\n", RxContext, Status);
4643
4644 return Status;
4645 }
4646
4647 NTSTATUS
4648 NTAPI
4649 RxLowIoReadShellCompletion(
4650 PRX_CONTEXT RxContext)
4651 {
4652 PIRP Irp;
4653 PFCB Fcb;
4654 NTSTATUS Status;
4655 BOOLEAN PagingIo, IsPipe;
4656 PIO_STACK_LOCATION Stack;
4657 PLOWIO_CONTEXT LowIoContext;
4658
4659 PAGED_CODE();
4660
4661 DPRINT("RxLowIoReadShellCompletion(%p)\n", RxContext);
4662
4663 Status = RxContext->IoStatusBlock.Status;
4664 DPRINT("In %p, Status: %lx, Information: %lx\n", RxContext, Status, RxContext->IoStatusBlock.Information);
4665
4666 Irp = RxContext->CurrentIrp;
4667 PagingIo = BooleanFlagOn(Irp->Flags, IRP_PAGING_IO);
4668
4669 /* Set IRP information from the RX_CONTEXT status block */
4670 Irp->IoStatus.Information = RxContext->IoStatusBlock.Information;
4671
4672 /* Fixup status for paging file if nothing was read */
4673 if (PagingIo)
4674 {
4675 if (NT_SUCCESS(Status) && RxContext->IoStatusBlock.Information == 0)
4676 {
4677 Status = STATUS_END_OF_FILE;
4678 }
4679 }
4680
4681 LowIoContext = &RxContext->LowIoContext;
4682 ASSERT(RxLowIoIsBufferLocked(LowIoContext));
4683
4684 /* Check broken cases that should never happen */
4685 Fcb = (PFCB)RxContext->pFcb;
4686 if (Status == STATUS_FILE_LOCK_CONFLICT)
4687 {
4688 if (BooleanFlagOn(RxContext->FlagsForLowIo, RXCONTEXT_FLAG4LOWIO_THIS_READ_ENLARGED))
4689 {
4690 ASSERT(FALSE);
4691 return STATUS_RETRY;
4692 }
4693 }
4694 else if (Status == STATUS_SUCCESS)
4695 {
4696 if (BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_RECURSIVE_CALL))
4697 {
4698 if (BooleanFlagOn(Fcb->FcbState, FCB_STATE_FILE_IS_DISK_COMPRESSED) ||
4699 BooleanFlagOn(Fcb->FcbState, FCB_STATE_FILE_IS_BUF_COMPRESSED))
4700 {
4701 ASSERT(FALSE);
4702 }
4703 }
4704
4705 if (BooleanFlagOn(Fcb->FcbState, FCB_STATE_FILE_IS_SHADOWED))
4706 {
4707 ASSERT(FALSE);
4708 }
4709 }
4710
4711 /* Readahead should go through Cc and not finish here */
4712 ASSERT(!BooleanFlagOn(RxContext->FlagsForLowIo, RXCONTEXT_FLAG4LOWIO_READAHEAD));
4713
4714 /* If it's sync, RxCommonRead will finish the work - nothing to do here */
4715 if (BooleanFlagOn(LowIoContext->Flags, LOWIO_CONTEXT_FLAG_SYNCCALL))
4716 {
4717 return Status;
4718 }
4719
4720 Stack = RxContext->CurrentIrpSp;
4721 IsPipe = BooleanFlagOn(RxContext->FlagsForLowIo, RXCONTEXT_FLAG4LOWIO_PIPE_OPERATION);
4722 /* Release lock if required */
4723 if (PagingIo)
4724 {
4725 RxReleasePagingIoResourceForThread(RxContext, Fcb, LowIoContext->ResourceThreadId);
4726 }
4727 else
4728 {
4729 /* Set FastIo if read was a success */
4730 if (NT_SUCCESS(Status) && !IsPipe)
4731 {
4732 SetFlag(Stack->FileObject->Flags, FO_FILE_FAST_IO_READ);
4733 }
4734
4735 if (BooleanFlagOn(RxContext->FlagsForLowIo, RXCONTEXT_FLAG4LOWIO_PIPE_SYNC_OPERATION))
4736 {
4737 RxResumeBlockedOperations_Serially(RxContext, &((PFOBX)RxContext->pFobx)->Specific.NamedPipe.ReadSerializationQueue);
4738 }
4739 else
4740 {
4741 RxReleaseFcbForThread(RxContext, Fcb, LowIoContext->ResourceThreadId);
4742 }
4743 }
4744
4745 if (IsPipe)
4746 {
4747 UNIMPLEMENTED;
4748 }
4749
4750 /* Final sanity checks */
4751 ASSERT(Status != STATUS_RETRY);
4752 ASSERT(Irp->IoStatus.Information <= Stack->Parameters.Read.Length);
4753 ASSERT(RxContext->MajorFunction == IRP_MJ_READ);
4754
4755 return Status;
4756 }
4757
4758 NTSTATUS
4759 RxNotifyChangeDirectory(
4760 PRX_CONTEXT RxContext)
4761 {
4762 UNIMPLEMENTED;
4763 return STATUS_NOT_IMPLEMENTED;
4764 }
4765
4766 NTSTATUS
4767 RxPostStackOverflowRead (
4768 IN PRX_CONTEXT RxContext)
4769 {
4770 PAGED_CODE();
4771
4772 UNIMPLEMENTED;
4773 return STATUS_NOT_IMPLEMENTED;
4774 }
4775
4776 /*
4777 * @implemented
4778 */
4779 VOID
4780 RxpPrepareCreateContextForReuse(
4781 PRX_CONTEXT RxContext)
4782 {
4783 /* Reuse can only happen for open operations (STATUS_RETRY) */
4784 ASSERT(RxContext->MajorFunction == IRP_MJ_CREATE);
4785
4786 /* Release the FCB if it was acquired */
4787 if (RxContext->Create.FcbAcquired)
4788 {
4789 RxReleaseFcb(RxContext, RxContext->pFcb);
4790 RxContext->Create.FcbAcquired = FALSE;
4791 }
4792
4793 /* Free the canonical name */
4794 RxFreeCanonicalNameBuffer(RxContext);
4795
4796 /* If we have a VNetRoot associated */
4797 if (RxContext->Create.pVNetRoot != NULL || RxContext->Create.NetNamePrefixEntry != NULL)
4798 {
4799 /* Remove our link and thus, dereference the VNetRoot */
4800 RxpAcquirePrefixTableLockShared(RxContext->RxDeviceObject->pRxNetNameTable, TRUE, TRUE);
4801 if (RxContext->Create.pVNetRoot != NULL)
4802 {
4803 RxDereferenceVNetRoot(RxContext->Create.pVNetRoot, TRUE);
4804 RxContext->Create.pVNetRoot = NULL;
4805 }
4806 RxpReleasePrefixTableLock(RxContext->RxDeviceObject->pRxNetNameTable, TRUE);
4807 }
4808
4809 DPRINT("RxContext: %p prepared for reuse\n", RxContext);
4810 }
4811
4812 /*
4813 * @implemented
4814 */
4815 NTSTATUS
4816 RxpQueryInfoMiniRdr(
4817 PRX_CONTEXT RxContext,
4818 FILE_INFORMATION_CLASS FileInfoClass,
4819 PVOID Buffer)
4820 {
4821 PFCB Fcb;
4822 NTSTATUS Status;
4823
4824 Fcb = (PFCB)RxContext->pFcb;
4825
4826 /* Set the RX_CONTEXT */
4827 RxContext->Info.FsInformationClass = FileInfoClass;
4828 RxContext->Info.Buffer = Buffer;
4829
4830 /* Pass down */
4831 MINIRDR_CALL(Status, RxContext, Fcb->MRxDispatch, MRxQueryFileInfo, (RxContext));
4832
4833 return Status;
4834 }
4835
4836 /*
4837 * @implemented
4838 */
4839 NTSTATUS
4840 RxPrefixClaim(
4841 IN PRX_CONTEXT RxContext)
4842 {
4843 PIRP Irp;
4844 NTSTATUS Status;
4845 NET_ROOT_TYPE NetRootType;
4846 UNICODE_STRING CanonicalName, FileName, NetRootName;
4847
4848 PAGED_CODE();
4849
4850 Irp = RxContext->CurrentIrp;
4851
4852 /* This has to come from MUP */
4853 if (Irp->RequestorMode == UserMode)
4854 {
4855 return STATUS_INVALID_DEVICE_REQUEST;
4856 }
4857
4858 if (RxContext->MajorFunction == IRP_MJ_DEVICE_CONTROL)
4859 {
4860 PQUERY_PATH_REQUEST QueryRequest;
4861
4862 /* Get parameters */
4863 QueryRequest = RxContext->CurrentIrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
4864
4865 /* Don't overflow allocation */
4866 if (QueryRequest->PathNameLength >= MAXUSHORT - 1)
4867 {
4868 return STATUS_INVALID_DEVICE_REQUEST;
4869 }
4870
4871 /* Forcefully rewrite IRP MJ */
4872 RxContext->MajorFunction = IRP_MJ_CREATE;
4873
4874 /* Fake canon name */
4875 RxContext->PrefixClaim.SuppliedPathName.Buffer = RxAllocatePoolWithTag(NonPagedPool, QueryRequest->PathNameLength, RX_MISC_POOLTAG);
4876 if (RxContext->PrefixClaim.SuppliedPathName.Buffer == NULL)
4877 {
4878 Status = STATUS_INSUFFICIENT_RESOURCES;
4879 goto Leave;
4880 }
4881
4882 /* Copy the prefix to look for */
4883 RtlCopyMemory(RxContext->PrefixClaim.SuppliedPathName.Buffer, &QueryRequest->FilePathName[0], QueryRequest->PathNameLength);
4884 RxContext->PrefixClaim.SuppliedPathName.Length = QueryRequest->PathNameLength;
4885 RxContext->PrefixClaim.SuppliedPathName.MaximumLength = QueryRequest->PathNameLength;
4886
4887 /* Zero the create parameters */
4888 RtlZeroMemory(&RxContext->Create.NtCreateParameters,
4889 FIELD_OFFSET(RX_CONTEXT, AlsoCanonicalNameBuffer) - FIELD_OFFSET(RX_CONTEXT, Create.NtCreateParameters));
4890 RxContext->Create.ThisIsATreeConnectOpen = TRUE;
4891 RxContext->Create.NtCreateParameters.SecurityContext = QueryRequest->SecurityContext;
4892 }
4893 else
4894 {
4895 /* If not devcontrol, it comes from open, name was already copied */
4896 ASSERT(RxContext->MajorFunction == IRP_MJ_CREATE);
4897 ASSERT(RxContext->PrefixClaim.SuppliedPathName.Buffer != NULL);
4898 }
4899
4900 /* Canonilize name */
4901 NetRootType = NET_ROOT_WILD;
4902 RtlInitEmptyUnicodeString(&CanonicalName, NULL, 0);
4903 FileName.Length = RxContext->PrefixClaim.SuppliedPathName.Length;
4904 FileName.MaximumLength = RxContext->PrefixClaim.SuppliedPathName.MaximumLength;
4905 FileName.Buffer = RxContext->PrefixClaim.SuppliedPathName.Buffer;
4906 NetRootName.Length = RxContext->PrefixClaim.SuppliedPathName.Length;
4907 NetRootName.MaximumLength = RxContext->PrefixClaim.SuppliedPathName.MaximumLength;
4908 NetRootName.Buffer = RxContext->PrefixClaim.SuppliedPathName.Buffer;
4909 Status = RxFirstCanonicalize(RxContext, &FileName, &CanonicalName, &NetRootType);
4910 /* It went fine, attempt to establish a connection (that way we know whether the prefix is accepted) */
4911 if (NT_SUCCESS(Status))
4912 {
4913 Status = RxFindOrConstructVirtualNetRoot(RxContext, &CanonicalName, NetRootType, &NetRootName);
4914 }
4915 if (Status == STATUS_PENDING)
4916 {
4917 return Status;
4918 }
4919 /* Reply to MUP */
4920 if (NT_SUCCESS(Status))
4921 {
4922 PQUERY_PATH_RESPONSE QueryResponse;
4923
4924 /* We accept the length that was canon (minus netroot) */
4925 QueryResponse = RxContext->CurrentIrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
4926 QueryResponse->LengthAccepted = RxContext->PrefixClaim.SuppliedPathName.Length - NetRootName.Length;
4927 }
4928
4929 Leave:
4930 /* If we reach that point with MJ, reset everything and make IRP being a device control */
4931 if (RxContext->MajorFunction == IRP_MJ_CREATE)
4932 {
4933 if (RxContext->PrefixClaim.SuppliedPathName.Buffer != NULL)
4934 {
4935 RxFreePoolWithTag(RxContext->PrefixClaim.SuppliedPathName.Buffer, RX_MISC_POOLTAG);
4936 }
4937
4938 RxpPrepareCreateContextForReuse(RxContext);
4939
4940 RxContext->MajorFunction = IRP_MJ_DEVICE_CONTROL;
4941 }
4942
4943 return Status;
4944 }
4945
4946 NTSTATUS
4947 NTAPI
4948 RxPrepareToReparseSymbolicLink(
4949 PRX_CONTEXT RxContext,
4950 BOOLEAN SymbolicLinkEmbeddedInOldPath,
4951 PUNICODE_STRING NewPath,
4952 BOOLEAN NewPathIsAbsolute,
4953 PBOOLEAN ReparseRequired)
4954 {
4955 UNIMPLEMENTED;
4956 return STATUS_NOT_IMPLEMENTED;
4957 }
4958
4959 /*
4960 * @implemented
4961 */
4962 VOID
4963 RxPrePostIrp(
4964 IN PVOID Context,
4965 IN PIRP Irp)
4966 {
4967 LOCK_OPERATION Lock;
4968 PIO_STACK_LOCATION Stack;
4969 PRX_CONTEXT RxContext = Context;
4970
4971 /* NULL IRP is no option */
4972 if (Irp == NULL)
4973 {
4974 return;
4975 }
4976
4977 /* Check whether preparation was really needed */
4978 if (BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_NO_PREPOSTING_NEEDED))
4979 {
4980 return;
4981 }
4982 /* Mark the context as prepared */
4983 SetFlag(RxContext->Flags, RX_CONTEXT_FLAG_NO_PREPOSTING_NEEDED);
4984
4985 /* Just lock the user buffer, with the correct length, depending on the MJ */
4986 Lock = IoReadAccess;
4987 Stack = RxContext->CurrentIrpSp;
4988 if (RxContext->MajorFunction == IRP_MJ_READ || RxContext->MajorFunction == IRP_MJ_WRITE)
4989 {
4990 if (!BooleanFlagOn(RxContext->MinorFunction, IRP_MN_MDL))
4991 {
4992 if (RxContext->MajorFunction == IRP_MJ_READ)
4993 {
4994 Lock = IoWriteAccess;
4995 }
4996 RxLockUserBuffer(RxContext, Lock, Stack->Parameters.Read.Length);
4997 }
4998 }
4999 else
5000 {
5001 if ((RxContext->MajorFunction == IRP_MJ_DIRECTORY_CONTROL && RxContext->MinorFunction == IRP_MN_QUERY_DIRECTORY) ||
5002 RxContext->MajorFunction == IRP_MJ_QUERY_EA)
5003 {
5004 Lock = IoWriteAccess;
5005 RxLockUserBuffer(RxContext, Lock, Stack->Parameters.QueryDirectory.Length);
5006 }
5007 else if (RxContext->MajorFunction == IRP_MJ_SET_EA)
5008 {
5009 RxLockUserBuffer(RxContext, Lock, Stack->Parameters.SetEa.Length);
5010 }
5011 }
5012
5013 /* As it will be posted (async), mark the IRP pending */
5014 IoMarkIrpPending(Irp);
5015 }
5016
5017 VOID
5018 NTAPI
5019 RxpUnregisterMinirdr(
5020 IN PRDBSS_DEVICE_OBJECT RxDeviceObject)
5021 {
5022 UNIMPLEMENTED;
5023 }
5024
5025 NTSTATUS
5026 RxQueryAlternateNameInfo(
5027 PRX_CONTEXT RxContext,
5028 PFILE_NAME_INFORMATION AltNameInfo)
5029 {
5030 UNIMPLEMENTED;
5031 return STATUS_NOT_IMPLEMENTED;
5032 }
5033
5034 /*
5035 * @implemented
5036 */
5037 NTSTATUS
5038 RxQueryBasicInfo(
5039 PRX_CONTEXT RxContext,
5040 PFILE_BASIC_INFORMATION BasicInfo)
5041 {
5042 PAGED_CODE();
5043
5044 DPRINT("RxQueryBasicInfo(%p, %p)\n", RxContext, BasicInfo);
5045
5046 /* Simply zero and forward to mini-rdr */
5047 RtlZeroMemory(BasicInfo, sizeof(FILE_BASIC_INFORMATION));
5048 return RxpQueryInfoMiniRdr(RxContext, FileBasicInformation, BasicInfo);
5049 }
5050
5051 NTSTATUS
5052 RxQueryCompressedInfo(
5053 PRX_CONTEXT RxContext,
5054 PFILE_COMPRESSION_INFORMATION CompressionInfo)
5055 {
5056 UNIMPLEMENTED;
5057 return STATUS_NOT_IMPLEMENTED;
5058 }
5059
5060 /*
5061 * @implemented
5062 */
5063 NTSTATUS
5064 RxQueryDirectory(
5065 PRX_CONTEXT RxContext)
5066 {
5067 PIRP Irp;
5068 PFCB Fcb;
5069 PFOBX Fobx;
5070 UCHAR Flags;
5071 NTSTATUS Status;
5072 BOOLEAN LockNotGranted;
5073 ULONG Length, FileIndex;
5074 PUNICODE_STRING FileName;
5075 PIO_STACK_LOCATION Stack;
5076 FILE_INFORMATION_CLASS FileInfoClass;
5077
5078 PAGED_CODE();
5079
5080 DPRINT("RxQueryDirectory(%p)\n", RxContext);
5081
5082 /* Get parameters */
5083 Stack = RxContext->CurrentIrpSp;
5084 Length = Stack->Parameters.QueryDirectory.Length;
5085 FileName = Stack->Parameters.QueryDirectory.FileName;
5086 FileInfoClass = Stack->Parameters.QueryDirectory.FileInformationClass;
5087 DPRINT("Wait: %d, Length: %ld, FileName: %p, Class: %d\n",
5088 FlagOn(RxContext->Flags, RX_CONTEXT_FLAG_WAIT), Length,
5089 FileName, FileInfoClass);
5090
5091 Irp = RxContext->CurrentIrp;
5092 Flags = Stack->Flags;
5093 FileIndex = Stack->Parameters.QueryDirectory.FileIndex;
5094 DPRINT("Index: %d, Buffer: %p, Flags: %x\n", FileIndex, Irp->UserBuffer, Flags);
5095
5096 if (FileName != NULL)
5097 {
5098 DPRINT("FileName: %wZ\n", FileName);
5099 }
5100
5101 /* No FOBX: not a standard file/directory */
5102 Fobx = (PFOBX)RxContext->pFobx;
5103 if (Fobx == NULL)
5104 {
5105 return STATUS_OBJECT_NAME_INVALID;
5106 }
5107
5108 /* We can only deal with a disk */
5109 Fcb = (PFCB)RxContext->pFcb;
5110 if (Fcb->pNetRoot->Type != NET_ROOT_DISK)
5111 {
5112 DPRINT1("Not a disk! %x\n", Fcb->pNetRoot->Type);
5113 return STATUS_INVALID_DEVICE_REQUEST;
5114 }
5115
5116 /* Setup RX_CONTEXT related fields */
5117 RxContext->QueryDirectory.FileIndex = FileIndex;
5118 RxContext->QueryDirectory.RestartScan = BooleanFlagOn(Flags, SL_RESTART_SCAN);
5119 RxContext->QueryDirectory.ReturnSingleEntry = BooleanFlagOn(Flags, SL_RETURN_SINGLE_ENTRY);
5120 RxContext->QueryDirectory.IndexSpecified = BooleanFlagOn(Flags, SL_INDEX_SPECIFIED);
5121 RxContext->QueryDirectory.InitialQuery = (Fobx->UnicodeQueryTemplate.Buffer == NULL) && !BooleanFlagOn(Fobx->Flags, FOBX_FLAG_MATCH_ALL);
5122
5123 /* We don't support (yet?) a specific index being set */
5124 if (RxContext->QueryDirectory.IndexSpecified)
5125 {
5126 return STATUS_NOT_IMPLEMENTED;
5127 }
5128
5129 /* Try to lock FCB */
5130 LockNotGranted = TRUE;
5131 if (RxContext->QueryDirectory.InitialQuery)
5132 {
5133 Status = RxAcquireExclusiveFcb(RxContext, Fcb);
5134 if (Status != STATUS_LOCK_NOT_GRANTED)
5135 {
5136 if (!NT_SUCCESS(Status))
5137 {
5138 return Status;
5139 }
5140
5141 if (Fobx->UnicodeQueryTemplate.Buffer != NULL)
5142 {
5143 RxContext->QueryDirectory.InitialQuery = FALSE;
5144 RxConvertToSharedFcb(RxContext, Fcb);
5145 }
5146
5147 LockNotGranted = FALSE;
5148 }
5149 }
5150 else
5151 {
5152 Status = RxAcquireExclusiveFcb(RxContext, Fcb);
5153 if (Status != STATUS_LOCK_NOT_GRANTED)
5154 {
5155 if (!NT_SUCCESS(Status))
5156 {
5157 return Status;
5158 }
5159
5160 LockNotGranted = FALSE;
5161 }
5162 }
5163
5164 /* If it failed, post request */
5165 if (LockNotGranted)
5166 {
5167 return RxFsdPostRequest(RxContext);
5168 }
5169
5170 /* This cannot be done on a orphaned directory */
5171 if (BooleanFlagOn(Fcb->FcbState, FCB_STATE_ORPHANED))
5172 {
5173 RxReleaseFcb(RxContext, Fcb);
5174 return STATUS_FILE_CLOSED;
5175 }
5176
5177 _SEH2_TRY
5178 {
5179 /* Set index */
5180 if (!RxContext->QueryDirectory.IndexSpecified && RxContext->QueryDirectory.RestartScan)
5181 {
5182 RxContext->QueryDirectory.FileIndex = 0;
5183 }
5184
5185 /* Assume success */
5186 Status = STATUS_SUCCESS;
5187 /* If initial query, prepare FOBX */
5188 if (RxContext->QueryDirectory.InitialQuery)
5189 {
5190 /* We cannot have a template already! */
5191 ASSERT(!BooleanFlagOn(Fobx->Flags, FOBX_FLAG_FREE_UNICODE));
5192
5193 /* If we have a file name and a correct one, duplicate it in the FOBX */
5194 if (FileName != NULL && FileName->Length != 0 && FileName->Buffer != NULL &&
5195 (FileName->Length != sizeof(WCHAR) || FileName->Buffer[0] != '*') &&
5196 (FileName->Length != 12 * sizeof(WCHAR) ||
5197 RtlCompareMemory(FileName->Buffer, Rx8QMdot3QM, 12 * sizeof(WCHAR)) != 12 * sizeof(WCHAR)))
5198 {
5199 Fobx->ContainsWildCards = FsRtlDoesNameContainWildCards(FileName);
5200
5201 Fobx->UnicodeQueryTemplate.Buffer = RxAllocatePoolWithTag(PagedPool, FileName->Length, RX_DIRCTL_POOLTAG);
5202 if (Fobx->UnicodeQueryTemplate.Buffer != NULL)
5203 {
5204 /* UNICODE_STRING; length has to be even */
5205 if ((FileName->Length & 1) != 0)
5206 {
5207 Status = STATUS_INVALID_PARAMETER;
5208 RxFreePoolWithTag(Fobx->UnicodeQueryTemplate.Buffer, RX_DIRCTL_POOLTAG);
5209 }
5210 else
5211 {
5212 Fobx->UnicodeQueryTemplate.Length = FileName->Length;
5213 Fobx->UnicodeQueryTemplate.MaximumLength = FileName->Length;
5214 RtlMoveMemory(Fobx->UnicodeQueryTemplate.Buffer, FileName->Buffer, FileName->Length);
5215
5216 SetFlag(Fobx->Flags, FOBX_FLAG_FREE_UNICODE);
5217 }
5218 }
5219 else
5220 {
5221 Status = STATUS_INSUFFICIENT_RESOURCES;
5222 }
5223 }
5224 /* No name specified, or a match all wildcard? Match everything */
5225 else
5226 {
5227 Fobx->ContainsWildCards = TRUE;
5228
5229 Fobx->UnicodeQueryTemplate.Buffer = &RxStarForTemplate;
5230 Fobx->UnicodeQueryTemplate.Length = sizeof(WCHAR);
5231 Fobx->UnicodeQueryTemplate.MaximumLength = sizeof(WCHAR);
5232
5233 SetFlag(Fobx->Flags, FOBX_FLAG_MATCH_ALL);
5234 }
5235
5236 /* No need for exclusive any longer */
5237 if (NT_SUCCESS(Status))
5238 {
5239 RxConvertToSharedFcb(RxContext, Fcb);
5240 }
5241 }
5242
5243 /* Lock user buffer and forward to mini-rdr */
5244 if (NT_SUCCESS(Status))
5245 {
5246 RxLockUserBuffer(RxContext, IoModifyAccess, Length);
5247 RxContext->Info.FileInformationClass = FileInfoClass;
5248 RxContext->Info.Buffer = RxNewMapUserBuffer(RxContext);
5249 RxContext->Info.Length = Length;
5250
5251 if (RxContext->Info.Buffer != NULL)
5252 {
5253 MINIRDR_CALL(Status, RxContext, Fcb->MRxDispatch, MRxQueryDirectory, (RxContext));
5254 }
5255
5256 /* Post if mini-rdr asks to */
5257 if (RxContext->PostRequest)
5258 {
5259 RxFsdPostRequest(RxContext);
5260 }
5261 else
5262 {
5263 Irp->IoStatus.Information = Length - RxContext->Info.LengthRemaining;
5264 }
5265 }
5266 }
5267 _SEH2_FINALLY
5268 {
5269 RxReleaseFcb(RxContext, Fcb);
5270 }
5271 _SEH2_END;
5272
5273 return Status;
5274 }
5275
5276 NTSTATUS
5277 RxQueryEaInfo(
5278 PRX_CONTEXT RxContext,
5279 PFILE_EA_INFORMATION EaInfo)
5280 {
5281 UNIMPLEMENTED;
5282 return STATUS_NOT_IMPLEMENTED;
5283 }
5284
5285 NTSTATUS
5286 RxQueryInternalInfo(
5287 PRX_CONTEXT RxContext,
5288 PFILE_INTERNAL_INFORMATION InternalInfo)
5289 {
5290 UNIMPLEMENTED;
5291 return STATUS_NOT_IMPLEMENTED;
5292 }
5293
5294 NTSTATUS
5295 RxQueryNameInfo(
5296 PRX_CONTEXT RxContext,
5297 PFILE_NAME_INFORMATION NameInfo)
5298 {
5299 UNIMPLEMENTED;
5300 return STATUS_NOT_IMPLEMENTED;
5301 }
5302
5303 NTSTATUS
5304 RxQueryPipeInfo(
5305 PRX_CONTEXT RxContext,
5306 PFILE_PIPE_INFORMATION PipeInfo)
5307 {
5308 UNIMPLEMENTED;
5309 return STATUS_NOT_IMPLEMENTED;
5310 }
5311
5312 NTSTATUS
5313 RxQueryPositionInfo(
5314 PRX_CONTEXT RxContext,
5315 PFILE_POSITION_INFORMATION PositionInfo)
5316 {
5317 UNIMPLEMENTED;
5318 return STATUS_NOT_IMPLEMENTED;
5319 }
5320
5321 /*
5322 * @implemented
5323 */
5324 NTSTATUS
5325 RxQueryStandardInfo(
5326 PRX_CONTEXT RxContext,
5327 PFILE_STANDARD_INFORMATION StandardInfo)
5328 {
5329 PFCB Fcb;
5330 PFOBX Fobx;
5331 NTSTATUS Status;
5332
5333 PAGED_CODE();
5334
5335 DPRINT("RxQueryStandardInfo(%p, %p)\n", RxContext, StandardInfo);
5336
5337 /* Zero output buffer */
5338 RtlZeroMemory(StandardInfo, sizeof(FILE_STANDARD_INFORMATION));
5339
5340 Fcb = (PFCB)RxContext->pFcb;
5341 Fobx = (PFOBX)RxContext->pFobx;
5342 /* If not a standard file type, or opened for backup, immediately forward to mini-rdr */
5343 if ((NodeType(Fcb) != RDBSS_NTC_STORAGE_TYPE_DIRECTORY && NodeType(Fcb) != RDBSS_NTC_STORAGE_TYPE_FILE) ||
5344 BooleanFlagOn(Fobx->pSrvOpen->CreateOptions, FILE_OPEN_FOR_BACKUP_INTENT))
5345 {
5346 return RxpQueryInfoMiniRdr(RxContext, FileStandardInformation, StandardInfo);
5347 }
5348
5349 /* Otherwise, fill what we can already */
5350 Status = STATUS_SUCCESS;
5351 StandardInfo->NumberOfLinks = Fcb->NumberOfLinks;
5352 StandardInfo->DeletePending = BooleanFlagOn(Fcb->FcbState, FCB_STATE_DELETE_ON_CLOSE);
5353 StandardInfo->Directory = (NodeType(Fcb) == RDBSS_NTC_STORAGE_TYPE_DIRECTORY);
5354 if (StandardInfo->NumberOfLinks == 0)
5355 {
5356 StandardInfo->NumberOfLinks = 1;
5357 }
5358
5359 if (NodeType(Fcb) == RDBSS_NTC_STORAGE_TYPE_FILE)
5360 {
5361 StandardInfo->AllocationSize.QuadPart = Fcb->Header.AllocationSize.QuadPart;
5362 RxGetFileSizeWithLock(Fcb, &StandardInfo->EndOfFile.QuadPart);
5363 }
5364
5365 /* If we are asked to forcefully forward to mini-rdr or if size isn't cached, do it */
5366 if (RxForceQFIPassThrough || !BooleanFlagOn(Fcb->FcbState, FCB_STATE_FILESIZECACHEING_ENABLED))
5367 {
5368 Status = RxpQueryInfoMiniRdr(RxContext, FileStandardInformation, StandardInfo);
5369 }
5370 else
5371 {
5372 RxContext->IoStatusBlock.Information -= sizeof(FILE_STANDARD_INFORMATION);
5373 }
5374
5375 return Status;
5376 }
5377
5378 /*
5379 * @implemented
5380 */
5381 VOID
5382 NTAPI
5383 RxReadRegistryParameters(
5384 VOID)
5385 {
5386 NTSTATUS Status;
5387 HANDLE KeyHandle;
5388 ULONG ResultLength;
5389 UCHAR Buffer[0x40];
5390 UNICODE_STRING KeyName, ParamName;
5391 OBJECT_ATTRIBUTES ObjectAttributes;
5392 PKEY_VALUE_PARTIAL_INFORMATION PartialInfo;
5393
5394 PAGED_CODE();
5395
5396 RtlInitUnicodeString(&KeyName, L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\LanmanWorkStation\\Parameters");
5397 InitializeObjectAttributes(&ObjectAttributes, &KeyName, OBJ_CASE_INSENSITIVE, NULL, NULL);
5398 Status = ZwOpenKey(&KeyHandle, READ_CONTROL | KEY_NOTIFY | KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE, &ObjectAttributes);
5399 if (!NT_SUCCESS(Status))
5400 {
5401 return;
5402 }
5403
5404 PartialInfo = (PKEY_VALUE_PARTIAL_INFORMATION)Buffer;
5405 RtlInitUnicodeString(&ParamName, L"DisableByteRangeLockingOnReadOnlyFiles");
5406 Status = ZwQueryValueKey(KeyHandle, &ParamName, KeyValuePartialInformation, PartialInfo, sizeof(Buffer), &ResultLength);
5407 if (NT_SUCCESS(Status) && PartialInfo->Type == REG_DWORD)
5408 {
5409 DisableByteRangeLockingOnReadOnlyFiles = ((ULONG)PartialInfo->Data != 0);
5410 }
5411
5412 RtlInitUnicodeString(&ParamName, L"ReadAheadGranularity");
5413 Status = ZwQueryValueKey(KeyHandle, &ParamName, KeyValuePartialInformation, PartialInfo, sizeof(Buffer), &ResultLength);
5414 if (NT_SUCCESS(Status) && PartialInfo->Type == REG_DWORD)
5415 {
5416 ULONG Granularity = (ULONG)PartialInfo->Data;
5417
5418 if (Granularity > 16)
5419 {
5420 Granularity = 16;
5421 }
5422
5423 ReadAheadGranularity = Granularity << PAGE_SHIFT;
5424 }
5425
5426 RtlInitUnicodeString(&ParamName, L"DisableFlushOnCleanup");
5427 Status = ZwQueryValueKey(KeyHandle, &ParamName, KeyValuePartialInformation, PartialInfo, sizeof(Buffer), &ResultLength);
5428 if (NT_SUCCESS(Status) && PartialInfo->Type == REG_DWORD)
5429 {
5430 DisableFlushOnCleanup = ((ULONG)PartialInfo->Data != 0);
5431 }
5432
5433 ZwClose(KeyHandle);
5434 }
5435
5436 /*
5437 * @implemented
5438 */
5439 NTSTATUS
5440 NTAPI
5441 RxRegisterMinirdr(
5442 OUT PRDBSS_DEVICE_OBJECT *DeviceObject,
5443 IN OUT PDRIVER_OBJECT DriverObject,
5444 IN PMINIRDR_DISPATCH MrdrDispatch,
5445 IN ULONG Controls,
5446 IN PUNICODE_STRING DeviceName,
5447 IN ULONG DeviceExtensionSize,
5448 IN DEVICE_TYPE DeviceType,
5449 IN ULONG DeviceCharacteristics)
5450 {
5451 NTSTATUS Status;
5452 PRDBSS_DEVICE_OBJECT RDBSSDevice;
5453
5454 PAGED_CODE();
5455
5456 if (!DeviceObject)
5457 {
5458 return STATUS_INVALID_PARAMETER;
5459 }
5460
5461 /* Create device object with provided parameters */
5462 Status = IoCreateDevice(DriverObject,
5463 DeviceExtensionSize + sizeof(RDBSS_DEVICE_OBJECT),
5464 DeviceName,
5465 DeviceType,
5466 DeviceCharacteristics,
5467 FALSE,
5468 (PDEVICE_OBJECT *)&RDBSSDevice);
5469 if (!NT_SUCCESS(Status))
5470 {
5471 return Status;
5472 }
5473
5474 if (!RxData.DriverObject)
5475 {
5476 return STATUS_UNSUCCESSFUL;
5477 }
5478
5479 /* Initialize our DO extension */
5480 RDBSSDevice->RDBSSDeviceObject = NULL;
5481 ++RxFileSystemDeviceObject->ReferenceCount;
5482 *DeviceObject = RDBSSDevice;
5483 RDBSSDevice->RdbssExports = &RxExports;
5484 RDBSSDevice->Dispatch = MrdrDispatch;
5485 RDBSSDevice->RegistrationControls = Controls;
5486 RDBSSDevice->DeviceName = *DeviceName;
5487 RDBSSDevice->RegisterUncProvider = !BooleanFlagOn(Controls, RX_REGISTERMINI_FLAG_DONT_PROVIDE_UNCS);
5488 RDBSSDevice->RegisterMailSlotProvider = !BooleanFlagOn(Controls, RX_REGISTERMINI_FLAG_DONT_PROVIDE_MAILSLOTS);
5489 InitializeListHead(&RDBSSDevice->OverflowQueue[0]);
5490 InitializeListHead(&RDBSSDevice->OverflowQueue[1]);
5491 InitializeListHead(&RDBSSDevice->OverflowQueue[2]);
5492 KeInitializeSpinLock(&RDBSSDevice->OverflowQueueSpinLock);
5493 RDBSSDevice->NetworkProviderPriority = RxGetNetworkProviderPriority(DeviceName);
5494
5495 DPRINT("Registered MiniRdr %wZ (prio: %x)\n", DeviceName, RDBSSDevice->NetworkProviderPriority);
5496
5497 ExAcquireFastMutex(&RxData.MinirdrRegistrationMutex);
5498 InsertTailList(&RxData.RegisteredMiniRdrs, &RDBSSDevice->MiniRdrListLinks);
5499 ExReleaseFastMutex(&RxData.MinirdrRegistrationMutex);
5500
5501 /* Unless mini-rdr explicitly asked not to, initialize dispatch table */
5502 if (!BooleanFlagOn(Controls, RX_REGISTERMINI_FLAG_DONT_INIT_DRIVER_DISPATCH))
5503 {
5504 RxInitializeMinirdrDispatchTable(DriverObject);
5505 }
5506
5507 /* Unless mini-rdr explicitly asked not to, initialize prefix scavenger */
5508 if (!BooleanFlagOn(Controls, RX_REGISTERMINI_FLAG_DONT_INIT_PREFIX_N_SCAVENGER))
5509 {
5510 LARGE_INTEGER ScavengerTimeLimit;
5511
5512 RDBSSDevice->pRxNetNameTable = &RDBSSDevice->RxNetNameTableInDeviceObject;
5513 RxInitializePrefixTable(RDBSSDevice->pRxNetNameTable, 0, FALSE);
5514 RDBSSDevice->RxNetNameTableInDeviceObject.IsNetNameTable = TRUE;
5515 ScavengerTimeLimit.QuadPart = MrdrDispatch->ScavengerTimeout * 10000000LL;
5516 RDBSSDevice->pRdbssScavenger = &RDBSSDevice->RdbssScavengerInDeviceObject;
5517 RxInitializeRdbssScavenger(RDBSSDevice->pRdbssScavenger, ScavengerTimeLimit);
5518 }
5519
5520 RDBSSDevice->pAsynchronousRequestsCompletionEvent = NULL;
5521
5522 return STATUS_SUCCESS;
5523 }
5524
5525 VOID
5526 NTAPI
5527 RxReleaseFcbFromLazyWrite(
5528 PVOID Context)
5529 {
5530 UNIMPLEMENTED;
5531 }
5532
5533 VOID
5534 NTAPI
5535 RxReleaseFcbFromReadAhead(
5536 PVOID Context)
5537 {
5538 UNIMPLEMENTED;
5539 }
5540
5541 VOID
5542 NTAPI
5543 RxReleaseFileForNtCreateSection(
5544 PFILE_OBJECT FileObject)
5545 {
5546 UNIMPLEMENTED;
5547 }
5548
5549 NTSTATUS
5550 NTAPI
5551 RxReleaseForCcFlush(
5552 PFILE_OBJECT FileObject,
5553 PDEVICE_OBJECT DeviceObject)
5554 {
5555 UNIMPLEMENTED;
5556 return STATUS_NOT_IMPLEMENTED;
5557 }
5558
5559 /*
5560 * @implemented
5561 */
5562 VOID
5563 RxRemoveFromTopLevelIrpAllocatedContextsList(
5564 PRX_TOPLEVELIRP_CONTEXT TopLevelContext)
5565 {
5566 KIRQL OldIrql;
5567
5568 /* Make sure this is a TLC and that it was allocated (otherwise, it is not in the list */
5569 ASSERT(TopLevelContext->Signature == RX_TOPLEVELIRP_CONTEXT_SIGNATURE);
5570 ASSERT(BooleanFlagOn(TopLevelContext->Flags, RX_TOPLEVELCTX_FLAG_FROM_POOL));
5571
5572 KeAcquireSpinLock(&TopLevelIrpSpinLock, &OldIrql);
5573 RemoveEntryList(&TopLevelContext->ListEntry);
5574 KeReleaseSpinLock(&TopLevelIrpSpinLock, OldIrql);
5575 }
5576
5577 /*
5578 * @implemented
5579 */
5580 PRX_CONTEXT
5581 RxRemoveOverflowEntry(
5582 PRDBSS_DEVICE_OBJECT DeviceObject,
5583 WORK_QUEUE_TYPE Queue)
5584 {
5585 KIRQL OldIrql;
5586 PRX_CONTEXT Context;
5587
5588 KeAcquireSpinLock(&DeviceObject->OverflowQueueSpinLock, &OldIrql);
5589 if (DeviceObject->OverflowQueueCount[Queue] <= 0)
5590 {
5591 /* No entries left, nothing to return */
5592 InterlockedDecrement(&DeviceObject->PostedRequestCount[Queue]);
5593 Context = NULL;
5594 }
5595 else
5596 {
5597 PLIST_ENTRY Entry;
5598
5599 /* Decrement count */
5600 --DeviceObject->OverflowQueueCount[Queue];
5601
5602 /* Return head */
5603 Entry = RemoveHeadList(&DeviceObject->OverflowQueue[Queue]);
5604 Context = CONTAINING_RECORD(Entry, RX_CONTEXT, OverflowListEntry);
5605 ClearFlag(Context->Flags, ~(RX_CONTEXT_FLAG_FSP_DELAYED_OVERFLOW_QUEUE | RX_CONTEXT_FLAG_FSP_CRITICAL_OVERFLOW_QUEUE));
5606 Context->OverflowListEntry.Flink = NULL;
5607 }
5608 KeReleaseSpinLock(&DeviceObject->OverflowQueueSpinLock, OldIrql);
5609
5610 return Context;
5611 }
5612
5613 VOID
5614 RxRemoveShareAccess(
5615 _Inout_ PFILE_OBJECT FileObject,
5616 _Inout_ PSHARE_ACCESS ShareAccess,
5617 _In_ PSZ where,
5618 _In_ PSZ wherelogtag)
5619 {
5620 UNIMPLEMENTED;
5621 }
5622
5623 NTSTATUS
5624 RxSearchForCollapsibleOpen(
5625 PRX_CONTEXT RxContext,
5626 ACCESS_MASK DesiredAccess,
5627 ULONG ShareAccess)
5628 {
5629 PFCB Fcb;
5630 NTSTATUS Status;
5631 PLIST_ENTRY ListEntry;
5632 BOOLEAN ShouldTry, Purged, Scavenged;
5633
5634 PAGED_CODE();
5635
5636 DPRINT("RxSearchForCollapsibleOpen(%p, %x, %x)\n", RxContext, DesiredAccess, ShareAccess);
5637
5638 Fcb = (PFCB)RxContext->pFcb;
5639
5640 /* If we're asked to open for backup, don't allow SRV_OPEN reuse */
5641 if (BooleanFlagOn(RxContext->Create.NtCreateParameters.CreateOptions, FILE_OPEN_FOR_BACKUP_INTENT))
5642 {
5643 ClearFlag(Fcb->FcbState, FCB_STATE_COLLAPSING_ENABLED);
5644
5645 RxScavengeRelatedFobxs(Fcb);
5646 RxPurgeFcbInSystemCache(Fcb, NULL, 0, FALSE, TRUE);
5647
5648 return STATUS_NOT_FOUND;
5649 }
5650
5651 /* If basic open, ask the mini-rdr if we should try to collapse */
5652 if (RxContext->Create.NtCreateParameters.Disposition == FILE_OPEN ||
5653 RxContext->Create.NtCreateParameters.Disposition == FILE_OPEN_IF)
5654 {
5655 ShouldTry = TRUE;
5656
5657 if (Fcb->MRxDispatch != NULL)
5658 {
5659 ASSERT(RxContext->pRelevantSrvOpen == NULL);
5660 ASSERT(Fcb->MRxDispatch->MRxShouldTryToCollapseThisOpen != NULL);
5661
5662 ShouldTry = NT_SUCCESS(Fcb->MRxDispatch->MRxShouldTryToCollapseThisOpen(RxContext));
5663 }
5664 }
5665 else
5666 {
5667 ShouldTry = FALSE;
5668 }
5669
5670 if (BooleanFlagOn(RxContext->Create.NtCreateParameters.CreateOptions, FILE_DELETE_ON_CLOSE))
5671 {
5672 ShouldTry = FALSE;
5673 }
5674
5675 /* If we shouldn't try, ask the caller to allocate a new SRV_OPEN */
5676 if (!ShouldTry)
5677 {
5678 if (NT_SUCCESS(RxCheckShareAccessPerSrvOpens(Fcb, DesiredAccess, ShareAccess)))
5679 {
5680 return STATUS_NOT_FOUND;
5681 }
5682
5683 ClearFlag(Fcb->FcbState, FCB_STATE_COLLAPSING_ENABLED);
5684
5685 RxScavengeRelatedFobxs(Fcb);
5686 RxPurgeFcbInSystemCache(Fcb, NULL, 0, FALSE, TRUE);
5687
5688 return STATUS_NOT_FOUND;
5689 }
5690
5691 /* Only collapse for matching NET_ROOT & disks */
5692 if (Fcb->pNetRoot != RxContext->Create.pNetRoot ||
5693 Fcb->pNetRoot->Type != NET_ROOT_DISK)
5694 {
5695 return STATUS_NOT_FOUND;
5696 }
5697
5698 Purged = FALSE;
5699 Scavenged = FALSE;
5700 Status = STATUS_NOT_FOUND;
5701 TryAgain:
5702 /* Browse all our SRV_OPEN to find the matching one */
5703 for (ListEntry = Fcb->SrvOpenList.Flink;
5704 ListEntry != &Fcb->SrvOpenList;
5705 ListEntry = ListEntry->Flink)
5706 {
5707 PSRV_OPEN SrvOpen;
5708
5709 SrvOpen = CONTAINING_RECORD(ListEntry, SRV_OPEN, SrvOpenQLinks);
5710 /* Not the same VNET_ROOT, move to the next one */
5711 if (SrvOpen->pVNetRoot != RxContext->Create.pVNetRoot)
5712 {
5713 RxContext->Create.TryForScavengingOnSharingViolation = TRUE;
5714 continue;
5715 }
5716
5717 /* Is there a sharing violation? */
5718 if (SrvOpen->DesiredAccess != DesiredAccess || SrvOpen->ShareAccess != ShareAccess ||
5719 BooleanFlagOn(SrvOpen->Flags, (SRVOPEN_FLAG_CLOSED | SRVOPEN_FLAG_COLLAPSING_DISABLED | SRVOPEN_FLAG_FILE_DELETED | SRVOPEN_FLAG_FILE_RENAMED)))
5720 {
5721 if (SrvOpen->pVNetRoot != RxContext->Create.pVNetRoot)
5722 {
5723 RxContext->Create.TryForScavengingOnSharingViolation = TRUE;
5724 continue;
5725 }
5726
5727 /* Check against the SRV_OPEN */
5728 Status = RxCheckShareAccessPerSrvOpens(Fcb, DesiredAccess, ShareAccess);
5729 if (!NT_SUCCESS(Status))
5730 {
5731 break;
5732 }
5733 }
5734 else
5735 {
5736 /* Don't allow collaspse for reparse point opening */
5737 if (BooleanFlagOn(RxContext->Create.NtCreateParameters.CreateOptions ^ SrvOpen->CreateOptions, FILE_OPEN_REPARSE_POINT))
5738 {
5739 Purged = TRUE;
5740 Scavenged = TRUE;
5741 Status = STATUS_NOT_FOUND;
5742 break;
5743 }
5744
5745 /* Not readonly? Or bytereange lock disabled? Try to collapse! */
5746 if (DisableByteRangeLockingOnReadOnlyFiles || !BooleanFlagOn(SrvOpen->pFcb->Attributes, FILE_ATTRIBUTE_READONLY))
5747 {
5748 RxContext->pRelevantSrvOpen = (PMRX_SRV_OPEN)SrvOpen;
5749
5750 ASSERT(Fcb->MRxDispatch->MRxShouldTryToCollapseThisOpen != NULL);
5751 if (NT_SUCCESS(Fcb->MRxDispatch->MRxShouldTryToCollapseThisOpen(RxContext)))
5752 {
5753 /* Is close delayed - great reuse*/
5754 if (BooleanFlagOn(SrvOpen->Flags, SRVOPEN_FLAG_CLOSE_DELAYED))
5755 {
5756 DPRINT("Delayed close successfull, reusing %p\n", SrvOpen);
5757 InterlockedDecrement(&((PSRV_CALL)Fcb->pNetRoot->pSrvCall)->NumberOfCloseDelayedFiles);
5758 ClearFlag(SrvOpen->Flags, SRVOPEN_FLAG_CLOSE_DELAYED);
5759 }
5760
5761 return STATUS_SUCCESS;
5762 }
5763
5764 Status = STATUS_NOT_FOUND;
5765 break;
5766 }
5767 }
5768 }
5769 /* We browse the whole list and didn't find any matching? NOT_FOUND */
5770 if (ListEntry == &Fcb->SrvOpenList)
5771 {
5772 Status = STATUS_NOT_FOUND;
5773 }
5774
5775 /* Only required access: read attributes? Don't reuse */
5776 if ((DesiredAccess & 0xFFEFFFFF) == FILE_READ_ATTRIBUTES)
5777 {
5778 return STATUS_NOT_FOUND;
5779 }
5780
5781 /* Not found? Scavenge and retry to look for collaspile SRV_OPEN */
5782 if (!Scavenged)
5783 {
5784 ClearFlag(Fcb->FcbState, FCB_STATE_COLLAPSING_ENABLED);
5785 Scavenged = TRUE;
5786 RxScavengeRelatedFobxs(Fcb);
5787 goto TryAgain;
5788 }
5789
5790 /* Not found? Purgeable? Purge and retry to look for collaspile SRV_OPEN */
5791 if (!Purged && RxIsOkToPurgeFcb(Fcb))
5792 {
5793 RxPurgeFcbInSystemCache(Fcb, NULL, 0, FALSE, TRUE);
5794 Purged = TRUE;
5795 goto TryAgain;
5796 }
5797
5798 /* If sharing violation, keep track of it */
5799 if (Status == STATUS_SHARING_VIOLATION)
5800 {
5801 RxContext->Create.TryForScavengingOnSharingViolation = TRUE;
5802 }
5803
5804 DPRINT("Status: %x\n", Status);
5805 return Status;
5806 }
5807
5808 /*
5809 * @implemented
5810 */
5811 VOID
5812 RxSetShareAccess(
5813 _In_ ACCESS_MASK DesiredAccess,
5814 _In_ ULONG DesiredShareAccess,
5815 _Inout_ PFILE_OBJECT FileObject,
5816 _Out_ PSHARE_ACCESS ShareAccess,
5817 _In_ PSZ where,
5818 _In_ PSZ wherelogtag)
5819 {
5820 PAGED_CODE();
5821
5822 RxDumpCurrentAccess(where, "before", wherelogtag, ShareAccess);
5823 IoSetShareAccess(DesiredAccess, DesiredShareAccess, FileObject, ShareAccess);
5824 RxDumpCurrentAccess(where, "after", wherelogtag, ShareAccess);
5825 }
5826
5827 /*
5828 * @implemented
5829 */
5830 VOID
5831 RxSetupNetFileObject(
5832 PRX_CONTEXT RxContext)
5833 {
5834 PFCB Fcb;
5835 PFOBX Fobx;
5836 PFILE_OBJECT FileObject;
5837 PIO_STACK_LOCATION Stack;
5838
5839 PAGED_CODE();
5840
5841 /* Assert FOBX is FOBX or NULL */
5842 Fobx = (PFOBX)RxContext->pFobx;
5843 ASSERT((Fobx == NULL) || (NodeType(Fobx) == RDBSS_NTC_FOBX));
5844
5845 Fcb = (PFCB)RxContext->pFcb;
5846 Stack = RxContext->CurrentIrpSp;
5847 FileObject = Stack->FileObject;
5848 /* If it's temporary mark FO as such */
5849 if (Fcb != NULL && NodeType(Fcb) != RDBSS_NTC_VCB &&
5850 BooleanFlagOn(Fcb->FcbState, FCB_STATE_TEMPORARY))
5851 {
5852 if (FileObject == NULL)
5853 {
5854 return;
5855 }
5856
5857 FileObject->Flags |= FO_TEMPORARY_FILE;
5858 }
5859
5860 /* No FO, nothing to setup */
5861 if (FileObject == NULL)
5862 {
5863 return;
5864 }
5865
5866 /* Assign FCB & CCB (FOBX) to FO */
5867 FileObject->FsContext = Fcb;
5868 FileObject->FsContext2 = Fobx;
5869 if (Fobx != NULL)
5870 {
5871 ULONG_PTR StackTop, StackBottom;
5872
5873 /* If FO is allocated on pool, keep track of it */
5874 IoGetStackLimits(&StackTop, &StackBottom);
5875 if ((ULONG_PTR)FileObject <= StackBottom || (ULONG_PTR)FileObject >= StackTop)
5876 {
5877 Fobx->AssociatedFileObject = FileObject;
5878 }
5879 else
5880 {
5881 Fobx->AssociatedFileObject = NULL;
5882 }
5883
5884 /* Make sure to mark FOBX if it's a DFS open */
5885 if (RxContext->Create.NtCreateParameters.DfsContext == UIntToPtr(DFS_OPEN_CONTEXT))
5886 {
5887 SetFlag(Fobx->Flags, FOBX_FLAG_DFS_OPEN);
5888 }
5889 else
5890 {
5891 ClearFlag(Fobx->Flags, FOBX_FLAG_DFS_OPEN);
5892 }
5893 }
5894
5895 /* Set Cc pointers */
5896 FileObject->SectionObjectPointer = &Fcb->NonPaged->SectionObjectPointers;
5897
5898 /* Update access state */
5899 if (Stack->Parameters.Create.SecurityContext != NULL)
5900 {
5901 PACCESS_STATE AccessState;
5902
5903 AccessState = Stack->Parameters.Create.SecurityContext->AccessState;
5904 AccessState->PreviouslyGrantedAccess |= AccessState->RemainingDesiredAccess;
5905 AccessState->RemainingDesiredAccess = 0;
5906 }
5907 }
5908
5909 /*
5910 * @implemented
5911 */
5912 NTSTATUS
5913 NTAPI
5914 RxStartMinirdr(
5915 IN PRX_CONTEXT RxContext,
5916 OUT PBOOLEAN PostToFsp)
5917 {
5918 NTSTATUS Status;
5919 BOOLEAN Wait, AlreadyStarted;
5920 PRDBSS_DEVICE_OBJECT DeviceObject;
5921
5922 /* If we've not been post, then, do it */
5923 if (!BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_IN_FSP))
5924 {
5925 SECURITY_SUBJECT_CONTEXT SubjectContext;
5926
5927 SeCaptureSubjectContext(&SubjectContext);
5928 RxContext->FsdUid = RxGetUid(&SubjectContext);
5929 SeReleaseSubjectContext(&SubjectContext);
5930
5931 *PostToFsp = TRUE;
5932 return STATUS_PENDING;
5933 }
5934
5935 /* Acquire all the required locks */
5936 Wait = BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_WAIT);
5937 if (!ExAcquireResourceExclusiveLite(&RxData.Resource, Wait))
5938 {
5939 *PostToFsp = TRUE;
5940 return STATUS_PENDING;
5941 }
5942
5943 if (!RxAcquirePrefixTableLockExclusive(RxContext->RxDeviceObject->pRxNetNameTable, Wait))
5944 {
5945 ExReleaseResourceLite(&RxData.Resource);
5946 *PostToFsp = TRUE;
5947 return STATUS_PENDING;
5948 }
5949
5950 AlreadyStarted = FALSE;
5951 DeviceObject = RxContext->RxDeviceObject;
5952 _SEH2_TRY
5953 {
5954 /* MUP handle set, means already registered */
5955 if (DeviceObject->MupHandle != NULL)
5956 {
5957 AlreadyStarted = TRUE;
5958 Status = STATUS_REDIRECTOR_STARTED;
5959 _SEH2_LEAVE;
5960 }
5961
5962 /* If we're asked to register to MUP, then do it */
5963 Status = STATUS_SUCCESS;
5964 if (DeviceObject->RegisterUncProvider)
5965 {
5966 Status = FsRtlRegisterUncProvider(&DeviceObject->MupHandle,
5967 &DeviceObject->DeviceName,
5968 DeviceObject->RegisterMailSlotProvider);
5969 }
5970 if (!NT_SUCCESS(Status))
5971 {
5972 DeviceObject->MupHandle = NULL;
5973 _SEH2_LEAVE;
5974 }
5975
5976 /* Register as file system */
5977 IoRegisterFileSystem(&DeviceObject->DeviceObject);
5978 DeviceObject->RegisteredAsFileSystem = TRUE;
5979
5980 /* Inform mini-rdr it has to start */
5981 MINIRDR_CALL(Status, RxContext, DeviceObject->Dispatch, MRxStart, (RxContext, DeviceObject));
5982 if (NT_SUCCESS(Status))
5983 {
5984 ++DeviceObject->StartStopContext.Version;
5985 RxSetRdbssState(DeviceObject, RDBSS_STARTED);
5986 InterlockedExchangeAdd(&RxData.NumberOfMinirdrsStarted, 1);
5987
5988 Status = RxInitializeMRxDispatcher(DeviceObject);
5989 }
5990 }
5991 _SEH2_FINALLY
5992 {
5993 if (_SEH2_AbnormalTermination() || !NT_SUCCESS(Status))
5994 {
5995 if (!AlreadyStarted)
5996 {
5997 RxUnstart(RxContext, DeviceObject);
5998 }
5999 }
6000
6001 RxReleasePrefixTableLock(RxContext->RxDeviceObject->pRxNetNameTable);
6002 ExReleaseResourceLite(&RxData.Resource);
6003 }
6004 _SEH2_END;
6005
6006 return Status;
6007 }
6008
6009 NTSTATUS
6010 NTAPI
6011 RxStopMinirdr(
6012 IN PRX_CONTEXT RxContext,
6013 OUT PBOOLEAN PostToFsp)
6014 {
6015 UNIMPLEMENTED;
6016 return STATUS_NOT_IMPLEMENTED;
6017 }
6018
6019 NTSTATUS
6020 RxSystemControl(
6021 IN PRDBSS_DEVICE_OBJECT RxDeviceObject,
6022 IN PIRP Irp)
6023 {
6024 UNIMPLEMENTED;
6025 return STATUS_NOT_IMPLEMENTED;
6026 }
6027
6028 /*
6029 * @implemented
6030 */
6031 BOOLEAN
6032 RxTryToBecomeTheTopLevelIrp(
6033 IN OUT PRX_TOPLEVELIRP_CONTEXT TopLevelContext,
6034 IN PIRP Irp,
6035 IN PRDBSS_DEVICE_OBJECT RxDeviceObject,
6036 IN BOOLEAN ForceTopLevel
6037 )
6038 {
6039 BOOLEAN FromPool = FALSE;
6040
6041 PAGED_CODE();
6042
6043 /* If not top level, and not have to be, quit */
6044 if (IoGetTopLevelIrp() && !ForceTopLevel)
6045 {
6046 return FALSE;
6047 }
6048
6049 /* If not TLC provider, allocate one */
6050 if (TopLevelContext == NULL)
6051 {
6052 TopLevelContext = RxAllocatePoolWithTag(NonPagedPool, sizeof(RX_TOPLEVELIRP_CONTEXT), RX_TLC_POOLTAG);
6053 if (TopLevelContext == NULL)
6054 {
6055 return FALSE;
6056 }
6057
6058 FromPool = TRUE;
6059 }
6060
6061 /* Init it */
6062 __RxInitializeTopLevelIrpContext(TopLevelContext, Irp, RxDeviceObject, FromPool);
6063
6064 ASSERT(TopLevelContext->Signature == RX_TOPLEVELIRP_CONTEXT_SIGNATURE);
6065 if (FromPool)
6066 {
6067 ASSERT(BooleanFlagOn(TopLevelContext->Flags, RX_TOPLEVELCTX_FLAG_FROM_POOL));
6068 }
6069
6070 /* Make it top level IRP */
6071 IoSetTopLevelIrp((PIRP)TopLevelContext);
6072 return TRUE;
6073 }
6074
6075 /*
6076 * @implemented
6077 */
6078 VOID
6079 RxUpdateShareAccess(
6080 _Inout_ PFILE_OBJECT FileObject,
6081 _Inout_ PSHARE_ACCESS ShareAccess,
6082 _In_ PSZ where,
6083 _In_ PSZ wherelogtag)
6084 {
6085 PAGED_CODE();
6086
6087 RxDumpCurrentAccess(where, "before", wherelogtag, ShareAccess);
6088 IoUpdateShareAccess(FileObject, ShareAccess);
6089 RxDumpCurrentAccess(where, "after", wherelogtag, ShareAccess);
6090 }
6091
6092 /*
6093 * @implemented
6094 */
6095 VOID
6096 RxUninitializeCacheMap(
6097 PRX_CONTEXT RxContext,
6098 PFILE_OBJECT FileObject,
6099 PLARGE_INTEGER TruncateSize)
6100 {
6101 PFCB Fcb;
6102 NTSTATUS Status;
6103 CACHE_UNINITIALIZE_EVENT UninitEvent;
6104
6105 PAGED_CODE();
6106
6107 Fcb = FileObject->FsContext;
6108 ASSERT(NodeTypeIsFcb(Fcb));
6109 ASSERT(RxIsFcbAcquiredExclusive(Fcb));
6110
6111 KeInitializeEvent(&UninitEvent.Event, SynchronizationEvent, FALSE);
6112 CcUninitializeCacheMap(FileObject, TruncateSize, &UninitEvent);
6113
6114 /* Always release the FCB before waiting for the uninit event */
6115 RxReleaseFcb(RxContext, Fcb);
6116
6117 KeWaitForSingleObject(&UninitEvent.Event, Executive, KernelMode, FALSE, NULL);
6118
6119 /* Re-acquire it afterwards */
6120 Status = RxAcquireExclusiveFcb(RxContext, Fcb);
6121 ASSERT(NT_SUCCESS(Status));
6122 }
6123
6124 VOID
6125 NTAPI
6126 RxUnload(
6127 IN PDRIVER_OBJECT DriverObject)
6128 {
6129 UNIMPLEMENTED;
6130 }
6131
6132 VOID
6133 NTAPI
6134 RxUnlockOperation(
6135 IN PVOID Context,
6136 IN PFILE_LOCK_INFO LockInfo)
6137 {
6138 UNIMPLEMENTED;
6139 }
6140
6141 VOID
6142 RxUnstart(
6143 PRX_CONTEXT Context,
6144 PRDBSS_DEVICE_OBJECT DeviceObject)
6145 {
6146 UNIMPLEMENTED;
6147 }
6148
6149 /*
6150 * @implemented
6151 */
6152 VOID
6153 RxUnwindTopLevelIrp(
6154 IN OUT PRX_TOPLEVELIRP_CONTEXT TopLevelContext)
6155 {
6156 DPRINT("RxUnwindTopLevelIrp(%p)\n", TopLevelContext);
6157
6158 /* No TLC provided? Ask the system for ours! */
6159 if (TopLevelContext == NULL)
6160 {
6161 TopLevelContext = (PRX_TOPLEVELIRP_CONTEXT)IoGetTopLevelIrp();
6162 if (TopLevelContext == NULL)
6163 {
6164 return;
6165 }
6166
6167 /* In that case, just assert it's really ours */
6168 ASSERT(RxIsThisAnRdbssTopLevelContext(TopLevelContext));
6169 ASSERT(BooleanFlagOn(TopLevelContext->Flags, RX_TOPLEVELCTX_FLAG_FROM_POOL));
6170 }
6171
6172 ASSERT(TopLevelContext->Signature == RX_TOPLEVELIRP_CONTEXT_SIGNATURE);
6173 ASSERT(TopLevelContext->Thread == PsGetCurrentThread());
6174 /* Restore the previous top level IRP */
6175 IoSetTopLevelIrp(TopLevelContext->Previous);
6176 /* If TLC was allocated from pool, remove it from list and release it */
6177 if (BooleanFlagOn(TopLevelContext->Flags, RX_TOPLEVELCTX_FLAG_FROM_POOL))
6178 {
6179 RxRemoveFromTopLevelIrpAllocatedContextsList(TopLevelContext);
6180 RxFreePoolWithTag(TopLevelContext, RX_TLC_POOLTAG);
6181 }
6182 }
6183
6184 /*
6185 * @implemented
6186 */
6187 VOID
6188 RxUpdateShareAccessPerSrvOpens(
6189 IN PSRV_OPEN SrvOpen)
6190 {
6191 ACCESS_MASK DesiredAccess;
6192 BOOLEAN ReadAccess;
6193 BOOLEAN WriteAccess;
6194 BOOLEAN DeleteAccess;
6195
6196 PAGED_CODE();
6197
6198 /* If already updated, no need to continue */
6199 if (BooleanFlagOn(SrvOpen->Flags, SRVOPEN_FLAG_SHAREACCESS_UPDATED))
6200 {
6201 return;
6202 }
6203
6204 /* Check if any access wanted */
6205 DesiredAccess = SrvOpen->DesiredAccess;
6206 ReadAccess = (DesiredAccess & (FILE_READ_DATA | FILE_EXECUTE)) != 0;
6207 WriteAccess = (DesiredAccess & (FILE_WRITE_DATA | FILE_APPEND_DATA)) != 0;
6208 DeleteAccess = (DesiredAccess & DELETE) != 0;
6209
6210 /* In that case, update it */
6211 if ((ReadAccess) || (WriteAccess) || (DeleteAccess))
6212 {
6213 BOOLEAN SharedRead;
6214 BOOLEAN SharedWrite;
6215 BOOLEAN SharedDelete;
6216 ULONG DesiredShareAccess;
6217 PSHARE_ACCESS ShareAccess;
6218
6219 ShareAccess = &((PFCB)SrvOpen->pFcb)->ShareAccessPerSrvOpens;
6220 DesiredShareAccess = SrvOpen->ShareAccess;
6221
6222 SharedRead = (DesiredShareAccess & FILE_SHARE_READ) != 0;
6223 SharedWrite = (DesiredShareAccess & FILE_SHARE_WRITE) != 0;
6224 SharedDelete = (DesiredShareAccess & FILE_SHARE_DELETE) != 0;
6225
6226 ShareAccess->OpenCount++;
6227
6228 ShareAccess->Readers += ReadAccess;
6229 ShareAccess->Writers += WriteAccess;
6230 ShareAccess->Deleters += DeleteAccess;
6231 ShareAccess->SharedRead += SharedRead;
6232 ShareAccess->SharedWrite += SharedWrite;
6233 ShareAccess->SharedDelete += SharedDelete;
6234 }
6235
6236 SetFlag(SrvOpen->Flags, SRVOPEN_FLAG_SHAREACCESS_UPDATED);
6237 }
6238
6239 /*
6240 * @implemented
6241 */
6242 NTSTATUS
6243 RxXXXControlFileCallthru(
6244 PRX_CONTEXT Context)
6245 {
6246 NTSTATUS Status;
6247
6248 PAGED_CODE();
6249
6250 DPRINT("RxXXXControlFileCallthru(%p)\n", Context);
6251
6252 /* No dispatch table? Nothing to dispatch */
6253 if (Context->RxDeviceObject->Dispatch == NULL)
6254 {
6255 Context->pFobx = NULL;
6256 return STATUS_INVALID_DEVICE_REQUEST;
6257 }
6258
6259 /* Init the lowio context */
6260 Status = RxLowIoPopulateFsctlInfo(Context);
6261 if (!NT_SUCCESS(Status))
6262 {
6263 return Status;
6264 }
6265
6266 /* Check whether we're consistent: a length means a buffer */
6267 if ((Context->LowIoContext.ParamsFor.FsCtl.InputBufferLength > 0 && Context->LowIoContext.ParamsFor.FsCtl.pInputBuffer == NULL) ||
6268 (Context->LowIoContext.ParamsFor.FsCtl.OutputBufferLength > 0 && Context->LowIoContext.ParamsFor.FsCtl.pOutputBuffer == NULL))
6269 {
6270 return STATUS_INVALID_PARAMETER;
6271 }
6272
6273 /* Forward the call to the mini-rdr */
6274 DPRINT("Calling: %p\n", Context->RxDeviceObject->Dispatch->MRxDevFcbXXXControlFile);
6275 Status = Context->RxDeviceObject->Dispatch->MRxDevFcbXXXControlFile(Context);
6276 if (Status != STATUS_PENDING)
6277 {
6278 Context->CurrentIrp->IoStatus.Information = Context->InformationToReturn;
6279 }
6280
6281 DPRINT("RxXXXControlFileCallthru: %x, %ld\n", Context->CurrentIrp->IoStatus.Status, Context->CurrentIrp->IoStatus.Information);
6282 return Status;
6283 }