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