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