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