bd01b565607c614ca0cf8548bb6c2e16f62b3fcd
[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                            NotificationEvent,
725                            FALSE);
726
727         KeInitializeEvent( &pDeviceExt->Specific.Control.CommServiceCB.IrpPoolHasReleaseEntries,
728                            NotificationEvent,
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         if( BooleanFlagOn( AFSDebugFlags, AFS_DBG_BUGCHECK_EXCEPTION))
1321         {
1322
1323             KeBugCheck( (ULONG)-2);
1324         }
1325         else
1326         {
1327
1328             AFSDbgLogMsg( 0,
1329                           0,
1330                           "AFSExAllocatePoolWithTag failure Type %08lX Size %08lX Tag %08lX %08lX\n",
1331                           PoolType,
1332                           NumberOfBytes,
1333                           Tag,
1334                           PsGetCurrentThread());
1335
1336             switch ( Tag ) {
1337
1338             case AFS_GENERIC_MEMORY_21_TAG:
1339             case AFS_GENERIC_MEMORY_22_TAG:
1340                 // AFSDumpTraceFiles -- do nothing;
1341                 break;
1342
1343             default:
1344                 AFSBreakPoint();
1345             }
1346         }
1347     }
1348
1349     return pBuffer;
1350 }
1351
1352 void
1353 AFSExFreePool( IN void *Buffer)
1354 {
1355
1356     ExFreePool( Buffer);
1357
1358     return;
1359 }
1360
1361 NTSTATUS
1362 AFSShutdownRedirector()
1363 {
1364
1365     NTSTATUS ntStatus = STATUS_SUCCESS;
1366     AFSDeviceExt *pRDRDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1367     AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
1368     LARGE_INTEGER liTimeout;
1369
1370     __Enter
1371     {
1372
1373         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1374                       AFS_TRACE_LEVEL_VERBOSE,
1375                       "%s Shutting down redirector Extent count %08lX Request count %08lX\n",
1376                                 __FUNCTION__,
1377                                 pControlDevExt->Specific.Control.ExtentCount,
1378                                 pControlDevExt->Specific.Control.OutstandingServiceRequestCount);
1379
1380         //
1381         // Set the shutdown flag so the worker is more agressive in tearing down extents
1382         //
1383
1384         SetFlag( pRDRDevExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN);
1385
1386         //
1387         // Wait on any outstanding service requests
1388         //
1389
1390         liTimeout.QuadPart = -(30 *AFS_ONE_SECOND);
1391
1392         ntStatus = KeWaitForSingleObject( &pControlDevExt->Specific.Control.OutstandingServiceRequestEvent,
1393                                           Executive,
1394                                           KernelMode,
1395                                           FALSE,
1396                                           &liTimeout);
1397
1398         if( ntStatus == STATUS_TIMEOUT)
1399         {
1400
1401             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1402                           AFS_TRACE_LEVEL_WARNING,
1403                               "AFSShutdownRedirector Failed to complete all service requests Remaining count %08lX\n",
1404                                                     pControlDevExt->Specific.Control.OutstandingServiceRequestCount);
1405
1406             try_return( ntStatus = STATUS_UNSUCCESSFUL);
1407         }
1408
1409         AFSProcessQueuedResults( TRUE);
1410
1411         //
1412         // Wait for all extents to be released
1413         //
1414
1415         liTimeout.QuadPart = -(30 *AFS_ONE_SECOND);
1416
1417         ntStatus = KeWaitForSingleObject( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
1418                                           Executive,
1419                                           KernelMode,
1420                                           FALSE,
1421                                           &liTimeout);
1422
1423         if( ntStatus == STATUS_TIMEOUT)
1424         {
1425
1426             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1427                           AFS_TRACE_LEVEL_WARNING,
1428                               "AFSShutdownRedirector Failed to purge all extents Remaining count %08lX\n",
1429                                                     pControlDevExt->Specific.Control.ExtentCount);
1430
1431             try_return( ntStatus = STATUS_UNSUCCESSFUL);
1432         }
1433
1434         ntStatus = AFSUnloadLibrary( TRUE);
1435
1436         if( !NT_SUCCESS( ntStatus))
1437         {
1438
1439             try_return( ntStatus);
1440         }
1441
1442 try_exit:
1443
1444         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1445                       AFS_TRACE_LEVEL_VERBOSE,
1446                       "%s Completed shut down of redirector Extent count %08lX Request count %08lX Status %08lX\n",
1447                                 __FUNCTION__,
1448                                 pControlDevExt->Specific.Control.ExtentCount,
1449                                 pControlDevExt->Specific.Control.OutstandingServiceRequestCount,
1450                                 ntStatus);
1451     }
1452
1453     return ntStatus;
1454 }
1455
1456 //
1457 // Cache manager callback routines
1458 //
1459
1460 BOOLEAN
1461 AFSAcquireFcbForLazyWrite( IN PVOID Fcb,
1462                            IN BOOLEAN Wait)
1463 {
1464
1465     BOOLEAN bStatus = FALSE;
1466     AFSFcb *pFcb = (AFSFcb *)Fcb;
1467     BOOLEAN bReleaseMain = FALSE, bReleasePaging = FALSE;
1468
1469     //
1470     // Try and acquire the Fcb resource
1471     //
1472
1473     AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1474                   AFS_TRACE_LEVEL_VERBOSE,
1475                   "AFSAcquireFcbForLazyWrite Acquiring Fcb %08lX\n",
1476                   Fcb);
1477
1478     ASSERT( NULL == pFcb->Specific.File.LazyWriterThread);
1479
1480     pFcb->Specific.File.LazyWriterThread = PsGetCurrentThread();
1481
1482     AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1483                   AFS_TRACE_LEVEL_VERBOSE,
1484                   "AFSAcquireFcbForLazyWrite Attempt to acquire Fcb lock %08lX SHARED %08lX\n",
1485                   &pFcb->NPFcb->Resource,
1486                   PsGetCurrentThread());
1487
1488     if( AFSAcquireShared( &pFcb->NPFcb->Resource,
1489                           Wait))
1490     {
1491
1492         AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1493                       AFS_TRACE_LEVEL_VERBOSE,
1494                       "AFSAcquireFcbForLazyWrite Acquired Fcb lock %08lX SHARED %08lX\n",
1495                       &pFcb->NPFcb->Resource,
1496                       PsGetCurrentThread());
1497
1498         bReleaseMain = TRUE;
1499
1500         //
1501         // Try and grab the paging
1502         //
1503
1504         AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1505                       AFS_TRACE_LEVEL_VERBOSE,
1506                       "AFSAcquireFcbForLazyWrite Attempt to acquire Fcb PagingIo lock %08lX SHARED %08lX\n",
1507                       &pFcb->NPFcb->PagingResource,
1508                       PsGetCurrentThread());
1509
1510         if( AFSAcquireShared( &pFcb->NPFcb->PagingResource,
1511                               Wait))
1512         {
1513
1514             AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1515                           AFS_TRACE_LEVEL_VERBOSE,
1516                           "AFSAcquireFcbForLazyWrite Acquired Fcb PagingIo lock %08lX SHARED %08lX\n",
1517                           &pFcb->NPFcb->PagingResource,
1518                           PsGetCurrentThread());
1519
1520             bReleasePaging = TRUE;
1521
1522             //
1523             // All is well ...
1524             //
1525
1526             bStatus = TRUE;
1527
1528             IoSetTopLevelIrp( (PIRP)FSRTL_CACHE_TOP_LEVEL_IRP);
1529         }
1530     }
1531
1532     if( !bStatus)
1533     {
1534
1535         if( bReleaseMain)
1536         {
1537
1538             AFSReleaseResource( &pFcb->NPFcb->Resource);
1539         }
1540
1541         if( bReleasePaging)
1542         {
1543
1544             AFSReleaseResource( &pFcb->NPFcb->PagingResource);
1545         }
1546     }
1547
1548     return bStatus;
1549 }
1550
1551 VOID
1552 AFSReleaseFcbFromLazyWrite( IN PVOID Fcb)
1553 {
1554
1555     AFSFcb *pFcb = (AFSFcb *)Fcb;
1556
1557     AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1558                   AFS_TRACE_LEVEL_VERBOSE,
1559                   "AFSReleaseFcbFromLazyWrite Releasing Fcb %08lX\n",
1560                   Fcb);
1561
1562     IoSetTopLevelIrp( NULL);
1563
1564     ASSERT( PsGetCurrentThread() == pFcb->Specific.File.LazyWriterThread);
1565
1566     pFcb->Specific.File.LazyWriterThread = NULL;
1567
1568
1569     AFSReleaseResource( &pFcb->NPFcb->PagingResource);
1570
1571     AFSReleaseResource( &pFcb->NPFcb->Resource);
1572
1573     return;
1574 }
1575
1576 BOOLEAN
1577 AFSAcquireFcbForReadAhead( IN PVOID Fcb,
1578                            IN BOOLEAN Wait)
1579 {
1580
1581     BOOLEAN bStatus = FALSE;
1582     AFSFcb *pFcb = (AFSFcb *)Fcb;
1583
1584     AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1585                   AFS_TRACE_LEVEL_VERBOSE,
1586                   "AFSAcquireFcbForReadAhead Attempt to acquire Fcb lock %08lX SHARED %08lX\n",
1587                   &pFcb->NPFcb->Resource,
1588                   PsGetCurrentThread());
1589
1590     if( AFSAcquireShared( &pFcb->NPFcb->Resource,
1591                           Wait))
1592     {
1593
1594         AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1595                       AFS_TRACE_LEVEL_VERBOSE,
1596                       "AFSAcquireFcbForReadAhead Acquired Fcb lock %08lX SHARED %08lX\n",
1597                       &pFcb->NPFcb->Resource,
1598                       PsGetCurrentThread());
1599
1600         bStatus = TRUE;
1601
1602         IoSetTopLevelIrp( (PIRP)FSRTL_CACHE_TOP_LEVEL_IRP);
1603     }
1604
1605     return bStatus;
1606 }
1607
1608 VOID
1609 AFSReleaseFcbFromReadAhead( IN PVOID Fcb)
1610 {
1611
1612     AFSFcb *pFcb = (AFSFcb *)Fcb;
1613
1614     IoSetTopLevelIrp( NULL);
1615
1616     AFSReleaseResource( &pFcb->NPFcb->Resource);
1617
1618     return;
1619 }
1620
1621 NTSTATUS
1622 AFSGetCallerSID( OUT UNICODE_STRING *SIDString, OUT BOOLEAN *pbImpersonation)
1623 {
1624
1625     NTSTATUS ntStatus = STATUS_SUCCESS;
1626     PACCESS_TOKEN hToken = NULL;
1627     TOKEN_USER *pTokenInfo = NULL;
1628     BOOLEAN bCopyOnOpen = FALSE;
1629     BOOLEAN bEffectiveOnly = FALSE;
1630     BOOLEAN bPrimaryToken = FALSE;
1631     SECURITY_IMPERSONATION_LEVEL stImpersonationLevel;
1632     UNICODE_STRING uniSIDString;
1633
1634     __Enter
1635     {
1636
1637         hToken = PsReferenceImpersonationToken( PsGetCurrentThread(),
1638                                                 &bCopyOnOpen,
1639                                                 &bEffectiveOnly,
1640                                                 &stImpersonationLevel);
1641
1642         if( hToken == NULL)
1643         {
1644
1645             hToken = PsReferencePrimaryToken( PsGetCurrentProcess());
1646
1647             if( hToken == NULL)
1648             {
1649
1650                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1651                               AFS_TRACE_LEVEL_ERROR,
1652                               "AFSGetCallerSID Failed to retrieve impersonation or primary token\n");
1653
1654                 try_return( ntStatus);
1655             }
1656
1657             bPrimaryToken = TRUE;
1658         }
1659
1660         ntStatus = SeQueryInformationToken( hToken,
1661                                             TokenUser,
1662                                             (PVOID *)&pTokenInfo);
1663
1664         if( !NT_SUCCESS( ntStatus))
1665         {
1666
1667             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1668                           AFS_TRACE_LEVEL_ERROR,
1669                           "AFSGetCallerSID Failed to retrieve information Status %08lX\n", ntStatus);
1670
1671             try_return( ntStatus);
1672         }
1673
1674         uniSIDString.Length = 0;
1675         uniSIDString.MaximumLength = 0;
1676         uniSIDString.Buffer = NULL;
1677
1678         ntStatus = RtlConvertSidToUnicodeString( &uniSIDString,
1679                                                  pTokenInfo->User.Sid,
1680                                                  TRUE);
1681
1682         if( !NT_SUCCESS( ntStatus))
1683         {
1684
1685             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1686                           AFS_TRACE_LEVEL_ERROR,
1687                           "AFSGetCallerSID Failed to convert sid to string Status %08lX\n", ntStatus);
1688
1689             try_return( ntStatus);
1690         }
1691
1692         *SIDString = uniSIDString;
1693
1694         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING | AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
1695                       AFS_TRACE_LEVEL_VERBOSE_2,
1696                       "AFSGetCallerSID Successfully retrieved SID %wZ\n",
1697                       SIDString);
1698
1699         if ( bPrimaryToken == FALSE &&
1700              pbImpersonation)
1701         {
1702             *pbImpersonation = TRUE;
1703         }
1704
1705 try_exit:
1706
1707         if( hToken != NULL)
1708         {
1709             if( bPrimaryToken)
1710             {
1711                 PsDereferencePrimaryToken( hToken);
1712             }
1713             else
1714             {
1715                 PsDereferenceImpersonationToken( hToken);
1716             }
1717         }
1718
1719         if( pTokenInfo != NULL)
1720         {
1721             AFSExFreePool( pTokenInfo);
1722         }
1723     }
1724
1725     return ntStatus;
1726 }
1727
1728 ULONG
1729 AFSGetSessionId( IN HANDLE ProcessId, OUT BOOLEAN *pbImpersonation)
1730 {
1731
1732     NTSTATUS ntStatus = STATUS_SUCCESS;
1733     PACCESS_TOKEN hToken = NULL;
1734     ULONG ulSessionId = (ULONG)-1;
1735     BOOLEAN bCopyOnOpen = FALSE;
1736     BOOLEAN bEffectiveOnly = FALSE;
1737     BOOLEAN bPrimaryToken = FALSE;
1738     SECURITY_IMPERSONATION_LEVEL stImpersonationLevel;
1739
1740     __Enter
1741     {
1742
1743         hToken = PsReferenceImpersonationToken( PsGetCurrentThread(),
1744                                                 &bCopyOnOpen,
1745                                                 &bEffectiveOnly,
1746                                                 &stImpersonationLevel);
1747
1748         if( hToken == NULL)
1749         {
1750
1751             hToken = PsReferencePrimaryToken( PsGetCurrentProcess());
1752
1753             if( hToken == NULL)
1754             {
1755
1756                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1757                               AFS_TRACE_LEVEL_ERROR,
1758                               "AFSGetSessionId Failed to retrieve impersonation or primary token\n");
1759
1760                 try_return( ntStatus);
1761             }
1762
1763             bPrimaryToken = TRUE;
1764         }
1765
1766         ntStatus = SeQueryInformationToken( hToken,
1767                                             TokenSessionId,
1768                                             (PVOID *)&ulSessionId);
1769
1770         if( !NT_SUCCESS( ntStatus))
1771         {
1772             ulSessionId = (ULONG)-1;
1773
1774             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1775                           AFS_TRACE_LEVEL_ERROR,
1776                           "AFSGetSessionId Failed to retrieve session id Status %08lX\n",
1777                           ntStatus);
1778
1779             try_return( ntStatus);
1780         }
1781
1782         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING | AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
1783                       AFS_TRACE_LEVEL_VERBOSE_2,
1784                       "AFSGetSessionId found %08lX\n",
1785                       ulSessionId);
1786
1787         if ( bPrimaryToken == FALSE &&
1788              pbImpersonation)
1789         {
1790             *pbImpersonation = TRUE;
1791         }
1792
1793 try_exit:
1794
1795         if( hToken != NULL)
1796         {
1797             if( bPrimaryToken)
1798             {
1799                 PsDereferencePrimaryToken( hToken);
1800             }
1801             else
1802             {
1803                 PsDereferenceImpersonationToken( hToken);
1804             }
1805         }
1806     }
1807
1808     return ulSessionId;
1809 }
1810
1811 NTSTATUS
1812 AFSCheckThreadDacl( OUT GUID *AuthGroup)
1813 {
1814
1815     NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
1816     ULONG idx;
1817     PACCESS_TOKEN token = NULL;
1818     PTOKEN_DEFAULT_DACL defDacl = NULL;
1819     PACE_HEADER ace;
1820     PACCESS_ALLOWED_ACE adace;
1821     BOOLEAN bCopyOnOpen = FALSE, bEffectiveOnly = FALSE;
1822     SECURITY_IMPERSONATION_LEVEL stImpersonationLevel;
1823     BOOLEAN bLocatedACE = FALSE;
1824
1825     __Enter
1826     {
1827
1828         token = PsReferenceImpersonationToken( PsGetCurrentThread(),
1829                                                &bCopyOnOpen,
1830                                                &bEffectiveOnly,
1831                                                &stImpersonationLevel);
1832
1833         if( token == NULL)
1834         {
1835            try_return( ntStatus);
1836         }
1837
1838         ntStatus = SeQueryInformationToken( token,
1839                                             TokenDefaultDacl,
1840                                             (PVOID *)&defDacl);
1841
1842         if( ntStatus != STATUS_SUCCESS)
1843         {
1844            try_return( ntStatus);
1845         }
1846
1847         // scan through all ACEs in the DACL
1848         for (idx = 0, ace = (PACE_HEADER)((char *)defDacl->DefaultDacl + sizeof(ACL)); idx < defDacl->DefaultDacl->AceCount; idx++)
1849         {
1850            if (ace->AceType == ACCESS_ALLOWED_ACE_TYPE)
1851            {
1852               adace = (PACCESS_ALLOWED_ACE)ace;
1853
1854               if (adace->Header.AceSize == (FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) + AFS_DACL_SID_LENGTH))
1855               {
1856                  if (RtlCompareMemory( RtlSubAuthoritySid((PSID)&adace->SidStart, 0), &AFSSidGuid, sizeof(GUID)) == sizeof(GUID))
1857                  {
1858
1859                     RtlCopyMemory( AuthGroup,
1860                                    RtlSubAuthoritySid((PSID)&adace->SidStart, 4),
1861                                    sizeof( GUID));
1862
1863                     bLocatedACE = TRUE;
1864
1865                     break;
1866                  }
1867               }
1868            }
1869
1870            // go to next ace
1871            ace = (PACE_HEADER)((char *)ace + ace->AceSize);
1872         }
1873
1874 try_exit:
1875
1876         if( token != NULL)
1877         {
1878             PsDereferenceImpersonationToken( token);
1879         }
1880
1881         if (defDacl != NULL)
1882         {
1883            ExFreePool(defDacl);
1884         }
1885
1886         if( !bLocatedACE)
1887         {
1888             ntStatus = STATUS_UNSUCCESSFUL;
1889         }
1890     }
1891
1892     return ntStatus;
1893 }
1894
1895 NTSTATUS
1896 AFSProcessSetProcessDacl( IN AFSProcessCB *ProcessCB)
1897 {
1898
1899     PTOKEN_DEFAULT_DACL defDacl = NULL;
1900     HANDLE hToken = NULL;
1901     PACE_HEADER ace = NULL;
1902     SID_IDENTIFIER_AUTHORITY sia = SECURITY_NT_AUTHORITY;
1903     PACCESS_ALLOWED_ACE aaace;
1904     ULONG bytesNeeded;
1905     ULONG bytesReturned;
1906     ULONG idx;
1907     PSID psid;
1908     NTSTATUS ntStatus = STATUS_SUCCESS;
1909
1910     __Enter
1911     {
1912
1913         ntStatus = ZwOpenProcessTokenEx( NtCurrentProcess(),
1914                                          GENERIC_ALL,
1915                                          OBJ_KERNEL_HANDLE,
1916                                          &hToken);
1917
1918         if( !NT_SUCCESS( ntStatus))
1919         {
1920             try_return( ntStatus);
1921         }
1922
1923         // get the size of the current DACL
1924         ntStatus = ZwQueryInformationToken( hToken,
1925                                             TokenDefaultDacl,
1926                                             NULL,
1927                                             0,
1928                                             &bytesNeeded);
1929
1930         // if we failed to get the buffer size needed
1931         if ((ntStatus != STATUS_SUCCESS) && (ntStatus != STATUS_BUFFER_TOO_SMALL))
1932         {
1933             try_return( ntStatus);
1934         }
1935
1936         // tack on enough space for our ACE if we need to add it...
1937         bytesNeeded += FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) + AFS_DACL_SID_LENGTH;
1938
1939         // allocate space for the DACL
1940         defDacl = (PTOKEN_DEFAULT_DACL)ExAllocatePoolWithTag( PagedPool, bytesNeeded, AFS_GENERIC_MEMORY_26_TAG);
1941
1942         if (defDacl == NULL)
1943         {
1944            try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1945         }
1946
1947         // get the DACL
1948         ntStatus = ZwQueryInformationToken( hToken,
1949                                             TokenDefaultDacl,
1950                                             defDacl,
1951                                             bytesNeeded,
1952                                             &bytesReturned);
1953
1954         if( ntStatus != STATUS_SUCCESS)
1955         {
1956             try_return( ntStatus);
1957         }
1958
1959         // scan through DACL to see if we have the SID set already...
1960         ace = (PACE_HEADER)((char *)defDacl->DefaultDacl + sizeof(ACL));
1961         for (idx = 0; idx < defDacl->DefaultDacl->AceCount; idx++)
1962         {
1963             if (ace->AceType == ACCESS_ALLOWED_ACE_TYPE)
1964             {
1965                 aaace = (PACCESS_ALLOWED_ACE)ace;
1966
1967                 if (aaace->Header.AceSize == (FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) + AFS_DACL_SID_LENGTH))
1968                 {
1969                     // if the GUID part matches
1970                     if( RtlCompareMemory( RtlSubAuthoritySid((PSID)&aaace->SidStart, 0),
1971                                           &AFSSidGuid,
1972                                           sizeof(GUID)) == sizeof(GUID))
1973                     {
1974
1975                         if ( RtlCompareMemory( RtlSubAuthoritySid((PSID)&aaace->SidStart, 4),
1976                                                ProcessCB->ActiveAuthGroup,
1977                                                sizeof( GUID)) != sizeof( GUID))
1978                         {
1979
1980                             RtlCopyMemory( RtlSubAuthoritySid((PSID)&aaace->SidStart, 4),
1981                                            ProcessCB->ActiveAuthGroup,
1982                                            sizeof( GUID));
1983
1984                             if( AFSSetInformationToken != NULL)
1985                             {
1986                                 ntStatus = AFSSetInformationToken( hToken,
1987                                                                    TokenDefaultDacl,
1988                                                                    defDacl,
1989                                                                    bytesReturned);
1990                             }
1991                         }
1992
1993                         try_return( ntStatus);
1994                     }
1995                 }
1996             }
1997
1998             // go to next ace
1999             ace = (PACE_HEADER)((char *)ace + ace->AceSize);
2000         }
2001
2002         //
2003         // if we made it here we need to add a new ACE to the DACL
2004         //
2005
2006         aaace = (ACCESS_ALLOWED_ACE *)ace;
2007         aaace->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
2008         aaace->Header.AceFlags = 0;
2009         aaace->Mask = GENERIC_ALL;
2010         psid = (PSID)&aaace->SidStart;
2011         RtlInitializeSid( psid, &sia, 8);
2012
2013         RtlCopyMemory( RtlSubAuthoritySid(psid, 0),
2014                        &AFSSidGuid,
2015                        sizeof(GUID));
2016
2017         RtlCopyMemory( RtlSubAuthoritySid(psid, 4),
2018                        ProcessCB->ActiveAuthGroup,
2019                        sizeof( GUID));
2020
2021         aaace->Header.AceSize = (USHORT)(FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) + RtlLengthSid( psid));
2022
2023         defDacl->DefaultDacl->AclSize += aaace->Header.AceSize;
2024         defDacl->DefaultDacl->AceCount++;
2025
2026         if( AFSSetInformationToken != NULL)
2027         {
2028             ntStatus = AFSSetInformationToken( hToken,
2029                                               TokenDefaultDacl,
2030                                               defDacl,
2031                                               defDacl->DefaultDacl->AclSize + sizeof(PTOKEN_DEFAULT_DACL));
2032         }
2033
2034 try_exit:
2035
2036         if( hToken != NULL)
2037         {
2038             ZwClose( hToken);
2039         }
2040
2041         if (defDacl != NULL)
2042         {
2043            ExFreePool( defDacl);
2044         }
2045     }
2046
2047     return ntStatus;
2048 }
2049
2050