Windows: Remove Fcb.Specific.File.LazyWriterThread
[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     AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1557                   AFS_TRACE_LEVEL_VERBOSE,
1558                   "AFSAcquireFcbForLazyWrite Attempt to acquire Fcb lock %08lX SHARED %08lX\n",
1559                   &pFcb->NPFcb->Resource,
1560                   PsGetCurrentThread());
1561
1562     if( AFSAcquireShared( &pFcb->NPFcb->Resource,
1563                           Wait))
1564     {
1565
1566         AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1567                       AFS_TRACE_LEVEL_VERBOSE,
1568                       "AFSAcquireFcbForLazyWrite Acquired Fcb lock %08lX SHARED %08lX\n",
1569                       &pFcb->NPFcb->Resource,
1570                       PsGetCurrentThread());
1571
1572         bReleaseMain = TRUE;
1573
1574         //
1575         // Try and grab the paging
1576         //
1577
1578         AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1579                       AFS_TRACE_LEVEL_VERBOSE,
1580                       "AFSAcquireFcbForLazyWrite Attempt to acquire Fcb PagingIo lock %08lX SHARED %08lX\n",
1581                       &pFcb->NPFcb->PagingResource,
1582                       PsGetCurrentThread());
1583
1584         if( AFSAcquireShared( &pFcb->NPFcb->PagingResource,
1585                               Wait))
1586         {
1587
1588             AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1589                           AFS_TRACE_LEVEL_VERBOSE,
1590                           "AFSAcquireFcbForLazyWrite Acquired Fcb PagingIo lock %08lX SHARED %08lX\n",
1591                           &pFcb->NPFcb->PagingResource,
1592                           PsGetCurrentThread());
1593
1594             bReleasePaging = TRUE;
1595
1596             //
1597             // All is well ...
1598             //
1599
1600             bStatus = TRUE;
1601
1602             IoSetTopLevelIrp( (PIRP)FSRTL_CACHE_TOP_LEVEL_IRP);
1603         }
1604     }
1605
1606     if( !bStatus)
1607     {
1608
1609         if( bReleaseMain)
1610         {
1611
1612             AFSReleaseResource( &pFcb->NPFcb->Resource);
1613         }
1614
1615         if( bReleasePaging)
1616         {
1617
1618             AFSReleaseResource( &pFcb->NPFcb->PagingResource);
1619         }
1620     }
1621
1622     return bStatus;
1623 }
1624
1625 VOID
1626 AFSReleaseFcbFromLazyWrite( IN PVOID Fcb)
1627 {
1628
1629     AFSFcb *pFcb = (AFSFcb *)Fcb;
1630
1631     AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1632                   AFS_TRACE_LEVEL_VERBOSE,
1633                   "AFSReleaseFcbFromLazyWrite Releasing Fcb %08lX\n",
1634                   Fcb);
1635
1636     IoSetTopLevelIrp( NULL);
1637
1638     AFSReleaseResource( &pFcb->NPFcb->PagingResource);
1639
1640     AFSReleaseResource( &pFcb->NPFcb->Resource);
1641
1642     return;
1643 }
1644
1645 BOOLEAN
1646 AFSAcquireFcbForReadAhead( IN PVOID Fcb,
1647                            IN BOOLEAN Wait)
1648 {
1649
1650     BOOLEAN bStatus = FALSE;
1651     AFSFcb *pFcb = (AFSFcb *)Fcb;
1652
1653     AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1654                   AFS_TRACE_LEVEL_VERBOSE,
1655                   "AFSAcquireFcbForReadAhead Attempt to acquire Fcb lock %08lX SHARED %08lX\n",
1656                   &pFcb->NPFcb->Resource,
1657                   PsGetCurrentThread());
1658
1659     if( AFSAcquireShared( &pFcb->NPFcb->Resource,
1660                           Wait))
1661     {
1662
1663         AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1664                       AFS_TRACE_LEVEL_VERBOSE,
1665                       "AFSAcquireFcbForReadAhead Acquired Fcb lock %08lX SHARED %08lX\n",
1666                       &pFcb->NPFcb->Resource,
1667                       PsGetCurrentThread());
1668
1669         bStatus = TRUE;
1670
1671         IoSetTopLevelIrp( (PIRP)FSRTL_CACHE_TOP_LEVEL_IRP);
1672     }
1673
1674     return bStatus;
1675 }
1676
1677 VOID
1678 AFSReleaseFcbFromReadAhead( IN PVOID Fcb)
1679 {
1680
1681     AFSFcb *pFcb = (AFSFcb *)Fcb;
1682
1683     IoSetTopLevelIrp( NULL);
1684
1685     AFSReleaseResource( &pFcb->NPFcb->Resource);
1686
1687     return;
1688 }
1689
1690 NTSTATUS
1691 AFSGetCallerSID( OUT UNICODE_STRING *SIDString, OUT BOOLEAN *pbImpersonation)
1692 {
1693
1694     NTSTATUS ntStatus = STATUS_SUCCESS;
1695     PACCESS_TOKEN hToken = NULL;
1696     TOKEN_USER *pTokenInfo = NULL;
1697     BOOLEAN bCopyOnOpen = FALSE;
1698     BOOLEAN bEffectiveOnly = FALSE;
1699     BOOLEAN bPrimaryToken = FALSE;
1700     SECURITY_IMPERSONATION_LEVEL stImpersonationLevel;
1701     UNICODE_STRING uniSIDString;
1702
1703     __Enter
1704     {
1705
1706         hToken = PsReferenceImpersonationToken( PsGetCurrentThread(),
1707                                                 &bCopyOnOpen,
1708                                                 &bEffectiveOnly,
1709                                                 &stImpersonationLevel);
1710
1711         if( hToken == NULL)
1712         {
1713
1714             hToken = PsReferencePrimaryToken( PsGetCurrentProcess());
1715
1716             if( hToken == NULL)
1717             {
1718
1719                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1720                               AFS_TRACE_LEVEL_ERROR,
1721                               "AFSGetCallerSID Failed to retrieve impersonation or primary token\n");
1722
1723                 try_return( ntStatus);
1724             }
1725
1726             bPrimaryToken = TRUE;
1727         }
1728
1729         ntStatus = SeQueryInformationToken( hToken,
1730                                             TokenUser,
1731                                             (PVOID *)&pTokenInfo);
1732
1733         if( !NT_SUCCESS( ntStatus))
1734         {
1735
1736             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1737                           AFS_TRACE_LEVEL_ERROR,
1738                           "AFSGetCallerSID Failed to retrieve information Status %08lX\n", ntStatus);
1739
1740             try_return( ntStatus);
1741         }
1742
1743         uniSIDString.Length = 0;
1744         uniSIDString.MaximumLength = 0;
1745         uniSIDString.Buffer = NULL;
1746
1747         ntStatus = RtlConvertSidToUnicodeString( &uniSIDString,
1748                                                  pTokenInfo->User.Sid,
1749                                                  TRUE);
1750
1751         if( !NT_SUCCESS( ntStatus))
1752         {
1753
1754             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1755                           AFS_TRACE_LEVEL_ERROR,
1756                           "AFSGetCallerSID Failed to convert sid to string Status %08lX\n", ntStatus);
1757
1758             try_return( ntStatus);
1759         }
1760
1761         *SIDString = uniSIDString;
1762
1763         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING | AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
1764                       AFS_TRACE_LEVEL_VERBOSE_2,
1765                       "AFSGetCallerSID Successfully retrieved SID %wZ\n",
1766                       SIDString);
1767
1768         if ( bPrimaryToken == FALSE &&
1769              pbImpersonation)
1770         {
1771             *pbImpersonation = TRUE;
1772         }
1773
1774 try_exit:
1775
1776         if( hToken != NULL)
1777         {
1778             if( bPrimaryToken)
1779             {
1780                 PsDereferencePrimaryToken( hToken);
1781             }
1782             else
1783             {
1784                 PsDereferenceImpersonationToken( hToken);
1785             }
1786         }
1787
1788         if( pTokenInfo != NULL)
1789         {
1790             ExFreePool( pTokenInfo);    // Allocated by SeQueryInformationToken
1791         }
1792     }
1793
1794     return ntStatus;
1795 }
1796
1797 ULONG
1798 AFSGetSessionId( IN HANDLE ProcessId, OUT BOOLEAN *pbImpersonation)
1799 {
1800
1801     NTSTATUS ntStatus = STATUS_SUCCESS;
1802     PACCESS_TOKEN hToken = NULL;
1803     ULONG ulSessionId = (ULONG)-1;
1804     BOOLEAN bCopyOnOpen = FALSE;
1805     BOOLEAN bEffectiveOnly = FALSE;
1806     BOOLEAN bPrimaryToken = FALSE;
1807     SECURITY_IMPERSONATION_LEVEL stImpersonationLevel;
1808
1809     __Enter
1810     {
1811
1812         hToken = PsReferenceImpersonationToken( PsGetCurrentThread(),
1813                                                 &bCopyOnOpen,
1814                                                 &bEffectiveOnly,
1815                                                 &stImpersonationLevel);
1816
1817         if( hToken == NULL)
1818         {
1819
1820             hToken = PsReferencePrimaryToken( PsGetCurrentProcess());
1821
1822             if( hToken == NULL)
1823             {
1824
1825                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1826                               AFS_TRACE_LEVEL_ERROR,
1827                               "AFSGetSessionId Failed to retrieve impersonation or primary token\n");
1828
1829                 try_return( ntStatus);
1830             }
1831
1832             bPrimaryToken = TRUE;
1833         }
1834
1835         ntStatus = SeQueryInformationToken( hToken,
1836                                             TokenSessionId,
1837                                             (PVOID *)&ulSessionId);
1838
1839         if( !NT_SUCCESS( ntStatus))
1840         {
1841             ulSessionId = (ULONG)-1;
1842
1843             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1844                           AFS_TRACE_LEVEL_ERROR,
1845                           "AFSGetSessionId Failed to retrieve session id Status %08lX\n",
1846                           ntStatus);
1847
1848             try_return( ntStatus);
1849         }
1850
1851         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING | AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
1852                       AFS_TRACE_LEVEL_VERBOSE_2,
1853                       "AFSGetSessionId found %08lX\n",
1854                       ulSessionId);
1855
1856         if ( bPrimaryToken == FALSE &&
1857              pbImpersonation)
1858         {
1859             *pbImpersonation = TRUE;
1860         }
1861
1862 try_exit:
1863
1864         if( hToken != NULL)
1865         {
1866             if( bPrimaryToken)
1867             {
1868                 PsDereferencePrimaryToken( hToken);
1869             }
1870             else
1871             {
1872                 PsDereferenceImpersonationToken( hToken);
1873             }
1874         }
1875     }
1876
1877     return ulSessionId;
1878 }
1879
1880 NTSTATUS
1881 AFSCheckThreadDacl( OUT GUID *AuthGroup)
1882 {
1883
1884     NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
1885     ULONG idx;
1886     PACCESS_TOKEN token = NULL;
1887     PTOKEN_DEFAULT_DACL defDacl = NULL;
1888     PACE_HEADER ace;
1889     PACCESS_ALLOWED_ACE adace;
1890     BOOLEAN bCopyOnOpen = FALSE, bEffectiveOnly = FALSE;
1891     SECURITY_IMPERSONATION_LEVEL stImpersonationLevel;
1892     BOOLEAN bLocatedACE = FALSE;
1893
1894     __Enter
1895     {
1896
1897         token = PsReferenceImpersonationToken( PsGetCurrentThread(),
1898                                                &bCopyOnOpen,
1899                                                &bEffectiveOnly,
1900                                                &stImpersonationLevel);
1901
1902         if( token == NULL)
1903         {
1904            try_return( ntStatus);
1905         }
1906
1907         ntStatus = SeQueryInformationToken( token,
1908                                             TokenDefaultDacl,
1909                                             (PVOID *)&defDacl);
1910
1911         if( ntStatus != STATUS_SUCCESS)
1912         {
1913            try_return( ntStatus);
1914         }
1915
1916         // scan through all ACEs in the DACL
1917         for (idx = 0, ace = (PACE_HEADER)((char *)defDacl->DefaultDacl + sizeof(ACL)); idx < defDacl->DefaultDacl->AceCount; idx++)
1918         {
1919            if (ace->AceType == ACCESS_ALLOWED_ACE_TYPE)
1920            {
1921               adace = (PACCESS_ALLOWED_ACE)ace;
1922
1923               if (adace->Header.AceSize == (FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) + AFS_DACL_SID_LENGTH))
1924               {
1925                  if (RtlCompareMemory( RtlSubAuthoritySid((PSID)&adace->SidStart, 0), &AFSSidGuid, sizeof(GUID)) == sizeof(GUID))
1926                  {
1927
1928                     RtlCopyMemory( AuthGroup,
1929                                    RtlSubAuthoritySid((PSID)&adace->SidStart, 4),
1930                                    sizeof( GUID));
1931
1932                     bLocatedACE = TRUE;
1933
1934                     break;
1935                  }
1936               }
1937            }
1938
1939            // go to next ace
1940            ace = (PACE_HEADER)((char *)ace + ace->AceSize);
1941         }
1942
1943 try_exit:
1944
1945         if( token != NULL)
1946         {
1947             PsDereferenceImpersonationToken( token);
1948         }
1949
1950         if (defDacl != NULL)
1951         {
1952            ExFreePool(defDacl);
1953         }
1954
1955         if( !bLocatedACE)
1956         {
1957             ntStatus = STATUS_UNSUCCESSFUL;
1958         }
1959     }
1960
1961     return ntStatus;
1962 }
1963
1964 NTSTATUS
1965 AFSProcessSetProcessDacl( IN AFSProcessCB *ProcessCB)
1966 {
1967
1968     PTOKEN_DEFAULT_DACL defDacl = NULL;
1969     HANDLE hToken = NULL;
1970     PACE_HEADER ace = NULL;
1971     SID_IDENTIFIER_AUTHORITY sia = SECURITY_NT_AUTHORITY;
1972     PACCESS_ALLOWED_ACE aaace;
1973     ULONG bytesNeeded;
1974     ULONG bytesReturned;
1975     ULONG idx;
1976     PSID psid;
1977     NTSTATUS ntStatus = STATUS_SUCCESS;
1978
1979     __Enter
1980     {
1981
1982         ntStatus = ZwOpenProcessTokenEx( NtCurrentProcess(),
1983                                          GENERIC_ALL,
1984                                          OBJ_KERNEL_HANDLE,
1985                                          &hToken);
1986
1987         if( !NT_SUCCESS( ntStatus))
1988         {
1989             try_return( ntStatus);
1990         }
1991
1992         // get the size of the current DACL
1993         ntStatus = ZwQueryInformationToken( hToken,
1994                                             TokenDefaultDacl,
1995                                             NULL,
1996                                             0,
1997                                             &bytesNeeded);
1998
1999         // if we failed to get the buffer size needed
2000         if ((ntStatus != STATUS_SUCCESS) && (ntStatus != STATUS_BUFFER_TOO_SMALL))
2001         {
2002             try_return( ntStatus);
2003         }
2004
2005         // tack on enough space for our ACE if we need to add it...
2006         bytesNeeded += FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) + AFS_DACL_SID_LENGTH;
2007
2008         // allocate space for the DACL
2009         defDacl = (PTOKEN_DEFAULT_DACL)ExAllocatePoolWithTag( PagedPool, bytesNeeded, AFS_GENERIC_MEMORY_26_TAG);
2010
2011         if (defDacl == NULL)
2012         {
2013            try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2014         }
2015
2016         // get the DACL
2017         ntStatus = ZwQueryInformationToken( hToken,
2018                                             TokenDefaultDacl,
2019                                             defDacl,
2020                                             bytesNeeded,
2021                                             &bytesReturned);
2022
2023         if( ntStatus != STATUS_SUCCESS)
2024         {
2025             try_return( ntStatus);
2026         }
2027
2028         // scan through DACL to see if we have the SID set already...
2029         ace = (PACE_HEADER)((char *)defDacl->DefaultDacl + sizeof(ACL));
2030         for (idx = 0; idx < defDacl->DefaultDacl->AceCount; idx++)
2031         {
2032             if (ace->AceType == ACCESS_ALLOWED_ACE_TYPE)
2033             {
2034                 aaace = (PACCESS_ALLOWED_ACE)ace;
2035
2036                 if (aaace->Header.AceSize == (FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) + AFS_DACL_SID_LENGTH))
2037                 {
2038                     // if the GUID part matches
2039                     if( RtlCompareMemory( RtlSubAuthoritySid((PSID)&aaace->SidStart, 0),
2040                                           &AFSSidGuid,
2041                                           sizeof(GUID)) == sizeof(GUID))
2042                     {
2043
2044                         if ( RtlCompareMemory( RtlSubAuthoritySid((PSID)&aaace->SidStart, 4),
2045                                                ProcessCB->ActiveAuthGroup,
2046                                                sizeof( GUID)) != sizeof( GUID))
2047                         {
2048
2049                             RtlCopyMemory( RtlSubAuthoritySid((PSID)&aaace->SidStart, 4),
2050                                            ProcessCB->ActiveAuthGroup,
2051                                            sizeof( GUID));
2052
2053                             if( AFSSetInformationToken != NULL)
2054                             {
2055                                 ntStatus = AFSSetInformationToken( hToken,
2056                                                                    TokenDefaultDacl,
2057                                                                    defDacl,
2058                                                                    bytesReturned);
2059                             }
2060                         }
2061
2062                         try_return( ntStatus);
2063                     }
2064                 }
2065             }
2066
2067             // go to next ace
2068             ace = (PACE_HEADER)((char *)ace + ace->AceSize);
2069         }
2070
2071         //
2072         // if we made it here we need to add a new ACE to the DACL
2073         //
2074
2075         aaace = (ACCESS_ALLOWED_ACE *)ace;
2076         aaace->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
2077         aaace->Header.AceFlags = 0;
2078         aaace->Mask = GENERIC_ALL;
2079         psid = (PSID)&aaace->SidStart;
2080         RtlInitializeSid( psid, &sia, 8);
2081
2082         RtlCopyMemory( RtlSubAuthoritySid(psid, 0),
2083                        &AFSSidGuid,
2084                        sizeof(GUID));
2085
2086         RtlCopyMemory( RtlSubAuthoritySid(psid, 4),
2087                        ProcessCB->ActiveAuthGroup,
2088                        sizeof( GUID));
2089
2090         aaace->Header.AceSize = (USHORT)(FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) + RtlLengthSid( psid));
2091
2092         defDacl->DefaultDacl->AclSize += aaace->Header.AceSize;
2093         defDacl->DefaultDacl->AceCount++;
2094
2095         if( AFSSetInformationToken != NULL)
2096         {
2097             ntStatus = AFSSetInformationToken( hToken,
2098                                               TokenDefaultDacl,
2099                                               defDacl,
2100                                               defDacl->DefaultDacl->AclSize + sizeof(PTOKEN_DEFAULT_DACL));
2101         }
2102
2103 try_exit:
2104
2105         if( hToken != NULL)
2106         {
2107             ZwClose( hToken);
2108         }
2109
2110         if (defDacl != NULL)
2111         {
2112            ExFreePool( defDacl);
2113         }
2114     }
2115
2116     return ntStatus;
2117 }
2118
2119