[RXCE]
[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 NTSTATUS
796 RxCancelNotifyChangeDirectoryRequestsForVNetRoot(
797 PV_NET_ROOT VNetRoot,
798 BOOLEAN ForceFilesClosed)
799 {
800 UNIMPLEMENTED;
801 return STATUS_NOT_IMPLEMENTED;
802 }
803
804 VOID
805 NTAPI
806 RxCancelRoutine(
807 PDEVICE_OBJECT DeviceObject,
808 PIRP Irp)
809 {
810 UNIMPLEMENTED;
811 }
812
813 /*
814 * @implemented
815 */
816 NTSTATUS
817 RxCanonicalizeFileNameByServerSpecs(
818 PRX_CONTEXT RxContext,
819 PUNICODE_STRING NetRootName)
820 {
821 USHORT NextChar, CurChar;
822 USHORT MaxChars;
823
824 PAGED_CODE();
825
826 /* Validate file name is not empty */
827 MaxChars = NetRootName->Length / sizeof(WCHAR);
828 if (MaxChars == 0)
829 {
830 return STATUS_MORE_PROCESSING_REQUIRED;
831 }
832
833 /* Validate name is correct */
834 for (NextChar = 0, CurChar = 0; CurChar + 1 < MaxChars; NextChar = CurChar + 1)
835 {
836 USHORT i;
837
838 for (i = NextChar + 1; i < MaxChars; ++i)
839 {
840 if (NetRootName->Buffer[i] == '\\' || NetRootName->Buffer[i] == ':')
841 {
842 break;
843 }
844 }
845
846 CurChar = i - 1;
847 if (CurChar == NextChar)
848 {
849 if (((NetRootName->Buffer[NextChar] != '\\' && NetRootName->Buffer[NextChar] != ':') || NextChar == (MaxChars - 1)) && NetRootName->Buffer[NextChar] != '.')
850 {
851 continue;
852 }
853
854 if (CurChar != 0)
855 {
856 if (CurChar >= MaxChars - 1)
857 {
858 continue;
859 }
860
861 if (NetRootName->Buffer[CurChar + 1] != ':')
862 {
863 return STATUS_OBJECT_PATH_SYNTAX_BAD;
864 }
865 }
866 else
867 {
868 if (NetRootName->Buffer[1] != ':')
869 {
870 return STATUS_OBJECT_PATH_SYNTAX_BAD;
871 }
872 }
873 }
874 else
875 {
876 if ((CurChar - NextChar) == 1)
877 {
878 if (NetRootName->Buffer[NextChar + 2] != '.')
879 {
880 continue;
881 }
882
883 if (NetRootName->Buffer[NextChar] == '\\' || NetRootName->Buffer[NextChar] == ':' || NetRootName->Buffer[NextChar] == '.')
884 {
885 return STATUS_OBJECT_PATH_SYNTAX_BAD;
886 }
887 }
888 else
889 {
890 if ((CurChar - NextChar) != 2 || (NetRootName->Buffer[NextChar] != '\\' && NetRootName->Buffer[NextChar] != ':')
891 || NetRootName->Buffer[NextChar + 1] != '.')
892 {
893 continue;
894 }
895
896 if (NetRootName->Buffer[NextChar + 2] == '.')
897 {
898 return STATUS_OBJECT_PATH_SYNTAX_BAD;
899 }
900 }
901 }
902 }
903
904 return STATUS_MORE_PROCESSING_REQUIRED;
905 }
906
907 NTSTATUS
908 RxCanonicalizeNameAndObtainNetRoot(
909 PRX_CONTEXT RxContext,
910 PUNICODE_STRING FileName,
911 PUNICODE_STRING NetRootName)
912 {
913 NTSTATUS Status;
914 NET_ROOT_TYPE NetRootType;
915 UNICODE_STRING CanonicalName;
916
917 PAGED_CODE();
918
919 NetRootType = NET_ROOT_WILD;
920
921 RtlInitEmptyUnicodeString(NetRootName, NULL, 0);
922 RtlInitEmptyUnicodeString(&CanonicalName, NULL, 0);
923
924 /* if not relative opening, just handle the passed name */
925 if (RxContext->CurrentIrpSp->FileObject->RelatedFileObject == NULL)
926 {
927 Status = RxFirstCanonicalize(RxContext, FileName, &CanonicalName, &NetRootType);
928 if (!NT_SUCCESS(Status))
929 {
930 return Status;
931 }
932 }
933 else
934 {
935 PFCB Fcb;
936
937 /* Make sure we have a valid FCB and a FOBX */
938 Fcb = RxContext->CurrentIrpSp->FileObject->RelatedFileObject->FsContext;
939 if (Fcb == NULL ||
940 RxContext->CurrentIrpSp->FileObject->RelatedFileObject->FsContext2 == NULL)
941 {
942 return STATUS_INVALID_PARAMETER;
943 }
944
945 if (!NodeTypeIsFcb(Fcb))
946 {
947 return STATUS_INVALID_PARAMETER;
948 }
949
950 UNIMPLEMENTED;
951 }
952
953 /* Get/Create the associated VNetRoot for opening */
954 Status = RxFindOrConstructVirtualNetRoot(RxContext, &CanonicalName, NetRootType, NetRootName);
955 if (!NT_SUCCESS(Status) && Status != STATUS_PENDING &&
956 BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_MAILSLOT_REPARSE))
957 {
958 ASSERT(CanonicalName.Buffer == RxContext->Create.CanonicalNameBuffer);
959
960 RxFreeCanonicalNameBuffer(RxContext);
961 Status = RxFirstCanonicalize(RxContext, FileName, &CanonicalName, &NetRootType);
962 if (NT_SUCCESS(Status))
963 {
964 Status = RxFindOrConstructVirtualNetRoot(RxContext, &CanonicalName, NetRootType, NetRootName);
965 }
966 }
967
968 /* Filename cannot contain wildcards */
969 if (FsRtlDoesNameContainWildCards(NetRootName))
970 {
971 Status = STATUS_OBJECT_NAME_INVALID;
972 }
973
974 /* Make sure file name is correct */
975 if (NT_SUCCESS(Status))
976 {
977 Status = RxCanonicalizeFileNameByServerSpecs(RxContext, NetRootName);
978 }
979
980 /* Give the mini-redirector a chance to prepare the name */
981 if (NT_SUCCESS(Status) || Status == STATUS_MORE_PROCESSING_REQUIRED)
982 {
983 if (RxContext->Create.pNetRoot != NULL)
984 {
985 NTSTATUS IgnoredStatus;
986
987 MINIRDR_CALL(IgnoredStatus, RxContext, RxContext->Create.pNetRoot->pSrvCall->RxDeviceObject->Dispatch,
988 MRxPreparseName, (RxContext, NetRootName));
989 (void)IgnoredStatus;
990 }
991 }
992
993 return Status;
994 }
995
996 VOID
997 NTAPI
998 RxCheckFcbStructuresForAlignment(
999 VOID)
1000 {
1001 UNIMPLEMENTED;
1002 }
1003
1004 NTSTATUS
1005 RxCheckShareAccess(
1006 _In_ ACCESS_MASK DesiredAccess,
1007 _In_ ULONG DesiredShareAccess,
1008 _Inout_ PFILE_OBJECT FileObject,
1009 _Inout_ PSHARE_ACCESS ShareAccess,
1010 _In_ BOOLEAN Update,
1011 _In_ PSZ where,
1012 _In_ PSZ wherelogtag)
1013 {
1014 PAGED_CODE();
1015
1016 RxDumpWantedAccess(where, "", wherelogtag, DesiredAccess, DesiredShareAccess);
1017 RxDumpCurrentAccess(where, "", wherelogtag, ShareAccess);
1018
1019 return IoCheckShareAccess(DesiredAccess, DesiredShareAccess, FileObject, ShareAccess, Update);
1020 }
1021
1022 /*
1023 * @implemented
1024 */
1025 NTSTATUS
1026 RxCheckShareAccessPerSrvOpens(
1027 IN PFCB Fcb,
1028 IN ACCESS_MASK DesiredAccess,
1029 IN ULONG DesiredShareAccess)
1030 {
1031 BOOLEAN ReadAccess;
1032 BOOLEAN WriteAccess;
1033 BOOLEAN DeleteAccess;
1034 PSHARE_ACCESS ShareAccess;
1035
1036 PAGED_CODE();
1037
1038 ShareAccess = &Fcb->ShareAccessPerSrvOpens;
1039
1040 RxDumpWantedAccess("RxCheckShareAccessPerSrvOpens", "", "RxCheckShareAccessPerSrvOpens", DesiredAccess, DesiredShareAccess);
1041 RxDumpCurrentAccess("RxCheckShareAccessPerSrvOpens", "", "RxCheckShareAccessPerSrvOpens", ShareAccess);
1042
1043 /* Check if any access wanted */
1044 ReadAccess = (DesiredAccess & (FILE_READ_DATA | FILE_EXECUTE)) != 0;
1045 WriteAccess = (DesiredAccess & (FILE_WRITE_DATA | FILE_APPEND_DATA)) != 0;
1046 DeleteAccess = (DesiredAccess & DELETE) != 0;
1047
1048 if (ReadAccess || WriteAccess || DeleteAccess)
1049 {
1050 BOOLEAN SharedRead = (DesiredShareAccess & FILE_SHARE_READ) != 0;
1051 BOOLEAN SharedWrite = (DesiredShareAccess & FILE_SHARE_WRITE) != 0;
1052 BOOLEAN SharedDelete = (DesiredShareAccess & FILE_SHARE_DELETE) != 0;
1053
1054 /* Check whether there's a violation */
1055 if ((ReadAccess &&
1056 (ShareAccess->SharedRead < ShareAccess->OpenCount)) ||
1057 (WriteAccess &&
1058 (ShareAccess->SharedWrite < ShareAccess->OpenCount)) ||
1059 (DeleteAccess &&
1060 (ShareAccess->SharedDelete < ShareAccess->OpenCount)) ||
1061 ((ShareAccess->Readers != 0) && !SharedRead) ||
1062 ((ShareAccess->Writers != 0) && !SharedWrite) ||
1063 ((ShareAccess->Deleters != 0) && !SharedDelete))
1064 {
1065 return STATUS_SHARING_VIOLATION;
1066 }
1067 }
1068
1069 return STATUS_SUCCESS;
1070 }
1071
1072 /*
1073 * @implemented
1074 */
1075 NTSTATUS
1076 RxCloseAssociatedSrvOpen(
1077 IN PFOBX Fobx,
1078 IN PRX_CONTEXT RxContext OPTIONAL)
1079 {
1080 PFCB Fcb;
1081 NTSTATUS Status;
1082 PSRV_OPEN SrvOpen;
1083 BOOLEAN CloseSrvOpen;
1084 PRX_CONTEXT LocalContext;
1085
1086 PAGED_CODE();
1087
1088 /* Assume SRV_OPEN is already closed */
1089 CloseSrvOpen = FALSE;
1090 /* If we have a FOBX, we'll have to close it */
1091 if (Fobx != NULL)
1092 {
1093 /* If the FOBX isn't closed yet */
1094 if (!BooleanFlagOn(Fobx->Flags, FOBX_FLAG_SRVOPEN_CLOSED))
1095 {
1096 SrvOpen = Fobx->SrvOpen;
1097 Fcb = (PFCB)SrvOpen->pFcb;
1098 /* Check whether we've to close SRV_OPEN first */
1099 if (!BooleanFlagOn(SrvOpen->Flags, SRVOPEN_FLAG_CLOSED))
1100 {
1101 CloseSrvOpen = TRUE;
1102 }
1103 else
1104 {
1105 ASSERT(RxIsFcbAcquiredExclusive(Fcb));
1106
1107 /* Not much to do */
1108 SetFlag(Fobx->Flags, FOBX_FLAG_SRVOPEN_CLOSED);
1109
1110 if (SrvOpen->OpenCount > 0)
1111 {
1112 --SrvOpen->OpenCount;
1113 }
1114 }
1115 }
1116
1117 /* No need to close SRV_OPEN, so close FOBX */
1118 if (!CloseSrvOpen)
1119 {
1120 RxMarkFobxOnClose(Fobx);
1121
1122 return STATUS_SUCCESS;
1123 }
1124 }
1125 else
1126 {
1127 /* No FOBX? No RX_CONTEXT, ok, job done! */
1128 if (RxContext == NULL)
1129 {
1130 return STATUS_SUCCESS;
1131 }
1132
1133 /* Get the FCB from RX_CONTEXT */
1134 Fcb = (PFCB)RxContext->pFcb;
1135 SrvOpen == NULL;
1136 }
1137
1138 /* If we don't have RX_CONTEXT, allocte one, we'll need it */
1139 if (RxContext == NULL)
1140 {
1141 ASSERT(Fobx != NULL);
1142
1143 LocalContext = RxCreateRxContext(NULL, Fcb->RxDeviceObject, RX_CONTEXT_FLAG_MUST_SUCCEED_NONBLOCKING | RX_CONTEXT_FLAG_WAIT);
1144 if (LocalContext == NULL)
1145 {
1146 return STATUS_INSUFFICIENT_RESOURCES;
1147 }
1148
1149 LocalContext->MajorFunction = 2;
1150 LocalContext->pFcb = RX_GET_MRX_FCB(Fcb);
1151 LocalContext->pFobx = (PMRX_FOBX)Fobx;
1152 LocalContext->pRelevantSrvOpen = (PMRX_SRV_OPEN)Fobx->SrvOpen;
1153 }
1154 else
1155 {
1156 LocalContext = RxContext;
1157 }
1158
1159 ASSERT(RxIsFcbAcquiredExclusive(Fcb));
1160
1161 /* Now, close the FOBX */
1162 if (Fobx != NULL)
1163 {
1164 RxMarkFobxOnClose(Fobx);
1165 }
1166 else
1167 {
1168 InterlockedDecrement((volatile long *)&Fcb->OpenCount);
1169 }
1170
1171 /* If not a "standard" file, SRV_OPEN can be null */
1172 if (SrvOpen == NULL)
1173 {
1174 ASSERT((NodeType(Fcb) == RDBSS_NTC_OPENTARGETDIR_FCB) || (NodeType(Fcb) == RDBSS_NTC_IPC_SHARE) || (NodeType(Fcb) == RDBSS_NTC_MAILSLOT));
1175 RxDereferenceNetFcb(Fcb);
1176
1177 if (LocalContext != RxContext)
1178 {
1179 RxDereferenceAndDeleteRxContext(LocalContext);
1180 }
1181
1182 return STATUS_SUCCESS;
1183 }
1184
1185 /* If SRV_OPEN isn't in a good condition, nothing to close */
1186 if (SrvOpen->Condition != Condition_Good)
1187 {
1188 if (LocalContext != RxContext)
1189 {
1190 RxDereferenceAndDeleteRxContext(LocalContext);
1191 }
1192
1193 return STATUS_SUCCESS;
1194 }
1195
1196 /* Decrease open count */
1197 if (SrvOpen->OpenCount > 0)
1198 {
1199 --SrvOpen->OpenCount;
1200 }
1201
1202 /* If we're the only one left, is there a FOBX handled by Scavenger? */
1203 if (SrvOpen->OpenCount == 1)
1204 {
1205 if (!IsListEmpty(&SrvOpen->FobxList))
1206 {
1207 if (!IsListEmpty(&CONTAINING_RECORD(SrvOpen->FobxList.Flink, FOBX, FobxQLinks)->ScavengerFinalizationList))
1208 {
1209 SetFlag(SrvOpen->Flags, SRVOPEN_FLAG_CLOSE_DELAYED);
1210 }
1211 }
1212 }
1213
1214 /* Nothing left, purge FCB */
1215 if (SrvOpen->OpenCount == 0 && RxContext == NULL)
1216 {
1217 RxPurgeNetFcb(Fcb, LocalContext);
1218 }
1219
1220 /* Already closed? Job done! */
1221 SrvOpen = Fobx->SrvOpen;
1222 if (SrvOpen == NULL ||
1223 (SrvOpen->OpenCount != 0 && !BooleanFlagOn(SrvOpen->Flags, SRVOPEN_FLAG_BUFFERING_STATE_CHANGE_PENDING)) ||
1224 BooleanFlagOn(SrvOpen->Flags, SRVOPEN_FLAG_CLOSED))
1225 {
1226 SetFlag(Fobx->Flags, FOBX_FLAG_SRVOPEN_CLOSED);
1227 if (LocalContext != RxContext)
1228 {
1229 RxDereferenceAndDeleteRxContext(LocalContext);
1230 }
1231
1232 return STATUS_SUCCESS;
1233 }
1234
1235 ASSERT(RxIsFcbAcquiredExclusive(Fcb));
1236
1237 /* Inform mini-rdr about closing */
1238 MINIRDR_CALL(Status, LocalContext, Fcb->MRxDispatch, MRxCloseSrvOpen, (LocalContext));
1239 DPRINT("MRxCloseSrvOpen returned: %lx, called with RX_CONTEXT %p for FOBX %p (FCB %p, SRV_OPEN %p)\n ",
1240 Status, RxContext, Fobx, Fcb, SrvOpen);
1241
1242 /* And mark as such */
1243 SetFlag(SrvOpen->Flags, SRVOPEN_FLAG_CLOSED);
1244 SrvOpen->Key = (PVOID)-1;
1245
1246 /* If we were delayed, we're not! */
1247 if (BooleanFlagOn(SrvOpen->Flags, SRVOPEN_FLAG_CLOSE_DELAYED))
1248 {
1249 InterlockedDecrement(&((PSRV_CALL)Fcb->pNetRoot->pSrvCall)->NumberOfCloseDelayedFiles);
1250 }
1251
1252 /* Clear access */
1253 RxRemoveShareAccessPerSrvOpens(SrvOpen);
1254 RxPurgeChangeBufferingStateRequestsForSrvOpen(SrvOpen);
1255
1256 /* Dereference */
1257 RxDereferenceSrvOpen(SrvOpen, LHS_ExclusiveLockHeld);
1258
1259 /* Mark the FOBX closed as well */
1260 SetFlag(Fobx->Flags, FOBX_FLAG_SRVOPEN_CLOSED);
1261
1262 if (LocalContext != RxContext)
1263 {
1264 RxDereferenceAndDeleteRxContext(LocalContext);
1265 }
1266
1267 return Status;
1268 }
1269
1270 /*
1271 * @implemented
1272 */
1273 NTSTATUS
1274 RxCollapseOrCreateSrvOpen(
1275 PRX_CONTEXT RxContext)
1276 {
1277 PFCB Fcb;
1278 NTSTATUS Status;
1279 ULONG Disposition;
1280 PSRV_OPEN SrvOpen;
1281 USHORT ShareAccess;
1282 PIO_STACK_LOCATION Stack;
1283 ACCESS_MASK DesiredAccess;
1284 RX_BLOCK_CONDITION FcbCondition;
1285
1286 PAGED_CODE();
1287
1288 DPRINT("RxCollapseOrCreateSrvOpen(%p)\n", RxContext);
1289
1290 Fcb = (PFCB)RxContext->pFcb;
1291 ASSERT(RxIsFcbAcquiredExclusive(Fcb));
1292 ++Fcb->UncleanCount;
1293
1294 Stack = RxContext->CurrentIrpSp;
1295 DesiredAccess = Stack->Parameters.Create.SecurityContext->DesiredAccess & FILE_ALL_ACCESS;
1296 ShareAccess = Stack->Parameters.Create.ShareAccess & FILE_SHARE_VALID_FLAGS;
1297
1298 Disposition = RxContext->Create.NtCreateParameters.Disposition;
1299
1300 /* Try to find a reusable SRV_OPEN */
1301 Status = RxSearchForCollapsibleOpen(RxContext, DesiredAccess, ShareAccess);
1302 if (Status == STATUS_NOT_FOUND)
1303 {
1304 /* If none found, create one */
1305 SrvOpen = RxCreateSrvOpen((PV_NET_ROOT)RxContext->Create.pVNetRoot, Fcb);
1306 if (SrvOpen == NULL)
1307 {
1308 Status = STATUS_INSUFFICIENT_RESOURCES;
1309 }
1310 else
1311 {
1312 SrvOpen->DesiredAccess = DesiredAccess;
1313 SrvOpen->ShareAccess = ShareAccess;
1314 Status = STATUS_SUCCESS;
1315 }
1316
1317 RxContext->pRelevantSrvOpen = (PMRX_SRV_OPEN)SrvOpen;
1318
1319 if (Status != STATUS_SUCCESS)
1320 {
1321 FcbCondition = Condition_Bad;
1322 }
1323 else
1324 {
1325 RxInitiateSrvOpenKeyAssociation(SrvOpen);
1326
1327 /* Cookie to check the mini-rdr doesn't mess with RX_CONTEXT */
1328 RxContext->CurrentIrp->IoStatus.Information = 0xABCDEF;
1329 /* Inform the mini-rdr we're handling a create */
1330 MINIRDR_CALL(Status, RxContext, Fcb->MRxDispatch, MRxCreate, (RxContext));
1331 ASSERT(RxContext->CurrentIrp->IoStatus.Information == 0xABCDEF);
1332
1333 DPRINT("MRxCreate returned: %x\n", Status);
1334 if (Status == STATUS_SUCCESS)
1335 {
1336 /* In case of overwrite, reset file size */
1337 if (Disposition == FILE_OVERWRITE || Disposition == FILE_OVERWRITE_IF)
1338 {
1339 RxAcquirePagingIoResource(RxContext, Fcb);
1340 Fcb->Header.AllocationSize.QuadPart = 0LL;
1341 Fcb->Header.FileSize.QuadPart = 0LL;
1342 Fcb->Header.ValidDataLength.QuadPart = 0LL;
1343 RxContext->CurrentIrpSp->FileObject->SectionObjectPointer = &Fcb->NonPaged->SectionObjectPointers;
1344 CcSetFileSizes(RxContext->CurrentIrpSp->FileObject, (PCC_FILE_SIZES)&Fcb->Header.AllocationSize);
1345 RxReleasePagingIoResource(RxContext, Fcb);
1346 }
1347 else
1348 {
1349 /* Otherwise, adjust sizes */
1350 RxContext->CurrentIrpSp->FileObject->SectionObjectPointer = &Fcb->NonPaged->SectionObjectPointers;
1351 if (CcIsFileCached(RxContext->CurrentIrpSp->FileObject))
1352 {
1353 RxAdjustAllocationSizeforCC(Fcb);
1354 }
1355 CcSetFileSizes(RxContext->CurrentIrpSp->FileObject, (PCC_FILE_SIZES)&Fcb->Header.AllocationSize);
1356 }
1357 }
1358
1359 /* Set the IoStatus with information returned by mini-rdr */
1360 RxContext->CurrentIrp->IoStatus.Information = RxContext->Create.ReturnedCreateInformation;
1361
1362 SrvOpen->OpenStatus = Status;
1363 /* Set SRV_OPEN state - good or bad - depending on whether create succeed */
1364 RxTransitionSrvOpen(SrvOpen, (Status == STATUS_SUCCESS ? Condition_Good : Condition_Bad));
1365
1366 ASSERT(RxIsFcbAcquiredExclusive(Fcb));
1367
1368 RxCompleteSrvOpenKeyAssociation(SrvOpen);
1369
1370 if (Status == STATUS_SUCCESS)
1371 {
1372 if (BooleanFlagOn(Stack->Parameters.Create.Options, FILE_DELETE_ON_CLOSE))
1373 {
1374 ClearFlag(Fcb->FcbState, FCB_STATE_COLLAPSING_ENABLED);
1375 }
1376 SrvOpen->CreateOptions = RxContext->Create.NtCreateParameters.CreateOptions;
1377 FcbCondition = Condition_Good;
1378 }
1379 else
1380 {
1381 FcbCondition = Condition_Bad;
1382 RxDereferenceSrvOpen(SrvOpen, LHS_ExclusiveLockHeld);
1383 RxContext->pRelevantSrvOpen = NULL;
1384
1385 if (RxContext->pFobx != NULL)
1386 {
1387 RxDereferenceNetFobx(RxContext->pFobx, LHS_ExclusiveLockHeld);
1388 RxContext->pFobx = NULL;
1389 }
1390 }
1391 }
1392
1393 /* Set FCB state - good or bad - depending on whether create succeed */
1394 DPRINT("Transitioning FCB %p to condition %lx\n", Fcb, Fcb->Condition);
1395 RxTransitionNetFcb(Fcb, FcbCondition);
1396 }
1397 else if (Status == STATUS_SUCCESS)
1398 {
1399 BOOLEAN IsGood, ExtraOpen;
1400
1401 /* A reusable SRV_OPEN was found */
1402 RxContext->CurrentIrp->IoStatus.Information = FILE_OPENED;
1403 ExtraOpen = FALSE;
1404
1405 SrvOpen = (PSRV_OPEN)RxContext->pRelevantSrvOpen;
1406
1407 IsGood = (SrvOpen->Condition == Condition_Good);
1408 /* If the SRV_OPEN isn't in a stable situation, wait for it to become stable */
1409 if (!StableCondition(SrvOpen->Condition))
1410 {
1411 RxReferenceSrvOpen(SrvOpen);
1412 ++SrvOpen->OpenCount;
1413 ExtraOpen = TRUE;
1414
1415 RxReleaseFcb(RxContext, Fcb);
1416 RxContext->Create.FcbAcquired = FALSE;
1417
1418 RxWaitForStableSrvOpen(SrvOpen, RxContext);
1419
1420 if (NT_SUCCESS(RxAcquireExclusiveFcb(RxContext, Fcb)))
1421 {
1422 RxContext->Create.FcbAcquired = TRUE;
1423 }
1424
1425 IsGood = (SrvOpen->Condition == Condition_Good);
1426 }
1427
1428 /* Inform the mini-rdr we do an opening with a reused SRV_OPEN */
1429 if (IsGood)
1430 {
1431 MINIRDR_CALL(Status, RxContext, Fcb->MRxDispatch, MRxCollapseOpen, (RxContext));
1432
1433 ASSERT(RxIsFcbAcquiredExclusive(Fcb));
1434 }
1435 else
1436 {
1437 Status = SrvOpen->OpenStatus;
1438 }
1439
1440 if (ExtraOpen)
1441 {
1442 --SrvOpen->OpenCount;
1443 RxDereferenceSrvOpen(SrvOpen, LHS_ExclusiveLockHeld);
1444 }
1445 }
1446
1447 --Fcb->UncleanCount;
1448
1449 DPRINT("Status: %x\n", Status);
1450 return Status;
1451 }
1452
1453 NTSTATUS
1454 NTAPI
1455 RxCommonCleanup(
1456 PRX_CONTEXT Context)
1457 {
1458 #define BugCheckFileId RDBSS_BUG_CHECK_CLEANUP
1459 PFCB Fcb;
1460 PFOBX Fobx;
1461 ULONG OpenCount;
1462 NTSTATUS Status;
1463 PNET_ROOT NetRoot;
1464 PFILE_OBJECT FileObject;
1465 PLARGE_INTEGER TruncateSize;
1466 BOOLEAN NeedPurge, FcbTableAcquired, OneLeft, IsFile, FcbAcquired;
1467
1468 PAGED_CODE();
1469
1470 Fcb = (PFCB)Context->pFcb;
1471 Fobx = (PFOBX)Context->pFobx;
1472 DPRINT("RxCommonCleanup(%p); FOBX: %p, FCB: %p\n", Context, Fobx, Fcb);
1473
1474 /* File system closing, it's OK */
1475 if (Fobx == NULL)
1476 {
1477 if (Fcb->UncleanCount > 0)
1478 {
1479 InterlockedDecrement((volatile long *)&Fcb->UncleanCount);
1480 }
1481
1482 return STATUS_SUCCESS;
1483 }
1484
1485 /* Check we have a correct FCB type */
1486 if (NodeType(Fcb) != RDBSS_NTC_STORAGE_TYPE_FILE &&
1487 NodeType(Fcb) != RDBSS_NTC_STORAGE_TYPE_DIRECTORY &&
1488 NodeType(Fcb) != RDBSS_NTC_STORAGE_TYPE_UNKNOWN &&
1489 NodeType(Fcb) != RDBSS_NTC_SPOOLFILE)
1490 {
1491 DPRINT1("Invalid Fcb type for %p\n", Fcb);
1492 RxBugCheck(Fcb->Header.NodeTypeCode, 0, 0);
1493 }
1494
1495 FileObject = Context->CurrentIrpSp->FileObject;
1496 ASSERT(!BooleanFlagOn(FileObject->Flags, FO_CLEANUP_COMPLETE));
1497
1498 RxMarkFobxOnCleanup(Fobx, &NeedPurge);
1499
1500 Status = RxAcquireExclusiveFcb(Context, Fcb);
1501 if (!NT_SUCCESS(Status))
1502 {
1503 return Status;
1504 }
1505
1506 FcbAcquired = TRUE;
1507
1508 Fobx->AssociatedFileObject = NULL;
1509
1510 /* In case SRV_OPEN used is part of FCB */
1511 if (BooleanFlagOn(Fcb->FcbState, FCB_STATE_SRVOPEN_USED))
1512 {
1513 ASSERT(Fcb->UncleanCount != 0);
1514 InterlockedDecrement((volatile long *)&Fcb->UncleanCount);
1515
1516 if (BooleanFlagOn(FileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING))
1517 {
1518 --Fcb->UncachedUncleanCount;
1519 }
1520
1521 /* Inform mini-rdr */
1522 MINIRDR_CALL(Status, Context, Fcb->MRxDispatch, MRxCleanupFobx, (Context));
1523
1524 ASSERT(Fobx->SrvOpen->UncleanFobxCount != 0);
1525 --Fobx->SrvOpen->UncleanFobxCount;
1526
1527 RxUninitializeCacheMap(Context, FileObject, NULL);
1528
1529 RxReleaseFcb(Context, Fcb);
1530
1531 return STATUS_SUCCESS;
1532 }
1533
1534 /* Report the fact that file could be set as delete on close */
1535 if (BooleanFlagOn(Fobx->Flags, FOBX_FLAG_DELETE_ON_CLOSE))
1536 {
1537 SetFlag(Fcb->FcbState, FCB_STATE_DELETE_ON_CLOSE);
1538 }
1539
1540 /* Cancel any pending notification */
1541 RxCancelNotifyChangeDirectoryRequestsForFobx(Fobx);
1542
1543 /* Backup open count before we start playing with it */
1544 OpenCount = Fcb->ShareAccess.OpenCount;
1545
1546 NetRoot = (PNET_ROOT)Fcb->pNetRoot;
1547 FcbTableAcquired = FALSE;
1548 OneLeft = FALSE;
1549
1550 _SEH2_TRY
1551 {
1552 /* Unclean count and delete on close? Verify whether we're the one */
1553 if (Fcb->UncleanCount == 1 && BooleanFlagOn(Fcb->FcbState, FCB_STATE_DELETE_ON_CLOSE))
1554 {
1555 if (RxAcquireFcbTableLockExclusive(&NetRoot->FcbTable, FALSE))
1556 {
1557 FcbTableAcquired = TRUE;
1558 }
1559 else
1560 {
1561 RxReleaseFcb(Context, Fcb);
1562
1563 RxAcquireFcbTableLockExclusive(&NetRoot->FcbTable, TRUE);
1564
1565 Status = RxAcquireExclusiveFcb(Context, Fcb);
1566 if (Status != STATUS_SUCCESS)
1567 {
1568 RxReleaseFcbTableLock(&NetRoot->FcbTable);
1569 return Status;
1570 }
1571
1572 FcbTableAcquired = TRUE;
1573 }
1574
1575 if (Fcb->UncleanCount == 1)
1576 {
1577 OneLeft = TRUE;
1578 }
1579 else
1580 {
1581 RxReleaseFcbTableLock(&NetRoot->FcbTable);
1582 FcbTableAcquired = FALSE;
1583 }
1584 }
1585
1586 IsFile = FALSE;
1587 TruncateSize = NULL;
1588 /* Handle cleanup for pipes and printers */
1589 if (NetRoot->Type == NET_ROOT_PIPE || NetRoot->Type == NET_ROOT_PRINT)
1590 {
1591 UNIMPLEMENTED;
1592 }
1593 /* Handle cleanup for files */
1594 else if (NetRoot->Type == NET_ROOT_DISK || NetRoot->Type == NET_ROOT_WILD)
1595 {
1596 if (NodeType(Fcb) == RDBSS_NTC_STORAGE_TYPE_FILE)
1597 {
1598 UNIMPLEMENTED;
1599 IsFile = TRUE;
1600 }
1601 }
1602
1603 /* We have to still be there! */
1604 ASSERT(Fcb->UncleanCount != 0);
1605 InterlockedDecrement((volatile long *)&Fcb->UncleanCount);
1606
1607 if (BooleanFlagOn(FileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING))
1608 {
1609 --Fcb->UncachedUncleanCount;
1610 }
1611
1612 /* Inform mini-rdr about ongoing cleanup */
1613 MINIRDR_CALL(Status, Context, Fcb->MRxDispatch, MRxCleanupFobx, (Context));
1614
1615 ASSERT(Fobx->SrvOpen->UncleanFobxCount != 0);
1616 --Fobx->SrvOpen->UncleanFobxCount;
1617
1618 /* Flush cache */
1619 if (DisableFlushOnCleanup)
1620 {
1621 /* Only if we're the last standing */
1622 if (Fcb->NonPaged->SectionObjectPointers.DataSectionObject != NULL &&
1623 Fcb->UncleanCount == Fcb->UncachedUncleanCount)
1624 {
1625 DPRINT1("Flushing %p due to last cached handle cleanup\n", Context);
1626 RxFlushFcbInSystemCache(Fcb, TRUE);
1627 }
1628 }
1629 else
1630 {
1631 /* Always */
1632 if (Fcb->NonPaged->SectionObjectPointers.DataSectionObject != NULL)
1633 {
1634 DPRINT1("Flushing %p on cleanup\n", Context);
1635 RxFlushFcbInSystemCache(Fcb, TRUE);
1636 }
1637 }
1638
1639 /* If only remaining uncached & unclean, then flush and purge */
1640 if (!BooleanFlagOn(FileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING))
1641 {
1642 if (Fcb->UncachedUncleanCount != 0)
1643 {
1644 if (Fcb->UncachedUncleanCount == Fcb->UncleanCount &&
1645 Fcb->NonPaged->SectionObjectPointers.DataSectionObject != NULL)
1646 {
1647 DPRINT1("Flushing FCB in system cache for %p\n", Context);
1648 RxPurgeFcbInSystemCache(Fcb, NULL, 0, FALSE, TRUE);
1649 }
1650 }
1651 }
1652
1653 /* If purge required, flush */
1654 if (!OneLeft && NeedPurge)
1655 {
1656 DPRINT1("Flushing FCB in system cache for %p\n", Context);
1657 RxFlushFcbInSystemCache(Fcb, TRUE);
1658 }
1659
1660 /* If it was a file, drop cache */
1661 if (IsFile)
1662 {
1663 DPRINT1("Uninit cache map for file\n");
1664 RxUninitializeCacheMap(Context, FileObject, TruncateSize);
1665 }
1666
1667 /* If that's the one left, or if it needs purge, flush */
1668 if (OneLeft || NeedPurge)
1669 {
1670 RxPurgeFcbInSystemCache(Fcb, NULL, 0, FALSE, !OneLeft);
1671 /* Also remove from FCB table */
1672 if (OneLeft)
1673 {
1674 RxRemoveNameNetFcb(Fcb);
1675 RxReleaseFcbTableLock(&NetRoot->FcbTable);
1676 FcbTableAcquired = FALSE;
1677 }
1678 }
1679
1680 /* Remove any share access */
1681 if (OpenCount != 0 && NetRoot->Type == NET_ROOT_DISK)
1682 {
1683 RxRemoveShareAccess(FileObject, &Fcb->ShareAccess, "Cleanup the share access", "ClnUpShr");
1684 }
1685
1686 /* In case there's caching, on a file, update file metadata */
1687 if (NodeType(Fcb) == RDBSS_NTC_STORAGE_TYPE_FILE && BooleanFlagOn(Fobx->Flags, 0x20000000) &&
1688 BooleanFlagOn(Fcb->FcbState, FCB_STATE_WRITECACHING_ENABLED) && !BooleanFlagOn(Fobx->pSrvOpen->Flags, SRVOPEN_FLAG_DONTUSE_WRITE_CACHING))
1689 {
1690 UNIMPLEMENTED;
1691 }
1692
1693 /* We're clean! */
1694 SetFlag(FileObject->Flags, FO_CLEANUP_COMPLETE);
1695
1696 FcbAcquired = FALSE;
1697 RxReleaseFcb(Context, Fcb);
1698 }
1699 _SEH2_FINALLY
1700 {
1701 if (FcbAcquired)
1702 {
1703 RxReleaseFcb(Context, Fcb);
1704 }
1705
1706 if (FcbTableAcquired)
1707 {
1708 RxReleaseFcbTableLock(&NetRoot->FcbTable);
1709 }
1710 }
1711 _SEH2_END;
1712
1713 return Status;
1714 #undef BugCheckFileId
1715 }
1716
1717 NTSTATUS
1718 NTAPI
1719 RxCommonClose(
1720 PRX_CONTEXT Context)
1721 {
1722 #define BugCheckFileId RDBSS_BUG_CHECK_CLOSE
1723 PFCB Fcb;
1724 PFOBX Fobx;
1725 NTSTATUS Status;
1726 PFILE_OBJECT FileObject;
1727 BOOLEAN DereferenceFobx, AcquiredFcb;
1728
1729 PAGED_CODE();
1730
1731 Fcb = (PFCB)Context->pFcb;
1732 Fobx = (PFOBX)Context->pFobx;
1733 FileObject = Context->CurrentIrpSp->FileObject;
1734 DPRINT("RxCommonClose(%p); FOBX: %p, FCB: %p, FO: %p\n", Context, Fobx, Fcb, FileObject);
1735
1736 Status = RxAcquireExclusiveFcb(Context, Fcb);
1737 if (!NT_SUCCESS(Status))
1738 {
1739 return Status;
1740 }
1741
1742 AcquiredFcb = TRUE;
1743 _SEH2_TRY
1744 {
1745 BOOLEAN Freed;
1746
1747 /* Check our FCB type is expected */
1748 if (NodeType(Fcb) != RDBSS_NTC_STORAGE_TYPE_UNKNOWN &&
1749 (NodeType(Fcb) < RDBSS_NTC_STORAGE_TYPE_DIRECTORY || (NodeType(Fcb) > RDBSS_NTC_STORAGE_TYPE_FILE &&
1750 (NodeType(Fcb) < RDBSS_NTC_SPOOLFILE || NodeType(Fcb) > RDBSS_NTC_OPENTARGETDIR_FCB))))
1751 {
1752 RxBugCheck(NodeType(Fcb), 0, 0);
1753 }
1754
1755 RxReferenceNetFcb(Fcb);
1756
1757 DereferenceFobx = FALSE;
1758 /* If we're not closing FS */
1759 if (Fobx != NULL)
1760 {
1761 PSRV_OPEN SrvOpen;
1762 PSRV_CALL SrvCall;
1763
1764 SrvOpen = (PSRV_OPEN)Fobx->pSrvOpen;
1765 SrvCall = (PSRV_CALL)Fcb->pNetRoot->pSrvCall;
1766 /* Handle delayed close */
1767 if (NodeType(Fcb) != RDBSS_NTC_STORAGE_TYPE_DIRECTORY)
1768 {
1769 if (!BooleanFlagOn(Fcb->FcbState, FCB_STATE_DELETE_ON_CLOSE | FCB_STATE_ORPHANED))
1770 {
1771 if (BooleanFlagOn(Fcb->FcbState, FCB_STATE_COLLAPSING_ENABLED))
1772 {
1773 DPRINT("Delay close for FOBX: %p, SrvOpen %p\n", Fobx, SrvOpen);
1774
1775 if (SrvOpen->OpenCount == 1 && !BooleanFlagOn(SrvOpen->Flags, SRVOPEN_FLAG_COLLAPSING_DISABLED))
1776 {
1777 if (InterlockedIncrement(&SrvCall->NumberOfCloseDelayedFiles) >= SrvCall->MaximumNumberOfCloseDelayedFiles)
1778 {
1779 InterlockedDecrement(&SrvCall->NumberOfCloseDelayedFiles);
1780 }
1781 else
1782 {
1783 DereferenceFobx = TRUE;
1784 SetFlag(SrvOpen->Flags, SRVOPEN_FLAG_CLOSE_DELAYED);
1785 }
1786 }
1787 }
1788 }
1789 }
1790
1791 /* If we reach maximum of delayed close/or if there are no delayed close */
1792 if (!DereferenceFobx)
1793 {
1794 PNET_ROOT NetRoot;
1795
1796 NetRoot = (PNET_ROOT)Fcb->pNetRoot;
1797 if (NetRoot->Type != NET_ROOT_PRINT)
1798 {
1799 /* Delete if asked */
1800 if (BooleanFlagOn(Fobx->Flags, FOBX_FLAG_DELETE_ON_CLOSE))
1801 {
1802 RxScavengeRelatedFobxs(Fcb);
1803 RxSynchronizeWithScavenger(Context);
1804
1805 RxReleaseFcb(Context, Fcb);
1806
1807 RxAcquireFcbTableLockExclusive(&NetRoot->FcbTable, TRUE);
1808 RxOrphanThisFcb(Fcb);
1809 RxReleaseFcbTableLock(&NetRoot->FcbTable);
1810
1811 Status = RxAcquireExclusiveFcb(Context, Fcb);
1812 ASSERT(NT_SUCCESS(Status));
1813 }
1814 }
1815 }
1816
1817 RxMarkFobxOnClose(Fobx);
1818 }
1819
1820 if (DereferenceFobx)
1821 {
1822 ASSERT(Fobx != NULL);
1823 RxDereferenceNetFobx(Fobx, LHS_SharedLockHeld);
1824 }
1825 else
1826 {
1827 RxCloseAssociatedSrvOpen(Fobx, Context);
1828 if (Fobx != NULL)
1829 {
1830 RxDereferenceNetFobx(Fobx, LHS_ExclusiveLockHeld);
1831 }
1832 }
1833
1834 Freed = RxDereferenceAndFinalizeNetFcb(Fcb, Context, FALSE, FALSE);
1835 AcquiredFcb = !Freed;
1836
1837 FileObject->FsContext = (PVOID)-1;
1838
1839 if (Freed)
1840 {
1841 RxTrackerUpdateHistory(Context, NULL, TRACKER_FCB_FREE, __LINE__, __FILE__, 0);
1842 }
1843 else
1844 {
1845 RxReleaseFcb(Context, Fcb);
1846 AcquiredFcb = FALSE;
1847 }
1848 }
1849 _SEH2_FINALLY
1850 {
1851 if (_SEH2_AbnormalTermination())
1852 {
1853 if (AcquiredFcb)
1854 {
1855 RxReleaseFcb(Context, Fcb);
1856 }
1857 }
1858 else
1859 {
1860 ASSERT(!AcquiredFcb);
1861 }
1862 }
1863 _SEH2_END;
1864
1865 DPRINT("Status: %x\n", Status);
1866 return Status;
1867 #undef BugCheckFileId
1868 }
1869
1870 NTSTATUS
1871 NTAPI
1872 RxCommonCreate(
1873 PRX_CONTEXT Context)
1874 {
1875 PIRP Irp;
1876 NTSTATUS Status;
1877 PFILE_OBJECT FileObject;
1878 PIO_STACK_LOCATION Stack;
1879
1880 PAGED_CODE();
1881
1882 DPRINT("RxCommonCreate(%p)\n", Context);
1883
1884 Irp = Context->CurrentIrp;
1885 Stack = Context->CurrentIrpSp;
1886 FileObject = Stack->FileObject;
1887
1888 /* Check whether that's a device opening */
1889 if (FileObject->FileName.Length == 0 && FileObject->RelatedFileObject == NULL)
1890 {
1891 FileObject->FsContext = &RxDeviceFCB;
1892 FileObject->FsContext2 = NULL;
1893
1894 ++RxDeviceFCB.NodeReferenceCount;
1895 ++RxDeviceFCB.OpenCount;
1896
1897 Irp->IoStatus.Information = FILE_OPENED;
1898 DPRINT("Device opening FO: %p, DO: %p, Name: %wZ\n", FileObject, Context->RxDeviceObject, &Context->RxDeviceObject->DeviceName);
1899
1900 Status = STATUS_SUCCESS;
1901 }
1902 else
1903 {
1904 PFCB RelatedFcb = NULL;
1905
1906 /* Make sure caller is consistent */
1907 if (FlagOn(Stack->Parameters.Create.Options, FILE_DIRECTORY_FILE | FILE_NON_DIRECTORY_FILE | FILE_OPEN_REMOTE_INSTANCE) ==
1908 (FILE_DIRECTORY_FILE | FILE_NON_DIRECTORY_FILE | FILE_OPEN_REMOTE_INSTANCE))
1909 {
1910 DPRINT1("Create.Options: %x\n", Stack->Parameters.Create.Options);
1911 return STATUS_INVALID_PARAMETER;
1912 }
1913
1914 DPRINT("Ctxt: %p, FO: %p, Options: %lx, Flags: %lx, Attr: %lx, ShareAccess: %lx, DesiredAccess: %lx\n",
1915 Context, FileObject, Stack->Parameters.Create.Options, Stack->Flags, Stack->Parameters.Create.FileAttributes,
1916 Stack->Parameters.Create.ShareAccess, Stack->Parameters.Create.SecurityContext->DesiredAccess);
1917 DPRINT("FileName: %wZ\n", &FileObject->FileName);
1918
1919 if (FileObject->RelatedFileObject != NULL)
1920 {
1921 RelatedFcb = FileObject->RelatedFileObject->FsContext;
1922 DPRINT("Rel FO: %p, path: %wZ\n", FileObject->RelatedFileObject, RelatedFcb->FcbTableEntry.Path);
1923 }
1924
1925 /* Going to rename? */
1926 if (BooleanFlagOn(Stack->Flags, SL_OPEN_TARGET_DIRECTORY))
1927 {
1928 DPRINT("TargetDir!\n");
1929 }
1930
1931 /* Copy create parameters to the context */
1932 RxCopyCreateParameters(Context);
1933
1934 /* If the caller wants to establish a connection, go ahead */
1935 if (BooleanFlagOn(Stack->Parameters.Create.Options, FILE_CREATE_TREE_CONNECTION))
1936 {
1937 Status = RxCreateTreeConnect(Context);
1938 }
1939 else
1940 {
1941 /* Validate file name */
1942 if (FileObject->FileName.Length > sizeof(WCHAR) &&
1943 FileObject->FileName.Buffer[1] == OBJ_NAME_PATH_SEPARATOR &&
1944 FileObject->FileName.Buffer[0] == OBJ_NAME_PATH_SEPARATOR)
1945 {
1946 FileObject->FileName.Length -= sizeof(WCHAR);
1947 RtlMoveMemory(&FileObject->FileName.Buffer[0], &FileObject->FileName.Buffer[1],
1948 FileObject->FileName.Length);
1949
1950 if (FileObject->FileName.Length > sizeof(WCHAR) &&
1951 FileObject->FileName.Buffer[1] == OBJ_NAME_PATH_SEPARATOR &&
1952 FileObject->FileName.Buffer[0] == OBJ_NAME_PATH_SEPARATOR)
1953 {
1954 return STATUS_OBJECT_NAME_INVALID;
1955 }
1956 }
1957
1958 /* Attempt to open the file */
1959 do
1960 {
1961 UNICODE_STRING NetRootName;
1962
1963 /* Strip last \ if required */
1964 if (FileObject->FileName.Length != 0 &&
1965 FileObject->FileName.Buffer[FileObject->FileName.Length / sizeof(WCHAR) - 1] == OBJ_NAME_PATH_SEPARATOR)
1966 {
1967 if (BooleanFlagOn(Stack->Parameters.Create.Options, FILE_NON_DIRECTORY_FILE))
1968 {
1969 return STATUS_OBJECT_NAME_INVALID;
1970 }
1971
1972 FileObject->FileName.Length -= sizeof(WCHAR);
1973 Context->Create.Flags |= RX_CONTEXT_CREATE_FLAG_STRIPPED_TRAILING_BACKSLASH;
1974 }
1975
1976 if (BooleanFlagOn(Context->Flags, RX_CONTEXT_FLAG_WRITE_THROUGH))
1977 {
1978 FileObject->Flags |= FO_WRITE_THROUGH;
1979 }
1980
1981 /* Get the associated net root to opening */
1982 Status = RxCanonicalizeNameAndObtainNetRoot(Context, &FileObject->FileName, &NetRootName);
1983 if (Status != STATUS_MORE_PROCESSING_REQUIRED)
1984 {
1985 break;
1986 }
1987
1988 /* And attempt to open */
1989 Status = RxCreateFromNetRoot(Context, &NetRootName);
1990 if (Status == STATUS_SHARING_VIOLATION)
1991 {
1992 UNIMPLEMENTED;
1993 }
1994 else if (Status == STATUS_REPARSE)
1995 {
1996 Context->CurrentIrp->IoStatus.Information = 0;
1997 }
1998 else
1999 {
2000 ASSERT(!BooleanFlagOn(Context->Create.Flags, RX_CONTEXT_CREATE_FLAG_REPARSE));
2001 }
2002 }
2003 while (Status == STATUS_MORE_PROCESSING_REQUIRED);
2004 }
2005
2006 if (Status == STATUS_RETRY)
2007 {
2008 RxpPrepareCreateContextForReuse(Context);
2009 }
2010 ASSERT(Status != STATUS_PENDING);
2011 }
2012
2013 DPRINT("Status: %lx\n", Status);
2014 return Status;
2015 }
2016
2017 /*
2018 * @implemented
2019 */
2020 NTSTATUS
2021 NTAPI
2022 RxCommonDevFCBCleanup(
2023 PRX_CONTEXT Context)
2024 {
2025 PMRX_FCB Fcb;
2026 NTSTATUS Status;
2027
2028 PAGED_CODE();
2029
2030 DPRINT("RxCommonDevFCBCleanup(%p)\n", Context);
2031
2032 Fcb = Context->pFcb;
2033 Status = STATUS_SUCCESS;
2034 ASSERT(NodeType(Fcb) == RDBSS_NTC_DEVICE_FCB);
2035
2036 /* Our FOBX if set, has to be a VNetRoot */
2037 if (Context->pFobx != NULL)
2038 {
2039 RxAcquirePrefixTableLockShared(Context->RxDeviceObject->pRxNetNameTable, TRUE);
2040 if (Context->pFobx->NodeTypeCode != RDBSS_NTC_V_NETROOT)
2041 {
2042 Status = STATUS_INVALID_DEVICE_REQUEST;
2043 }
2044 RxReleasePrefixTableLock(Context->RxDeviceObject->pRxNetNameTable);
2045 }
2046 else
2047 {
2048 --Fcb->UncleanCount;
2049 }
2050
2051 return Status;
2052 }
2053
2054 /*
2055 * @implemented
2056 */
2057 NTSTATUS
2058 NTAPI
2059 RxCommonDevFCBClose(
2060 PRX_CONTEXT Context)
2061 {
2062 PMRX_FCB Fcb;
2063 NTSTATUS Status;
2064 PMRX_V_NET_ROOT NetRoot;
2065
2066 PAGED_CODE();
2067
2068 DPRINT("RxCommonDevFCBClose(%p)\n", Context);
2069
2070 Fcb = Context->pFcb;
2071 NetRoot = (PMRX_V_NET_ROOT)Context->pFobx;
2072 Status = STATUS_SUCCESS;
2073 ASSERT(NodeType(Fcb) == RDBSS_NTC_DEVICE_FCB);
2074
2075 /* Our FOBX if set, has to be a VNetRoot */
2076 if (NetRoot != NULL)
2077 {
2078 RxAcquirePrefixTableLockExclusive(Context->RxDeviceObject->pRxNetNameTable, TRUE);
2079 if (NetRoot->NodeTypeCode == RDBSS_NTC_V_NETROOT)
2080 {
2081 --NetRoot->NumberOfOpens;
2082 RxDereferenceVNetRoot(NetRoot, LHS_ExclusiveLockHeld);
2083 }
2084 else
2085 {
2086 Status = STATUS_NOT_IMPLEMENTED;
2087 }
2088 RxReleasePrefixTableLock(Context->RxDeviceObject->pRxNetNameTable);
2089 }
2090 else
2091 {
2092 --Fcb->OpenCount;
2093 }
2094
2095 return Status;
2096 }
2097
2098 NTSTATUS
2099 NTAPI
2100 RxCommonDevFCBFsCtl(
2101 PRX_CONTEXT Context)
2102 {
2103 UNIMPLEMENTED;
2104 return STATUS_NOT_IMPLEMENTED;
2105 }
2106
2107 /*
2108 * @implemented
2109 */
2110 NTSTATUS
2111 NTAPI
2112 RxCommonDevFCBIoCtl(
2113 PRX_CONTEXT Context)
2114 {
2115 NTSTATUS Status;
2116
2117 PAGED_CODE();
2118
2119 DPRINT("RxCommonDevFCBIoCtl(%p)\n", Context);
2120
2121 if (Context->pFobx != NULL)
2122 {
2123 return STATUS_INVALID_HANDLE;
2124 }
2125
2126 /* Is that a prefix claim from MUP? */
2127 if (Context->CurrentIrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_REDIR_QUERY_PATH)
2128 {
2129 return RxPrefixClaim(Context);
2130 }
2131
2132 /* Otherwise, pass through the mini-rdr */
2133 Status = RxXXXControlFileCallthru(Context);
2134 if (Status != STATUS_PENDING)
2135 {
2136 if (Context->PostRequest)
2137 {
2138 Context->ResumeRoutine = RxCommonDevFCBIoCtl;
2139 Status = RxFsdPostRequest(Context);
2140 }
2141 }
2142
2143 DPRINT("Status: %lx\n", Status);
2144 return Status;
2145 }
2146
2147 NTSTATUS
2148 NTAPI
2149 RxCommonDevFCBQueryVolInfo(
2150 PRX_CONTEXT Context)
2151 {
2152 UNIMPLEMENTED;
2153 return STATUS_NOT_IMPLEMENTED;
2154 }
2155
2156 /*
2157 * @implemented
2158 */
2159 NTSTATUS
2160 NTAPI
2161 RxCommonDeviceControl(
2162 PRX_CONTEXT Context)
2163 {
2164 NTSTATUS Status;
2165
2166 PAGED_CODE();
2167
2168 /* Prefix claim is only allowed for device, not files */
2169 if (Context->CurrentIrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_REDIR_QUERY_PATH)
2170 {
2171 return STATUS_INVALID_DEVICE_REQUEST;
2172 }
2173
2174 /* Submit to mini-rdr */
2175 RxInitializeLowIoContext(&Context->LowIoContext, LOWIO_OP_IOCTL);
2176 Status = RxLowIoSubmit(Context, RxLowIoIoCtlShellCompletion);
2177 if (Status == STATUS_PENDING)
2178 {
2179 RxDereferenceAndDeleteRxContext_Real(Context);
2180 }
2181
2182 return Status;
2183 }
2184
2185 /*
2186 * @implemented
2187 */
2188 NTSTATUS
2189 NTAPI
2190 RxCommonDirectoryControl(
2191 PRX_CONTEXT Context)
2192 {
2193 PFCB Fcb;
2194 PFOBX Fobx;
2195 NTSTATUS Status;
2196 PIO_STACK_LOCATION Stack;
2197
2198 PAGED_CODE();
2199
2200 Fcb = (PFCB)Context->pFcb;
2201 Fobx = (PFOBX)Context->pFobx;
2202 Stack = Context->CurrentIrpSp;
2203 DPRINT("RxCommonDirectoryControl(%p) FOBX: %p, FCB: %p, Minor: %d\n", Context, Fobx, Fcb, Stack->MinorFunction);
2204
2205 /* Call the appropriate helper */
2206 if (Stack->MinorFunction == IRP_MN_QUERY_DIRECTORY)
2207 {
2208 Status = RxQueryDirectory(Context);
2209 }
2210 else if (Stack->MinorFunction == IRP_MN_NOTIFY_CHANGE_DIRECTORY)
2211 {
2212 Status = RxNotifyChangeDirectory(Context);
2213 if (Status == STATUS_PENDING)
2214 {
2215 RxDereferenceAndDeleteRxContext_Real(Context);
2216 }
2217 }
2218 else
2219 {
2220 Status = STATUS_INVALID_DEVICE_REQUEST;
2221 }
2222
2223 return Status;
2224 }
2225
2226 NTSTATUS
2227 NTAPI
2228 RxCommonDispatchProblem(
2229 PRX_CONTEXT Context)
2230 {
2231 UNIMPLEMENTED;
2232 return STATUS_NOT_IMPLEMENTED;
2233 }
2234
2235 NTSTATUS
2236 NTAPI
2237 RxCommonFileSystemControl(
2238 PRX_CONTEXT Context)
2239 {
2240 UNIMPLEMENTED;
2241 return STATUS_NOT_IMPLEMENTED;
2242 }
2243
2244 NTSTATUS
2245 NTAPI
2246 RxCommonFlushBuffers(
2247 PRX_CONTEXT Context)
2248 {
2249 UNIMPLEMENTED;
2250 return STATUS_NOT_IMPLEMENTED;
2251 }
2252
2253 NTSTATUS
2254 NTAPI
2255 RxCommonLockControl(
2256 PRX_CONTEXT Context)
2257 {
2258 UNIMPLEMENTED;
2259 return STATUS_NOT_IMPLEMENTED;
2260 }
2261
2262 NTSTATUS
2263 NTAPI
2264 RxCommonQueryEa(
2265 PRX_CONTEXT Context)
2266 {
2267 UNIMPLEMENTED;
2268 return STATUS_NOT_IMPLEMENTED;
2269 }
2270
2271 /*
2272 * @implemented
2273 */
2274 NTSTATUS
2275 NTAPI
2276 RxCommonQueryInformation(
2277 PRX_CONTEXT Context)
2278 {
2279 #define SET_SIZE_AND_QUERY(AlreadyConsummed, Function) \
2280 Context->Info.Length = Stack->Parameters.QueryFile.Length - (AlreadyConsummed); \
2281 Status = Function(Context, Add2Ptr(Buffer, AlreadyConsummed))
2282
2283 PFCB Fcb;
2284 PIRP Irp;
2285 PFOBX Fobx;
2286 BOOLEAN Locked;
2287 NTSTATUS Status;
2288 PIO_STACK_LOCATION Stack;
2289 FILE_INFORMATION_CLASS FileInfoClass;
2290
2291 PAGED_CODE();
2292
2293 Fcb = (PFCB)Context->pFcb;
2294 Fobx = (PFOBX)Context->pFobx;
2295 DPRINT("RxCommonQueryInformation(%p) FCB: %p, FOBX: %p\n", Context, Fcb, Fobx);
2296
2297 Irp = Context->CurrentIrp;
2298 Stack = Context->CurrentIrpSp;
2299 DPRINT("Buffer: %p, Length: %lx, Class: %ld\n", Irp->AssociatedIrp.SystemBuffer,
2300 Stack->Parameters.QueryFile.Length, Stack->Parameters.QueryFile.FileInformationClass);
2301
2302 Context->Info.Length = Stack->Parameters.QueryFile.Length;
2303 FileInfoClass = Stack->Parameters.QueryFile.FileInformationClass;
2304
2305 Locked = FALSE;
2306 _SEH2_TRY
2307 {
2308 PVOID Buffer;
2309
2310 /* Get a writable buffer */
2311 Buffer = RxMapSystemBuffer(Context);
2312 if (Buffer == NULL)
2313 {
2314 Status = STATUS_INSUFFICIENT_RESOURCES;
2315 _SEH2_LEAVE;
2316 }
2317 /* Zero it */
2318 RtlZeroMemory(Buffer, Context->Info.Length);
2319
2320 /* Validate file type */
2321 if (NodeType(Fcb) != RDBSS_NTC_STORAGE_TYPE_UNKNOWN)
2322 {
2323 if (NodeType(Fcb) < RDBSS_NTC_STORAGE_TYPE_DIRECTORY)
2324 {
2325 Status = STATUS_INVALID_PARAMETER;
2326 _SEH2_LEAVE;
2327 }
2328 else if (NodeType(Fcb) > RDBSS_NTC_STORAGE_TYPE_FILE)
2329 {
2330 if (NodeType(Fcb) == RDBSS_NTC_MAILSLOT)
2331 {
2332 Status = STATUS_NOT_IMPLEMENTED;
2333 }
2334 else
2335 {
2336 Status = STATUS_INVALID_PARAMETER;
2337 }
2338
2339 _SEH2_LEAVE;
2340 }
2341 }
2342
2343 /* Acquire the right lock */
2344 if (!BooleanFlagOn(Fcb->FcbState, FCB_STATE_PAGING_FILE) &&
2345 FileInfoClass != FileNameInformation)
2346 {
2347 if (FileInfoClass == FileCompressionInformation)
2348 {
2349 Status = RxAcquireExclusiveFcb(Context, Fcb);
2350 }
2351 else
2352 {
2353 Status = RxAcquireSharedFcb(Context, Fcb);
2354 }
2355
2356 if (Status == STATUS_LOCK_NOT_GRANTED)
2357 {
2358 Status = STATUS_PENDING;
2359 _SEH2_LEAVE;
2360 }
2361 else if (!NT_SUCCESS(Status))
2362 {
2363 _SEH2_LEAVE;
2364 }
2365
2366 Locked = TRUE;
2367 }
2368
2369 /* Dispatch to the right helper */
2370 switch (FileInfoClass)
2371 {
2372 case FileBasicInformation:
2373 Status = RxQueryBasicInfo(Context, Buffer);
2374 break;
2375
2376 case FileStandardInformation:
2377 Status = RxQueryStandardInfo(Context, Buffer);
2378 break;
2379
2380 case FileInternalInformation:
2381 Status = RxQueryInternalInfo(Context, Buffer);
2382 break;
2383
2384 case FileEaInformation:
2385 Status = RxQueryEaInfo(Context, Buffer);
2386 break;
2387
2388 case FileNameInformation:
2389 Status = RxQueryNameInfo(Context, Buffer);
2390 break;
2391
2392 case FileAllInformation:
2393 SET_SIZE_AND_QUERY(0, RxQueryBasicInfo);
2394 if (!NT_SUCCESS(Status))
2395 {
2396 break;
2397 }
2398
2399 SET_SIZE_AND_QUERY(sizeof(FILE_BASIC_INFORMATION), RxQueryStandardInfo);
2400 if (!NT_SUCCESS(Status))
2401 {
2402 break;
2403 }
2404
2405 SET_SIZE_AND_QUERY(sizeof(FILE_BASIC_INFORMATION) +
2406 sizeof(FILE_STANDARD_INFORMATION), RxQueryInternalInfo);
2407 if (!NT_SUCCESS(Status))
2408 {
2409 break;
2410 }
2411
2412 SET_SIZE_AND_QUERY(sizeof(FILE_BASIC_INFORMATION) +
2413 sizeof(FILE_STANDARD_INFORMATION) +
2414 sizeof(FILE_INTERNAL_INFORMATION), RxQueryEaInfo);
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), RxQueryPositionInfo);
2424 if (!NT_SUCCESS(Status))
2425 {
2426 break;
2427 }
2428
2429 SET_SIZE_AND_QUERY(sizeof(FILE_BASIC_INFORMATION) +
2430 sizeof(FILE_STANDARD_INFORMATION) +
2431 sizeof(FILE_INTERNAL_INFORMATION) +
2432 sizeof(FILE_EA_INFORMATION) +
2433 sizeof(FILE_POSITION_INFORMATION), RxQueryNameInfo);
2434 break;
2435
2436 case FileAlternateNameInformation:
2437 Status = RxQueryAlternateNameInfo(Context, Buffer);
2438 break;
2439
2440 case FilePipeInformation:
2441 case FilePipeLocalInformation:
2442 case FilePipeRemoteInformation:
2443 Status = RxQueryPipeInfo(Context, Buffer);
2444 break;
2445
2446 case FileCompressionInformation:
2447 Status = RxQueryCompressedInfo(Context, Buffer);
2448 break;
2449
2450 default:
2451 Context->IoStatusBlock.Status = RxpQueryInfoMiniRdr(Context, FileInfoClass, Buffer);
2452 Status = Context->IoStatusBlock.Status;
2453 break;
2454 }
2455
2456 if (Context->Info.Length < 0)
2457 {
2458 Status = STATUS_BUFFER_OVERFLOW;
2459 Context->Info.Length = Stack->Parameters.QueryFile.Length;
2460 }
2461
2462 Irp->IoStatus.Information = Stack->Parameters.QueryFile.Length - Context->Info.Length;
2463 }
2464 _SEH2_FINALLY
2465 {
2466 if (Locked)
2467 {
2468 RxReleaseFcb(Context, Fcb);
2469 }
2470 }
2471 _SEH2_END;
2472
2473 DPRINT("Status: %x\n", Status);
2474 return Status;
2475
2476 #undef SET_SIZE_AND_QUERY
2477 }
2478
2479 NTSTATUS
2480 NTAPI
2481 RxCommonQueryQuotaInformation(
2482 PRX_CONTEXT Context)
2483 {
2484 UNIMPLEMENTED;
2485 return STATUS_NOT_IMPLEMENTED;
2486 }
2487
2488 NTSTATUS
2489 NTAPI
2490 RxCommonQuerySecurity(
2491 PRX_CONTEXT Context)
2492 {
2493 UNIMPLEMENTED;
2494 return STATUS_NOT_IMPLEMENTED;
2495 }
2496
2497 /*
2498 * @implemented
2499 */
2500 NTSTATUS
2501 NTAPI
2502 RxCommonQueryVolumeInformation(
2503 PRX_CONTEXT Context)
2504 {
2505 PIRP Irp;
2506 PFCB Fcb;
2507 PFOBX Fobx;
2508 NTSTATUS Status;
2509 PIO_STACK_LOCATION Stack;
2510
2511 PAGED_CODE();
2512
2513 Fcb = (PFCB)Context->pFcb;
2514 Fobx = (PFOBX)Context->pFobx;
2515
2516 DPRINT("RxCommonQueryVolumeInformation(%p) FCB: %p, FOBX: %p\n", Context, Fcb, Fobx);
2517
2518 Irp = Context->CurrentIrp;
2519 Stack = Context->CurrentIrpSp;
2520 DPRINT("Length: %lx, Class: %lx, Buffer %p\n", Stack->Parameters.QueryVolume.Length,
2521 Stack->Parameters.QueryVolume.FsInformationClass, Irp->AssociatedIrp.SystemBuffer);
2522
2523 Context->Info.FsInformationClass = Stack->Parameters.QueryVolume.FsInformationClass;
2524 Context->Info.Buffer = Irp->AssociatedIrp.SystemBuffer;
2525 Context->Info.Length = Stack->Parameters.QueryVolume.Length;
2526
2527 /* Forward to mini-rdr */
2528 MINIRDR_CALL(Status, Context, Fcb->MRxDispatch, MRxQueryVolumeInfo, (Context));
2529
2530 /* Post request if mini-rdr asked to */
2531 if (Context->PostRequest)
2532 {
2533 Status = RxFsdPostRequest(Context);
2534 }
2535 else
2536 {
2537 Irp->IoStatus.Information = Stack->Parameters.QueryVolume.Length - Context->Info.Length;
2538 }
2539
2540 DPRINT("Status: %x\n", Status);
2541 return Status;
2542 }
2543
2544 NTSTATUS
2545 NTAPI
2546 RxCommonRead(
2547 PRX_CONTEXT RxContext)
2548 {
2549 PFCB Fcb;
2550 PIRP Irp;
2551 PFOBX Fobx;
2552 NTSTATUS Status;
2553 PNET_ROOT NetRoot;
2554 PVOID SystemBuffer;
2555 PFILE_OBJECT FileObject;
2556 LARGE_INTEGER ByteOffset;
2557 PIO_STACK_LOCATION Stack;
2558 PLOWIO_CONTEXT LowIoContext;
2559 PRDBSS_DEVICE_OBJECT RxDeviceObject;
2560 ULONG ReadLength, CapturedRxContextSerialNumber = RxContext->SerialNumber;
2561 BOOLEAN CanWait, PagingIo, NoCache, Sync, PostRequest, IsPipe, ReadCachingEnabled, ReadCachingDisabled, InFsp, OwnerSet;
2562
2563 PAGED_CODE();
2564
2565 Fcb = (PFCB)RxContext->pFcb;
2566 Fobx = (PFOBX)RxContext->pFobx;
2567 DPRINT("RxCommonRead(%p) FOBX: %p, FCB: %p\n", RxContext, Fobx, Fcb);
2568
2569 /* Get some parameters */
2570 Irp = RxContext->CurrentIrp;
2571 Stack = RxContext->CurrentIrpSp;
2572 CanWait = BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_WAIT);
2573 PagingIo = BooleanFlagOn(Irp->Flags, IRP_PAGING_IO);
2574 NoCache = BooleanFlagOn(Irp->Flags, IRP_NOCACHE);
2575 Sync = !BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_ASYNC_OPERATION);
2576 InFsp = BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_IN_FSP);
2577 ReadLength = Stack->Parameters.Read.Length;
2578 ByteOffset.QuadPart = Stack->Parameters.Read.ByteOffset.QuadPart;
2579 DPRINT("Reading: %lx@%I64x %s %s %s %s\n", ReadLength, ByteOffset.QuadPart,
2580 (CanWait ? "CW" : "!CW"), (PagingIo ? "PI" : "!PI"), (NoCache ? "NC" : "!NC"), (Sync ? "S" : "!S"));
2581
2582 RxItsTheSameContext();
2583
2584 Irp->IoStatus.Information = 0;
2585
2586 /* Should the read be loud - so far, it's just ignored on ReactOS:
2587 * s/DPRINT/DPRINT1/g will make it loud
2588 */
2589 LowIoContext = &RxContext->LowIoContext;
2590 CheckForLoudOperations(RxContext);
2591 if (BooleanFlagOn(LowIoContext->Flags, LOWIO_CONTEXT_FLAG_LOUDOPS))
2592 {
2593 DPRINT("LoudRead %I64x/%lx on %lx vdl/size/alloc %I64x/%I64x/%I64x\n",
2594 ByteOffset, ReadLength,
2595 Fcb, Fcb->Header.ValidDataLength, Fcb->Header.FileSize, Fcb->Header.AllocationSize);
2596 }
2597
2598 RxDeviceObject = RxContext->RxDeviceObject;
2599 /* Update stats */
2600 if (!BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_IN_FSP) && Fcb->CachedNetRootType == NET_ROOT_DISK)
2601 {
2602 InterlockedIncrement((volatile long *)&RxDeviceObject->ReadOperations);
2603
2604 if (ByteOffset.QuadPart != Fobx->Specific.DiskFile.PredictedReadOffset)
2605 {
2606 InterlockedIncrement((volatile long *)&RxDeviceObject->RandomReadOperations);
2607 }
2608 Fobx->Specific.DiskFile.PredictedReadOffset = ByteOffset.QuadPart + ReadLength;
2609
2610 if (PagingIo)
2611 {
2612 ExInterlockedAddLargeStatistic(&RxDeviceObject->PagingReadBytesRequested, ReadLength);
2613 }
2614 else if (NoCache)
2615 {
2616 ExInterlockedAddLargeStatistic(&RxDeviceObject->NonPagingReadBytesRequested, ReadLength);
2617 }
2618 else
2619 {
2620 ExInterlockedAddLargeStatistic(&RxDeviceObject->CacheReadBytesRequested, ReadLength);
2621 }
2622 }
2623
2624 /* A pagefile cannot be a pipe */
2625 IsPipe = Fcb->NetRoot->Type == NET_ROOT_PIPE;
2626 if (IsPipe && PagingIo)
2627 {
2628 return STATUS_INVALID_DEVICE_REQUEST;
2629 }
2630
2631 /* Null-length read is no-op */
2632 if (ReadLength == 0)
2633 {
2634 return STATUS_SUCCESS;
2635 }
2636
2637 /* Validate FCB type */
2638 if (NodeType(Fcb) != RDBSS_NTC_STORAGE_TYPE_FILE && NodeType(Fcb) != RDBSS_NTC_VOLUME_FCB)
2639 {
2640 return STATUS_INVALID_DEVICE_REQUEST;
2641 }
2642
2643 /* Init the lowio context for possible forward */
2644 RxInitializeLowIoContext(LowIoContext, LOWIO_OP_READ);
2645
2646 PostRequest = FALSE;
2647 ReadCachingDisabled = FALSE;
2648 OwnerSet = FALSE;
2649 ReadCachingEnabled = BooleanFlagOn(Fcb->FcbState, FCB_STATE_READCACHING_ENABLED);
2650 FileObject = Stack->FileObject;
2651 NetRoot = (PNET_ROOT)Fcb->pNetRoot;
2652 _SEH2_TRY
2653 {
2654 LONGLONG FileSize;
2655
2656 /* If no caching, make sure current Cc data have been flushed */
2657 if (!PagingIo && NoCache && !ReadCachingEnabled && FileObject->SectionObjectPointer != NULL)
2658 {
2659 Status = RxAcquireExclusiveFcb(RxContext, Fcb);
2660 if (Status == STATUS_LOCK_NOT_GRANTED)
2661 {
2662 PostRequest = TRUE;
2663 _SEH2_LEAVE;
2664 }
2665 else if (Status != STATUS_SUCCESS)
2666 {
2667 _SEH2_LEAVE;
2668 }
2669
2670 ExAcquireResourceSharedLite(Fcb->Header.PagingIoResource, TRUE);
2671 CcFlushCache(FileObject->SectionObjectPointer, &ByteOffset, ReadLength, &Irp->IoStatus);
2672 RxReleasePagingIoResource(RxContext, Fcb);
2673
2674 if (!NT_SUCCESS(Irp->IoStatus.Status))
2675 {
2676 _SEH2_LEAVE;
2677 }
2678
2679 RxAcquirePagingIoResource(RxContext, Fcb);
2680 RxReleasePagingIoResource(RxContext, Fcb);
2681 }
2682
2683 /* Acquire the appropriate lock */
2684 if (PagingIo && !ReadCachingEnabled)
2685 {
2686 ASSERT(!IsPipe);
2687
2688 if (!ExAcquireResourceSharedLite(Fcb->Header.PagingIoResource, CanWait))
2689 {
2690 PostRequest = TRUE;
2691 _SEH2_LEAVE;
2692 }
2693
2694 if (!CanWait)
2695 {
2696 LowIoContext->Resource = Fcb->Header.PagingIoResource;
2697 }
2698 }
2699 else
2700 {
2701 if (!ReadCachingEnabled)
2702 {
2703 if (!CanWait && NoCache)
2704 {
2705 Status = RxAcquireSharedFcbWaitForEx(RxContext, Fcb);
2706 if (Status == STATUS_LOCK_NOT_GRANTED)
2707 {
2708 DPRINT1("RdAsyLNG %x\n", RxContext);
2709 PostRequest = TRUE;
2710 _SEH2_LEAVE;
2711 }
2712 if (Status != STATUS_SUCCESS)
2713 {
2714 DPRINT1("RdAsyOthr %x\n", RxContext);
2715 _SEH2_LEAVE;
2716 }
2717
2718 if (RxIsFcbAcquiredShared(Fcb) <= 0xF000)
2719 {
2720 LowIoContext->Resource = Fcb->Header.Resource;
2721 }
2722 else
2723 {
2724 PostRequest = TRUE;
2725 _SEH2_LEAVE;
2726 }
2727 }
2728 else
2729 {
2730 Status = RxAcquireSharedFcb(RxContext, Fcb);
2731 if (Status == STATUS_LOCK_NOT_GRANTED)
2732 {
2733 PostRequest = TRUE;
2734 _SEH2_LEAVE;
2735 }
2736 else if (Status != STATUS_SUCCESS)
2737 {
2738 _SEH2_LEAVE;
2739 }
2740 }
2741 }
2742 }
2743
2744 RxItsTheSameContext();
2745
2746 ReadCachingDisabled = (ReadCachingEnabled == FALSE);
2747 if (IsPipe)
2748 {
2749 UNIMPLEMENTED;
2750 }
2751
2752 RxGetFileSizeWithLock(Fcb, &FileSize);
2753
2754 /* Make sure FLOCK doesn't conflict */
2755 if (!PagingIo)
2756 {
2757 if (!FsRtlCheckLockForReadAccess(&Fcb->Specific.Fcb.FileLock, Irp))
2758 {
2759 Status = STATUS_FILE_LOCK_CONFLICT;
2760 _SEH2_LEAVE;
2761 }
2762 }
2763
2764 /* Validate byteoffset vs length */
2765 if (BooleanFlagOn(Fcb->FcbState, FCB_STATE_READCACHING_ENABLED))
2766 {
2767 if (ByteOffset.QuadPart >= FileSize)
2768 {
2769 Status = STATUS_END_OF_FILE;
2770 _SEH2_LEAVE;
2771 }
2772
2773 if (ReadLength > FileSize - ByteOffset.QuadPart)
2774 {
2775 ReadLength = FileSize - ByteOffset.QuadPart;
2776 }
2777 }
2778
2779 /* Read with Cc! */
2780 if (!PagingIo && !NoCache && ReadCachingEnabled &&
2781 !BooleanFlagOn(Fobx->pSrvOpen->Flags, SRVOPEN_FLAG_DONTUSE_READ_CACHING))
2782 {
2783 /* File was not cached yet, do it */
2784 if (FileObject->PrivateCacheMap == NULL)
2785 {
2786 if (BooleanFlagOn(FileObject->Flags, FO_CLEANUP_COMPLETE))
2787 {
2788 Status = STATUS_FILE_CLOSED;
2789 _SEH2_LEAVE;
2790 }
2791
2792 RxAdjustAllocationSizeforCC(Fcb);
2793
2794 CcInitializeCacheMap(FileObject, (PCC_FILE_SIZES)&Fcb->Header.AllocationSize,
2795 FALSE, &RxData.CacheManagerCallbacks, Fcb);
2796
2797 if (BooleanFlagOn(Fcb->MRxDispatch->MRxFlags, RDBSS_NO_DEFERRED_CACHE_READAHEAD))
2798 {
2799 CcSetAdditionalCacheAttributes(FileObject, FALSE, FALSE);
2800 }
2801 else
2802 {
2803 CcSetAdditionalCacheAttributes(FileObject, TRUE, FALSE);
2804 SetFlag(Fcb->FcbState, FCB_STATE_READAHEAD_DEFERRED);
2805 }
2806
2807 CcSetReadAheadGranularity(FileObject, NetRoot->DiskParameters.ReadAheadGranularity);
2808 }
2809
2810 /* This should never happen - fix your RDR */
2811 if (BooleanFlagOn(RxContext->MinorFunction, IRP_MN_MDL))
2812 {
2813 ASSERT(FALSE);
2814 ASSERT(CanWait);
2815
2816 CcMdlRead(FileObject, &ByteOffset, ReadLength, &Irp->MdlAddress, &Irp->IoStatus);
2817 Status = Irp->IoStatus.Status;
2818 ASSERT(NT_SUCCESS(Status));
2819 }
2820 else
2821 {
2822 /* Map buffer */
2823 SystemBuffer = RxNewMapUserBuffer(RxContext);
2824 if (SystemBuffer == NULL)
2825 {
2826 Status = STATUS_INSUFFICIENT_RESOURCES;
2827 _SEH2_LEAVE;
2828 }
2829
2830 SetFlag(Fcb->FcbState, FCB_STATE_READCACHING_ENABLED);
2831
2832 RxItsTheSameContext();
2833
2834 /* Perform the read */
2835 if (!CcCopyRead(FileObject, &ByteOffset, ReadLength, CanWait, SystemBuffer, &Irp->IoStatus))
2836 {
2837 if (!ReadCachingEnabled)
2838 {
2839 ClearFlag(Fcb->FcbState, FCB_STATE_READCACHING_ENABLED);
2840 }
2841
2842 RxItsTheSameContext();
2843
2844 PostRequest = TRUE;
2845 _SEH2_LEAVE;
2846 }
2847
2848 if (!ReadCachingEnabled)
2849 {
2850 ClearFlag(Fcb->FcbState, FCB_STATE_READCACHING_ENABLED);
2851 }
2852
2853 Status = Irp->IoStatus.Status;
2854 ASSERT(NT_SUCCESS(Status));
2855 }
2856 }
2857 else
2858 {
2859 /* Validate the reading */
2860 if (FileObject->PrivateCacheMap != NULL && BooleanFlagOn(Fcb->FcbState, FCB_STATE_READAHEAD_DEFERRED) &&
2861 ByteOffset.QuadPart >= 4096)
2862 {
2863 CcSetAdditionalCacheAttributes(FileObject, FALSE, FALSE);
2864 ClearFlag(Fcb->FcbState, FCB_STATE_READAHEAD_DEFERRED);
2865 }
2866
2867 /* If it's consistent, forward to mini-rdr */
2868 if (Fcb->CachedNetRootType != NET_ROOT_DISK || BooleanFlagOn(Fcb->FcbState, FCB_STATE_READAHEAD_DEFERRED) ||
2869 ByteOffset.QuadPart < Fcb->Header.ValidDataLength.QuadPart)
2870 {
2871 LowIoContext->ParamsFor.ReadWrite.ByteCount = ReadLength;
2872 LowIoContext->ParamsFor.ReadWrite.ByteOffset = ByteOffset.QuadPart;
2873
2874 RxItsTheSameContext();
2875
2876 if (InFsp && ReadCachingDisabled)
2877 {
2878 ExSetResourceOwnerPointer((PagingIo ? Fcb->Header.PagingIoResource : Fcb->Header.Resource),
2879 (PVOID)((ULONG_PTR)RxContext | 3));
2880 OwnerSet = TRUE;
2881 }
2882
2883 Status = RxLowIoReadShell(RxContext);
2884
2885 RxItsTheSameContext();
2886 }
2887 else
2888 {
2889 if (ByteOffset.QuadPart > FileSize)
2890 {
2891 ReadLength = 0;
2892 Irp->IoStatus.Information = ReadLength;
2893 _SEH2_LEAVE;
2894 }
2895
2896 if (ByteOffset.QuadPart + ReadLength > FileSize)
2897 {
2898 ReadLength = FileSize - ByteOffset.QuadPart;
2899 }
2900
2901 SystemBuffer = RxNewMapUserBuffer(RxContext);
2902 RtlZeroMemory(SystemBuffer, ReadLength);
2903 Irp->IoStatus.Information = ReadLength;
2904 }
2905 }
2906 }
2907 _SEH2_FINALLY
2908 {
2909 RxItsTheSameContext();
2910
2911 /* Post if required */
2912 if (PostRequest)
2913 {
2914 InterlockedIncrement((volatile long *)&RxContext->ReferenceCount);
2915 Status = RxFsdPostRequest(RxContext);
2916 }
2917 else
2918 {
2919 /* Update FO in case of sync IO */
2920 if (!IsPipe && !PagingIo)
2921 {
2922 if (BooleanFlagOn(FileObject->Flags, FO_SYNCHRONOUS_IO))
2923 {
2924 FileObject->CurrentByteOffset.QuadPart = ByteOffset.QuadPart + Irp->IoStatus.Information;
2925 }
2926 }
2927 }
2928
2929 /* Set FastIo if read was a success */
2930 if (NT_SUCCESS(Status) && Status != STATUS_PENDING)
2931 {
2932 if (!IsPipe && !PagingIo)
2933 {
2934 SetFlag(FileObject->Flags, FO_FILE_FAST_IO_READ);
2935 }
2936 }
2937
2938 /* In case we're done (not expected any further processing */
2939 if (_SEH2_AbnormalTermination() || Status != STATUS_PENDING || PostRequest)
2940 {
2941 /* Release everything that can be */
2942 if (ReadCachingDisabled)
2943 {
2944 if (PagingIo)
2945 {
2946 if (OwnerSet)
2947 {
2948 RxReleasePagingIoResourceForThread(RxContext, Fcb, LowIoContext->ResourceThreadId);
2949 }
2950 else
2951 {
2952 RxReleasePagingIoResource(RxContext, Fcb);
2953 }
2954 }
2955 else
2956 {
2957 if (OwnerSet)
2958 {
2959 RxReleaseFcbForThread(RxContext, Fcb, LowIoContext->ResourceThreadId);
2960 }
2961 else
2962 {
2963 RxReleaseFcb(RxContext, Fcb);
2964 }
2965 }
2966 }
2967
2968 /* Dereference/Delete context */
2969 if (PostRequest)
2970 {
2971 RxDereferenceAndDeleteRxContext(RxContext);
2972 }
2973 else
2974 {
2975 if (BooleanFlagOn(RxContext->FlagsForLowIo, RXCONTEXT_FLAG4LOWIO_PIPE_SYNC_OPERATION))
2976 {
2977 RxResumeBlockedOperations_Serially(RxContext, &Fobx->Specific.NamedPipe.ReadSerializationQueue);
2978 }
2979 }
2980
2981 /* We cannot return more than asked */
2982 if (Status == STATUS_SUCCESS)
2983 {
2984 ASSERT(Irp->IoStatus.Information <= Stack->Parameters.Read.Length);
2985 }
2986 }
2987 else
2988 {
2989 ASSERT(!Sync);
2990
2991 RxDereferenceAndDeleteRxContext(RxContext);
2992 }
2993 }
2994 _SEH2_END;
2995
2996 return Status;
2997 }
2998
2999 NTSTATUS
3000 NTAPI
3001 RxCommonSetEa(
3002 PRX_CONTEXT Context)
3003 {
3004 UNIMPLEMENTED;
3005 return STATUS_NOT_IMPLEMENTED;
3006 }
3007
3008 NTSTATUS
3009 NTAPI
3010 RxCommonSetInformation(
3011 PRX_CONTEXT Context)
3012 {
3013 UNIMPLEMENTED;
3014 return STATUS_NOT_IMPLEMENTED;
3015 }
3016
3017 NTSTATUS
3018 NTAPI
3019 RxCommonSetQuotaInformation(
3020 PRX_CONTEXT Context)
3021 {
3022 UNIMPLEMENTED;
3023 return STATUS_NOT_IMPLEMENTED;
3024 }
3025
3026 NTSTATUS
3027 NTAPI
3028 RxCommonSetSecurity(
3029 PRX_CONTEXT Context)
3030 {
3031 UNIMPLEMENTED;
3032 return STATUS_NOT_IMPLEMENTED;
3033 }
3034
3035 NTSTATUS
3036 NTAPI
3037 RxCommonSetVolumeInformation(
3038 PRX_CONTEXT Context)
3039 {
3040 UNIMPLEMENTED;
3041 return STATUS_NOT_IMPLEMENTED;
3042 }
3043
3044 NTSTATUS
3045 NTAPI
3046 RxCommonUnimplemented(
3047 PRX_CONTEXT Context)
3048 {
3049 UNIMPLEMENTED;
3050 return STATUS_NOT_IMPLEMENTED;
3051 }
3052
3053 NTSTATUS
3054 NTAPI
3055 RxCommonWrite(
3056 PRX_CONTEXT Context)
3057 {
3058 UNIMPLEMENTED;
3059 return STATUS_NOT_IMPLEMENTED;
3060 }
3061
3062 NTSTATUS
3063 NTAPI
3064 RxCompleteMdl(
3065 IN PRX_CONTEXT RxContext)
3066 {
3067 PAGED_CODE();
3068
3069 UNIMPLEMENTED;
3070 return STATUS_NOT_IMPLEMENTED;
3071 }
3072
3073 /*
3074 * @implemented
3075 */
3076 VOID
3077 RxCopyCreateParameters(
3078 IN PRX_CONTEXT RxContext)
3079 {
3080 PIRP Irp;
3081 PVOID DfsContext;
3082 PFILE_OBJECT FileObject;
3083 PIO_STACK_LOCATION Stack;
3084 PDFS_NAME_CONTEXT DfsNameContext;
3085 PIO_SECURITY_CONTEXT SecurityContext;
3086
3087 Irp = RxContext->CurrentIrp;
3088 Stack = RxContext->CurrentIrpSp;
3089 FileObject = Stack->FileObject;
3090 SecurityContext = Stack->Parameters.Create.SecurityContext;
3091
3092 RxContext->Create.NtCreateParameters.SecurityContext = SecurityContext;
3093 if (SecurityContext->AccessState != NULL && SecurityContext->AccessState->SecurityDescriptor != NULL)
3094 {
3095 RxContext->Create.SdLength = RtlLengthSecurityDescriptor(SecurityContext->AccessState->SecurityDescriptor);
3096 DPRINT("SD Ctxt: %p, Length: %lx\n", RxContext->Create.NtCreateParameters.SecurityContext,
3097 RxContext->Create.SdLength);
3098 }
3099 if (SecurityContext->SecurityQos != NULL)
3100 {
3101 RxContext->Create.NtCreateParameters.ImpersonationLevel = SecurityContext->SecurityQos->ImpersonationLevel;
3102 }
3103 else
3104 {
3105 RxContext->Create.NtCreateParameters.ImpersonationLevel = SecurityImpersonation;
3106 }
3107 RxContext->Create.NtCreateParameters.DesiredAccess = SecurityContext->DesiredAccess;
3108
3109 RxContext->Create.NtCreateParameters.AllocationSize.QuadPart = Irp->Overlay.AllocationSize.QuadPart;
3110 RxContext->Create.NtCreateParameters.FileAttributes = Stack->Parameters.Create.FileAttributes & FILE_ATTRIBUTE_VALID_FLAGS;
3111 RxContext->Create.NtCreateParameters.ShareAccess = Stack->Parameters.Create.ShareAccess & FILE_SHARE_VALID_FLAGS;
3112 RxContext->Create.NtCreateParameters.Disposition = (Stack->Parameters.Create.Options >> 24) & 0x000000FF;
3113 RxContext->Create.NtCreateParameters.CreateOptions = Stack->Parameters.Create.Options & 0xFFFFFF;
3114
3115 DfsContext = FileObject->FsContext2;
3116 DfsNameContext = FileObject->FsContext;
3117 RxContext->Create.NtCreateParameters.DfsContext = DfsContext;
3118 RxContext->Create.NtCreateParameters.DfsNameContext = DfsNameContext;
3119 ASSERT(DfsContext == NULL || DfsContext == UIntToPtr(DFS_OPEN_CONTEXT) ||
3120 DfsContext == UIntToPtr(DFS_DOWNLEVEL_OPEN_CONTEXT) ||
3121 DfsContext == UIntToPtr(DFS_CSCAGENT_NAME_CONTEXT) ||
3122 DfsContext == UIntToPtr(DFS_USER_NAME_CONTEXT));
3123 ASSERT(DfsNameContext == NULL || DfsNameContext->NameContextType == DFS_OPEN_CONTEXT ||
3124 DfsNameContext->NameContextType == DFS_DOWNLEVEL_OPEN_CONTEXT ||
3125 DfsNameContext->NameContextType == DFS_CSCAGENT_NAME_CONTEXT ||
3126 DfsNameContext->NameContextType == DFS_USER_NAME_CONTEXT);
3127 FileObject->FsContext2 = NULL;
3128 FileObject->FsContext = NULL;
3129
3130 RxContext->pFcb = NULL;
3131 RxContext->Create.ReturnedCreateInformation = 0;
3132
3133 /* if we stripped last \, it has to be a directory! */
3134 if (BooleanFlagOn(RxContext->Create.Flags, RX_CONTEXT_CREATE_FLAG_STRIPPED_TRAILING_BACKSLASH))
3135 {
3136 SetFlag(RxContext->Create.NtCreateParameters.CreateOptions, FILE_DIRECTORY_FILE);
3137 }
3138
3139 RxContext->Create.EaLength = Stack->Parameters.Create.EaLength;
3140 if (RxContext->Create.EaLength == 0)
3141 {
3142 RxContext->Create.EaBuffer = NULL;
3143 }
3144 else
3145 {
3146 RxContext->Create.EaBuffer = Irp->AssociatedIrp.SystemBuffer;
3147 DPRINT("EA Buffer: %p, Length: %lx\n", Irp->AssociatedIrp.SystemBuffer, RxContext->Create.EaLength);
3148 }
3149 }
3150
3151 NTSTATUS
3152 RxCreateFromNetRoot(
3153 PRX_CONTEXT Context,
3154 PUNICODE_STRING NetRootName)
3155 {
3156 PFCB Fcb;
3157 NTSTATUS Status;
3158 PNET_ROOT NetRoot;
3159 PFILE_OBJECT FileObject;
3160 PIO_STACK_LOCATION Stack;
3161 ACCESS_MASK DesiredAccess;
3162 USHORT DesiredShareAccess;
3163
3164 PAGED_CODE();
3165
3166 /* Validate that the context is consistent */
3167 if (Context->Create.pNetRoot == NULL)
3168 {
3169 return STATUS_BAD_NETWORK_PATH;
3170 }
3171
3172 NetRoot = (PNET_ROOT)Context->Create.pNetRoot;
3173 if (Context->RxDeviceObject != NetRoot->pSrvCall->RxDeviceObject)
3174 {
3175 return STATUS_BAD_NETWORK_PATH;
3176 }
3177
3178 if (Context->Create.NtCreateParameters.DfsContext == UIntToPtr(DFS_OPEN_CONTEXT) &&
3179 !BooleanFlagOn(NetRoot->pSrvCall->Flags, SRVCALL_FLAG_DFS_AWARE_SERVER))
3180 {
3181 return STATUS_DFS_UNAVAILABLE;
3182 }
3183
3184 if (Context->Create.NtCreateParameters.DfsContext == UIntToPtr(DFS_DOWNLEVEL_OPEN_CONTEXT) &&
3185 BooleanFlagOn(NetRoot->Flags, NETROOT_FLAG_DFS_AWARE_NETROOT))
3186 {
3187 return STATUS_OBJECT_TYPE_MISMATCH;
3188 }
3189
3190 Stack = Context->CurrentIrpSp;
3191 DesiredShareAccess = Stack->Parameters.Create.ShareAccess & FILE_SHARE_VALID_FLAGS;
3192 if (NetRoot->Type == NET_ROOT_PRINT)
3193 {
3194 DesiredShareAccess = FILE_SHARE_VALID_FLAGS;
3195 }
3196
3197 DesiredAccess = Stack->Parameters.Create.SecurityContext->DesiredAccess & FILE_ALL_ACCESS;
3198
3199 /* We don't support renaming yet */
3200 if (BooleanFlagOn(Stack->Flags, SL_OPEN_TARGET_DIRECTORY))
3201 {
3202 UNIMPLEMENTED;
3203 return STATUS_NOT_IMPLEMENTED;
3204 }
3205
3206 /* Try to find (or create) the FCB for the file */
3207 Status = RxFindOrCreateFcb(Context, NetRootName);
3208 Fcb = (PFCB)Context->pFcb;
3209 if (Fcb == NULL)
3210 {
3211 ASSERT(!NT_SUCCESS(Status));
3212 }
3213 if (!NT_SUCCESS(Status) || Fcb == NULL)
3214 {
3215 return Status;
3216 }
3217
3218 if (BooleanFlagOn(Context->Flags, RX_CONTEXT_FLAG_CREATE_MAILSLOT))
3219 {
3220 Fcb->Header.NodeTypeCode = RDBSS_NTC_MAILSLOT;
3221 }
3222 else
3223 {
3224 Status = STATUS_MORE_PROCESSING_REQUIRED;
3225 }
3226
3227 /* If finding FCB worked (mailslot case), mark the FCB as good and quit */
3228 if (NT_SUCCESS(Status))
3229 {
3230 RxTransitionNetFcb(Fcb, Condition_Good);
3231 DPRINT("Transitioning FCB %lx Condition %lx\n", Fcb, Fcb->Condition);
3232 ++Fcb->OpenCount;
3233 RxSetupNetFileObject(Context);
3234 return STATUS_SUCCESS;
3235 }
3236
3237 /* Not mailslot! */
3238 FileObject = Stack->FileObject;
3239 /* Check SA for conflict */
3240 if (Fcb->OpenCount > 0)
3241 {
3242 Status = RxCheckShareAccess(DesiredAccess, DesiredShareAccess, FileObject,
3243 &Fcb->ShareAccess, FALSE, "early check per useropens", "EarlyPerUO");
3244 if (!NT_SUCCESS(Status))
3245 {
3246 RxDereferenceNetFcb(Fcb);
3247 return Status;
3248 }
3249 }
3250
3251 if (BooleanFlagOn(Context->Create.NtCreateParameters.CreateOptions, FILE_DELETE_ON_CLOSE) &&
3252 !BooleanFlagOn(Context->Create.NtCreateParameters.DesiredAccess, ~SYNCHRONIZE))
3253 {
3254 UNIMPLEMENTED;
3255 }
3256
3257 _SEH2_TRY
3258 {
3259 /* Find a SRV_OPEN that suits the opening */
3260 Status = RxCollapseOrCreateSrvOpen(Context);
3261 if (Status == STATUS_SUCCESS)
3262 {
3263 PFOBX Fobx;
3264 PSRV_OPEN SrvOpen;
3265
3266 SrvOpen = (PSRV_OPEN)Context->pRelevantSrvOpen;
3267 Fobx = (PFOBX)Context->pFobx;
3268 /* There are already opens, check for conflict */
3269 if (Fcb->OpenCount != 0)
3270 {
3271 if (!NT_SUCCESS(RxCheckShareAccess(DesiredAccess, DesiredShareAccess,
3272 FileObject, &Fcb->ShareAccess,
3273 FALSE, "second check per useropens",
3274 "2ndAccPerUO")))
3275 {
3276 ++SrvOpen->UncleanFobxCount;
3277 RxDereferenceNetFobx(Fobx, LHS_LockNotHeld);
3278
3279 _SEH2_LEAVE;
3280 }
3281 }
3282 else
3283 {
3284 if (NetRoot->Type != NET_ROOT_PIPE)
3285 {
3286 RxSetShareAccess(DesiredAccess, DesiredShareAccess, FileObject,
3287 &Fcb->ShareAccess, "initial shareaccess setup", "InitShrAcc");
3288 }
3289 }
3290
3291 RxSetupNetFileObject(Context);
3292
3293 /* No conflict? Set up SA */
3294 if (Fcb->OpenCount != 0 && NetRoot->Type != NET_ROOT_PIPE)
3295 {
3296 RxUpdateShareAccess(FileObject, &Fcb->ShareAccess, "update share access", "UpdShrAcc");
3297 }
3298
3299 ++Fcb->UncleanCount;
3300 if (BooleanFlagOn(FileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING))
3301 {
3302 ++Fcb->UncachedUncleanCount;
3303 }
3304
3305 if (SrvOpen->UncleanFobxCount == 0 && Fcb->UncleanCount == 1 &&
3306 !BooleanFlagOn(SrvOpen->Flags, SRVOPEN_FLAG_NO_BUFFERING_STATE_CHANGE))
3307 {
3308 RxChangeBufferingState(SrvOpen, NULL, FALSE);
3309 }
3310
3311 /* No pending close, we're active */
3312 ClearFlag(Fcb->FcbState, FCB_STATE_DELAY_CLOSE);
3313
3314 ++Fcb->OpenCount;
3315 ++SrvOpen->UncleanFobxCount;
3316 ++SrvOpen->OpenCount;
3317 SrvOpen->ulFileSizeVersion = Fcb->ulFileSizeVersion;
3318
3319 if (BooleanFlagOn(Stack->Parameters.Create.Options, FILE_NO_INTERMEDIATE_BUFFERING))
3320 {
3321 SetFlag(SrvOpen->Flags, SRVOPEN_FLAG_DONTUSE_READ_CACHING);
3322 SetFlag(SrvOpen->Flags, SRVOPEN_FLAG_DONTUSE_WRITE_CACHING);
3323
3324 ClearFlag(Fcb->FcbState, FCB_STATE_WRITECACHING_ENABLED);
3325 ClearFlag(Fcb->FcbState, FCB_STATE_READCACHING_ENABLED);
3326
3327 RxPurgeFcbInSystemCache(Fcb, NULL, 0, TRUE, TRUE);
3328 }
3329
3330 /* Now, update SA for the SRV_OPEN */
3331 RxUpdateShareAccessPerSrvOpens(SrvOpen);
3332
3333 if (BooleanFlagOn(Stack->Parameters.Create.Options, FILE_DELETE_ON_CLOSE))
3334 {
3335 SetFlag(Fobx->Flags, FOBX_FLAG_DELETE_ON_CLOSE);
3336 }
3337
3338 /* Update the FOBX info */
3339 if (Fobx != NULL)
3340 {
3341 if (Context->Create.pNetRoot->Type == NET_ROOT_PIPE)
3342 {
3343 SetFlag(FileObject->Flags, FO_NAMED_PIPE);
3344 }
3345
3346 if (Context->Create.pNetRoot->Type == NET_ROOT_PRINT ||
3347 Context->Create.pNetRoot->Type == NET_ROOT_PIPE)
3348 {
3349 Fobx->PipeHandleInformation = &Fobx->Specific.NamedPipe.PipeHandleInformation;