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