[RDBSS]
[reactos.git] / reactos / sdk / lib / drivers / rdbsslib / rdbss.c
1 /*
2 * ReactOS kernel
3 * Copyright (C) 2017 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19 /*
20 * COPYRIGHT: See COPYING in the top level directory
21 * PROJECT: ReactOS kernel
22 * FILE: sdk/lib/drivers/rdbsslib/rdbss.c
23 * PURPOSE: RDBSS library
24 * PROGRAMMER: Pierre Schweitzer (pierre@reactos.org)
25 */
26
27 /* INCLUDES *****************************************************************/
28
29 #include <rx.h>
30 #include <pseh/pseh2.h>
31 #include <limits.h>
32 #include <dfs.h>
33 #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 NTSTATUS
348 RxLowIoWriteShell(
349 IN PRX_CONTEXT RxContext);
350
351 NTSTATUS
352 NTAPI
353 RxLowIoWriteShellCompletion(
354 PRX_CONTEXT RxContext);
355
356 PVOID
357 RxNewMapUserBuffer(
358 PRX_CONTEXT RxContext);
359
360 NTSTATUS
361 RxNotifyChangeDirectory(
362 PRX_CONTEXT RxContext);
363
364 NTSTATUS
365 RxpQueryInfoMiniRdr(
366 PRX_CONTEXT RxContext,
367 FILE_INFORMATION_CLASS FileInfoClass,
368 PVOID Buffer);
369
370 VOID
371 RxPurgeNetFcb(
372 PFCB Fcb,
373 PRX_CONTEXT LocalContext);
374
375 NTSTATUS
376 RxQueryAlternateNameInfo(
377 PRX_CONTEXT RxContext,
378 PFILE_NAME_INFORMATION AltNameInfo);
379
380 NTSTATUS
381 RxQueryBasicInfo(
382 PRX_CONTEXT RxContext,
383 PFILE_BASIC_INFORMATION BasicInfo);
384
385 NTSTATUS
386 RxQueryCompressedInfo(
387 PRX_CONTEXT RxContext,
388 PFILE_COMPRESSION_INFORMATION CompressionInfo);
389
390 NTSTATUS
391 RxQueryDirectory(
392 PRX_CONTEXT RxContext);
393
394 NTSTATUS
395 RxQueryEaInfo(
396 PRX_CONTEXT RxContext,
397 PFILE_EA_INFORMATION EaInfo);
398
399 NTSTATUS
400 RxQueryInternalInfo(
401 PRX_CONTEXT RxContext,
402 PFILE_INTERNAL_INFORMATION InternalInfo);
403
404 NTSTATUS
405 RxQueryNameInfo(
406 PRX_CONTEXT RxContext,
407 PFILE_NAME_INFORMATION NameInfo);
408
409 NTSTATUS
410 RxQueryPipeInfo(
411 PRX_CONTEXT RxContext,
412 PFILE_PIPE_INFORMATION PipeInfo);
413
414 NTSTATUS
415 RxQueryPositionInfo(
416 PRX_CONTEXT RxContext,
417 PFILE_POSITION_INFORMATION PositionInfo);
418
419 NTSTATUS
420 RxQueryStandardInfo(
421 PRX_CONTEXT RxContext,
422 PFILE_STANDARD_INFORMATION StandardInfo);
423
424 VOID
425 NTAPI
426 RxReadRegistryParameters(
427 VOID);
428
429 VOID
430 NTAPI
431 RxReleaseFileForNtCreateSection(
432 PFILE_OBJECT FileObject);
433
434 NTSTATUS
435 NTAPI
436 RxReleaseForCcFlush(
437 PFILE_OBJECT FileObject,
438 PDEVICE_OBJECT DeviceObject);
439
440 PRX_CONTEXT
441 RxRemoveOverflowEntry(
442 PRDBSS_DEVICE_OBJECT DeviceObject,
443 WORK_QUEUE_TYPE Queue);
444
445 NTSTATUS
446 RxSearchForCollapsibleOpen(
447 PRX_CONTEXT RxContext,
448 ACCESS_MASK DesiredAccess,
449 ULONG ShareAccess);
450
451 NTSTATUS
452 RxSetAllocationInfo(
453 PRX_CONTEXT RxContext);
454
455 NTSTATUS
456 RxSetBasicInfo(
457 PRX_CONTEXT RxContext);
458
459 NTSTATUS
460 RxSetDispositionInfo(
461 PRX_CONTEXT RxContext);
462
463 NTSTATUS
464 RxSetEndOfFileInfo(
465 PRX_CONTEXT RxContext);
466
467 NTSTATUS
468 RxSetPipeInfo(
469 PRX_CONTEXT RxContext);
470
471 NTSTATUS
472 RxSetPositionInfo(
473 PRX_CONTEXT RxContext);
474
475 NTSTATUS
476 RxSetRenameInfo(
477 PRX_CONTEXT RxContext);
478
479 NTSTATUS
480 RxSetSimpleInfo(
481 PRX_CONTEXT RxContext);
482
483 VOID
484 RxSetupNetFileObject(
485 PRX_CONTEXT RxContext);
486
487 NTSTATUS
488 RxSystemControl(
489 IN PRDBSS_DEVICE_OBJECT RxDeviceObject,
490 IN PIRP Irp);
491
492 VOID
493 RxUninitializeCacheMap(
494 PRX_CONTEXT RxContext,
495 PFILE_OBJECT FileObject,
496 PLARGE_INTEGER TruncateSize);
497
498 VOID
499 RxUnstart(
500 PRX_CONTEXT Context,
501 PRDBSS_DEVICE_OBJECT DeviceObject);
502
503 NTSTATUS
504 RxXXXControlFileCallthru(
505 PRX_CONTEXT Context);
506
507 PVOID
508 NTAPI
509 _RxAllocatePoolWithTag(
510 _In_ POOL_TYPE PoolType,
511 _In_ SIZE_T NumberOfBytes,
512 _In_ ULONG Tag);
513
514 VOID
515 NTAPI
516 _RxFreePool(
517 _In_ PVOID Buffer);
518
519 VOID
520 NTAPI
521 _RxFreePoolWithTag(
522 _In_ PVOID Buffer,
523 _In_ ULONG Tag);
524
525 WCHAR RxStarForTemplate = '*';
526 WCHAR Rx8QMdot3QM[] = L">>>>>>>>.>>>*";
527 BOOLEAN DisableByteRangeLockingOnReadOnlyFiles = FALSE;
528 BOOLEAN DisableFlushOnCleanup = FALSE;
529 ULONG ReadAheadGranularity = 1 << PAGE_SHIFT;
530 LIST_ENTRY RxActiveContexts;
531 NPAGED_LOOKASIDE_LIST RxContextLookasideList;
532 FAST_MUTEX RxContextPerFileSerializationMutex;
533 RDBSS_DATA RxData;
534 FCB RxDeviceFCB;
535 BOOLEAN RxLoudLowIoOpsEnabled = FALSE;
536 RX_FSD_DISPATCH_VECTOR RxDeviceFCBVector[IRP_MJ_MAXIMUM_FUNCTION + 1] =
537 {
538 { RxCommonDispatchProblem },
539 { RxCommonDispatchProblem },
540 { RxCommonDevFCBClose },
541 { RxCommonDispatchProblem },
542 { RxCommonDispatchProblem },
543 { RxCommonDispatchProblem },
544 { RxCommonDispatchProblem },
545 { RxCommonDispatchProblem },
546 { RxCommonDispatchProblem },
547 { RxCommonDispatchProblem },
548 { RxCommonDevFCBQueryVolInfo },
549 { RxCommonDispatchProblem },
550 { RxCommonDispatchProblem },
551 { RxCommonDevFCBFsCtl },
552 { RxCommonDevFCBIoCtl },
553 { RxCommonDevFCBIoCtl },
554 { RxCommonDispatchProblem },
555 { RxCommonDispatchProblem },
556 { RxCommonDevFCBCleanup },
557 { RxCommonDispatchProblem },
558 { RxCommonDispatchProblem },
559 { RxCommonDispatchProblem },
560 { RxCommonUnimplemented },
561 { RxCommonUnimplemented },
562 { RxCommonUnimplemented },
563 { RxCommonUnimplemented },
564 { RxCommonUnimplemented },
565 { RxCommonUnimplemented },
566 };
567 RDBSS_EXPORTS RxExports;
568 FAST_IO_DISPATCH RxFastIoDispatch;
569 PRDBSS_DEVICE_OBJECT RxFileSystemDeviceObject;
570 RX_FSD_DISPATCH_VECTOR RxFsdDispatchVector[IRP_MJ_MAXIMUM_FUNCTION + 1] =
571 {
572 { RxCommonCreate },
573 { RxCommonUnimplemented },
574 { RxCommonClose },
575 { RxCommonRead },
576 { RxCommonWrite },
577 { RxCommonQueryInformation },
578 { RxCommonSetInformation },
579 { RxCommonQueryEa },
580 { RxCommonSetEa },
581 { RxCommonFlushBuffers },
582 { RxCommonQueryVolumeInformation },
583 { RxCommonSetVolumeInformation },
584 { RxCommonDirectoryControl },
585 { RxCommonFileSystemControl },
586 { RxCommonDeviceControl },
587 { RxCommonDeviceControl },
588 { RxCommonUnimplemented },
589 { RxCommonLockControl },
590 { RxCommonCleanup },
591 { RxCommonUnimplemented },
592 { RxCommonQuerySecurity },
593 { RxCommonSetSecurity },
594 { RxCommonUnimplemented },
595 { RxCommonUnimplemented },
596 { RxCommonUnimplemented },
597 { RxCommonQueryQuotaInformation },
598 { RxCommonSetQuotaInformation },
599 { RxCommonUnimplemented },
600 };
601 ULONG RxFsdEntryCount;
602 LIST_ENTRY RxIrpsList;
603 KSPIN_LOCK RxIrpsListSpinLock;
604 KMUTEX RxScavengerMutex;
605 KMUTEX RxSerializationMutex;
606 UCHAR RxSpaceForTheWrappersDeviceObject[sizeof(*RxFileSystemDeviceObject)];
607 KSPIN_LOCK TopLevelIrpSpinLock;
608 LIST_ENTRY TopLevelIrpAllocatedContextsList;
609 BOOLEAN RxForceQFIPassThrough = FALSE;
610 BOOLEAN RxNoAsync = FALSE;
611
612 DECLARE_CONST_UNICODE_STRING(unknownId, L"???");
613
614 #if RDBSS_ASSERTS
615 #ifdef ASSERT
616 #undef ASSERT
617 #endif
618
619 #define ASSERT(exp) \
620 if (!(exp)) \
621 { \
622 RxAssert(#exp, __FILE__, __LINE__, NULL); \
623 }
624 #endif
625
626 #if RX_POOL_WRAPPER
627 #undef RxAllocatePool
628 #undef RxAllocatePoolWithTag
629 #undef RxFreePool
630
631 #define RxAllocatePool(P, S) _RxAllocatePoolWithTag(P, S, 0)
632 #define RxAllocatePoolWithTag _RxAllocatePoolWithTag
633 #define RxFreePool _RxFreePool
634 #define RxFreePoolWithTag _RxFreePoolWithTag
635 #endif
636
637 /* FUNCTIONS ****************************************************************/
638
639 /*
640 * @implemented
641 */
642 VOID
643 CheckForLoudOperations(
644 PRX_CONTEXT RxContext)
645 {
646 PAGED_CODE();
647
648 #define ALLSCR_LENGTH (sizeof(L"all.scr") - sizeof(UNICODE_NULL))
649
650 /* Are loud operations enabled? */
651 if (RxLoudLowIoOpsEnabled)
652 {
653 PFCB Fcb;
654
655 /* If so, the operation will be loud only if filename ends with all.scr */
656 Fcb = (PFCB)RxContext->pFcb;
657 if (RtlCompareMemory(Add2Ptr(Fcb->PrivateAlreadyPrefixedName.Buffer, (Fcb->PrivateAlreadyPrefixedName.Length - ALLSCR_LENGTH)),
658 L"all.scr", ALLSCR_LENGTH) == ALLSCR_LENGTH)
659 {
660 SetFlag(RxContext->LowIoContext.Flags, LOWIO_CONTEXT_FLAG_LOUDOPS);
661 }
662 }
663 #undef ALLSCR_LENGTH
664 }
665
666 /*
667 * @implemented
668 */
669 VOID
670 __RxInitializeTopLevelIrpContext(
671 IN OUT PRX_TOPLEVELIRP_CONTEXT TopLevelContext,
672 IN PIRP Irp,
673 IN PRDBSS_DEVICE_OBJECT RxDeviceObject,
674 IN ULONG Flags)
675 {
676 DPRINT("__RxInitializeTopLevelIrpContext(%p, %p, %p, %u)\n", TopLevelContext, Irp, RxDeviceObject, Flags);
677
678 RtlZeroMemory(TopLevelContext, sizeof(RX_TOPLEVELIRP_CONTEXT));
679 TopLevelContext->Irp = Irp;
680 TopLevelContext->Flags = (Flags ? RX_TOPLEVELCTX_FLAG_FROM_POOL : 0);
681 TopLevelContext->Signature = RX_TOPLEVELIRP_CONTEXT_SIGNATURE;
682 TopLevelContext->RxDeviceObject = RxDeviceObject;
683 TopLevelContext->Previous = IoGetTopLevelIrp();
684 TopLevelContext->Thread = PsGetCurrentThread();
685
686 /* We cannot add to list something that'd come from stack */
687 if (BooleanFlagOn(TopLevelContext->Flags, RX_TOPLEVELCTX_FLAG_FROM_POOL))
688 {
689 RxAddToTopLevelIrpAllocatedContextsList(TopLevelContext);
690 }
691 }
692
693 /*
694 * @implemented
695 */
696 VOID
697 __RxWriteReleaseResources(
698 PRX_CONTEXT RxContext,
699 BOOLEAN ResourceOwnerSet,
700 ULONG LineNumber,
701 PCSTR FileName,
702 ULONG SerialNumber)
703 {
704 PFCB Fcb;
705
706 PAGED_CODE();
707
708 ASSERT(RxContext != NULL);
709
710 Fcb = (PFCB)RxContext->pFcb;
711 ASSERT(Fcb != NULL);
712
713 /* If FCB resource was acquired, release it */
714 if (RxContext->FcbResourceAcquired)
715 {
716 /* Taking care of owner */
717 if (ResourceOwnerSet)
718 {
719 RxReleaseFcbForThread(RxContext, Fcb, RxContext->LowIoContext.ResourceThreadId);
720 }
721 else
722 {
723 RxReleaseFcb(RxContext, Fcb);
724 }
725
726 RxContext->FcbResourceAcquired = FALSE;
727 }
728
729 /* If FCB paging resource was acquired, release it */
730 if (RxContext->FcbPagingIoResourceAcquired)
731 {
732 /* Taking care of owner */
733 if (ResourceOwnerSet)
734 {
735 RxReleasePagingIoResourceForThread(RxContext, Fcb, RxContext->LowIoContext.ResourceThreadId);
736 }
737 else
738 {
739 RxReleasePagingIoResource(RxContext, Fcb);
740 }
741
742 /* No need to release boolean here, RxReleasePagingIoResource() takes care of it */
743 }
744 }
745
746 NTSTATUS
747 NTAPI
748 RxAcquireExclusiveFcbResourceInMRx(
749 _Inout_ PMRX_FCB Fcb)
750 {
751 UNIMPLEMENTED;
752 return STATUS_NOT_IMPLEMENTED;
753 }
754
755 BOOLEAN
756 NTAPI
757 RxAcquireFcbForLazyWrite(
758 PVOID Context,
759 BOOLEAN Wait)
760 {
761 UNIMPLEMENTED;
762 return FALSE;
763 }
764
765 BOOLEAN
766 NTAPI
767 RxAcquireFcbForReadAhead(
768 PVOID Context,
769 BOOLEAN Wait)
770 {
771 UNIMPLEMENTED;
772 return FALSE;
773 }
774
775 VOID
776 NTAPI
777 RxAcquireFileForNtCreateSection(
778 PFILE_OBJECT FileObject)
779 {
780 UNIMPLEMENTED;
781 }
782
783 NTSTATUS
784 NTAPI
785 RxAcquireForCcFlush(
786 PFILE_OBJECT FileObject,
787 PDEVICE_OBJECT DeviceObject)
788 {
789 UNIMPLEMENTED;
790 return STATUS_NOT_IMPLEMENTED;
791 }
792
793 /*
794 * @implemented
795 */
796 VOID
797 RxAddToTopLevelIrpAllocatedContextsList(
798 PRX_TOPLEVELIRP_CONTEXT TopLevelContext)
799 {
800 KIRQL OldIrql;
801
802 DPRINT("RxAddToTopLevelIrpAllocatedContextsList(%p)\n", TopLevelContext);
803
804 ASSERT(TopLevelContext->Signature == RX_TOPLEVELIRP_CONTEXT_SIGNATURE);
805 ASSERT(BooleanFlagOn(TopLevelContext->Flags, RX_TOPLEVELCTX_FLAG_FROM_POOL));
806
807 KeAcquireSpinLock(&TopLevelIrpSpinLock, &OldIrql);
808 InsertTailList(&TopLevelIrpAllocatedContextsList, &TopLevelContext->ListEntry);
809 KeReleaseSpinLock(&TopLevelIrpSpinLock, OldIrql);
810 }
811
812 /*
813 * @implemented
814 */
815 VOID
816 NTAPI
817 RxAddToWorkque(
818 IN PRX_CONTEXT RxContext,
819 IN PIRP Irp)
820 {
821 ULONG Queued;
822 KIRQL OldIrql;
823 WORK_QUEUE_TYPE Queue;
824 PIO_STACK_LOCATION Stack;
825
826 Stack = RxContext->CurrentIrpSp;
827 RxContext->PostRequest = FALSE;
828
829 /* First of all, select the appropriate queue - delayed for prefix claim, critical for the rest */
830 if (RxContext->MajorFunction == IRP_MJ_DEVICE_CONTROL &&
831 Stack->Parameters.DeviceIoControl.IoControlCode == IOCTL_REDIR_QUERY_PATH)
832 {
833 Queue = DelayedWorkQueue;
834 SetFlag(RxContext->Flags, RX_CONTEXT_FLAG_FSP_DELAYED_OVERFLOW_QUEUE);
835 }
836 else
837 {
838 Queue = CriticalWorkQueue;
839 SetFlag(RxContext->Flags, RX_CONTEXT_FLAG_FSP_CRITICAL_OVERFLOW_QUEUE);
840 }
841
842 /* Check for overflow */
843 if (Stack->FileObject != NULL)
844 {
845 KeAcquireSpinLock(&RxFileSystemDeviceObject->OverflowQueueSpinLock, &OldIrql);
846
847 Queued = InterlockedIncrement(&RxFileSystemDeviceObject->PostedRequestCount[Queue]);
848 /* In case of an overflow, add the new queued call to the overflow list */
849 if (Queued > 1)
850 {
851 InterlockedDecrement(&RxFileSystemDeviceObject->PostedRequestCount[Queue]);
852 InsertTailList(&RxFileSystemDeviceObject->OverflowQueue[Queue], &RxContext->OverflowListEntry);
853 ++RxFileSystemDeviceObject->OverflowQueueCount[Queue];
854
855 KeReleaseSpinLock(&RxFileSystemDeviceObject->OverflowQueueSpinLock, OldIrql);
856 return;
857 }
858
859 KeReleaseSpinLock(&RxFileSystemDeviceObject->OverflowQueueSpinLock, OldIrql);
860 }
861
862 ExInitializeWorkItem(&RxContext->WorkQueueItem, RxFspDispatch, RxContext);
863 ExQueueWorkItem((PWORK_QUEUE_ITEM)&RxContext->WorkQueueItem, Queue);
864 }
865
866 /*
867 * @implemented
868 */
869 VOID
870 RxAdjustFileTimesAndSize(
871 PRX_CONTEXT Context)
872 {
873 PFCB Fcb;
874 PFOBX Fobx;
875 NTSTATUS Status;
876 PFILE_OBJECT FileObject;
877 LARGE_INTEGER CurrentTime;
878 FILE_BASIC_INFORMATION FileBasicInfo;
879 FILE_END_OF_FILE_INFORMATION FileEOFInfo;
880 BOOLEAN FileModified, SetLastChange, SetLastAccess, SetLastWrite, NeedUpdate;
881
882 PAGED_CODE();
883
884 FileObject = Context->CurrentIrpSp->FileObject;
885 /* If Cc isn't initialized, the file was not read nor written, nothing to do */
886 if (FileObject->PrivateCacheMap == NULL)
887 {
888 return;
889 }
890
891 /* Get now */
892 KeQuerySystemTime(&CurrentTime);
893
894 Fobx = (PFOBX)Context->pFobx;
895 /* Was the file modified? */
896 FileModified = BooleanFlagOn(FileObject->Flags, FO_FILE_MODIFIED);
897 /* We'll set last write if it was modified and user didn't update yet */
898 SetLastWrite = FileModified && !BooleanFlagOn(Fobx->Flags, FOBX_FLAG_USER_SET_LAST_WRITE);
899 /* File was accessed if: written or read (fastio), we'll update last access if user didn't */
900 SetLastAccess = SetLastWrite ||
901 (BooleanFlagOn(FileObject->Flags, FO_FILE_FAST_IO_READ) &&
902 !BooleanFlagOn(Fobx->Flags, FOBX_FLAG_USER_SET_LAST_ACCESS));
903 /* We'll set last change if it was modified and user didn't update yet */
904 SetLastChange = FileModified && !BooleanFlagOn(Fobx->Flags, FOBX_FLAG_USER_SET_LAST_CHANGE);
905
906 /* Nothing to update? Job done */
907 if (!FileModified && !SetLastWrite && !SetLastAccess && !SetLastChange)
908 {
909 return;
910 }
911
912 Fcb = (PFCB)Context->pFcb;
913 /* By default, we won't issue any MRxSetFileInfoAtCleanup call */
914 NeedUpdate = FALSE;
915 RtlZeroMemory(&FileBasicInfo, sizeof(FileBasicInfo));
916
917 /* Update lastwrite time if required */
918 if (SetLastWrite)
919 {
920 NeedUpdate = TRUE;
921 Fcb->LastWriteTime.QuadPart = CurrentTime.QuadPart;
922 FileBasicInfo.LastWriteTime.QuadPart = CurrentTime.QuadPart;
923 }
924
925 /* Update lastaccess time if required */
926 if (SetLastAccess)
927 {
928 NeedUpdate = TRUE;
929 Fcb->LastAccessTime.QuadPart = CurrentTime.QuadPart;
930 FileBasicInfo.LastAccessTime.QuadPart = CurrentTime.QuadPart;
931 }
932
933 /* Update lastchange time if required */
934 if (SetLastChange)
935 {
936 NeedUpdate = TRUE;
937 Fcb->LastChangeTime.QuadPart = CurrentTime.QuadPart;
938 FileBasicInfo.ChangeTime.QuadPart = CurrentTime.QuadPart;
939 }
940
941 /* If one of the date was modified, issue a call to mini-rdr */
942 if (NeedUpdate)
943 {
944 Context->Info.FileInformationClass = FileBasicInformation;
945 Context->Info.Buffer = &FileBasicInfo;
946 Context->Info.Length = sizeof(FileBasicInfo);
947
948 MINIRDR_CALL(Status, Context, Fcb->MRxDispatch, MRxSetFileInfoAtCleanup, (Context));
949 (void)Status;
950 }
951
952 /* If the file was modified, update its EOF */
953 if (FileModified)
954 {
955 FileEOFInfo.EndOfFile.QuadPart = Fcb->Header.FileSize.QuadPart;
956
957 Context->Info.FileInformationClass = FileEndOfFileInformation;
958 Context->Info.Buffer = &FileEOFInfo;
959 Context->Info.Length = sizeof(FileEOFInfo);
960
961 MINIRDR_CALL(Status, Context, Fcb->MRxDispatch, MRxSetFileInfoAtCleanup, (Context));
962 (void)Status;
963 }
964 }
965
966 /*
967 * @implemented
968 */
969 NTSTATUS
970 RxAllocateCanonicalNameBuffer(
971 PRX_CONTEXT RxContext,
972 PUNICODE_STRING CanonicalName,
973 USHORT CanonicalLength)
974 {
975 PAGED_CODE();
976
977 DPRINT("RxContext: %p - CanonicalNameBuffer: %p\n", RxContext, RxContext->Create.CanonicalNameBuffer);
978
979 /* Context must be free of any already allocated name */
980 ASSERT(RxContext->Create.CanonicalNameBuffer == NULL);
981
982 /* Validate string length */
983 if (CanonicalLength > USHRT_MAX - 1)
984 {
985 CanonicalName->Buffer = NULL;
986 return STATUS_OBJECT_PATH_INVALID;
987 }
988
989 CanonicalName->Buffer = RxAllocatePoolWithTag(PagedPool | POOL_COLD_ALLOCATION, CanonicalLength, RX_MISC_POOLTAG);
990 if (CanonicalName->Buffer == NULL)
991 {
992 return STATUS_INSUFFICIENT_RESOURCES;
993 }
994
995 CanonicalName->Length = 0;
996 CanonicalName->MaximumLength = CanonicalLength;
997
998 /* Set the two places - they must always be identical */
999 RxContext->Create.CanonicalNameBuffer = CanonicalName->Buffer;
1000 RxContext->AlsoCanonicalNameBuffer = CanonicalName->Buffer;
1001
1002 return STATUS_SUCCESS;
1003 }
1004
1005 /*
1006 * @implemented
1007 */
1008 VOID
1009 RxCancelNotifyChangeDirectoryRequestsForFobx(
1010 PFOBX Fobx)
1011 {
1012 KIRQL OldIrql;
1013 PLIST_ENTRY Entry;
1014 PRX_CONTEXT Context;
1015 LIST_ENTRY ContextsToCancel;
1016
1017 /* Init a list for the contexts to cancel */
1018 InitializeListHead(&ContextsToCancel);
1019
1020 /* Lock our list lock */
1021 KeAcquireSpinLock(&RxStrucSupSpinLock, &OldIrql);
1022
1023 /* Now, browse all the active contexts, to find the associated ones */
1024 Entry = RxActiveContexts.Flink;
1025 while (Entry != &RxActiveContexts)
1026 {
1027 Context = CONTAINING_RECORD(Entry, RX_CONTEXT, ContextListEntry);
1028 Entry = Entry->Flink;
1029
1030 /* Not the IRP we're looking for, ignore */
1031 if (Context->MajorFunction != IRP_MJ_DIRECTORY_CONTROL ||
1032 Context->MinorFunction != IRP_MN_NOTIFY_CHANGE_DIRECTORY)
1033 {
1034 continue;
1035 }
1036
1037 /* Not the FOBX we're looking for, ignore */
1038 if ((PFOBX)Context->pFobx != Fobx)
1039 {
1040 continue;
1041 }
1042
1043 /* No cancel routine (can't be cancel, then), ignore */
1044 if (Context->MRxCancelRoutine == NULL)
1045 {
1046 continue;
1047 }
1048
1049 /* Mark our context as cancelled */
1050 SetFlag(Context->Flags, RX_CONTEXT_FLAG_CANCELLED);
1051
1052 /* Move it to our list */
1053 RemoveEntryList(&Context->ContextListEntry);
1054 InsertTailList(&ContextsToCancel, &Context->ContextListEntry);
1055
1056 InterlockedIncrement((volatile long *)&Context->ReferenceCount);
1057 }
1058
1059 /* Done with the contexts */
1060 KeReleaseSpinLock(&RxStrucSupSpinLock, OldIrql);
1061
1062 /* Now, handle all our "extracted" contexts */
1063 while (!IsListEmpty(&ContextsToCancel))
1064 {
1065 Entry = RemoveHeadList(&ContextsToCancel);
1066 Context = CONTAINING_RECORD(Entry, RX_CONTEXT, ContextListEntry);
1067
1068 /* If they had an associated IRP (should be always true) */
1069 if (Context->CurrentIrp != NULL)
1070 {
1071 /* Then, call cancel routine */
1072 ASSERT(Context->MRxCancelRoutine != NULL);
1073 DPRINT1("Canceling %p with %p\n", Context, Context->MRxCancelRoutine);
1074 Context->MRxCancelRoutine(Context);
1075 }
1076
1077 /* And delete the context */
1078 RxDereferenceAndDeleteRxContext(Context);
1079 }
1080 }
1081
1082 /*
1083 * @implemented
1084 */
1085 NTSTATUS
1086 RxCancelNotifyChangeDirectoryRequestsForVNetRoot(
1087 PV_NET_ROOT VNetRoot,
1088 BOOLEAN ForceFilesClosed)
1089 {
1090 KIRQL OldIrql;
1091 NTSTATUS Status;
1092 PLIST_ENTRY Entry;
1093 PRX_CONTEXT Context;
1094 LIST_ENTRY ContextsToCancel;
1095
1096 /* Init a list for the contexts to cancel */
1097 InitializeListHead(&ContextsToCancel);
1098
1099 /* Lock our list lock */
1100 KeAcquireSpinLock(&RxStrucSupSpinLock, &OldIrql);
1101
1102 /* Now, browse all the active contexts, to find the associated ones */
1103 Entry = RxActiveContexts.Flink;
1104 while (Entry != &RxActiveContexts)
1105 {
1106 Context = CONTAINING_RECORD(Entry, RX_CONTEXT, ContextListEntry);
1107 Entry = Entry->Flink;
1108
1109 /* Not the IRP we're looking for, ignore */
1110 if (Context->MajorFunction != IRP_MJ_DIRECTORY_CONTROL ||
1111 Context->MinorFunction != IRP_MN_NOTIFY_CHANGE_DIRECTORY)
1112 {
1113 continue;
1114 }
1115
1116 /* Not the VNetRoot we're looking for, ignore */
1117 if (Context->pFcb == NULL ||
1118 (PV_NET_ROOT)Context->NotifyChangeDirectory.pVNetRoot != VNetRoot)
1119 {
1120 continue;
1121 }
1122
1123 /* No cancel routine (can't be cancel, then), ignore */
1124 if (Context->MRxCancelRoutine == NULL)
1125 {
1126 continue;
1127 }
1128
1129 /* At that point, we found a matching context
1130 * If we're not asked to force close, then fail - it's still open
1131 */
1132 if (!ForceFilesClosed)
1133 {
1134 Status = STATUS_FILES_OPEN;
1135 break;
1136 }
1137
1138 /* Mark our context as cancelled */
1139 SetFlag(Context->Flags, RX_CONTEXT_FLAG_CANCELLED);
1140
1141 /* Move it to our list */
1142 RemoveEntryList(&Context->ContextListEntry);
1143 InsertTailList(&ContextsToCancel, &Context->ContextListEntry);
1144
1145 InterlockedIncrement((volatile long *)&Context->ReferenceCount);
1146 }
1147
1148 /* Done with the contexts */
1149 KeReleaseSpinLock(&RxStrucSupSpinLock, OldIrql);
1150
1151 if (Status != STATUS_SUCCESS)
1152 {
1153 return Status;
1154 }
1155
1156 /* Now, handle all our "extracted" contexts */
1157 while (!IsListEmpty(&ContextsToCancel))
1158 {
1159 Entry = RemoveHeadList(&ContextsToCancel);
1160 Context = CONTAINING_RECORD(Entry, RX_CONTEXT, ContextListEntry);
1161
1162 /* If they had an associated IRP (should be always true) */
1163 if (Context->CurrentIrp != NULL)
1164 {
1165 /* Then, call cancel routine */
1166 ASSERT(Context->MRxCancelRoutine != NULL);
1167 DPRINT1("Canceling %p with %p\n", Context, Context->MRxCancelRoutine);
1168 Context->MRxCancelRoutine(Context);
1169 }
1170
1171 /* And delete the context */
1172 RxDereferenceAndDeleteRxContext(Context);
1173 }
1174
1175 return Status;
1176 }
1177
1178 VOID
1179 NTAPI
1180 RxCancelRoutine(
1181 PDEVICE_OBJECT DeviceObject,
1182 PIRP Irp)
1183 {
1184 UNIMPLEMENTED;
1185 }
1186
1187 /*
1188 * @implemented
1189 */
1190 NTSTATUS
1191 RxCanonicalizeFileNameByServerSpecs(
1192 PRX_CONTEXT RxContext,
1193 PUNICODE_STRING NetRootName)
1194 {
1195 USHORT NextChar, CurChar;
1196 USHORT MaxChars;
1197
1198 PAGED_CODE();
1199
1200 /* Validate file name is not empty */
1201 MaxChars = NetRootName->Length / sizeof(WCHAR);
1202 if (MaxChars == 0)
1203 {
1204 return STATUS_MORE_PROCESSING_REQUIRED;
1205 }
1206
1207 /* Validate name is correct */
1208 for (NextChar = 0, CurChar = 0; CurChar + 1 < MaxChars; NextChar = CurChar + 1)
1209 {
1210 USHORT i;
1211
1212 for (i = NextChar + 1; i < MaxChars; ++i)
1213 {
1214 if (NetRootName->Buffer[i] == '\\' || NetRootName->Buffer[i] == ':')
1215 {
1216 break;
1217 }
1218 }
1219
1220 CurChar = i - 1;
1221 if (CurChar == NextChar)
1222 {
1223 if (((NetRootName->Buffer[NextChar] != '\\' && NetRootName->Buffer[NextChar] != ':') || NextChar == (MaxChars - 1)) && NetRootName->Buffer[NextChar] != '.')
1224 {
1225 continue;
1226 }
1227
1228 if (CurChar != 0)
1229 {
1230 if (CurChar >= MaxChars - 1)
1231 {
1232 continue;
1233 }
1234
1235 if (NetRootName->Buffer[CurChar + 1] != ':')
1236 {
1237 return STATUS_OBJECT_PATH_SYNTAX_BAD;
1238 }
1239 }
1240 else
1241 {
1242 if (NetRootName->Buffer[1] != ':')
1243 {
1244 return STATUS_OBJECT_PATH_SYNTAX_BAD;
1245 }
1246 }
1247 }
1248 else
1249 {
1250 if ((CurChar - NextChar) == 1)
1251 {
1252 if (NetRootName->Buffer[NextChar + 2] != '.')
1253 {
1254 continue;
1255 }
1256
1257 if (NetRootName->Buffer[NextChar] == '\\' || NetRootName->Buffer[NextChar] == ':' || NetRootName->Buffer[NextChar] == '.')
1258 {
1259 return STATUS_OBJECT_PATH_SYNTAX_BAD;
1260 }
1261 }
1262 else
1263 {
1264 if ((CurChar - NextChar) != 2 || (NetRootName->Buffer[NextChar] != '\\' && NetRootName->Buffer[NextChar] != ':')
1265 || NetRootName->Buffer[NextChar + 1] != '.')
1266 {
1267 continue;
1268 }
1269
1270 if (NetRootName->Buffer[NextChar + 2] == '.')
1271 {
1272 return STATUS_OBJECT_PATH_SYNTAX_BAD;
1273 }
1274 }
1275 }
1276 }
1277
1278 return STATUS_MORE_PROCESSING_REQUIRED;
1279 }
1280
1281 NTSTATUS
1282 RxCanonicalizeNameAndObtainNetRoot(
1283 PRX_CONTEXT RxContext,
1284 PUNICODE_STRING FileName,
1285 PUNICODE_STRING NetRootName)
1286 {
1287 NTSTATUS Status;
1288 NET_ROOT_TYPE NetRootType;
1289 UNICODE_STRING CanonicalName;
1290
1291 PAGED_CODE();
1292
1293 NetRootType = NET_ROOT_WILD;
1294
1295 RtlInitEmptyUnicodeString(NetRootName, NULL, 0);
1296 RtlInitEmptyUnicodeString(&CanonicalName, NULL, 0);
1297
1298 /* if not relative opening, just handle the passed name */
1299 if (RxContext->CurrentIrpSp->FileObject->RelatedFileObject == NULL)
1300 {
1301 Status = RxFirstCanonicalize(RxContext, FileName, &CanonicalName, &NetRootType);
1302 if (!NT_SUCCESS(Status))
1303 {
1304 return Status;
1305 }
1306 }
1307 else
1308 {
1309 PFCB Fcb;
1310
1311 /* Make sure we have a valid FCB and a FOBX */
1312 Fcb = RxContext->CurrentIrpSp->FileObject->RelatedFileObject->FsContext;
1313 if (Fcb == NULL ||
1314 RxContext->CurrentIrpSp->FileObject->RelatedFileObject->FsContext2 == NULL)
1315 {
1316 return STATUS_INVALID_PARAMETER;
1317 }
1318
1319 if (!NodeTypeIsFcb(Fcb))
1320 {
1321 return STATUS_INVALID_PARAMETER;
1322 }
1323
1324 UNIMPLEMENTED;
1325 }
1326
1327 /* Get/Create the associated VNetRoot for opening */
1328 Status = RxFindOrConstructVirtualNetRoot(RxContext, &CanonicalName, NetRootType, NetRootName);
1329 if (!NT_SUCCESS(Status) && Status != STATUS_PENDING &&
1330 BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_MAILSLOT_REPARSE))
1331 {
1332 ASSERT(CanonicalName.Buffer == RxContext->Create.CanonicalNameBuffer);
1333
1334 RxFreeCanonicalNameBuffer(RxContext);
1335 Status = RxFirstCanonicalize(RxContext, FileName, &CanonicalName, &NetRootType);
1336 if (NT_SUCCESS(Status))
1337 {
1338 Status = RxFindOrConstructVirtualNetRoot(RxContext, &CanonicalName, NetRootType, NetRootName);
1339 }
1340 }
1341
1342 /* Filename cannot contain wildcards */
1343 if (FsRtlDoesNameContainWildCards(NetRootName))
1344 {
1345 Status = STATUS_OBJECT_NAME_INVALID;
1346 }
1347
1348 /* Make sure file name is correct */
1349 if (NT_SUCCESS(Status))
1350 {
1351 Status = RxCanonicalizeFileNameByServerSpecs(RxContext, NetRootName);
1352 }
1353
1354 /* Give the mini-redirector a chance to prepare the name */
1355 if (NT_SUCCESS(Status) || Status == STATUS_MORE_PROCESSING_REQUIRED)
1356 {
1357 if (RxContext->Create.pNetRoot != NULL)
1358 {
1359 NTSTATUS IgnoredStatus;
1360
1361 MINIRDR_CALL(IgnoredStatus, RxContext, RxContext->Create.pNetRoot->pSrvCall->RxDeviceObject->Dispatch,
1362 MRxPreparseName, (RxContext, NetRootName));
1363 (void)IgnoredStatus;
1364 }
1365 }
1366
1367 return Status;
1368 }
1369
1370 VOID
1371 NTAPI
1372 RxCheckFcbStructuresForAlignment(
1373 VOID)
1374 {
1375 UNIMPLEMENTED;
1376 }
1377
1378 NTSTATUS
1379 RxCheckShareAccess(
1380 _In_ ACCESS_MASK DesiredAccess,
1381 _In_ ULONG DesiredShareAccess,
1382 _Inout_ PFILE_OBJECT FileObject,
1383 _Inout_ PSHARE_ACCESS ShareAccess,
1384 _In_ BOOLEAN Update,
1385 _In_ PSZ where,
1386 _In_ PSZ wherelogtag)
1387 {
1388 PAGED_CODE();
1389
1390 RxDumpWantedAccess(where, "", wherelogtag, DesiredAccess, DesiredShareAccess);
1391 RxDumpCurrentAccess(where, "", wherelogtag, ShareAccess);
1392
1393 return IoCheckShareAccess(DesiredAccess, DesiredShareAccess, FileObject, ShareAccess, Update);
1394 }
1395
1396 /*
1397 * @implemented
1398 */
1399 NTSTATUS
1400 RxCheckShareAccessPerSrvOpens(
1401 IN PFCB Fcb,
1402 IN ACCESS_MASK DesiredAccess,
1403 IN ULONG DesiredShareAccess)
1404 {
1405 BOOLEAN ReadAccess;
1406 BOOLEAN WriteAccess;
1407 BOOLEAN DeleteAccess;
1408 PSHARE_ACCESS ShareAccess;
1409
1410 PAGED_CODE();
1411
1412 ShareAccess = &Fcb->ShareAccessPerSrvOpens;
1413
1414 RxDumpWantedAccess("RxCheckShareAccessPerSrvOpens", "", "RxCheckShareAccessPerSrvOpens", DesiredAccess, DesiredShareAccess);
1415 RxDumpCurrentAccess("RxCheckShareAccessPerSrvOpens", "", "RxCheckShareAccessPerSrvOpens", ShareAccess);
1416
1417 /* Check if any access wanted */
1418 ReadAccess = (DesiredAccess & (FILE_READ_DATA | FILE_EXECUTE)) != 0;
1419 WriteAccess = (DesiredAccess & (FILE_WRITE_DATA | FILE_APPEND_DATA)) != 0;
1420 DeleteAccess = (DesiredAccess & DELETE) != 0;
1421
1422 if (ReadAccess || WriteAccess || DeleteAccess)
1423 {
1424 BOOLEAN SharedRead = (DesiredShareAccess & FILE_SHARE_READ) != 0;
1425 BOOLEAN SharedWrite = (DesiredShareAccess & FILE_SHARE_WRITE) != 0;
1426 BOOLEAN SharedDelete = (DesiredShareAccess & FILE_SHARE_DELETE) != 0;
1427
1428 /* Check whether there's a violation */
1429 if ((ReadAccess &&
1430 (ShareAccess->SharedRead < ShareAccess->OpenCount)) ||
1431 (WriteAccess &&
1432 (ShareAccess->SharedWrite < ShareAccess->OpenCount)) ||
1433 (DeleteAccess &&
1434 (ShareAccess->SharedDelete < ShareAccess->OpenCount)) ||
1435 ((ShareAccess->Readers != 0) && !SharedRead) ||
1436 ((ShareAccess->Writers != 0) && !SharedWrite) ||
1437 ((ShareAccess->Deleters != 0) && !SharedDelete))
1438 {
1439 return STATUS_SHARING_VIOLATION;
1440 }
1441 }
1442
1443 return STATUS_SUCCESS;
1444 }
1445
1446 VOID
1447 RxCleanupPipeQueues(
1448 PRX_CONTEXT Context)
1449 {
1450 UNIMPLEMENTED;
1451 }
1452
1453 /*
1454 * @implemented
1455 */
1456 NTSTATUS
1457 RxCloseAssociatedSrvOpen(
1458 IN PFOBX Fobx,
1459 IN PRX_CONTEXT RxContext OPTIONAL)
1460 {
1461 PFCB Fcb;
1462 NTSTATUS Status;
1463 PSRV_OPEN SrvOpen;
1464 BOOLEAN CloseSrvOpen;
1465 PRX_CONTEXT LocalContext;
1466
1467 PAGED_CODE();
1468
1469 /* Assume SRV_OPEN is already closed */
1470 CloseSrvOpen = FALSE;
1471 /* If we have a FOBX, we'll have to close it */
1472 if (Fobx != NULL)
1473 {
1474 /* If the FOBX isn't closed yet */
1475 if (!BooleanFlagOn(Fobx->Flags, FOBX_FLAG_SRVOPEN_CLOSED))
1476 {
1477 SrvOpen = Fobx->SrvOpen;
1478 Fcb = (PFCB)SrvOpen->pFcb;
1479 /* Check whether we've to close SRV_OPEN first */
1480 if (!BooleanFlagOn(SrvOpen->Flags, SRVOPEN_FLAG_CLOSED))
1481 {
1482 CloseSrvOpen = TRUE;
1483 }
1484 else
1485 {
1486 ASSERT(RxIsFcbAcquiredExclusive(Fcb));
1487
1488 /* Not much to do */
1489 SetFlag(Fobx->Flags, FOBX_FLAG_SRVOPEN_CLOSED);
1490
1491 if (SrvOpen->OpenCount > 0)
1492 {
1493 --SrvOpen->OpenCount;
1494 }
1495 }
1496 }
1497
1498 /* No need to close SRV_OPEN, so close FOBX */
1499 if (!CloseSrvOpen)
1500 {
1501 RxMarkFobxOnClose(Fobx);
1502
1503 return STATUS_SUCCESS;
1504 }
1505 }
1506 else
1507 {
1508 /* No FOBX? No RX_CONTEXT, ok, job done! */
1509 if (RxContext == NULL)
1510 {
1511 return STATUS_SUCCESS;
1512 }
1513
1514 /* Get the FCB from RX_CONTEXT */
1515 Fcb = (PFCB)RxContext->pFcb;
1516 SrvOpen = NULL;
1517 }
1518
1519 /* If we don't have RX_CONTEXT, allocte one, we'll need it */
1520 if (RxContext == NULL)
1521 {
1522 ASSERT(Fobx != NULL);
1523
1524 LocalContext = RxCreateRxContext(NULL, Fcb->RxDeviceObject, RX_CONTEXT_FLAG_MUST_SUCCEED_NONBLOCKING | RX_CONTEXT_FLAG_WAIT);
1525 if (LocalContext == NULL)
1526 {
1527 return STATUS_INSUFFICIENT_RESOURCES;
1528 }
1529
1530 LocalContext->MajorFunction = 2;
1531 LocalContext->pFcb = RX_GET_MRX_FCB(Fcb);
1532 LocalContext->pFobx = (PMRX_FOBX)Fobx;
1533 LocalContext->pRelevantSrvOpen = (PMRX_SRV_OPEN)Fobx->SrvOpen;
1534 }
1535 else
1536 {
1537 LocalContext = RxContext;
1538 }
1539
1540 ASSERT(RxIsFcbAcquiredExclusive(Fcb));
1541
1542 /* Now, close the FOBX */
1543 if (Fobx != NULL)
1544 {
1545 RxMarkFobxOnClose(Fobx);
1546 }
1547 else
1548 {
1549 InterlockedDecrement((volatile long *)&Fcb->OpenCount);
1550 }
1551
1552 /* If not a "standard" file, SRV_OPEN can be null */
1553 if (SrvOpen == NULL)
1554 {
1555 ASSERT((NodeType(Fcb) == RDBSS_NTC_OPENTARGETDIR_FCB) || (NodeType(Fcb) == RDBSS_NTC_IPC_SHARE) || (NodeType(Fcb) == RDBSS_NTC_MAILSLOT));
1556 RxDereferenceNetFcb(Fcb);
1557
1558 if (LocalContext != RxContext)
1559 {
1560 RxDereferenceAndDeleteRxContext(LocalContext);
1561 }
1562
1563 return STATUS_SUCCESS;
1564 }
1565
1566 /* If SRV_OPEN isn't in a good condition, nothing to close */
1567 if (SrvOpen->Condition != Condition_Good)
1568 {
1569 if (LocalContext != RxContext)
1570 {
1571 RxDereferenceAndDeleteRxContext(LocalContext);
1572 }
1573
1574 return STATUS_SUCCESS;
1575 }
1576
1577 /* Decrease open count */
1578 if (SrvOpen->OpenCount > 0)
1579 {
1580 --SrvOpen->OpenCount;
1581 }
1582
1583 /* If we're the only one left, is there a FOBX handled by Scavenger? */
1584 if (SrvOpen->OpenCount == 1)
1585 {
1586 if (!IsListEmpty(&SrvOpen->FobxList))
1587 {
1588 if (!IsListEmpty(&CONTAINING_RECORD(SrvOpen->FobxList.Flink, FOBX, FobxQLinks)->ScavengerFinalizationList))
1589 {
1590 SetFlag(SrvOpen->Flags, SRVOPEN_FLAG_CLOSE_DELAYED);
1591 }
1592 }
1593 }
1594
1595 /* Nothing left, purge FCB */
1596 if (SrvOpen->OpenCount == 0 && RxContext == NULL)
1597 {
1598 RxPurgeNetFcb(Fcb, LocalContext);
1599 }
1600
1601 /* Already closed? Job done! */
1602 SrvOpen = Fobx->SrvOpen;
1603 if (SrvOpen == NULL ||
1604 (SrvOpen->OpenCount != 0 && !BooleanFlagOn(SrvOpen->Flags, SRVOPEN_FLAG_BUFFERING_STATE_CHANGE_PENDING)) ||
1605 BooleanFlagOn(SrvOpen->Flags, SRVOPEN_FLAG_CLOSED))
1606 {
1607 SetFlag(Fobx->Flags, FOBX_FLAG_SRVOPEN_CLOSED);
1608 if (LocalContext != RxContext)
1609 {
1610 RxDereferenceAndDeleteRxContext(LocalContext);
1611 }
1612
1613 return STATUS_SUCCESS;
1614 }
1615
1616 ASSERT(RxIsFcbAcquiredExclusive(Fcb));
1617
1618 /* Inform mini-rdr about closing */
1619 MINIRDR_CALL(Status, LocalContext, Fcb->MRxDispatch, MRxCloseSrvOpen, (LocalContext));
1620 DPRINT("MRxCloseSrvOpen returned: %lx, called with RX_CONTEXT %p for FOBX %p (FCB %p, SRV_OPEN %p)\n ",
1621 Status, RxContext, Fobx, Fcb, SrvOpen);
1622
1623 /* And mark as such */
1624 SetFlag(SrvOpen->Flags, SRVOPEN_FLAG_CLOSED);
1625 SrvOpen->Key = (PVOID)-1;
1626
1627 /* If we were delayed, we're not! */
1628 if (BooleanFlagOn(SrvOpen->Flags, SRVOPEN_FLAG_CLOSE_DELAYED))
1629 {
1630 InterlockedDecrement(&((PSRV_CALL)Fcb->pNetRoot->pSrvCall)->NumberOfCloseDelayedFiles);
1631 }
1632
1633 /* Clear access */
1634 RxRemoveShareAccessPerSrvOpens(SrvOpen);
1635 RxPurgeChangeBufferingStateRequestsForSrvOpen(SrvOpen);
1636
1637 /* Dereference */
1638 RxDereferenceSrvOpen(SrvOpen, LHS_ExclusiveLockHeld);
1639
1640 /* Mark the FOBX closed as well */
1641 SetFlag(Fobx->Flags, FOBX_FLAG_SRVOPEN_CLOSED);
1642
1643 if (LocalContext != RxContext)
1644 {
1645 RxDereferenceAndDeleteRxContext(LocalContext);
1646 }
1647
1648 return Status;
1649 }
1650
1651 /*
1652 * @implemented
1653 */
1654 NTSTATUS
1655 RxCollapseOrCreateSrvOpen(
1656 PRX_CONTEXT RxContext)
1657 {
1658 PFCB Fcb;
1659 NTSTATUS Status;
1660 ULONG Disposition;
1661 PSRV_OPEN SrvOpen;
1662 USHORT ShareAccess;
1663 PIO_STACK_LOCATION Stack;
1664 ACCESS_MASK DesiredAccess;
1665 RX_BLOCK_CONDITION FcbCondition;
1666
1667 PAGED_CODE();
1668
1669 DPRINT("RxCollapseOrCreateSrvOpen(%p)\n", RxContext);
1670
1671 Fcb = (PFCB)RxContext->pFcb;
1672 ASSERT(RxIsFcbAcquiredExclusive(Fcb));
1673 ++Fcb->UncleanCount;
1674
1675 Stack = RxContext->CurrentIrpSp;
1676 DesiredAccess = Stack->Parameters.Create.SecurityContext->DesiredAccess & FILE_ALL_ACCESS;
1677 ShareAccess = Stack->Parameters.Create.ShareAccess & FILE_SHARE_VALID_FLAGS;
1678
1679 Disposition = RxContext->Create.NtCreateParameters.Disposition;
1680
1681 /* Try to find a reusable SRV_OPEN */
1682 Status = RxSearchForCollapsibleOpen(RxContext, DesiredAccess, ShareAccess);
1683 if (Status == STATUS_NOT_FOUND)
1684 {
1685 /* If none found, create one */
1686 SrvOpen = RxCreateSrvOpen((PV_NET_ROOT)RxContext->Create.pVNetRoot, Fcb);
1687 if (SrvOpen == NULL)
1688 {
1689 Status = STATUS_INSUFFICIENT_RESOURCES;
1690 }
1691 else
1692 {
1693 SrvOpen->DesiredAccess = DesiredAccess;
1694 SrvOpen->ShareAccess = ShareAccess;
1695 Status = STATUS_SUCCESS;
1696 }
1697
1698 RxContext->pRelevantSrvOpen = (PMRX_SRV_OPEN)SrvOpen;
1699
1700 if (Status != STATUS_SUCCESS)
1701 {
1702 FcbCondition = Condition_Bad;
1703 }
1704 else
1705 {
1706 RxInitiateSrvOpenKeyAssociation(SrvOpen);
1707
1708 /* Cookie to check the mini-rdr doesn't mess with RX_CONTEXT */
1709 RxContext->CurrentIrp->IoStatus.Information = 0xABCDEF;
1710 /* Inform the mini-rdr we're handling a create */
1711 MINIRDR_CALL(Status, RxContext, Fcb->MRxDispatch, MRxCreate, (RxContext));
1712 ASSERT(RxContext->CurrentIrp->IoStatus.Information == 0xABCDEF);
1713
1714 DPRINT("MRxCreate returned: %x\n", Status);
1715 if (Status == STATUS_SUCCESS)
1716 {
1717 /* In case of overwrite, reset file size */
1718 if (Disposition == FILE_OVERWRITE || Disposition == FILE_OVERWRITE_IF)
1719 {
1720 RxAcquirePagingIoResource(RxContext, Fcb);
1721 Fcb->Header.AllocationSize.QuadPart = 0LL;
1722 Fcb->Header.FileSize.QuadPart = 0LL;
1723 Fcb->Header.ValidDataLength.QuadPart = 0LL;
1724 RxContext->CurrentIrpSp->FileObject->SectionObjectPointer = &Fcb->NonPaged->SectionObjectPointers;
1725 CcSetFileSizes(RxContext->CurrentIrpSp->FileObject, (PCC_FILE_SIZES)&Fcb->Header.AllocationSize);
1726 RxReleasePagingIoResource(RxContext, Fcb);
1727 }
1728 else
1729 {
1730 /* Otherwise, adjust sizes */
1731 RxContext->CurrentIrpSp->FileObject->SectionObjectPointer = &Fcb->NonPaged->SectionObjectPointers;
1732 if (CcIsFileCached(RxContext->CurrentIrpSp->FileObject))
1733 {
1734 RxAdjustAllocationSizeforCC(Fcb);
1735 }
1736 CcSetFileSizes(RxContext->CurrentIrpSp->FileObject, (PCC_FILE_SIZES)&Fcb->Header.AllocationSize);
1737 }
1738 }
1739
1740 /* Set the IoStatus with information returned by mini-rdr */
1741 RxContext->CurrentIrp->IoStatus.Information = RxContext->Create.ReturnedCreateInformation;
1742
1743 SrvOpen->OpenStatus = Status;
1744 /* Set SRV_OPEN state - good or bad - depending on whether create succeed */
1745 RxTransitionSrvOpen(SrvOpen, (Status == STATUS_SUCCESS ? Condition_Good : Condition_Bad));
1746
1747 ASSERT(RxIsFcbAcquiredExclusive(Fcb));
1748
1749 RxCompleteSrvOpenKeyAssociation(SrvOpen);
1750
1751 if (Status == STATUS_SUCCESS)
1752 {
1753 if (BooleanFlagOn(Stack->Parameters.Create.Options, FILE_DELETE_ON_CLOSE))
1754 {
1755 ClearFlag(Fcb->FcbState, FCB_STATE_COLLAPSING_ENABLED);
1756 }
1757 SrvOpen->CreateOptions = RxContext->Create.NtCreateParameters.CreateOptions;
1758 FcbCondition = Condition_Good;
1759 }
1760 else
1761 {
1762 FcbCondition = Condition_Bad;
1763 RxDereferenceSrvOpen(SrvOpen, LHS_ExclusiveLockHeld);
1764 RxContext->pRelevantSrvOpen = NULL;
1765
1766 if (RxContext->pFobx != NULL)
1767 {
1768 RxDereferenceNetFobx(RxContext->pFobx, LHS_ExclusiveLockHeld);
1769 RxContext->pFobx = NULL;
1770 }
1771 }
1772 }
1773
1774 /* Set FCB state - good or bad - depending on whether create succeed */
1775 DPRINT("Transitioning FCB %p to condition %lx\n", Fcb, Fcb->Condition);
1776 RxTransitionNetFcb(Fcb, FcbCondition);
1777 }
1778 else if (Status == STATUS_SUCCESS)
1779 {
1780 BOOLEAN IsGood, ExtraOpen;
1781
1782 /* A reusable SRV_OPEN was found */
1783 RxContext->CurrentIrp->IoStatus.Information = FILE_OPENED;
1784 ExtraOpen = FALSE;
1785
1786 SrvOpen = (PSRV_OPEN)RxContext->pRelevantSrvOpen;
1787
1788 IsGood = (SrvOpen->Condition == Condition_Good);
1789 /* If the SRV_OPEN isn't in a stable situation, wait for it to become stable */
1790 if (!StableCondition(SrvOpen->Condition))
1791 {
1792 RxReferenceSrvOpen(SrvOpen);
1793 ++SrvOpen->OpenCount;
1794 ExtraOpen = TRUE;
1795
1796 RxReleaseFcb(RxContext, Fcb);
1797 RxContext->Create.FcbAcquired = FALSE;
1798
1799 RxWaitForStableSrvOpen(SrvOpen, RxContext);
1800
1801 if (NT_SUCCESS(RxAcquireExclusiveFcb(RxContext, Fcb)))
1802 {
1803 RxContext->Create.FcbAcquired = TRUE;
1804 }
1805
1806 IsGood = (SrvOpen->Condition == Condition_Good);
1807 }
1808
1809 /* Inform the mini-rdr we do an opening with a reused SRV_OPEN */
1810 if (IsGood)
1811 {
1812 MINIRDR_CALL(Status, RxContext, Fcb->MRxDispatch, MRxCollapseOpen, (RxContext));
1813
1814 ASSERT(RxIsFcbAcquiredExclusive(Fcb));
1815 }
1816 else
1817 {
1818 Status = SrvOpen->OpenStatus;
1819 }
1820
1821 if (ExtraOpen)
1822 {
1823 --SrvOpen->OpenCount;
1824 RxDereferenceSrvOpen(SrvOpen, LHS_ExclusiveLockHeld);
1825 }
1826 }
1827
1828 --Fcb->UncleanCount;
1829
1830 DPRINT("Status: %x\n", Status);
1831 return Status;
1832 }
1833
1834 /*
1835 * @implemented
1836 */
1837 NTSTATUS
1838 NTAPI
1839 RxCommonCleanup(
1840 PRX_CONTEXT Context)
1841 {
1842 #define BugCheckFileId RDBSS_BUG_CHECK_CLEANUP
1843 PFCB Fcb;
1844 PFOBX Fobx;
1845 ULONG OpenCount;
1846 NTSTATUS Status;
1847 PNET_ROOT NetRoot;
1848 PFILE_OBJECT FileObject;
1849 LARGE_INTEGER TruncateSize;
1850 PLARGE_INTEGER TruncateSizePtr;
1851 BOOLEAN NeedPurge, FcbTableAcquired, OneLeft, IsFile, FcbAcquired, LeftForDelete;
1852
1853 PAGED_CODE();
1854
1855 Fcb = (PFCB)Context->pFcb;
1856 Fobx = (PFOBX)Context->pFobx;
1857 DPRINT("RxCommonCleanup(%p); FOBX: %p, FCB: %p\n", Context, Fobx, Fcb);
1858
1859 /* File system closing, it's OK */
1860 if (Fobx == NULL)
1861 {
1862 if (Fcb->UncleanCount > 0)
1863 {
1864 InterlockedDecrement((volatile long *)&Fcb->UncleanCount);
1865 }
1866
1867 return STATUS_SUCCESS;
1868 }
1869
1870 /* Check we have a correct FCB type */
1871 if (NodeType(Fcb) != RDBSS_NTC_STORAGE_TYPE_FILE &&
1872 NodeType(Fcb) != RDBSS_NTC_STORAGE_TYPE_DIRECTORY &&
1873 NodeType(Fcb) != RDBSS_NTC_STORAGE_TYPE_UNKNOWN &&
1874 NodeType(Fcb) != RDBSS_NTC_SPOOLFILE)
1875 {
1876 DPRINT1("Invalid Fcb type for %p\n", Fcb);
1877 RxBugCheck(Fcb->Header.NodeTypeCode, 0, 0);
1878 }
1879
1880 FileObject = Context->CurrentIrpSp->FileObject;
1881 ASSERT(!BooleanFlagOn(FileObject->Flags, FO_CLEANUP_COMPLETE));
1882
1883 RxMarkFobxOnCleanup(Fobx, &NeedPurge);
1884
1885 Status = RxAcquireExclusiveFcb(Context, Fcb);
1886 if (!NT_SUCCESS(Status))
1887 {
1888 return Status;
1889 }
1890
1891 FcbAcquired = TRUE;
1892
1893 Fobx->AssociatedFileObject = NULL;
1894
1895 /* In case SRV_OPEN used is part of FCB */
1896 if (BooleanFlagOn(Fcb->FcbState, FCB_STATE_SRVOPEN_USED))
1897 {
1898 ASSERT(Fcb->UncleanCount != 0);
1899 InterlockedDecrement((volatile long *)&Fcb->UncleanCount);
1900
1901 if (BooleanFlagOn(FileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING))
1902 {
1903 --Fcb->UncachedUncleanCount;
1904 }
1905
1906 /* Inform mini-rdr */
1907 MINIRDR_CALL(Status, Context, Fcb->MRxDispatch, MRxCleanupFobx, (Context));
1908
1909 ASSERT(Fobx->SrvOpen->UncleanFobxCount != 0);
1910 --Fobx->SrvOpen->UncleanFobxCount;
1911
1912 RxUninitializeCacheMap(Context, FileObject, NULL);
1913
1914 RxReleaseFcb(Context, Fcb);
1915
1916 return STATUS_SUCCESS;
1917 }
1918
1919 /* Report the fact that file could be set as delete on close */
1920 if (BooleanFlagOn(Fobx->Flags, FOBX_FLAG_DELETE_ON_CLOSE))
1921 {
1922 SetFlag(Fcb->FcbState, FCB_STATE_DELETE_ON_CLOSE);
1923 }
1924
1925 /* Cancel any pending notification */
1926 RxCancelNotifyChangeDirectoryRequestsForFobx(Fobx);
1927
1928 /* Backup open count before we start playing with it */
1929 OpenCount = Fcb->ShareAccess.OpenCount;
1930
1931 NetRoot = (PNET_ROOT)Fcb->pNetRoot;
1932 FcbTableAcquired = FALSE;
1933 LeftForDelete = FALSE;
1934 OneLeft = (Fcb->UncleanCount == 1);
1935
1936 _SEH2_TRY
1937 {
1938 /* Unclean count and delete on close? Verify whether we're the one */
1939 if (OneLeft && BooleanFlagOn(Fcb->FcbState, FCB_STATE_DELETE_ON_CLOSE))
1940 {
1941 if (RxAcquireFcbTableLockExclusive(&NetRoot->FcbTable, FALSE))
1942 {
1943 FcbTableAcquired = TRUE;
1944 }
1945 else
1946 {
1947 RxReleaseFcb(Context, Fcb);
1948
1949 RxAcquireFcbTableLockExclusive(&NetRoot->FcbTable, TRUE);
1950
1951 Status = RxAcquireExclusiveFcb(Context, Fcb);
1952 if (Status != STATUS_SUCCESS)
1953 {
1954 RxReleaseFcbTableLock(&NetRoot->FcbTable);
1955 return Status;
1956 }
1957
1958 FcbTableAcquired = TRUE;
1959 }
1960
1961 /* That means we'll perform the delete on close! */
1962 if (Fcb->UncleanCount == 1)
1963 {
1964 LeftForDelete = TRUE;
1965 }
1966 else
1967 {
1968 RxReleaseFcbTableLock(&NetRoot->FcbTable);
1969 FcbTableAcquired = FALSE;
1970 }
1971 }
1972
1973 IsFile = FALSE;
1974 TruncateSizePtr = NULL;
1975 /* Handle cleanup for pipes and printers */
1976 if (NetRoot->Type == NET_ROOT_PIPE || NetRoot->Type == NET_ROOT_PRINT)
1977 {
1978 RxCleanupPipeQueues(Context);
1979 }
1980 /* Handle cleanup for files */
1981 else if (NetRoot->Type == NET_ROOT_DISK || NetRoot->Type == NET_ROOT_WILD)
1982 {
1983 Context->LowIoContext.Flags |= LOWIO_CONTEXT_FLAG_SAVEUNLOCKS;
1984 if (NodeType(Fcb) == RDBSS_NTC_STORAGE_TYPE_FILE)
1985 {
1986 /* First, unlock */
1987 FsRtlFastUnlockAll(&Fcb->Specific.Fcb.FileLock, FileObject, RxGetRequestorProcess(Context), Context);
1988
1989 /* If there are still locks to release, proceed */
1990 if (Context->LowIoContext.ParamsFor.Locks.LockList != NULL)
1991 {
1992 RxInitializeLowIoContext(&Context->LowIoContext, LOWIO_OP_UNLOCK_MULTIPLE);
1993 Context->LowIoContext.ParamsFor.Locks.Flags = 0;
1994 Status = RxLowIoLockControlShell(Context);
1995 }
1996
1997 /* Fix times and size */
1998 RxAdjustFileTimesAndSize(Context);
1999
2000 /* If we're the only one left... */
2001 if (OneLeft)
2002 {
2003 /* And if we're supposed to delete on close */
2004 if (LeftForDelete)
2005 {
2006 /* Update the sizes */
2007 RxAcquirePagingIoResource(Context, Fcb);
2008 Fcb->Header.FileSize.QuadPart = 0;
2009 Fcb->Header.ValidDataLength.QuadPart = 0;
2010 RxReleasePagingIoResource(Context, Fcb);
2011 }
2012 /* Otherwise, call the mini-rdr to adjust sizes */
2013 else
2014 {
2015 /* File got grown up, fill with zeroes */
2016 if (!BooleanFlagOn(Fcb->FcbState, FCB_STATE_PAGING_FILE) &&
2017 (Fcb->Header.ValidDataLength.QuadPart < Fcb->Header.FileSize.QuadPart))
2018 {
2019 MINIRDR_CALL(Status, Context, Fcb->MRxDispatch, MRxZeroExtend, (Context));
2020 Fcb->Header.ValidDataLength.QuadPart = Fcb->Header.FileSize.QuadPart;
2021 }
2022
2023 /* File was truncated, let mini-rdr proceed */
2024 if (BooleanFlagOn(Fcb->FcbState, FCB_STATE_TRUNCATE_ON_CLOSE))
2025 {
2026 MINIRDR_CALL(Status, Context, Fcb->MRxDispatch, MRxTruncate, (Context));
2027 ClearFlag(Fcb->FcbState, FCB_STATE_TRUNCATE_ON_CLOSE);
2028
2029 /* Keep track of file change for Cc uninit */
2030 TruncateSize.QuadPart = Fcb->Header.FileSize.QuadPart;
2031 TruncateSizePtr = &TruncateSize;
2032 }
2033 }
2034 }
2035
2036 /* If RxMarkFobxOnCleanup() asked for purge, make sure we're the only one left first */
2037 if (NeedPurge)
2038 {
2039 if (!OneLeft)
2040 {
2041 NeedPurge = FALSE;
2042 }
2043 }
2044 /* Otherwise, try to see whether we can purge */
2045 else
2046 {
2047 NeedPurge = (OneLeft && (LeftForDelete || !BooleanFlagOn(Fcb->FcbState, FCB_STATE_COLLAPSING_ENABLED)));
2048 }
2049
2050 IsFile = TRUE;
2051 }
2052 }
2053
2054 /* We have to still be there! */
2055 ASSERT(Fcb->UncleanCount != 0);
2056 InterlockedDecrement((volatile long *)&Fcb->UncleanCount);
2057
2058 if (BooleanFlagOn(FileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING))
2059 {
2060 --Fcb->UncachedUncleanCount;
2061 }
2062
2063 /* Inform mini-rdr about ongoing cleanup */
2064 MINIRDR_CALL(Status, Context, Fcb->MRxDispatch, MRxCleanupFobx, (Context));
2065
2066 ASSERT(Fobx->SrvOpen->UncleanFobxCount != 0);
2067 --Fobx->SrvOpen->UncleanFobxCount;
2068
2069 /* Flush cache */
2070 if (DisableFlushOnCleanup)
2071 {
2072 /* Only if we're the last standing */
2073 if (Fcb->NonPaged->SectionObjectPointers.DataSectionObject != NULL &&
2074 Fcb->UncleanCount == Fcb->UncachedUncleanCount)
2075 {
2076 DPRINT("Flushing %p due to last cached handle cleanup\n", Context);
2077 RxFlushFcbInSystemCache(Fcb, TRUE);
2078 }
2079 }
2080 else
2081 {
2082 /* Always */
2083 if (Fcb->NonPaged->SectionObjectPointers.DataSectionObject != NULL)
2084 {
2085 DPRINT("Flushing %p on cleanup\n", Context);
2086 RxFlushFcbInSystemCache(Fcb, TRUE);
2087 }
2088 }
2089
2090 /* If only remaining uncached & unclean, then flush and purge */
2091 if (!BooleanFlagOn(FileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING))
2092 {
2093 if (Fcb->UncachedUncleanCount != 0)
2094 {
2095 if (Fcb->UncachedUncleanCount == Fcb->UncleanCount &&
2096 Fcb->NonPaged->SectionObjectPointers.DataSectionObject != NULL)
2097 {
2098 DPRINT("Flushing FCB in system cache for %p\n", Context);
2099 RxPurgeFcbInSystemCache(Fcb, NULL, 0, FALSE, TRUE);
2100 }
2101 }
2102 }
2103
2104 /* If purge required, and not about to delete, flush */
2105 if (!LeftForDelete && NeedPurge)
2106 {
2107 DPRINT("Flushing FCB in system cache for %p\n", Context);
2108 RxFlushFcbInSystemCache(Fcb, TRUE);
2109 }
2110
2111 /* If it was a file, drop cache */
2112 if (IsFile)
2113 {
2114 DPRINT("Uninit cache map for file\n");
2115 RxUninitializeCacheMap(Context, FileObject, TruncateSizePtr);
2116 }
2117
2118 /* If that's the one left for deletion, or if it needs purge, flush */
2119 if (LeftForDelete || NeedPurge)
2120 {
2121 RxPurgeFcbInSystemCache(Fcb, NULL, 0, FALSE, !LeftForDelete);
2122 /* If that's for deletion, also remove from FCB table */
2123 if (LeftForDelete)
2124 {
2125 RxRemoveNameNetFcb(Fcb);
2126 RxReleaseFcbTableLock(&NetRoot->FcbTable);
2127 FcbTableAcquired = FALSE;
2128 }
2129 }
2130
2131 /* Remove any share access */
2132 if (OpenCount != 0 && NetRoot->Type == NET_ROOT_DISK)
2133 {
2134 RxRemoveShareAccess(FileObject, &Fcb->ShareAccess, "Cleanup the share access", "ClnUpShr");
2135 }
2136
2137 /* In case there's caching, on a file, and we were asked to drop collapsing, handle it */
2138 if (NodeType(Fcb) == RDBSS_NTC_STORAGE_TYPE_FILE && BooleanFlagOn(Fobx->Flags, FOBX_FLAG_DISABLE_COLLAPSING) &&
2139 RxWriteCacheingAllowed(Fcb, Fobx->pSrvOpen))
2140 {
2141 NTSTATUS InternalStatus;
2142 PRX_CONTEXT InternalContext;
2143
2144 /* If we can properly set EOF, there's no need to drop collapsing, try to do it */
2145 InternalStatus = STATUS_UNSUCCESSFUL;
2146 InternalContext = RxCreateRxContext(Context->CurrentIrp,
2147 Fcb->RxDeviceObject,
2148 RX_CONTEXT_FLAG_WAIT | RX_CONTEXT_FLAG_MUST_SUCCEED_NONBLOCKING);
2149 if (InternalContext != NULL)
2150 {
2151 FILE_END_OF_FILE_INFORMATION FileEOF;
2152
2153 InternalStatus = STATUS_SUCCESS;
2154
2155 /* Initialize the context for file information set */
2156 InternalContext->pFcb = RX_GET_MRX_FCB(Fcb);
2157 InternalContext->pFobx = (PMRX_FOBX)Fobx;
2158 InternalContext->pRelevantSrvOpen = Fobx->pSrvOpen;
2159
2160 /* Get EOF from the FCB */
2161 FileEOF.EndOfFile.QuadPart = Fcb->Header.FileSize.QuadPart;
2162 InternalContext->Info.FileInformationClass = FileEndOfFileInformation;
2163 InternalContext->Info.Buffer = &FileEOF;
2164 InternalContext->Info.Length = sizeof(FileEOF);
2165
2166 /* Call the mini-rdr */
2167 MINIRDR_CALL_THROUGH(InternalStatus, Fcb->MRxDispatch, MRxSetFileInfo, (InternalContext));
2168
2169 /* We're done */
2170 RxDereferenceAndDeleteRxContext(InternalContext);
2171 }
2172
2173 /* We tried, so, clean the FOBX flag */
2174 ClearFlag(Fobx->Flags, FOBX_FLAG_DISABLE_COLLAPSING);
2175 /* If it failed, then, disable collapsing on the FCB */
2176 if (!NT_SUCCESS(InternalStatus))
2177 {
2178 ClearFlag(Fcb->FcbState, FCB_STATE_COLLAPSING_ENABLED);
2179 }
2180 }
2181
2182 /* We're clean! */
2183 SetFlag(FileObject->Flags, FO_CLEANUP_COMPLETE);
2184
2185 FcbAcquired = FALSE;
2186 RxReleaseFcb(Context, Fcb);
2187 }
2188 _SEH2_FINALLY
2189 {
2190 if (FcbAcquired)
2191 {
2192 RxReleaseFcb(Context, Fcb);
2193 }
2194
2195 if (FcbTableAcquired)
2196 {
2197 RxReleaseFcbTableLock(&NetRoot->FcbTable);
2198 }
2199 }
2200 _SEH2_END;
2201
2202 return Status;
2203 #undef BugCheckFileId
2204 }
2205
2206 NTSTATUS
2207 NTAPI
2208 RxCommonClose(
2209 PRX_CONTEXT Context)
2210 {
2211 #define BugCheckFileId RDBSS_BUG_CHECK_CLOSE
2212 PFCB Fcb;
2213 PFOBX Fobx;
2214 NTSTATUS Status;
2215 PFILE_OBJECT FileObject;
2216 BOOLEAN DereferenceFobx, AcquiredFcb;
2217
2218 PAGED_CODE();
2219
2220 Fcb = (PFCB)Context->pFcb;
2221 Fobx = (PFOBX)Context->pFobx;
2222 FileObject = Context->CurrentIrpSp->FileObject;
2223 DPRINT("RxCommonClose(%p); FOBX: %p, FCB: %p, FO: %p\n", Context, Fobx, Fcb, FileObject);
2224
2225 Status = RxAcquireExclusiveFcb(Context, Fcb);
2226 if (!NT_SUCCESS(Status))
2227 {
2228 return Status;
2229 }
2230
2231 AcquiredFcb = TRUE;
2232 _SEH2_TRY
2233 {
2234 BOOLEAN Freed;
2235
2236 /* Check our FCB type is expected */
2237 if (NodeType(Fcb) != RDBSS_NTC_STORAGE_TYPE_UNKNOWN &&
2238 (NodeType(Fcb) < RDBSS_NTC_STORAGE_TYPE_DIRECTORY || (NodeType(Fcb) > RDBSS_NTC_STORAGE_TYPE_FILE &&
2239 (NodeType(Fcb) < RDBSS_NTC_SPOOLFILE || NodeType(Fcb) > RDBSS_NTC_OPENTARGETDIR_FCB))))
2240 {
2241 RxBugCheck(NodeType(Fcb), 0, 0);
2242 }
2243
2244 RxReferenceNetFcb(Fcb);
2245
2246 DereferenceFobx = FALSE;
2247 /* If we're not closing FS */
2248 if (Fobx != NULL)
2249 {
2250 PSRV_OPEN SrvOpen;
2251 PSRV_CALL SrvCall;
2252
2253 SrvOpen = (PSRV_OPEN)Fobx->pSrvOpen;
2254 SrvCall = (PSRV_CALL)Fcb->pNetRoot->pSrvCall;
2255 /* Handle delayed close */
2256 if (NodeType(Fcb) != RDBSS_NTC_STORAGE_TYPE_DIRECTORY)
2257 {
2258 if (!BooleanFlagOn(Fcb->FcbState, FCB_STATE_DELETE_ON_CLOSE | FCB_STATE_ORPHANED))
2259 {
2260 if (BooleanFlagOn(Fcb->FcbState, FCB_STATE_COLLAPSING_ENABLED))
2261 {
2262 DPRINT("Delay close for FOBX: %p, SrvOpen %p\n", Fobx, SrvOpen);
2263
2264 if (SrvOpen->OpenCount == 1 && !BooleanFlagOn(SrvOpen->Flags, SRVOPEN_FLAG_COLLAPSING_DISABLED))
2265 {
2266 if (InterlockedIncrement(&SrvCall->NumberOfCloseDelayedFiles) >= SrvCall->MaximumNumberOfCloseDelayedFiles)
2267 {
2268 InterlockedDecrement(&SrvCall->NumberOfCloseDelayedFiles);
2269 }
2270 else
2271 {
2272 DereferenceFobx = TRUE;
2273 SetFlag(SrvOpen->Flags, SRVOPEN_FLAG_CLOSE_DELAYED);
2274 }
2275 }
2276 }
2277 }
2278 }
2279
2280 /* If we reach maximum of delayed close/or if there are no delayed close */
2281 if (!DereferenceFobx)
2282 {
2283 PNET_ROOT NetRoot;
2284
2285 NetRoot = (PNET_ROOT)Fcb->pNetRoot;
2286 if (NetRoot->Type != NET_ROOT_PRINT)
2287 {
2288 /* Delete if asked */
2289 if (BooleanFlagOn(Fobx->Flags, FOBX_FLAG_DELETE_ON_CLOSE))
2290 {
2291 RxScavengeRelatedFobxs(Fcb);
2292 RxSynchronizeWithScavenger(Context);
2293
2294 RxReleaseFcb(Context, Fcb);
2295
2296 RxAcquireFcbTableLockExclusive(&NetRoot->FcbTable, TRUE);
2297 RxOrphanThisFcb(Fcb);
2298 RxReleaseFcbTableLock(&NetRoot->FcbTable);
2299
2300 Status = RxAcquireExclusiveFcb(Context, Fcb);
2301 ASSERT(NT_SUCCESS(Status));
2302 }
2303 }
2304 }
2305
2306 RxMarkFobxOnClose(Fobx);
2307 }
2308
2309 if (DereferenceFobx)
2310 {
2311 ASSERT(Fobx != NULL);
2312 RxDereferenceNetFobx(Fobx, LHS_SharedLockHeld);
2313 }
2314 else
2315 {
2316 RxCloseAssociatedSrvOpen(Fobx, Context);
2317 if (Fobx != NULL)
2318 {
2319 RxDereferenceNetFobx(Fobx, LHS_ExclusiveLockHeld);
2320 }
2321 }
2322
2323 Freed = RxDereferenceAndFinalizeNetFcb(Fcb, Context, FALSE, FALSE);
2324 AcquiredFcb = !Freed;
2325
2326 FileObject->FsContext = (PVOID)-1;
2327
2328 if (Freed)
2329 {
2330 RxTrackerUpdateHistory(Context, NULL, TRACKER_FCB_FREE, __LINE__, __FILE__, 0);
2331 }
2332 else
2333 {
2334 RxReleaseFcb(Context, Fcb);
2335 AcquiredFcb = FALSE;
2336 }
2337 }
2338 _SEH2_FINALLY
2339 {
2340 if (_SEH2_AbnormalTermination())
2341 {
2342 if (AcquiredFcb)
2343 {
2344 RxReleaseFcb(Context, Fcb);
2345 }
2346 }
2347 else
2348 {
2349 ASSERT(!AcquiredFcb);
2350 }
2351 }
2352 _SEH2_END;
2353
2354 DPRINT("Status: %x\n", Status);
2355 return Status;
2356 #undef BugCheckFileId
2357 }
2358
2359 /*
2360 * @implemented
2361 */
2362 NTSTATUS
2363 NTAPI
2364 RxCommonCreate(
2365 PRX_CONTEXT Context)
2366 {
2367 PIRP Irp;
2368 NTSTATUS Status;
2369 PFILE_OBJECT FileObject;
2370 PIO_STACK_LOCATION Stack;
2371
2372 PAGED_CODE();
2373
2374 DPRINT("RxCommonCreate(%p)\n", Context);
2375
2376 Irp = Context->CurrentIrp;
2377 Stack = Context->CurrentIrpSp;
2378 FileObject = Stack->FileObject;
2379
2380 /* Check whether that's a device opening */
2381 if (FileObject->FileName.Length == 0 && FileObject->RelatedFileObject == NULL)
2382 {
2383 FileObject->FsContext = &RxDeviceFCB;
2384 FileObject->FsContext2 = NULL;
2385
2386 ++RxDeviceFCB.NodeReferenceCount;
2387 ++RxDeviceFCB.OpenCount;
2388
2389 Irp->IoStatus.Information = FILE_OPENED;
2390 DPRINT("Device opening FO: %p, DO: %p, Name: %wZ\n", FileObject, Context->RxDeviceObject, &Context->RxDeviceObject->DeviceName);
2391
2392 Status = STATUS_SUCCESS;
2393 }
2394 else
2395 {
2396 PFCB RelatedFcb = NULL;
2397
2398 /* Make sure caller is consistent */
2399 if (FlagOn(Stack->Parameters.Create.Options, FILE_DIRECTORY_FILE | FILE_NON_DIRECTORY_FILE | FILE_OPEN_REMOTE_INSTANCE) ==
2400 (FILE_DIRECTORY_FILE | FILE_NON_DIRECTORY_FILE | FILE_OPEN_REMOTE_INSTANCE))
2401 {
2402 DPRINT1("Create.Options: %x\n", Stack->Parameters.Create.Options);
2403 return STATUS_INVALID_PARAMETER;
2404 }
2405
2406 DPRINT("Ctxt: %p, FO: %p, Options: %lx, Flags: %lx, Attr: %lx, ShareAccess: %lx, DesiredAccess: %lx\n",
2407 Context, FileObject, Stack->Parameters.Create.Options, Stack->Flags, Stack->Parameters.Create.FileAttributes,
2408 Stack->Parameters.Create.ShareAccess, Stack->Parameters.Create.SecurityContext->DesiredAccess);
2409 DPRINT("FileName: %wZ\n", &FileObject->FileName);
2410
2411 if (FileObject->RelatedFileObject != NULL)
2412 {
2413 RelatedFcb = FileObject->RelatedFileObject->FsContext;
2414 DPRINT("Rel FO: %p, path: %wZ\n", FileObject->RelatedFileObject, RelatedFcb->FcbTableEntry.Path);
2415 }
2416
2417 /* Going to rename? */
2418 if (BooleanFlagOn(Stack->Flags, SL_OPEN_TARGET_DIRECTORY))
2419 {
2420 DPRINT("TargetDir!\n");
2421 }
2422
2423 /* Copy create parameters to the context */
2424 RxCopyCreateParameters(Context);
2425
2426 /* If the caller wants to establish a connection, go ahead */
2427 if (BooleanFlagOn(Stack->Parameters.Create.Options, FILE_CREATE_TREE_CONNECTION))
2428 {
2429 Status = RxCreateTreeConnect(Context);
2430 }
2431 else
2432 {
2433 /* Validate file name */
2434 if (FileObject->FileName.Length > sizeof(WCHAR) &&
2435 FileObject->FileName.Buffer[1] == OBJ_NAME_PATH_SEPARATOR &&
2436 FileObject->FileName.Buffer[0] == OBJ_NAME_PATH_SEPARATOR)
2437 {
2438 FileObject->FileName.Length -= sizeof(WCHAR);
2439 RtlMoveMemory(&FileObject->FileName.Buffer[0], &FileObject->FileName.Buffer[1],
2440 FileObject->FileName.Length);
2441
2442 if (FileObject->FileName.Length > sizeof(WCHAR) &&
2443 FileObject->FileName.Buffer[1] == OBJ_NAME_PATH_SEPARATOR &&
2444 FileObject->FileName.Buffer[0] == OBJ_NAME_PATH_SEPARATOR)
2445 {
2446 return STATUS_OBJECT_NAME_INVALID;
2447 }
2448 }
2449
2450 /* Attempt to open the file */
2451 do
2452 {
2453 UNICODE_STRING NetRootName;
2454
2455 /* Strip last \ if required */
2456 if (FileObject->FileName.Length != 0 &&
2457 FileObject->FileName.Buffer[FileObject->FileName.Length / sizeof(WCHAR) - 1] == OBJ_NAME_PATH_SEPARATOR)
2458 {
2459 if (BooleanFlagOn(Stack->Parameters.Create.Options, FILE_NON_DIRECTORY_FILE))
2460 {
2461 return STATUS_OBJECT_NAME_INVALID;
2462 }
2463
2464 FileObject->FileName.Length -= sizeof(WCHAR);
2465 Context->Create.Flags |= RX_CONTEXT_CREATE_FLAG_STRIPPED_TRAILING_BACKSLASH;
2466 }
2467
2468 if (BooleanFlagOn(Context->Flags, RX_CONTEXT_FLAG_WRITE_THROUGH))
2469 {
2470 FileObject->Flags |= FO_WRITE_THROUGH;
2471 }
2472
2473 /* Get the associated net root to opening */
2474 Status = RxCanonicalizeNameAndObtainNetRoot(Context, &FileObject->FileName, &NetRootName);
2475 if (Status != STATUS_MORE_PROCESSING_REQUIRED)
2476 {
2477 break;
2478 }
2479
2480 /* And attempt to open */
2481 Status = RxCreateFromNetRoot(Context, &NetRootName);
2482 if (Status == STATUS_SHARING_VIOLATION)
2483 {
2484 ASSERT(!BooleanFlagOn(Context->Create.Flags, RX_CONTEXT_CREATE_FLAG_REPARSE));
2485
2486 /* If that happens for file creation, fail for real */
2487 if (Context->Create.NtCreateParameters.Disposition == FILE_CREATE)
2488 {
2489 Status = STATUS_OBJECT_NAME_COLLISION;
2490 }
2491 else
2492 {
2493 /* Otherwise, if possible, attempt to scavenger current FOBX
2494 * to check whether a dormant FOBX is the reason for sharing violation
2495 */
2496 if (Context->Create.TryForScavengingOnSharingViolation &&
2497 !Context->Create.ScavengingAlreadyTried)
2498 {
2499 /* Only doable with a VNetRoot */
2500 if (Context->Create.pVNetRoot != NULL)
2501 {
2502 PV_NET_ROOT VNetRoot;
2503 NT_CREATE_PARAMETERS SavedParameters;
2504
2505 /* Save create parameters */
2506 RtlCopyMemory(&SavedParameters, &Context->Create.NtCreateParameters, sizeof(NT_CREATE_PARAMETERS));
2507
2508 /* Reference the VNetRoot for the scavenging time */
2509 VNetRoot = (PV_NET_ROOT)Context->Create.pVNetRoot;
2510 RxReferenceVNetRoot(VNetRoot);
2511
2512 /* Prepare the RX_CONTEXT for reuse */
2513 RxpPrepareCreateContextForReuse(Context);
2514 RxReinitializeContext(Context);
2515
2516 /* Copy what we saved */
2517 RtlCopyMemory(&Context->Create.NtCreateParameters, &SavedParameters, sizeof(NT_CREATE_PARAMETERS));
2518
2519 /* And recopy what can be */
2520 RxCopyCreateParameters(Context);
2521
2522 /* And start purging, then scavenging FOBX */
2523 RxPurgeRelatedFobxs((PNET_ROOT)VNetRoot->pNetRoot, Context,
2524 DONT_ATTEMPT_FINALIZE_ON_PURGE, NULL);
2525 RxScavengeFobxsForNetRoot((PNET_ROOT)VNetRoot->pNetRoot,
2526 NULL, TRUE);
2527
2528 /* Ask for a second round */
2529 Status = STATUS_MORE_PROCESSING_REQUIRED;
2530
2531 /* Keep track we already scavenged */
2532 Context->Create.ScavengingAlreadyTried = TRUE;
2533
2534 /* Reference our SRV_CALL for CBS handling */
2535 RxReferenceSrvCall(VNetRoot->pNetRoot->pSrvCall);
2536 RxpProcessChangeBufferingStateRequests((PSRV_CALL)VNetRoot->pNetRoot->pSrvCall, FALSE);
2537
2538 /* Drop our extra reference */
2539 RxDereferenceVNetRoot(VNetRoot, LHS_LockNotHeld);
2540 }
2541 }
2542 }
2543 }
2544 else if (Status == STATUS_REPARSE)
2545 {
2546 Context->CurrentIrp->IoStatus.Information = 0;
2547 }
2548 else
2549 {
2550 ASSERT(!BooleanFlagOn(Context->Create.Flags, RX_CONTEXT_CREATE_FLAG_REPARSE));
2551 }
2552 }
2553 while (Status == STATUS_MORE_PROCESSING_REQUIRED);
2554 }
2555
2556 if (Status == STATUS_RETRY)
2557 {
2558 RxpPrepareCreateContextForReuse(Context);
2559 }
2560 ASSERT(Status != STATUS_PENDING);
2561 }
2562
2563 DPRINT("Status: %lx\n", Status);
2564 return Status;
2565 }
2566
2567 /*
2568 * @implemented
2569 */
2570 NTSTATUS
2571 NTAPI
2572 RxCommonDevFCBCleanup(
2573 PRX_CONTEXT Context)
2574 {
2575 PMRX_FCB Fcb;
2576 NTSTATUS Status;
2577
2578 PAGED_CODE();
2579
2580 DPRINT("RxCommonDevFCBCleanup(%p)\n", Context);
2581
2582 Fcb = Context->pFcb;
2583 Status = STATUS_SUCCESS;
2584 ASSERT(NodeType(Fcb) == RDBSS_NTC_DEVICE_FCB);
2585
2586 /* Our FOBX if set, has to be a VNetRoot */
2587 if (Context->pFobx != NULL)
2588 {
2589 RxAcquirePrefixTableLockShared(Context->RxDeviceObject->pRxNetNameTable, TRUE);
2590 if (Context->pFobx->NodeTypeCode != RDBSS_NTC_V_NETROOT)
2591 {
2592 Status = STATUS_INVALID_DEVICE_REQUEST;
2593 }
2594 RxReleasePrefixTableLock(Context->RxDeviceObject->pRxNetNameTable);
2595 }
2596 else
2597 {
2598 --Fcb->UncleanCount;
2599 }
2600
2601 return Status;
2602 }
2603
2604 /*
2605 * @implemented
2606 */
2607 NTSTATUS
2608 NTAPI
2609 RxCommonDevFCBClose(
2610 PRX_CONTEXT Context)
2611 {
2612 PMRX_FCB Fcb;
2613 NTSTATUS Status;
2614 PMRX_V_NET_ROOT NetRoot;
2615
2616 PAGED_CODE();
2617
2618 DPRINT("RxCommonDevFCBClose(%p)\n", Context);
2619
2620 Fcb = Context->pFcb;
2621 NetRoot = (PMRX_V_NET_ROOT)Context->pFobx;
2622 Status = STATUS_SUCCESS;
2623 ASSERT(NodeType(Fcb) == RDBSS_NTC_DEVICE_FCB);
2624
2625 /* Our FOBX if set, has to be a VNetRoot */
2626 if (NetRoot != NULL)
2627 {
2628 RxAcquirePrefixTableLockExclusive(Context->RxDeviceObject->pRxNetNameTable, TRUE);
2629 if (NetRoot->NodeTypeCode == RDBSS_NTC_V_NETROOT)
2630 {
2631 --NetRoot->NumberOfOpens;
2632 RxDereferenceVNetRoot(NetRoot, LHS_ExclusiveLockHeld);
2633 }
2634 else
2635 {
2636 Status = STATUS_NOT_IMPLEMENTED;
2637 }
2638 RxReleasePrefixTableLock(Context->RxDeviceObject->pRxNetNameTable);
2639 }
2640 else
2641 {
2642 --Fcb->OpenCount;
2643 }
2644
2645 return Status;
2646 }
2647
2648 NTSTATUS
2649 NTAPI
2650 RxCommonDevFCBFsCtl(
2651 PRX_CONTEXT Context)
2652 {
2653 UNIMPLEMENTED;
2654 return STATUS_NOT_IMPLEMENTED;
2655 }
2656
2657 /*
2658 * @implemented
2659 */
2660 NTSTATUS
2661 NTAPI
2662 RxCommonDevFCBIoCtl(
2663 PRX_CONTEXT Context)
2664 {
2665 NTSTATUS Status;
2666
2667 PAGED_CODE();
2668
2669 DPRINT("RxCommonDevFCBIoCtl(%p)\n", Context);
2670
2671 if (Context->pFobx != NULL)
2672 {
2673 return STATUS_INVALID_HANDLE;
2674 }
2675
2676 /* Is that a prefix claim from MUP? */
2677 if (Context->CurrentIrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_REDIR_QUERY_PATH)
2678 {
2679 return RxPrefixClaim(Context);
2680 }
2681
2682 /* Otherwise, pass through the mini-rdr */
2683 Status = RxXXXControlFileCallthru(Context);
2684 if (Status != STATUS_PENDING)
2685 {
2686 if (Context->PostRequest)
2687 {
2688 Context->ResumeRoutine = RxCommonDevFCBIoCtl;
2689 Status = RxFsdPostRequest(Context);
2690 }
2691 }
2692
2693 DPRINT("Status: %lx\n", Status);
2694 return Status;
2695 }
2696
2697 NTSTATUS
2698 NTAPI
2699 RxCommonDevFCBQueryVolInfo(
2700 PRX_CONTEXT Context)
2701 {
2702 UNIMPLEMENTED;
2703 return STATUS_NOT_IMPLEMENTED;
2704 }
2705
2706 /*
2707 * @implemented
2708 */
2709 NTSTATUS
2710 NTAPI
2711 RxCommonDeviceControl(
2712 PRX_CONTEXT Context)
2713 {
2714 NTSTATUS Status;
2715
2716 PAGED_CODE();
2717
2718 /* Prefix claim is only allowed for device, not files */
2719 if (Context->CurrentIrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_REDIR_QUERY_PATH)
2720 {
2721 return STATUS_INVALID_DEVICE_REQUEST;
2722 }
2723
2724 /* Submit to mini-rdr */
2725 RxInitializeLowIoContext(&Context->LowIoContext, LOWIO_OP_IOCTL);
2726 Status = RxLowIoSubmit(Context, RxLowIoIoCtlShellCompletion);
2727 if (Status == STATUS_PENDING)
2728 {
2729 RxDereferenceAndDeleteRxContext_Real(Context);
2730 }
2731
2732 return Status;
2733 }
2734
2735 /*
2736 * @implemented
2737 */
2738 NTSTATUS
2739 NTAPI
2740 RxCommonDirectoryControl(
2741 PRX_CONTEXT Context)
2742 {
2743 PFCB Fcb;
2744 PFOBX Fobx;
2745 NTSTATUS Status;
2746 PIO_STACK_LOCATION Stack;
2747
2748 PAGED_CODE();
2749
2750 Fcb = (PFCB)Context->pFcb;
2751 Fobx = (PFOBX)Context->pFobx;
2752 Stack = Context->CurrentIrpSp;
2753 DPRINT("RxCommonDirectoryControl(%p) FOBX: %p, FCB: %p, Minor: %d\n", Context, Fobx, Fcb, Stack->MinorFunction);
2754
2755 /* Call the appropriate helper */
2756 if (Stack->MinorFunction == IRP_MN_QUERY_DIRECTORY)
2757 {
2758 Status = RxQueryDirectory(Context);
2759 }
2760 else if (Stack->MinorFunction == IRP_MN_NOTIFY_CHANGE_DIRECTORY)
2761 {
2762 Status = RxNotifyChangeDirectory(Context);
2763 if (Status == STATUS_PENDING)
2764 {
2765 RxDereferenceAndDeleteRxContext_Real(Context);
2766 }
2767 }
2768 else
2769 {
2770 Status = STATUS_INVALID_DEVICE_REQUEST;
2771 }
2772
2773 return Status;
2774 }
2775
2776 NTSTATUS
2777 NTAPI
2778 RxCommonDispatchProblem(
2779 PRX_CONTEXT Context)
2780 {
2781 UNIMPLEMENTED;
2782 return STATUS_NOT_IMPLEMENTED;
2783 }
2784
2785 NTSTATUS
2786 NTAPI
2787 RxCommonFileSystemControl(
2788 PRX_CONTEXT Context)
2789 {
2790 PIRP Irp;
2791 ULONG ControlCode;
2792 PIO_STACK_LOCATION Stack;
2793
2794 PAGED_CODE();
2795
2796 Irp = Context->CurrentIrp;
2797 Stack = Context->CurrentIrpSp;
2798 ControlCode = Stack->Parameters.FileSystemControl.FsControlCode;
2799
2800 DPRINT1("RxCommonFileSystemControl: %p, %p, %d, %lx\n", Context, Irp, Stack->MinorFunction, ControlCode);
2801
2802 UNIMPLEMENTED;
2803 return STATUS_NOT_IMPLEMENTED;
2804 }
2805
2806 NTSTATUS
2807 NTAPI
2808 RxCommonFlushBuffers(
2809 PRX_CONTEXT Context)
2810 {
2811 UNIMPLEMENTED;
2812 return STATUS_NOT_IMPLEMENTED;
2813 }
2814
2815 NTSTATUS
2816 NTAPI
2817 RxCommonLockControl(
2818 PRX_CONTEXT Context)
2819 {
2820 UNIMPLEMENTED;
2821 return STATUS_NOT_IMPLEMENTED;
2822 }
2823
2824 NTSTATUS
2825 NTAPI
2826 RxCommonQueryEa(
2827 PRX_CONTEXT Context)
2828 {
2829 UNIMPLEMENTED;
2830 return STATUS_NOT_IMPLEMENTED;
2831 }
2832
2833 /*
2834 * @implemented
2835 */
2836 NTSTATUS
2837 NTAPI
2838 RxCommonQueryInformation(
2839 PRX_CONTEXT Context)
2840 {
2841 #define SET_SIZE_AND_QUERY(AlreadyConsummed, Function) \
2842 Context->Info.Length = Stack->Parameters.QueryFile.Length - (AlreadyConsummed); \
2843 Status = Function(Context, Add2Ptr(Buffer, AlreadyConsummed))
2844
2845 PFCB Fcb;
2846 PIRP Irp;
2847 PFOBX Fobx;
2848 BOOLEAN Locked;
2849 NTSTATUS Status;
2850 PIO_STACK_LOCATION Stack;
2851 FILE_INFORMATION_CLASS FileInfoClass;
2852
2853 PAGED_CODE();
2854
2855 Fcb = (PFCB)Context->pFcb;
2856 Fobx = (PFOBX)Context->pFobx;
2857 DPRINT("RxCommonQueryInformation(%p) FCB: %p, FOBX: %p\n", Context, Fcb, Fobx);
2858
2859 Irp = Context->CurrentIrp;
2860 Stack = Context->CurrentIrpSp;
2861 DPRINT("Buffer: %p, Length: %lx, Class: %ld\n", Irp->AssociatedIrp.SystemBuffer,
2862 Stack->Parameters.QueryFile.Length, Stack->Parameters.QueryFile.FileInformationClass);
2863
2864 Context->Info.Length = Stack->Parameters.QueryFile.Length;
2865 FileInfoClass = Stack->Parameters.QueryFile.FileInformationClass;
2866
2867 Locked = FALSE;
2868 _SEH2_TRY
2869 {
2870 PVOID Buffer;
2871
2872 /* Get a writable buffer */
2873 Buffer = RxMapSystemBuffer(Context);
2874 if (Buffer == NULL)
2875 {
2876 Status = STATUS_INSUFFICIENT_RESOURCES;
2877 _SEH2_LEAVE;
2878 }
2879 /* Zero it */
2880 RtlZeroMemory(Buffer, Context->Info.Length);
2881
2882 /* Validate file type */
2883 if (NodeType(Fcb) != RDBSS_NTC_STORAGE_TYPE_UNKNOWN)
2884 {
2885 if (NodeType(Fcb) < RDBSS_NTC_STORAGE_TYPE_DIRECTORY)
2886 {
2887 Status = STATUS_INVALID_PARAMETER;
2888 _SEH2_LEAVE;
2889 }
2890 else if (NodeType(Fcb) > RDBSS_NTC_STORAGE_TYPE_FILE)
2891 {
2892 if (NodeType(Fcb) == RDBSS_NTC_MAILSLOT)
2893 {
2894 Status = STATUS_NOT_IMPLEMENTED;
2895 }
2896 else
2897 {
2898 Status = STATUS_INVALID_PARAMETER;
2899 }
2900
2901 _SEH2_LEAVE;
2902 }
2903 }
2904
2905 /* Acquire the right lock */
2906 if (!BooleanFlagOn(Fcb->FcbState, FCB_STATE_PAGING_FILE) &&
2907 FileInfoClass != FileNameInformation)
2908 {
2909 if (FileInfoClass == FileCompressionInformation)
2910 {
2911 Status = RxAcquireExclusiveFcb(Context, Fcb);
2912 }
2913 else
2914 {
2915 Status = RxAcquireSharedFcb(Context, Fcb);
2916 }
2917
2918 if (Status == STATUS_LOCK_NOT_GRANTED)
2919 {
2920 Status = STATUS_PENDING;
2921 _SEH2_LEAVE;
2922 }
2923 else if (!NT_SUCCESS(Status))
2924 {
2925 _SEH2_LEAVE;
2926 }
2927
2928 Locked = TRUE;
2929 }
2930
2931 /* Dispatch to the right helper */
2932 switch (FileInfoClass)
2933 {
2934 case FileBasicInformation:
2935 Status = RxQueryBasicInfo(Context, Buffer);
2936 break;
2937
2938 case FileStandardInformation:
2939 Status = RxQueryStandardInfo(Context, Buffer);
2940 break;
2941
2942 case FileInternalInformation:
2943 Status = RxQueryInternalInfo(Context, Buffer);
2944 break;
2945
2946 case FileEaInformation:
2947 Status = RxQueryEaInfo(Context, Buffer);
2948 break;
2949
2950 case FileNameInformation:
2951 Status = RxQueryNameInfo(Context, Buffer);
2952 break;
2953
2954 case FileAllInformation:
2955 SET_SIZE_AND_QUERY(0, RxQueryBasicInfo);
2956 if (!NT_SUCCESS(Status))
2957 {
2958 break;
2959 }
2960
2961 SET_SIZE_AND_QUERY(sizeof(FILE_BASIC_INFORMATION), RxQueryStandardInfo);
2962 if (!NT_SUCCESS(Status))
2963 {
2964 break;
2965 }
2966
2967 SET_SIZE_AND_QUERY(sizeof(FILE_BASIC_INFORMATION) +
2968 sizeof(FILE_STANDARD_INFORMATION), RxQueryInternalInfo);
2969 if (!NT_SUCCESS(Status))
2970 {
2971 break;
2972 }
2973
2974 SET_SIZE_AND_QUERY(sizeof(FILE_BASIC_INFORMATION) +
2975 sizeof(FILE_STANDARD_INFORMATION) +
2976 sizeof(FILE_INTERNAL_INFORMATION), RxQueryEaInfo);
2977 if (!NT_SUCCESS(Status))
2978 {
2979 break;
2980 }
2981
2982 SET_SIZE_AND_QUERY(sizeof(FILE_BASIC_INFORMATION) +
2983 sizeof(FILE_STANDARD_INFORMATION) +
2984 sizeof(FILE_INTERNAL_INFORMATION) +
2985 sizeof(FILE_EA_INFORMATION), RxQueryPositionInfo);
2986 if (!NT_SUCCESS(Status))
2987 {
2988 break;
2989 }
2990
2991 SET_SIZE_AND_QUERY(sizeof(FILE_BASIC_INFORMATION) +
2992 sizeof(FILE_STANDARD_INFORMATION) +
2993 sizeof(FILE_INTERNAL_INFORMATION) +
2994 sizeof(FILE_EA_INFORMATION) +
2995 sizeof(FILE_POSITION_INFORMATION), RxQueryNameInfo);
2996 break;
2997
2998 case FileAlternateNameInformation:
2999 Status = RxQueryAlternateNameInfo(Context, Buffer);
3000 break;
3001
3002 case FilePipeInformation:
3003 case FilePipeLocalInformation:
3004 case FilePipeRemoteInformation:
3005 Status = RxQueryPipeInfo(Context, Buffer);
3006 break;
3007
3008 case FileCompressionInformation:
3009 Status = RxQueryCompressedInfo(Context, Buffer);
3010 break;
3011
3012 default:
3013 Context->IoStatusBlock.Status = RxpQueryInfoMiniRdr(Context, FileInfoClass, Buffer);
3014 Status = Context->IoStatusBlock.Status;
3015 break;
3016 }
3017
3018 if (Context->Info.Length < 0)
3019 {
3020 Status = STATUS_BUFFER_OVERFLOW;
3021 Context->Info.Length = Stack->Parameters.QueryFile.Length;
3022 }
3023
3024 Irp->IoStatus.Information = Stack->Parameters.QueryFile.Length - Context->Info.Length;
3025 }
3026 _SEH2_FINALLY
3027 {
3028 if (Locked)
3029 {
3030 RxReleaseFcb(Context, Fcb);
3031 }
3032 }
3033 _SEH2_END;
3034
3035 DPRINT("Status: %x\n", Status);
3036 return Status;
3037
3038 #undef SET_SIZE_AND_QUERY
3039 }
3040
3041 NTSTATUS
3042 NTAPI
3043 RxCommonQueryQuotaInformation(
3044 PRX_CONTEXT Context)
3045 {
3046 UNIMPLEMENTED;
3047 return STATUS_NOT_IMPLEMENTED;
3048 }
3049
3050 NTSTATUS
3051 NTAPI
3052 RxCommonQuerySecurity(
3053 PRX_CONTEXT Context)
3054 {
3055 UNIMPLEMENTED;
3056 return STATUS_NOT_IMPLEMENTED;
3057 }
3058
3059 /*
3060 * @implemented
3061 */
3062 NTSTATUS
3063 NTAPI
3064 RxCommonQueryVolumeInformation(
3065 PRX_CONTEXT Context)
3066 {
3067 PIRP Irp;
3068 PFCB Fcb;
3069 PFOBX Fobx;
3070 NTSTATUS Status;
3071 PIO_STACK_LOCATION Stack;
3072
3073 PAGED_CODE();
3074
3075 Fcb = (PFCB)Context->pFcb;
3076 Fobx = (PFOBX)Context->pFobx;
3077
3078 DPRINT("RxCommonQueryVolumeInformation(%p) FCB: %p, FOBX: %p\n", Context, Fcb, Fobx);
3079
3080 Irp = Context->CurrentIrp;
3081 Stack = Context->CurrentIrpSp;
3082 DPRINT("Length: %lx, Class: %lx, Buffer %p\n", Stack->Parameters.QueryVolume.Length,
3083 Stack->Parameters.QueryVolume.FsInformationClass, Irp->AssociatedIrp.SystemBuffer);
3084
3085 Context->Info.FsInformationClass = Stack->Parameters.QueryVolume.FsInformationClass;
3086 Context->Info.Buffer = Irp->AssociatedIrp.SystemBuffer;
3087 Context->Info.Length = Stack->Parameters.QueryVolume.Length;
3088
3089 /* Forward to mini-rdr */
3090 MINIRDR_CALL(Status, Context, Fcb->MRxDispatch, MRxQueryVolumeInfo, (Context));
3091
3092 /* Post request if mini-rdr asked to */
3093 if (Context->PostRequest)
3094 {
3095 Status = RxFsdPostRequest(Context);
3096 }
3097 else
3098 {
3099 Irp->IoStatus.Information = Stack->Parameters.QueryVolume.Length - Context->Info.Length;
3100 }
3101
3102 DPRINT("Status: %x\n", Status);
3103 return Status;
3104 }
3105
3106 NTSTATUS
3107 NTAPI
3108 RxCommonRead(
3109 PRX_CONTEXT RxContext)
3110 {
3111 PFCB Fcb;
3112 PIRP Irp;
3113 PFOBX Fobx;
3114 NTSTATUS Status;
3115 PNET_ROOT NetRoot;
3116 PVOID SystemBuffer;
3117 PFILE_OBJECT FileObject;
3118 LARGE_INTEGER ByteOffset;
3119 PIO_STACK_LOCATION Stack;
3120 PLOWIO_CONTEXT LowIoContext;
3121 PRDBSS_DEVICE_OBJECT RxDeviceObject;
3122 ULONG ReadLength, CapturedRxContextSerialNumber = RxContext->SerialNumber;
3123 BOOLEAN CanWait, PagingIo, NoCache, Sync, PostRequest, IsPipe, ReadCachingEnabled, ReadCachingDisabled, InFsp, OwnerSet;
3124
3125 PAGED_CODE();
3126
3127 Fcb = (PFCB)RxContext->pFcb;
3128 Fobx = (PFOBX)RxContext->pFobx;
3129 DPRINT("RxCommonRead(%p) FOBX: %p, FCB: %p\n", RxContext, Fobx, Fcb);
3130
3131 /* Get some parameters */
3132 Irp = RxContext->CurrentIrp;
3133 Stack = RxContext->CurrentIrpSp;
3134 CanWait = BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_WAIT);
3135 PagingIo = BooleanFlagOn(Irp->Flags, IRP_PAGING_IO);
3136 NoCache = BooleanFlagOn(Irp->Flags, IRP_NOCACHE);
3137 Sync = !BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_ASYNC_OPERATION);
3138 InFsp = BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_IN_FSP);
3139 ReadLength = Stack->Parameters.Read.Length;
3140 ByteOffset.QuadPart = Stack->Parameters.Read.ByteOffset.QuadPart;
3141 DPRINT("Reading: %lx@%I64x %s %s %s %s\n", ReadLength, ByteOffset.QuadPart,
3142 (CanWait ? "CW" : "!CW"), (PagingIo ? "PI" : "!PI"), (NoCache ? "NC" : "!NC"), (Sync ? "S" : "!S"));
3143
3144 RxItsTheSameContext();
3145
3146 Irp->IoStatus.Information = 0;
3147
3148 /* Should the read be loud - so far, it's just ignored on ReactOS:
3149 * s/DPRINT/DPRINT1/g will make it loud
3150 */
3151 LowIoContext = &RxContext->LowIoContext;
3152 CheckForLoudOperations(RxContext);
3153 if (BooleanFlagOn(LowIoContext->Flags, LOWIO_CONTEXT_FLAG_LOUDOPS))
3154 {
3155 DPRINT("LoudRead %I64x/%lx on %lx vdl/size/alloc %I64x/%I64x/%I64x\n",
3156 ByteOffset, ReadLength,
3157 Fcb, Fcb->Header.ValidDataLength, Fcb->Header.FileSize, Fcb->Header.AllocationSize);
3158 }
3159
3160 RxDeviceObject = RxContext->RxDeviceObject;
3161 /* Update stats */
3162 if (!BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_IN_FSP) && Fcb->CachedNetRootType == NET_ROOT_DISK)
3163 {
3164 InterlockedIncrement((volatile long *)&RxDeviceObject->ReadOperations);
3165
3166 if (ByteOffset.QuadPart != Fobx->Specific.DiskFile.PredictedReadOffset)
3167 {
3168 InterlockedIncrement((volatile long *)&RxDeviceObject->RandomReadOperations);
3169 }
3170 Fobx->Specific.DiskFile.PredictedReadOffset = ByteOffset.QuadPart + ReadLength;
3171
3172 if (PagingIo)
3173 {
3174 ExInterlockedAddLargeStatistic(&RxDeviceObject->PagingReadBytesRequested, ReadLength);
3175 }
3176 else if (NoCache)
3177 {
3178 ExInterlockedAddLargeStatistic(&RxDeviceObject->NonPagingReadBytesRequested, ReadLength);
3179 }
3180 else
3181 {
3182 ExInterlockedAddLargeStatistic(&RxDeviceObject->CacheReadBytesRequested, ReadLength);
3183 }
3184 }
3185
3186 /* A pagefile cannot be a pipe */
3187 IsPipe = Fcb->NetRoot->Type == NET_ROOT_PIPE;
3188 if (IsPipe && PagingIo)
3189 {
3190 return STATUS_INVALID_DEVICE_REQUEST;
3191 }
3192
3193 /* Null-length read is no-op */
3194 if (ReadLength == 0)
3195 {
3196 return STATUS_SUCCESS;
3197 }
3198
3199 /* Validate FCB type */
3200 if (NodeType(Fcb) != RDBSS_NTC_STORAGE_TYPE_FILE && NodeType(Fcb) != RDBSS_NTC_VOLUME_FCB)
3201 {
3202 return STATUS_INVALID_DEVICE_REQUEST;
3203 }
3204
3205 /* Init the lowio context for possible forward */
3206 RxInitializeLowIoContext(LowIoContext, LOWIO_OP_READ);
3207
3208 PostRequest = FALSE;
3209 ReadCachingDisabled = FALSE;
3210 OwnerSet = FALSE;
3211 ReadCachingEnabled = BooleanFlagOn(Fcb->FcbState, FCB_STATE_READCACHING_ENABLED);
3212 FileObject = Stack->FileObject;
3213 NetRoot = (PNET_ROOT)Fcb->pNetRoot;
3214 _SEH2_TRY
3215 {
3216 LONGLONG FileSize;
3217
3218 /* If no caching, make sure current Cc data have been flushed */
3219 if (!PagingIo && NoCache && !ReadCachingEnabled && FileObject->SectionObjectPointer != NULL)
3220 {
3221 Status = RxAcquireExclusiveFcb(RxContext, Fcb);
3222 if (Status == STATUS_LOCK_NOT_GRANTED)
3223 {
3224 PostRequest = TRUE;
3225 _SEH2_LEAVE;
3226 }
3227 else if (Status != STATUS_SUCCESS)
3228 {
3229 _SEH2_LEAVE;
3230 }
3231
3232 ExAcquireResourceSharedLite(Fcb->Header.PagingIoResource, TRUE);
3233 CcFlushCache(FileObject->SectionObjectPointer, &ByteOffset, ReadLength, &Irp->IoStatus);
3234 RxReleasePagingIoResource(RxContext, Fcb);
3235
3236 if (!NT_SUCCESS(Irp->IoStatus.Status))
3237 {
3238 _SEH2_LEAVE;
3239 }
3240
3241 RxAcquirePagingIoResource(RxContext, Fcb);
3242 RxReleasePagingIoResource(RxContext, Fcb);
3243 }
3244
3245 /* Acquire the appropriate lock */
3246 if (PagingIo && !ReadCachingEnabled)
3247 {
3248 ASSERT(!IsPipe);
3249
3250 if (!ExAcquireResourceSharedLite(Fcb->Header.PagingIoResource, CanWait))
3251 {
3252 PostRequest = TRUE;
3253 _SEH2_LEAVE;
3254 }
3255
3256 if (!CanWait)
3257 {
3258 LowIoContext->Resource = Fcb->Header.PagingIoResource;
3259 }
3260 }
3261 else
3262 {
3263 if (!ReadCachingEnabled)
3264 {
3265 if (!CanWait && NoCache)
3266 {
3267 Status = RxAcquireSharedFcbWaitForEx(RxContext, Fcb);
3268 if (Status == STATUS_LOCK_NOT_GRANTED)
3269 {
3270 DPRINT1("RdAsyLNG %x\n", RxContext);
3271 PostRequest = TRUE;
3272 _SEH2_LEAVE;
3273 }
3274 if (Status != STATUS_SUCCESS)
3275 {
3276 DPRINT1("RdAsyOthr %x\n", RxContext);
3277 _SEH2_LEAVE;
3278 }
3279
3280 if (RxIsFcbAcquiredShared(Fcb) <= 0xF000)
3281 {
3282 LowIoContext->Resource = Fcb->Header.Resource;
3283 }
3284 else
3285 {
3286 PostRequest = TRUE;
3287 _SEH2_LEAVE;
3288 }
3289 }
3290 else
3291 {
3292 Status = RxAcquireSharedFcb(RxContext, Fcb);
3293 if (Status == STATUS_LOCK_NOT_GRANTED)
3294 {
3295 PostRequest = TRUE;
3296 _SEH2_LEAVE;
3297 }
3298 else if (Status != STATUS_SUCCESS)
3299 {
3300 _SEH2_LEAVE;
3301 }
3302 }
3303 }
3304 }
3305
3306 RxItsTheSameContext();
3307
3308 ReadCachingDisabled = (ReadCachingEnabled == FALSE);
3309 if (IsPipe)
3310 {
3311 UNIMPLEMENTED;
3312 }
3313
3314 RxGetFileSizeWithLock(Fcb, &FileSize);
3315
3316 /* Make sure FLOCK doesn't conflict */
3317 if (!PagingIo)
3318 {
3319 if (!FsRtlCheckLockForReadAccess(&Fcb->Specific.Fcb.FileLock, Irp))
3320 {
3321 Status = STATUS_FILE_LOCK_CONFLICT;
3322 _SEH2_LEAVE;
3323 }
3324 }
3325
3326 /* Validate byteoffset vs length */
3327 if (BooleanFlagOn(Fcb->FcbState, FCB_STATE_READCACHING_ENABLED))
3328 {
3329 if (ByteOffset.QuadPart >= FileSize)
3330 {
3331 Status = STATUS_END_OF_FILE;
3332 _SEH2_LEAVE;
3333 }
3334
3335 if (ReadLength > FileSize - ByteOffset.QuadPart)
3336 {
3337 ReadLength = FileSize - ByteOffset.QuadPart;
3338 }
3339 }
3340
3341 /* Read with Cc! */
3342 if (!PagingIo && !NoCache && ReadCachingEnabled &&
3343 !BooleanFlagOn(Fobx->pSrvOpen->Flags, SRVOPEN_FLAG_DONTUSE_READ_CACHING))
3344 {
3345 /* File was not cached yet, do it */
3346 if (FileObject->PrivateCacheMap == NULL)
3347 {
3348 if (BooleanFlagOn(FileObject->Flags, FO_CLEANUP_COMPLETE))
3349 {
3350 Status = STATUS_FILE_CLOSED;
3351 _SEH2_LEAVE;
3352 }
3353
3354 RxAdjustAllocationSizeforCC(Fcb);
3355
3356 CcInitializeCacheMap(FileObject, (PCC_FILE_SIZES)&Fcb->Header.AllocationSize,
3357 FALSE, &RxData.CacheManagerCallbacks, Fcb);
3358
3359 if (BooleanFlagOn(Fcb->MRxDispatch->MRxFlags, RDBSS_NO_DEFERRED_CACHE_READAHEAD))
3360 {
3361 CcSetAdditionalCacheAttributes(FileObject, FALSE, F