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