0ec1ed66fdc0655ca54d34483ef893760cf2eb64
[openafs.git] / src / WINNT / afsrdr / kernel / fs / AFSGeneric.cpp
1 /*
2  * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC.
3  * Copyright (c) 2009, 2010, 2011 Your File System, Inc.
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * - Redistributions of source code must retain the above copyright notice,
11  *   this list of conditions and the following disclaimer.
12  * - Redistributions in binary form must reproduce the above copyright
13  *   notice,
14  *   this list of conditions and the following disclaimer in the
15  *   documentation
16  *   and/or other materials provided with the distribution.
17  * - Neither the names of Kernel Drivers, LLC and Your File System, Inc.
18  *   nor the names of their contributors may be used to endorse or promote
19  *   products derived from this software without specific prior written
20  *   permission from Kernel Drivers, LLC and Your File System, Inc.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
25  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
26  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
27  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
29  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
30  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  */
34
35 //
36 // File: AFSGeneric.cpp
37 //
38
39 #include "AFSCommon.h"
40
41 //
42 // Function: AFSExceptionFilter
43 //
44 // Description:
45 //
46 //      This function is the exception handler
47 //
48 // Return:
49 //
50 //      A status is returned for the function
51 //
52
53 ULONG
54 AFSExceptionFilter( IN CHAR *FunctionString,
55                     IN ULONG Code,
56                     IN PEXCEPTION_POINTERS ExceptPtrs)
57 {
58
59     PEXCEPTION_RECORD ExceptRec;
60     PCONTEXT Context;
61
62     __try
63     {
64
65         ExceptRec = ExceptPtrs->ExceptionRecord;
66
67         Context = ExceptPtrs->ContextRecord;
68
69         AFSDbgLogMsg( 0,
70                       0,
71                       "AFSExceptionFilter (Framework) - EXR %p CXR %p Function %s Code %08lX Address %p Routine %p\n",
72                       ExceptRec,
73                       Context,
74                       FunctionString,
75                       ExceptRec->ExceptionCode,
76                       ExceptRec->ExceptionAddress,
77                       (void *)AFSExceptionFilter);
78
79         DbgPrint("**** Exception Caught in AFS Redirector ****\n");
80
81         DbgPrint("\n\nPerform the following WnDbg Cmds:\n");
82         DbgPrint("\n\t.exr %p ;  .cxr %p\n\n", ExceptRec, Context);
83
84         DbgPrint("**** Exception Complete from AFS Redirector ****\n");
85
86         if( BooleanFlagOn( AFSDebugFlags, AFS_DBG_BUGCHECK_EXCEPTION))
87         {
88
89             KeBugCheck( (ULONG)-2);
90         }
91         else
92         {
93
94             AFSBreakPoint();
95         }
96     }
97     __except( EXCEPTION_EXECUTE_HANDLER)
98     {
99
100         NOTHING;
101     }
102
103     return EXCEPTION_EXECUTE_HANDLER;
104 }
105
106 //
107 // Function: AFSAcquireExcl()
108 //
109 // Purpose: Called to acquire a resource exclusive with optional wait
110 //
111 // Parameters:
112 //                PERESOURCE Resource - Resource to acquire
113 //                BOOLEAN Wait - Whether to block
114 //
115 // Return:
116 //                BOOLEAN - Whether the mask was acquired
117 //
118
119 BOOLEAN
120 AFSAcquireExcl( IN PERESOURCE Resource,
121                 IN BOOLEAN wait)
122 {
123
124     BOOLEAN bStatus = FALSE;
125
126     //
127     // Normal kernel APCs must be disabled before calling
128     // ExAcquireResourceExclusiveLite. Otherwise a bugcheck occurs.
129     //
130
131     KeEnterCriticalRegion();
132
133     bStatus = ExAcquireResourceExclusiveLite( Resource,
134                                               wait);
135
136     if( !bStatus)
137     {
138
139         KeLeaveCriticalRegion();
140     }
141
142     return bStatus;
143 }
144
145 BOOLEAN
146 AFSAcquireSharedStarveExclusive( IN PERESOURCE Resource,
147                                  IN BOOLEAN Wait)
148 {
149
150     BOOLEAN bStatus = FALSE;
151
152     KeEnterCriticalRegion();
153
154     bStatus = ExAcquireSharedStarveExclusive( Resource,
155                                               Wait);
156
157     if( !bStatus)
158     {
159
160         KeLeaveCriticalRegion();
161     }
162
163     return bStatus;
164 }
165
166 //
167 // Function: AFSAcquireShared()
168 //
169 // Purpose: Called to acquire a resource shared with optional wait
170 //
171 // Parameters:
172 //                PERESOURCE Resource - Resource to acquire
173 //                BOOLEAN Wait - Whether to block
174 //
175 // Return:
176 //                BOOLEAN - Whether the mask was acquired
177 //
178
179 BOOLEAN
180 AFSAcquireShared( IN PERESOURCE Resource,
181                   IN BOOLEAN wait)
182 {
183
184     BOOLEAN bStatus = FALSE;
185
186     KeEnterCriticalRegion();
187
188     bStatus = ExAcquireResourceSharedLite( Resource,
189                                            wait);
190
191     if( !bStatus)
192     {
193
194         KeLeaveCriticalRegion();
195     }
196
197     return bStatus;
198 }
199
200 //
201 // Function: AFSReleaseResource()
202 //
203 // Purpose: Called to release a resource
204 //
205 // Parameters:
206 //                PERESOURCE Resource - Resource to release
207 //
208 // Return:
209 //                None
210 //
211
212 void
213 AFSReleaseResource( IN PERESOURCE Resource)
214 {
215
216     if( Resource != &AFSDbgLogLock)
217     {
218
219         AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
220                       AFS_TRACE_LEVEL_VERBOSE,
221                       "AFSReleaseResource Releasing lock %08lX Thread %08lX\n",
222                       Resource,
223                       PsGetCurrentThread());
224     }
225
226     ExReleaseResourceLite( Resource);
227
228     KeLeaveCriticalRegion();
229
230     return;
231 }
232
233 void
234 AFSConvertToShared( IN PERESOURCE Resource)
235 {
236
237     AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
238                   AFS_TRACE_LEVEL_VERBOSE,
239                   "AFSConvertToShared Converting lock %08lX Thread %08lX\n",
240                   Resource,
241                   PsGetCurrentThread());
242
243     ExConvertExclusiveToSharedLite( Resource);
244
245     return;
246 }
247
248 //
249 // Function: AFSCompleteRequest
250 //
251 // Description:
252 //
253 //      This function completes irps
254 //
255 // Return:
256 //
257 //      A status is returned for the function
258 //
259
260 void
261 AFSCompleteRequest( IN PIRP Irp,
262                     IN ULONG Status)
263 {
264
265     Irp->IoStatus.Status = Status;
266
267     IoCompleteRequest( Irp,
268                        IO_NO_INCREMENT);
269
270     return;
271 }
272
273 NTSTATUS
274 AFSReadRegistry( IN PUNICODE_STRING RegistryPath)
275 {
276
277     NTSTATUS ntStatus        = STATUS_SUCCESS;
278     ULONG Default            = 0;
279     UNICODE_STRING paramPath;
280     ULONG Value                = 0;
281     RTL_QUERY_REGISTRY_TABLE paramTable[2];
282     UNICODE_STRING defaultUnicodeName;
283     WCHAR SubKeyString[]    = L"\\Parameters";
284
285     //
286     // Setup the paramPath buffer.
287     //
288
289     paramPath.MaximumLength = RegistryPath->Length + sizeof( SubKeyString);
290     paramPath.Buffer = (PWSTR)AFSExAllocatePoolWithTag( PagedPool,
291                                                         paramPath.MaximumLength,
292                                                         AFS_GENERIC_MEMORY_15_TAG);
293
294     RtlInitUnicodeString( &defaultUnicodeName,
295                           L"NO NAME");
296
297     //
298     // If it exists, setup the path.
299     //
300
301     if( paramPath.Buffer != NULL)
302     {
303
304         //
305         // Move in the paths
306         //
307
308         RtlCopyMemory( &paramPath.Buffer[ 0],
309                        &RegistryPath->Buffer[ 0],
310                        RegistryPath->Length);
311
312         RtlCopyMemory( &paramPath.Buffer[ RegistryPath->Length / 2],
313                        SubKeyString,
314                        sizeof( SubKeyString));
315
316         paramPath.Length = paramPath.MaximumLength;
317
318         RtlZeroMemory( paramTable,
319                        sizeof( paramTable));
320
321         Value = 0;
322
323         //
324         // Setup the table to query the registry for the needed value
325         //
326
327         paramTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
328         paramTable[0].Name = AFS_REG_DEBUG_FLAGS;
329         paramTable[0].EntryContext = &Value;
330
331         paramTable[0].DefaultType = REG_DWORD;
332         paramTable[0].DefaultData = &Default;
333         paramTable[0].DefaultLength = sizeof (ULONG) ;
334
335         //
336         // Query the registry
337         //
338
339         ntStatus = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,
340                                            paramPath.Buffer,
341                                            paramTable,
342                                            NULL,
343                                            NULL);
344
345         if( NT_SUCCESS( ntStatus))
346         {
347
348             AFSDebugFlags = Value;
349         }
350
351         RtlZeroMemory( paramTable,
352                        sizeof( paramTable));
353
354         Value = 0;
355
356         //
357         // Setup the table to query the registry for the needed value
358         //
359
360         paramTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
361         paramTable[0].Name = AFS_REG_TRACE_SUBSYSTEM;
362         paramTable[0].EntryContext = &Value;
363
364         paramTable[0].DefaultType = REG_DWORD;
365         paramTable[0].DefaultData = &Default;
366         paramTable[0].DefaultLength = sizeof (ULONG) ;
367
368         //
369         // Query the registry
370         //
371
372         ntStatus = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,
373                                            paramPath.Buffer,
374                                            paramTable,
375                                            NULL,
376                                            NULL);
377
378         if( NT_SUCCESS( ntStatus))
379         {
380
381             AFSTraceComponent = Value;
382         }
383
384         RtlZeroMemory( paramTable,
385                        sizeof( paramTable));
386
387         Value = 0;
388
389         //
390         // Setup the table to query the registry for the needed value
391         //
392
393         paramTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
394         paramTable[0].Name = AFS_REG_TRACE_BUFFER_LENGTH;
395         paramTable[0].EntryContext = &Value;
396
397         paramTable[0].DefaultType = REG_DWORD;
398         paramTable[0].DefaultData = &Default;
399         paramTable[0].DefaultLength = sizeof (ULONG);
400
401         //
402         // Query the registry
403         //
404
405         ntStatus = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,
406                                            paramPath.Buffer,
407                                            paramTable,
408                                            NULL,
409                                            NULL);
410
411         if( NT_SUCCESS( ntStatus) &&
412             Value > 0)
413         {
414
415             AFSDbgBufferLength = Value;
416
417             //
418             // Let's limit things a bit ...
419             //
420
421             if( AFSDbgBufferLength > 10240)
422             {
423
424                 AFSDbgBufferLength = 1024;
425             }
426         }
427         else
428         {
429
430             AFSDbgBufferLength = 0;
431         }
432
433         //
434         // Make it bytes
435         //
436
437         AFSDbgBufferLength *= 1024;
438
439         //
440         // Now get ready to set up for MaxServerDirty
441         //
442
443         paramTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
444         paramTable[0].Name = AFS_REG_MAX_DIRTY;
445         paramTable[0].EntryContext = &Value;
446
447         paramTable[0].DefaultType = REG_DWORD;
448         paramTable[0].DefaultData = &Default;
449         paramTable[0].DefaultLength = sizeof (ULONG) ;
450
451         //
452         // Query the registry
453         //
454
455         ntStatus = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,
456                                            paramPath.Buffer,
457                                            paramTable,
458                                            NULL,
459                                            NULL);
460
461         if( NT_SUCCESS( ntStatus))
462         {
463
464             AFSMaxDirtyFile = Value;
465         }
466
467         RtlZeroMemory( paramTable,
468                        sizeof( paramTable));
469
470         Value = 0;
471
472         //
473         // Setup the table to query the registry for the needed value
474         //
475
476         paramTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
477         paramTable[0].Name = AFS_REG_TRACE_LEVEL;
478         paramTable[0].EntryContext = &Value;
479
480         paramTable[0].DefaultType = REG_DWORD;
481         paramTable[0].DefaultData = &Default;
482         paramTable[0].DefaultLength = sizeof (ULONG) ;
483
484         //
485         // Query the registry
486         //
487
488         ntStatus = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,
489                                            paramPath.Buffer,
490                                            paramTable,
491                                            NULL,
492                                            NULL);
493
494         if( NT_SUCCESS( ntStatus))
495         {
496
497             AFSTraceLevel = Value;
498         }
499
500         //
501         // MaxIO
502         //
503
504         paramTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
505         paramTable[0].Name = AFS_REG_MAX_IO;
506         paramTable[0].EntryContext = &Value;
507
508         paramTable[0].DefaultType = REG_DWORD;
509         paramTable[0].DefaultData = &Default;
510         paramTable[0].DefaultLength = sizeof (ULONG) ;
511
512         //
513         // Query the registry
514         //
515
516         ntStatus = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,
517                                            paramPath.Buffer,
518                                            paramTable,
519                                            NULL,
520                                            NULL);
521
522         if( NT_SUCCESS( ntStatus))
523         {
524
525             AFSMaxDirectIo = Value;
526         }
527
528         //
529         // Now set up for ShutdownStatus query
530         //
531
532         paramTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
533         paramTable[0].Name = AFS_REG_SHUTDOWN_STATUS;
534         paramTable[0].EntryContext = &Value;
535
536         paramTable[0].DefaultType = REG_DWORD;
537         paramTable[0].DefaultData = &Default;
538         paramTable[0].DefaultLength = sizeof (ULONG) ;
539
540         //
541         // Query the registry
542         //
543
544         ntStatus = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,
545                                            paramPath.Buffer,
546                                            paramTable,
547                                            NULL,
548                                            NULL);
549
550         if( !NT_SUCCESS( ntStatus) ||
551             Value != (ULONG)-1)
552         {
553
554             SetFlag( AFSDebugFlags, AFS_DBG_CLEAN_SHUTDOWN);
555         }
556
557         //
558         // Now set up for RequireCleanShutdown query
559         //
560
561         paramTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
562         paramTable[0].Name = AFS_REG_REQUIRE_CLEAN_SHUTDOWN;
563         paramTable[0].EntryContext = &Value;
564
565         paramTable[0].DefaultType = REG_DWORD;
566         paramTable[0].DefaultData = &Default;
567         paramTable[0].DefaultLength = sizeof (ULONG) ;
568
569         //
570         // Query the registry
571         //
572
573         ntStatus = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,
574                                            paramPath.Buffer,
575                                            paramTable,
576                                            NULL,
577                                            NULL);
578
579         if( !NT_SUCCESS( ntStatus) ||
580             Value != 0L)
581         {
582
583             SetFlag( AFSDebugFlags, AFS_DBG_REQUIRE_CLEAN_SHUTDOWN);
584         }
585
586         //
587         // Free up the buffer
588         //
589
590         ExFreePool( paramPath.Buffer);
591
592         ntStatus = STATUS_SUCCESS;
593     }
594     else
595     {
596         ntStatus = STATUS_INSUFFICIENT_RESOURCES;
597     }
598
599     return ntStatus;
600 }
601
602 NTSTATUS
603 AFSUpdateRegistryParameter( IN PUNICODE_STRING ValueName,
604                             IN ULONG ValueType,
605                             IN void *ValueData,
606                             IN ULONG ValueDataLength)
607 {
608
609     NTSTATUS ntStatus        = STATUS_SUCCESS;
610     UNICODE_STRING paramPath, uniParamKey;
611     HANDLE hParameters = 0;
612     ULONG ulDisposition = 0;
613     OBJECT_ATTRIBUTES stObjectAttributes;
614
615     __Enter
616     {
617
618         RtlInitUnicodeString( &uniParamKey,
619                               L"\\Parameters");
620
621         //
622         // Setup the paramPath buffer.
623         //
624
625         paramPath.MaximumLength = AFSRegistryPath.Length + uniParamKey.Length;
626         paramPath.Buffer = (PWSTR)AFSExAllocatePoolWithTag( PagedPool,
627                                                             paramPath.MaximumLength,
628                                                             AFS_GENERIC_MEMORY_16_TAG);
629
630         if( paramPath.Buffer == NULL)
631         {
632
633             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
634         }
635
636         //
637         // Move in the paths
638         //
639
640         RtlCopyMemory( paramPath.Buffer,
641                        AFSRegistryPath.Buffer,
642                        AFSRegistryPath.Length);
643
644         paramPath.Length = AFSRegistryPath.Length;
645
646         RtlCopyMemory( &paramPath.Buffer[ paramPath.Length / 2],
647                        uniParamKey.Buffer,
648                        uniParamKey.Length);
649
650         paramPath.Length += uniParamKey.Length;
651
652         InitializeObjectAttributes( &stObjectAttributes,
653                                     &paramPath,
654                                     OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
655                                     NULL,
656                                     NULL);
657
658         ntStatus = ZwOpenKey( &hParameters,
659                               KEY_ALL_ACCESS,
660                               &stObjectAttributes);
661
662         if( !NT_SUCCESS( ntStatus))
663         {
664
665             try_return( ntStatus);
666         }
667
668         //
669         // Set the value
670         //
671
672         ntStatus = ZwSetValueKey( hParameters,
673                                   ValueName,
674                                   0,
675                                   ValueType,
676                                   ValueData,
677                                   ValueDataLength);
678
679         ZwClose( hParameters);
680
681 try_exit:
682
683         if( paramPath.Buffer != NULL)
684         {
685
686             //
687             // Free up the buffer
688             //
689
690             ExFreePool( paramPath.Buffer);
691         }
692     }
693
694     return ntStatus;
695 }
696
697 NTSTATUS
698 AFSInitializeControlDevice()
699 {
700
701     NTSTATUS ntStatus = STATUS_SUCCESS;
702     AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
703     AFSProcessCB *pProcessCB = NULL;
704
705     __Enter
706     {
707
708         //
709         // Initialize the comm pool resources
710         //
711
712         ExInitializeResourceLite( &pDeviceExt->Specific.Control.CommServiceCB.IrpPoolLock);
713
714         ExInitializeResourceLite( &pDeviceExt->Specific.Control.CommServiceCB.ResultPoolLock);
715
716         ExInitializeResourceLite( &pDeviceExt->Specific.Control.ExtentReleaseResource);
717
718         ExInitializeResourceLite( &pDeviceExt->Specific.Control.SysName32ListLock);
719
720         ExInitializeResourceLite( &pDeviceExt->Specific.Control.SysName64ListLock);
721
722         //
723         // And the events
724         //
725
726         KeInitializeEvent( &pDeviceExt->Specific.Control.CommServiceCB.IrpPoolHasEntries,
727                            SynchronizationEvent,
728                            FALSE);
729
730         KeInitializeEvent( &pDeviceExt->Specific.Control.CommServiceCB.IrpPoolHasReleaseEntries,
731                            SynchronizationEvent,
732                            FALSE);
733
734         KeInitializeEvent( &pDeviceExt->Specific.Control.ExtentReleaseEvent,
735                            NotificationEvent,
736                            FALSE);
737
738         pDeviceExt->Specific.Control.ExtentReleaseSequence = 0;
739
740         KeInitializeEvent( &pDeviceExt->Specific.Control.VolumeWorkerCloseEvent,
741                            NotificationEvent,
742                            TRUE);
743
744         //
745         // Library support information
746         //
747
748         KeInitializeEvent( &pDeviceExt->Specific.Control.LoadLibraryEvent,
749                            SynchronizationEvent,
750                            TRUE);
751
752         //
753         // Initialize the library queued as cancelled
754         //
755
756         pDeviceExt->Specific.Control.LibraryState = AFS_LIBRARY_QUEUE_CANCELLED;
757
758         ExInitializeResourceLite( &pDeviceExt->Specific.Control.LibraryStateLock);
759
760         pDeviceExt->Specific.Control.InflightLibraryRequests = 0;
761
762         KeInitializeEvent( &pDeviceExt->Specific.Control.InflightLibraryEvent,
763                            NotificationEvent,
764                            FALSE);
765
766         pDeviceExt->Specific.Control.ExtentCount = 0;
767         pDeviceExt->Specific.Control.ExtentsHeldLength = 0;
768
769         KeInitializeEvent( &pDeviceExt->Specific.Control.ExtentsHeldEvent,
770                            NotificationEvent,
771                            TRUE);
772
773         pDeviceExt->Specific.Control.OutstandingServiceRequestCount = 0;
774
775         KeInitializeEvent( &pDeviceExt->Specific.Control.OutstandingServiceRequestEvent,
776                            NotificationEvent,
777                            TRUE);
778
779         pDeviceExt->Specific.Control.WaitingForMemoryCount = 0;
780
781         KeInitializeEvent( &pDeviceExt->Specific.Control.MemoryAvailableEvent,
782                            NotificationEvent,
783                            TRUE);
784
785         ExInitializeResourceLite( &pDeviceExt->Specific.Control.LibraryQueueLock);
786
787         pDeviceExt->Specific.Control.LibraryQueueHead = NULL;
788
789         pDeviceExt->Specific.Control.LibraryQueueTail = NULL;
790
791         //
792         // Set the initial state of the irp pool
793         //
794
795         pDeviceExt->Specific.Control.CommServiceCB.IrpPoolControlFlag = POOL_INACTIVE;
796
797         //
798         // Initialize our process and sid tree information
799         //
800
801         ExInitializeResourceLite( &pDeviceExt->Specific.Control.ProcessTreeLock);
802
803         pDeviceExt->Specific.Control.ProcessTree.TreeLock = &pDeviceExt->Specific.Control.ProcessTreeLock;
804
805         pDeviceExt->Specific.Control.ProcessTree.TreeHead = NULL;
806
807         ExInitializeResourceLite( &pDeviceExt->Specific.Control.AuthGroupTreeLock);
808
809         pDeviceExt->Specific.Control.AuthGroupTree.TreeLock = &pDeviceExt->Specific.Control.AuthGroupTreeLock;
810
811         pDeviceExt->Specific.Control.AuthGroupTree.TreeHead = NULL;
812     }
813
814     return ntStatus;
815 }
816
817 NTSTATUS
818 AFSRemoveControlDevice()
819 {
820
821     NTSTATUS ntStatus = STATUS_SUCCESS;
822     AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
823     AFSProcessCB *pProcessCB = NULL;
824
825     __Enter
826     {
827
828         //
829         // Initialize the comm pool resources
830         //
831
832         ExDeleteResourceLite( &pDeviceExt->Specific.Control.CommServiceCB.IrpPoolLock);
833
834         ExDeleteResourceLite( &pDeviceExt->Specific.Control.CommServiceCB.ResultPoolLock);
835
836         ExDeleteResourceLite( &pDeviceExt->Specific.Control.ExtentReleaseResource);
837
838         ExDeleteResourceLite( &pDeviceExt->Specific.Control.SysName32ListLock);
839
840         ExDeleteResourceLite( &pDeviceExt->Specific.Control.SysName64ListLock);
841
842         ExDeleteResourceLite( &pDeviceExt->Specific.Control.ProcessTreeLock);
843
844         if( pDeviceExt->Specific.Control.ProcessTree.TreeHead != NULL)
845         {
846             ExFreePool( pDeviceExt->Specific.Control.ProcessTree.TreeHead);
847         }
848
849         ExDeleteResourceLite( &pDeviceExt->Specific.Control.AuthGroupTreeLock);
850
851         ExDeleteResourceLite( &pDeviceExt->Specific.Control.LibraryStateLock);
852
853         ExDeleteResourceLite( &pDeviceExt->Specific.Control.LibraryQueueLock);
854     }
855
856     return ntStatus;
857 }
858
859 void
860 AFSInitServerStrings()
861 {
862
863     UNICODE_STRING uniFullName;
864     WCHAR wchBuffer[ 50];
865
866     //
867     // Add the server name into the list of resources
868     //
869
870     uniFullName.Length = (2 * sizeof( WCHAR)) + AFSServerName.Length;
871     uniFullName.MaximumLength = uniFullName.Length + sizeof( WCHAR);
872
873     uniFullName.Buffer = wchBuffer;
874
875     wchBuffer[ 0] = L'\\';
876     wchBuffer[ 1] = L'\\';
877
878     RtlCopyMemory( &wchBuffer[ 2],
879                    AFSServerName.Buffer,
880                    AFSServerName.Length);
881
882     AFSAddConnectionEx( &uniFullName,
883                         RESOURCEDISPLAYTYPE_SERVER,
884                         0);
885
886     //
887     // Add in the global share name
888     //
889
890     wchBuffer[ uniFullName.Length/sizeof( WCHAR)] = L'\\';
891
892     uniFullName.Length += sizeof( WCHAR);
893
894     RtlCopyMemory( &wchBuffer[ uniFullName.Length/sizeof( WCHAR)],
895                    AFSGlobalRootName.Buffer,
896                    AFSGlobalRootName.Length);
897
898     uniFullName.Length += AFSGlobalRootName.Length;
899
900     AFSAddConnectionEx( &uniFullName,
901                         RESOURCEDISPLAYTYPE_SHARE,
902                         AFS_CONNECTION_FLAG_GLOBAL_SHARE);
903
904     return;
905 }
906
907 NTSTATUS
908 AFSReadServerName()
909 {
910
911     NTSTATUS ntStatus        = STATUS_SUCCESS;
912     ULONG Default            = 0;
913     UNICODE_STRING paramPath;
914     RTL_QUERY_REGISTRY_TABLE paramTable[2];
915
916     __Enter
917     {
918
919         //
920         // Setup the paramPath buffer.
921         //
922
923         paramPath.MaximumLength = PAGE_SIZE;
924         paramPath.Buffer = (PWSTR)AFSExAllocatePoolWithTag( PagedPool,
925                                                             paramPath.MaximumLength,
926                                                             AFS_GENERIC_MEMORY_17_TAG);
927
928         //
929         // If it exists, setup the path.
930         //
931
932         if( paramPath.Buffer == NULL)
933         {
934
935             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
936         }
937
938         //
939         // Move in the paths
940         //
941
942         RtlZeroMemory( paramPath.Buffer,
943                        paramPath.MaximumLength);
944
945         RtlCopyMemory( &paramPath.Buffer[ 0],
946                        L"\\TransarcAFSDaemon\\Parameters",
947                        58);
948
949         paramPath.Length = 58;
950
951         RtlZeroMemory( paramTable,
952                        sizeof( paramTable));
953
954         //
955         // Setup the table to query the registry for the needed value
956         //
957
958         AFSServerName.Length = 0;
959         AFSServerName.MaximumLength = 0;
960         AFSServerName.Buffer = NULL;
961
962         paramTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
963         paramTable[0].Name = AFS_NETBIOS_NAME;
964         paramTable[0].EntryContext = &AFSServerName;
965
966         paramTable[0].DefaultType = REG_NONE;
967         paramTable[0].DefaultData = NULL;
968         paramTable[0].DefaultLength = 0;
969
970         //
971         // Query the registry
972         //
973
974         ntStatus = RtlQueryRegistryValues( RTL_REGISTRY_SERVICES,
975                                            paramPath.Buffer,
976                                            paramTable,
977                                            NULL,
978                                            NULL);
979
980         //
981         // Free up the buffer
982         //
983
984         ExFreePool( paramPath.Buffer);
985
986 try_exit:
987
988         if( !NT_SUCCESS( ntStatus))
989         {
990
991             RtlInitUnicodeString( &AFSServerName,
992                                   L"AFS");
993         }
994     }
995
996     return ntStatus;
997 }
998
999 NTSTATUS
1000 AFSSetSysNameInformation( IN AFSSysNameNotificationCB *SysNameInfo,
1001                           IN ULONG SysNameInfoBufferLength)
1002 {
1003
1004     NTSTATUS         ntStatus = STATUS_SUCCESS;
1005     AFSDeviceExt    *pControlDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
1006     AFSSysNameCB    *pSysName = NULL;
1007     ERESOURCE       *pSysNameLock = NULL;
1008     AFSSysNameCB   **pSysNameListHead = NULL, **pSysNameListTail = NULL;
1009     ULONG            ulIndex = 0;
1010     __Enter
1011     {
1012
1013         //
1014         // Depending on the architecture of the information, set up the lsit
1015         //
1016
1017         if( SysNameInfo->Architecture == AFS_SYSNAME_ARCH_32BIT)
1018         {
1019
1020             pSysNameLock = &pControlDevExt->Specific.Control.SysName32ListLock;
1021
1022             pSysNameListHead = &pControlDevExt->Specific.Control.SysName32ListHead;
1023
1024             pSysNameListTail = &pControlDevExt->Specific.Control.SysName32ListTail;
1025         }
1026         else
1027         {
1028
1029 #if defined(_WIN64)
1030
1031             pSysNameLock = &pControlDevExt->Specific.Control.SysName64ListLock;
1032
1033             pSysNameListHead = &pControlDevExt->Specific.Control.SysName64ListHead;
1034
1035             pSysNameListTail = &pControlDevExt->Specific.Control.SysName64ListTail;
1036
1037 #else
1038
1039             try_return( ntStatus = STATUS_INVALID_PARAMETER);
1040 #endif
1041         }
1042
1043         //
1044         // Process the request
1045         //
1046
1047         AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1048                       AFS_TRACE_LEVEL_VERBOSE,
1049                       "AFSSetSysNameInformation Acquiring SysName lock %08lX EXCL %08lX\n",
1050                       pSysNameLock,
1051                       PsGetCurrentThread());
1052
1053         AFSAcquireExcl( pSysNameLock,
1054                         TRUE);
1055
1056         //
1057         // If we already have a list, then tear it down
1058         //
1059
1060         if( *pSysNameListHead != NULL)
1061         {
1062
1063             AFSResetSysNameList( *pSysNameListHead);
1064
1065             *pSysNameListHead = NULL;
1066         }
1067
1068         //
1069         // Loop through the entries adding in a node for each
1070         //
1071
1072         while( ulIndex < SysNameInfo->NumberOfNames)
1073         {
1074
1075             pSysName = (AFSSysNameCB *)AFSExAllocatePoolWithTag( PagedPool,
1076                                                                  sizeof( AFSSysNameCB) +
1077                                                                  SysNameInfo->SysNames[ ulIndex].Length +
1078                                                                  sizeof( WCHAR),
1079                                                                  AFS_SYS_NAME_NODE_TAG);
1080
1081             if( pSysName == NULL)
1082             {
1083
1084                 //
1085                 // Reset the current list
1086                 //
1087
1088                 AFSResetSysNameList( *pSysNameListHead);
1089
1090                 *pSysNameListHead = NULL;
1091
1092                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1093             }
1094
1095             RtlZeroMemory( pSysName,
1096                            sizeof( AFSSysNameCB) +
1097                                    SysNameInfo->SysNames[ ulIndex].Length +
1098                                    sizeof( WCHAR));
1099
1100             pSysName->SysName.Length = (USHORT)SysNameInfo->SysNames[ ulIndex].Length;
1101
1102             pSysName->SysName.MaximumLength = pSysName->SysName.Length + sizeof( WCHAR);
1103
1104             pSysName->SysName.Buffer = (WCHAR *)((char *)pSysName + sizeof( AFSSysNameCB));
1105
1106             RtlCopyMemory( pSysName->SysName.Buffer,
1107                            SysNameInfo->SysNames[ ulIndex].String,
1108                            pSysName->SysName.Length);
1109
1110             if( *pSysNameListHead == NULL)
1111             {
1112
1113                 *pSysNameListHead = pSysName;
1114             }
1115             else
1116             {
1117
1118                 (*pSysNameListTail)->fLink = pSysName;
1119             }
1120
1121             *pSysNameListTail = pSysName;
1122
1123             ulIndex++;
1124         }
1125
1126 try_exit:
1127
1128         AFSReleaseResource( pSysNameLock);
1129     }
1130
1131     return ntStatus;
1132 }
1133
1134 void
1135 AFSResetSysNameList( IN AFSSysNameCB *SysNameList)
1136 {
1137
1138     AFSSysNameCB *pNextEntry = NULL, *pCurrentEntry = SysNameList;
1139
1140     while( pCurrentEntry != NULL)
1141     {
1142
1143         pNextEntry = pCurrentEntry->fLink;
1144
1145         ExFreePool( pCurrentEntry);
1146
1147         pCurrentEntry = pNextEntry;
1148     }
1149
1150     return;
1151 }
1152
1153 NTSTATUS
1154 AFSDefaultDispatch( IN PDEVICE_OBJECT DeviceObject,
1155                     IN PIRP Irp)
1156 {
1157
1158     NTSTATUS            ntStatus = STATUS_INVALID_DEVICE_REQUEST;
1159     PIO_STACK_LOCATION  pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1160
1161     AFSCompleteRequest( Irp,
1162                         ntStatus);
1163
1164     return ntStatus;
1165 }
1166
1167 NTSTATUS
1168 AFSSendDeviceIoControl( IN DEVICE_OBJECT *TargetDeviceObject,
1169                         IN ULONG IOControl,
1170                         IN void *InputBuffer,
1171                         IN ULONG InputBufferLength,
1172                         IN OUT void *OutputBuffer,
1173                         IN ULONG OutputBufferLength,
1174                         OUT ULONG *ResultLength)
1175 {
1176
1177     NTSTATUS            ntStatus = STATUS_SUCCESS;
1178     PIRP                pIrp = NULL;
1179     KEVENT              kEvent;
1180     PIO_STACK_LOCATION  pIoStackLocation = NULL;
1181
1182     __Enter
1183     {
1184
1185         //
1186         // Initialize the event
1187         //
1188
1189         KeInitializeEvent( &kEvent,
1190                            SynchronizationEvent,
1191                            FALSE);
1192
1193         //
1194         // Allocate an irp for this request.  This could also come from a
1195         // private pool, for instance.
1196         //
1197
1198         pIrp = IoAllocateIrp( TargetDeviceObject->StackSize,
1199                               FALSE);
1200
1201         if( pIrp == NULL)
1202         {
1203
1204             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1205         }
1206
1207         //
1208         // Build the IRP's main body
1209         //
1210
1211         pIrp->RequestorMode = KernelMode;
1212
1213         //
1214         // Set up the I/O stack location.
1215         //
1216
1217         pIoStackLocation = IoGetNextIrpStackLocation( pIrp);
1218         pIoStackLocation->MajorFunction = IRP_MJ_DEVICE_CONTROL;
1219         pIoStackLocation->DeviceObject = TargetDeviceObject;
1220
1221         pIoStackLocation->Parameters.DeviceIoControl.IoControlCode = IOControl;
1222
1223         pIrp->AssociatedIrp.SystemBuffer = (void *)InputBuffer;
1224         pIoStackLocation->Parameters.DeviceIoControl.InputBufferLength = InputBufferLength;
1225
1226         //
1227         // Set the completion routine.
1228         //
1229
1230         IoSetCompletionRoutine( pIrp,
1231                                 AFSIrpComplete,
1232                                 &kEvent,
1233                                 TRUE,
1234                                 TRUE,
1235                                 TRUE);
1236
1237         //
1238         // Send it to the FSD
1239         //
1240
1241         ntStatus = IoCallDriver( TargetDeviceObject,
1242                                  pIrp);
1243
1244         if( NT_SUCCESS( ntStatus))
1245         {
1246
1247             //
1248             // Wait for the I/O
1249             //
1250
1251             ntStatus = KeWaitForSingleObject( &kEvent,
1252                                               Executive,
1253                                               KernelMode,
1254                                               FALSE,
1255                                               0);
1256
1257             if( NT_SUCCESS( ntStatus))
1258             {
1259
1260                 ntStatus = pIrp->IoStatus.Status;
1261
1262                 if( ResultLength != NULL)
1263                 {
1264                     *ResultLength = (ULONG)pIrp->IoStatus.Information;
1265                 }
1266             }
1267         }
1268
1269 try_exit:
1270
1271         if( pIrp != NULL)
1272         {
1273
1274             if( pIrp->MdlAddress != NULL)
1275             {
1276
1277                 if( FlagOn( pIrp->MdlAddress->MdlFlags, MDL_PAGES_LOCKED))
1278                 {
1279
1280                     MmUnlockPages( pIrp->MdlAddress);
1281                 }
1282
1283                 IoFreeMdl( pIrp->MdlAddress);
1284             }
1285
1286             pIrp->MdlAddress = NULL;
1287
1288             //
1289             // Free the Irp
1290             //
1291
1292             IoFreeIrp( pIrp);
1293         }
1294     }
1295
1296     return ntStatus;
1297 }
1298
1299 NTSTATUS
1300 AFSIrpComplete( IN PDEVICE_OBJECT DeviceObject,
1301                 IN PIRP           Irp,
1302                 IN PVOID          Context)
1303 {
1304
1305     KEVENT *pEvent = (KEVENT *)Context;
1306
1307     KeSetEvent( pEvent,
1308                 0,
1309                 FALSE);
1310
1311     return STATUS_MORE_PROCESSING_REQUIRED;
1312 }
1313
1314 void *
1315 AFSExAllocatePoolWithTag( IN POOL_TYPE  PoolType,
1316                           IN SIZE_T  NumberOfBytes,
1317                           IN ULONG  Tag)
1318 {
1319
1320     AFSDeviceExt *pControlDevExt = NULL;
1321     void *pBuffer = NULL;
1322     BOOLEAN bTimeout = FALSE;
1323     LARGE_INTEGER liTimeout;
1324     NTSTATUS ntStatus;
1325
1326     //
1327     // Attempt to allocation memory from the system.  If the allocation fails
1328     // wait up to 30 seconds for the AFS redirector to free some memory.  As
1329     // long as the wait does not timeout, continue to retry the allocation.
1330     // If the wait does timeout, attempt to allocate one more time in case
1331     // memory was freed by another driver.  Otherwise, fail the request.
1332     //
1333
1334     if ( AFSDeviceObject)
1335     {
1336
1337         pControlDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
1338     }
1339
1340     while( pBuffer == NULL)
1341     {
1342
1343         pBuffer = ExAllocatePoolWithTag( PoolType,
1344                                          NumberOfBytes,
1345                                          Tag);
1346
1347         if( pBuffer == NULL)
1348         {
1349
1350             if ( bTimeout || pControlDevExt == NULL)
1351             {
1352
1353                 AFSDbgLogMsg( 0,
1354                               0,
1355                               "AFSExAllocatePoolWithTag failure Type %08lX Size %08lX Tag %08lX %08lX\n",
1356                               PoolType,
1357                               NumberOfBytes,
1358                               Tag,
1359                               PsGetCurrentThread());
1360
1361                 switch ( Tag ) {
1362
1363                 case AFS_GENERIC_MEMORY_21_TAG:
1364                 case AFS_GENERIC_MEMORY_22_TAG:
1365                     // AFSDumpTraceFiles -- do nothing;
1366                     break;
1367
1368                 default:
1369                     AFSBreakPoint();
1370                 }
1371
1372                 break;
1373             }
1374
1375
1376             //
1377             // Wait up to 30 seconds for a memory deallocation
1378             //
1379
1380             liTimeout.QuadPart = -(30 *AFS_ONE_SECOND);
1381
1382             if( InterlockedIncrement( &pControlDevExt->Specific.Control.WaitingForMemoryCount) == 1)
1383             {
1384                 KeClearEvent( &pControlDevExt->Specific.Control.MemoryAvailableEvent);
1385             }
1386
1387             ntStatus = KeWaitForSingleObject( &pControlDevExt->Specific.Control.MemoryAvailableEvent,
1388                                               Executive,
1389                                               KernelMode,
1390                                               FALSE,
1391                                               &liTimeout);
1392
1393             if( ntStatus == STATUS_TIMEOUT)
1394             {
1395
1396                 bTimeout = TRUE;
1397             }
1398
1399             InterlockedDecrement( &pControlDevExt->Specific.Control.WaitingForMemoryCount);
1400         }
1401     }
1402
1403     return pBuffer;
1404 }
1405
1406 void
1407 AFSExFreePoolWithTag( IN void *Buffer, IN ULONG Tag)
1408 {
1409
1410     AFSDeviceExt *pControlDevExt = NULL;
1411
1412     if ( AFSDeviceObject)
1413     {
1414
1415         pControlDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
1416     }
1417
1418     if ( Tag)
1419     {
1420
1421         ExFreePoolWithTag( Buffer, Tag);
1422     }
1423     else
1424     {
1425
1426         ExFreePool( Buffer);
1427     }
1428
1429     if ( pControlDevExt)
1430     {
1431
1432         KeSetEvent( &pControlDevExt->Specific.Control.MemoryAvailableEvent,
1433                     0,
1434                     FALSE);
1435     }
1436     return;
1437 }
1438
1439 NTSTATUS
1440 AFSShutdownRedirector()
1441 {
1442
1443     NTSTATUS ntStatus = STATUS_SUCCESS;
1444     AFSDeviceExt *pRDRDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1445     AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
1446     LARGE_INTEGER liTimeout;
1447
1448     __Enter
1449     {
1450
1451         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1452                       AFS_TRACE_LEVEL_VERBOSE,
1453                       "%s Shutting down redirector Extent count %08lX Request count %08lX\n",
1454                       __FUNCTION__,
1455                       pControlDevExt->Specific.Control.ExtentCount,
1456                       pControlDevExt->Specific.Control.OutstandingServiceRequestCount);
1457
1458         //
1459         // Set the shutdown flag so the worker is more agressive in tearing down extents
1460         //
1461
1462         SetFlag( pRDRDevExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN);
1463
1464         //
1465         // Wait on any outstanding service requests
1466         //
1467
1468         liTimeout.QuadPart = -(30 *AFS_ONE_SECOND);
1469
1470         ntStatus = KeWaitForSingleObject( &pControlDevExt->Specific.Control.OutstandingServiceRequestEvent,
1471                                           Executive,
1472                                           KernelMode,
1473                                           FALSE,
1474                                           &liTimeout);
1475
1476         if( ntStatus == STATUS_TIMEOUT)
1477         {
1478
1479             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1480                           AFS_TRACE_LEVEL_WARNING,
1481                           "AFSShutdownRedirector Failed to complete all service requests Remaining count %08lX\n",
1482                           pControlDevExt->Specific.Control.OutstandingServiceRequestCount);
1483
1484             try_return( ntStatus = STATUS_UNSUCCESSFUL);
1485         }
1486
1487         AFSProcessQueuedResults( TRUE);
1488
1489         //
1490         // Wait for all extents to be released
1491         //
1492
1493         liTimeout.QuadPart = -(30 *AFS_ONE_SECOND);
1494
1495         ntStatus = KeWaitForSingleObject( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
1496                                           Executive,
1497                                           KernelMode,
1498                                           FALSE,
1499                                           &liTimeout);
1500
1501         if( ntStatus == STATUS_TIMEOUT)
1502         {
1503
1504             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1505                           AFS_TRACE_LEVEL_WARNING,
1506                           "AFSShutdownRedirector Failed to purge all extents Remaining count %08lX\n",
1507                           pControlDevExt->Specific.Control.ExtentCount);
1508
1509             try_return( ntStatus = STATUS_UNSUCCESSFUL);
1510         }
1511
1512         ntStatus = AFSUnloadLibrary( TRUE);
1513
1514         if( !NT_SUCCESS( ntStatus))
1515         {
1516
1517             try_return( ntStatus);
1518         }
1519
1520 try_exit:
1521
1522         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1523                       AFS_TRACE_LEVEL_VERBOSE,
1524                       "%s Completed shut down of redirector Extent count %08lX Request count %08lX Status %08lX\n",
1525                       __FUNCTION__,
1526                       pControlDevExt->Specific.Control.ExtentCount,
1527                       pControlDevExt->Specific.Control.OutstandingServiceRequestCount,
1528                       ntStatus);
1529     }
1530
1531     return ntStatus;
1532 }
1533
1534 //
1535 // Cache manager callback routines
1536 //
1537
1538 BOOLEAN
1539 AFSAcquireFcbForLazyWrite( IN PVOID Fcb,
1540                            IN BOOLEAN Wait)
1541 {
1542
1543     BOOLEAN bStatus = FALSE;
1544     AFSFcb *pFcb = (AFSFcb *)Fcb;
1545     BOOLEAN bReleaseMain = FALSE, bReleasePaging = FALSE;
1546
1547     //
1548     // Try and acquire the Fcb resource
1549     //
1550
1551     AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1552                   AFS_TRACE_LEVEL_VERBOSE,
1553                   "AFSAcquireFcbForLazyWrite Acquiring Fcb %08lX\n",
1554                   Fcb);
1555
1556     ASSERT( NULL == pFcb->Specific.File.LazyWriterThread);
1557
1558     pFcb->Specific.File.LazyWriterThread = PsGetCurrentThread();
1559
1560     AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1561                   AFS_TRACE_LEVEL_VERBOSE,
1562                   "AFSAcquireFcbForLazyWrite Attempt to acquire Fcb lock %08lX SHARED %08lX\n",
1563                   &pFcb->NPFcb->Resource,
1564                   PsGetCurrentThread());
1565
1566     if( AFSAcquireShared( &pFcb->NPFcb->Resource,
1567                           Wait))
1568     {
1569
1570         AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1571                       AFS_TRACE_LEVEL_VERBOSE,
1572                       "AFSAcquireFcbForLazyWrite Acquired Fcb lock %08lX SHARED %08lX\n",
1573                       &pFcb->NPFcb->Resource,
1574                       PsGetCurrentThread());
1575
1576         bReleaseMain = TRUE;
1577
1578         //
1579         // Try and grab the paging
1580         //
1581
1582         AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1583                       AFS_TRACE_LEVEL_VERBOSE,
1584                       "AFSAcquireFcbForLazyWrite Attempt to acquire Fcb PagingIo lock %08lX SHARED %08lX\n",
1585                       &pFcb->NPFcb->PagingResource,
1586                       PsGetCurrentThread());
1587
1588         if( AFSAcquireShared( &pFcb->NPFcb->PagingResource,
1589                               Wait))
1590         {
1591
1592             AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1593                           AFS_TRACE_LEVEL_VERBOSE,
1594                           "AFSAcquireFcbForLazyWrite Acquired Fcb PagingIo lock %08lX SHARED %08lX\n",
1595                           &pFcb->NPFcb->PagingResource,
1596                           PsGetCurrentThread());
1597
1598             bReleasePaging = TRUE;
1599
1600             //
1601             // All is well ...
1602             //
1603
1604             bStatus = TRUE;
1605
1606             IoSetTopLevelIrp( (PIRP)FSRTL_CACHE_TOP_LEVEL_IRP);
1607         }
1608     }
1609
1610     if( !bStatus)
1611     {
1612
1613         if( bReleaseMain)
1614         {
1615
1616             AFSReleaseResource( &pFcb->NPFcb->Resource);
1617         }
1618
1619         if( bReleasePaging)
1620         {
1621
1622             AFSReleaseResource( &pFcb->NPFcb->PagingResource);
1623         }
1624     }
1625
1626     return bStatus;
1627 }
1628
1629 VOID
1630 AFSReleaseFcbFromLazyWrite( IN PVOID Fcb)
1631 {
1632
1633     AFSFcb *pFcb = (AFSFcb *)Fcb;
1634
1635     AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1636                   AFS_TRACE_LEVEL_VERBOSE,
1637                   "AFSReleaseFcbFromLazyWrite Releasing Fcb %08lX\n",
1638                   Fcb);
1639
1640     IoSetTopLevelIrp( NULL);
1641
1642     ASSERT( PsGetCurrentThread() == pFcb->Specific.File.LazyWriterThread);
1643
1644     pFcb->Specific.File.LazyWriterThread = NULL;
1645
1646
1647     AFSReleaseResource( &pFcb->NPFcb->PagingResource);
1648
1649     AFSReleaseResource( &pFcb->NPFcb->Resource);
1650
1651     return;
1652 }
1653
1654 BOOLEAN
1655 AFSAcquireFcbForReadAhead( IN PVOID Fcb,
1656                            IN BOOLEAN Wait)
1657 {
1658
1659     BOOLEAN bStatus = FALSE;
1660     AFSFcb *pFcb = (AFSFcb *)Fcb;
1661
1662     AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1663                   AFS_TRACE_LEVEL_VERBOSE,
1664                   "AFSAcquireFcbForReadAhead Attempt to acquire Fcb lock %08lX SHARED %08lX\n",
1665                   &pFcb->NPFcb->Resource,
1666                   PsGetCurrentThread());
1667
1668     if( AFSAcquireShared( &pFcb->NPFcb->Resource,
1669                           Wait))
1670     {
1671
1672         AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1673                       AFS_TRACE_LEVEL_VERBOSE,
1674                       "AFSAcquireFcbForReadAhead Acquired Fcb lock %08lX SHARED %08lX\n",
1675                       &pFcb->NPFcb->Resource,
1676                       PsGetCurrentThread());
1677
1678         bStatus = TRUE;
1679
1680         IoSetTopLevelIrp( (PIRP)FSRTL_CACHE_TOP_LEVEL_IRP);
1681     }
1682
1683     return bStatus;
1684 }
1685
1686 VOID
1687 AFSReleaseFcbFromReadAhead( IN PVOID Fcb)
1688 {
1689
1690     AFSFcb *pFcb = (AFSFcb *)Fcb;
1691
1692     IoSetTopLevelIrp( NULL);
1693
1694     AFSReleaseResource( &pFcb->NPFcb->Resource);
1695
1696     return;
1697 }
1698
1699 NTSTATUS
1700 AFSGetCallerSID( OUT UNICODE_STRING *SIDString, OUT BOOLEAN *pbImpersonation)
1701 {
1702
1703     NTSTATUS ntStatus = STATUS_SUCCESS;
1704     PACCESS_TOKEN hToken = NULL;
1705     TOKEN_USER *pTokenInfo = NULL;
1706     BOOLEAN bCopyOnOpen = FALSE;
1707     BOOLEAN bEffectiveOnly = FALSE;
1708     BOOLEAN bPrimaryToken = FALSE;
1709     SECURITY_IMPERSONATION_LEVEL stImpersonationLevel;
1710     UNICODE_STRING uniSIDString;
1711
1712     __Enter
1713     {
1714
1715         hToken = PsReferenceImpersonationToken( PsGetCurrentThread(),
1716                                                 &bCopyOnOpen,
1717                                                 &bEffectiveOnly,
1718                                                 &stImpersonationLevel);
1719
1720         if( hToken == NULL)
1721         {
1722
1723             hToken = PsReferencePrimaryToken( PsGetCurrentProcess());
1724
1725             if( hToken == NULL)
1726             {
1727
1728                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1729                               AFS_TRACE_LEVEL_ERROR,
1730                               "AFSGetCallerSID Failed to retrieve impersonation or primary token\n");
1731
1732                 try_return( ntStatus);
1733             }
1734
1735             bPrimaryToken = TRUE;
1736         }
1737
1738         ntStatus = SeQueryInformationToken( hToken,
1739                                             TokenUser,
1740                                             (PVOID *)&pTokenInfo);
1741
1742         if( !NT_SUCCESS( ntStatus))
1743         {
1744
1745             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1746                           AFS_TRACE_LEVEL_ERROR,
1747                           "AFSGetCallerSID Failed to retrieve information Status %08lX\n", ntStatus);
1748
1749             try_return( ntStatus);
1750         }
1751
1752         uniSIDString.Length = 0;
1753         uniSIDString.MaximumLength = 0;
1754         uniSIDString.Buffer = NULL;
1755
1756         ntStatus = RtlConvertSidToUnicodeString( &uniSIDString,
1757                                                  pTokenInfo->User.Sid,
1758                                                  TRUE);
1759
1760         if( !NT_SUCCESS( ntStatus))
1761         {
1762
1763             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1764                           AFS_TRACE_LEVEL_ERROR,
1765                           "AFSGetCallerSID Failed to convert sid to string Status %08lX\n", ntStatus);
1766
1767             try_return( ntStatus);
1768         }
1769
1770         *SIDString = uniSIDString;
1771
1772         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING | AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
1773                       AFS_TRACE_LEVEL_VERBOSE_2,
1774                       "AFSGetCallerSID Successfully retrieved SID %wZ\n",
1775                       SIDString);
1776
1777         if ( bPrimaryToken == FALSE &&
1778              pbImpersonation)
1779         {
1780             *pbImpersonation = TRUE;
1781         }
1782
1783 try_exit:
1784
1785         if( hToken != NULL)
1786         {
1787             if( bPrimaryToken)
1788             {
1789                 PsDereferencePrimaryToken( hToken);
1790             }
1791             else
1792             {
1793                 PsDereferenceImpersonationToken( hToken);
1794             }
1795         }
1796
1797         if( pTokenInfo != NULL)
1798         {
1799             ExFreePool( pTokenInfo);    // Allocated by SeQueryInformationToken
1800         }
1801     }
1802
1803     return ntStatus;
1804 }
1805
1806 ULONG
1807 AFSGetSessionId( IN HANDLE ProcessId, OUT BOOLEAN *pbImpersonation)
1808 {
1809
1810     NTSTATUS ntStatus = STATUS_SUCCESS;
1811     PACCESS_TOKEN hToken = NULL;
1812     ULONG ulSessionId = (ULONG)-1;
1813     BOOLEAN bCopyOnOpen = FALSE;
1814     BOOLEAN bEffectiveOnly = FALSE;
1815     BOOLEAN bPrimaryToken = FALSE;
1816     SECURITY_IMPERSONATION_LEVEL stImpersonationLevel;
1817
1818     __Enter
1819     {
1820
1821         hToken = PsReferenceImpersonationToken( PsGetCurrentThread(),
1822                                                 &bCopyOnOpen,
1823                                                 &bEffectiveOnly,
1824                                                 &stImpersonationLevel);
1825
1826         if( hToken == NULL)
1827         {
1828
1829             hToken = PsReferencePrimaryToken( PsGetCurrentProcess());
1830
1831             if( hToken == NULL)
1832             {
1833
1834                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1835                               AFS_TRACE_LEVEL_ERROR,
1836                               "AFSGetSessionId Failed to retrieve impersonation or primary token\n");
1837
1838                 try_return( ntStatus);
1839             }
1840
1841             bPrimaryToken = TRUE;
1842         }
1843
1844         ntStatus = SeQueryInformationToken( hToken,
1845                                             TokenSessionId,
1846                                             (PVOID *)&ulSessionId);
1847
1848         if( !NT_SUCCESS( ntStatus))
1849         {
1850             ulSessionId = (ULONG)-1;
1851
1852             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1853                           AFS_TRACE_LEVEL_ERROR,
1854                           "AFSGetSessionId Failed to retrieve session id Status %08lX\n",
1855                           ntStatus);
1856
1857             try_return( ntStatus);
1858         }
1859
1860         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING | AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
1861                       AFS_TRACE_LEVEL_VERBOSE_2,
1862                       "AFSGetSessionId found %08lX\n",
1863                       ulSessionId);
1864
1865         if ( bPrimaryToken == FALSE &&
1866              pbImpersonation)
1867         {
1868             *pbImpersonation = TRUE;
1869         }
1870
1871 try_exit:
1872
1873         if( hToken != NULL)
1874         {
1875             if( bPrimaryToken)
1876             {
1877                 PsDereferencePrimaryToken( hToken);
1878             }
1879             else
1880             {
1881                 PsDereferenceImpersonationToken( hToken);
1882             }
1883         }
1884     }
1885
1886     return ulSessionId;
1887 }
1888
1889 NTSTATUS
1890 AFSCheckThreadDacl( OUT GUID *AuthGroup)
1891 {
1892
1893     NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
1894     ULONG idx;
1895     PACCESS_TOKEN token = NULL;
1896     PTOKEN_DEFAULT_DACL defDacl = NULL;
1897     PACE_HEADER ace;
1898     PACCESS_ALLOWED_ACE adace;
1899     BOOLEAN bCopyOnOpen = FALSE, bEffectiveOnly = FALSE;
1900     SECURITY_IMPERSONATION_LEVEL stImpersonationLevel;
1901     BOOLEAN bLocatedACE = FALSE;
1902
1903     __Enter
1904     {
1905
1906         token = PsReferenceImpersonationToken( PsGetCurrentThread(),
1907                                                &bCopyOnOpen,
1908                                                &bEffectiveOnly,
1909                                                &stImpersonationLevel);
1910
1911         if( token == NULL)
1912         {
1913            try_return( ntStatus);
1914         }
1915
1916         ntStatus = SeQueryInformationToken( token,
1917                                             TokenDefaultDacl,
1918                                             (PVOID *)&defDacl);
1919
1920         if( ntStatus != STATUS_SUCCESS)
1921         {
1922            try_return( ntStatus);
1923         }
1924
1925         // scan through all ACEs in the DACL
1926         for (idx = 0, ace = (PACE_HEADER)((char *)defDacl->DefaultDacl + sizeof(ACL)); idx < defDacl->DefaultDacl->AceCount; idx++)
1927         {
1928            if (ace->AceType == ACCESS_ALLOWED_ACE_TYPE)
1929            {
1930               adace = (PACCESS_ALLOWED_ACE)ace;
1931
1932               if (adace->Header.AceSize == (FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) + AFS_DACL_SID_LENGTH))
1933               {
1934                  if (RtlCompareMemory( RtlSubAuthoritySid((PSID)&adace->SidStart, 0), &AFSSidGuid, sizeof(GUID)) == sizeof(GUID))
1935                  {
1936
1937                     RtlCopyMemory( AuthGroup,
1938                                    RtlSubAuthoritySid((PSID)&adace->SidStart, 4),
1939                                    sizeof( GUID));
1940
1941                     bLocatedACE = TRUE;
1942
1943                     break;
1944                  }
1945               }
1946            }
1947
1948            // go to next ace
1949            ace = (PACE_HEADER)((char *)ace + ace->AceSize);
1950         }
1951
1952 try_exit:
1953
1954         if( token != NULL)
1955         {
1956             PsDereferenceImpersonationToken( token);
1957         }
1958
1959         if (defDacl != NULL)
1960         {
1961            ExFreePool(defDacl);
1962         }
1963
1964         if( !bLocatedACE)
1965         {
1966             ntStatus = STATUS_UNSUCCESSFUL;
1967         }
1968     }
1969
1970     return ntStatus;
1971 }
1972
1973 NTSTATUS
1974 AFSProcessSetProcessDacl( IN AFSProcessCB *ProcessCB)
1975 {
1976
1977     PTOKEN_DEFAULT_DACL defDacl = NULL;
1978     HANDLE hToken = NULL;
1979     PACE_HEADER ace = NULL;
1980     SID_IDENTIFIER_AUTHORITY sia = SECURITY_NT_AUTHORITY;
1981     PACCESS_ALLOWED_ACE aaace;
1982     ULONG bytesNeeded;
1983     ULONG bytesReturned;
1984     ULONG idx;
1985     PSID psid;
1986     NTSTATUS ntStatus = STATUS_SUCCESS;
1987
1988     __Enter
1989     {
1990
1991         ntStatus = ZwOpenProcessTokenEx( NtCurrentProcess(),
1992                                          GENERIC_ALL,
1993                                          OBJ_KERNEL_HANDLE,
1994                                          &hToken);
1995
1996         if( !NT_SUCCESS( ntStatus))
1997         {
1998             try_return( ntStatus);
1999         }
2000
2001         // get the size of the current DACL
2002         ntStatus = ZwQueryInformationToken( hToken,
2003                                             TokenDefaultDacl,
2004                                             NULL,
2005                                             0,
2006                                             &bytesNeeded);
2007
2008         // if we failed to get the buffer size needed
2009         if ((ntStatus != STATUS_SUCCESS) && (ntStatus != STATUS_BUFFER_TOO_SMALL))
2010         {
2011             try_return( ntStatus);
2012         }
2013
2014         // tack on enough space for our ACE if we need to add it...
2015         bytesNeeded += FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) + AFS_DACL_SID_LENGTH;
2016
2017         // allocate space for the DACL
2018         defDacl = (PTOKEN_DEFAULT_DACL)ExAllocatePoolWithTag( PagedPool, bytesNeeded, AFS_GENERIC_MEMORY_26_TAG);
2019
2020         if (defDacl == NULL)
2021         {
2022            try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2023         }
2024
2025         // get the DACL
2026         ntStatus = ZwQueryInformationToken( hToken,
2027                                             TokenDefaultDacl,
2028                                             defDacl,
2029                                             bytesNeeded,
2030                                             &bytesReturned);
2031
2032         if( ntStatus != STATUS_SUCCESS)
2033         {
2034             try_return( ntStatus);
2035         }
2036
2037         // scan through DACL to see if we have the SID set already...
2038         ace = (PACE_HEADER)((char *)defDacl->DefaultDacl + sizeof(ACL));
2039         for (idx = 0; idx < defDacl->DefaultDacl->AceCount; idx++)
2040         {
2041             if (ace->AceType == ACCESS_ALLOWED_ACE_TYPE)
2042             {
2043                 aaace = (PACCESS_ALLOWED_ACE)ace;
2044
2045                 if (aaace->Header.AceSize == (FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) + AFS_DACL_SID_LENGTH))
2046                 {
2047                     // if the GUID part matches
2048                     if( RtlCompareMemory( RtlSubAuthoritySid((PSID)&aaace->SidStart, 0),
2049                                           &AFSSidGuid,
2050                                           sizeof(GUID)) == sizeof(GUID))
2051                     {
2052
2053                         if ( RtlCompareMemory( RtlSubAuthoritySid((PSID)&aaace->SidStart, 4),
2054                                                ProcessCB->ActiveAuthGroup,
2055                                                sizeof( GUID)) != sizeof( GUID))
2056                         {
2057
2058                             RtlCopyMemory( RtlSubAuthoritySid((PSID)&aaace->SidStart, 4),
2059                                            ProcessCB->ActiveAuthGroup,
2060                                            sizeof( GUID));
2061
2062                             if( AFSSetInformationToken != NULL)
2063                             {
2064                                 ntStatus = AFSSetInformationToken( hToken,
2065                                                                    TokenDefaultDacl,
2066                                                                    defDacl,
2067                                                                    bytesReturned);
2068                             }
2069                         }
2070
2071                         try_return( ntStatus);
2072                     }
2073                 }
2074             }
2075
2076             // go to next ace
2077             ace = (PACE_HEADER)((char *)ace + ace->AceSize);
2078         }
2079
2080         //
2081         // if we made it here we need to add a new ACE to the DACL
2082         //
2083
2084         aaace = (ACCESS_ALLOWED_ACE *)ace;
2085         aaace->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
2086         aaace->Header.AceFlags = 0;
2087         aaace->Mask = GENERIC_ALL;
2088         psid = (PSID)&aaace->SidStart;
2089         RtlInitializeSid( psid, &sia, 8);
2090
2091         RtlCopyMemory( RtlSubAuthoritySid(psid, 0),
2092                        &AFSSidGuid,
2093                        sizeof(GUID));
2094
2095         RtlCopyMemory( RtlSubAuthoritySid(psid, 4),
2096                        ProcessCB->ActiveAuthGroup,
2097                        sizeof( GUID));
2098
2099         aaace->Header.AceSize = (USHORT)(FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) + RtlLengthSid( psid));
2100
2101         defDacl->DefaultDacl->AclSize += aaace->Header.AceSize;
2102         defDacl->DefaultDacl->AceCount++;
2103
2104         if( AFSSetInformationToken != NULL)
2105         {
2106             ntStatus = AFSSetInformationToken( hToken,
2107                                               TokenDefaultDacl,
2108                                               defDacl,
2109                                               defDacl->DefaultDacl->AclSize + sizeof(PTOKEN_DEFAULT_DACL));
2110         }
2111
2112 try_exit:
2113
2114         if( hToken != NULL)
2115         {
2116             ZwClose( hToken);
2117         }
2118
2119         if (defDacl != NULL)
2120         {
2121            ExFreePool( defDacl);
2122         }
2123     }
2124
2125     return ntStatus;
2126 }
2127
2128