2672d5fb0c0c71d4967fa466fa166726166f1fb2
[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 #include <copysup.h>
34
35 #define NDEBUG
36 #include <debug.h>
37
38 #define RX_TOPLEVELCTX_FLAG_FROM_POOL 1
39
40 typedef
41 NTSTATUS
42 (NTAPI *PRX_FSD_DISPATCH) (
43 PRX_CONTEXT Context);
44
45 typedef struct _RX_FSD_DISPATCH_VECTOR
46 {
47 PRX_FSD_DISPATCH CommonRoutine;
48 } RX_FSD_DISPATCH_VECTOR, *PRX_FSD_DISPATCH_VECTOR;
49
50 VOID
51 NTAPI
52 RxAcquireFileForNtCreateSection(
53 PFILE_OBJECT FileObject);
54
55 NTSTATUS
56 NTAPI
57 RxAcquireForCcFlush(
58 PFILE_OBJECT FileObject,
59 PDEVICE_OBJECT DeviceObject);
60
61 VOID
62 RxAddToTopLevelIrpAllocatedContextsList(
63 PRX_TOPLEVELIRP_CONTEXT TopLevelContext);
64
65 VOID
66 RxAssert(
67 PVOID Assert,
68 PVOID File,
69 ULONG Line,
70 PVOID Message);
71
72 NTSTATUS
73 NTAPI
74 RxCommonCleanup(
75 PRX_CONTEXT Context);
76
77 NTSTATUS
78 NTAPI
79 RxCommonClose(
80 PRX_CONTEXT Context);
81
82 NTSTATUS
83 NTAPI
84 RxCommonCreate(
85 PRX_CONTEXT Context);
86
87 NTSTATUS
88 NTAPI
89 RxCommonDevFCBCleanup(
90 PRX_CONTEXT Context);
91
92 NTSTATUS
93 NTAPI
94 RxCommonDevFCBClose(
95 PRX_CONTEXT Context);
96
97 NTSTATUS
98 NTAPI
99 RxCommonDevFCBFsCtl(
100 PRX_CONTEXT Context);
101
102 NTSTATUS
103 NTAPI
104 RxCommonDevFCBIoCtl(
105 PRX_CONTEXT Context);
106
107 NTSTATUS
108 NTAPI
109 RxCommonDevFCBQueryVolInfo(
110 PRX_CONTEXT Context);
111
112 NTSTATUS
113 NTAPI
114 RxCommonDeviceControl(
115 PRX_CONTEXT Context);
116
117 NTSTATUS
118 NTAPI
119 RxCommonDirectoryControl(
120 PRX_CONTEXT Context);
121
122 NTSTATUS
123 NTAPI
124 RxCommonDispatchProblem(
125 PRX_CONTEXT Context);
126
127 NTSTATUS
128 NTAPI
129 RxCommonFileSystemControl(
130 PRX_CONTEXT Context);
131
132 NTSTATUS
133 NTAPI
134 RxCommonFlushBuffers(
135 PRX_CONTEXT Context);
136
137 NTSTATUS
138 NTAPI
139 RxCommonLockControl(
140 PRX_CONTEXT Context);
141
142 NTSTATUS
143 NTAPI
144 RxCommonQueryEa(
145 PRX_CONTEXT Context);
146
147 NTSTATUS
148 NTAPI
149 RxCommonQueryInformation(
150 PRX_CONTEXT Context);
151
152 NTSTATUS
153 NTAPI
154 RxCommonQueryQuotaInformation(
155 PRX_CONTEXT Context);
156
157 NTSTATUS
158 NTAPI
159 RxCommonQuerySecurity(
160 PRX_CONTEXT Context);
161
162 NTSTATUS
163 NTAPI
164 RxCommonQueryVolumeInformation(
165 PRX_CONTEXT Context);
166
167 NTSTATUS
168 NTAPI
169 RxCommonRead(
170 PRX_CONTEXT Context);
171
172 NTSTATUS
173 NTAPI
174 RxCommonSetEa(
175 PRX_CONTEXT Context);
176
177 NTSTATUS
178 NTAPI
179 RxCommonSetInformation(
180 PRX_CONTEXT Context);
181
182 NTSTATUS
183 NTAPI
184 RxCommonSetQuotaInformation(
185 PRX_CONTEXT Context);
186
187 NTSTATUS
188 NTAPI
189 RxCommonSetSecurity(
190 PRX_CONTEXT Context);
191
192 NTSTATUS
193 NTAPI
194 RxCommonSetVolumeInformation(
195 PRX_CONTEXT Context);
196
197 NTSTATUS
198 NTAPI
199 RxCommonUnimplemented(
200 PRX_CONTEXT Context);
201
202 NTSTATUS
203 NTAPI
204 RxCommonWrite(
205 PRX_CONTEXT Context);
206
207 VOID
208 RxCopyCreateParameters(
209 IN PRX_CONTEXT RxContext);
210
211 NTSTATUS
212 RxCreateFromNetRoot(
213 PRX_CONTEXT Context,
214 PUNICODE_STRING NetRootName);
215
216 NTSTATUS
217 RxCreateTreeConnect(
218 IN PRX_CONTEXT RxContext);
219
220 BOOLEAN
221 NTAPI
222 RxFastIoCheckIfPossible(
223 PFILE_OBJECT FileObject,
224 PLARGE_INTEGER FileOffset,
225 ULONG Length, BOOLEAN Wait,
226 ULONG LockKey, BOOLEAN CheckForReadOperation,
227 PIO_STATUS_BLOCK IoStatus,
228 PDEVICE_OBJECT DeviceObject);
229
230 BOOLEAN
231 NTAPI
232 RxFastIoDeviceControl(
233 PFILE_OBJECT FileObject,
234 BOOLEAN Wait,
235 PVOID InputBuffer OPTIONAL,
236 ULONG InputBufferLength,
237 PVOID OutputBuffer OPTIONAL,
238 ULONG OutputBufferLength,
239 ULONG IoControlCode,
240 PIO_STATUS_BLOCK IoStatus,
241 PDEVICE_OBJECT DeviceObject);
242
243 BOOLEAN
244 NTAPI
245 RxFastIoRead(
246 PFILE_OBJECT FileObject,
247 PLARGE_INTEGER FileOffset,
248 ULONG Length,
249 BOOLEAN Wait,
250 ULONG LockKey,
251 PVOID Buffer,
252 PIO_STATUS_BLOCK IoStatus,
253 PDEVICE_OBJECT DeviceObject);
254
255 BOOLEAN
256 NTAPI
257 RxFastIoWrite(
258 PFILE_OBJECT FileObject,
259 PLARGE_INTEGER FileOffset,
260 ULONG Length,
261 BOOLEAN Wait,
262 ULONG LockKey,
263 PVOID Buffer,
264 PIO_STATUS_BLOCK IoStatus,
265 PDEVICE_OBJECT DeviceObject);
266
267 NTSTATUS
268 RxFindOrCreateFcb(
269 PRX_CONTEXT RxContext,
270 PUNICODE_STRING NetRootName);
271
272 NTSTATUS
273 RxFirstCanonicalize(
274 PRX_CONTEXT RxContext,
275 PUNICODE_STRING FileName,
276 PUNICODE_STRING CanonicalName,
277 PNET_ROOT_TYPE NetRootType);
278
279 VOID
280 RxFreeCanonicalNameBuffer(
281 PRX_CONTEXT Context);
282
283 VOID
284 NTAPI
285 RxFspDispatch(
286 IN PVOID Context);
287
288 VOID
289 NTAPI
290 RxGetRegistryParameters(
291 IN PUNICODE_STRING RegistryPath);
292
293 NTSTATUS
294 NTAPI
295 RxGetStringRegistryParameter(
296 IN HANDLE KeyHandle,
297 IN PCWSTR KeyName,
298 OUT PUNICODE_STRING OutString,
299 IN PUCHAR Buffer,
300 IN ULONG BufferLength,
301 IN BOOLEAN LogFailure);
302
303 VOID
304 NTAPI
305 RxInitializeDebugSupport(
306 VOID);
307
308 VOID
309 NTAPI
310 RxInitializeDispatchVectors(
311 PDRIVER_OBJECT DriverObject);
312
313 NTSTATUS
314 NTAPI
315 RxInitializeRegistrationStructures(
316 VOID);
317
318 VOID
319 NTAPI
320 RxInitializeTopLevelIrpPackage(
321 VOID);
322
323 VOID
324 NTAPI
325 RxInitUnwind(
326 PDRIVER_OBJECT DriverObject,
327 USHORT State);
328
329 BOOLEAN
330 RxIsThisAnRdbssTopLevelContext(
331 PRX_TOPLEVELIRP_CONTEXT TopLevelContext);
332
333 NTSTATUS
334 NTAPI
335 RxLowIoIoCtlShellCompletion(
336 PRX_CONTEXT RxContext);
337
338 NTSTATUS
339 RxLowIoReadShell(
340 PRX_CONTEXT RxContext);
341
342 NTSTATUS
343 NTAPI
344 RxLowIoReadShellCompletion(
345 PRX_CONTEXT RxContext);
346
347 PVOID
348 RxNewMapUserBuffer(
349 PRX_CONTEXT RxContext);
350
351 NTSTATUS
352 RxNotifyChangeDirectory(
353 PRX_CONTEXT RxContext);
354
355 NTSTATUS
356 RxpQueryInfoMiniRdr(
357 PRX_CONTEXT RxContext,
358 FILE_INFORMATION_CLASS FileInfoClass,
359 PVOID Buffer);
360
361 VOID
362 RxPurgeNetFcb(
363 PFCB Fcb,
364 PRX_CONTEXT LocalContext);
365
366 NTSTATUS
367 RxQueryAlternateNameInfo(
368 PRX_CONTEXT RxContext,
369 PFILE_NAME_INFORMATION AltNameInfo);
370
371 NTSTATUS
372 RxQueryBasicInfo(
373 PRX_CONTEXT RxContext,
374 PFILE_BASIC_INFORMATION BasicInfo);
375
376 NTSTATUS
377 RxQueryCompressedInfo(
378 PRX_CONTEXT RxContext,
379 PFILE_COMPRESSION_INFORMATION CompressionInfo);
380
381 NTSTATUS
382 RxQueryDirectory(
383 PRX_CONTEXT RxContext);
384
385 NTSTATUS
386 RxQueryEaInfo(
387 PRX_CONTEXT RxContext,
388 PFILE_EA_INFORMATION EaInfo);
389
390 NTSTATUS
391 RxQueryInternalInfo(
392 PRX_CONTEXT RxContext,
393 PFILE_INTERNAL_INFORMATION InternalInfo);
394
395 NTSTATUS
396 RxQueryNameInfo(
397 PRX_CONTEXT RxContext,
398 PFILE_NAME_INFORMATION NameInfo);
399
400 NTSTATUS
401 RxQueryPipeInfo(
402 PRX_CONTEXT RxContext,
403 PFILE_PIPE_INFORMATION PipeInfo);
404
405 NTSTATUS
406 RxQueryPositionInfo(
407 PRX_CONTEXT RxContext,
408 PFILE_POSITION_INFORMATION PositionInfo);
409
410 NTSTATUS
411 RxQueryStandardInfo(
412 PRX_CONTEXT RxContext,
413 PFILE_STANDARD_INFORMATION StandardInfo);
414
415 VOID
416 NTAPI
417 RxReadRegistryParameters(
418 VOID);
419
420 VOID
421 NTAPI
422 RxReleaseFileForNtCreateSection(
423 PFILE_OBJECT FileObject);
424
425 NTSTATUS
426 NTAPI
427 RxReleaseForCcFlush(
428 PFILE_OBJECT FileObject,
429 PDEVICE_OBJECT DeviceObject);
430
431 PRX_CONTEXT
432 RxRemoveOverflowEntry(
433 PRDBSS_DEVICE_OBJECT DeviceObject,
434 WORK_QUEUE_TYPE Queue);
435
436 NTSTATUS
437 RxSearchForCollapsibleOpen(
438 PRX_CONTEXT RxContext,
439 ACCESS_MASK DesiredAccess,
440 ULONG ShareAccess);
441
442 VOID
443 RxSetupNetFileObject(
444 PRX_CONTEXT RxContext);
445
446 NTSTATUS
447 RxSystemControl(
448 IN PRDBSS_DEVICE_OBJECT RxDeviceObject,
449 IN PIRP Irp);
450
451 VOID
452 RxUninitializeCacheMap(
453 PRX_CONTEXT RxContext,
454 PFILE_OBJECT FileObject,
455 PLARGE_INTEGER TruncateSize);
456
457 VOID
458 RxUnstart(
459 PRX_CONTEXT Context,
460 PRDBSS_DEVICE_OBJECT DeviceObject);
461
462 NTSTATUS
463 RxXXXControlFileCallthru(
464 PRX_CONTEXT Context);
465
466 PVOID
467 NTAPI
468 _RxAllocatePoolWithTag(
469 _In_ POOL_TYPE PoolType,
470 _In_ SIZE_T NumberOfBytes,
471 _In_ ULONG Tag);
472
473 VOID
474 NTAPI
475 _RxFreePool(
476 _In_ PVOID Buffer);
477
478 VOID
479 NTAPI
480 _RxFreePoolWithTag(
481 _In_ PVOID Buffer,
482 _In_ ULONG Tag);
483
484 WCHAR RxStarForTemplate = '*';
485 WCHAR Rx8QMdot3QM[] = L">>>>>>>>.>>>*";
486 BOOLEAN DisableByteRangeLockingOnReadOnlyFiles = FALSE;
487 BOOLEAN DisableFlushOnCleanup = FALSE;
488 ULONG ReadAheadGranularity = 1 << PAGE_SHIFT;
489 LIST_ENTRY RxActiveContexts;
490 NPAGED_LOOKASIDE_LIST RxContextLookasideList;
491 FAST_MUTEX RxContextPerFileSerializationMutex;
492 RDBSS_DATA RxData;
493 FCB RxDeviceFCB;
494 BOOLEAN RxLoudLowIoOpsEnabled = FALSE;
495 RX_FSD_DISPATCH_VECTOR RxDeviceFCBVector[IRP_MJ_MAXIMUM_FUNCTION + 1] =
496 {
497 { RxCommonDispatchProblem },
498 { RxCommonDispatchProblem },
499 { RxCommonDevFCBClose },
500 { RxCommonDispatchProblem },
501 { RxCommonDispatchProblem },
502 { RxCommonDispatchProblem },
503 { RxCommonDispatchProblem },
504 { RxCommonDispatchProblem },
505 { RxCommonDispatchProblem },
506 { RxCommonDispatchProblem },
507 { RxCommonDevFCBQueryVolInfo },
508 { RxCommonDispatchProblem },
509 { RxCommonDispatchProblem },
510 { RxCommonDevFCBFsCtl },
511 { RxCommonDevFCBIoCtl },
512 { RxCommonDevFCBIoCtl },
513 { RxCommonDispatchProblem },
514 { RxCommonDispatchProblem },
515 { RxCommonDevFCBCleanup },
516 { RxCommonDispatchProblem },
517 { RxCommonDispatchProblem },
518 { RxCommonDispatchProblem },
519 { RxCommonUnimplemented },
520 { RxCommonUnimplemented },
521 { RxCommonUnimplemented },
522 { RxCommonUnimplemented },
523 { RxCommonUnimplemented },
524 { RxCommonUnimplemented },
525 };
526 RDBSS_EXPORTS RxExports;
527 FAST_IO_DISPATCH RxFastIoDispatch;
528 PRDBSS_DEVICE_OBJECT RxFileSystemDeviceObject;
529 RX_FSD_DISPATCH_VECTOR RxFsdDispatchVector[IRP_MJ_MAXIMUM_FUNCTION + 1] =
530 {
531 { RxCommonCreate },
532 { RxCommonUnimplemented },
533 { RxCommonClose },
534 { RxCommonRead },
535 { RxCommonWrite },
536 { RxCommonQueryInformation },
537 { RxCommonSetInformation },
538 { RxCommonQueryEa },
539 { RxCommonSetEa },
540 { RxCommonFlushBuffers },
541 { RxCommonQueryVolumeInformation },
542 { RxCommonSetVolumeInformation },
543 { RxCommonDirectoryControl },
544 { RxCommonFileSystemControl },
545 { RxCommonDeviceControl },
546 { RxCommonDeviceControl },
547 { RxCommonUnimplemented },
548 { RxCommonLockControl },
549 { RxCommonCleanup },
550 { RxCommonUnimplemented },
551 { RxCommonQuerySecurity },
552 { RxCommonSetSecurity },
553 { RxCommonUnimplemented },
554 { RxCommonUnimplemented },
555 { RxCommonUnimplemented },
556 { RxCommonQueryQuotaInformation },
557 { RxCommonSetQuotaInformation },
558 { RxCommonUnimplemented },
559 };
560 ULONG RxFsdEntryCount;
561 LIST_ENTRY RxIrpsList;
562 KSPIN_LOCK RxIrpsListSpinLock;
563 KMUTEX RxScavengerMutex;
564 KMUTEX RxSerializationMutex;
565 UCHAR RxSpaceForTheWrappersDeviceObject[sizeof(*RxFileSystemDeviceObject)];
566 KSPIN_LOCK TopLevelIrpSpinLock;
567 LIST_ENTRY TopLevelIrpAllocatedContextsList;
568 BOOLEAN RxForceQFIPassThrough = FALSE;
569
570 DECLARE_CONST_UNICODE_STRING(unknownId, L"???");
571
572 #if RDBSS_ASSERTS
573 #ifdef ASSERT
574 #undef ASSERT
575 #endif
576
577 #define ASSERT(exp) \
578 if (!(exp)) \
579 { \
580 RxAssert(#exp, __FILE__, __LINE__, NULL); \
581 }
582 #endif
583
584 #if RX_POOL_WRAPPER
585 #undef RxAllocatePool
586 #undef RxAllocatePoolWithTag
587 #undef RxFreePool
588
589 #define RxAllocatePool(P, S) _RxAllocatePoolWithTag(P, S, 0)
590 #define RxAllocatePoolWithTag _RxAllocatePoolWithTag
591 #define RxFreePool _RxFreePool
592 #define RxFreePoolWithTag _RxFreePoolWithTag
593 #endif
594
595 /* FUNCTIONS ****************************************************************/
596
597 /*
598 * @implemented
599 */
600 VOID
601 CheckForLoudOperations(
602 PRX_CONTEXT RxContext)
603 {
604 PAGED_CODE();
605
606 #define ALLSCR_LENGTH (sizeof(L"all.scr") - sizeof(UNICODE_NULL))
607
608 /* Are loud operations enabled? */
609 if (RxLoudLowIoOpsEnabled)
610 {
611 PFCB Fcb;
612
613 /* If so, the operation will be loud only if filename ends with all.scr */
614 Fcb = (PFCB)RxContext->pFcb;
615 if (RtlCompareMemory(Add2Ptr(Fcb->PrivateAlreadyPrefixedName.Buffer, (Fcb->PrivateAlreadyPrefixedName.Length - ALLSCR_LENGTH)),
616 L"all.scr", ALLSCR_LENGTH) == ALLSCR_LENGTH)
617 {
618 SetFlag(RxContext->LowIoContext.Flags, LOWIO_CONTEXT_FLAG_LOUDOPS);
619 }
620 }
621 #undef ALLSCR_LENGTH
622 }
623
624 /*
625 * @implemented
626 */
627 VOID
628 __RxInitializeTopLevelIrpContext(
629 IN OUT PRX_TOPLEVELIRP_CONTEXT TopLevelContext,
630 IN PIRP Irp,
631 IN PRDBSS_DEVICE_OBJECT RxDeviceObject,
632 IN ULONG Flags)
633 {
634 DPRINT("__RxInitializeTopLevelIrpContext(%p, %p, %p, %u)\n", TopLevelContext, Irp, RxDeviceObject, Flags);
635
636 RtlZeroMemory(TopLevelContext, sizeof(RX_TOPLEVELIRP_CONTEXT));
637 TopLevelContext->Irp = Irp;
638 TopLevelContext->Flags = (Flags ? RX_TOPLEVELCTX_FLAG_FROM_POOL : 0);
639 TopLevelContext->Signature = RX_TOPLEVELIRP_CONTEXT_SIGNATURE;
640 TopLevelContext->RxDeviceObject = RxDeviceObject;
641 TopLevelContext->Previous = IoGetTopLevelIrp();
642 TopLevelContext->Thread = PsGetCurrentThread();
643
644 /* We cannot add to list something that'd come from stack */
645 if (BooleanFlagOn(TopLevelContext->Flags, RX_TOPLEVELCTX_FLAG_FROM_POOL))
646 {
647 RxAddToTopLevelIrpAllocatedContextsList(TopLevelContext);
648 }
649 }
650
651 NTSTATUS
652 NTAPI
653 RxAcquireExclusiveFcbResourceInMRx(
654 _Inout_ PMRX_FCB Fcb)
655 {
656 UNIMPLEMENTED;
657 return STATUS_NOT_IMPLEMENTED;
658 }
659
660 BOOLEAN
661 NTAPI
662 RxAcquireFcbForLazyWrite(
663 PVOID Context,
664 BOOLEAN Wait)
665 {
666 UNIMPLEMENTED;
667 return FALSE;
668 }
669
670 BOOLEAN
671 NTAPI
672 RxAcquireFcbForReadAhead(
673 PVOID Context,
674 BOOLEAN Wait)
675 {
676 UNIMPLEMENTED;
677 return FALSE;
678 }
679
680 VOID
681 NTAPI
682 RxAcquireFileForNtCreateSection(
683 PFILE_OBJECT FileObject)
684 {
685 UNIMPLEMENTED;
686 }
687
688 NTSTATUS
689 NTAPI
690 RxAcquireForCcFlush(
691 PFILE_OBJECT FileObject,
692 PDEVICE_OBJECT DeviceObject)
693 {
694 UNIMPLEMENTED;
695 return STATUS_NOT_IMPLEMENTED;
696 }
697
698 /*
699 * @implemented
700 */
701 VOID
702 RxAddToTopLevelIrpAllocatedContextsList(
703 PRX_TOPLEVELIRP_CONTEXT TopLevelContext)
704 {
705 KIRQL OldIrql;
706
707 DPRINT("RxAddToTopLevelIrpAllocatedContextsList(%p)\n", TopLevelContext);
708
709 ASSERT(TopLevelContext->Signature == RX_TOPLEVELIRP_CONTEXT_SIGNATURE);
710 ASSERT(BooleanFlagOn(TopLevelContext->Flags, RX_TOPLEVELCTX_FLAG_FROM_POOL));
711
712 KeAcquireSpinLock(&TopLevelIrpSpinLock, &OldIrql);
713 InsertTailList(&TopLevelIrpAllocatedContextsList, &TopLevelContext->ListEntry);
714 KeReleaseSpinLock(&TopLevelIrpSpinLock, OldIrql);
715 }
716
717 /*
718 * @implemented
719 */
720 VOID
721 RxAddToWorkque(
722 IN PRX_CONTEXT RxContext,
723 IN PIRP Irp)
724 {
725 ULONG Queued;
726 KIRQL OldIrql;
727 WORK_QUEUE_TYPE Queue;
728 PIO_STACK_LOCATION Stack;
729
730 Stack = RxContext->CurrentIrpSp;
731 RxContext->PostRequest = FALSE;
732
733 /* First of all, select the appropriate queue - delayed for prefix claim, critical for the rest */
734 if (RxContext->MajorFunction == IRP_MJ_DEVICE_CONTROL &&
735 Stack->Parameters.DeviceIoControl.IoControlCode == IOCTL_REDIR_QUERY_PATH)
736 {
737 Queue = DelayedWorkQueue;
738 SetFlag(RxContext->Flags, RX_CONTEXT_FLAG_FSP_DELAYED_OVERFLOW_QUEUE);
739 }
740 else
741 {
742 Queue = CriticalWorkQueue;
743 SetFlag(RxContext->Flags, RX_CONTEXT_FLAG_FSP_CRITICAL_OVERFLOW_QUEUE);
744 }
745
746 /* Check for overflow */
747 if (Stack->FileObject != NULL)
748 {
749 KeAcquireSpinLock(&RxFileSystemDeviceObject->OverflowQueueSpinLock, &OldIrql);
750
751 Queued = InterlockedIncrement(&RxFileSystemDeviceObject->PostedRequestCount[Queue]);
752 /* In case of an overflow, add the new queued call to the overflow list */
753 if (Queued > 1)
754 {
755 InterlockedDecrement(&RxFileSystemDeviceObject->PostedRequestCount[Queue]);
756 InsertTailList(&RxFileSystemDeviceObject->OverflowQueue[Queue], &RxContext->OverflowListEntry);
757 ++RxFileSystemDeviceObject->OverflowQueueCount[Queue];
758
759 KeReleaseSpinLock(&RxFileSystemDeviceObject->OverflowQueueSpinLock, OldIrql);
760 return;
761 }
762
763 KeReleaseSpinLock(&RxFileSystemDeviceObject->OverflowQueueSpinLock, OldIrql);
764 }
765
766 ExInitializeWorkItem(&RxContext->WorkQueueItem, RxFspDispatch, RxContext);
767 ExQueueWorkItem((PWORK_QUEUE_ITEM)&RxContext->WorkQueueItem, Queue);
768 }
769
770 /*
771 * @implemented
772 */
773 VOID
774 RxAdjustFileTimesAndSize(
775 PRX_CONTEXT Context)
776 {
777 PFCB Fcb;
778 PFOBX Fobx;
779 NTSTATUS Status;
780 PFILE_OBJECT FileObject;
781 LARGE_INTEGER CurrentTime;
782 FILE_BASIC_INFORMATION FileBasicInfo;
783 FILE_END_OF_FILE_INFORMATION FileEOFInfo;
784 BOOLEAN FileModified, SetLastChange, SetLastAccess, SetLastWrite, NeedUpdate;
785
786 PAGED_CODE();
787
788 FileObject = Context->CurrentIrpSp->FileObject;
789 /* If Cc isn't initialized, the file was not read nor written, nothing to do */
790 if (FileObject->PrivateCacheMap == NULL)
791 {
792 return;
793 }
794
795 /* Get now */
796 KeQuerySystemTime(&CurrentTime);
797
798 Fobx = (PFOBX)Context->pFobx;
799 /* Was the file modified? */
800 FileModified = BooleanFlagOn(FileObject->Flags, FO_FILE_MODIFIED);
801 /* We'll set last write if it was modified and user didn't update yet */
802 SetLastWrite = FileModified && !BooleanFlagOn(Fobx->Flags, FOBX_FLAG_USER_SET_LAST_WRITE);
803 /* File was accessed if: written or read (fastio), we'll update last access if user didn't */
804 SetLastAccess = SetLastWrite ||
805 (BooleanFlagOn(FileObject->Flags, FO_FILE_FAST_IO_READ) &&
806 !BooleanFlagOn(Fobx->Flags, FOBX_FLAG_USER_SET_LAST_ACCESS));
807 /* We'll set last change if it was modified and user didn't update yet */
808 SetLastChange = FileModified && !BooleanFlagOn(Fobx->Flags, FOBX_FLAG_USER_SET_LAST_CHANGE);
809
810 /* Nothing to update? Job done */
811 if (!FileModified && !SetLastWrite && !SetLastAccess && !SetLastChange)
812 {
813 return;
814 }
815
816 Fcb = (PFCB)Context->pFcb;
817 /* By default, we won't issue any MRxSetFileInfoAtCleanup call */
818 NeedUpdate = FALSE;
819 RtlZeroMemory(&FileBasicInfo, sizeof(FileBasicInfo));
820
821 /* Update lastwrite time if required */
822 if (SetLastWrite)
823 {
824 NeedUpdate = TRUE;
825 Fcb->LastWriteTime.QuadPart = CurrentTime.QuadPart;
826 FileBasicInfo.LastWriteTime.QuadPart = CurrentTime.QuadPart;
827 }
828
829 /* Update lastaccess time if required */
830 if (SetLastAccess)
831 {
832 NeedUpdate = TRUE;
833 Fcb->LastAccessTime.QuadPart = CurrentTime.QuadPart;
834 FileBasicInfo.LastAccessTime.QuadPart = CurrentTime.QuadPart;
835 }
836
837 /* Update lastchange time if required */
838 if (SetLastChange)
839 {
840 NeedUpdate = TRUE;
841 Fcb->LastChangeTime.QuadPart = CurrentTime.QuadPart;
842 FileBasicInfo.ChangeTime.QuadPart = CurrentTime.QuadPart;
843 }
844
845 /* If one of the date was modified, issue a call to mini-rdr */
846 if (NeedUpdate)
847 {
848 Context->Info.FileInformationClass = FileBasicInformation;
849 Context->Info.Buffer = &FileBasicInfo;
850 Context->Info.Length = sizeof(FileBasicInfo);
851
852 MINIRDR_CALL(Status, Context, Fcb->MRxDispatch, MRxSetFileInfoAtCleanup, (Context));
853 (void)Status;
854 }
855
856 /* If the file was modified, update its EOF */
857 if (FileModified)
858 {
859 FileEOFInfo.EndOfFile.QuadPart = Fcb->Header.FileSize.QuadPart;
860
861 Context->Info.FileInformationClass = FileEndOfFileInformation;
862 Context->Info.Buffer = &FileEOFInfo;
863 Context->Info.Length = sizeof(FileEOFInfo);
864
865 MINIRDR_CALL(Status, Context, Fcb->MRxDispatch, MRxSetFileInfoAtCleanup, (Context));
866 (void)Status;
867 }
868 }
869
870 /*
871 * @implemented
872 */
873 NTSTATUS
874 RxAllocateCanonicalNameBuffer(
875 PRX_CONTEXT RxContext,
876 PUNICODE_STRING CanonicalName,
877 USHORT CanonicalLength)
878 {
879 PAGED_CODE();
880
881 DPRINT("RxContext: %p - CanonicalNameBuffer: %p\n", RxContext, RxContext->Create.CanonicalNameBuffer);
882
883 /* Context must be free of any already allocated name */
884 ASSERT(RxContext->Create.CanonicalNameBuffer == NULL);
885
886 /* Validate string length */
887 if (CanonicalLength > USHRT_MAX - 1)
888 {
889 CanonicalName->Buffer = NULL;
890 return STATUS_OBJECT_PATH_INVALID;
891 }
892
893 CanonicalName->Buffer = RxAllocatePoolWithTag(PagedPool | POOL_COLD_ALLOCATION, CanonicalLength, RX_MISC_POOLTAG);
894 if (CanonicalName->Buffer == NULL)
895 {
896 return STATUS_INSUFFICIENT_RESOURCES;
897 }
898
899 CanonicalName->Length = 0;
900 CanonicalName->MaximumLength = CanonicalLength;
901
902 /* Set the two places - they must always be identical */
903 RxContext->Create.CanonicalNameBuffer = CanonicalName->Buffer;
904 RxContext->AlsoCanonicalNameBuffer = CanonicalName->Buffer;
905
906 return STATUS_SUCCESS;
907 }
908
909 /*
910 * @implemented
911 */
912 VOID
913 RxCancelNotifyChangeDirectoryRequestsForFobx(
914 PFOBX Fobx)
915 {
916 KIRQL OldIrql;
917 PLIST_ENTRY Entry;
918 PRX_CONTEXT Context;
919 LIST_ENTRY ContextsToCancel;
920
921 /* Init a list for the contexts to cancel */
922 InitializeListHead(&ContextsToCancel);
923
924 /* Lock our list lock */
925 KeAcquireSpinLock(&RxStrucSupSpinLock, &OldIrql);
926
927 /* Now, browse all the active contexts, to find the associated ones */
928 Entry = RxActiveContexts.Flink;
929 while (Entry != &RxActiveContexts)
930 {
931 Context = CONTAINING_RECORD(Entry, RX_CONTEXT, ContextListEntry);
932 Entry = Entry->Flink;
933
934 /* Not the IRP we're looking for, ignore */
935 if (Context->MajorFunction != IRP_MJ_DIRECTORY_CONTROL ||
936 Context->MinorFunction != IRP_MN_NOTIFY_CHANGE_DIRECTORY)
937 {
938 continue;
939 }
940
941 /* Not the FOBX we're looking for, ignore */
942 if ((PFOBX)Context->pFobx != Fobx)
943 {
944 continue;
945 }
946
947 /* No cancel routine (can't be cancel, then), ignore */
948 if (Context->MRxCancelRoutine == NULL)
949 {
950 continue;
951 }
952
953 /* Mark our context as cancelled */
954 SetFlag(Context->Flags, RX_CONTEXT_FLAG_CANCELLED);
955
956 /* Move it to our list */
957 RemoveEntryList(&Context->ContextListEntry);
958 InsertTailList(&ContextsToCancel, &Context->ContextListEntry);
959
960 InterlockedIncrement((volatile long *)&Context->ReferenceCount);
961 }
962
963 /* Done with the contexts */
964 KeReleaseSpinLock(&RxStrucSupSpinLock, OldIrql);
965
966 /* Now, handle all our "extracted" contexts */
967 while (!IsListEmpty(&ContextsToCancel))
968 {
969 Entry = RemoveHeadList(&ContextsToCancel);
970 Context = CONTAINING_RECORD(Entry, RX_CONTEXT, ContextListEntry);
971
972 /* If they had an associated IRP (should be always true) */
973 if (Context->CurrentIrp != NULL)
974 {
975 /* Then, call cancel routine */
976 ASSERT(Context->MRxCancelRoutine != NULL);
977 DPRINT1("Canceling %p with %p\n", Context, Context->MRxCancelRoutine);
978 Context->MRxCancelRoutine(Context);
979 }
980
981 /* And delete the context */
982 RxDereferenceAndDeleteRxContext(Context);
983 }
984 }
985
986 /*
987 * @implemented
988 */
989 NTSTATUS
990 RxCancelNotifyChangeDirectoryRequestsForVNetRoot(
991 PV_NET_ROOT VNetRoot,
992 BOOLEAN ForceFilesClosed)
993 {
994 KIRQL OldIrql;
995 NTSTATUS Status;
996 PLIST_ENTRY Entry;
997 PRX_CONTEXT Context;
998 LIST_ENTRY ContextsToCancel;
999
1000 /* Init a list for the contexts to cancel */
1001 InitializeListHead(&ContextsToCancel);
1002
1003 /* Lock our list lock */
1004 KeAcquireSpinLock(&RxStrucSupSpinLock, &OldIrql);
1005
1006 /* Now, browse all the active contexts, to find the associated ones */
1007 Entry = RxActiveContexts.Flink;
1008 while (Entry != &RxActiveContexts)
1009 {
1010 Context = CONTAINING_RECORD(Entry, RX_CONTEXT, ContextListEntry);
1011 Entry = Entry->Flink;
1012
1013 /* Not the IRP we're looking for, ignore */
1014 if (Context->MajorFunction != IRP_MJ_DIRECTORY_CONTROL ||
1015 Context->MinorFunction != IRP_MN_NOTIFY_CHANGE_DIRECTORY)
1016 {
1017 continue;
1018 }
1019
1020 /* Not the VNetRoot we're looking for, ignore */
1021 if (Context->pFcb == NULL ||
1022 (PV_NET_ROOT)Context->NotifyChangeDirectory.pVNetRoot != VNetRoot)
1023 {
1024 continue;
1025 }
1026
1027 /* No cancel routine (can't be cancel, then), ignore */
1028 if (Context->MRxCancelRoutine == NULL)
1029 {
1030 continue;
1031 }
1032
1033 /* At that point, we found a matching context
1034 * If we're not asked to force close, then fail - it's still open
1035 */
1036 if (!ForceFilesClosed)
1037 {
1038 Status = STATUS_FILES_OPEN;
1039 break;
1040 }
1041
1042 /* Mark our context as cancelled */
1043 SetFlag(Context->Flags, RX_CONTEXT_FLAG_CANCELLED);
1044
1045 /* Move it to our list */
1046 RemoveEntryList(&Context->ContextListEntry);
1047 InsertTailList(&ContextsToCancel, &Context->ContextListEntry);
1048
1049 InterlockedIncrement((volatile long *)&Context->ReferenceCount);
1050 }
1051
1052 /* Done with the contexts */
1053 KeReleaseSpinLock(&RxStrucSupSpinLock, OldIrql);
1054
1055 if (Status != STATUS_SUCCESS)
1056 {
1057 return Status;
1058 }
1059
1060 /* Now, handle all our "extracted" contexts */
1061 while (!IsListEmpty(&ContextsToCancel))
1062 {
1063 Entry = RemoveHeadList(&ContextsToCancel);
1064 Context = CONTAINING_RECORD(Entry, RX_CONTEXT, ContextListEntry);
1065
1066 /* If they had an associated IRP (should be always true) */
1067 if (Context->CurrentIrp != NULL)
1068 {
1069 /* Then, call cancel routine */
1070 ASSERT(Context->MRxCancelRoutine != NULL);
1071 DPRINT1("Canceling %p with %p\n", Context, Context->MRxCancelRoutine);
1072 Context->MRxCancelRoutine(Context);
1073 }
1074
1075 /* And delete the context */
1076 RxDereferenceAndDeleteRxContext(Context);
1077 }
1078
1079 return Status;
1080 }
1081
1082 VOID
1083 NTAPI
1084 RxCancelRoutine(
1085 PDEVICE_OBJECT DeviceObject,
1086 PIRP Irp)
1087 {
1088 UNIMPLEMENTED;
1089 }
1090
1091 /*
1092 * @implemented
1093 */
1094 NTSTATUS
1095 RxCanonicalizeFileNameByServerSpecs(
1096 PRX_CONTEXT RxContext,
1097 PUNICODE_STRING NetRootName)
1098 {
1099 USHORT NextChar, CurChar;
1100 USHORT MaxChars;
1101
1102 PAGED_CODE();
1103
1104 /* Validate file name is not empty */
1105 MaxChars = NetRootName->Length / sizeof(WCHAR);
1106 if (MaxChars == 0)
1107 {
1108 return STATUS_MORE_PROCESSING_REQUIRED;
1109 }
1110
1111 /* Validate name is correct */
1112 for (NextChar = 0, CurChar = 0; CurChar + 1 < MaxChars; NextChar = CurChar + 1)
1113 {
1114 USHORT i;
1115
1116 for (i = NextChar + 1; i < MaxChars; ++i)
1117 {
1118 if (NetRootName->Buffer[i] == '\\' || NetRootName->Buffer[i] == ':')
1119 {
1120 break;
1121 }
1122 }
1123
1124 CurChar = i - 1;
1125 if (CurChar == NextChar)
1126 {
1127 if (((NetRootName->Buffer[NextChar] != '\\' && NetRootName->Buffer[NextChar] != ':') || NextChar == (MaxChars - 1)) && NetRootName->Buffer[NextChar] != '.')
1128 {
1129 continue;
1130 }
1131
1132 if (CurChar != 0)
1133 {
1134 if (CurChar >= MaxChars - 1)
1135 {
1136 continue;
1137 }
1138
1139 if (NetRootName->Buffer[CurChar + 1] != ':')
1140 {
1141 return STATUS_OBJECT_PATH_SYNTAX_BAD;
1142 }
1143 }
1144 else
1145 {
1146 if (NetRootName->Buffer[1] != ':')
1147 {
1148 return STATUS_OBJECT_PATH_SYNTAX_BAD;
1149 }
1150 }
1151 }
1152 else
1153 {
1154 if ((CurChar - NextChar) == 1)
1155 {
1156 if (NetRootName->Buffer[NextChar + 2] != '.')
1157 {
1158 continue;
1159 }
1160
1161 if (NetRootName->Buffer[NextChar] == '\\' || NetRootName->Buffer[NextChar] == ':' || NetRootName->Buffer[NextChar] == '.')
1162 {
1163 return STATUS_OBJECT_PATH_SYNTAX_BAD;
1164 }
1165 }
1166 else
1167 {
1168 if ((CurChar - NextChar) != 2 || (NetRootName->Buffer[NextChar] != '\\' && NetRootName->Buffer[NextChar] != ':')
1169 || NetRootName->Buffer[NextChar + 1] != '.')
1170 {
1171 continue;
1172 }
1173
1174 if (NetRootName->Buffer[NextChar + 2] == '.')
1175 {
1176 return STATUS_OBJECT_PATH_SYNTAX_BAD;
1177 }
1178 }
1179 }
1180 }
1181
1182 return STATUS_MORE_PROCESSING_REQUIRED;
1183 }
1184
1185 NTSTATUS
1186 RxCanonicalizeNameAndObtainNetRoot(
1187 PRX_CONTEXT RxContext,
1188 PUNICODE_STRING FileName,
1189 PUNICODE_STRING NetRootName)
1190 {
1191 NTSTATUS Status;
1192 NET_ROOT_TYPE NetRootType;
1193 UNICODE_STRING CanonicalName;
1194
1195 PAGED_CODE();
1196
1197 NetRootType = NET_ROOT_WILD;
1198
1199 RtlInitEmptyUnicodeString(NetRootName, NULL, 0);
1200 RtlInitEmptyUnicodeString(&CanonicalName, NULL, 0);
1201
1202 /* if not relative opening, just handle the passed name */
1203 if (RxContext->CurrentIrpSp->FileObject->RelatedFileObject == NULL)
1204 {
1205 Status = RxFirstCanonicalize(RxContext, FileName, &CanonicalName, &NetRootType);
1206 if (!NT_SUCCESS(Status))
1207 {
1208 return Status;
1209 }
1210 }
1211 else
1212 {
1213 PFCB Fcb;
1214
1215 /* Make sure we have a valid FCB and a FOBX */
1216 Fcb = RxContext->CurrentIrpSp->FileObject->RelatedFileObject->FsContext;
1217 if (Fcb == NULL ||
1218 RxContext->CurrentIrpSp->FileObject->RelatedFileObject->FsContext2 == NULL)
1219 {
1220 return STATUS_INVALID_PARAMETER;
1221 }
1222
1223 if (!NodeTypeIsFcb(Fcb))
1224 {
1225 return STATUS_INVALID_PARAMETER;
1226 }
1227
1228 UNIMPLEMENTED;
1229 }
1230
1231 /* Get/Create the associated VNetRoot for opening */
1232 Status = RxFindOrConstructVirtualNetRoot(RxContext, &CanonicalName, NetRootType, NetRootName);
1233 if (!NT_SUCCESS(Status) && Status != STATUS_PENDING &&
1234 BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_MAILSLOT_REPARSE))
1235 {
1236 ASSERT(CanonicalName.Buffer == RxContext->Create.CanonicalNameBuffer);
1237
1238 RxFreeCanonicalNameBuffer(RxContext);
1239 Status = RxFirstCanonicalize(RxContext, FileName, &CanonicalName, &NetRootType);
1240 if (NT_SUCCESS(Status))
1241 {
1242 Status = RxFindOrConstructVirtualNetRoot(RxContext, &CanonicalName, NetRootType, NetRootName);
1243 }
1244 }
1245
1246 /* Filename cannot contain wildcards */
1247 if (FsRtlDoesNameContainWildCards(NetRootName))
1248 {
1249 Status = STATUS_OBJECT_NAME_INVALID;
1250 }
1251
1252 /* Make sure file name is correct */
1253 if (NT_SUCCESS(Status))
1254 {
1255 Status = RxCanonicalizeFileNameByServerSpecs(RxContext, NetRootName);
1256 }
1257
1258 /* Give the mini-redirector a chance to prepare the name */
1259 if (NT_SUCCESS(Status) || Status == STATUS_MORE_PROCESSING_REQUIRED)
1260 {
1261 if (RxContext->Create.pNetRoot != NULL)
1262 {
1263 NTSTATUS IgnoredStatus;
1264
1265 MINIRDR_CALL(IgnoredStatus, RxContext, RxContext->Create.pNetRoot->pSrvCall->RxDeviceObject->Dispatch,
1266 MRxPreparseName, (RxContext, NetRootName));
1267 (void)IgnoredStatus;
1268 }
1269 }
1270
1271 return Status;
1272 }
1273
1274 VOID
1275 NTAPI
1276 RxCheckFcbStructuresForAlignment(
1277 VOID)
1278 {
1279 UNIMPLEMENTED;
1280 }
1281
1282 NTSTATUS
1283 RxCheckShareAccess(
1284 _In_ ACCESS_MASK DesiredAccess,
1285 _In_ ULONG DesiredShareAccess,
1286 _Inout_ PFILE_OBJECT FileObject,
1287 _Inout_ PSHARE_ACCESS ShareAccess,
1288 _In_ BOOLEAN Update,
1289 _In_ PSZ where,
1290 _In_ PSZ wherelogtag)
1291 {
1292 PAGED_CODE();
1293
1294 RxDumpWantedAccess(where, "", wherelogtag, DesiredAccess, DesiredShareAccess);
1295 RxDumpCurrentAccess(where, "", wherelogtag, ShareAccess);
1296
1297 return IoCheckShareAccess(DesiredAccess, DesiredShareAccess, FileObject, ShareAccess, Update);
1298 }
1299
1300 /*
1301 * @implemented
1302 */
1303 NTSTATUS
1304 RxCheckShareAccessPerSrvOpens(
1305 IN PFCB Fcb,
1306 IN ACCESS_MASK DesiredAccess,
1307 IN ULONG DesiredShareAccess)
1308 {
1309 BOOLEAN ReadAccess;
1310 BOOLEAN WriteAccess;
1311 BOOLEAN DeleteAccess;
1312 PSHARE_ACCESS ShareAccess;
1313
1314 PAGED_CODE();
1315
1316 ShareAccess = &Fcb->ShareAccessPerSrvOpens;
1317
1318 RxDumpWantedAccess("RxCheckShareAccessPerSrvOpens", "", "RxCheckShareAccessPerSrvOpens", DesiredAccess, DesiredShareAccess);
1319 RxDumpCurrentAccess("RxCheckShareAccessPerSrvOpens", "", "RxCheckShareAccessPerSrvOpens", ShareAccess);
1320
1321 /* Check if any access wanted */
1322 ReadAccess = (DesiredAccess & (FILE_READ_DATA | FILE_EXECUTE)) != 0;
1323 WriteAccess = (DesiredAccess & (FILE_WRITE_DATA | FILE_APPEND_DATA)) != 0;
1324 DeleteAccess = (DesiredAccess & DELETE) != 0;
1325
1326 if (ReadAccess || WriteAccess || DeleteAccess)
1327 {
1328 BOOLEAN SharedRead = (DesiredShareAccess & FILE_SHARE_READ) != 0;
1329 BOOLEAN SharedWrite = (DesiredShareAccess & FILE_SHARE_WRITE) != 0;
1330 BOOLEAN SharedDelete = (DesiredShareAccess & FILE_SHARE_DELETE) != 0;
1331
1332 /* Check whether there's a violation */
1333 if ((ReadAccess &&
1334 (ShareAccess->SharedRead < ShareAccess->OpenCount)) ||
1335 (WriteAccess &&
1336 (ShareAccess->SharedWrite < ShareAccess->OpenCount)) ||
1337 (DeleteAccess &&
1338 (ShareAccess->SharedDelete < ShareAccess->OpenCount)) ||
1339 ((ShareAccess->Readers != 0) && !SharedRead) ||
1340 ((ShareAccess->Writers != 0) && !SharedWrite) ||
1341 ((ShareAccess->Deleters != 0) && !SharedDelete))
1342 {
1343 return STATUS_SHARING_VIOLATION;
1344 }
1345 }
1346
1347 return STATUS_SUCCESS;
1348 }
1349
1350 VOID
1351 RxCleanupPipeQueues(
1352 PRX_CONTEXT Context)
1353 {
1354 UNIMPLEMENTED;
1355 }
1356
1357 /*
1358 * @implemented
1359 */
1360 NTSTATUS
1361 RxCloseAssociatedSrvOpen(
1362 IN PFOBX Fobx,
1363 IN PRX_CONTEXT RxContext OPTIONAL)
1364 {
1365 PFCB Fcb;
1366 NTSTATUS Status;
1367 PSRV_OPEN SrvOpen;
1368 BOOLEAN CloseSrvOpen;
1369 PRX_CONTEXT LocalContext;
1370
1371 PAGED_CODE();
1372
1373 /* Assume SRV_OPEN is already closed */
1374 CloseSrvOpen = FALSE;
1375 /* If we have a FOBX, we'll have to close it */
1376 if (Fobx != NULL)
1377 {
1378 /* If the FOBX isn't closed yet */
1379 if (!BooleanFlagOn(Fobx->Flags, FOBX_FLAG_SRVOPEN_CLOSED))
1380 {
1381 SrvOpen = Fobx->SrvOpen;
1382 Fcb = (PFCB)SrvOpen->pFcb;
1383 /* Check whether we've to close SRV_OPEN first */
1384 if (!BooleanFlagOn(SrvOpen->Flags, SRVOPEN_FLAG_CLOSED))
1385 {
1386 CloseSrvOpen = TRUE;
1387 }
1388 else
1389 {
1390 ASSERT(RxIsFcbAcquiredExclusive(Fcb));
1391
1392 /* Not much to do */
1393 SetFlag(Fobx->Flags, FOBX_FLAG_SRVOPEN_CLOSED);
1394
1395 if (SrvOpen->OpenCount > 0)
1396 {
1397 --SrvOpen->OpenCount;
1398 }
1399 }
1400 }
1401
1402 /* No need to close SRV_OPEN, so close FOBX */
1403 if (!CloseSrvOpen)
1404 {
1405 RxMarkFobxOnClose(Fobx);
1406
1407 return STATUS_SUCCESS;
1408 }
1409 }
1410 else
1411 {
1412 /* No FOBX? No RX_CONTEXT, ok, job done! */
1413 if (RxContext == NULL)
1414 {
1415 return STATUS_SUCCESS;
1416 }
1417
1418 /* Get the FCB from RX_CONTEXT */
1419 Fcb = (PFCB)RxContext->pFcb;
1420 SrvOpen = NULL;
1421 }
1422
1423 /* If we don't have RX_CONTEXT, allocte one, we'll need it */
1424 if (RxContext == NULL)
1425 {
1426 ASSERT(Fobx != NULL);
1427
1428 LocalContext = RxCreateRxContext(NULL, Fcb->RxDeviceObject, RX_CONTEXT_FLAG_MUST_SUCCEED_NONBLOCKING | RX_CONTEXT_FLAG_WAIT);
1429 if (LocalContext == NULL)
1430 {
1431 return STATUS_INSUFFICIENT_RESOURCES;
1432 }
1433
1434 LocalContext->MajorFunction = 2;
1435 LocalContext->pFcb = RX_GET_MRX_FCB(Fcb);
1436 LocalContext->pFobx = (PMRX_FOBX)Fobx;
1437 LocalContext->pRelevantSrvOpen = (PMRX_SRV_OPEN)Fobx->SrvOpen;
1438 }
1439 else
1440 {
1441 LocalContext = RxContext;
1442 }
1443
1444 ASSERT(RxIsFcbAcquiredExclusive(Fcb));
1445
1446 /* Now, close the FOBX */
1447 if (Fobx != NULL)
1448 {
1449 RxMarkFobxOnClose(Fobx);
1450 }
1451 else
1452 {
1453 InterlockedDecrement((volatile long *)&Fcb->OpenCount);
1454 }
1455
1456 /* If not a "standard" file, SRV_OPEN can be null */
1457 if (SrvOpen == NULL)
1458 {
1459 ASSERT((NodeType(Fcb) == RDBSS_NTC_OPENTARGETDIR_FCB) || (NodeType(Fcb) == RDBSS_NTC_IPC_SHARE) || (NodeType(Fcb) == RDBSS_NTC_MAILSLOT));
1460 RxDereferenceNetFcb(Fcb);
1461
1462 if (LocalContext != RxContext)
1463 {
1464 RxDereferenceAndDeleteRxContext(LocalContext);
1465 }
1466
1467 return STATUS_SUCCESS;
1468 }
1469
1470 /* If SRV_OPEN isn't in a good condition, nothing to close */
1471 if (SrvOpen->Condition != Condition_Good)
1472 {
1473 if (LocalContext != RxContext)
1474 {
1475 RxDereferenceAndDeleteRxContext(LocalContext);
1476 }
1477
1478 return STATUS_SUCCESS;
1479 }
1480
1481 /* Decrease open count */
1482 if (SrvOpen->OpenCount > 0)
1483 {
1484 --SrvOpen->OpenCount;
1485 }
1486
1487 /* If we're the only one left, is there a FOBX handled by Scavenger? */
1488 if (SrvOpen->OpenCount == 1)
1489 {
1490 if (!IsListEmpty(&SrvOpen->FobxList))
1491 {
1492 if (!IsListEmpty(&CONTAINING_RECORD(SrvOpen->FobxList.Flink, FOBX, FobxQLinks)->ScavengerFinalizationList))
1493 {
1494 SetFlag(SrvOpen->Flags, SRVOPEN_FLAG_CLOSE_DELAYED);
1495 }
1496 }
1497 }
1498
1499 /* Nothing left, purge FCB */
1500 if (SrvOpen->OpenCount == 0 && RxContext == NULL)
1501 {
1502 RxPurgeNetFcb(Fcb, LocalContext);
1503 }
1504
1505 /* Already closed? Job done! */
1506 SrvOpen = Fobx->SrvOpen;
1507 if (SrvOpen == NULL ||
1508 (SrvOpen->OpenCount != 0 && !BooleanFlagOn(SrvOpen->Flags, SRVOPEN_FLAG_BUFFERING_STATE_CHANGE_PENDING)) ||
1509 BooleanFlagOn(SrvOpen->Flags, SRVOPEN_FLAG_CLOSED))
1510 {
1511 SetFlag(Fobx->Flags, FOBX_FLAG_SRVOPEN_CLOSED);
1512 if (LocalContext != RxContext)
1513 {
1514 RxDereferenceAndDeleteRxContext(LocalContext);
1515 }
1516
1517 return STATUS_SUCCESS;
1518 }
1519
1520 ASSERT(RxIsFcbAcquiredExclusive(Fcb));
1521
1522 /* Inform mini-rdr about closing */
1523 MINIRDR_CALL(Status, LocalContext, Fcb->MRxDispatch, MRxCloseSrvOpen, (LocalContext));
1524 DPRINT("MRxCloseSrvOpen returned: %lx, called with RX_CONTEXT %p for FOBX %p (FCB %p, SRV_OPEN %p)\n ",
1525 Status, RxContext, Fobx, Fcb, SrvOpen);
1526
1527 /* And mark as such */
1528 SetFlag(SrvOpen->Flags, SRVOPEN_FLAG_CLOSED);
1529 SrvOpen->Key = (PVOID)-1;
1530
1531 /* If we were delayed, we're not! */
1532 if (BooleanFlagOn(SrvOpen->Flags, SRVOPEN_FLAG_CLOSE_DELAYED))
1533 {
1534 InterlockedDecrement(&((PSRV_CALL)Fcb->pNetRoot->pSrvCall)->NumberOfCloseDelayedFiles);
1535 }
1536
1537 /* Clear access */
1538 RxRemoveShareAccessPerSrvOpens(SrvOpen);
1539 RxPurgeChangeBufferingStateRequestsForSrvOpen(SrvOpen);
1540
1541 /* Dereference */
1542 RxDereferenceSrvOpen(SrvOpen, LHS_ExclusiveLockHeld);
1543
1544 /* Mark the FOBX closed as well */
1545 SetFlag(Fobx->Flags, FOBX_FLAG_SRVOPEN_CLOSED);
1546
1547 if (LocalContext != RxContext)
1548 {
1549 RxDereferenceAndDeleteRxContext(LocalContext);
1550 }
1551
1552 return Status;
1553 }
1554
1555 /*
1556 * @implemented
1557 */
1558 NTSTATUS
1559 RxCollapseOrCreateSrvOpen(
1560 PRX_CONTEXT RxContext)
1561 {
1562 PFCB Fcb;
1563 NTSTATUS Status;
1564 ULONG Disposition;
1565 PSRV_OPEN SrvOpen;
1566 USHORT ShareAccess;
1567 PIO_STACK_LOCATION Stack;
1568 ACCESS_MASK DesiredAccess;
1569 RX_BLOCK_CONDITION FcbCondition;
1570
1571 PAGED_CODE();
1572
1573 DPRINT("RxCollapseOrCreateSrvOpen(%p)\n", RxContext);
1574
1575 Fcb = (PFCB)RxContext->pFcb;
1576 ASSERT(RxIsFcbAcquiredExclusive(Fcb));
1577 ++Fcb->UncleanCount;
1578
1579 Stack = RxContext->CurrentIrpSp;
1580 DesiredAccess = Stack->Parameters.Create.SecurityContext->DesiredAccess & FILE_ALL_ACCESS;
1581 ShareAccess = Stack->Parameters.Create.ShareAccess & FILE_SHARE_VALID_FLAGS;
1582
1583 Disposition = RxContext->Create.NtCreateParameters.Disposition;
1584
1585 /* Try to find a reusable SRV_OPEN */
1586 Status = RxSearchForCollapsibleOpen(RxContext, DesiredAccess, ShareAccess);
1587 if (Status == STATUS_NOT_FOUND)
1588 {
1589 /* If none found, create one */
1590 SrvOpen = RxCreateSrvOpen((PV_NET_ROOT)RxContext->Create.pVNetRoot, Fcb);
1591 if (SrvOpen == NULL)
1592 {
1593 Status = STATUS_INSUFFICIENT_RESOURCES;
1594 }
1595 else
1596 {
1597 SrvOpen->DesiredAccess = DesiredAccess;
1598 SrvOpen->ShareAccess = ShareAccess;
1599 Status = STATUS_SUCCESS;
1600 }
1601
1602 RxContext->pRelevantSrvOpen = (PMRX_SRV_OPEN)SrvOpen;
1603
1604 if (Status != STATUS_SUCCESS)
1605 {
1606 FcbCondition = Condition_Bad;
1607 }
1608 else
1609 {
1610 RxInitiateSrvOpenKeyAssociation(SrvOpen);
1611
1612 /* Cookie to check the mini-rdr doesn't mess with RX_CONTEXT */
1613 RxContext->CurrentIrp->IoStatus.Information = 0xABCDEF;
1614 /* Inform the mini-rdr we're handling a create */
1615 MINIRDR_CALL(Status, RxContext, Fcb->MRxDispatch, MRxCreate, (RxContext));
1616 ASSERT(RxContext->CurrentIrp->IoStatus.Information == 0xABCDEF);
1617
1618 DPRINT("MRxCreate returned: %x\n", Status);
1619 if (Status == STATUS_SUCCESS)
1620 {
1621 /* In case of overwrite, reset file size */
1622 if (Disposition == FILE_OVERWRITE || Disposition == FILE_OVERWRITE_IF)
1623 {
1624 RxAcquirePagingIoResource(RxContext, Fcb);
1625 Fcb->Header.AllocationSize.QuadPart = 0LL;
1626 Fcb->Header.FileSize.QuadPart = 0LL;
1627 Fcb->Header.ValidDataLength.QuadPart = 0LL;
1628 RxContext->CurrentIrpSp->FileObject->SectionObjectPointer = &Fcb->NonPaged->SectionObjectPointers;
1629 CcSetFileSizes(RxContext->CurrentIrpSp->FileObject, (PCC_FILE_SIZES)&Fcb->Header.AllocationSize);
1630 RxReleasePagingIoResource(RxContext, Fcb);
1631 }
1632 else
1633 {
1634 /* Otherwise, adjust sizes */
1635 RxContext->CurrentIrpSp->FileObject->SectionObjectPointer = &Fcb->NonPaged->SectionObjectPointers;
1636 if (CcIsFileCached(RxContext->CurrentIrpSp->FileObject))
1637 {
1638 RxAdjustAllocationSizeforCC(Fcb);
1639 }
1640 CcSetFileSizes(RxContext->CurrentIrpSp->FileObject, (PCC_FILE_SIZES)&Fcb->Header.AllocationSize);
1641 }
1642 }
1643
1644 /* Set the IoStatus with information returned by mini-rdr */
1645 RxContext->CurrentIrp->IoStatus.Information = RxContext->Create.ReturnedCreateInformation;
1646
1647 SrvOpen->OpenStatus = Status;
1648 /* Set SRV_OPEN state - good or bad - depending on whether create succeed */
1649 RxTransitionSrvOpen(SrvOpen, (Status == STATUS_SUCCESS ? Condition_Good : Condition_Bad));
1650
1651 ASSERT(RxIsFcbAcquiredExclusive(Fcb));
1652
1653 RxCompleteSrvOpenKeyAssociation(SrvOpen);
1654
1655 if (Status == STATUS_SUCCESS)
1656 {
1657 if (BooleanFlagOn(Stack->Parameters.Create.Options, FILE_DELETE_ON_CLOSE))
1658 {
1659 ClearFlag(Fcb->FcbState, FCB_STATE_COLLAPSING_ENABLED);
1660 }
1661 SrvOpen->CreateOptions = RxContext->Create.NtCreateParameters.CreateOptions;
1662 FcbCondition = Condition_Good;
1663 }
1664 else
1665 {
1666 FcbCondition = Condition_Bad;
1667 RxDereferenceSrvOpen(SrvOpen, LHS_ExclusiveLockHeld);
1668 RxContext->pRelevantSrvOpen = NULL;
1669
1670 if (RxContext->pFobx != NULL)
1671 {
1672 RxDereferenceNetFobx(RxContext->pFobx, LHS_ExclusiveLockHeld);
1673 RxContext->pFobx = NULL;
1674 }
1675 }
1676 }
1677
1678 /* Set FCB state - good or bad - depending on whether create succeed */
1679 DPRINT("Transitioning FCB %p to condition %lx\n", Fcb, Fcb->Condition);
1680 RxTransitionNetFcb(Fcb, FcbCondition);
1681 }
1682 else if (Status == STATUS_SUCCESS)
1683 {
1684 BOOLEAN IsGood, ExtraOpen;
1685
1686 /* A reusable SRV_OPEN was found */
1687 RxContext->CurrentIrp->IoStatus.Information = FILE_OPENED;
1688 ExtraOpen = FALSE;
1689
1690 SrvOpen = (PSRV_OPEN)RxContext->pRelevantSrvOpen;
1691
1692 IsGood = (SrvOpen->Condition == Condition_Good);
1693 /* If the SRV_OPEN isn't in a stable situation, wait for it to become stable */
1694 if (!StableCondition(SrvOpen->Condition))
1695 {
1696 RxReferenceSrvOpen(SrvOpen);
1697 ++SrvOpen->OpenCount;
1698 ExtraOpen = TRUE;
1699
1700 RxReleaseFcb(RxContext, Fcb);
1701 RxContext->Create.FcbAcquired = FALSE;
1702
1703 RxWaitForStableSrvOpen(SrvOpen, RxContext);
1704
1705 if (NT_SUCCESS(RxAcquireExclusiveFcb(RxContext, Fcb)))
1706 {
1707 RxContext->Create.FcbAcquired = TRUE;
1708 }
1709
1710 IsGood = (SrvOpen->Condition == Condition_Good);
1711 }
1712
1713 /* Inform the mini-rdr we do an opening with a reused SRV_OPEN */
1714 if (IsGood)
1715 {
1716 MINIRDR_CALL(Status, RxContext, Fcb->MRxDispatch, MRxCollapseOpen, (RxContext));
1717
1718 ASSERT(RxIsFcbAcquiredExclusive(Fcb));
1719 }
1720 else
1721 {
1722 Status = SrvOpen->OpenStatus;
1723 }
1724
1725 if (ExtraOpen)
1726 {
1727 --SrvOpen->OpenCount;
1728 RxDereferenceSrvOpen(SrvOpen, LHS_ExclusiveLockHeld);
1729 }
1730 }
1731
1732 --Fcb->UncleanCount;
1733
1734 DPRINT("Status: %x\n", Status);
1735 return Status;
1736 }
1737
1738 NTSTATUS
1739 NTAPI
1740 RxCommonCleanup(
1741 PRX_CONTEXT Context)
1742 {
1743 #define BugCheckFileId RDBSS_BUG_CHECK_CLEANUP
1744 PFCB Fcb;
1745 PFOBX Fobx;
1746 ULONG OpenCount;
1747 NTSTATUS Status;
1748 PNET_ROOT NetRoot;
1749 PFILE_OBJECT FileObject;
1750 LARGE_INTEGER TruncateSize;
1751 PLARGE_INTEGER TruncateSizePtr;
1752 BOOLEAN NeedPurge, FcbTableAcquired, OneLeft, IsFile, FcbAcquired, LeftForDelete;
1753
1754 PAGED_CODE();
1755
1756 Fcb = (PFCB)Context->pFcb;
1757 Fobx = (PFOBX)Context->pFobx;
1758 DPRINT("RxCommonCleanup(%p); FOBX: %p, FCB: %p\n", Context, Fobx, Fcb);
1759
1760 /* File system closing, it's OK */
1761 if (Fobx == NULL)
1762 {
1763 if (Fcb->UncleanCount > 0)
1764 {
1765 InterlockedDecrement((volatile long *)&Fcb->UncleanCount);
1766 }
1767
1768 return STATUS_SUCCESS;
1769 }
1770
1771 /* Check we have a correct FCB type */
1772 if (NodeType(Fcb) != RDBSS_NTC_STORAGE_TYPE_FILE &&
1773 NodeType(Fcb) != RDBSS_NTC_STORAGE_TYPE_DIRECTORY &&
1774 NodeType(Fcb) != RDBSS_NTC_STORAGE_TYPE_UNKNOWN &&
1775 NodeType(Fcb) != RDBSS_NTC_SPOOLFILE)
1776 {
1777 DPRINT1("Invalid Fcb type for %p\n", Fcb);
1778 RxBugCheck(Fcb->Header.NodeTypeCode, 0, 0);
1779 }
1780
1781 FileObject = Context->CurrentIrpSp->FileObject;
1782 ASSERT(!BooleanFlagOn(FileObject->Flags, FO_CLEANUP_COMPLETE));
1783
1784 RxMarkFobxOnCleanup(Fobx, &NeedPurge);
1785
1786 Status = RxAcquireExclusiveFcb(Context, Fcb);
1787 if (!NT_SUCCESS(Status))
1788 {
1789 return Status;
1790 }
1791
1792 FcbAcquired = TRUE;
1793
1794 Fobx->AssociatedFileObject = NULL;
1795
1796 /* In case SRV_OPEN used is part of FCB */
1797 if (BooleanFlagOn(Fcb->FcbState, FCB_STATE_SRVOPEN_USED))
1798 {
1799 ASSERT(Fcb->UncleanCount != 0);
1800 InterlockedDecrement((volatile long *)&Fcb->UncleanCount);
1801
1802 if (BooleanFlagOn(FileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING))
1803 {
1804 --Fcb->UncachedUncleanCount;
1805 }
1806
1807 /* Inform mini-rdr */
1808 MINIRDR_CALL(Status, Context, Fcb->MRxDispatch, MRxCleanupFobx, (Context));
1809
1810 ASSERT(Fobx->SrvOpen->UncleanFobxCount != 0);
1811 --Fobx->SrvOpen->UncleanFobxCount;
1812
1813 RxUninitializeCacheMap(Context, FileObject, NULL);
1814
1815 RxReleaseFcb(Context, Fcb);
1816
1817 return STATUS_SUCCESS;
1818 }
1819
1820 /* Report the fact that file could be set as delete on close */
1821 if (BooleanFlagOn(Fobx->Flags, FOBX_FLAG_DELETE_ON_CLOSE))
1822 {
1823 SetFlag(Fcb->FcbState, FCB_STATE_DELETE_ON_CLOSE);
1824 }
1825
1826 /* Cancel any pending notification */
1827 RxCancelNotifyChangeDirectoryRequestsForFobx(Fobx);
1828
1829 /* Backup open count before we start playing with it */
1830 OpenCount = Fcb->ShareAccess.OpenCount;
1831
1832 NetRoot = (PNET_ROOT)Fcb->pNetRoot;
1833 FcbTableAcquired = FALSE;
1834 LeftForDelete = FALSE;
1835 OneLeft = (Fcb->UncleanCount == 1);
1836
1837 _SEH2_TRY
1838 {
1839 /* Unclean count and delete on close? Verify whether we're the one */
1840 if (OneLeft && BooleanFlagOn(Fcb->FcbState, FCB_STATE_DELETE_ON_CLOSE))
1841 {
1842 if (RxAcquireFcbTableLockExclusive(&NetRoot->FcbTable, FALSE))
1843 {
1844 FcbTableAcquired = TRUE;
1845 }
1846 else
1847 {
1848 RxReleaseFcb(Context, Fcb);
1849
1850 RxAcquireFcbTableLockExclusive(&NetRoot->FcbTable, TRUE);
1851
1852 Status = RxAcquireExclusiveFcb(Context, Fcb);
1853 if (Status != STATUS_SUCCESS)
1854 {
1855 RxReleaseFcbTableLock(&NetRoot->FcbTable);
1856 return Status;
1857 }
1858
1859 FcbTableAcquired = TRUE;
1860 }
1861
1862 /* That means we'll perform the delete on close! */
1863 if (Fcb->UncleanCount == 1)
1864 {
1865 LeftForDelete = TRUE;
1866 }
1867 else
1868 {
1869 RxReleaseFcbTableLock(&NetRoot->FcbTable);
1870 FcbTableAcquired = FALSE;
1871 }
1872 }
1873
1874 IsFile = FALSE;
1875 TruncateSizePtr = NULL;
1876 /* Handle cleanup for pipes and printers */
1877 if (NetRoot->Type == NET_ROOT_PIPE || NetRoot->Type == NET_ROOT_PRINT)
1878 {
1879 RxCleanupPipeQueues(Context);
1880 }
1881 /* Handle cleanup for files */
1882 else if (NetRoot->Type == NET_ROOT_DISK || NetRoot->Type == NET_ROOT_WILD)
1883 {
1884 Context->LowIoContext.Flags |= LOWIO_CONTEXT_FLAG_SAVEUNLOCKS;
1885 if (NodeType(Fcb) == RDBSS_NTC_STORAGE_TYPE_FILE)
1886 {
1887 /* First, unlock */
1888 FsRtlFastUnlockAll(&Fcb->Specific.Fcb.FileLock, FileObject, RxGetRequestorProcess(Context), Context);
1889
1890 /* If there are still locks to release, proceed */
1891 if (Context->LowIoContext.ParamsFor.Locks.LockList != NULL)
1892 {
1893 RxInitializeLowIoContext(&Context->LowIoContext, LOWIO_OP_UNLOCK_MULTIPLE);
1894 Context->LowIoContext.ParamsFor.Locks.Flags = 0;
1895 Status = RxLowIoLockControlShell(Context);
1896 }
1897
1898 /* Fix times and size */
1899 RxAdjustFileTimesAndSize(Context);
1900
1901 /* If we're the only one left... */
1902 if (OneLeft)
1903 {
1904 /* And if we're supposed to delete on close */
1905 if (LeftForDelete)
1906 {
1907 /* Update the sizes */
1908 RxAcquirePagingIoResource(Context, Fcb);
1909 Fcb->Header.FileSize.QuadPart = 0;
1910 Fcb->Header.ValidDataLength.QuadPart = 0;
1911 RxReleasePagingIoResource(Context, Fcb);
1912 }
1913 /* Otherwise, call the mini-rdr to adjust sizes */
1914 else
1915 {
1916 /* File got grown up, fill with zeroes */
1917 if (!BooleanFlagOn(Fcb->FcbState, FCB_STATE_PAGING_FILE) &&
1918 (Fcb->Header.ValidDataLength.QuadPart < Fcb->Header.FileSize.QuadPart))
1919 {
1920 MINIRDR_CALL(Status, Context, Fcb->MRxDispatch, MRxZeroExtend, (Context));
1921 Fcb->Header.ValidDataLength.QuadPart = Fcb->Header.FileSize.QuadPart;
1922 }
1923
1924 /* File was truncated, let mini-rdr proceed */
1925 if (BooleanFlagOn(Fcb->FcbState, FCB_STATE_TRUNCATE_ON_CLOSE))
1926 {
1927 MINIRDR_CALL(Status, Context, Fcb->MRxDispatch, MRxTruncate, (Context));
1928 ClearFlag(Fcb->FcbState, FCB_STATE_TRUNCATE_ON_CLOSE);
1929
1930 /* Keep track of file change for Cc uninit */
1931 TruncateSize.QuadPart = Fcb->Header.FileSize.QuadPart;
1932 TruncateSizePtr = &TruncateSize;
1933 }
1934 }
1935 }
1936
1937 /* If RxMarkFobxOnCleanup() asked for purge, make sure we're the only one left first */
1938 if (NeedPurge)
1939 {
1940 if (!OneLeft)
1941 {
1942 NeedPurge = FALSE;
1943 }
1944 }
1945 /* Otherwise, try to see whether we can purge */
1946 else
1947 {
1948 NeedPurge = (OneLeft && (LeftForDelete || !BooleanFlagOn(Fcb->FcbState, FCB_STATE_COLLAPSING_ENABLED)));
1949 }
1950
1951 IsFile = TRUE;
1952 }
1953 }
1954
1955 /* We have to still be there! */
1956 ASSERT(Fcb->UncleanCount != 0);
1957 InterlockedDecrement((volatile long *)&Fcb->UncleanCount);
1958
1959 if (BooleanFlagOn(FileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING))
1960 {
1961 --Fcb->UncachedUncleanCount;
1962 }
1963
1964 /* Inform mini-rdr about ongoing cleanup */
1965 MINIRDR_CALL(Status, Context, Fcb->MRxDispatch, MRxCleanupFobx, (Context));
1966
1967 ASSERT(Fobx->SrvOpen->UncleanFobxCount != 0);
1968 --Fobx->SrvOpen->UncleanFobxCount;
1969
1970 /* Flush cache */
1971 if (DisableFlushOnCleanup)
1972 {
1973 /* Only if we're the last standing */
1974 if (Fcb->NonPaged->SectionObjectPointers.DataSectionObject != NULL &&
1975 Fcb->UncleanCount == Fcb->UncachedUncleanCount)
1976 {
1977 DPRINT("Flushing %p due to last cached handle cleanup\n", Context);
1978 RxFlushFcbInSystemCache(Fcb, TRUE);
1979 }
1980 }
1981 else
1982 {
1983 /* Always */
1984 if (Fcb->NonPaged->SectionObjectPointers.DataSectionObject != NULL)
1985 {
1986 DPRINT("Flushing %p on cleanup\n", Context);
1987 RxFlushFcbInSystemCache(Fcb, TRUE);
1988 }
1989 }
1990
1991 /* If only remaining uncached & unclean, then flush and purge */
1992 if (!BooleanFlagOn(FileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING))
1993 {
1994 if (Fcb->UncachedUncleanCount != 0)
1995 {
1996 if (Fcb->UncachedUncleanCount == Fcb->UncleanCount &&
1997 Fcb->NonPaged->SectionObjectPointers.DataSectionObject != NULL)
1998 {
1999 DPRINT("Flushing FCB in system cache for %p\n", Context);
2000 RxPurgeFcbInSystemCache(Fcb, NULL, 0, FALSE, TRUE);
2001 }
2002 }
2003 }
2004
2005 /* If purge required, and not about to delete, flush */
2006 if (!LeftForDelete && NeedPurge)
2007 {
2008 DPRINT("Flushing FCB in system cache for %p\n", Context);
2009 RxFlushFcbInSystemCache(Fcb, TRUE);
2010 }
2011
2012 /* If it was a file, drop cache */
2013 if (IsFile)
2014 {
2015 DPRINT("Uninit cache map for file\n");
2016 RxUninitializeCacheMap(Context, FileObject, TruncateSizePtr);
2017 }
2018
2019 /* If that's the one left for deletion, or if it needs purge, flush */
2020 if (LeftForDelete || NeedPurge)
2021 {
2022 RxPurgeFcbInSystemCache(Fcb, NULL, 0, FALSE, !LeftForDelete);
2023 /* If that's for deletion, also remove from FCB table */
2024 if (LeftForDelete)
2025 {
2026 RxRemoveNameNetFcb(Fcb);
2027 RxReleaseFcbTableLock(&NetRoot->FcbTable);
2028 FcbTableAcquired = FALSE;
2029 }
2030 }
2031
2032 /* Remove any share access */
2033 if (OpenCount != 0 && NetRoot->Type == NET_ROOT_DISK)
2034 {
2035 RxRemoveShareAccess(FileObject, &Fcb->ShareAccess, "Cleanup the share access", "ClnUpShr");
2036 }
2037
2038 /* In case there's caching, on a file, update file metadata */
2039 if (NodeType(Fcb) == RDBSS_NTC_STORAGE_TYPE_FILE && BooleanFlagOn(Fobx->Flags, 0x20000000) &&
2040 BooleanFlagOn(Fcb->FcbState, FCB_STATE_WRITECACHING_ENABLED) && !BooleanFlagOn(Fobx->pSrvOpen->Flags, SRVOPEN_FLAG_DONTUSE_WRITE_CACHING))
2041 {
2042 UNIMPLEMENTED;
2043 }
2044
2045 /* We're clean! */
2046 SetFlag(FileObject->Flags, FO_CLEANUP_COMPLETE);
2047
2048 FcbAcquired = FALSE;
2049 RxReleaseFcb(Context, Fcb);
2050 }
2051 _SEH2_FINALLY
2052 {
2053 if (FcbAcquired)
2054 {
2055 RxReleaseFcb(Context, Fcb);
2056 }
2057
2058 if (FcbTableAcquired)
2059 {
2060 RxReleaseFcbTableLock(&NetRoot->FcbTable);
2061 }
2062 }
2063 _SEH2_END;
2064
2065 return Status;
2066 #undef BugCheckFileId
2067 }
2068
2069 NTSTATUS
2070 NTAPI
2071 RxCommonClose(
2072 PRX_CONTEXT Context)
2073 {
2074 #define BugCheckFileId RDBSS_BUG_CHECK_CLOSE
2075 PFCB Fcb;
2076 PFOBX Fobx;
2077 NTSTATUS Status;
2078 PFILE_OBJECT FileObject;
2079 BOOLEAN DereferenceFobx, AcquiredFcb;
2080
2081 PAGED_CODE();
2082
2083 Fcb = (PFCB)Context->pFcb;
2084 Fobx = (PFOBX)Context->pFobx;
2085 FileObject = Context->CurrentIrpSp->FileObject;
2086 DPRINT("RxCommonClose(%p); FOBX: %p, FCB: %p, FO: %p\n", Context, Fobx, Fcb, FileObject);
2087
2088 Status = RxAcquireExclusiveFcb(Context, Fcb);
2089 if (!NT_SUCCESS(Status))
2090 {
2091 return Status;
2092 }
2093
2094 AcquiredFcb = TRUE;
2095 _SEH2_TRY
2096 {
2097 BOOLEAN Freed;
2098
2099 /* Check our FCB type is expected */
2100 if (NodeType(Fcb) != RDBSS_NTC_STORAGE_TYPE_UNKNOWN &&
2101 (NodeType(Fcb) < RDBSS_NTC_STORAGE_TYPE_DIRECTORY || (NodeType(Fcb) > RDBSS_NTC_STORAGE_TYPE_FILE &&
2102 (NodeType(Fcb) < RDBSS_NTC_SPOOLFILE || NodeType(Fcb) > RDBSS_NTC_OPENTARGETDIR_FCB))))
2103 {
2104 RxBugCheck(NodeType(Fcb), 0, 0);
2105 }
2106
2107 RxReferenceNetFcb(Fcb);
2108
2109 DereferenceFobx = FALSE;
2110 /* If we're not closing FS */
2111 if (Fobx != NULL)
2112 {
2113 PSRV_OPEN SrvOpen;
2114 PSRV_CALL SrvCall;
2115
2116 SrvOpen = (PSRV_OPEN)Fobx->pSrvOpen;
2117 SrvCall = (PSRV_CALL)Fcb->pNetRoot->pSrvCall;
2118 /* Handle delayed close */
2119 if (NodeType(Fcb) != RDBSS_NTC_STORAGE_TYPE_DIRECTORY)
2120 {
2121 if (!BooleanFlagOn(Fcb->FcbState, FCB_STATE_DELETE_ON_CLOSE | FCB_STATE_ORPHANED))
2122 {
2123 if (BooleanFlagOn(Fcb->FcbState, FCB_STATE_COLLAPSING_ENABLED))
2124 {
2125 DPRINT("Delay close for FOBX: %p, SrvOpen %p\n", Fobx, SrvOpen);
2126
2127 if (SrvOpen->OpenCount == 1 && !BooleanFlagOn(SrvOpen->Flags, SRVOPEN_FLAG_COLLAPSING_DISABLED))
2128 {
2129 if (InterlockedIncrement(&SrvCall->NumberOfCloseDelayedFiles) >= SrvCall->MaximumNumberOfCloseDelayedFiles)
2130 {
2131 InterlockedDecrement(&SrvCall->NumberOfCloseDelayedFiles);
2132 }
2133 else
2134 {
2135 DereferenceFobx = TRUE;
2136 SetFlag(SrvOpen->Flags, SRVOPEN_FLAG_CLOSE_DELAYED);
2137 }
2138 }
2139 }
2140 }
2141 }
2142
2143 /* If we reach maximum of delayed close/or if there are no delayed close */
2144 if (!DereferenceFobx)
2145 {
2146 PNET_ROOT NetRoot;
2147
2148 NetRoot = (PNET_ROOT)Fcb->pNetRoot;
2149 if (NetRoot->Type != NET_ROOT_PRINT)
2150 {
2151 /* Delete if asked */
2152 if (BooleanFlagOn(Fobx->Flags, FOBX_FLAG_DELETE_ON_CLOSE))
2153 {
2154 RxScavengeRelatedFobxs(Fcb);
2155 RxSynchronizeWithScavenger(Context);
2156
2157 RxReleaseFcb(Context, Fcb);
2158
2159 RxAcquireFcbTableLockExclusive(&NetRoot->FcbTable, TRUE);
2160 RxOrphanThisFcb(Fcb);
2161 RxReleaseFcbTableLock(&NetRoot->FcbTable);
2162
2163 Status = RxAcquireExclusiveFcb(Context, Fcb);
2164 ASSERT(NT_SUCCESS(Status));
2165 }
2166 }
2167 }
2168
2169 RxMarkFobxOnClose(Fobx);
2170 }
2171
2172 if (DereferenceFobx)
2173 {
2174 ASSERT(Fobx != NULL);
2175 RxDereferenceNetFobx(Fobx, LHS_SharedLockHeld);
2176 }
2177 else
2178 {
2179 RxCloseAssociatedSrvOpen(Fobx, Context);
2180 if (Fobx != NULL)
2181 {
2182 RxDereferenceNetFobx(Fobx, LHS_ExclusiveLockHeld);
2183 }
2184 }
2185
2186 Freed = RxDereferenceAndFinalizeNetFcb(Fcb, Context, FALSE, FALSE);
2187 AcquiredFcb = !Freed;
2188
2189 FileObject->FsContext = (PVOID)-1;
2190
2191 if (Freed)
2192 {
2193 RxTrackerUpdateHistory(Context, NULL, TRACKER_FCB_FREE, __LINE__, __FILE__, 0);
2194 }
2195 else
2196 {
2197 RxReleaseFcb(Context, Fcb);
2198 AcquiredFcb = FALSE;
2199 }
2200 }
2201 _SEH2_FINALLY
2202 {
2203 if (_SEH2_AbnormalTermination())
2204 {
2205 if (AcquiredFcb)
2206 {
2207 RxReleaseFcb(Context, Fcb);
2208 }
2209 }
2210 else
2211 {
2212 ASSERT(!AcquiredFcb);
2213 }
2214 }
2215 _SEH2_END;
2216
2217 DPRINT("Status: %x\n", Status);
2218 return Status;
2219 #undef BugCheckFileId
2220 }
2221
2222 NTSTATUS
2223 NTAPI
2224 RxCommonCreate(
2225 PRX_CONTEXT Context)
2226 {
2227 PIRP Irp;
2228 NTSTATUS Status;
2229 PFILE_OBJECT FileObject;
2230 PIO_STACK_LOCATION Stack;
2231
2232 PAGED_CODE();
2233
2234 DPRINT("RxCommonCreate(%p)\n", Context);
2235
2236 Irp = Context->CurrentIrp;
2237 Stack = Context->CurrentIrpSp;
2238 FileObject = Stack->FileObject;
2239
2240 /* Check whether that's a device opening */
2241 if (FileObject->FileName.Length == 0 && FileObject->RelatedFileObject == NULL)
2242 {
2243 FileObject->FsContext = &RxDeviceFCB;
2244 FileObject->FsContext2 = NULL;
2245
2246 ++RxDeviceFCB.NodeReferenceCount;
2247 ++RxDeviceFCB.OpenCount;
2248
2249 Irp->IoStatus.Information = FILE_OPENED;
2250 DPRINT("Device opening FO: %p, DO: %p, Name: %wZ\n", FileObject, Context->RxDeviceObject, &Context->RxDeviceObject->DeviceName);
2251
2252 Status = STATUS_SUCCESS;
2253 }
2254 else
2255 {
2256 PFCB RelatedFcb = NULL;
2257
2258 /* Make sure caller is consistent */
2259 if (FlagOn(Stack->Parameters.Create.Options, FILE_DIRECTORY_FILE | FILE_NON_DIRECTORY_FILE | FILE_OPEN_REMOTE_INSTANCE) ==
2260 (FILE_DIRECTORY_FILE | FILE_NON_DIRECTORY_FILE | FILE_OPEN_REMOTE_INSTANCE))
2261 {
2262 DPRINT1("Create.Options: %x\n", Stack->Parameters.Create.Options);
2263 return STATUS_INVALID_PARAMETER;
2264 }
2265
2266 DPRINT("Ctxt: %p, FO: %p, Options: %lx, Flags: %lx, Attr: %lx, ShareAccess: %lx, DesiredAccess: %lx\n",
2267 Context, FileObject, Stack->Parameters.Create.Options, Stack->Flags, Stack->Parameters.Create.FileAttributes,
2268 Stack->Parameters.Create.ShareAccess, Stack->Parameters.Create.SecurityContext->DesiredAccess);
2269 DPRINT("FileName: %wZ\n", &FileObject->FileName);
2270
2271 if (FileObject->RelatedFileObject != NULL)
2272 {
2273 RelatedFcb = FileObject->RelatedFileObject->FsContext;
2274 DPRINT("Rel FO: %p, path: %wZ\n", FileObject->RelatedFileObject, RelatedFcb->FcbTableEntry.Path);
2275 }
2276
2277 /* Going to rename? */
2278 if (BooleanFlagOn(Stack->Flags, SL_OPEN_TARGET_DIRECTORY))
2279 {
2280 DPRINT("TargetDir!\n");
2281 }
2282
2283 /* Copy create parameters to the context */
2284 RxCopyCreateParameters(Context);
2285
2286 /* If the caller wants to establish a connection, go ahead */
2287 if (BooleanFlagOn(Stack->Parameters.Create.Options, FILE_CREATE_TREE_CONNECTION))
2288 {
2289 Status = RxCreateTreeConnect(Context);
2290 }
2291 else
2292 {
2293 /* Validate file name */
2294 if (FileObject->FileName.Length > sizeof(WCHAR) &&
2295 FileObject->FileName.Buffer[1] == OBJ_NAME_PATH_SEPARATOR &&
2296 FileObject->FileName.Buffer[0] == OBJ_NAME_PATH_SEPARATOR)
2297 {
2298 FileObject->FileName.Length -= sizeof(WCHAR);
2299 RtlMoveMemory(&FileObject->FileName.Buffer[0], &FileObject->FileName.Buffer[1],
2300 FileObject->FileName.Length);
2301
2302 if (FileObject->FileName.Length > sizeof(WCHAR) &&
2303 FileObject->FileName.Buffer[1] == OBJ_NAME_PATH_SEPARATOR &&
2304 FileObject->FileName.Buffer[0] == OBJ_NAME_PATH_SEPARATOR)
2305 {
2306 return STATUS_OBJECT_NAME_INVALID;
2307 }
2308 }
2309
2310 /* Attempt to open the file */
2311 do
2312 {
2313 UNICODE_STRING NetRootName;
2314
2315 /* Strip last \ if required */
2316 if (FileObject->FileName.Length != 0 &&
2317 FileObject->FileName.Buffer[FileObject->FileName.Length / sizeof(WCHAR) - 1] == OBJ_NAME_PATH_SEPARATOR)
2318 {
2319 if (BooleanFlagOn(Stack->Parameters.Create.Options, FILE_NON_DIRECTORY_FILE))
2320 {
2321 return STATUS_OBJECT_NAME_INVALID;
2322 }
2323
2324 FileObject->FileName.Length -= sizeof(WCHAR);
2325 Context->Create.Flags |= RX_CONTEXT_CREATE_FLAG_STRIPPED_TRAILING_BACKSLASH;
2326 }
2327
2328 if (BooleanFlagOn(Context->Flags, RX_CONTEXT_FLAG_WRITE_THROUGH))
2329 {
2330 FileObject->Flags |= FO_WRITE_THROUGH;
2331 }
2332
2333 /* Get the associated net root to opening */
2334 Status = RxCanonicalizeNameAndObtainNetRoot(Context, &FileObject->FileName, &NetRootName);
2335 if (Status != STATUS_MORE_PROCESSING_REQUIRED)
2336 {
2337 break;
2338 }
2339
2340 /* And attempt to open */
2341 Status = RxCreateFromNetRoot(Context, &NetRootName);
2342 if (Status == STATUS_SHARING_VIOLATION)
2343 {
2344 UNIMPLEMENTED;
2345 }
2346 else if (Status == STATUS_REPARSE)
2347 {
2348 Context->CurrentIrp->IoStatus.Information = 0;
2349 }
2350 else
2351 {
2352 ASSERT(!BooleanFlagOn(Context->Create.Flags, RX_CONTEXT_CREATE_FLAG_REPARSE));
2353 }
2354 }
2355 while (Status == STATUS_MORE_PROCESSING_REQUIRED);
2356 }
2357
2358 if (Status == STATUS_RETRY)
2359 {
2360 RxpPrepareCreateContextForReuse(Context);
2361 }
2362 ASSERT(Status != STATUS_PENDING);
2363 }
2364
2365 DPRINT("Status: %lx\n", Status);
2366 return Status;
2367 }
2368
2369 /*
2370 * @implemented
2371 */
2372 NTSTATUS
2373 NTAPI
2374 RxCommonDevFCBCleanup(
2375 PRX_CONTEXT Context)
2376 {
2377 PMRX_FCB Fcb;
2378 NTSTATUS Status;
2379
2380 PAGED_CODE();
2381
2382 DPRINT("RxCommonDevFCBCleanup(%p)\n", Context);
2383
2384 Fcb = Context->pFcb;
2385 Status = STATUS_SUCCESS;
2386 ASSERT(NodeType(Fcb) == RDBSS_NTC_DEVICE_FCB);
2387
2388 /* Our FOBX if set, has to be a VNetRoot */
2389 if (Context->pFobx != NULL)
2390 {
2391 RxAcquirePrefixTableLockShared(Context->RxDeviceObject->pRxNetNameTable, TRUE);
2392 if (Context->pFobx->NodeTypeCode != RDBSS_NTC_V_NETROOT)
2393 {
2394 Status = STATUS_INVALID_DEVICE_REQUEST;
2395 }
2396 RxReleasePrefixTableLock(Context->RxDeviceObject->pRxNetNameTable);
2397 }
2398 else
2399 {
2400 --Fcb->UncleanCount;
2401 }
2402
2403 return Status;
2404 }
2405
2406 /*
2407 * @implemented
2408 */
2409 NTSTATUS
2410 NTAPI
2411 RxCommonDevFCBClose(
2412 PRX_CONTEXT Context)
2413 {
2414 PMRX_FCB Fcb;
2415 NTSTATUS Status;
2416 PMRX_V_NET_ROOT NetRoot;
2417
2418 PAGED_CODE();
2419
2420 DPRINT("RxCommonDevFCBClose(%p)\n", Context);
2421
2422 Fcb = Context->pFcb;
2423 NetRoot = (PMRX_V_NET_ROOT)Context->pFobx;
2424 Status = STATUS_SUCCESS;
2425 ASSERT(NodeType(Fcb) == RDBSS_NTC_DEVICE_FCB);
2426
2427 /* Our FOBX if set, has to be a VNetRoot */
2428 if (NetRoot != NULL)
2429 {
2430 RxAcquirePrefixTableLockExclusive(Context->RxDeviceObject->pRxNetNameTable, TRUE);
2431 if (NetRoot->NodeTypeCode == RDBSS_NTC_V_NETROOT)
2432 {
2433 --NetRoot->NumberOfOpens;
2434 RxDereferenceVNetRoot(NetRoot, LHS_ExclusiveLockHeld);
2435 }
2436 else
2437 {
2438 Status = STATUS_NOT_IMPLEMENTED;
2439 }
2440 RxReleasePrefixTableLock(Context->RxDeviceObject->pRxNetNameTable);
2441 }
2442 else
2443 {
2444 --Fcb->OpenCount;
2445 }
2446
2447 return Status;
2448 }
2449
2450 NTSTATUS
2451 NTAPI
2452 RxCommonDevFCBFsCtl(
2453 PRX_CONTEXT Context)
2454 {
2455 UNIMPLEMENTED;
2456 return STATUS_NOT_IMPLEMENTED;
2457 }
2458
2459 /*
2460 * @implemented
2461 */
2462 NTSTATUS
2463 NTAPI
2464 RxCommonDevFCBIoCtl(
2465 PRX_CONTEXT Context)
2466 {
2467 NTSTATUS Status;
2468
2469 PAGED_CODE();
2470
2471 DPRINT("RxCommonDevFCBIoCtl(%p)\n", Context);
2472
2473 if (Context->pFobx != NULL)
2474 {
2475 return STATUS_INVALID_HANDLE;
2476 }
2477
2478 /* Is that a prefix claim from MUP? */
2479 if (Context->CurrentIrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_REDIR_QUERY_PATH)
2480 {
2481 return RxPrefixClaim(Context);
2482 }
2483
2484 /* Otherwise, pass through the mini-rdr */
2485 Status = RxXXXControlFileCallthru(Context);
2486 if (Status != STATUS_PENDING)
2487 {
2488 if (Context->PostRequest)
2489 {
2490 Context->ResumeRoutine = RxCommonDevFCBIoCtl;
2491 Status = RxFsdPostRequest(Context);
2492 }
2493 }
2494
2495 DPRINT("Status: %lx\n", Status);
2496 return Status;
2497 }
2498
2499 NTSTATUS
2500 NTAPI
2501 RxCommonDevFCBQueryVolInfo(
2502 PRX_CONTEXT Context)
2503 {
2504 UNIMPLEMENTED;
2505 return STATUS_NOT_IMPLEMENTED;
2506 }
2507
2508 /*
2509 * @implemented
2510 */
2511 NTSTATUS
2512 NTAPI
2513 RxCommonDeviceControl(
2514 PRX_CONTEXT Context)
2515 {
2516 NTSTATUS Status;
2517
2518 PAGED_CODE();
2519
2520 /* Prefix claim is only allowed for device, not files */
2521 if (Context->CurrentIrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_REDIR_QUERY_PATH)
2522 {
2523 return STATUS_INVALID_DEVICE_REQUEST;
2524 }
2525
2526 /* Submit to mini-rdr */
2527 RxInitializeLowIoContext(&Context->LowIoContext, LOWIO_OP_IOCTL);
2528 Status = RxLowIoSubmit(Context, RxLowIoIoCtlShellCompletion);
2529 if (Status == STATUS_PENDING)
2530 {
2531 RxDereferenceAndDeleteRxContext_Real(Context);
2532 }
2533
2534 return Status;
2535 }
2536
2537 /*
2538 * @implemented
2539 */
2540 NTSTATUS
2541 NTAPI
2542 RxCommonDirectoryControl(
2543 PRX_CONTEXT Context)
2544 {
2545 PFCB Fcb;
2546 PFOBX Fobx;
2547 NTSTATUS Status;
2548 PIO_STACK_LOCATION Stack;
2549
2550 PAGED_CODE();
2551
2552 Fcb = (PFCB)Context->pFcb;
2553 Fobx = (PFOBX)Context->pFobx;
2554 Stack = Context->CurrentIrpSp;
2555 DPRINT("RxCommonDirectoryControl(%p) FOBX: %p, FCB: %p, Minor: %d\n", Context, Fobx, Fcb, Stack->MinorFunction);
2556
2557 /* Call the appropriate helper */
2558 if (Stack->MinorFunction == IRP_MN_QUERY_DIRECTORY)
2559 {
2560 Status = RxQueryDirectory(Context);
2561 }
2562 else if (Stack->MinorFunction == IRP_MN_NOTIFY_CHANGE_DIRECTORY)
2563 {
2564 Status = RxNotifyChangeDirectory(Context);
2565 if (Status == STATUS_PENDING)
2566 {
2567 RxDereferenceAndDeleteRxContext_Real(Context);
2568 }
2569 }
2570 else
2571 {
2572 Status = STATUS_INVALID_DEVICE_REQUEST;
2573 }
2574
2575 return Status;
2576 }
2577
2578 NTSTATUS
2579 NTAPI
2580 RxCommonDispatchProblem(
2581 PRX_CONTEXT Context)
2582 {
2583 UNIMPLEMENTED;
2584 return STATUS_NOT_IMPLEMENTED;
2585 }
2586
2587 NTSTATUS
2588 NTAPI
2589 RxCommonFileSystemControl(
2590 PRX_CONTEXT Context)
2591 {
2592 UNIMPLEMENTED;
2593 return STATUS_NOT_IMPLEMENTED;
2594 }
2595
2596 NTSTATUS
2597 NTAPI
2598 RxCommonFlushBuffers(
2599 PRX_CONTEXT Context)
2600 {
2601 UNIMPLEMENTED;
2602 return STATUS_NOT_IMPLEMENTED;
2603 }
2604
2605 NTSTATUS
2606 NTAPI
2607 RxCommonLockControl(
2608 PRX_CONTEXT Context)
2609 {
2610 UNIMPLEMENTED;
2611 return STATUS_NOT_IMPLEMENTED;
2612 }
2613
2614 NTSTATUS
2615 NTAPI
2616 RxCommonQueryEa(
2617 PRX_CONTEXT Context)
2618 {
2619 UNIMPLEMENTED;
2620 return STATUS_NOT_IMPLEMENTED;
2621 }
2622
2623 /*
2624 * @implemented
2625 */
2626 NTSTATUS
2627 NTAPI
2628 RxCommonQueryInformation(
2629 PRX_CONTEXT Context)
2630 {
2631 #define SET_SIZE_AND_QUERY(AlreadyConsummed, Function) \
2632 Context->Info.Length = Stack->Parameters.QueryFile.Length - (AlreadyConsummed); \
2633 Status = Function(Context, Add2Ptr(Buffer, AlreadyConsummed))
2634
2635 PFCB Fcb;
2636 PIRP Irp;
2637 PFOBX Fobx;
2638 BOOLEAN Locked;
2639 NTSTATUS Status;
2640 PIO_STACK_LOCATION Stack;
2641 FILE_INFORMATION_CLASS FileInfoClass;
2642
2643 PAGED_CODE();
2644
2645 Fcb = (PFCB)Context->pFcb;
2646 Fobx = (PFOBX)Context->pFobx;
2647 DPRINT("RxCommonQueryInformation(%p) FCB: %p, FOBX: %p\n", Context, Fcb, Fobx);
2648
2649 Irp = Context->CurrentIrp;
2650 Stack = Context->CurrentIrpSp;
2651 DPRINT("Buffer: %p, Length: %lx, Class: %ld\n", Irp->AssociatedIrp.SystemBuffer,
2652 Stack->Parameters.QueryFile.Length, Stack->Parameters.QueryFile.FileInformationClass);
2653
2654 Context->Info.Length = Stack->Parameters.QueryFile.Length;
2655 FileInfoClass = Stack->Parameters.QueryFile.FileInformationClass;
2656
2657 Locked = FALSE;
2658 _SEH2_TRY
2659 {
2660 PVOID Buffer;
2661
2662 /* Get a writable buffer */
2663 Buffer = RxMapSystemBuffer(Context);
2664 if (Buffer == NULL)
2665 {
2666 Status = STATUS_INSUFFICIENT_RESOURCES;
2667 _SEH2_LEAVE;
2668 }
2669 /* Zero it */
2670 RtlZeroMemory(Buffer, Context->Info.Length);
2671
2672 /* Validate file type */
2673 if (NodeType(Fcb) != RDBSS_NTC_STORAGE_TYPE_UNKNOWN)
2674 {
2675 if (NodeType(Fcb) < RDBSS_NTC_STORAGE_TYPE_DIRECTORY)
2676 {
2677 Status = STATUS_INVALID_PARAMETER;
2678 _SEH2_LEAVE;
2679 }
2680 else if (NodeType(Fcb) > RDBSS_NTC_STORAGE_TYPE_FILE)
2681 {
2682 if (NodeType(Fcb) == RDBSS_NTC_MAILSLOT)
2683 {
2684 Status = STATUS_NOT_IMPLEMENTED;
2685 }
2686 else
2687 {
2688 Status = STATUS_INVALID_PARAMETER;
2689 }
2690
2691 _SEH2_LEAVE;
2692 }
2693 }
2694
2695 /* Acquire the right lock */
2696 if (!BooleanFlagOn(Fcb->FcbState, FCB_STATE_PAGING_FILE) &&
2697 FileInfoClass != FileNameInformation)
2698 {
2699 if (FileInfoClass == FileCompressionInformation)
2700 {
2701 Status = RxAcquireExclusiveFcb(Context, Fcb);
2702 }
2703 else
2704 {
2705 Status = RxAcquireSharedFcb(Context, Fcb);
2706 }
2707
2708 if (Status == STATUS_LOCK_NOT_GRANTED)
2709 {
2710 Status = STATUS_PENDING;
2711 _SEH2_LEAVE;
2712 }
2713 else if (!NT_SUCCESS(Status))
2714 {
2715 _SEH2_LEAVE;
2716 }
2717
2718 Locked = TRUE;
2719 }
2720
2721 /* Dispatch to the right helper */
2722 switch (FileInfoClass)
2723 {
2724 case FileBasicInformation:
2725 Status = RxQueryBasicInfo(Context, Buffer);
2726 break;
2727
2728 case FileStandardInformation:
2729 Status = RxQueryStandardInfo(Context, Buffer);
2730 break;
2731
2732 case FileInternalInformation:
2733 Status = RxQueryInternalInfo(Context, Buffer);
2734 break;
2735
2736 case FileEaInformation:
2737 Status = RxQueryEaInfo(Context, Buffer);
2738 break;
2739
2740 case FileNameInformation:
2741 Status = RxQueryNameInfo(Context, Buffer);
2742 break;
2743
2744 case FileAllInformation:
2745 SET_SIZE_AND_QUERY(0, RxQueryBasicInfo);
2746 if (!NT_SUCCESS(Status))
2747 {
2748 break;
2749 }
2750
2751 SET_SIZE_AND_QUERY(sizeof(FILE_BASIC_INFORMATION), RxQueryStandardInfo);
2752 if (!NT_SUCCESS(Status))
2753 {
2754 break;
2755 }
2756
2757 SET_SIZE_AND_QUERY(sizeof(FILE_BASIC_INFORMATION) +
2758 sizeof(FILE_STANDARD_INFORMATION), RxQueryInternalInfo);
2759 if (!NT_SUCCESS(Status))
2760 {
2761 break;
2762 }
2763
2764 SET_SIZE_AND_QUERY(sizeof(FILE_BASIC_INFORMATION) +
2765 sizeof(FILE_STANDARD_INFORMATION) +
2766 sizeof(FILE_INTERNAL_INFORMATION), RxQueryEaInfo);
2767 if (!NT_SUCCESS(Status))
2768 {
2769 break;
2770 }
2771
2772 SET_SIZE_AND_QUERY(sizeof(FILE_BASIC_INFORMATION) +
2773 sizeof(FILE_STANDARD_INFORMATION) +
2774 sizeof(FILE_INTERNAL_INFORMATION) +
2775 sizeof(FILE_EA_INFORMATION), RxQueryPositionInfo);
2776 if (!NT_SUCCESS(Status))
2777 {
2778 break;
2779 }
2780
2781 SET_SIZE_AND_QUERY(sizeof(FILE_BASIC_INFORMATION) +
2782 sizeof(FILE_STANDARD_INFORMATION) +
2783 sizeof(FILE_INTERNAL_INFORMATION) +
2784 sizeof(FILE_EA_INFORMATION) +
2785 sizeof(FILE_POSITION_INFORMATION), RxQueryNameInfo);
2786 break;
2787
2788 case FileAlternateNameInformation:
2789 Status = RxQueryAlternateNameInfo(Context, Buffer);
2790 break;
2791
2792 case FilePipeInformation:
2793 case FilePipeLocalInformation:
2794 case FilePipeRemoteInformation:
2795 Status = RxQueryPipeInfo(Context, Buffer);
2796 break;
2797
2798 case FileCompressionInformation:
2799 Status = RxQueryCompressedInfo(Context, Buffer);
2800 break;
2801
2802 default:
2803 Context->IoStatusBlock.Status = RxpQueryInfoMiniRdr(Context, FileInfoClass, Buffer);
2804 Status = Context->IoStatusBlock.Status;
2805 break;
2806 }
2807
2808 if (Context->Info.Length < 0)
2809 {
2810 Status = STATUS_BUFFER_OVERFLOW;
2811 Context->Info.Length = Stack->Parameters.QueryFile.Length;
2812 }
2813
2814 Irp->IoStatus.Information = Stack->Parameters.QueryFile.Length - Context->Info.Length;
2815 }
2816 _SEH2_FINALLY
2817 {
2818 if (Locked)
2819 {
2820 RxReleaseFcb(Context, Fcb);
2821 }
2822 }
2823 _SEH2_END;
2824
2825 DPRINT("Status: %x\n", Status);
2826 return Status;
2827
2828 #undef SET_SIZE_AND_QUERY
2829 }
2830
2831 NTSTATUS
2832 NTAPI
2833 RxCommonQueryQuotaInformation(
2834 PRX_CONTEXT Context)
2835 {
2836 UNIMPLEMENTED;
2837 return STATUS_NOT_IMPLEMENTED;
2838 }
2839
2840 NTSTATUS
2841 NTAPI
2842 RxCommonQuerySecurity(
2843 PRX_CONTEXT Context)
2844 {
2845 UNIMPLEMENTED;
2846 return STATUS_NOT_IMPLEMENTED;
2847 }
2848
2849 /*
2850 * @implemented
2851 */
2852 NTSTATUS
2853 NTAPI
2854 RxCommonQueryVolumeInformation(
2855 PRX_CONTEXT Context)
2856 {
2857 PIRP Irp;
2858 PFCB Fcb;
2859 PFOBX Fobx;
2860 NTSTATUS Status;
2861 PIO_STACK_LOCATION Stack;
2862
2863 PAGED_CODE();
2864
2865 Fcb = (PFCB)Context->pFcb;
2866 Fobx = (PFOBX)Context->pFobx;
2867
2868 DPRINT("RxCommonQueryVolumeInformation(%p) FCB: %p, FOBX: %p\n", Context, Fcb, Fobx);
2869
2870 Irp = Context->CurrentIrp;
2871 Stack = Context->CurrentIrpSp;
2872 DPRINT("Length: %lx, Class: %lx, Buffer %p\n", Stack->Parameters.QueryVolume.Length,
2873 Stack->Parameters.QueryVolume.FsInformationClass, Irp->AssociatedIrp.SystemBuffer);
2874
2875 Context->Info.FsInformationClass = Stack->Parameters.QueryVolume.FsInformationClass;
2876 Context->Info.Buffer = Irp->AssociatedIrp.SystemBuffer;
2877 Context->Info.Length = Stack->Parameters.QueryVolume.Length;
2878
2879 /* Forward to mini-rdr */
2880 MINIRDR_CALL(Status, Context, Fcb->MRxDispatch, MRxQueryVolumeInfo, (Context));
2881
2882 /* Post request if mini-rdr asked to */
2883 if (Context->PostRequest)
2884 {
2885 Status = RxFsdPostRequest(Context);
2886 }
2887 else
2888 {
2889 Irp->IoStatus.Information = Stack->Parameters.QueryVolume.Length - Context->Info.Length;
2890 }
2891
2892 DPRINT("Status: %x\n", Status);
2893 return Status;
2894 }
2895
2896 NTSTATUS
2897 NTAPI
2898 RxCommonRead(
2899 PRX_CONTEXT RxContext)
2900 {
2901 PFCB Fcb;
2902 PIRP Irp;
2903 PFOBX Fobx;
2904 NTSTATUS Status;
2905 PNET_ROOT NetRoot;
2906 PVOID SystemBuffer;
2907 PFILE_OBJECT FileObject;
2908 LARGE_INTEGER ByteOffset;
2909 PIO_STACK_LOCATION Stack;
2910 PLOWIO_CONTEXT LowIoContext;
2911 PRDBSS_DEVICE_OBJECT RxDeviceObject;
2912 ULONG ReadLength, CapturedRxContextSerialNumber = RxContext->SerialNumber;
2913 BOOLEAN CanWait, PagingIo, NoCache, Sync, PostRequest, IsPipe, ReadCachingEnabled, ReadCachingDisabled, InFsp, OwnerSet;
2914
2915 PAGED_CODE();
2916
2917 Fcb = (PFCB)RxContext->pFcb;
2918 Fobx = (PFOBX)RxContext->pFobx;
2919 DPRINT("RxCommonRead(%p) FOBX: %p, FCB: %p\n", RxContext, Fobx, Fcb);
2920
2921 /* Get some parameters */
2922 Irp = RxContext->CurrentIrp;
2923 Stack = RxContext->CurrentIrpSp;
2924 CanWait = BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_WAIT);
2925 PagingIo = BooleanFlagOn(Irp->Flags, IRP_PAGING_IO);
2926 NoCache = BooleanFlagOn(Irp->Flags, IRP_NOCACHE);
2927 Sync = !BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_ASYNC_OPERATION);
2928 InFsp = BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_IN_FSP);
2929 ReadLength = Stack->Parameters.Read.Length;
2930 ByteOffset.QuadPart = Stack->Parameters.Read.ByteOffset.QuadPart;
2931 DPRINT("Reading: %lx@%I64x %s %s %s %s\n", ReadLength, ByteOffset.QuadPart,
2932 (CanWait ? "CW" : "!CW"), (PagingIo ? "PI" : "!PI"), (NoCache ? "NC" : "!NC"), (Sync ? "S" : "!S"));
2933
2934 RxItsTheSameContext();
2935
2936 Irp->IoStatus.Information = 0;
2937
2938 /* Should the read be loud - so far, it's just ignored on ReactOS:
2939 * s/DPRINT/DPRINT1/g will make it loud
2940 */
2941 LowIoContext = &RxContext->LowIoContext;
2942 CheckForLoudOperations(RxContext);
2943 if (BooleanFlagOn(LowIoContext->Flags, LOWIO_CONTEXT_FLAG_LOUDOPS))
2944 {
2945 DPRINT("LoudRead %I64x/%lx on %lx vdl/size/alloc %I64x/%I64x/%I64x\n",
2946 ByteOffset, ReadLength,
2947 Fcb, Fcb->Header.ValidDataLength, Fcb->Header.FileSize, Fcb->Header.AllocationSize);
2948 }
2949
2950 RxDeviceObject = RxContext->RxDeviceObject;
2951 /* Update stats */
2952 if (!BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_IN_FSP) && Fcb->CachedNetRootType == NET_ROOT_DISK)
2953 {
2954 InterlockedIncrement((volatile long *)&RxDeviceObject->ReadOperations);
2955
2956 if (ByteOffset.QuadPart != Fobx->Specific.DiskFile.PredictedReadOffset)
2957 {
2958 InterlockedIncrement((volatile long *)&RxDeviceObject->RandomReadOperations);
2959 }
2960 Fobx->Specific.DiskFile.PredictedReadOffset = ByteOffset.QuadPart + ReadLength;
2961
2962 if (PagingIo)
2963 {
2964 ExInterlockedAddLargeStatistic(&RxDeviceObject->PagingReadBytesRequested, ReadLength);
2965 }
2966 else if (NoCache)
2967 {
2968 ExInterlockedAddLargeStatistic(&RxDeviceObject->NonPagingReadBytesRequested, ReadLength);
2969 }
2970 else
2971 {
2972 ExInterlockedAddLargeStatistic(&RxDeviceObject->CacheReadBytesRequested, ReadLength);
2973 }
2974 }
2975
2976 /* A pagefile cannot be a pipe */
2977 IsPipe = Fcb->NetRoot->Type == NET_ROOT_PIPE;
2978 if (IsPipe && PagingIo)
2979 {
2980 return STATUS_INVALID_DEVICE_REQUEST;
2981 }
2982
2983 /* Null-length read is no-op */
2984 if (ReadLength == 0)
2985 {
2986 return STATUS_SUCCESS;
2987 }
2988
2989 /* Validate FCB type */
2990 if (NodeType(Fcb) != RDBSS_NTC_STORAGE_TYPE_FILE && NodeType(Fcb) != RDBSS_NTC_VOLUME_FCB)
2991 {
2992 return STATUS_INVALID_DEVICE_REQUEST;
2993 }
2994
2995 /* Init the lowio context for possible forward */
2996 RxInitializeLowIoContext(LowIoContext, LOWIO_OP_READ);
2997
2998 PostRequest = FALSE;
2999 ReadCachingDisabled = FALSE;
3000 OwnerSet = FALSE;
3001 ReadCachingEnabled = BooleanFlagOn(Fcb->FcbState, FCB_STATE_READCACHING_ENABLED);
3002 FileObject = Stack->FileObject;
3003 NetRoot = (PNET_ROOT)Fcb->pNetRoot;
3004 _SEH2_TRY
3005 {
3006 LONGLONG FileSize;
3007
3008 /* If no caching, make sure current Cc data have been flushed */
3009 if (!PagingIo && NoCache && !ReadCachingEnabled && FileObject->SectionObjectPointer != NULL)
3010 {
3011 Status = RxAcquireExclusiveFcb(RxContext, Fcb);
3012 if (Status == STATUS_LOCK_NOT_GRANTED)
3013 {
3014 PostRequest = TRUE;
3015 _SEH2_LEAVE;
3016 }
3017 else if (Status != STATUS_SUCCESS)
3018 {
3019 _SEH2_LEAVE;
3020 }
3021
3022 ExAcquireResourceSharedLite(Fcb->Header.PagingIoResource, TRUE);
3023 CcFlushCache(FileObject->SectionObjectPointer, &ByteOffset, ReadLength, &Irp->IoStatus);
3024 RxReleasePagingIoResource(RxContext, Fcb);
3025
3026 if (!NT_SUCCESS(Irp->IoStatus.Status))
3027 {
3028 _SEH2_LEAVE;
3029 }
3030
3031 RxAcquirePagingIoResource(RxContext, Fcb);
3032 RxReleasePagingIoResource(RxContext, Fcb);
3033 }
3034
3035 /* Acquire the appropriate lock */
3036 if (PagingIo && !ReadCachingEnabled)
3037 {
3038 ASSERT(!IsPipe);
3039
3040 if (!ExAcquireResourceSharedLite(Fcb->Header.PagingIoResource, CanWait))
3041 {
3042 PostRequest = TRUE;
3043 _SEH2_LEAVE;
3044 }
3045
3046 if (!CanWait)
3047 {
3048 LowIoContext->Resource = Fcb->Header.PagingIoResource;
3049 }
3050 }
3051 else
3052 {
3053 if (!ReadCachingEnabled)
3054 {
3055 if (!CanWait && NoCache)
3056 {
3057 Status = RxAcquireSharedFcbWaitForEx(RxContext, Fcb);
3058 if (Status == STATUS_LOCK_NOT_GRANTED)
3059 {
3060 DPRINT1("RdAsyLNG %x\n", RxContext);
3061 PostRequest = TRUE;
3062 _SEH2_LEAVE;
3063 }
3064 if (Status != STATUS_SUCCESS)
3065 {
3066 DPRINT1("RdAsyOthr %x\n", RxContext);
3067 _SEH2_LEAVE;
3068 }
3069
3070 if (RxIsFcbAcquiredShared(Fcb) <= 0xF000)
3071 {
3072 LowIoContext->Resource = Fcb->Header.Resource;
3073 }
3074 else
3075 {
3076 PostRequest = TRUE;
3077 _SEH2_LEAVE;
3078 }
3079 }
3080 else
3081 {
3082 Status = RxAcquireSharedFcb(RxContext, Fcb);
3083 if (Status == STATUS_LOCK_NOT_GRANTED)
3084 {
3085 PostRequest = TRUE;
3086 _SEH2_LEAVE;
3087 }
3088 else if (Status != STATUS_SUCCESS)
3089 {
3090 _SEH2_LEAVE;
3091 }
3092 }
3093 }
3094 }
3095
3096 RxItsTheSameContext();
3097
3098 ReadCachingDisabled = (ReadCachingEnabled == FALSE);
3099 if (IsPipe)
3100 {
3101 UNIMPLEMENTED;
3102 }
3103
3104 RxGetFileSizeWithLock(Fcb, &FileSize);
3105
3106 /* Make sure FLOCK doesn't conflict */
3107 if (!PagingIo)
3108 {
3109 if (!FsRtlCheckLockForReadAccess(&Fcb->Specific.Fcb.FileLock, Irp))
3110 {
3111 Status = STATUS_FILE_LOCK_CONFLICT;
3112 _SEH2_LEAVE;
3113 }
3114 }
3115
3116 /* Validate byteoffset vs length */
3117 if (BooleanFlagOn(Fcb->FcbState, FCB_STATE_READCACHING_ENABLED))
3118 {
3119 if (ByteOffset.QuadPart >= FileSize)
3120 {
3121 Status = STATUS_END_OF_FILE;
3122 _SEH2_LEAVE;
3123 }
3124
3125 if (ReadLength > FileSize - ByteOffset.QuadPart)
3126 {
3127 ReadLength = FileSize - ByteOffset.QuadPart;
3128 }
3129 }
3130
3131 /* Read with Cc! */
3132 if (!PagingIo && !NoCache && ReadCachingEnabled &&
3133 !BooleanFlagOn(Fobx->pSrvOpen->Flags, SRVOPEN_FLAG_DONTUSE_READ_CACHING))
3134 {
3135 /* File was not cached yet, do it */
3136 if (FileObject->PrivateCacheMap == NULL)
3137 {
3138 if (BooleanFlagOn(FileObject->Flags, FO_CLEANUP_COMPLETE))
3139 {
3140 Status = STATUS_FILE_CLOSED;
3141 _SEH2_LEAVE;
3142 }
3143
3144 RxAdjustAllocationSizeforCC(Fcb);
3145
3146 CcInitializeCacheMap(FileObject, (PCC_FILE_SIZES)&Fcb->Header.AllocationSize,
3147 FALSE, &RxData.CacheManagerCallbacks, Fcb);
3148
3149 if (BooleanFlagOn(Fcb->MRxDispatch->MRxFlags, RDBSS_NO_DEFERRED_CACHE_READAHEAD))
3150 {
3151 CcSetAdditionalCacheAttributes(FileObject, FALSE, FALSE);
3152 }
3153 else
3154 {
3155 CcSetAdditionalCacheAttributes(FileObject, TRUE, FALSE);
3156 SetFlag(Fcb->FcbState, FCB_STATE_READAHEAD_DEFERRED);
3157 }
3158
3159 CcSetReadAheadGranularity(FileObject, NetRoot->DiskParameters.ReadAheadGranularity);
3160 }
3161
3162 /* This should never happen - fix your RDR */
3163 if (BooleanFlagOn(RxContext->MinorFunction, IRP_MN_MDL))
3164 {
3165 ASSERT(FALSE);
3166 ASSERT(CanWait);
3167
3168 CcMdlRead(FileObject, &ByteOffset, ReadLength, &Irp->MdlAddress, &Irp->IoStatus);
3169 Status = Irp->IoStatus.Status;
3170 ASSERT(NT_SUCCESS(Status));
3171 }
3172 else
3173 {
3174 /* Map buffer */
3175 SystemBuffer = RxNewMapUserBuffer(RxContext);
3176 if (SystemBuffer == NULL)
3177 {
3178 Status = STATUS_INSUFFICIENT_RESOURCES;
3179 _SEH2_LEAVE;
3180 }
3181
3182 SetFlag(Fcb->FcbState, FCB_STATE_READCACHING_ENABLED);
3183
3184 RxItsTheSameContext();
3185
3186 /* Perform the read */
3187 if (!CcCopyRead(FileObject, &ByteOffset, ReadLength, CanWait, SystemBuffer, &Irp->IoStatus))
3188 {
3189 if (!ReadCachingEnabled)
3190 {
3191 ClearFlag(Fcb->FcbState, FCB_STATE_READCACHING_ENABLED);
3192 }
3193
3194 RxItsTheSameContext();
3195
3196 PostRequest = TRUE;
3197 _SEH2_LEAVE;
3198 }
3199
3200 if (!ReadCachingEnabled)
3201 {
3202 ClearFlag(Fcb->FcbState, FCB_STATE_READCACHING_ENABLED);
3203 }
3204
3205 Status = Irp->IoStatus.Status;
3206 ASSERT(NT_SUCCESS(Status));
3207 }
3208 }
3209 else
3210 {
3211 /* Validate the reading */
3212 if (FileObject->PrivateCacheMap != NULL && BooleanFlagOn(Fcb->FcbState, FCB_STATE_READAHEAD_DEFERRED) &&
3213 ByteOffset.QuadPart >= 4096)
3214 {
3215 CcSetAdditionalCacheAttributes(FileObject, FALSE, FALSE);
3216 ClearFlag(Fcb->FcbState, FCB_STATE_READAHEAD_DEFERRED);
3217 }
3218
3219 /* If it's consistent, forward to mini-rdr */
3220 if (Fcb->CachedNetRootType != NET_ROOT_DISK || BooleanFlagOn(Fcb->FcbState, FCB_STATE_READAHEAD_DEFERRED) ||
3221 ByteOffset.QuadPart < Fcb->Header.ValidDataLength.QuadPart)
3222 {
3223 LowIoContext->ParamsFor.ReadWrite.ByteCount = ReadLength;
3224 LowIoContext->ParamsFor.ReadWrite.ByteOffset = ByteOffset.QuadPart;
3225
3226 RxItsTheSameContext();
3227
3228 if (InFsp && ReadCachingDisabled)
3229 {
3230 ExSetResourceOwnerPointer((PagingIo ? Fcb->Header.PagingIoResource : Fcb->Header.Resource),
3231 (PVOID)((ULONG_PTR)RxContext | 3));
3232 OwnerSet = TRUE;
3233 }
3234
3235 Status = RxLowIoReadShell(RxContext);
3236
3237 RxItsTheSameContext();
3238 }
3239 else
3240 {
3241 if (ByteOffset.QuadPart > FileSize)
3242 {
3243 ReadLength = 0;
3244 Irp->IoStatus.Information = ReadLength;
3245 _SEH2_LEAVE;
3246 }
3247
3248 if (ByteOffset.QuadPart + ReadLength > FileSize)
3249 {
3250 ReadLength = FileSize - ByteOffset.QuadPart;
3251 }
3252
3253 SystemBuffer = RxNewMapUserBuffer(RxContext);
3254 RtlZeroMemory(SystemBuffer, ReadLength);
3255 Irp->IoStatus.Information = ReadLength;
3256 }
3257 }
3258 }
3259 _SEH2_FINALLY
3260 {
3261 RxItsTheSameContext();
3262
3263 /* Post if required */
3264 if (PostRequest)
3265 {
3266 InterlockedIncrement((volatile long *)&RxContext->ReferenceCount);
3267 Status = RxFsdPostRequest(RxContext);
3268 }
3269 else
3270 {
3271 /* Update FO in case of sync IO */
3272 if (!IsPipe && !PagingIo)
3273 {
3274 if (BooleanFlagOn(FileObject->Flags, FO_SYNCHRONOUS_IO))
3275 {
3276 FileObject->CurrentByteOffset.QuadPart = ByteOffset.QuadPart + Irp->IoStatus.Information;
3277 }
3278 }
3279 }
3280
3281 /* Set FastIo if read was a success */
3282 if (NT_SUCCESS(Status) && Status != STATUS_PENDING)
3283 {
3284 if (!IsPipe && !PagingIo)
3285 {
3286 SetFlag(FileObject->Flags, FO_FILE_FAST_IO_READ);
3287 }
3288 }
3289
3290 /* In case we're done (not expected any further processing */
3291 if (_SEH2_AbnormalTermination() || Status != STATUS_PENDING || PostRequest)
3292 {
3293 /* Release everything that can be */
3294 if (ReadCachingDisabled)
3295 {
3296 if (PagingIo)
3297 {
3298 if (OwnerSet)
3299 {
3300 RxReleasePagingIoResourceForThread(RxContext, Fcb, LowIoContext->ResourceThreadId);
3301 }
3302 else
3303 {
3304 RxReleasePagingIoResource(RxContext, Fcb);
3305 }
3306 }
3307 else
3308 {
3309 if (OwnerSet)
3310 {
3311 RxReleaseFcbForThread(RxContext, Fcb, LowIoContext->ResourceThreadId);
3312 }
3313 else
3314 {
3315 RxReleaseFcb(RxContext, Fcb);
3316 }
3317 }
3318 }
3319
3320 /* Dereference/Delete context */
3321 if (PostRequest)
3322 {
3323 RxDereferenceAndDeleteRxContext(RxContext);
3324 }
3325 else
3326 {
3327 if (BooleanFlagOn(RxContext->FlagsForLowIo, RXCONTEXT_FLAG4LOWIO_PIPE_SYNC_OPERATION))
3328 {
3329 RxResumeBlockedOperations_Serially(RxContext, &Fobx->Specific.NamedPipe.ReadSerializationQueue);
3330 }
3331 }
3332
3333 /* We cannot return more than asked */
3334 if (Status == STATUS_SUCCESS)
3335 {
3336 ASSERT(Irp->IoStatus.Information <= Stack->Parameters.Read.Length);
3337 }
3338 }
3339 else
3340 {
3341 ASSERT(!Sync);
3342
3343 RxDereferenceAndDeleteRxContext(RxContext);
3344 }
3345 }
3346 _SEH2_END;
3347
3348 return Status;
3349 }
3350
3351 NTSTATUS
3352 NTAPI
3353 RxCommonSetEa(
3354 PRX_CONTEXT Context)
3355 {
3356 UNIMPLEMENTED;
3357 return STATUS_NOT_IMPLEMENTED;
3358 }
3359
3360 NTSTATUS
3361 NTAPI
3362 RxCommonSetInformation(
3363 PRX_CONTEXT Context)
3364 {
3365 UNIMPLEMENTED;
3366 return STATUS_NOT_IMPLEMENTED;
3367 }
3368
3369 NTSTATUS
3370 NTAPI
3371 RxCommonSetQuotaInformation(
3372 PRX_CONTEXT Context)
3373 {
3374 UNIMPLEMENTED;
3375 return STATUS_NOT_IMPLEMENTED;
3376 }
3377
3378 NTSTATUS
3379 NTAPI
3380 RxCommonSetSecurity(
3381 PRX_CONTEXT Context)
3382 {
3383 UNIMPLEMENTED;
3384 return STATUS_NOT_IMPLEMENTED;
3385 }
3386
3387 NTSTATUS
3388 NTAPI
3389 RxCommonSetVolumeInformation(
3390 PRX_CONTEXT Context)
3391 {
3392 UNIMPLEMENTED;
3393 return STATUS_NOT_IMPLEMENTED;
3394 }
3395
3396 NTSTATUS
3397 NTAPI
3398 RxCommonUnimplemented(
3399 PRX_CONTEXT Context)
3400 {
3401 UNIMPLEMENTED;
3402 return STATUS_NOT_IMPLEMENTED;
3403 }
3404
3405 NTSTATUS
3406 NTAPI
3407 RxCommonWrite(
3408 PRX_CONTEXT Context)
3409 {
3410 UNIMPLEMENTED;
3411 return STATUS_NOT_IMPLEMENTED;
3412 }
3413
3414 NTSTATUS
3415 NTAPI
3416 RxCompleteMdl(
3417 IN PRX_CONTEXT RxContext)
3418 {
3419 PAGED_CODE();
3420
3421 UNIMPLEMENTED;
3422 return STATUS_NOT_IMPLEMENTED;
3423 }
3424
3425 /*
3426 * @implemented
3427 */
3428 VOID
3429 RxCopyCreateParameters(
3430 IN PRX_CONTEXT RxContext)
3431 {
3432 PIRP Irp;
3433 PVOID DfsContext;
3434 PFILE_OBJECT FileObject;
3435 PIO_STACK_LOCATION Stack;
3436 PDFS_NAME_CONTEXT DfsNameContext;
3437 PIO_SECURITY_CONTEXT SecurityContext;
3438
3439 Irp = RxContext->CurrentIrp;
3440 Stack = RxContext->CurrentIrpSp;
3441 FileObject = Stack->FileObject;
3442 SecurityContext = Stack->Parameters.Create.SecurityContext;
3443
3444 RxContext->Create.NtCreateParameters.SecurityContext = SecurityContext;
3445 if (SecurityContext->AccessState != NULL && SecurityContext->AccessState->SecurityDescriptor != NULL)
3446 {
3447 RxContext->Create.SdLength = RtlLengthSecurityDescriptor(SecurityContext->AccessState->SecurityDescriptor);
3448 DPRINT("SD Ctxt: %p, Length: %lx\n", RxContext->Create.NtCreateParameters.SecurityContext,
3449 RxContext->Create.SdLength);
3450 }
3451 if (SecurityContext->SecurityQos != NULL)
3452 {
3453 RxContext->Create.NtCreateParameters.ImpersonationLevel = SecurityContext->SecurityQos->ImpersonationLevel;
3454 }
3455 else
3456 {
3457 RxContext->Create.NtCreateParameters.ImpersonationLevel = SecurityImpersonation;
3458 }
3459 RxContext->Create.NtCreateParameters.DesiredAccess = SecurityContext->DesiredAccess;
3460
3461 RxContext->Create.NtCreateParameters.AllocationSize.QuadPart = Irp->Overlay.AllocationSize.QuadPart;
3462 RxContext->Create.NtCreateParameters.FileAttributes = Stack->Parameters.Create.FileAttributes & FILE_ATTRIBUTE_VALID_FLAGS;
3463 RxContext->Create.NtCreateParameters.ShareAccess = Stack->Parameters.Create.ShareAccess & FILE_SHARE_VALID_FLAGS;
3464 RxContext->Create.NtCreateParameters.Disposition = (Stack->Parameters.Create.Options >> 24) & 0x000000FF;
3465 RxContext->Create.NtCreateParameters.CreateOptions = Stack->Parameters.Create.Options & 0xFFFFFF;
3466
3467 DfsContext = FileObject->FsContext2;
3468 DfsNameContext = FileObject->FsContext;
3469 RxContext->Create.NtCreateParameters.DfsContext = DfsContext;
3470 RxContext->Create.NtCreateParameters.DfsNameContext = DfsNameContext;
3471 ASSERT(DfsContext == NULL || DfsContext == UIntToPtr(DFS_OPEN_CONTEXT) ||
3472 DfsContext == UIntToPtr(DFS_DOWNLEVEL_OPEN_CONTEXT) ||
3473 DfsContext == UIntToPtr(DFS_CSCAGENT_NAME_CONTEXT) ||
3474 DfsContext == UIntToPtr(DFS_USER_NAME_CONTEXT));
3475 ASSERT(DfsNameContext == NULL || DfsNameContext->NameContextType == DFS_OPEN_CONTEXT ||
3476 DfsNameContext->NameContextType == DFS_DOWNLEVEL_OPEN_CONTEXT ||
3477 DfsNameContext->NameContextType == DFS_CSCAGENT_NAME_CONTEXT ||
3478 DfsNameContext->NameContextType == DFS_USER_NAME_CONTEXT);
3479 FileObject->FsContext2 = NULL;
3480 FileObject->FsContext = NULL;
3481
3482 RxContext->pFcb = NULL;
3483 RxContext->Create.ReturnedCreateInformation = 0;
3484
3485 /* if we stripped last \, it has to be a directory! */
3486 if (BooleanFlagOn(RxContext->Create.Flags, RX_CONTEXT_CREATE_FLAG_STRIPPED_TRAILING_BACKSLASH))
3487 {
3488 SetFlag(RxContext->Create.NtCreateParameters.CreateOptions, FILE_DIRECTORY_FILE);
3489 }
3490
3491 RxContext->Create.EaLength = Stack->Parameters.Create.EaLength;
3492 if (RxContext->Create.EaLength == 0)
3493 {
3494 RxContext->Create.EaBuffer = NULL;
3495 }
3496 else
3497 {
3498 RxContext->Create.EaBuffer = Irp->AssociatedIrp.SystemBuffer;
3499 DPRINT("EA Buffer: %p, Length: %lx\n", Irp->AssociatedIrp.SystemBuffer, RxContext->Create.EaLength);
3500 }
3501 }
3502
3503 NTSTATUS
3504 RxCreateFromNetRoot(
3505 PRX_CONTEXT Context,
3506 PUNICODE_STRING NetRootName)
3507 {
3508 PFCB Fcb;
3509 NTSTATUS Status;
3510 PNET_ROOT NetRoot;
3511 PFILE_OBJECT FileObject;
3512 PIO_STACK_LOCATION Stack;
3513 ACCESS_MASK DesiredAccess;
3514 USHORT DesiredShareAccess;
3515
3516 PAGED_CODE();
3517
3518 /* Validate that the context is consistent */
3519 if (Context->Create.pNetRoot == NULL)
3520 {
3521 return STATUS_BAD_NETWORK_PATH;
3522 }
3523
3524 NetRoot = (PNET_ROOT)Context->Create.pNetRoot;
3525 if (Context->RxDeviceObject != NetRoot->pSrvCall->RxDeviceObject)
3526 {
3527 return STATUS_BAD_NETWORK_PATH;
3528 }
3529
3530 if (Context->Create.NtCreateParameters.DfsContext == UIntToPtr(DFS_OPEN_CONTEXT) &&
3531 !BooleanFlagOn(NetRoot->pSrvCall->Flags, SRVCALL_FLAG_DFS_AWARE_SERVER))
3532 {
3533 return STATUS_DFS_UNAVAILABLE;
3534 }
3535
3536 if (Context->Create.NtCreateParameters.DfsContext == UIntToPtr(DFS_DOWNLEVEL_OPEN_CONTEXT) &&
3537 BooleanFlagOn(NetRoot->Flags, NETROOT_FLAG_DFS_AWARE_NETROOT))
3538 {
3539 return STATUS_OBJECT_TYPE_MISMATCH;
3540 }
3541
3542 Stack = Context->CurrentIrpSp;
3543 DesiredShareAccess = Stack->Parameters.Create.ShareAccess & FILE_SHARE_VALID_FLAGS;
3544 if (NetRoot->Type == NET_ROOT_PRINT)
3545 {
3546 DesiredShareAccess = FILE_SHARE_VALID_FLAGS;
3547 }
3548
3549 DesiredAccess = Stack->Parameters.Create.SecurityContext->DesiredAccess & FILE_ALL_ACCESS;
3550
3551 /* We don't support renaming yet */
3552 if (BooleanFlagOn(Stack->Flags, SL_OPEN_TARGET_DIRECTORY))
3553 {
3554 UNIMPLEMENTED;
3555 return STATUS_NOT_IMPLEMENTED;
3556 }
3557
3558 /* Try to find (or create) the FCB for the file */
3559 Status = RxFindOrCreateFcb(Context, NetRootName);
3560 Fcb = (PFCB)Context->pFcb;
3561 if (Fcb == NULL)
3562 {
3563 ASSERT(!NT_SUCCESS(Status));
3564 }
3565 if (!NT_SUCCESS(Status) || Fcb == NULL)
3566 {
3567 return Status;
3568 }
3569
3570 if (BooleanFlagOn(Context->Flags, RX_CONTEXT_FLAG_CREATE_MAILSLOT))
3571 {
3572 Fcb->Header.NodeTypeCode = RDBSS_NTC_MAILSLOT;
3573 }
3574 else
3575 {
3576 Status = STATUS_MORE_PROCESSING_REQUIRED;
3577 }
3578
3579 /* If finding FCB worked (mailslot case), mark the FCB as good and quit */
3580 if (NT_SUCCESS(Status))
3581 {
3582 RxTransitionNetFcb(Fcb, Condition_Good);
3583 DPRINT("Transitioning FCB %lx Condition %lx\n", Fcb, Fcb->Condition);
3584 ++Fcb->OpenCount;
3585 RxSetupNetFileObject(Context);
3586 return STATUS_SUCCESS;
3587 }
3588
3589 /* Not mailslot! */
3590 FileObject = Stack->FileObject;
3591 /* Check SA for conflict */
3592 if (Fcb->OpenCount > 0)
3593 {
3594 Status = RxCheckShareAccess(DesiredAccess, DesiredShareAccess, FileObject,
3595 &Fcb->ShareAccess, FALSE, "early check per useropens", "EarlyPerUO");
3596 if (!NT_SUCCESS(Status))
3597 {
3598 RxDereferenceNetFcb(Fcb);
3599 return Status;
3600 }
3601 }
3602
3603 if (BooleanFlagOn(Context->Create.NtCreateParameters.CreateOptions, FILE_DELETE_ON_CLOSE) &&
3604 !BooleanFlagOn(Context->Create.NtCreateParameters.DesiredAccess, ~SYNCHRONIZE))
3605 {
3606 UNIMPLEMENTED;
3607 }
3608
3609 _SEH2_TRY
3610 {
3611 /* Find a SRV_OPEN that suits the opening */
3612 Status = RxCollapseOrCreateSrvOpen(Context);
3613 if (Status == STATUS_SUCCESS)
3614 {
3615 PFOBX Fobx;
3616 PSRV_OPEN SrvOpen;
3617
3618 SrvOpen = (PSRV_OPEN)Context->pRelevantSrvOpen;
3619 Fobx = (PFOBX)Context->pFobx;
3620 /* There are already opens, check for conflict */
3621 if (Fcb->OpenCount != 0)
3622 {
3623 if (!NT_SUCCESS(RxCheckShareAccess(DesiredAccess, DesiredShareAccess,
3624 FileObject, &Fcb->ShareAccess,
3625 FALSE, "second check per useropens",
3626 "2ndAccPerUO")))
3627 {
3628 ++SrvOpen->UncleanFobxCount;
3629 RxDereferenceNetFobx(Fobx, LHS_LockNotHeld);
3630
3631 _SEH2_LEAVE;
3632 }
3633 }
3634 else
3635 {
3636 if (NetRoot->Type != NET_ROOT_PIPE)
3637 {
3638 RxSetShareAccess(DesiredAccess, DesiredShareAccess, FileObject,
3639 &Fcb->ShareAccess, "initial shareaccess setup", "InitShrAcc");
3640 }
3641 }
3642
3643 RxSetupNetFileObject(Context);
3644
3645 /* No conflict? Set up SA */
3646 if (Fcb->OpenCount != 0 && NetRoot->Type != NET_ROOT_PIPE)
3647 {
3648 RxUpdateShareAccess(FileObject, &Fcb->ShareAccess, "update share access", "UpdShrAcc");
3649 }
3650
3651 ++Fcb->UncleanCount;
3652 if (BooleanFlagOn(FileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING))
3653 {
3654 ++Fcb->UncachedUncleanCount;
3655 }
3656
3657 if (SrvOpen->UncleanFobxCount == 0 && Fcb->UncleanCount == 1 &&
3658 !BooleanFlagOn(SrvOpen->Flags, SRVOPEN_FLAG_NO_BUFFERING_STATE_CHANGE))
3659 {
3660 RxChangeBufferingState(SrvOpen, NULL, FALSE);
3661 }
3662
3663 /* No pending close, we're active */
3664 ClearFlag(Fcb->FcbState, FCB_STATE_DELAY_CLOSE);
3665
3666 ++Fcb->OpenCount;
3667 ++SrvOpen->UncleanFobxCount;
3668 ++SrvOpen->OpenCount;
3669 SrvOpen->ulFileSizeVersion = Fcb->ulFileSizeVersion;
3670
3671 if (BooleanFlagOn(Stack->Parameters.Create.Options, FILE_NO_INTERMEDIATE_BUFFERING))
3672 {
3673 SetFlag(SrvOpen->Flags, SRVOPEN_FLAG_DONTUSE_READ_CACHING);
3674 SetFlag(SrvOpen->Flags, SRVOPEN_FLAG_DONTUSE_WRITE_CACHING);
3675
3676 ClearFlag(Fcb->FcbState, FCB_STATE_WRITECACHING_ENABLED);
3677 ClearFlag(Fcb->FcbState, FCB_STATE_READCACHING_ENABLED);
3678
3679 RxPurgeFcbInSystemCache(Fcb, NULL, 0, TRUE, TRUE);
3680 }
3681
3682 /* Now, update SA for the SRV_OPEN */
3683 RxUpdateShareAccessPerSrvOpens(SrvOpen);
3684
3685 if (BooleanFlagOn(Stack->Parameters.Create.Options, FILE_DELETE_ON_CLOSE))
3686 {
3687 SetFlag(Fobx->Flags, FOBX_FLAG_DELETE_ON_CLOSE);
3688 }
3689
3690 /* Update the FOBX info */
3691 if (Fobx != NULL)
3692 {
3693 if (Context->Create.pNetRoot->Type == NET_ROOT_PIPE)
3694 {
3695 SetFlag(FileObject->Flags, FO_NAMED_PIPE);
3696 }
3697
3698 if (Context->Create.pNetRoot->Type == NET_ROOT_PRINT ||
3699 Context->Create.pNetRoot->Type == NET_ROOT_PIPE)
3700 {
3701 Fobx->PipeHandleInformation = &Fobx->Specific.NamedPipe.PipeHandleInformation;
3702
3703 Fobx->Specific.NamedPipe.CollectDataTime.QuadPart = 0;
3704 Fobx->Specific.NamedPipe.CollectDataSize = Context->Create.pNetRoot->NamedPipeParameters.DataCollectionSize;
3705
3706 Fobx->Specific.NamedPipe.PipeHandleInformation.TypeOfPipe = Context->Create.PipeType;
3707 Fobx->Specific.NamedPipe.PipeHandleInformation.ReadMode = Context->Create.PipeReadMode;
3708 Fobx->Specific.NamedPipe.PipeHandleInformation.CompletionMode = Context->Create.PipeCompletionMode;
3709
3710 InitializeListHead(&Fobx->Specific.NamedPipe.ReadSerializationQueue);
3711 InitializeListHead(&Fobx->Specific.NamedPipe.WriteSerializationQueue);
3712 }
3713 }
3714
3715 Status = STATUS_SUCCESS;
3716 }
3717 }
3718 _SEH2_FINALLY
3719 {
3720 if (Fcb->OpenCount == 0)
3721 {
3722 if (Context->Create.FcbAcquired)
3723 {
3724 Context->Create.FcbAcquired = (RxDereferenceAndFinalizeNetFcb(Fcb,
3725 Context,
3726 FALSE,
3727 FALSE) == 0);
3728 if (!Context->Create.FcbAcquired)
3729 {
3730 RxTrackerUpdateHistory(Context, NULL, TRACKER_FCB_FREE, __LINE__, __FILE__, 0);
3731 }
3732 }
3733 }
3734 else
3735 {
3736 RxDereferenceNetFcb(Fcb);
3737 }
3738 }
3739 _SEH2_END;
3740
3741 return Status;
3742 }
3743
3744 /*
3745 * @implemented
3746 */
3747 NTSTATUS
3748 RxCreateTreeConnect(
3749 IN PRX_CONTEXT RxContext)
3750 {
3751 NTSTATUS Status;
3752 PV_NET_ROOT VNetRoot;
3753 PFILE_OBJECT FileObject;
3754 PIO_STACK_LOCATION Stack;
3755 NET_ROOT_TYPE NetRootType;
3756 UNICODE_STRING CanonicalName, RemainingName;
3757
3758 PAGED_CODE();
3759
3760 Stack = RxContext->CurrentIrpSp;
3761 FileObject = Stack->FileObject;
3762
3763 RtlInitEmptyUnicodeString(&CanonicalName, NULL, 0);
3764 /* As long as we don't know connection type, mark it wild */
3765 NetRootType = NET_ROOT_WILD;
3766 /* Get the type by parsing the name */
3767 Status = RxFirstCanonicalize(RxContext, &FileObject->FileName, &CanonicalName, &NetRootType);
3768 if (!NT_SUCCESS(Status))
3769 {
3770 return Status;
3771 }
3772
3773 RxContext->Create.ThisIsATreeConnectOpen = TRUE;
3774 RxContext->Create.TreeConnectOpenDeferred = FALSE;
3775 RtlInitEmptyUnicodeString(&RxContext->Create.TransportName, NULL, 0);
3776 RtlInitEmptyUnicodeString(&RxContext->Create.UserName, NULL, 0);
3777 RtlInitEmptyUnicodeString(&RxContext->Create.Password, NULL, 0);
3778 RtlInitEmptyUnicodeString(&RxContext->Create.UserDomainName, NULL, 0);
3779
3780 /* We don't handle EA - they come from DFS, don't care */
3781 if (Stack->Parameters.Create.EaLength > 0)
3782 {
3783 UNIMPLEMENTED;
3784 }
3785
3786 /* Mount if required */
3787 Status = RxFindOrConstructVirtualNetRoot(RxContext, &CanonicalName, NetRootType, &RemainingName);
3788 if (Status == STATUS_NETWORK_CREDENTIAL_CONFLICT)
3789 {
3790 RxScavengeVNetRoots(RxContext->RxDeviceObject);
3791 Status = RxFindOrConstructVirtualNetRoot(RxContext, &CanonicalName, NetRootType, &RemainingName);
3792 }
3793
3794 if (!NT_SUCCESS(Status))
3795 {
3796 return Status;
3797 }
3798
3799 /* Validate the rest of the name with mini-rdr */
3800 if (RemainingName.Length > 0)
3801 {
3802 MINIRDR_CALL(Status, RxContext,
3803 RxContext->Create.pNetRoot->pSrvCall->RxDeviceObject->Dispatch,
3804 MRxIsValidDirectory, (RxContext, &RemainingName));
3805 }
3806
3807 if (!NT_SUCCESS(Status))
3808 {
3809 return Status;
3810 }
3811
3812 VNetRoot = (PV_NET_ROOT)RxContext->Create.pVNetRoot;
3813 RxReferenceVNetRoot(VNetRoot);
3814 if (InterlockedCompareExchange(&VNetRoot->AdditionalReferenceForDeleteFsctlTaken, 1, 0) != 0)
3815 {
3816 RxDereferenceVNetRoot(VNetRoot, LHS_LockNotHeld);
3817 }
3818
3819 FileObject->FsContext = &RxDeviceFCB;
3820 FileObject->FsContext2 = VNetRoot;
3821
3822 VNetRoot->ConstructionStatus = STATUS_SUCCESS;
3823 ++VNetRoot->NumberOfOpens;
3824
3825 /* Create is over - clear context */
3826 RxContext->Create.pSrvCall = NULL;
3827 RxContext->Create.pNetRoot = NULL;
3828 RxContext->Create.pVNetRoot = NULL;
3829
3830 return Status;
3831 }
3832
3833 VOID
3834 NTAPI
3835 RxDebugControlCommand(
3836 _In_ PSTR ControlString)
3837 {
3838 UNIMPLEMENTED;
3839 }
3840
3841 NTSTATUS
3842 NTAPI
3843 RxDriverEntry(
3844 IN PDRIVER_OBJECT DriverObject,
3845 IN PUNICODE_STRING RegistryPath)
3846 {
3847 NTSTATUS Status;
3848 USHORT i, State = 0;
3849
3850 DPRINT("RxDriverEntry(%p, %p)\n", DriverObject, RegistryPath);
3851
3852 _SEH2_TRY
3853 {
3854 RxCheckFcbStructuresForAlignment();
3855
3856 RtlZeroMemory(&RxData, sizeof(RxData));
3857 RxData.NodeTypeCode = RDBSS_NTC_DATA_HEADER;
3858 RxData.NodeByteSize = sizeof(RxData);
3859 RxData.DriverObject = DriverObject;
3860
3861 RtlZeroMemory(&RxDeviceFCB, sizeof(RxDeviceFCB));
3862 RxDeviceFCB.spacer.NodeTypeCode = RDBSS_NTC_DEVICE_FCB;
3863 RxDeviceFCB.spacer.NodeByteSize = sizeof(RxDeviceFCB);
3864
3865 KeInitializeSpinLock(&RxStrucSupSpinLock);
3866 RxExports.pRxStrucSupSpinLock = &RxStrucSupSpinLock;
3867
3868 RxInitializeDebugSupport();
3869
3870 RxFileSystemDeviceObject = (PRDBSS_DEVICE_OBJECT)&RxSpaceForTheWrappersDeviceObject;
3871 RtlZeroMemory(&RxSpaceForTheWrappersDeviceObject, sizeof(RxSpaceForTheWrappersDeviceObject));
3872
3873 RxInitializeLog();
3874 State = 2;
3875
3876 RxGetRegistryParameters(RegistryPath);
3877 RxReadRegistryParameters();