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