614004b9334eca484471e1c2fe64932bebb6bb03
[openafs.git] / src / WINNT / afsrdr / kernel / fs / AFSCommSupport.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: AFSCommSupport.cpp
37 //
38
39 #include "AFSCommon.h"
40
41 NTSTATUS
42 AFSReleaseFid( IN AFSFileID *FileId)
43 {
44
45     NTSTATUS ntStatus = STATUS_SUCCESS;
46
47     __Enter
48     {
49
50         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FID,
51                                       0,
52                                       NULL,
53                                       NULL,
54                                       FileId,
55                                       NULL,
56                                       0,
57                                       NULL,
58                                       0,
59                                       NULL,
60                                       NULL);
61     }
62
63     return ntStatus;
64 }
65
66 NTSTATUS
67 AFSProcessRequest( IN ULONG RequestType,
68                    IN ULONG RequestFlags,
69                    IN GUID *AuthGroup,
70                    IN PUNICODE_STRING FileName,
71                    IN AFSFileID *FileId,
72                    IN WCHAR *Cell,
73                    IN ULONG  CellLength,
74                    IN void  *Data,
75                    IN ULONG DataLength,
76                    IN OUT void *ResultBuffer,
77                    IN OUT PULONG ResultBufferLength)
78 {
79
80     NTSTATUS         ntStatus = STATUS_SUCCESS;
81     AFSPoolEntry     stPoolEntry, *pPoolEntry = NULL;
82     AFSCommSrvcCB   *pCommSrvc = NULL;
83     BOOLEAN          bReleasePool = FALSE;
84     AFSDeviceExt    *pControlDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
85     AFSDeviceExt    *pRDRDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
86     BOOLEAN          bWait = BooleanFlagOn( RequestFlags, AFS_REQUEST_FLAG_SYNCHRONOUS);
87     ULONG            ulPoolEntryLength = 0;
88     BOOLEAN          bDecrementCount = FALSE;
89
90     __try
91     {
92
93         if( BooleanFlagOn( pRDRDevExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
94         {
95             try_return( ntStatus = STATUS_DEVICE_NOT_READY);
96         }
97
98         if( InterlockedIncrement( &pControlDevExt->Specific.Control.OutstandingServiceRequestCount) == 1)
99         {
100             KeClearEvent( &pControlDevExt->Specific.Control.OutstandingServiceRequestEvent);
101         }
102
103         bDecrementCount = TRUE;
104
105         pCommSrvc = &pControlDevExt->Specific.Control.CommServiceCB;
106
107         //
108         // Grab the pool resource and check the state
109         //
110
111         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
112                       AFS_TRACE_LEVEL_VERBOSE,
113                       "AFSProcessRequest Acquiring IrpPoolLock lock %p EXCL %08lX\n",
114                       &pCommSrvc->IrpPoolLock,
115                       PsGetCurrentThread()));
116
117         AFSAcquireExcl( &pCommSrvc->IrpPoolLock,
118                         TRUE);
119
120         bReleasePool = TRUE;
121
122         if( pCommSrvc->IrpPoolControlFlag != POOL_ACTIVE)
123         {
124
125             //
126             // Pool not running so bail.
127             //
128
129             try_return( ntStatus = STATUS_DEVICE_NOT_READY);
130         }
131
132         //
133         // If this is an async request we need to allocate a pool entry for the request
134         //
135
136         pPoolEntry = &stPoolEntry;
137
138         if( !bWait)
139         {
140
141             ASSERT( ResultBuffer == NULL);
142
143             ulPoolEntryLength = sizeof( AFSPoolEntry) + QuadAlign( DataLength);
144
145             if( FileName != NULL)
146             {
147
148                 ulPoolEntryLength += FileName->Length;
149             }
150
151             pPoolEntry = (AFSPoolEntry *)AFSExAllocatePoolWithTag( NonPagedPool,
152                                                                    ulPoolEntryLength,
153                                                                    AFS_POOL_ENTRY_TAG);
154
155             if( pPoolEntry == NULL)
156             {
157
158                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
159             }
160
161             RtlZeroMemory( pPoolEntry,
162                            ulPoolEntryLength);
163
164             pPoolEntry->Data = (void *)((char *)pPoolEntry + sizeof( AFSPoolEntry));
165
166             pPoolEntry->FileName.Buffer = (WCHAR *)((char *)pPoolEntry->Data + DataLength);
167         }
168         else
169         {
170
171             RtlZeroMemory( pPoolEntry,
172                            sizeof( AFSPoolEntry));
173
174             KeInitializeEvent( &pPoolEntry->Event,
175                                NotificationEvent,
176                                FALSE);
177         }
178
179         pPoolEntry->RequestType = RequestType;
180
181         pPoolEntry->RequestIndex = pCommSrvc->IrpPoolRequestIndex++;
182
183         pPoolEntry->RequestFlags = RequestFlags;
184
185         pPoolEntry->ResultBufferLength = 0;
186
187         if( FileId != NULL)
188         {
189
190             pPoolEntry->FileId = *FileId;
191         }
192
193         pPoolEntry->FileName.Length = 0;
194
195         if( FileName != NULL)
196         {
197
198             if( bWait)
199             {
200
201                 pPoolEntry->FileName = *FileName;
202             }
203             else
204             {
205
206                 pPoolEntry->FileName.Length = FileName->Length;
207
208                 pPoolEntry->FileName.MaximumLength = pPoolEntry->FileName.Length;
209
210                 RtlCopyMemory( pPoolEntry->FileName.Buffer,
211                                FileName->Buffer,
212                                pPoolEntry->FileName.Length);
213             }
214         }
215
216         //
217         // Move in the data if there is some
218         //
219
220         pPoolEntry->DataLength = DataLength;
221
222         if( Data != NULL &&
223             DataLength > 0)
224         {
225
226             if( bWait)
227             {
228
229                 pPoolEntry->Data = Data;
230             }
231             else
232             {
233
234                 RtlCopyMemory( pPoolEntry->Data,
235                                Data,
236                                DataLength);
237             }
238         }
239
240         pPoolEntry->ResultBuffer = ResultBuffer;
241
242         pPoolEntry->ResultBufferLength = ResultBufferLength;
243
244         //
245         // Store off the auth group
246         //
247
248         if( AuthGroup == NULL)
249         {
250             AFSRetrieveAuthGroup( (ULONGLONG)PsGetCurrentProcessId(),
251                                   (ULONGLONG)PsGetCurrentThreadId(),
252                                   &pPoolEntry->AuthGroup);
253         }
254         else
255         {
256             RtlCopyMemory( &pPoolEntry->AuthGroup,
257                            AuthGroup,
258                            sizeof( GUID));
259         }
260
261         if( AFSIsLocalSystemAuthGroup( &pPoolEntry->AuthGroup))
262         {
263             SetFlag( pPoolEntry->RequestFlags, AFS_REQUEST_LOCAL_SYSTEM_PAG);
264         }
265
266         if( AFSIsNoPAGAuthGroup( &pPoolEntry->AuthGroup))
267         {
268             AFSDbgTrace(( 0,
269                           0,
270                           "AFSProcessRequest NoPAG Auth Group %08lX\n",
271                           PsGetCurrentThread()));
272         }
273
274         //
275         // Indicate the type of process
276         //
277
278 #ifdef AMD64
279
280         if( !AFSIs64BitProcess( (ULONGLONG)PsGetCurrentProcessId()))
281         {
282             SetFlag( pPoolEntry->RequestFlags, AFS_REQUEST_FLAG_WOW64);
283         }
284
285 #endif
286
287         //
288         // Insert the entry into the request pool
289         //
290
291         ntStatus = AFSInsertRequest( pCommSrvc,
292                                      pPoolEntry);
293
294         if( !NT_SUCCESS( ntStatus))
295         {
296
297             if( !bWait)
298             {
299
300                 ExFreePool( pPoolEntry);
301             }
302
303             try_return( ntStatus);
304         }
305
306         //
307         // Drop the lock on the pool prior to waiting
308         //
309
310         AFSReleaseResource( &pCommSrvc->IrpPoolLock);
311
312         bReleasePool = FALSE;
313
314         //
315         // Wait for the result if this is NOT an asynchronous request
316         //
317
318         if( bWait)
319         {
320
321             //
322             // Wait for the result of the request. We specify no timeout ...
323             //
324
325             ntStatus = KeWaitForSingleObject( &pPoolEntry->Event,
326                                               Executive,
327                                               KernelMode,
328                                               FALSE,
329                                               NULL);
330
331             //
332             // Process the result of the request
333             //
334
335             if( ntStatus == STATUS_SUCCESS)
336             {
337
338                 ntStatus = pPoolEntry->ResultStatus;
339             }
340             else
341             {
342
343                 ntStatus = STATUS_DEVICE_NOT_READY;
344             }
345         }
346
347 try_exit:
348
349         if( bReleasePool)
350         {
351
352             AFSReleaseResource( &pCommSrvc->IrpPoolLock);
353         }
354
355         if( bDecrementCount &&
356             InterlockedDecrement( &pControlDevExt->Specific.Control.OutstandingServiceRequestCount) == 0)
357         {
358             KeSetEvent( &pControlDevExt->Specific.Control.OutstandingServiceRequestEvent,
359                         0,
360                         FALSE);
361         }
362     }
363     __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()))
364     {
365
366         AFSDumpTraceFilesFnc();
367
368         if( bReleasePool)
369         {
370
371             AFSReleaseResource( &pCommSrvc->IrpPoolLock);
372         }
373
374         if( bDecrementCount &&
375             InterlockedDecrement( &pControlDevExt->Specific.Control.OutstandingServiceRequestCount) == 0)
376         {
377             KeSetEvent( &pControlDevExt->Specific.Control.OutstandingServiceRequestEvent,
378                         0,
379                         FALSE);
380         }
381
382         if ( ntStatus == STATUS_SUCCESS)
383         {
384
385             ntStatus = STATUS_UNSUCCESSFUL;
386         }
387     }
388
389     return ntStatus;
390 }
391
392 static
393 NTSTATUS
394 AFSCheckIoctlPermissions( IN ULONG ControlCode)
395 {
396     switch ( ControlCode)
397     {
398         //
399         // First the FS ioctls
400         //
401
402         case IOCTL_AFS_INITIALIZE_CONTROL_DEVICE:
403
404             //
405             // Only a System Service can run this (unless we are compiled
406             // for debug with the correct flags set.
407             //
408
409             if ( !AFSIsUser( SeExports->SeLocalSystemSid)
410 #if DBG
411                 && !BooleanFlagOn( AFSDebugFlags, AFS_DBG_DISABLE_SYSTEM_SID_CHECK)
412 #endif
413                 )
414             {
415
416                 return STATUS_ACCESS_DENIED;
417             }
418             return STATUS_SUCCESS;
419
420         case IOCTL_AFS_INITIALIZE_REDIRECTOR_DEVICE:
421         case IOCTL_AFS_PROCESS_IRP_REQUEST:
422         case IOCTL_AFS_PROCESS_IRP_RESULT:
423         case IOCTL_AFS_SYSNAME_NOTIFICATION:
424         case IOCTL_AFS_SHUTDOWN:
425
426             //
427             // Once initialized, only the service can call these
428             //
429
430             if ( !AFSIsService())
431             {
432
433                 return STATUS_ACCESS_DENIED;
434             }
435             return STATUS_SUCCESS;
436
437         case IOCTL_AFS_CONFIGURE_DEBUG_TRACE:
438         case IOCTL_AFS_GET_TRACE_BUFFER:
439         case IOCTL_AFS_FORCE_CRASH:
440
441             //
442             // Any admin can call these
443             //
444
445             if ( !AFSIsInGroup( SeExports->SeAliasAdminsSid))
446             {
447
448                 return STATUS_ACCESS_DENIED;
449             }
450             return STATUS_SUCCESS;
451
452         case IOCTL_AFS_AUTHGROUP_CREATE_AND_SET:
453         case IOCTL_AFS_AUTHGROUP_QUERY:
454         case IOCTL_AFS_AUTHGROUP_SET:
455         case IOCTL_AFS_AUTHGROUP_RESET:
456         case IOCTL_AFS_AUTHGROUP_LOGON_CREATE:
457         case IOCTL_AFS_AUTHGROUP_SID_CREATE:
458         case IOCTL_AFS_AUTHGROUP_SID_QUERY:
459
460             //
461             // Anyone can call these.
462             //
463
464             return STATUS_SUCCESS;
465
466         //
467         // And now the LIB ioctls
468         //
469
470         case IOCTL_AFS_INITIALIZE_LIBRARY_DEVICE:
471         case IOCTL_AFS_CONFIG_LIBRARY_TRACE:
472
473             //
474             // Only the kernel can issue this
475             //
476
477             return STATUS_ACCESS_DENIED;
478
479         case IOCTL_AFS_STATUS_REQUEST:
480         case 0x140390:      // IOCTL_LMR_DISABLE_LOCAL_BUFFERING
481
482             //
483             // Anyone can call these.
484             //
485
486             return STATUS_SUCCESS;
487
488         case IOCTL_AFS_ADD_CONNECTION:
489         case IOCTL_AFS_CANCEL_CONNECTION:
490         case IOCTL_AFS_GET_CONNECTION:
491         case IOCTL_AFS_LIST_CONNECTIONS:
492         case IOCTL_AFS_GET_CONNECTION_INFORMATION:
493
494             //
495             // These must only be called by the network provider but we
496             // don't have a method of enforcing that at the moment.
497             //
498
499             return STATUS_SUCCESS;
500
501         case IOCTL_AFS_SET_FILE_EXTENTS:
502         case IOCTL_AFS_RELEASE_FILE_EXTENTS:
503         case IOCTL_AFS_SET_FILE_EXTENT_FAILURE:
504         case IOCTL_AFS_INVALIDATE_CACHE:
505         case IOCTL_AFS_NETWORK_STATUS:
506         case IOCTL_AFS_VOLUME_STATUS:
507
508             //
509             // Again, service only
510             //
511
512             if ( !AFSIsService())
513             {
514
515                 return STATUS_ACCESS_DENIED;
516             }
517             return STATUS_SUCCESS;
518
519         case IOCTL_AFS_GET_OBJECT_INFORMATION:
520
521             //
522             // Admins only
523             //
524
525             if ( !AFSIsInGroup( SeExports->SeAliasAdminsSid))
526             {
527
528                 return STATUS_ACCESS_DENIED;
529             }
530             return STATUS_SUCCESS;
531
532         case IOCTL_AFS_SET_REPARSE_POLICY:
533         case IOCTL_AFS_GET_REPARSE_POLICY:
534
535             //
536             // Anyone can call this
537             //
538
539             return STATUS_SUCCESS;
540
541         default:
542
543             //
544             // NOTE that for security we police all known functions here
545             // and return STATUS_NOT_IMPLEMENTED.  So new ioctls need to
546             // be added both here and either below or in
547             // ..\lib\AFSDevControl.cpp
548             //
549
550             return STATUS_NOT_IMPLEMENTED;
551     }
552 }
553 NTSTATUS
554 AFSProcessControlRequest( IN PIRP Irp)
555 {
556
557     NTSTATUS            ntStatus = STATUS_SUCCESS;
558     PIO_STACK_LOCATION  pIrpSp;
559     ULONG               ulIoControlCode;
560     BOOLEAN             bCompleteRequest = TRUE;
561     AFSDeviceExt       *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
562
563     __try
564     {
565
566         pIrpSp = IoGetCurrentIrpStackLocation( Irp);
567
568         ulIoControlCode = pIrpSp->Parameters.DeviceIoControl.IoControlCode;
569
570         ntStatus = AFSCheckIoctlPermissions( ulIoControlCode);
571
572         if ( !NT_SUCCESS( ntStatus))
573         {
574             try_return( ntStatus);
575         }
576
577         switch( ulIoControlCode)
578         {
579
580             case IOCTL_AFS_INITIALIZE_CONTROL_DEVICE:
581             {
582                 //
583                 // Go intialize the pool
584                 //
585                 ntStatus = AFSInitIrpPool();
586
587                 if( !NT_SUCCESS( ntStatus))
588                 {
589
590                     //
591                     // Don't initialize
592                     //
593
594                     break;
595                 }
596
597                 //
598                 // Tag this instance as the one to close the irp pool when it is closed
599                 //
600
601                 pIrpSp->FileObject->FsContext = (void *)((ULONG_PTR)pIrpSp->FileObject->FsContext | AFS_CONTROL_INSTANCE);
602
603                 AFSRegisterService();
604
605                 break;
606             }
607
608             case IOCTL_AFS_INITIALIZE_REDIRECTOR_DEVICE:
609             {
610
611                 AFSRedirectorInitInfo *pRedirInitInfo = (AFSRedirectorInitInfo *)Irp->AssociatedIrp.SystemBuffer;
612
613                 //
614                 // Extract off the passed in information which contains the
615                 // cache file parameters
616                 //
617
618                 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSRedirectorInitInfo) ||
619                     pIrpSp->Parameters.DeviceIoControl.InputBufferLength < (ULONG)FIELD_OFFSET( AFSRedirectorInitInfo, CacheFileName) +
620                                                                                                     pRedirInitInfo->CacheFileNameLength)
621                 {
622
623                     ntStatus = STATUS_INVALID_PARAMETER;
624
625                     break;
626                 }
627
628                 //
629                 // Initialize the Redirector device
630                 //
631
632                 ntStatus = AFSInitializeRedirector( pRedirInitInfo);
633
634                 if( !NT_SUCCESS( ntStatus))
635                 {
636
637                     break;
638                 }
639
640                 //
641                 // Stash away context so we know the instance used to initialize the redirector
642                 //
643
644                 pIrpSp->FileObject->FsContext = (void *)((ULONG_PTR)pIrpSp->FileObject->FsContext | AFS_REDIRECTOR_INSTANCE);
645
646                 break;
647             }
648
649             case IOCTL_AFS_PROCESS_IRP_REQUEST:
650             {
651
652                 ntStatus = AFSProcessIrpRequest( Irp);
653
654                 break;
655             }
656
657             case IOCTL_AFS_PROCESS_IRP_RESULT:
658             {
659
660                 ntStatus = AFSProcessIrpResult( Irp);
661
662                 break;
663             }
664
665             case IOCTL_AFS_SYSNAME_NOTIFICATION:
666             {
667
668                 AFSSysNameNotificationCB *pSysNameInfo = (AFSSysNameNotificationCB *)Irp->AssociatedIrp.SystemBuffer;
669
670                 if( pSysNameInfo == NULL ||
671                     pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSSysNameNotificationCB))
672                 {
673
674                     ntStatus = STATUS_INVALID_PARAMETER;
675
676                     break;
677                 }
678
679                 ntStatus = AFSSetSysNameInformation( pSysNameInfo,
680                                                      pIrpSp->Parameters.DeviceIoControl.InputBufferLength);
681
682                 break;
683             }
684
685             case IOCTL_AFS_CONFIGURE_DEBUG_TRACE:
686             {
687
688                 AFSTraceConfigCB *pTraceInfo = (AFSTraceConfigCB *)Irp->AssociatedIrp.SystemBuffer;
689
690                 if( pTraceInfo == NULL ||
691                     pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSTraceConfigCB))
692                 {
693
694                     ntStatus = STATUS_INVALID_PARAMETER;
695
696                     break;
697                 }
698
699                 ntStatus = AFSConfigureTrace( pTraceInfo);
700
701                 break;
702             }
703
704             case IOCTL_AFS_GET_TRACE_BUFFER:
705             {
706
707                 if( pIrpSp->Parameters.DeviceIoControl.OutputBufferLength == 0)
708                 {
709
710                     ntStatus = STATUS_INVALID_PARAMETER;
711
712                     break;
713                 }
714
715                 ntStatus = AFSGetTraceBuffer( pIrpSp->Parameters.DeviceIoControl.OutputBufferLength,
716                                               Irp->AssociatedIrp.SystemBuffer,
717                                               &Irp->IoStatus.Information);
718
719                 break;
720             }
721
722             case IOCTL_AFS_FORCE_CRASH:
723             {
724
725 #if DBG
726
727                 if( BooleanFlagOn( AFSDebugFlags, AFS_DBG_FLAG_ENABLE_FORCE_CRASH))
728                 {
729
730                     KeBugCheck( (ULONG)-1);
731                 }
732 #endif
733
734                 break;
735             }
736
737 #ifdef NOT_IMPLEMENTED
738             case IOCTL_AFS_LOAD_LIBRARY:
739             {
740
741                 AFSLoadLibraryCB *pLoadLib = (AFSLoadLibraryCB *)Irp->AssociatedIrp.SystemBuffer;
742                 UNICODE_STRING uniServicePath;
743
744                 if( pLoadLib == NULL ||
745                     pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSLoadLibraryCB) ||
746                     pIrpSp->Parameters.DeviceIoControl.InputBufferLength < (ULONG)FIELD_OFFSET( AFSLoadLibraryCB, LibraryServicePath) +
747                                                                                                     pLoadLib->LibraryServicePathLength)
748                 {
749
750                     ntStatus = STATUS_INVALID_PARAMETER;
751
752                     break;
753                 }
754
755                 uniServicePath.Length = pLoadLib->LibraryServicePathLength;
756                 uniServicePath.MaximumLength = uniServicePath.Length;
757
758                 uniServicePath.Buffer = pLoadLib->LibraryServicePath;
759
760                 if( uniServicePath.Length == 0)
761                 {
762
763                     ntStatus = STATUS_INVALID_PARAMETER;
764
765                     break;
766                 }
767
768                 ntStatus = AFSLoadLibrary( pLoadLib->Flags,
769                                            &uniServicePath);
770
771                 if( NT_SUCCESS( ntStatus))
772                 {
773
774                     //
775                     // Intialize the library
776                     //
777
778                     ntStatus = AFSInitializeLibrary( NULL,
779                                                      FALSE);
780                 }
781
782                 break;
783             }
784
785             case IOCTL_AFS_UNLOAD_LIBRARY:
786             {
787
788                 //
789                 // Try to unload the library we currently have in place
790                 //
791
792                 ntStatus = AFSUnloadLibrary( FALSE);
793
794                 break;
795             }
796 #endif
797
798             case IOCTL_AFS_SHUTDOWN:
799             {
800
801                 ntStatus = AFSShutdownRedirector();
802
803                 break;
804             }
805
806             case IOCTL_AFS_AUTHGROUP_CREATE_AND_SET:
807             {
808
809                 AFSAuthGroupRequestCB *pAuthGroupRequestCB = (AFSAuthGroupRequestCB *)Irp->AssociatedIrp.SystemBuffer;
810
811                 if( pAuthGroupRequestCB == NULL ||
812                     pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSAuthGroupRequestCB))
813                 {
814
815                     ntStatus = STATUS_INVALID_PARAMETER;
816
817                     break;
818                 }
819
820                 ntStatus = AFSCreateSetProcessAuthGroup( pAuthGroupRequestCB);
821
822                 break;
823             }
824
825             case IOCTL_AFS_AUTHGROUP_QUERY:
826             {
827
828                 ntStatus = AFSQueryProcessAuthGroupList( ( GUID *)Irp->AssociatedIrp.SystemBuffer,
829                                                          pIrpSp->Parameters.DeviceIoControl.OutputBufferLength,
830                                                          &Irp->IoStatus.Information);
831
832                 break;
833             }
834
835             case IOCTL_AFS_AUTHGROUP_SET:
836             {
837
838                 AFSAuthGroupRequestCB *pAuthGroupRequestCB = (AFSAuthGroupRequestCB *)Irp->AssociatedIrp.SystemBuffer;
839
840                 if( pAuthGroupRequestCB == NULL ||
841                     pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSAuthGroupRequestCB))
842                 {
843
844                     ntStatus = STATUS_INVALID_PARAMETER;
845
846                     break;
847                 }
848
849                 ntStatus = AFSSetActiveProcessAuthGroup( pAuthGroupRequestCB);
850
851                 break;
852             }
853
854             case IOCTL_AFS_AUTHGROUP_RESET:
855             {
856
857                 AFSAuthGroupRequestCB *pAuthGroupRequestCB = (AFSAuthGroupRequestCB *)Irp->AssociatedIrp.SystemBuffer;
858
859                 if( pAuthGroupRequestCB == NULL ||
860                     pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSAuthGroupRequestCB))
861                 {
862
863                     ntStatus = STATUS_INVALID_PARAMETER;
864
865                     break;
866                 }
867
868                 ntStatus = AFSResetActiveProcessAuthGroup( pAuthGroupRequestCB);
869
870                 break;
871             }
872
873             case IOCTL_AFS_AUTHGROUP_LOGON_CREATE:
874             case IOCTL_AFS_AUTHGROUP_SID_CREATE:
875             {
876
877                 AFSAuthGroupRequestCB *pAuthGroupRequestCB = (AFSAuthGroupRequestCB *)Irp->AssociatedIrp.SystemBuffer;
878
879                 if( pAuthGroupRequestCB != NULL &&
880                     pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSAuthGroupRequestCB))
881                 {
882
883                     ntStatus = STATUS_INVALID_PARAMETER;
884
885                     break;
886                 }
887
888                 ntStatus = AFSCreateAuthGroupForSIDorLogonSession( pAuthGroupRequestCB,
889                                                                    ulIoControlCode == IOCTL_AFS_AUTHGROUP_LOGON_CREATE);
890
891                 break;
892             }
893
894             case IOCTL_AFS_AUTHGROUP_SID_QUERY:
895             {
896
897                 AFSAuthGroupRequestCB *pAuthGroupRequestCB = NULL;
898
899                 if( pIrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof( GUID))
900                 {
901                     ntStatus = STATUS_INVALID_PARAMETER;
902                     break;
903                 }
904
905                 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength >= sizeof( AFSAuthGroupRequestCB))
906                 {
907                     pAuthGroupRequestCB = (AFSAuthGroupRequestCB *)Irp->AssociatedIrp.SystemBuffer;
908                 }
909
910                 ntStatus = AFSQueryAuthGroup( pAuthGroupRequestCB,
911                                               (GUID *)Irp->AssociatedIrp.SystemBuffer,
912                                               &Irp->IoStatus.Information);
913
914                 break;
915             }
916
917             case IOCTL_AFS_SET_REPARSE_POLICY:
918             {
919
920                 AFSSetReparsePointPolicyCB *pPolicy = (AFSSetReparsePointPolicyCB *)Irp->AssociatedIrp.SystemBuffer;
921
922                 if( pPolicy == NULL ||
923                     pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSSetReparsePointPolicyCB))
924                 {
925                     ntStatus = STATUS_INVALID_PARAMETER;
926                     break;
927                 }
928
929                 ntStatus = AFSSetReparsePointPolicy( pPolicy);
930
931                 break;
932             }
933
934             case IOCTL_AFS_GET_REPARSE_POLICY:
935             {
936
937                 AFSGetReparsePointPolicyCB *pPolicy = (AFSGetReparsePointPolicyCB *)Irp->AssociatedIrp.SystemBuffer;
938
939                 if( pPolicy == NULL ||
940                     pIrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof( AFSGetReparsePointPolicyCB))
941                 {
942                     ntStatus = STATUS_INVALID_PARAMETER;
943                     break;
944                 }
945
946                 ntStatus = AFSGetReparsePointPolicy( pPolicy);
947
948                 if ( NT_SUCCESS( ntStatus))
949                 {
950
951                     Irp->IoStatus.Information = sizeof( AFSGetReparsePointPolicyCB);
952                 }
953
954                 break;
955             }
956
957             default:
958             {
959
960                 //
961                 // Check the state of the library
962                 //
963
964                 ntStatus = AFSCheckLibraryState( Irp);
965
966                 if( !NT_SUCCESS( ntStatus) ||
967                     ntStatus == STATUS_PENDING)
968                 {
969
970                     if( ntStatus == STATUS_PENDING)
971                     {
972                         bCompleteRequest = FALSE;
973                     }
974
975                     break;
976                 }
977
978                 bCompleteRequest = FALSE;
979
980                 IoSkipCurrentIrpStackLocation( Irp);
981
982                 ntStatus = IoCallDriver( pDevExt->Specific.Control.LibraryDeviceObject,
983                                          Irp);
984
985                 //
986                 // Indicate the library is done with the request
987                 //
988
989                 AFSClearLibraryRequest();
990
991                 break;
992             }
993         }
994
995     }
996     __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()))
997     {
998
999         ntStatus = STATUS_UNSUCCESSFUL;
1000
1001         AFSDumpTraceFilesFnc();
1002     }
1003
1004 try_exit:
1005
1006     if( bCompleteRequest)
1007     {
1008
1009         Irp->IoStatus.Status = ntStatus;
1010
1011         AFSCompleteRequest( Irp,
1012                               ntStatus);
1013     }
1014
1015     return ntStatus;
1016 }
1017
1018 NTSTATUS
1019 AFSInitIrpPool()
1020 {
1021
1022     NTSTATUS       ntStatus = STATUS_SUCCESS;
1023     AFSCommSrvcCB *pCommSrvc = NULL;
1024     BOOLEAN        bReleasePools = FALSE;
1025     AFSDeviceExt  *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
1026
1027     __Enter
1028     {
1029
1030         pCommSrvc = &pDevExt->Specific.Control.CommServiceCB;
1031
1032         //
1033         // Whenever we change state we must grab both pool locks. On the checking of the state
1034         // within the processing routines for these respective pools, we only grab one lock to
1035         // minimize serialization. The ordering is always the Irp pool then the result pool
1036         // locks. We also do this in the tear down of the pool
1037         //
1038
1039         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1040                       AFS_TRACE_LEVEL_VERBOSE,
1041                       "AFSInitIrpPool Acquiring IrpPoolLock lock %p EXCL %08lX\n",
1042                       &pCommSrvc->IrpPoolLock,
1043                       PsGetCurrentThread()));
1044
1045         AFSAcquireExcl( &pCommSrvc->IrpPoolLock,
1046                           TRUE);
1047
1048         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1049                       AFS_TRACE_LEVEL_VERBOSE,
1050                       "AFSInitIrpPool Acquiring ResultPoolLock lock %p EXCL %08lX\n",
1051                       &pCommSrvc->ResultPoolLock,
1052                       PsGetCurrentThread()));
1053
1054         AFSAcquireExcl( &pCommSrvc->ResultPoolLock,
1055                           TRUE);
1056
1057         bReleasePools = TRUE;
1058
1059         //
1060         // The pool can be either ACTIVE or INACTIVE. If the pool state is INACTIVE and we
1061         // are receiving the INIT request, then activate it. If the pool is ACTIVE, then we
1062         // shouldn't be getting this request ...
1063         //
1064
1065         if( pCommSrvc->IrpPoolControlFlag == POOL_ACTIVE)
1066         {
1067
1068             //
1069             // We have already been activated so just fail this request
1070             //
1071
1072             try_return( ntStatus = STATUS_INVALID_PARAMETER);
1073         }
1074         else if( pCommSrvc->IrpPoolControlFlag == POOL_INACTIVE)
1075         {
1076
1077             //
1078             // The pool is currently INACTIVE so start it up and ready it to
1079             // receive irp requests
1080             //
1081
1082             pCommSrvc->IrpPoolControlFlag = POOL_ACTIVE;
1083
1084             pDevExt->Specific.Control.ServiceProcess = (PKPROCESS)PsGetCurrentProcess();
1085
1086             try_return( ntStatus = STATUS_SUCCESS);
1087         }
1088         else
1089         {
1090
1091             //
1092             // The pool is in some mixed state, fail the request.
1093             //
1094
1095             try_return( ntStatus = STATUS_DEVICE_NOT_READY);
1096         }
1097
1098 try_exit:
1099
1100         if( bReleasePools)
1101         {
1102
1103             AFSReleaseResource( &pCommSrvc->IrpPoolLock);
1104
1105             AFSReleaseResource( &pCommSrvc->ResultPoolLock);
1106         }
1107     }
1108
1109     return ntStatus;
1110 }
1111
1112 void
1113 AFSCleanupIrpPool()
1114 {
1115
1116     AFSPoolEntry   *pEntry = NULL, *pNextEntry = NULL;
1117     AFSDeviceExt   *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
1118     AFSCommSrvcCB  *pCommSrvc = (AFSCommSrvcCB *)&pDevExt->Specific.Control.CommServiceCB;
1119
1120     __Enter
1121     {
1122
1123         //
1124         // When we change the state, grab both pool locks exclusive. The order is always the
1125         // Irp pool then the result pool lock
1126         //
1127
1128         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1129                       AFS_TRACE_LEVEL_VERBOSE,
1130                       "AFSCleanupIrpPool Acquiring IrpPoolLock lock %p EXCL %08lX\n",
1131                       &pCommSrvc->IrpPoolLock,
1132                       PsGetCurrentThread()));
1133
1134         AFSAcquireExcl( &pCommSrvc->IrpPoolLock,
1135                         TRUE);
1136
1137         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1138                       AFS_TRACE_LEVEL_VERBOSE,
1139                       "AFSCleanupIrpPool Acquiring ResultPoolLock lock %p EXCL %08lX\n",
1140                       &pCommSrvc->ResultPoolLock,
1141                       PsGetCurrentThread()));
1142
1143         AFSAcquireExcl( &pCommSrvc->ResultPoolLock,
1144                         TRUE);
1145
1146         //
1147         // Indicate we are pending stop
1148         //
1149
1150         pCommSrvc->IrpPoolControlFlag = POOL_INACTIVE;
1151
1152         //
1153         // Set the event to release any waiting workers
1154         // (everyone waits on IrpPoolHasReleaseEntries)
1155         //
1156
1157         KeSetEvent( &pCommSrvc->IrpPoolHasReleaseEntries,
1158                     0,
1159                     FALSE);
1160
1161         //
1162         // Go through the pool entries and free up the structures.
1163         //
1164
1165         pEntry = pCommSrvc->RequestPoolHead;
1166
1167         while( pEntry != NULL)
1168         {
1169
1170             pNextEntry = pEntry->fLink;
1171
1172             if( BooleanFlagOn( pEntry->RequestFlags, AFS_REQUEST_FLAG_SYNCHRONOUS))
1173             {
1174
1175                 //
1176                 // Here we need to complete the irp, cancelled, and delete the data block
1177                 //
1178
1179                 pEntry->ResultStatus = (ULONG) STATUS_CANCELLED;
1180
1181                 KeSetEvent( &pEntry->Event,
1182                             0,
1183                             FALSE);
1184             }
1185             else
1186             {
1187
1188                 ExFreePool( pEntry);
1189             }
1190
1191             pEntry = pNextEntry;
1192         }
1193
1194         //
1195         // Cleanup the control structure for the request pool
1196         //
1197
1198         pCommSrvc->RequestPoolHead = NULL;
1199
1200         pCommSrvc->RequestPoolTail = NULL;
1201
1202         pCommSrvc->IrpPoolRequestIndex = 1;
1203
1204         KeClearEvent( &pCommSrvc->IrpPoolHasEntries);
1205
1206         KeClearEvent( &pCommSrvc->IrpPoolHasReleaseEntries);
1207
1208         //
1209         // Release the irp pool lock.
1210         //
1211
1212         AFSReleaseResource( &pCommSrvc->IrpPoolLock);
1213
1214         //
1215         // Go through the result pool entries and free up the structures.
1216         //
1217
1218         pEntry = pCommSrvc->ResultPoolHead;
1219
1220         while( pEntry != NULL)
1221         {
1222
1223             pNextEntry = pEntry->fLink;
1224
1225             pEntry->ResultStatus = (ULONG) STATUS_CANCELLED;
1226
1227             if( pEntry->RequestType == AFS_REQUEST_TYPE_PROCESS_READ_FILE ||
1228                 pEntry->RequestType == AFS_REQUEST_TYPE_PROCESS_WRITE_FILE)
1229             {
1230
1231                 AFSFileIOCB *pFileIO = (AFSFileIOCB *)pEntry->Data;
1232
1233                 if( pFileIO->MappedIOBuffer != NULL)
1234                 {
1235                     MmUnmapLockedPages( pFileIO->MappedIOBuffer,
1236                                         (PMDL)pFileIO->SystemIOBufferMdl);
1237
1238                     pFileIO->MappedIOBuffer = NULL;
1239                 }
1240             }
1241
1242             //
1243             // Here we will set the event of the requestor and let the blocked thread
1244             // free the data block
1245             //
1246
1247             KeSetEvent( &pEntry->Event,
1248                         0,
1249                         FALSE);
1250
1251             //
1252             // Go onto the next entry
1253             //
1254
1255             pEntry = pNextEntry;
1256         }
1257
1258         //
1259         // Cleanup the control structure for the result pool
1260         //
1261
1262         pCommSrvc->ResultPoolHead = NULL;
1263
1264         pCommSrvc->ResultPoolTail = NULL;
1265
1266         //
1267         // Release the result pool lock.
1268         //
1269
1270         AFSReleaseResource( &pCommSrvc->ResultPoolLock);
1271
1272     }
1273
1274     return;
1275 }
1276
1277 NTSTATUS
1278 AFSInsertRequest( IN AFSCommSrvcCB *CommSrvc,
1279                   IN AFSPoolEntry *Entry)
1280 {
1281
1282     NTSTATUS ntStatus = STATUS_SUCCESS;
1283
1284     __Enter
1285     {
1286
1287         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1288                       AFS_TRACE_LEVEL_VERBOSE,
1289                       "AFSInsertRequest Acquiring IrpPoolLock lock %p EXCL %08lX\n",
1290                       &CommSrvc->IrpPoolLock,
1291                       PsGetCurrentThread()));
1292
1293         AFSAcquireExcl( &CommSrvc->IrpPoolLock,
1294                         TRUE);
1295
1296         if( CommSrvc->IrpPoolControlFlag != POOL_ACTIVE)
1297         {
1298
1299             try_return( ntStatus = STATUS_DEVICE_NOT_READY);
1300         }
1301
1302         if( CommSrvc->RequestPoolHead == NULL)
1303         {
1304
1305             CommSrvc->RequestPoolHead = Entry;
1306         }
1307         else
1308         {
1309
1310             CommSrvc->RequestPoolTail->fLink = Entry;
1311
1312             Entry->bLink = CommSrvc->RequestPoolTail;
1313         }
1314
1315         CommSrvc->RequestPoolTail = Entry;
1316
1317         if( Entry->RequestType == AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS)
1318         {
1319
1320             KeSetEvent( &CommSrvc->IrpPoolHasReleaseEntries,
1321                         0,
1322                         FALSE);
1323         }
1324         else
1325         {
1326
1327             KeSetEvent( &CommSrvc->IrpPoolHasEntries,
1328                         0,
1329                         FALSE);
1330         }
1331
1332         InterlockedIncrement( &CommSrvc->QueueCount);
1333
1334 try_exit:
1335
1336         AFSReleaseResource( &CommSrvc->IrpPoolLock);
1337     }
1338
1339     return ntStatus;
1340 }
1341
1342 NTSTATUS
1343 AFSProcessIrpRequest( IN PIRP Irp)
1344 {
1345
1346     NTSTATUS         ntStatus = STATUS_SUCCESS;
1347     AFSDeviceExt    *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
1348     IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1349     AFSCommSrvcCB   *pCommSrvc = NULL;
1350     AFSPoolEntry    *pEntry = NULL, *pPrevEntry = NULL;
1351     AFSCommRequest  *pRequest = NULL;
1352     BOOLEAN          bReleaseRequestThread = FALSE;
1353     PVOID            Objects[2];
1354
1355     __Enter
1356     {
1357
1358         pCommSrvc = &pDevExt->Specific.Control.CommServiceCB;
1359
1360         pRequest = (AFSCommRequest *)Irp->AssociatedIrp.SystemBuffer;
1361
1362         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1363                       AFS_TRACE_LEVEL_VERBOSE,
1364                       "AFSProcessIrpRequest Acquiring IrpPoolLock lock %p EXCL %08lX\n",
1365                       &pCommSrvc->IrpPoolLock,
1366                       PsGetCurrentThread()));
1367
1368         AFSAcquireExcl( &pCommSrvc->IrpPoolLock,
1369                         TRUE);
1370
1371         if( pCommSrvc->IrpPoolControlFlag != POOL_ACTIVE)
1372         {
1373
1374             AFSReleaseResource( &pCommSrvc->IrpPoolLock);
1375
1376             try_return( ntStatus = STATUS_DEVICE_NOT_READY);
1377         }
1378
1379         AFSReleaseResource( &pCommSrvc->IrpPoolLock);
1380
1381         //
1382         // Is this a dedicated flush thread?
1383         //
1384
1385         if( BooleanFlagOn( pRequest->RequestFlags, AFS_REQUEST_RELEASE_THREAD))
1386         {
1387
1388             bReleaseRequestThread = TRUE;
1389         }
1390
1391         //
1392         // Populate the objects array for the non release only threads
1393         // Release only workers can only process release extent events
1394         // whereas normal workers can process any kind of event.
1395         // Release only workers are present to ensure there cannot be
1396         // a deadlock due to all extents held by the redirector and
1397         // there not be a worker available to release them.
1398         //
1399
1400         Objects[0] = &pCommSrvc->IrpPoolHasReleaseEntries;
1401
1402         Objects[1] = &pCommSrvc->IrpPoolHasEntries;
1403
1404         //
1405         // Wait on the 'have items' event until we can retrieve an item
1406         //
1407
1408         while( TRUE)
1409         {
1410
1411             if( bReleaseRequestThread)
1412             {
1413
1414                 ntStatus = KeWaitForSingleObject( &pCommSrvc->IrpPoolHasReleaseEntries,
1415                                                   UserRequest,
1416                                                   UserMode,
1417                                                   TRUE,
1418                                                   NULL);
1419
1420                 if( ntStatus != STATUS_SUCCESS)
1421                 {
1422
1423                     ntStatus = STATUS_DEVICE_NOT_READY;
1424
1425                     break;
1426                 }
1427
1428             }
1429             else
1430             {
1431
1432                 ntStatus = KeWaitForMultipleObjects( 2,
1433                                                      Objects,
1434                                                      WaitAny,
1435                                                      UserRequest,
1436                                                      UserMode,
1437                                                      TRUE,
1438                                                      NULL,
1439                                                      NULL);
1440
1441                 if( ntStatus != STATUS_WAIT_0 &&
1442                     ntStatus != STATUS_WAIT_1)
1443                 {
1444
1445                     ntStatus = STATUS_DEVICE_NOT_READY;
1446
1447                     break;
1448                 }
1449             }
1450
1451             //
1452             // Grab the lock on the request pool
1453             //
1454
1455             AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1456                           AFS_TRACE_LEVEL_VERBOSE,
1457                           "AFSProcessIrpRequest Acquiring IrpPoolLock (WAIT) lock %p EXCL %08lX\n",
1458                           &pCommSrvc->IrpPoolLock,
1459                           PsGetCurrentThread()));
1460
1461             AFSAcquireExcl( &pCommSrvc->IrpPoolLock,
1462                             TRUE);
1463
1464             if( pCommSrvc->IrpPoolControlFlag != POOL_ACTIVE)
1465             {
1466
1467                 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
1468
1469                 //
1470                 // Wake up the next worker since this is a SynchronizationEvent
1471                 //
1472
1473                 KeSetEvent( &pCommSrvc->IrpPoolHasReleaseEntries,
1474                             0,
1475                             FALSE);
1476
1477                 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
1478             }
1479
1480             //
1481             // If this is a dedicated flush thread only look for a flush request in the queue
1482             //
1483
1484             if( bReleaseRequestThread)
1485             {
1486
1487                 pEntry = pCommSrvc->RequestPoolHead;
1488
1489                 pPrevEntry = NULL;
1490
1491                 while( pEntry != NULL)
1492                 {
1493
1494                     if( pEntry->RequestType == AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS)
1495                     {
1496
1497                         if( pPrevEntry == NULL)
1498                         {
1499
1500                             pCommSrvc->RequestPoolHead = pEntry->fLink;
1501
1502                             if( pCommSrvc->RequestPoolHead == NULL)
1503                             {
1504
1505                                 pCommSrvc->RequestPoolTail = NULL;
1506                             }
1507                         }
1508                         else
1509                         {
1510
1511                             pPrevEntry->fLink = pEntry->fLink;
1512
1513                             if( pPrevEntry->fLink == NULL)
1514                             {
1515
1516                                 pCommSrvc->RequestPoolTail = pPrevEntry;
1517                             }
1518                         }
1519
1520                         break;
1521                     }
1522
1523                     pPrevEntry = pEntry;
1524
1525                     pEntry = pEntry->fLink;
1526                 }
1527
1528                 if( pEntry != NULL)
1529                 {
1530
1531                     //
1532                     // There might be another release entry pending
1533                     //
1534
1535                     KeSetEvent( &pCommSrvc->IrpPoolHasReleaseEntries,
1536                                 0,
1537                                 FALSE);
1538                 }
1539
1540                 //
1541                 // And release the request pool lock
1542                 //
1543
1544                 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
1545             }
1546             else
1547             {
1548
1549                 pEntry = pCommSrvc->RequestPoolHead;
1550
1551                 if( pEntry != NULL)
1552                 {
1553
1554                     pCommSrvc->RequestPoolHead = pEntry->fLink;
1555
1556                     pEntry->bLink = NULL;
1557
1558                     if( pCommSrvc->RequestPoolHead == NULL)
1559                     {
1560
1561                         pCommSrvc->RequestPoolTail = NULL;
1562                     }
1563                     else
1564                     {
1565
1566                         KeSetEvent( &pCommSrvc->IrpPoolHasEntries,
1567                                     0,
1568                                     FALSE);
1569                     }
1570                 }
1571
1572                 //
1573                 // And release the request pool lock
1574                 //
1575
1576                 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
1577             }
1578
1579             //
1580             // Insert the entry into the result pool, if we have one
1581             //
1582
1583             if( pEntry != NULL)
1584             {
1585
1586                 //
1587                 // Move the request data into the passed in buffer
1588                 //
1589
1590                 ASSERT( sizeof( AFSCommRequest) +
1591                                     pEntry->FileName.Length +
1592                                     pEntry->DataLength <= pIrpSp->Parameters.DeviceIoControl.OutputBufferLength);
1593
1594                 RtlCopyMemory( &pRequest->AuthGroup,
1595                                &pEntry->AuthGroup,
1596                                sizeof( GUID));
1597
1598                 pRequest->FileId = pEntry->FileId;
1599
1600                 pRequest->RequestType = pEntry->RequestType;
1601
1602                 pRequest->RequestIndex = pEntry->RequestIndex;
1603
1604                 pRequest->RequestFlags = pEntry->RequestFlags;
1605
1606                 pRequest->NameLength = pEntry->FileName.Length;
1607
1608                 pRequest->QueueCount = InterlockedDecrement( &pCommSrvc->QueueCount);
1609
1610                 if( pRequest->NameLength > 0)
1611                 {
1612
1613                     RtlCopyMemory( pRequest->Name,
1614                                    pEntry->FileName.Buffer,
1615                                    pRequest->NameLength);
1616                 }
1617
1618                 //
1619                 // If this is an IO request then need to map the system buffer to the service process
1620                 //
1621
1622                 if( pEntry->RequestType == AFS_REQUEST_TYPE_PROCESS_READ_FILE ||
1623                     pEntry->RequestType == AFS_REQUEST_TYPE_PROCESS_WRITE_FILE)
1624                 {
1625
1626                     AFSFileIOCB *pFileIO = (AFSFileIOCB *)pEntry->Data;
1627
1628                     ASSERT( pFileIO->SystemIOBuffer != NULL);
1629
1630                     pFileIO->MappedIOBuffer = MmMapLockedPagesSpecifyCache( (PMDL)pFileIO->SystemIOBufferMdl,
1631                                                                             UserMode,
1632                                                                             MmCached,
1633                                                                             NULL,
1634                                                                             FALSE,
1635                                                                             NormalPagePriority);
1636                 }
1637
1638                 pRequest->DataOffset = 0;
1639
1640                 pRequest->DataLength = pEntry->DataLength;
1641
1642                 if( pRequest->DataLength > 0)
1643                 {
1644
1645                     pRequest->DataOffset = pEntry->FileName.Length;
1646
1647                     RtlCopyMemory( (void *)((char *)pRequest->Name + pRequest->DataOffset),
1648                                    pEntry->Data,
1649                                    pRequest->DataLength);
1650                 }
1651
1652                 pRequest->ResultBufferLength = 0;
1653
1654                 if( pEntry->ResultBufferLength != NULL)
1655                 {
1656
1657                     pRequest->ResultBufferLength = *(pEntry->ResultBufferLength);
1658                 }
1659
1660                 Irp->IoStatus.Information = sizeof( AFSCommRequest) +
1661                                                         pEntry->FileName.Length +
1662                                                         pEntry->DataLength;
1663
1664                 //
1665                 // If this is a synchronous request then move the request into the
1666                 // result pool
1667                 //
1668
1669                 if( BooleanFlagOn( pEntry->RequestFlags, AFS_REQUEST_FLAG_SYNCHRONOUS))
1670                 {
1671
1672                     pEntry->fLink = NULL;
1673                     pEntry->bLink = NULL;
1674
1675                     AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1676                                   AFS_TRACE_LEVEL_VERBOSE,
1677                                   "AFSProcessIrpRequest Acquiring ResultPoolLock lock %p EXCL %08lX\n",
1678                                   &pCommSrvc->ResultPoolLock,
1679                                   PsGetCurrentThread()));
1680
1681                     AFSAcquireExcl( &pCommSrvc->ResultPoolLock,
1682                                     TRUE);
1683
1684                     if( pCommSrvc->ResultPoolHead == NULL)
1685                     {
1686
1687                         pCommSrvc->ResultPoolHead = pEntry;
1688                     }
1689                     else
1690                     {
1691
1692                         pCommSrvc->ResultPoolTail->fLink = pEntry;
1693
1694                         pEntry->bLink = pCommSrvc->ResultPoolTail;
1695                     }
1696
1697                     pCommSrvc->ResultPoolTail = pEntry;
1698
1699                     AFSReleaseResource( &pCommSrvc->ResultPoolLock);
1700                 }
1701                 else
1702                 {
1703
1704                     //
1705                     // Free up the pool entry
1706                     //
1707
1708                     ExFreePool( pEntry);
1709                 }
1710
1711                 break;
1712             }
1713         }
1714
1715 try_exit:
1716
1717         NOTHING;
1718     }
1719
1720     return ntStatus;
1721 }
1722
1723 NTSTATUS
1724 AFSProcessIrpResult( IN PIRP Irp)
1725 {
1726
1727     NTSTATUS            ntStatus = STATUS_SUCCESS;
1728     AFSDeviceExt       *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
1729     AFSCommSrvcCB      *pCommSrvc = NULL;
1730     AFSPoolEntry       *pCurrentEntry = NULL;
1731     AFSCommResult      *pResult = NULL;
1732     ULONG               ulCopyLen = 0;
1733
1734     __Enter
1735     {
1736
1737         pCommSrvc = &pDevExt->Specific.Control.CommServiceCB;
1738
1739         //
1740         // Get the request for the incoming result
1741         //
1742
1743         pResult = (AFSCommResult *)Irp->AssociatedIrp.SystemBuffer;
1744
1745         if( pResult == NULL)
1746         {
1747
1748             try_return( ntStatus = STATUS_INVALID_PARAMETER);
1749         }
1750
1751         //
1752         // Go look for our entry
1753         //
1754
1755         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1756                       AFS_TRACE_LEVEL_VERBOSE,
1757                       "AFSProcessIrpResult Acquiring ResultPoolLock lock %p EXCL %08lX\n",
1758                       &pCommSrvc->ResultPoolLock,
1759                       PsGetCurrentThread()));
1760
1761         AFSAcquireExcl( &pCommSrvc->ResultPoolLock,
1762                           TRUE);
1763
1764         pCurrentEntry = pCommSrvc->ResultPoolHead;
1765
1766         while( pCurrentEntry != NULL)
1767         {
1768
1769             if( pCurrentEntry->RequestIndex == pResult->RequestIndex)
1770             {
1771
1772                 //
1773                 // Found the entry so remove it from the queue
1774                 //
1775
1776                 if( pCurrentEntry->bLink == NULL)
1777                 {
1778
1779                     //
1780                     // At the head of the list
1781                     //
1782
1783                     pCommSrvc->ResultPoolHead = pCurrentEntry->fLink;
1784
1785                     if( pCommSrvc->ResultPoolHead != NULL)
1786                     {
1787
1788                         pCommSrvc->ResultPoolHead->bLink = NULL;
1789                     }
1790                 }
1791                 else
1792                 {
1793
1794                     pCurrentEntry->bLink->fLink = pCurrentEntry->fLink;
1795                 }
1796
1797                 if( pCurrentEntry->fLink == NULL)
1798                 {
1799
1800                     pCommSrvc->ResultPoolTail = pCurrentEntry->bLink;
1801
1802                     if( pCommSrvc->ResultPoolTail != NULL)
1803                     {
1804
1805                         pCommSrvc->ResultPoolTail->fLink = NULL;
1806                     }
1807                 }
1808                 else
1809                 {
1810
1811                     pCurrentEntry->fLink->bLink = pCurrentEntry->bLink;
1812                 }
1813
1814                 break;
1815             }
1816
1817             pCurrentEntry = pCurrentEntry->fLink;
1818         }
1819
1820         AFSReleaseResource( &pCommSrvc->ResultPoolLock);
1821
1822         if( pCurrentEntry == NULL)
1823         {
1824
1825             try_return( ntStatus = STATUS_INVALID_PARAMETER);
1826         }
1827
1828         //
1829         // If this is an IO request, unmap the user buffer
1830         //
1831
1832         if( pCurrentEntry->RequestType == AFS_REQUEST_TYPE_PROCESS_READ_FILE ||
1833             pCurrentEntry->RequestType == AFS_REQUEST_TYPE_PROCESS_WRITE_FILE)
1834         {
1835
1836             AFSFileIOCB *pFileIO = (AFSFileIOCB *)pCurrentEntry->Data;
1837
1838             if( pFileIO->MappedIOBuffer != NULL)
1839             {
1840                 MmUnmapLockedPages( pFileIO->MappedIOBuffer,
1841                                     (PMDL)pFileIO->SystemIOBufferMdl);
1842
1843                 pFileIO->MappedIOBuffer = NULL;
1844             }
1845         }
1846
1847         //
1848         // OK, move in the result information
1849         //
1850
1851         pCurrentEntry->ResultStatus = pResult->ResultStatus;
1852
1853         if( ( pCurrentEntry->ResultStatus == STATUS_SUCCESS ||
1854               pCurrentEntry->ResultStatus == STATUS_BUFFER_OVERFLOW) &&
1855             pCurrentEntry->ResultBufferLength != NULL &&
1856             pCurrentEntry->ResultBuffer != NULL)
1857         {
1858
1859             ASSERT( pResult->ResultBufferLength <= *(pCurrentEntry->ResultBufferLength));
1860
1861             ulCopyLen = pResult->ResultBufferLength;
1862
1863             if( ulCopyLen > *(pCurrentEntry->ResultBufferLength))
1864             {
1865                 ulCopyLen = *(pCurrentEntry->ResultBufferLength);
1866             }
1867
1868             *(pCurrentEntry->ResultBufferLength) = ulCopyLen;
1869
1870             if( pResult->ResultBufferLength > 0)
1871             {
1872
1873                 RtlCopyMemory( pCurrentEntry->ResultBuffer,
1874                                pResult->ResultData,
1875                                ulCopyLen);
1876             }
1877         }
1878
1879         KeSetEvent( &pCurrentEntry->Event,
1880                     0,
1881                     FALSE);
1882
1883 try_exit:
1884
1885         if( !NT_SUCCESS( ntStatus))
1886         {
1887
1888         }
1889     }
1890
1891     return ntStatus;
1892 }