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