Windows: Implement dynamic cell detection for RDR
[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_REG_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 AFSReadMountRootName()
1001 {
1002
1003     NTSTATUS ntStatus        = STATUS_SUCCESS;
1004     ULONG Default            = 0;
1005     UNICODE_STRING paramPath;
1006     RTL_QUERY_REGISTRY_TABLE paramTable[2];
1007
1008     __Enter
1009     {
1010
1011         //
1012         // Setup the paramPath buffer.
1013         //
1014
1015         paramPath.MaximumLength = PAGE_SIZE;
1016         paramPath.Buffer = (PWSTR)AFSExAllocatePoolWithTag( PagedPool,
1017                                                             paramPath.MaximumLength,
1018                                                             AFS_GENERIC_MEMORY_17_TAG);
1019
1020         //
1021         // If it exists, setup the path.
1022         //
1023
1024         if( paramPath.Buffer == NULL)
1025         {
1026
1027             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1028         }
1029
1030         //
1031         // Move in the paths
1032         //
1033
1034         RtlZeroMemory( paramPath.Buffer,
1035                        paramPath.MaximumLength);
1036
1037         RtlCopyMemory( &paramPath.Buffer[ 0],
1038                        L"\\TransarcAFSDaemon\\Parameters",
1039                        58);
1040
1041         paramPath.Length = 58;
1042
1043         RtlZeroMemory( paramTable,
1044                        sizeof( paramTable));
1045
1046         //
1047         // Setup the table to query the registry for the needed value
1048         //
1049
1050         AFSMountRootName.Length = 0;
1051         AFSMountRootName.MaximumLength = 0;
1052         AFSMountRootName.Buffer = NULL;
1053
1054         paramTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
1055         paramTable[0].Name = AFS_REG_MOUNT_ROOT;
1056         paramTable[0].EntryContext = &AFSMountRootName;
1057
1058         paramTable[0].DefaultType = REG_NONE;
1059         paramTable[0].DefaultData = NULL;
1060         paramTable[0].DefaultLength = 0;
1061
1062         //
1063         // Query the registry
1064         //
1065
1066         ntStatus = RtlQueryRegistryValues( RTL_REGISTRY_SERVICES,
1067                                            paramPath.Buffer,
1068                                            paramTable,
1069                                            NULL,
1070                                            NULL);
1071
1072         if ( NT_SUCCESS( ntStatus))
1073         {
1074             if ( AFSMountRootName.Buffer[0] == L'/')
1075             {
1076
1077                 AFSMountRootName.Buffer[0] = L'\\';
1078             }
1079         }
1080
1081         //
1082         // Free up the buffer
1083         //
1084
1085         ExFreePool( paramPath.Buffer);
1086
1087 try_exit:
1088
1089         if( !NT_SUCCESS( ntStatus))
1090         {
1091
1092             RtlInitUnicodeString( &AFSMountRootName,
1093                                   L"\\afs");
1094         }
1095     }
1096
1097     return ntStatus;
1098 }
1099
1100 NTSTATUS
1101 AFSSetSysNameInformation( IN AFSSysNameNotificationCB *SysNameInfo,
1102                           IN ULONG SysNameInfoBufferLength)
1103 {
1104
1105     NTSTATUS         ntStatus = STATUS_SUCCESS;
1106     AFSDeviceExt    *pControlDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
1107     AFSSysNameCB    *pSysName = NULL;
1108     ERESOURCE       *pSysNameLock = NULL;
1109     AFSSysNameCB   **pSysNameListHead = NULL, **pSysNameListTail = NULL;
1110     ULONG            ulIndex = 0;
1111     __Enter
1112     {
1113
1114         //
1115         // Depending on the architecture of the information, set up the lsit
1116         //
1117
1118         if( SysNameInfo->Architecture == AFS_SYSNAME_ARCH_32BIT)
1119         {
1120
1121             pSysNameLock = &pControlDevExt->Specific.Control.SysName32ListLock;
1122
1123             pSysNameListHead = &pControlDevExt->Specific.Control.SysName32ListHead;
1124
1125             pSysNameListTail = &pControlDevExt->Specific.Control.SysName32ListTail;
1126         }
1127         else
1128         {
1129
1130 #if defined(_WIN64)
1131
1132             pSysNameLock = &pControlDevExt->Specific.Control.SysName64ListLock;
1133
1134             pSysNameListHead = &pControlDevExt->Specific.Control.SysName64ListHead;
1135
1136             pSysNameListTail = &pControlDevExt->Specific.Control.SysName64ListTail;
1137
1138 #else
1139
1140             try_return( ntStatus = STATUS_INVALID_PARAMETER);
1141 #endif
1142         }
1143
1144         //
1145         // Process the request
1146         //
1147
1148         AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1149                       AFS_TRACE_LEVEL_VERBOSE,
1150                       "AFSSetSysNameInformation Acquiring SysName lock %08lX EXCL %08lX\n",
1151                       pSysNameLock,
1152                       PsGetCurrentThread());
1153
1154         AFSAcquireExcl( pSysNameLock,
1155                         TRUE);
1156
1157         //
1158         // If we already have a list, then tear it down
1159         //
1160
1161         if( *pSysNameListHead != NULL)
1162         {
1163
1164             AFSResetSysNameList( *pSysNameListHead);
1165
1166             *pSysNameListHead = NULL;
1167         }
1168
1169         //
1170         // Loop through the entries adding in a node for each
1171         //
1172
1173         while( ulIndex < SysNameInfo->NumberOfNames)
1174         {
1175
1176             pSysName = (AFSSysNameCB *)AFSExAllocatePoolWithTag( PagedPool,
1177                                                                  sizeof( AFSSysNameCB) +
1178                                                                  SysNameInfo->SysNames[ ulIndex].Length +
1179                                                                  sizeof( WCHAR),
1180                                                                  AFS_SYS_NAME_NODE_TAG);
1181
1182             if( pSysName == NULL)
1183             {
1184
1185                 //
1186                 // Reset the current list
1187                 //
1188
1189                 AFSResetSysNameList( *pSysNameListHead);
1190
1191                 *pSysNameListHead = NULL;
1192
1193                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1194             }
1195
1196             RtlZeroMemory( pSysName,
1197                            sizeof( AFSSysNameCB) +
1198                                    SysNameInfo->SysNames[ ulIndex].Length +
1199                                    sizeof( WCHAR));
1200
1201             pSysName->SysName.Length = (USHORT)SysNameInfo->SysNames[ ulIndex].Length;
1202
1203             pSysName->SysName.MaximumLength = pSysName->SysName.Length + sizeof( WCHAR);
1204
1205             pSysName->SysName.Buffer = (WCHAR *)((char *)pSysName + sizeof( AFSSysNameCB));
1206
1207             RtlCopyMemory( pSysName->SysName.Buffer,
1208                            SysNameInfo->SysNames[ ulIndex].String,
1209                            pSysName->SysName.Length);
1210
1211             if( *pSysNameListHead == NULL)
1212             {
1213
1214                 *pSysNameListHead = pSysName;
1215             }
1216             else
1217             {
1218
1219                 (*pSysNameListTail)->fLink = pSysName;
1220             }
1221
1222             *pSysNameListTail = pSysName;
1223
1224             ulIndex++;
1225         }
1226
1227 try_exit:
1228
1229         AFSReleaseResource( pSysNameLock);
1230     }
1231
1232     return ntStatus;
1233 }
1234
1235 void
1236 AFSResetSysNameList( IN AFSSysNameCB *SysNameList)
1237 {
1238
1239     AFSSysNameCB *pNextEntry = NULL, *pCurrentEntry = SysNameList;
1240
1241     while( pCurrentEntry != NULL)
1242     {
1243
1244         pNextEntry = pCurrentEntry->fLink;
1245
1246         ExFreePool( pCurrentEntry);
1247
1248         pCurrentEntry = pNextEntry;
1249     }
1250
1251     return;
1252 }
1253
1254 NTSTATUS
1255 AFSDefaultDispatch( IN PDEVICE_OBJECT DeviceObject,
1256                     IN PIRP Irp)
1257 {
1258
1259     NTSTATUS            ntStatus = STATUS_INVALID_DEVICE_REQUEST;
1260     PIO_STACK_LOCATION  pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1261
1262     AFSCompleteRequest( Irp,
1263                         ntStatus);
1264
1265     return ntStatus;
1266 }
1267
1268 NTSTATUS
1269 AFSSendDeviceIoControl( IN DEVICE_OBJECT *TargetDeviceObject,
1270                         IN ULONG IOControl,
1271                         IN void *InputBuffer,
1272                         IN ULONG InputBufferLength,
1273                         IN OUT void *OutputBuffer,
1274                         IN ULONG OutputBufferLength,
1275                         OUT ULONG *ResultLength)
1276 {
1277
1278     NTSTATUS            ntStatus = STATUS_SUCCESS;
1279     PIRP                pIrp = NULL;
1280     KEVENT              kEvent;
1281     PIO_STACK_LOCATION  pIoStackLocation = NULL;
1282
1283     __Enter
1284     {
1285
1286         //
1287         // Initialize the event
1288         //
1289
1290         KeInitializeEvent( &kEvent,
1291                            SynchronizationEvent,
1292                            FALSE);
1293
1294         //
1295         // Allocate an irp for this request.  This could also come from a
1296         // private pool, for instance.
1297         //
1298
1299         pIrp = IoAllocateIrp( TargetDeviceObject->StackSize,
1300                               FALSE);
1301
1302         if( pIrp == NULL)
1303         {
1304
1305             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1306         }
1307
1308         //
1309         // Build the IRP's main body
1310         //
1311
1312         pIrp->RequestorMode = KernelMode;
1313
1314         //
1315         // Set up the I/O stack location.
1316         //
1317
1318         pIoStackLocation = IoGetNextIrpStackLocation( pIrp);
1319         pIoStackLocation->MajorFunction = IRP_MJ_DEVICE_CONTROL;
1320         pIoStackLocation->DeviceObject = TargetDeviceObject;
1321
1322         pIoStackLocation->Parameters.DeviceIoControl.IoControlCode = IOControl;
1323
1324         pIrp->AssociatedIrp.SystemBuffer = (void *)InputBuffer;
1325         pIoStackLocation->Parameters.DeviceIoControl.InputBufferLength = InputBufferLength;
1326
1327         //
1328         // Set the completion routine.
1329         //
1330
1331         IoSetCompletionRoutine( pIrp,
1332                                 AFSIrpComplete,
1333                                 &kEvent,
1334                                 TRUE,
1335                                 TRUE,
1336                                 TRUE);
1337
1338         //
1339         // Send it to the FSD
1340         //
1341
1342         ntStatus = IoCallDriver( TargetDeviceObject,
1343                                  pIrp);
1344
1345         if( NT_SUCCESS( ntStatus))
1346         {
1347
1348             //
1349             // Wait for the I/O
1350             //
1351
1352             ntStatus = KeWaitForSingleObject( &kEvent,
1353                                               Executive,
1354                                               KernelMode,
1355                                               FALSE,
1356                                               0);
1357
1358             if( NT_SUCCESS( ntStatus))
1359             {
1360
1361                 ntStatus = pIrp->IoStatus.Status;
1362
1363                 if( ResultLength != NULL)
1364                 {
1365                     *ResultLength = (ULONG)pIrp->IoStatus.Information;
1366                 }
1367             }
1368         }
1369
1370 try_exit:
1371
1372         if( pIrp != NULL)
1373         {
1374
1375             if( pIrp->MdlAddress != NULL)
1376             {
1377
1378                 if( FlagOn( pIrp->MdlAddress->MdlFlags, MDL_PAGES_LOCKED))
1379                 {
1380
1381                     MmUnlockPages( pIrp->MdlAddress);
1382                 }
1383
1384                 IoFreeMdl( pIrp->MdlAddress);
1385             }
1386
1387             pIrp->MdlAddress = NULL;
1388
1389             //
1390             // Free the Irp
1391             //
1392
1393             IoFreeIrp( pIrp);
1394         }
1395     }
1396
1397     return ntStatus;
1398 }
1399
1400 NTSTATUS
1401 AFSIrpComplete( IN PDEVICE_OBJECT DeviceObject,
1402                 IN PIRP           Irp,
1403                 IN PVOID          Context)
1404 {
1405
1406     KEVENT *pEvent = (KEVENT *)Context;
1407
1408     KeSetEvent( pEvent,
1409                 0,
1410                 FALSE);
1411
1412     return STATUS_MORE_PROCESSING_REQUIRED;
1413 }
1414
1415 void *
1416 AFSExAllocatePoolWithTag( IN POOL_TYPE  PoolType,
1417                           IN SIZE_T  NumberOfBytes,
1418                           IN ULONG  Tag)
1419 {
1420
1421     AFSDeviceExt *pControlDevExt = NULL;
1422     void *pBuffer = NULL;
1423     BOOLEAN bTimeout = FALSE;
1424     LARGE_INTEGER liTimeout;
1425     NTSTATUS ntStatus;
1426
1427     //
1428     // Attempt to allocation memory from the system.  If the allocation fails
1429     // wait up to 30 seconds for the AFS redirector to free some memory.  As
1430     // long as the wait does not timeout, continue to retry the allocation.
1431     // If the wait does timeout, attempt to allocate one more time in case
1432     // memory was freed by another driver.  Otherwise, fail the request.
1433     //
1434
1435     if ( AFSDeviceObject)
1436     {
1437
1438         pControlDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
1439     }
1440
1441     while( pBuffer == NULL)
1442     {
1443
1444         pBuffer = ExAllocatePoolWithTag( PoolType,
1445                                          NumberOfBytes,
1446                                          Tag);
1447
1448         if( pBuffer == NULL)
1449         {
1450
1451             if ( bTimeout || pControlDevExt == NULL)
1452             {
1453
1454                 AFSDbgLogMsg( 0,
1455                               0,
1456                               "AFSExAllocatePoolWithTag failure Type %08lX Size %08lX Tag %08lX %08lX\n",
1457                               PoolType,
1458                               NumberOfBytes,
1459                               Tag,
1460                               PsGetCurrentThread());
1461
1462                 switch ( Tag ) {
1463
1464                 case AFS_GENERIC_MEMORY_21_TAG:
1465                 case AFS_GENERIC_MEMORY_22_TAG:
1466                     // AFSDumpTraceFiles -- do nothing;
1467                     break;
1468
1469                 default:
1470                     AFSBreakPoint();
1471                 }
1472
1473                 break;
1474             }
1475
1476
1477             //
1478             // Wait up to 30 seconds for a memory deallocation
1479             //
1480
1481             liTimeout.QuadPart = -(30 *AFS_ONE_SECOND);
1482
1483             if( InterlockedIncrement( &pControlDevExt->Specific.Control.WaitingForMemoryCount) == 1)
1484             {
1485                 KeClearEvent( &pControlDevExt->Specific.Control.MemoryAvailableEvent);
1486             }
1487
1488             ntStatus = KeWaitForSingleObject( &pControlDevExt->Specific.Control.MemoryAvailableEvent,
1489                                               Executive,
1490                                               KernelMode,
1491                                               FALSE,
1492                                               &liTimeout);
1493
1494             if( ntStatus == STATUS_TIMEOUT)
1495             {
1496
1497                 bTimeout = TRUE;
1498             }
1499
1500             InterlockedDecrement( &pControlDevExt->Specific.Control.WaitingForMemoryCount);
1501         }
1502     }
1503
1504     return pBuffer;
1505 }
1506
1507 void
1508 AFSExFreePoolWithTag( IN void *Buffer, IN ULONG Tag)
1509 {
1510
1511     AFSDeviceExt *pControlDevExt = NULL;
1512
1513     if ( AFSDeviceObject)
1514     {
1515
1516         pControlDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
1517     }
1518
1519     if ( Tag)
1520     {
1521
1522         ExFreePoolWithTag( Buffer, Tag);
1523     }
1524     else
1525     {
1526
1527         ExFreePool( Buffer);
1528     }
1529
1530     if ( pControlDevExt)
1531     {
1532
1533         KeSetEvent( &pControlDevExt->Specific.Control.MemoryAvailableEvent,
1534                     0,
1535                     FALSE);
1536     }
1537     return;
1538 }
1539
1540 NTSTATUS
1541 AFSShutdownRedirector()
1542 {
1543
1544     NTSTATUS ntStatus = STATUS_SUCCESS;
1545     AFSDeviceExt *pRDRDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1546     AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
1547     LARGE_INTEGER liTimeout;
1548
1549     __Enter
1550     {
1551
1552         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1553                       AFS_TRACE_LEVEL_VERBOSE,
1554                       "%s Shutting down redirector Extent count %08lX Request count %08lX\n",
1555                       __FUNCTION__,
1556                       pControlDevExt->Specific.Control.ExtentCount,
1557                       pControlDevExt->Specific.Control.OutstandingServiceRequestCount);
1558
1559         //
1560         // Set the shutdown flag so the worker is more agressive in tearing down extents
1561         //
1562
1563         SetFlag( pRDRDevExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN);
1564
1565         //
1566         // Wait on any outstanding service requests
1567         //
1568
1569         liTimeout.QuadPart = -(30 *AFS_ONE_SECOND);
1570
1571         ntStatus = KeWaitForSingleObject( &pControlDevExt->Specific.Control.OutstandingServiceRequestEvent,
1572                                           Executive,
1573                                           KernelMode,
1574                                           FALSE,
1575                                           &liTimeout);
1576
1577         if( ntStatus == STATUS_TIMEOUT)
1578         {
1579
1580             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1581                           AFS_TRACE_LEVEL_WARNING,
1582                           "AFSShutdownRedirector Failed to complete all service requests Remaining count %08lX\n",
1583                           pControlDevExt->Specific.Control.OutstandingServiceRequestCount);
1584
1585             try_return( ntStatus = STATUS_UNSUCCESSFUL);
1586         }
1587
1588         AFSProcessQueuedResults( TRUE);
1589
1590         //
1591         // Wait for all extents to be released
1592         //
1593
1594         liTimeout.QuadPart = -(30 *AFS_ONE_SECOND);
1595
1596         ntStatus = KeWaitForSingleObject( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
1597                                           Executive,
1598                                           KernelMode,
1599                                           FALSE,
1600                                           &liTimeout);
1601
1602         if( ntStatus == STATUS_TIMEOUT)
1603         {
1604
1605             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1606                           AFS_TRACE_LEVEL_WARNING,
1607                           "AFSShutdownRedirector Failed to purge all extents Remaining count %08lX\n",
1608                           pControlDevExt->Specific.Control.ExtentCount);
1609
1610             try_return( ntStatus = STATUS_UNSUCCESSFUL);
1611         }
1612
1613         ntStatus = AFSUnloadLibrary( TRUE);
1614
1615         if( !NT_SUCCESS( ntStatus))
1616         {
1617
1618             try_return( ntStatus);
1619         }
1620
1621 try_exit:
1622
1623         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1624                       AFS_TRACE_LEVEL_VERBOSE,
1625                       "%s Completed shut down of redirector Extent count %08lX Request count %08lX Status %08lX\n",
1626                       __FUNCTION__,
1627                       pControlDevExt->Specific.Control.ExtentCount,
1628                       pControlDevExt->Specific.Control.OutstandingServiceRequestCount,
1629                       ntStatus);
1630     }
1631
1632     return ntStatus;
1633 }
1634
1635 //
1636 // Cache manager callback routines
1637 //
1638
1639 BOOLEAN
1640 AFSAcquireFcbForLazyWrite( IN PVOID Fcb,
1641                            IN BOOLEAN Wait)
1642 {
1643
1644     BOOLEAN bStatus = FALSE;
1645     AFSFcb *pFcb = (AFSFcb *)Fcb;
1646     BOOLEAN bReleaseMain = FALSE, bReleasePaging = FALSE;
1647
1648     //
1649     // Try and acquire the Fcb resource
1650     //
1651
1652     AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1653                   AFS_TRACE_LEVEL_VERBOSE,
1654                   "AFSAcquireFcbForLazyWrite Acquiring Fcb %08lX\n",
1655                   Fcb);
1656
1657     AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1658                   AFS_TRACE_LEVEL_VERBOSE,
1659                   "AFSAcquireFcbForLazyWrite Attempt to acquire Fcb lock %08lX SHARED %08lX\n",
1660                   &pFcb->NPFcb->Resource,
1661                   PsGetCurrentThread());
1662
1663     if( AFSAcquireShared( &pFcb->NPFcb->Resource,
1664                           Wait))
1665     {
1666
1667         AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1668                       AFS_TRACE_LEVEL_VERBOSE,
1669                       "AFSAcquireFcbForLazyWrite Acquired Fcb lock %08lX SHARED %08lX\n",
1670                       &pFcb->NPFcb->Resource,
1671                       PsGetCurrentThread());
1672
1673         bReleaseMain = TRUE;
1674
1675         //
1676         // Try and grab the paging
1677         //
1678
1679         AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1680                       AFS_TRACE_LEVEL_VERBOSE,
1681                       "AFSAcquireFcbForLazyWrite Attempt to acquire Fcb PagingIo lock %08lX SHARED %08lX\n",
1682                       &pFcb->NPFcb->PagingResource,
1683                       PsGetCurrentThread());
1684
1685         if( AFSAcquireShared( &pFcb->NPFcb->PagingResource,
1686                               Wait))
1687         {
1688
1689             AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1690                           AFS_TRACE_LEVEL_VERBOSE,
1691                           "AFSAcquireFcbForLazyWrite Acquired Fcb PagingIo lock %08lX SHARED %08lX\n",
1692                           &pFcb->NPFcb->PagingResource,
1693                           PsGetCurrentThread());
1694
1695             bReleasePaging = TRUE;
1696
1697             //
1698             // All is well ...
1699             //
1700
1701             bStatus = TRUE;
1702
1703             IoSetTopLevelIrp( (PIRP)FSRTL_CACHE_TOP_LEVEL_IRP);
1704         }
1705     }
1706
1707     if( !bStatus)
1708     {
1709
1710         if( bReleaseMain)
1711         {
1712
1713             AFSReleaseResource( &pFcb->NPFcb->Resource);
1714         }
1715
1716         if( bReleasePaging)
1717         {
1718
1719             AFSReleaseResource( &pFcb->NPFcb->PagingResource);
1720         }
1721     }
1722
1723     return bStatus;
1724 }
1725
1726 VOID
1727 AFSReleaseFcbFromLazyWrite( IN PVOID Fcb)
1728 {
1729
1730     AFSFcb *pFcb = (AFSFcb *)Fcb;
1731
1732     AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1733                   AFS_TRACE_LEVEL_VERBOSE,
1734                   "AFSReleaseFcbFromLazyWrite Releasing Fcb %08lX\n",
1735                   Fcb);
1736
1737     IoSetTopLevelIrp( NULL);
1738
1739     AFSReleaseResource( &pFcb->NPFcb->PagingResource);
1740
1741     AFSReleaseResource( &pFcb->NPFcb->Resource);
1742
1743     return;
1744 }
1745
1746 BOOLEAN
1747 AFSAcquireFcbForReadAhead( IN PVOID Fcb,
1748                            IN BOOLEAN Wait)
1749 {
1750
1751     BOOLEAN bStatus = FALSE;
1752     AFSFcb *pFcb = (AFSFcb *)Fcb;
1753
1754     AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1755                   AFS_TRACE_LEVEL_VERBOSE,
1756                   "AFSAcquireFcbForReadAhead Attempt to acquire Fcb lock %08lX SHARED %08lX\n",
1757                   &pFcb->NPFcb->Resource,
1758                   PsGetCurrentThread());
1759
1760     if( AFSAcquireShared( &pFcb->NPFcb->Resource,
1761                           Wait))
1762     {
1763
1764         AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1765                       AFS_TRACE_LEVEL_VERBOSE,
1766                       "AFSAcquireFcbForReadAhead Acquired Fcb lock %08lX SHARED %08lX\n",
1767                       &pFcb->NPFcb->Resource,
1768                       PsGetCurrentThread());
1769
1770         bStatus = TRUE;
1771
1772         IoSetTopLevelIrp( (PIRP)FSRTL_CACHE_TOP_LEVEL_IRP);
1773     }
1774
1775     return bStatus;
1776 }
1777
1778 VOID
1779 AFSReleaseFcbFromReadAhead( IN PVOID Fcb)
1780 {
1781
1782     AFSFcb *pFcb = (AFSFcb *)Fcb;
1783
1784     IoSetTopLevelIrp( NULL);
1785
1786     AFSReleaseResource( &pFcb->NPFcb->Resource);
1787
1788     return;
1789 }
1790
1791 NTSTATUS
1792 AFSGetCallerSID( OUT UNICODE_STRING *SIDString, OUT BOOLEAN *pbImpersonation)
1793 {
1794
1795     NTSTATUS ntStatus = STATUS_SUCCESS;
1796     PACCESS_TOKEN hToken = NULL;
1797     TOKEN_USER *pTokenInfo = NULL;
1798     BOOLEAN bCopyOnOpen = FALSE;
1799     BOOLEAN bEffectiveOnly = FALSE;
1800     BOOLEAN bPrimaryToken = FALSE;
1801     SECURITY_IMPERSONATION_LEVEL stImpersonationLevel;
1802     UNICODE_STRING uniSIDString;
1803
1804     __Enter
1805     {
1806
1807         hToken = PsReferenceImpersonationToken( PsGetCurrentThread(),
1808                                                 &bCopyOnOpen,
1809                                                 &bEffectiveOnly,
1810                                                 &stImpersonationLevel);
1811
1812         if( hToken == NULL)
1813         {
1814
1815             hToken = PsReferencePrimaryToken( PsGetCurrentProcess());
1816
1817             if( hToken == NULL)
1818             {
1819
1820                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1821                               AFS_TRACE_LEVEL_ERROR,
1822                               "AFSGetCallerSID Failed to retrieve impersonation or primary token\n");
1823
1824                 try_return( ntStatus);
1825             }
1826
1827             bPrimaryToken = TRUE;
1828         }
1829
1830         ntStatus = SeQueryInformationToken( hToken,
1831                                             TokenUser,
1832                                             (PVOID *)&pTokenInfo);
1833
1834         if( !NT_SUCCESS( ntStatus))
1835         {
1836
1837             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1838                           AFS_TRACE_LEVEL_ERROR,
1839                           "AFSGetCallerSID Failed to retrieve information Status %08lX\n", ntStatus);
1840
1841             try_return( ntStatus);
1842         }
1843
1844         uniSIDString.Length = 0;
1845         uniSIDString.MaximumLength = 0;
1846         uniSIDString.Buffer = NULL;
1847
1848         ntStatus = RtlConvertSidToUnicodeString( &uniSIDString,
1849                                                  pTokenInfo->User.Sid,
1850                                                  TRUE);
1851
1852         if( !NT_SUCCESS( ntStatus))
1853         {
1854
1855             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1856                           AFS_TRACE_LEVEL_ERROR,
1857                           "AFSGetCallerSID Failed to convert sid to string Status %08lX\n", ntStatus);
1858
1859             try_return( ntStatus);
1860         }
1861
1862         *SIDString = uniSIDString;
1863
1864         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING | AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
1865                       AFS_TRACE_LEVEL_VERBOSE_2,
1866                       "AFSGetCallerSID Successfully retrieved SID %wZ\n",
1867                       SIDString);
1868
1869         if ( bPrimaryToken == FALSE &&
1870              pbImpersonation)
1871         {
1872             *pbImpersonation = TRUE;
1873         }
1874
1875 try_exit:
1876
1877         if( hToken != NULL)
1878         {
1879             if( bPrimaryToken)
1880             {
1881                 PsDereferencePrimaryToken( hToken);
1882             }
1883             else
1884             {
1885                 PsDereferenceImpersonationToken( hToken);
1886             }
1887         }
1888
1889         if( pTokenInfo != NULL)
1890         {
1891             ExFreePool( pTokenInfo);    // Allocated by SeQueryInformationToken
1892         }
1893     }
1894
1895     return ntStatus;
1896 }
1897
1898 ULONG
1899 AFSGetSessionId( IN HANDLE ProcessId, OUT BOOLEAN *pbImpersonation)
1900 {
1901
1902     NTSTATUS ntStatus = STATUS_SUCCESS;
1903     PACCESS_TOKEN hToken = NULL;
1904     ULONG ulSessionId = (ULONG)-1;
1905     BOOLEAN bCopyOnOpen = FALSE;
1906     BOOLEAN bEffectiveOnly = FALSE;
1907     BOOLEAN bPrimaryToken = FALSE;
1908     SECURITY_IMPERSONATION_LEVEL stImpersonationLevel;
1909
1910     __Enter
1911     {
1912
1913         hToken = PsReferenceImpersonationToken( PsGetCurrentThread(),
1914                                                 &bCopyOnOpen,
1915                                                 &bEffectiveOnly,
1916                                                 &stImpersonationLevel);
1917
1918         if( hToken == NULL)
1919         {
1920
1921             hToken = PsReferencePrimaryToken( PsGetCurrentProcess());
1922
1923             if( hToken == NULL)
1924             {
1925
1926                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1927                               AFS_TRACE_LEVEL_ERROR,
1928                               "AFSGetSessionId Failed to retrieve impersonation or primary token\n");
1929
1930                 try_return( ntStatus);
1931             }
1932
1933             bPrimaryToken = TRUE;
1934         }
1935
1936         ntStatus = SeQueryInformationToken( hToken,
1937                                             TokenSessionId,
1938                                             (PVOID *)&ulSessionId);
1939
1940         if( !NT_SUCCESS( ntStatus))
1941         {
1942             ulSessionId = (ULONG)-1;
1943
1944             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1945                           AFS_TRACE_LEVEL_ERROR,
1946                           "AFSGetSessionId Failed to retrieve session id Status %08lX\n",
1947                           ntStatus);
1948
1949             try_return( ntStatus);
1950         }
1951
1952         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING | AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
1953                       AFS_TRACE_LEVEL_VERBOSE_2,
1954                       "AFSGetSessionId found %08lX\n",
1955                       ulSessionId);
1956
1957         if ( bPrimaryToken == FALSE &&
1958              pbImpersonation)
1959         {
1960             *pbImpersonation = TRUE;
1961         }
1962
1963 try_exit:
1964
1965         if( hToken != NULL)
1966         {
1967             if( bPrimaryToken)
1968             {
1969                 PsDereferencePrimaryToken( hToken);
1970             }
1971             else
1972             {
1973                 PsDereferenceImpersonationToken( hToken);
1974             }
1975         }
1976     }
1977
1978     return ulSessionId;
1979 }
1980
1981 NTSTATUS
1982 AFSCheckThreadDacl( OUT GUID *AuthGroup)
1983 {
1984
1985     NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
1986     ULONG idx;
1987     PACCESS_TOKEN token = NULL;
1988     PTOKEN_DEFAULT_DACL defDacl = NULL;
1989     PACE_HEADER ace;
1990     PACCESS_ALLOWED_ACE adace;
1991     BOOLEAN bCopyOnOpen = FALSE, bEffectiveOnly = FALSE;
1992     SECURITY_IMPERSONATION_LEVEL stImpersonationLevel;
1993     BOOLEAN bLocatedACE = FALSE;
1994
1995     __Enter
1996     {
1997
1998         token = PsReferenceImpersonationToken( PsGetCurrentThread(),
1999                                                &bCopyOnOpen,
2000                                                &bEffectiveOnly,
2001                                                &stImpersonationLevel);
2002
2003         if( token == NULL)
2004         {
2005            try_return( ntStatus);
2006         }
2007
2008         ntStatus = SeQueryInformationToken( token,
2009                                             TokenDefaultDacl,
2010                                             (PVOID *)&defDacl);
2011
2012         if( ntStatus != STATUS_SUCCESS)
2013         {
2014            try_return( ntStatus);
2015         }
2016
2017         // scan through all ACEs in the DACL
2018         for (idx = 0, ace = (PACE_HEADER)((char *)defDacl->DefaultDacl + sizeof(ACL)); idx < defDacl->DefaultDacl->AceCount; idx++)
2019         {
2020            if (ace->AceType == ACCESS_ALLOWED_ACE_TYPE)
2021            {
2022               adace = (PACCESS_ALLOWED_ACE)ace;
2023
2024               if (adace->Header.AceSize == (FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) + AFS_DACL_SID_LENGTH))
2025               {
2026                  if (RtlCompareMemory( RtlSubAuthoritySid((PSID)&adace->SidStart, 0), &AFSSidGuid, sizeof(GUID)) == sizeof(GUID))
2027                  {
2028
2029                     RtlCopyMemory( AuthGroup,
2030                                    RtlSubAuthoritySid((PSID)&adace->SidStart, 4),
2031                                    sizeof( GUID));
2032
2033                     bLocatedACE = TRUE;
2034
2035                     break;
2036                  }
2037               }
2038            }
2039
2040            // go to next ace
2041            ace = (PACE_HEADER)((char *)ace + ace->AceSize);
2042         }
2043
2044 try_exit:
2045
2046         if( token != NULL)
2047         {
2048             PsDereferenceImpersonationToken( token);
2049         }
2050
2051         if (defDacl != NULL)
2052         {
2053            ExFreePool(defDacl);
2054         }
2055
2056         if( !bLocatedACE)
2057         {
2058             ntStatus = STATUS_UNSUCCESSFUL;
2059         }
2060     }
2061
2062     return ntStatus;
2063 }
2064
2065 NTSTATUS
2066 AFSProcessSetProcessDacl( IN AFSProcessCB *ProcessCB)
2067 {
2068
2069     PTOKEN_DEFAULT_DACL defDacl = NULL;
2070     HANDLE hToken = NULL;
2071     PACE_HEADER ace = NULL;
2072     SID_IDENTIFIER_AUTHORITY sia = SECURITY_NT_AUTHORITY;
2073     PACCESS_ALLOWED_ACE aaace;
2074     ULONG bytesNeeded;
2075     ULONG bytesReturned;
2076     ULONG idx;
2077     PSID psid;
2078     NTSTATUS ntStatus = STATUS_SUCCESS;
2079
2080     __Enter
2081     {
2082
2083         ntStatus = ZwOpenProcessTokenEx( NtCurrentProcess(),
2084                                          GENERIC_ALL,
2085                                          OBJ_KERNEL_HANDLE,
2086                                          &hToken);
2087
2088         if( !NT_SUCCESS( ntStatus))
2089         {
2090             try_return( ntStatus);
2091         }
2092
2093         // get the size of the current DACL
2094         ntStatus = ZwQueryInformationToken( hToken,
2095                                             TokenDefaultDacl,
2096                                             NULL,
2097                                             0,
2098                                             &bytesNeeded);
2099
2100         // if we failed to get the buffer size needed
2101         if ((ntStatus != STATUS_SUCCESS) && (ntStatus != STATUS_BUFFER_TOO_SMALL))
2102         {
2103             try_return( ntStatus);
2104         }
2105
2106         // tack on enough space for our ACE if we need to add it...
2107         bytesNeeded += FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) + AFS_DACL_SID_LENGTH;
2108
2109         // allocate space for the DACL
2110         defDacl = (PTOKEN_DEFAULT_DACL)ExAllocatePoolWithTag( PagedPool, bytesNeeded, AFS_GENERIC_MEMORY_26_TAG);
2111
2112         if (defDacl == NULL)
2113         {
2114            try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2115         }
2116
2117         // get the DACL
2118         ntStatus = ZwQueryInformationToken( hToken,
2119                                             TokenDefaultDacl,
2120                                             defDacl,
2121                                             bytesNeeded,
2122                                             &bytesReturned);
2123
2124         if( ntStatus != STATUS_SUCCESS)
2125         {
2126             try_return( ntStatus);
2127         }
2128
2129         // scan through DACL to see if we have the SID set already...
2130         ace = (PACE_HEADER)((char *)defDacl->DefaultDacl + sizeof(ACL));
2131         for (idx = 0; idx < defDacl->DefaultDacl->AceCount; idx++)
2132         {
2133             if (ace->AceType == ACCESS_ALLOWED_ACE_TYPE)
2134             {
2135                 aaace = (PACCESS_ALLOWED_ACE)ace;
2136
2137                 if (aaace->Header.AceSize == (FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) + AFS_DACL_SID_LENGTH))
2138                 {
2139                     // if the GUID part matches
2140                     if( RtlCompareMemory( RtlSubAuthoritySid((PSID)&aaace->SidStart, 0),
2141                                           &AFSSidGuid,
2142                                           sizeof(GUID)) == sizeof(GUID))
2143                     {
2144
2145                         if ( RtlCompareMemory( RtlSubAuthoritySid((PSID)&aaace->SidStart, 4),
2146                                                ProcessCB->ActiveAuthGroup,
2147                                                sizeof( GUID)) != sizeof( GUID))
2148                         {
2149
2150                             RtlCopyMemory( RtlSubAuthoritySid((PSID)&aaace->SidStart, 4),
2151                                            ProcessCB->ActiveAuthGroup,
2152                                            sizeof( GUID));
2153
2154                             if( AFSSetInformationToken != NULL)
2155                             {
2156                                 ntStatus = AFSSetInformationToken( hToken,
2157                                                                    TokenDefaultDacl,
2158                                                                    defDacl,
2159                                                                    bytesReturned);
2160                             }
2161                         }
2162
2163                         try_return( ntStatus);
2164                     }
2165                 }
2166             }
2167
2168             // go to next ace
2169             ace = (PACE_HEADER)((char *)ace + ace->AceSize);
2170         }
2171
2172         //
2173         // if we made it here we need to add a new ACE to the DACL
2174         //
2175
2176         aaace = (ACCESS_ALLOWED_ACE *)ace;
2177         aaace->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
2178         aaace->Header.AceFlags = 0;
2179         aaace->Mask = GENERIC_ALL;
2180         psid = (PSID)&aaace->SidStart;
2181         RtlInitializeSid( psid, &sia, 8);
2182
2183         RtlCopyMemory( RtlSubAuthoritySid(psid, 0),
2184                        &AFSSidGuid,
2185                        sizeof(GUID));
2186
2187         RtlCopyMemory( RtlSubAuthoritySid(psid, 4),
2188                        ProcessCB->ActiveAuthGroup,
2189                        sizeof( GUID));
2190
2191         aaace->Header.AceSize = (USHORT)(FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) + RtlLengthSid( psid));
2192
2193         defDacl->DefaultDacl->AclSize += aaace->Header.AceSize;
2194         defDacl->DefaultDacl->AceCount++;
2195
2196         if( AFSSetInformationToken != NULL)
2197         {
2198             ntStatus = AFSSetInformationToken( hToken,
2199                                               TokenDefaultDacl,
2200                                               defDacl,
2201                                               defDacl->DefaultDacl->AclSize + sizeof(PTOKEN_DEFAULT_DACL));
2202         }
2203
2204 try_exit:
2205
2206         if( hToken != NULL)
2207         {
2208             ZwClose( hToken);
2209         }
2210
2211         if (defDacl != NULL)
2212         {
2213            ExFreePool( defDacl);
2214         }
2215     }
2216
2217     return ntStatus;
2218 }
2219
2220