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