Windows: Police the DEBUG TRACE 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 NTSTATUS
389 AFSProcessControlRequest( IN PIRP Irp)
390 {
391
392     NTSTATUS            ntStatus = STATUS_SUCCESS;
393     PIO_STACK_LOCATION  pIrpSp;
394     ULONG               ulIoControlCode;
395     BOOLEAN             bCompleteRequest = TRUE;
396     AFSDeviceExt       *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
397
398     __try
399     {
400
401         pIrpSp = IoGetCurrentIrpStackLocation( Irp);
402
403         ulIoControlCode = pIrpSp->Parameters.DeviceIoControl.IoControlCode;
404
405         switch( ulIoControlCode)
406         {
407
408             case IOCTL_AFS_INITIALIZE_CONTROL_DEVICE:
409             {
410                 if ( !AFSIsUser( SeExports->SeLocalSystemSid)
411 #if DBG
412                     && !BooleanFlagOn( AFSDebugFlags, AFS_DBG_DISABLE_SYSTEM_SID_CHECK)
413 #endif
414                     )
415                 {
416
417                     ntStatus = STATUS_ACCESS_DENIED;
418                     break;
419                 }
420                 //
421                 // Go intialize the pool
422                 //
423                 ntStatus = AFSInitIrpPool();
424
425                 if( !NT_SUCCESS( ntStatus))
426                 {
427
428                     //
429                     // Don't initialize
430                     //
431
432                     break;
433                 }
434
435                 //
436                 // Tag this instance as the one to close the irp pool when it is closed
437                 //
438
439                 pIrpSp->FileObject->FsContext = (void *)((ULONG_PTR)pIrpSp->FileObject->FsContext | AFS_CONTROL_INSTANCE);
440
441                 AFSRegisterService();
442
443                 break;
444             }
445
446             case IOCTL_AFS_INITIALIZE_REDIRECTOR_DEVICE:
447             {
448
449                 AFSRedirectorInitInfo *pRedirInitInfo = (AFSRedirectorInitInfo *)Irp->AssociatedIrp.SystemBuffer;
450
451                 if ( !AFSIsService())
452                 {
453
454                     ntStatus = STATUS_ACCESS_DENIED;
455
456                     break;
457                 }
458
459                 //
460                 // Extract off the passed in information which contains the
461                 // cache file parameters
462                 //
463
464                 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSRedirectorInitInfo) ||
465                     pIrpSp->Parameters.DeviceIoControl.InputBufferLength < (ULONG)FIELD_OFFSET( AFSRedirectorInitInfo, CacheFileName) +
466                                                                                                     pRedirInitInfo->CacheFileNameLength)
467                 {
468
469                     ntStatus = STATUS_INVALID_PARAMETER;
470
471                     break;
472                 }
473
474                 //
475                 // Initialize the Redirector device
476                 //
477
478                 ntStatus = AFSInitializeRedirector( pRedirInitInfo);
479
480                 if( !NT_SUCCESS( ntStatus))
481                 {
482
483                     break;
484                 }
485
486                 //
487                 // Stash away context so we know the instance used to initialize the redirector
488                 //
489
490                 pIrpSp->FileObject->FsContext = (void *)((ULONG_PTR)pIrpSp->FileObject->FsContext | AFS_REDIRECTOR_INSTANCE);
491
492                 break;
493             }
494
495             case IOCTL_AFS_PROCESS_IRP_REQUEST:
496             {
497
498                 if ( !AFSIsService())
499                 {
500
501                     ntStatus = STATUS_ACCESS_DENIED;
502
503                     break;
504                 }
505
506                 ntStatus = AFSProcessIrpRequest( Irp);
507
508                 break;
509             }
510
511             case IOCTL_AFS_PROCESS_IRP_RESULT:
512             {
513
514                 if ( !AFSIsService())
515                 {
516
517                     ntStatus = STATUS_ACCESS_DENIED;
518
519                     break;
520                 }
521
522                 ntStatus = AFSProcessIrpResult( Irp);
523
524                 break;
525             }
526
527             case IOCTL_AFS_SYSNAME_NOTIFICATION:
528             {
529
530                 AFSSysNameNotificationCB *pSysNameInfo = (AFSSysNameNotificationCB *)Irp->AssociatedIrp.SystemBuffer;
531
532                 if ( !AFSIsService())
533                 {
534
535                     ntStatus = STATUS_ACCESS_DENIED;
536
537                     break;
538                 }
539
540                 if( pSysNameInfo == NULL ||
541                     pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSSysNameNotificationCB))
542                 {
543
544                     ntStatus = STATUS_INVALID_PARAMETER;
545
546                     break;
547                 }
548
549                 ntStatus = AFSSetSysNameInformation( pSysNameInfo,
550                                                      pIrpSp->Parameters.DeviceIoControl.InputBufferLength);
551
552                 break;
553             }
554
555             case IOCTL_AFS_CONFIGURE_DEBUG_TRACE:
556             {
557
558                 AFSTraceConfigCB *pTraceInfo = (AFSTraceConfigCB *)Irp->AssociatedIrp.SystemBuffer;
559
560                 if ( !AFSIsInGroup( SeExports->SeAliasAdminsSid))
561                 {
562
563                     ntStatus = STATUS_ACCESS_DENIED;
564                     break;
565                 }
566
567                 if( pTraceInfo == NULL ||
568                     pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSTraceConfigCB))
569                 {
570
571                     ntStatus = STATUS_INVALID_PARAMETER;
572
573                     break;
574                 }
575
576                 ntStatus = AFSConfigureTrace( pTraceInfo);
577
578                 break;
579             }
580
581             case IOCTL_AFS_GET_TRACE_BUFFER:
582             {
583
584                 if ( !AFSIsInGroup( SeExports->SeAliasAdminsSid))
585                 {
586
587                     ntStatus = STATUS_ACCESS_DENIED;
588                     break;
589                 }
590
591                 if( pIrpSp->Parameters.DeviceIoControl.OutputBufferLength == 0)
592                 {
593
594                     ntStatus = STATUS_INVALID_PARAMETER;
595
596                     break;
597                 }
598
599                 ntStatus = AFSGetTraceBuffer( pIrpSp->Parameters.DeviceIoControl.OutputBufferLength,
600                                               Irp->AssociatedIrp.SystemBuffer,
601                                               &Irp->IoStatus.Information);
602
603                 break;
604             }
605
606             case IOCTL_AFS_FORCE_CRASH:
607             {
608
609                 if ( !AFSIsInGroup( SeExports->SeAliasAdminsSid))
610                 {
611
612                     ntStatus = STATUS_ACCESS_DENIED;
613                     break;
614                 }
615
616 #if DBG
617
618                 if( BooleanFlagOn( AFSDebugFlags, AFS_DBG_FLAG_ENABLE_FORCE_CRASH))
619                 {
620
621                     KeBugCheck( (ULONG)-1);
622                 }
623 #endif
624
625                 break;
626             }
627
628 #ifdef NOT_IMPLEMENTED
629             case IOCTL_AFS_LOAD_LIBRARY:
630             {
631
632                 AFSLoadLibraryCB *pLoadLib = (AFSLoadLibraryCB *)Irp->AssociatedIrp.SystemBuffer;
633                 UNICODE_STRING uniServicePath;
634
635                 if( pLoadLib == NULL ||
636                     pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSLoadLibraryCB) ||
637                     pIrpSp->Parameters.DeviceIoControl.InputBufferLength < (ULONG)FIELD_OFFSET( AFSLoadLibraryCB, LibraryServicePath) +
638                                                                                                     pLoadLib->LibraryServicePathLength)
639                 {
640
641                     ntStatus = STATUS_INVALID_PARAMETER;
642
643                     break;
644                 }
645
646                 uniServicePath.Length = pLoadLib->LibraryServicePathLength;
647                 uniServicePath.MaximumLength = uniServicePath.Length;
648
649                 uniServicePath.Buffer = pLoadLib->LibraryServicePath;
650
651                 if( uniServicePath.Length == 0)
652                 {
653
654                     ntStatus = STATUS_INVALID_PARAMETER;
655
656                     break;
657                 }
658
659                 ntStatus = AFSLoadLibrary( pLoadLib->Flags,
660                                            &uniServicePath);
661
662                 if( NT_SUCCESS( ntStatus))
663                 {
664
665                     //
666                     // Intialize the library
667                     //
668
669                     ntStatus = AFSInitializeLibrary( NULL,
670                                                      FALSE);
671                 }
672
673                 break;
674             }
675
676             case IOCTL_AFS_UNLOAD_LIBRARY:
677             {
678
679                 //
680                 // Try to unload the library we currently have in place
681                 //
682
683                 ntStatus = AFSUnloadLibrary( FALSE);
684
685                 break;
686             }
687 #endif
688
689             case IOCTL_AFS_SHUTDOWN:
690             {
691
692                 if ( !AFSIsService())
693                 {
694
695                     ntStatus = STATUS_ACCESS_DENIED;
696
697                     break;
698                 }
699
700                 ntStatus = AFSShutdownRedirector();
701
702                 break;
703             }
704
705             case IOCTL_AFS_AUTHGROUP_CREATE_AND_SET:
706             {
707
708                 AFSAuthGroupRequestCB *pAuthGroupRequestCB = (AFSAuthGroupRequestCB *)Irp->AssociatedIrp.SystemBuffer;
709
710                 if( pAuthGroupRequestCB == NULL ||
711                     pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSAuthGroupRequestCB))
712                 {
713
714                     ntStatus = STATUS_INVALID_PARAMETER;
715
716                     break;
717                 }
718
719                 ntStatus = AFSCreateSetProcessAuthGroup( pAuthGroupRequestCB);
720
721                 break;
722             }
723
724             case IOCTL_AFS_AUTHGROUP_QUERY:
725             {
726
727                 ntStatus = AFSQueryProcessAuthGroupList( ( GUID *)Irp->AssociatedIrp.SystemBuffer,
728                                                          pIrpSp->Parameters.DeviceIoControl.OutputBufferLength,
729                                                          &Irp->IoStatus.Information);
730
731                 break;
732             }
733
734             case IOCTL_AFS_AUTHGROUP_SET:
735             {
736
737                 AFSAuthGroupRequestCB *pAuthGroupRequestCB = (AFSAuthGroupRequestCB *)Irp->AssociatedIrp.SystemBuffer;
738
739                 if( pAuthGroupRequestCB == NULL ||
740                     pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSAuthGroupRequestCB))
741                 {
742
743                     ntStatus = STATUS_INVALID_PARAMETER;
744
745                     break;
746                 }
747
748                 ntStatus = AFSSetActiveProcessAuthGroup( pAuthGroupRequestCB);
749
750                 break;
751             }
752
753             case IOCTL_AFS_AUTHGROUP_RESET:
754             {
755
756                 AFSAuthGroupRequestCB *pAuthGroupRequestCB = (AFSAuthGroupRequestCB *)Irp->AssociatedIrp.SystemBuffer;
757
758                 if( pAuthGroupRequestCB == NULL ||
759                     pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSAuthGroupRequestCB))
760                 {
761
762                     ntStatus = STATUS_INVALID_PARAMETER;
763
764                     break;
765                 }
766
767                 ntStatus = AFSResetActiveProcessAuthGroup( pAuthGroupRequestCB);
768
769                 break;
770             }
771
772             case IOCTL_AFS_AUTHGROUP_LOGON_CREATE:
773             case IOCTL_AFS_AUTHGROUP_SID_CREATE:
774             {
775
776                 AFSAuthGroupRequestCB *pAuthGroupRequestCB = (AFSAuthGroupRequestCB *)Irp->AssociatedIrp.SystemBuffer;
777
778                 if( pAuthGroupRequestCB != NULL &&
779                     pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSAuthGroupRequestCB))
780                 {
781
782                     ntStatus = STATUS_INVALID_PARAMETER;
783
784                     break;
785                 }
786
787                 ntStatus = AFSCreateAuthGroupForSIDorLogonSession( pAuthGroupRequestCB,
788                                                                    ulIoControlCode == IOCTL_AFS_AUTHGROUP_LOGON_CREATE);
789
790                 break;
791             }
792
793             case IOCTL_AFS_AUTHGROUP_SID_QUERY:
794             {
795
796                 AFSAuthGroupRequestCB *pAuthGroupRequestCB = NULL;
797
798                 if( pIrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof( GUID))
799                 {
800                     ntStatus = STATUS_INVALID_PARAMETER;
801                     break;
802                 }
803
804                 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength >= sizeof( AFSAuthGroupRequestCB))
805                 {
806                     pAuthGroupRequestCB = (AFSAuthGroupRequestCB *)Irp->AssociatedIrp.SystemBuffer;
807                 }
808
809                 ntStatus = AFSQueryAuthGroup( pAuthGroupRequestCB,
810                                               (GUID *)Irp->AssociatedIrp.SystemBuffer,
811                                               &Irp->IoStatus.Information);
812
813                 break;
814             }
815
816             default:
817             {
818
819                 //
820                 // Check the state of the library
821                 //
822
823                 ntStatus = AFSCheckLibraryState( Irp);
824
825                 if( !NT_SUCCESS( ntStatus) ||
826                     ntStatus == STATUS_PENDING)
827                 {
828
829                     if( ntStatus == STATUS_PENDING)
830                     {
831                         bCompleteRequest = FALSE;
832                     }
833
834                     break;
835                 }
836
837                 bCompleteRequest = FALSE;
838
839                 IoSkipCurrentIrpStackLocation( Irp);
840
841                 ntStatus = IoCallDriver( pDevExt->Specific.Control.LibraryDeviceObject,
842                                          Irp);
843
844                 //
845                 // Indicate the library is done with the request
846                 //
847
848                 AFSClearLibraryRequest();
849
850                 break;
851             }
852         }
853
854 //try_exit:
855
856     }
857     __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()))
858     {
859
860         ntStatus = STATUS_UNSUCCESSFUL;
861
862         AFSDumpTraceFilesFnc();
863     }
864
865     if( bCompleteRequest)
866     {
867
868         Irp->IoStatus.Status = ntStatus;
869
870         AFSCompleteRequest( Irp,
871                               ntStatus);
872     }
873
874     return ntStatus;
875 }
876
877 NTSTATUS
878 AFSInitIrpPool()
879 {
880
881     NTSTATUS       ntStatus = STATUS_SUCCESS;
882     AFSCommSrvcCB *pCommSrvc = NULL;
883     BOOLEAN        bReleasePools = FALSE;
884     AFSDeviceExt  *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
885
886     __Enter
887     {
888
889         pCommSrvc = &pDevExt->Specific.Control.CommServiceCB;
890
891         //
892         // Whenever we change state we must grab both pool locks. On the checking of the state
893         // within the processing routines for these respective pools, we only grab one lock to
894         // minimize serialization. The ordering is always the Irp pool then the result pool
895         // locks. We also do this in the tear down of the pool
896         //
897
898         AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
899                       AFS_TRACE_LEVEL_VERBOSE,
900                       "AFSInitIrpPool Acquiring IrpPoolLock lock %08lX EXCL %08lX\n",
901                       &pCommSrvc->IrpPoolLock,
902                       PsGetCurrentThread());
903
904         AFSAcquireExcl( &pCommSrvc->IrpPoolLock,
905                           TRUE);
906
907         AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
908                       AFS_TRACE_LEVEL_VERBOSE,
909                       "AFSInitIrpPool Acquiring ResultPoolLock lock %08lX EXCL %08lX\n",
910                       &pCommSrvc->ResultPoolLock,
911                       PsGetCurrentThread());
912
913         AFSAcquireExcl( &pCommSrvc->ResultPoolLock,
914                           TRUE);
915
916         bReleasePools = TRUE;
917
918         //
919         // The pool can be either ACTIVE or INACTIVE. If the pool state is INACTIVE and we
920         // are receiving the INIT request, then activate it. If the pool is ACTIVE, then we
921         // shouldn't be getting this request ...
922         //
923
924         if( pCommSrvc->IrpPoolControlFlag == POOL_ACTIVE)
925         {
926
927             //
928             // We have already been activated so just fail this request
929             //
930
931             try_return( ntStatus = STATUS_INVALID_PARAMETER);
932         }
933         else if( pCommSrvc->IrpPoolControlFlag == POOL_INACTIVE)
934         {
935
936             //
937             // The pool is currently INACTIVE so start it up and ready it to
938             // receive irp requests
939             //
940
941             pCommSrvc->IrpPoolControlFlag = POOL_ACTIVE;
942
943             pDevExt->Specific.Control.ServiceProcess = (PKPROCESS)PsGetCurrentProcess();
944
945             try_return( ntStatus = STATUS_SUCCESS);
946         }
947         else
948         {
949
950             //
951             // The pool is in some mixed state, fail the request.
952             //
953
954             try_return( ntStatus = STATUS_DEVICE_NOT_READY);
955         }
956
957 try_exit:
958
959         if( bReleasePools)
960         {
961
962             AFSReleaseResource( &pCommSrvc->IrpPoolLock);
963
964             AFSReleaseResource( &pCommSrvc->ResultPoolLock);
965         }
966     }
967
968     return ntStatus;
969 }
970
971 void
972 AFSCleanupIrpPool()
973 {
974
975     AFSPoolEntry   *pEntry = NULL, *pNextEntry = NULL;
976     AFSDeviceExt   *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
977     AFSCommSrvcCB  *pCommSrvc = (AFSCommSrvcCB *)&pDevExt->Specific.Control.CommServiceCB;
978
979     __Enter
980     {
981
982         //
983         // When we change the state, grab both pool locks exclusive. The order is always the
984         // Irp pool then the result pool lock
985         //
986
987         AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
988                       AFS_TRACE_LEVEL_VERBOSE,
989                       "AFSCleanupIrpPool Acquiring IrpPoolLock lock %08lX EXCL %08lX\n",
990                       &pCommSrvc->IrpPoolLock,
991                       PsGetCurrentThread());
992
993         AFSAcquireExcl( &pCommSrvc->IrpPoolLock,
994                         TRUE);
995
996         AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
997                       AFS_TRACE_LEVEL_VERBOSE,
998                       "AFSCleanupIrpPool Acquiring ResultPoolLock lock %08lX EXCL %08lX\n",
999                       &pCommSrvc->ResultPoolLock,
1000                       PsGetCurrentThread());
1001
1002         AFSAcquireExcl( &pCommSrvc->ResultPoolLock,
1003                         TRUE);
1004
1005         //
1006         // Indicate we are pending stop
1007         //
1008
1009         pCommSrvc->IrpPoolControlFlag = POOL_INACTIVE;
1010
1011         //
1012         // Set the event to release any waiting workers
1013         // (everyone waits on IrpPoolHasReleaseEntries)
1014         //
1015
1016         KeSetEvent( &pCommSrvc->IrpPoolHasReleaseEntries,
1017                     0,
1018                     FALSE);
1019
1020         //
1021         // Go through the pool entries and free up the structures.
1022         //
1023
1024         pEntry = pCommSrvc->RequestPoolHead;
1025
1026         while( pEntry != NULL)
1027         {
1028
1029             pNextEntry = pEntry->fLink;
1030
1031             if( BooleanFlagOn( pEntry->RequestFlags, AFS_REQUEST_FLAG_SYNCHRONOUS))
1032             {
1033
1034                 //
1035                 // Here we need to complete the irp, cancelled, and delete the data block
1036                 //
1037
1038                 pEntry->ResultStatus = (ULONG) STATUS_CANCELLED;
1039
1040                 KeSetEvent( &pEntry->Event,
1041                             0,
1042                             FALSE);
1043             }
1044             else
1045             {
1046
1047                 ExFreePool( pEntry);
1048             }
1049
1050             pEntry = pNextEntry;
1051         }
1052
1053         //
1054         // Cleanup the control structure for the request pool
1055         //
1056
1057         pCommSrvc->RequestPoolHead = NULL;
1058
1059         pCommSrvc->RequestPoolTail = NULL;
1060
1061         pCommSrvc->IrpPoolRequestIndex = 1;
1062
1063         KeClearEvent( &pCommSrvc->IrpPoolHasEntries);
1064
1065         KeClearEvent( &pCommSrvc->IrpPoolHasReleaseEntries);
1066
1067         //
1068         // Release the irp pool lock.
1069         //
1070
1071         AFSReleaseResource( &pCommSrvc->IrpPoolLock);
1072
1073         //
1074         // Go through the result pool entries and free up the structures.
1075         //
1076
1077         pEntry = pCommSrvc->ResultPoolHead;
1078
1079         while( pEntry != NULL)
1080         {
1081
1082             pNextEntry = pEntry->fLink;
1083
1084             pEntry->ResultStatus = (ULONG) STATUS_CANCELLED;
1085
1086             //
1087             // Here we will set the event of the requestor and let the blocked thread
1088             // free the data block
1089             //
1090
1091             KeSetEvent( &pEntry->Event,
1092                         0,
1093                         FALSE);
1094
1095             //
1096             // Go onto the next entry
1097             //
1098
1099             pEntry = pNextEntry;
1100         }
1101
1102         //
1103         // Cleanup the control structure for the result pool
1104         //
1105
1106         pCommSrvc->ResultPoolHead = NULL;
1107
1108         pCommSrvc->ResultPoolTail = NULL;
1109
1110         //
1111         // Release the result pool lock.
1112         //
1113
1114         AFSReleaseResource( &pCommSrvc->ResultPoolLock);
1115
1116     }
1117
1118     return;
1119 }
1120
1121 NTSTATUS
1122 AFSInsertRequest( IN AFSCommSrvcCB *CommSrvc,
1123                   IN AFSPoolEntry *Entry)
1124 {
1125
1126     NTSTATUS ntStatus = STATUS_SUCCESS;
1127
1128     __Enter
1129     {
1130
1131         AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1132                       AFS_TRACE_LEVEL_VERBOSE,
1133                       "AFSInsertRequest Acquiring IrpPoolLock lock %08lX EXCL %08lX\n",
1134                       &CommSrvc->IrpPoolLock,
1135                       PsGetCurrentThread());
1136
1137         AFSAcquireExcl( &CommSrvc->IrpPoolLock,
1138                         TRUE);
1139
1140         if( CommSrvc->IrpPoolControlFlag != POOL_ACTIVE)
1141         {
1142
1143             try_return( ntStatus = STATUS_DEVICE_NOT_READY);
1144         }
1145
1146         if( CommSrvc->RequestPoolHead == NULL)
1147         {
1148
1149             CommSrvc->RequestPoolHead = Entry;
1150         }
1151         else
1152         {
1153
1154             CommSrvc->RequestPoolTail->fLink = Entry;
1155
1156             Entry->bLink = CommSrvc->RequestPoolTail;
1157         }
1158
1159         CommSrvc->RequestPoolTail = Entry;
1160
1161         if( Entry->RequestType == AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS)
1162         {
1163
1164             KeSetEvent( &CommSrvc->IrpPoolHasReleaseEntries,
1165                         0,
1166                         FALSE);
1167         }
1168         else
1169         {
1170
1171             KeSetEvent( &CommSrvc->IrpPoolHasEntries,
1172                         0,
1173                         FALSE);
1174         }
1175
1176         InterlockedIncrement( &CommSrvc->QueueCount);
1177
1178 try_exit:
1179
1180         AFSReleaseResource( &CommSrvc->IrpPoolLock);
1181     }
1182
1183     return ntStatus;
1184 }
1185
1186 NTSTATUS
1187 AFSProcessIrpRequest( IN PIRP Irp)
1188 {
1189
1190     NTSTATUS         ntStatus = STATUS_SUCCESS;
1191     AFSDeviceExt    *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
1192     IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1193     AFSCommSrvcCB   *pCommSrvc = NULL;
1194     AFSPoolEntry    *pEntry = NULL, *pPrevEntry = NULL;
1195     AFSCommRequest  *pRequest = NULL;
1196     BOOLEAN          bReleaseRequestThread = FALSE;
1197     PVOID            Objects[2];
1198
1199     __Enter
1200     {
1201
1202         pCommSrvc = &pDevExt->Specific.Control.CommServiceCB;
1203
1204         pRequest = (AFSCommRequest *)Irp->AssociatedIrp.SystemBuffer;
1205
1206         AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1207                       AFS_TRACE_LEVEL_VERBOSE,
1208                       "AFSProcessIrpRequest Acquiring IrpPoolLock lock %08lX EXCL %08lX\n",
1209                       &pCommSrvc->IrpPoolLock,
1210                       PsGetCurrentThread());
1211
1212         AFSAcquireExcl( &pCommSrvc->IrpPoolLock,
1213                         TRUE);
1214
1215         if( pCommSrvc->IrpPoolControlFlag != POOL_ACTIVE)
1216         {
1217
1218             AFSReleaseResource( &pCommSrvc->IrpPoolLock);
1219
1220             try_return( ntStatus = STATUS_DEVICE_NOT_READY);
1221         }
1222
1223         AFSReleaseResource( &pCommSrvc->IrpPoolLock);
1224
1225         //
1226         // Is this a dedicated flush thread?
1227         //
1228
1229         if( BooleanFlagOn( pRequest->RequestFlags, AFS_REQUEST_RELEASE_THREAD))
1230         {
1231
1232             bReleaseRequestThread = TRUE;
1233         }
1234
1235         //
1236         // Populate the objects array for the non release only threads
1237         // Release only workers can only process release extent events
1238         // whereas normal workers can process any kind of event.
1239         // Release only workers are present to ensure there cannot be
1240         // a deadlock due to all extents held by the redirector and
1241         // there not be a worker available to release them.
1242         //
1243
1244         Objects[0] = &pCommSrvc->IrpPoolHasReleaseEntries;
1245
1246         Objects[1] = &pCommSrvc->IrpPoolHasEntries;
1247
1248         //
1249         // Wait on the 'have items' event until we can retrieve an item
1250         //
1251
1252         while( TRUE)
1253         {
1254
1255             if( bReleaseRequestThread)
1256             {
1257
1258                 ntStatus = KeWaitForSingleObject( &pCommSrvc->IrpPoolHasReleaseEntries,
1259                                                   UserRequest,
1260                                                   UserMode,
1261                                                   TRUE,
1262                                                   NULL);
1263
1264                 if( ntStatus != STATUS_SUCCESS)
1265                 {
1266
1267                     ntStatus = STATUS_DEVICE_NOT_READY;
1268
1269                     break;
1270                 }
1271
1272             }
1273             else
1274             {
1275
1276                 ntStatus = KeWaitForMultipleObjects( 2,
1277                                                      Objects,
1278                                                      WaitAny,
1279                                                      UserRequest,
1280                                                      UserMode,
1281                                                      TRUE,
1282                                                      NULL,
1283                                                      NULL);
1284
1285                 if( ntStatus != STATUS_WAIT_0 &&
1286                     ntStatus != STATUS_WAIT_1)
1287                 {
1288
1289                     ntStatus = STATUS_DEVICE_NOT_READY;
1290
1291                     break;
1292                 }
1293             }
1294
1295             //
1296             // Grab the lock on the request pool
1297             //
1298
1299             AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1300                           AFS_TRACE_LEVEL_VERBOSE,
1301                           "AFSProcessIrpRequest Acquiring IrpPoolLock (WAIT) lock %08lX EXCL %08lX\n",
1302                           &pCommSrvc->IrpPoolLock,
1303                           PsGetCurrentThread());
1304
1305             AFSAcquireExcl( &pCommSrvc->IrpPoolLock,
1306                             TRUE);
1307
1308             if( pCommSrvc->IrpPoolControlFlag != POOL_ACTIVE)
1309             {
1310
1311                 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
1312
1313                 //
1314                 // Wake up the next worker since this is a SynchronizationEvent
1315                 //
1316
1317                 KeSetEvent( &pCommSrvc->IrpPoolHasReleaseEntries,
1318                             0,
1319                             FALSE);
1320
1321                 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
1322             }
1323
1324             //
1325             // If this is a dedicated flush thread only look for a flush request in the queue
1326             //
1327
1328             if( bReleaseRequestThread)
1329             {
1330
1331                 pEntry = pCommSrvc->RequestPoolHead;
1332
1333                 pPrevEntry = NULL;
1334
1335                 while( pEntry != NULL)
1336                 {
1337
1338                     if( pEntry->RequestType == AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS)
1339                     {
1340
1341                         if( pPrevEntry == NULL)
1342                         {
1343
1344                             pCommSrvc->RequestPoolHead = pEntry->fLink;
1345
1346                             if( pCommSrvc->RequestPoolHead == NULL)
1347                             {
1348
1349                                 pCommSrvc->RequestPoolTail = NULL;
1350                             }
1351                         }
1352                         else
1353                         {
1354
1355                             pPrevEntry->fLink = pEntry->fLink;
1356
1357                             if( pPrevEntry->fLink == NULL)
1358                             {
1359
1360                                 pCommSrvc->RequestPoolTail = pPrevEntry;
1361                             }
1362                         }
1363
1364                         break;
1365                     }
1366
1367                     pPrevEntry = pEntry;
1368
1369                     pEntry = pEntry->fLink;
1370                 }
1371
1372                 if( pEntry != NULL)
1373                 {
1374
1375                     //
1376                     // There might be another release entry pending
1377                     //
1378
1379                     KeSetEvent( &pCommSrvc->IrpPoolHasReleaseEntries,
1380                                 0,
1381                                 FALSE);
1382                 }
1383
1384                 //
1385                 // And release the request pool lock
1386                 //
1387
1388                 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
1389             }
1390             else
1391             {
1392
1393                 pEntry = pCommSrvc->RequestPoolHead;
1394
1395                 if( pEntry != NULL)
1396                 {
1397
1398                     pCommSrvc->RequestPoolHead = pEntry->fLink;
1399
1400                     pEntry->bLink = NULL;
1401
1402                     if( pCommSrvc->RequestPoolHead == NULL)
1403                     {
1404
1405                         pCommSrvc->RequestPoolTail = NULL;
1406                     }
1407                     else
1408                     {
1409
1410                         KeSetEvent( &pCommSrvc->IrpPoolHasEntries,
1411                                     0,
1412                                     FALSE);
1413                     }
1414                 }
1415
1416                 //
1417                 // And release the request pool lock
1418                 //
1419
1420                 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
1421             }
1422
1423             //
1424             // Insert the entry into the result pool, if we have one
1425             //
1426
1427             if( pEntry != NULL)
1428             {
1429
1430                 //
1431                 // Move the request data into the passed in buffer
1432                 //
1433
1434                 ASSERT( sizeof( AFSCommRequest) +
1435                                     pEntry->FileName.Length +
1436                                     pEntry->DataLength <= pIrpSp->Parameters.DeviceIoControl.OutputBufferLength);
1437
1438                 RtlCopyMemory( &pRequest->AuthGroup,
1439                                &pEntry->AuthGroup,
1440                                sizeof( GUID));
1441
1442                 pRequest->FileId = pEntry->FileId;
1443
1444                 pRequest->RequestType = pEntry->RequestType;
1445
1446                 pRequest->RequestIndex = pEntry->RequestIndex;
1447
1448                 pRequest->RequestFlags = pEntry->RequestFlags;
1449
1450                 pRequest->NameLength = pEntry->FileName.Length;
1451
1452                 pRequest->QueueCount = InterlockedDecrement( &pCommSrvc->QueueCount);
1453
1454                 if( pRequest->NameLength > 0)
1455                 {
1456
1457                     RtlCopyMemory( pRequest->Name,
1458                                    pEntry->FileName.Buffer,
1459                                    pRequest->NameLength);
1460                 }
1461
1462                 pRequest->DataOffset = 0;
1463
1464                 pRequest->DataLength = pEntry->DataLength;
1465
1466                 if( pRequest->DataLength > 0)
1467                 {
1468
1469                     pRequest->DataOffset = pEntry->FileName.Length;
1470
1471                     RtlCopyMemory( (void *)((char *)pRequest->Name + pRequest->DataOffset),
1472                                    pEntry->Data,
1473                                    pRequest->DataLength);
1474                 }
1475
1476                 pRequest->ResultBufferLength = 0;
1477
1478                 if( pEntry->ResultBufferLength != NULL)
1479                 {
1480
1481                     pRequest->ResultBufferLength = *(pEntry->ResultBufferLength);
1482                 }
1483
1484                 Irp->IoStatus.Information = sizeof( AFSCommRequest) +
1485                                                         pEntry->FileName.Length +
1486                                                         pEntry->DataLength;
1487
1488                 //
1489                 // If this is a synchronous request then move the request into the
1490                 // result pool
1491                 //
1492
1493                 if( BooleanFlagOn( pEntry->RequestFlags, AFS_REQUEST_FLAG_SYNCHRONOUS))
1494                 {
1495
1496                     pEntry->fLink = NULL;
1497                     pEntry->bLink = NULL;
1498
1499                     AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1500                                   AFS_TRACE_LEVEL_VERBOSE,
1501                                   "AFSProcessIrpRequest Acquiring ResultPoolLock lock %08lX EXCL %08lX\n",
1502                                   &pCommSrvc->ResultPoolLock,
1503                                   PsGetCurrentThread());
1504
1505                     AFSAcquireExcl( &pCommSrvc->ResultPoolLock,
1506                                     TRUE);
1507
1508                     if( pCommSrvc->ResultPoolHead == NULL)
1509                     {
1510
1511                         pCommSrvc->ResultPoolHead = pEntry;
1512                     }
1513                     else
1514                     {
1515
1516                         pCommSrvc->ResultPoolTail->fLink = pEntry;
1517
1518                         pEntry->bLink = pCommSrvc->ResultPoolTail;
1519                     }
1520
1521                     pCommSrvc->ResultPoolTail = pEntry;
1522
1523                     AFSReleaseResource( &pCommSrvc->ResultPoolLock);
1524                 }
1525                 else
1526                 {
1527
1528                     //
1529                     // Free up the pool entry
1530                     //
1531
1532                     ExFreePool( pEntry);
1533                 }
1534
1535                 break;
1536             }
1537         }
1538
1539 try_exit:
1540
1541         NOTHING;
1542     }
1543
1544     return ntStatus;
1545 }
1546
1547 NTSTATUS
1548 AFSProcessIrpResult( IN PIRP Irp)
1549 {
1550
1551     NTSTATUS            ntStatus = STATUS_SUCCESS;
1552     AFSDeviceExt       *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
1553     AFSCommSrvcCB      *pCommSrvc = NULL;
1554     AFSPoolEntry       *pCurrentEntry = NULL;
1555     AFSCommResult      *pResult = NULL;
1556     ULONG               ulCopyLen = 0;
1557
1558     __Enter
1559     {
1560
1561         pCommSrvc = &pDevExt->Specific.Control.CommServiceCB;
1562
1563         //
1564         // Get the request for the incoming result
1565         //
1566
1567         pResult = (AFSCommResult *)Irp->AssociatedIrp.SystemBuffer;
1568
1569         if( pResult == NULL)
1570         {
1571
1572             try_return( ntStatus = STATUS_INVALID_PARAMETER);
1573         }
1574
1575         //
1576         // Go look for our entry
1577         //
1578
1579         AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1580                       AFS_TRACE_LEVEL_VERBOSE,
1581                       "AFSProcessIrpResult Acquiring ResultPoolLock lock %08lX EXCL %08lX\n",
1582                       &pCommSrvc->ResultPoolLock,
1583                       PsGetCurrentThread());
1584
1585         AFSAcquireExcl( &pCommSrvc->ResultPoolLock,
1586                           TRUE);
1587
1588         pCurrentEntry = pCommSrvc->ResultPoolHead;
1589
1590         while( pCurrentEntry != NULL)
1591         {
1592
1593             if( pCurrentEntry->RequestIndex == pResult->RequestIndex)
1594             {
1595
1596                 //
1597                 // Found the entry so remove it from the queue
1598                 //
1599
1600                 if( pCurrentEntry->bLink == NULL)
1601                 {
1602
1603                     //
1604                     // At the head of the list
1605                     //
1606
1607                     pCommSrvc->ResultPoolHead = pCurrentEntry->fLink;
1608
1609                     if( pCommSrvc->ResultPoolHead != NULL)
1610                     {
1611
1612                         pCommSrvc->ResultPoolHead->bLink = NULL;
1613                     }
1614                 }
1615                 else
1616                 {
1617
1618                     pCurrentEntry->bLink->fLink = pCurrentEntry->fLink;
1619                 }
1620
1621                 if( pCurrentEntry->fLink == NULL)
1622                 {
1623
1624                     pCommSrvc->ResultPoolTail = pCurrentEntry->bLink;
1625
1626                     if( pCommSrvc->ResultPoolTail != NULL)
1627                     {
1628
1629                         pCommSrvc->ResultPoolTail->fLink = NULL;
1630                     }
1631                 }
1632                 else
1633                 {
1634
1635                     pCurrentEntry->fLink->bLink = pCurrentEntry->bLink;
1636                 }
1637
1638                 break;
1639             }
1640
1641             pCurrentEntry = pCurrentEntry->fLink;
1642         }
1643
1644         AFSReleaseResource( &pCommSrvc->ResultPoolLock);
1645
1646         if( pCurrentEntry == NULL)
1647         {
1648
1649             try_return( ntStatus = STATUS_INVALID_PARAMETER);
1650         }
1651
1652         //
1653         // OK, move in the result information
1654         //
1655
1656         pCurrentEntry->ResultStatus = pResult->ResultStatus;
1657
1658         if( ( pCurrentEntry->ResultStatus == STATUS_SUCCESS ||
1659               pCurrentEntry->ResultStatus == STATUS_BUFFER_OVERFLOW) &&
1660             pCurrentEntry->ResultBufferLength != NULL &&
1661             pCurrentEntry->ResultBuffer != NULL)
1662         {
1663
1664             ASSERT( pResult->ResultBufferLength <= *(pCurrentEntry->ResultBufferLength));
1665
1666             ulCopyLen = pResult->ResultBufferLength;
1667
1668             if( ulCopyLen > *(pCurrentEntry->ResultBufferLength))
1669             {
1670                 ulCopyLen = *(pCurrentEntry->ResultBufferLength);
1671             }
1672
1673             *(pCurrentEntry->ResultBufferLength) = ulCopyLen;
1674
1675             if( pResult->ResultBufferLength > 0)
1676             {
1677
1678                 RtlCopyMemory( pCurrentEntry->ResultBuffer,
1679                                pResult->ResultData,
1680                                ulCopyLen);
1681             }
1682         }
1683
1684         KeSetEvent( &pCurrentEntry->Event,
1685                     0,
1686                     FALSE);
1687
1688 try_exit:
1689
1690         if( !NT_SUCCESS( ntStatus))
1691         {
1692
1693         }
1694     }
1695
1696     return ntStatus;
1697 }