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