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