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