Windows: Only allow the local system account to speak to the redirector
[openafs.git] / src / WINNT / afsrdr / kernel / fs / AFSCommSupport.cpp
1 /*
2  * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC.
3  * Copyright (c) 2009, 2010, 2011 Your File System, Inc.
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * - Redistributions of source code must retain the above copyright notice,
11  *   this list of conditions and the following disclaimer.
12  * - Redistributions in binary form must reproduce the above copyright
13  *   notice,
14  *   this list of conditions and the following disclaimer in the
15  *   documentation
16  *   and/or other materials provided with the distribution.
17  * - Neither the names of Kernel Drivers, LLC and Your File System, Inc.
18  *   nor the names of their contributors may be used to endorse or promote
19  *   products derived from this software without specific prior written
20  *   permission from Kernel Drivers, LLC and Your File System, Inc.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
25  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
26  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
27  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
29  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
30  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  */
34
35 //
36 // File: AFSCommSupport.cpp
37 //
38
39 #include "AFSCommon.h"
40
41 NTSTATUS
42 AFSReleaseFid( IN AFSFileID *FileId)
43 {
44
45     NTSTATUS ntStatus = STATUS_SUCCESS;
46
47     __Enter
48     {
49
50         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FID,
51                                       0,
52                                       NULL,
53                                       NULL,
54                                       FileId,
55                                       NULL,
56                                       0,
57                                       NULL,
58                                       NULL);
59     }
60
61     return ntStatus;
62 }
63
64 NTSTATUS
65 AFSProcessRequest( IN ULONG RequestType,
66                    IN ULONG RequestFlags,
67                    IN GUID *AuthGroup,
68                    IN PUNICODE_STRING FileName,
69                    IN AFSFileID *FileId,
70                    IN void  *Data,
71                    IN ULONG DataLength,
72                    IN OUT void *ResultBuffer,
73                    IN OUT PULONG ResultBufferLength)
74 {
75
76     NTSTATUS         ntStatus = STATUS_SUCCESS;
77     AFSPoolEntry     stPoolEntry, *pPoolEntry = NULL;
78     AFSCommSrvcCB   *pCommSrvc = NULL;
79     BOOLEAN          bReleasePool = FALSE;
80     AFSDeviceExt    *pControlDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
81     AFSDeviceExt    *pRDRDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
82     BOOLEAN          bWait = BooleanFlagOn( RequestFlags, AFS_REQUEST_FLAG_SYNCHRONOUS);
83     ULONG            ulPoolEntryLength = 0;
84     BOOLEAN          bDecrementCount = FALSE;
85
86     __try
87     {
88
89         if( BooleanFlagOn( pRDRDevExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
90         {
91             try_return( ntStatus = STATUS_DEVICE_NOT_READY);
92         }
93
94         if( InterlockedIncrement( &pControlDevExt->Specific.Control.OutstandingServiceRequestCount) == 1)
95         {
96             KeClearEvent( &pControlDevExt->Specific.Control.OutstandingServiceRequestEvent);
97         }
98
99         bDecrementCount = TRUE;
100
101         pCommSrvc = &pControlDevExt->Specific.Control.CommServiceCB;
102
103         //
104         // Grab the pool resource and check the state
105         //
106
107         AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
108                       AFS_TRACE_LEVEL_VERBOSE,
109                       "AFSProcessRequest Acquiring IrpPoolLock lock %08lX EXCL %08lX\n",
110                       &pCommSrvc->IrpPoolLock,
111                       PsGetCurrentThread());
112
113         AFSAcquireExcl( &pCommSrvc->IrpPoolLock,
114                         TRUE);
115
116         bReleasePool = TRUE;
117
118         if( pCommSrvc->IrpPoolControlFlag != POOL_ACTIVE)
119         {
120
121             //
122             // Pool not running so bail.
123             //
124
125             try_return( ntStatus = STATUS_DEVICE_NOT_READY);
126         }
127
128         //
129         // If this is an async request we need to allocate a pool entry for the request
130         //
131
132         pPoolEntry = &stPoolEntry;
133
134         if( !bWait)
135         {
136
137             ASSERT( ResultBuffer == NULL);
138
139             ulPoolEntryLength = sizeof( AFSPoolEntry) + QuadAlign( DataLength);
140
141             if( FileName != NULL)
142             {
143
144                 ulPoolEntryLength += FileName->Length;
145             }
146
147             pPoolEntry = (AFSPoolEntry *)AFSExAllocatePoolWithTag( NonPagedPool,
148                                                                    ulPoolEntryLength,
149                                                                    AFS_POOL_ENTRY_TAG);
150
151             if( pPoolEntry == NULL)
152             {
153
154                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
155             }
156
157             RtlZeroMemory( pPoolEntry,
158                            ulPoolEntryLength);
159
160             pPoolEntry->Data = (void *)((char *)pPoolEntry + sizeof( AFSPoolEntry));
161
162             pPoolEntry->FileName.Buffer = (WCHAR *)((char *)pPoolEntry->Data + DataLength);
163         }
164         else
165         {
166
167             RtlZeroMemory( pPoolEntry,
168                            sizeof( AFSPoolEntry));
169
170             KeInitializeEvent( &pPoolEntry->Event,
171                                NotificationEvent,
172                                FALSE);
173         }
174
175         pPoolEntry->RequestType = RequestType;
176
177         pPoolEntry->RequestIndex = pCommSrvc->IrpPoolRequestIndex++;
178
179         pPoolEntry->RequestFlags = RequestFlags;
180
181         pPoolEntry->ResultBufferLength = 0;
182
183         if( FileId != NULL)
184         {
185
186             pPoolEntry->FileId = *FileId;
187         }
188
189         pPoolEntry->FileName.Length = 0;
190
191         if( FileName != NULL)
192         {
193
194             if( bWait)
195             {
196
197                 pPoolEntry->FileName = *FileName;
198             }
199             else
200             {
201
202                 pPoolEntry->FileName.Length = FileName->Length;
203
204                 pPoolEntry->FileName.MaximumLength = pPoolEntry->FileName.Length;
205
206                 RtlCopyMemory( pPoolEntry->FileName.Buffer,
207                                FileName->Buffer,
208                                pPoolEntry->FileName.Length);
209             }
210         }
211
212         //
213         // Move in the data if there is some
214         //
215
216         pPoolEntry->DataLength = DataLength;
217
218         if( Data != NULL &&
219             DataLength > 0)
220         {
221
222             if( bWait)
223             {
224
225                 pPoolEntry->Data = Data;
226             }
227             else
228             {
229
230                 RtlCopyMemory( pPoolEntry->Data,
231                                Data,
232                                DataLength);
233             }
234         }
235
236         pPoolEntry->ResultBuffer = ResultBuffer;
237
238         pPoolEntry->ResultBufferLength = ResultBufferLength;
239
240         //
241         // Store off the auth group
242         //
243
244         if( AuthGroup == NULL)
245         {
246             AFSRetrieveAuthGroup( (ULONGLONG)PsGetCurrentProcessId(),
247                                   (ULONGLONG)PsGetCurrentThreadId(),
248                                   &pPoolEntry->AuthGroup);
249         }
250         else
251         {
252             RtlCopyMemory( &pPoolEntry->AuthGroup,
253                            AuthGroup,
254                            sizeof( GUID));
255         }
256
257         if( AFSIsLocalSystemAuthGroup( &pPoolEntry->AuthGroup))
258         {
259             SetFlag( pPoolEntry->RequestFlags, AFS_REQUEST_LOCAL_SYSTEM_PAG);
260         }
261
262         if( AFSIsNoPAGAuthGroup( &pPoolEntry->AuthGroup))
263         {
264             AFSDbgLogMsg( 0,
265                           0,
266                           "AFSProcessRequest NoPAG Auth Group %08lX\n",
267                           PsGetCurrentThread());
268         }
269
270         //
271         // Indicate the type of process
272         //
273
274 #ifdef AMD64
275
276         if( !AFSIs64BitProcess( (ULONGLONG)PsGetCurrentProcessId()))
277         {
278             SetFlag( pPoolEntry->RequestFlags, AFS_REQUEST_FLAG_WOW64);
279         }
280
281 #endif
282
283         //
284         // Insert the entry into the request pool
285         //
286
287         ntStatus = AFSInsertRequest( pCommSrvc,
288                                      pPoolEntry);
289
290         if( !NT_SUCCESS( ntStatus))
291         {
292
293             if( !bWait)
294             {
295
296                 ExFreePool( pPoolEntry);
297             }
298
299             try_return( ntStatus);
300         }
301
302         //
303         // Drop the lock on the pool prior to waiting
304         //
305
306         AFSReleaseResource( &pCommSrvc->IrpPoolLock);
307
308         bReleasePool = FALSE;
309
310         //
311         // Wait for the result if this is NOT an asynchronous request
312         //
313
314         if( bWait)
315         {
316
317             //
318             // Wait for the result of the request. We specify no timeout ...
319             //
320
321             ntStatus = KeWaitForSingleObject( &pPoolEntry->Event,
322                                               Executive,
323                                               KernelMode,
324                                               FALSE,
325                                               NULL);
326
327             //
328             // Process the result of the request
329             //
330
331             if( ntStatus == STATUS_SUCCESS)
332             {
333
334                 ntStatus = pPoolEntry->ResultStatus;
335             }
336             else
337             {
338
339                 ntStatus = STATUS_DEVICE_NOT_READY;
340             }
341         }
342
343 try_exit:
344
345         if( bReleasePool)
346         {
347
348             AFSReleaseResource( &pCommSrvc->IrpPoolLock);
349         }
350
351         if( bDecrementCount &&
352             InterlockedDecrement( &pControlDevExt->Specific.Control.OutstandingServiceRequestCount) == 0)
353         {
354             KeSetEvent( &pControlDevExt->Specific.Control.OutstandingServiceRequestEvent,
355                         0,
356                         FALSE);
357         }
358     }
359     __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()))
360     {
361
362         AFSDumpTraceFilesFnc();
363
364         if( bReleasePool)
365         {
366
367             AFSReleaseResource( &pCommSrvc->IrpPoolLock);
368         }
369
370         if( bDecrementCount &&
371             InterlockedDecrement( &pControlDevExt->Specific.Control.OutstandingServiceRequestCount) == 0)
372         {
373             KeSetEvent( &pControlDevExt->Specific.Control.OutstandingServiceRequestEvent,
374                         0,
375                         FALSE);
376         }
377
378         if ( ntStatus == STATUS_SUCCESS)
379         {
380
381             ntStatus = STATUS_UNSUCCESSFUL;
382         }
383     }
384
385     return ntStatus;
386 }
387
388 NTSTATUS
389 AFSProcessControlRequest( IN PIRP Irp)
390 {
391
392     NTSTATUS            ntStatus = STATUS_SUCCESS;
393     PIO_STACK_LOCATION  pIrpSp;
394     ULONG               ulIoControlCode;
395     BOOLEAN             bCompleteRequest = TRUE;
396     AFSDeviceExt       *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
397
398     __try
399     {
400
401         pIrpSp = IoGetCurrentIrpStackLocation( Irp);
402
403         ulIoControlCode = pIrpSp->Parameters.DeviceIoControl.IoControlCode;
404
405         switch( ulIoControlCode)
406         {
407
408             case IOCTL_AFS_INITIALIZE_CONTROL_DEVICE:
409             {
410                 if ( !AFSIsUser( SeExports->SeLocalSystemSid)
411 #if DBG
412                     && !BooleanFlagOn( AFSDebugFlags, AFS_DBG_DISABLE_SYSTEM_SID_CHECK)
413 #endif
414                     )
415                 {
416
417                     ntStatus = STATUS_ACCESS_DENIED;
418                     break;
419                 }
420                 //
421                 // Go intialize the pool
422                 //
423                 ntStatus = AFSInitIrpPool();
424
425                 if( !NT_SUCCESS( ntStatus))
426                 {
427
428                     //
429                     // Don't initialize
430                     //
431
432                     break;
433                 }
434
435                 //
436                 // Tag this instance as the one to close the irp pool when it is closed
437                 //
438
439                 pIrpSp->FileObject->FsContext = (void *)((ULONG_PTR)pIrpSp->FileObject->FsContext | AFS_CONTROL_INSTANCE);
440
441                 break;
442             }
443
444             case IOCTL_AFS_INITIALIZE_REDIRECTOR_DEVICE:
445             {
446
447                 AFSRedirectorInitInfo *pRedirInitInfo = (AFSRedirectorInitInfo *)Irp->AssociatedIrp.SystemBuffer;
448
449                 //
450                 // Extract off the passed in information which contains the
451                 // cache file parameters
452                 //
453
454                 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSRedirectorInitInfo) ||
455                     pIrpSp->Parameters.DeviceIoControl.InputBufferLength < (ULONG)FIELD_OFFSET( AFSRedirectorInitInfo, CacheFileName) +
456                                                                                                     pRedirInitInfo->CacheFileNameLength)
457                 {
458
459                     ntStatus = STATUS_INVALID_PARAMETER;
460
461                     break;
462                 }
463
464                 //
465                 // Initialize the Redirector device
466                 //
467
468                 ntStatus = AFSInitializeRedirector( pRedirInitInfo);
469
470                 if( !NT_SUCCESS( ntStatus))
471                 {
472
473                     break;
474                 }
475
476                 //
477                 // Stash away context so we know the instance used to initialize the redirector
478                 //
479
480                 pIrpSp->FileObject->FsContext = (void *)((ULONG_PTR)pIrpSp->FileObject->FsContext | AFS_REDIRECTOR_INSTANCE);
481
482                 break;
483             }
484
485             case IOCTL_AFS_PROCESS_IRP_REQUEST:
486             {
487
488                 ntStatus = AFSProcessIrpRequest( Irp);
489
490                 break;
491             }
492
493             case IOCTL_AFS_PROCESS_IRP_RESULT:
494             {
495
496                 ntStatus = AFSProcessIrpResult( Irp);
497
498                 break;
499             }
500
501             case IOCTL_AFS_SYSNAME_NOTIFICATION:
502             {
503
504                 AFSSysNameNotificationCB *pSysNameInfo = (AFSSysNameNotificationCB *)Irp->AssociatedIrp.SystemBuffer;
505
506                 if( pSysNameInfo == NULL ||
507                     pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSSysNameNotificationCB))
508                 {
509
510                     ntStatus = STATUS_INVALID_PARAMETER;
511
512                     break;
513                 }
514
515                 ntStatus = AFSSetSysNameInformation( pSysNameInfo,
516                                                      pIrpSp->Parameters.DeviceIoControl.InputBufferLength);
517
518                 break;
519             }
520
521             case IOCTL_AFS_CONFIGURE_DEBUG_TRACE:
522             {
523
524                 AFSTraceConfigCB *pTraceInfo = (AFSTraceConfigCB *)Irp->AssociatedIrp.SystemBuffer;
525
526                 if( pTraceInfo == NULL ||
527                     pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSTraceConfigCB))
528                 {
529
530                     ntStatus = STATUS_INVALID_PARAMETER;
531
532                     break;
533                 }
534
535                 ntStatus = AFSConfigureTrace( pTraceInfo);
536
537                 break;
538             }
539
540             case IOCTL_AFS_GET_TRACE_BUFFER:
541             {
542
543                 if( pIrpSp->Parameters.DeviceIoControl.OutputBufferLength == 0)
544                 {
545
546                     ntStatus = STATUS_INVALID_PARAMETER;
547
548                     break;
549                 }
550
551                 ntStatus = AFSGetTraceBuffer( pIrpSp->Parameters.DeviceIoControl.OutputBufferLength,
552                                               Irp->AssociatedIrp.SystemBuffer,
553                                               &Irp->IoStatus.Information);
554
555                 break;
556             }
557
558             case IOCTL_AFS_FORCE_CRASH:
559             {
560
561 #if DBG
562
563                 if( BooleanFlagOn( AFSDebugFlags, AFS_DBG_FLAG_ENABLE_FORCE_CRASH))
564                 {
565
566                     KeBugCheck( (ULONG)-1);
567                 }
568 #endif
569
570                 break;
571             }
572
573 #ifdef NOT_IMPLEMENTED
574             case IOCTL_AFS_LOAD_LIBRARY:
575             {
576
577                 AFSLoadLibraryCB *pLoadLib = (AFSLoadLibraryCB *)Irp->AssociatedIrp.SystemBuffer;
578                 UNICODE_STRING uniServicePath;
579
580                 if( pLoadLib == NULL ||
581                     pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSLoadLibraryCB) ||
582                     pIrpSp->Parameters.DeviceIoControl.InputBufferLength < (ULONG)FIELD_OFFSET( AFSLoadLibraryCB, LibraryServicePath) +
583                                                                                                     pLoadLib->LibraryServicePathLength)
584                 {
585
586                     ntStatus = STATUS_INVALID_PARAMETER;
587
588                     break;
589                 }
590
591                 uniServicePath.Length = pLoadLib->LibraryServicePathLength;
592                 uniServicePath.MaximumLength = uniServicePath.Length;
593
594                 uniServicePath.Buffer = pLoadLib->LibraryServicePath;
595
596                 if( uniServicePath.Length == 0)
597                 {
598
599                     ntStatus = STATUS_INVALID_PARAMETER;
600
601                     break;
602                 }
603
604                 ntStatus = AFSLoadLibrary( pLoadLib->Flags,
605                                            &uniServicePath);
606
607                 if( NT_SUCCESS( ntStatus))
608                 {
609
610                     //
611                     // Intialize the library
612                     //
613
614                     ntStatus = AFSInitializeLibrary( NULL,
615                                                      FALSE);
616                 }
617
618                 break;
619             }
620
621             case IOCTL_AFS_UNLOAD_LIBRARY:
622             {
623
624                 //
625                 // Try to unload the library we currently have in place
626                 //
627
628                 ntStatus = AFSUnloadLibrary( FALSE);
629
630                 break;
631             }
632 #endif
633
634             case IOCTL_AFS_SHUTDOWN:
635             {
636
637                 ntStatus = AFSShutdownRedirector();
638
639                 break;
640             }
641
642             case IOCTL_AFS_AUTHGROUP_CREATE_AND_SET:
643             {
644
645
646                 AFSAuthGroupRequestCB *pAuthGroupRequestCB = (AFSAuthGroupRequestCB *)Irp->AssociatedIrp.SystemBuffer;
647
648                 if( pAuthGroupRequestCB == NULL ||
649                     pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSAuthGroupRequestCB))
650                 {
651
652                     ntStatus = STATUS_INVALID_PARAMETER;
653
654                     break;
655                 }
656
657                 ntStatus = AFSCreateSetProcessAuthGroup( pAuthGroupRequestCB);
658
659                 break;
660             }
661
662             case IOCTL_AFS_AUTHGROUP_QUERY:
663             {
664
665                 ntStatus = AFSQueryProcessAuthGroupList( ( GUID *)Irp->AssociatedIrp.SystemBuffer,
666                                                          pIrpSp->Parameters.DeviceIoControl.OutputBufferLength,
667                                                          &Irp->IoStatus.Information);
668
669                 break;
670             }
671
672             case IOCTL_AFS_AUTHGROUP_SET:
673             {
674
675                 AFSAuthGroupRequestCB *pAuthGroupRequestCB = (AFSAuthGroupRequestCB *)Irp->AssociatedIrp.SystemBuffer;
676
677                 if( pAuthGroupRequestCB == NULL ||
678                     pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSAuthGroupRequestCB))
679                 {
680
681                     ntStatus = STATUS_INVALID_PARAMETER;
682
683                     break;
684                 }
685
686                 ntStatus = AFSSetActiveProcessAuthGroup( pAuthGroupRequestCB);
687
688                 break;
689             }
690
691             case IOCTL_AFS_AUTHGROUP_RESET:
692             {
693
694                 AFSAuthGroupRequestCB *pAuthGroupRequestCB = (AFSAuthGroupRequestCB *)Irp->AssociatedIrp.SystemBuffer;
695
696                 if( pAuthGroupRequestCB == NULL ||
697                     pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSAuthGroupRequestCB))
698                 {
699
700                     ntStatus = STATUS_INVALID_PARAMETER;
701
702                     break;
703                 }
704
705                 ntStatus = AFSResetActiveProcessAuthGroup( pAuthGroupRequestCB);
706
707                 break;
708             }
709
710             case IOCTL_AFS_AUTHGROUP_LOGON_CREATE:
711             case IOCTL_AFS_AUTHGROUP_SID_CREATE:
712             {
713
714                 AFSAuthGroupRequestCB *pAuthGroupRequestCB = (AFSAuthGroupRequestCB *)Irp->AssociatedIrp.SystemBuffer;
715
716                 if( pAuthGroupRequestCB != NULL &&
717                     pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSAuthGroupRequestCB))
718                 {
719
720                     ntStatus = STATUS_INVALID_PARAMETER;
721
722                     break;
723                 }
724
725                 ntStatus = AFSCreateAuthGroupForSIDorLogonSession( pAuthGroupRequestCB,
726                                                                    ulIoControlCode == IOCTL_AFS_AUTHGROUP_LOGON_CREATE);
727
728                 break;
729             }
730
731             case IOCTL_AFS_AUTHGROUP_SID_QUERY:
732             {
733
734                 AFSAuthGroupRequestCB *pAuthGroupRequestCB = NULL;
735
736                 if( pIrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof( GUID))
737                 {
738                     ntStatus = STATUS_INVALID_PARAMETER;
739                     break;
740                 }
741
742                 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength >= sizeof( AFSAuthGroupRequestCB))
743                 {
744                     pAuthGroupRequestCB = (AFSAuthGroupRequestCB *)Irp->AssociatedIrp.SystemBuffer;
745                 }
746
747                 ntStatus = AFSQueryAuthGroup( pAuthGroupRequestCB,
748                                               (GUID *)Irp->AssociatedIrp.SystemBuffer,
749                                               &Irp->IoStatus.Information);
750
751                 break;
752             }
753
754             default:
755             {
756
757                 //
758                 // Check the state of the library
759                 //
760
761                 ntStatus = AFSCheckLibraryState( Irp);
762
763                 if( !NT_SUCCESS( ntStatus) ||
764                     ntStatus == STATUS_PENDING)
765                 {
766
767                     if( ntStatus == STATUS_PENDING)
768                     {
769                         bCompleteRequest = FALSE;
770                     }
771
772                     break;
773                 }
774
775                 bCompleteRequest = FALSE;
776
777                 IoSkipCurrentIrpStackLocation( Irp);
778
779                 ntStatus = IoCallDriver( pDevExt->Specific.Control.LibraryDeviceObject,
780                                          Irp);
781
782                 //
783                 // Indicate the library is done with the request
784                 //
785
786                 AFSClearLibraryRequest();
787
788                 break;
789             }
790         }
791
792 //try_exit:
793
794     }
795     __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()))
796     {
797
798         ntStatus = STATUS_UNSUCCESSFUL;
799
800         AFSDumpTraceFilesFnc();
801     }
802
803     if( bCompleteRequest)
804     {
805
806         Irp->IoStatus.Status = ntStatus;
807
808         AFSCompleteRequest( Irp,
809                               ntStatus);
810     }
811
812     return ntStatus;
813 }
814
815 NTSTATUS
816 AFSInitIrpPool()
817 {
818
819     NTSTATUS       ntStatus = STATUS_SUCCESS;
820     AFSCommSrvcCB *pCommSrvc = NULL;
821     BOOLEAN        bReleasePools = FALSE;
822     AFSDeviceExt  *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
823
824     __Enter
825     {
826
827         pCommSrvc = &pDevExt->Specific.Control.CommServiceCB;
828
829         //
830         // Whenever we change state we must grab both pool locks. On the checking of the state
831         // within the processing routines for these respective pools, we only grab one lock to
832         // minimize serialization. The ordering is always the Irp pool then the result pool
833         // locks. We also do this in the tear down of the pool
834         //
835
836         AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
837                       AFS_TRACE_LEVEL_VERBOSE,
838                       "AFSInitIrpPool Acquiring IrpPoolLock lock %08lX EXCL %08lX\n",
839                       &pCommSrvc->IrpPoolLock,
840                       PsGetCurrentThread());
841
842         AFSAcquireExcl( &pCommSrvc->IrpPoolLock,
843                           TRUE);
844
845         AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
846                       AFS_TRACE_LEVEL_VERBOSE,
847                       "AFSInitIrpPool Acquiring ResultPoolLock lock %08lX EXCL %08lX\n",
848                       &pCommSrvc->ResultPoolLock,
849                       PsGetCurrentThread());
850
851         AFSAcquireExcl( &pCommSrvc->ResultPoolLock,
852                           TRUE);
853
854         bReleasePools = TRUE;
855
856         //
857         // The pool can be either ACTIVE or INACTIVE. If the pool state is INACTIVE and we
858         // are receiving the INIT request, then activate it. If the pool is ACTIVE, then we
859         // shouldn't be getting this request ...
860         //
861
862         if( pCommSrvc->IrpPoolControlFlag == POOL_ACTIVE)
863         {
864
865             //
866             // We have already been activated so just fail this request
867             //
868
869             try_return( ntStatus = STATUS_INVALID_PARAMETER);
870         }
871         else if( pCommSrvc->IrpPoolControlFlag == POOL_INACTIVE)
872         {
873
874             //
875             // The pool is currently INACTIVE so start it up and ready it to
876             // receive irp requests
877             //
878
879             pCommSrvc->IrpPoolControlFlag = POOL_ACTIVE;
880
881             pDevExt->Specific.Control.ServiceProcess = (PKPROCESS)PsGetCurrentProcess();
882
883             try_return( ntStatus = STATUS_SUCCESS);
884         }
885         else
886         {
887
888             //
889             // The pool is in some mixed state, fail the request.
890             //
891
892             try_return( ntStatus = STATUS_DEVICE_NOT_READY);
893         }
894
895 try_exit:
896
897         if( bReleasePools)
898         {
899
900             AFSReleaseResource( &pCommSrvc->IrpPoolLock);
901
902             AFSReleaseResource( &pCommSrvc->ResultPoolLock);
903         }
904     }
905
906     return ntStatus;
907 }
908
909 void
910 AFSCleanupIrpPool()
911 {
912
913     AFSPoolEntry   *pEntry = NULL, *pNextEntry = NULL;
914     AFSDeviceExt   *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
915     AFSCommSrvcCB  *pCommSrvc = (AFSCommSrvcCB *)&pDevExt->Specific.Control.CommServiceCB;
916
917     __Enter
918     {
919
920         //
921         // When we change the state, grab both pool locks exclusive. The order is always the
922         // Irp pool then the result pool lock
923         //
924
925         AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
926                       AFS_TRACE_LEVEL_VERBOSE,
927                       "AFSCleanupIrpPool Acquiring IrpPoolLock lock %08lX EXCL %08lX\n",
928                       &pCommSrvc->IrpPoolLock,
929                       PsGetCurrentThread());
930
931         AFSAcquireExcl( &pCommSrvc->IrpPoolLock,
932                         TRUE);
933
934         AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
935                       AFS_TRACE_LEVEL_VERBOSE,
936                       "AFSCleanupIrpPool Acquiring ResultPoolLock lock %08lX EXCL %08lX\n",
937                       &pCommSrvc->ResultPoolLock,
938                       PsGetCurrentThread());
939
940         AFSAcquireExcl( &pCommSrvc->ResultPoolLock,
941                         TRUE);
942
943         //
944         // Indicate we are pending stop
945         //
946
947         pCommSrvc->IrpPoolControlFlag = POOL_INACTIVE;
948
949         //
950         // Set the event to release any waiting workers
951         // (everyone waits on IrpPoolHasReleaseEntries)
952         //
953
954         KeSetEvent( &pCommSrvc->IrpPoolHasReleaseEntries,
955                     0,
956                     FALSE);
957
958         //
959         // Go through the pool entries and free up the structures.
960         //
961
962         pEntry = pCommSrvc->RequestPoolHead;
963
964         while( pEntry != NULL)
965         {
966
967             pNextEntry = pEntry->fLink;
968
969             if( BooleanFlagOn( pEntry->RequestFlags, AFS_REQUEST_FLAG_SYNCHRONOUS))
970             {
971
972                 //
973                 // Here we need to complete the irp, cancelled, and delete the data block
974                 //
975
976                 pEntry->ResultStatus = (ULONG) STATUS_CANCELLED;
977
978                 KeSetEvent( &pEntry->Event,
979                             0,
980                             FALSE);
981             }
982             else
983             {
984
985                 ExFreePool( pEntry);
986             }
987
988             pEntry = pNextEntry;
989         }
990
991         //
992         // Cleanup the control structure for the request pool
993         //
994
995         pCommSrvc->RequestPoolHead = NULL;
996
997         pCommSrvc->RequestPoolTail = NULL;
998
999         pCommSrvc->IrpPoolRequestIndex = 1;
1000
1001         KeClearEvent( &pCommSrvc->IrpPoolHasEntries);
1002
1003         KeClearEvent( &pCommSrvc->IrpPoolHasReleaseEntries);
1004
1005         //
1006         // Release the irp pool lock.
1007         //
1008
1009         AFSReleaseResource( &pCommSrvc->IrpPoolLock);
1010
1011         //
1012         // Go through the result pool entries and free up the structures.
1013         //
1014
1015         pEntry = pCommSrvc->ResultPoolHead;
1016
1017         while( pEntry != NULL)
1018         {
1019
1020             pNextEntry = pEntry->fLink;
1021
1022             pEntry->ResultStatus = (ULONG) STATUS_CANCELLED;
1023
1024             //
1025             // Here we will set the event of the requestor and let the blocked thread
1026             // free the data block
1027             //
1028
1029             KeSetEvent( &pEntry->Event,
1030                         0,
1031                         FALSE);
1032
1033             //
1034             // Go onto the next entry
1035             //
1036
1037             pEntry = pNextEntry;
1038         }
1039
1040         //
1041         // Cleanup the control structure for the result pool
1042         //
1043
1044         pCommSrvc->ResultPoolHead = NULL;
1045
1046         pCommSrvc->ResultPoolTail = NULL;
1047
1048         //
1049         // Release the result pool lock.
1050         //
1051
1052         AFSReleaseResource( &pCommSrvc->ResultPoolLock);
1053     }
1054
1055     return;
1056 }
1057
1058 NTSTATUS
1059 AFSInsertRequest( IN AFSCommSrvcCB *CommSrvc,
1060                   IN AFSPoolEntry *Entry)
1061 {
1062
1063     NTSTATUS ntStatus = STATUS_SUCCESS;
1064
1065     __Enter
1066     {
1067
1068         AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1069                       AFS_TRACE_LEVEL_VERBOSE,
1070                       "AFSInsertRequest Acquiring IrpPoolLock lock %08lX EXCL %08lX\n",
1071                       &CommSrvc->IrpPoolLock,
1072                       PsGetCurrentThread());
1073
1074         AFSAcquireExcl( &CommSrvc->IrpPoolLock,
1075                         TRUE);
1076
1077         if( CommSrvc->IrpPoolControlFlag != POOL_ACTIVE)
1078         {
1079
1080             try_return( ntStatus = STATUS_DEVICE_NOT_READY);
1081         }
1082
1083         if( CommSrvc->RequestPoolHead == NULL)
1084         {
1085
1086             CommSrvc->RequestPoolHead = Entry;
1087         }
1088         else
1089         {
1090
1091             CommSrvc->RequestPoolTail->fLink = Entry;
1092
1093             Entry->bLink = CommSrvc->RequestPoolTail;
1094         }
1095
1096         CommSrvc->RequestPoolTail = Entry;
1097
1098         if( Entry->RequestType == AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS)
1099         {
1100
1101             KeSetEvent( &CommSrvc->IrpPoolHasReleaseEntries,
1102                         0,
1103                         FALSE);
1104         }
1105         else
1106         {
1107
1108             KeSetEvent( &CommSrvc->IrpPoolHasEntries,
1109                         0,
1110                         FALSE);
1111         }
1112
1113         InterlockedIncrement( &CommSrvc->QueueCount);
1114
1115 try_exit:
1116
1117         AFSReleaseResource( &CommSrvc->IrpPoolLock);
1118     }
1119
1120     return ntStatus;
1121 }
1122
1123 NTSTATUS
1124 AFSProcessIrpRequest( IN PIRP Irp)
1125 {
1126
1127     NTSTATUS         ntStatus = STATUS_SUCCESS;
1128     AFSDeviceExt    *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
1129     IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1130     AFSCommSrvcCB   *pCommSrvc = NULL;
1131     AFSPoolEntry    *pEntry = NULL, *pPrevEntry = NULL;
1132     AFSCommRequest  *pRequest = NULL;
1133     BOOLEAN          bReleaseRequestThread = FALSE;
1134     PVOID            Objects[2];
1135
1136     __Enter
1137     {
1138
1139         pCommSrvc = &pDevExt->Specific.Control.CommServiceCB;
1140
1141         pRequest = (AFSCommRequest *)Irp->AssociatedIrp.SystemBuffer;
1142
1143         AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1144                       AFS_TRACE_LEVEL_VERBOSE,
1145                       "AFSProcessIrpRequest Acquiring IrpPoolLock lock %08lX EXCL %08lX\n",
1146                       &pCommSrvc->IrpPoolLock,
1147                       PsGetCurrentThread());
1148
1149         AFSAcquireExcl( &pCommSrvc->IrpPoolLock,
1150                         TRUE);
1151
1152         if( pCommSrvc->IrpPoolControlFlag != POOL_ACTIVE)
1153         {
1154
1155             AFSReleaseResource( &pCommSrvc->IrpPoolLock);
1156
1157             try_return( ntStatus = STATUS_DEVICE_NOT_READY);
1158         }
1159
1160         AFSReleaseResource( &pCommSrvc->IrpPoolLock);
1161
1162         //
1163         // Is this a dedicated flush thread?
1164         //
1165
1166         if( BooleanFlagOn( pRequest->RequestFlags, AFS_REQUEST_RELEASE_THREAD))
1167         {
1168
1169             bReleaseRequestThread = TRUE;
1170         }
1171
1172         //
1173         // Populate the objects array for the non release only threads
1174         // Release only workers can only process release extent events
1175         // whereas normal workers can process any kind of event.
1176         // Release only workers are present to ensure there cannot be
1177         // a deadlock due to all extents held by the redirector and
1178         // there not be a worker available to release them.
1179         //
1180
1181         Objects[0] = &pCommSrvc->IrpPoolHasReleaseEntries;
1182
1183         Objects[1] = &pCommSrvc->IrpPoolHasEntries;
1184
1185         //
1186         // Wait on the 'have items' event until we can retrieve an item
1187         //
1188
1189         while( TRUE)
1190         {
1191
1192             if( bReleaseRequestThread)
1193             {
1194
1195                 ntStatus = KeWaitForSingleObject( &pCommSrvc->IrpPoolHasReleaseEntries,
1196                                                   UserRequest,
1197                                                   UserMode,
1198                                                   TRUE,
1199                                                   NULL);
1200
1201                 if( ntStatus != STATUS_SUCCESS)
1202                 {
1203
1204                     ntStatus = STATUS_DEVICE_NOT_READY;
1205
1206                     break;
1207                 }
1208
1209             }
1210             else
1211             {
1212
1213                 ntStatus = KeWaitForMultipleObjects( 2,
1214                                                      Objects,
1215                                                      WaitAny,
1216                                                      UserRequest,
1217                                                      UserMode,
1218                                                      TRUE,
1219                                                      NULL,
1220                                                      NULL);
1221
1222                 if( ntStatus != STATUS_WAIT_0 &&
1223                     ntStatus != STATUS_WAIT_1)
1224                 {
1225
1226                     ntStatus = STATUS_DEVICE_NOT_READY;
1227
1228                     break;
1229                 }
1230             }
1231
1232             //
1233             // Grab the lock on the request pool
1234             //
1235
1236             AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1237                           AFS_TRACE_LEVEL_VERBOSE,
1238                           "AFSProcessIrpRequest Acquiring IrpPoolLock (WAIT) lock %08lX EXCL %08lX\n",
1239                           &pCommSrvc->IrpPoolLock,
1240                           PsGetCurrentThread());
1241
1242             AFSAcquireExcl( &pCommSrvc->IrpPoolLock,
1243                             TRUE);
1244
1245             if( pCommSrvc->IrpPoolControlFlag != POOL_ACTIVE)
1246             {
1247
1248                 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
1249
1250                 //
1251                 // Wake up the next worker since this is a SynchronizationEvent
1252                 //
1253
1254                 KeSetEvent( &pCommSrvc->IrpPoolHasReleaseEntries,
1255                             0,
1256                             FALSE);
1257
1258                 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
1259             }
1260
1261             //
1262             // If this is a dedicated flush thread only look for a flush request in the queue
1263             //
1264
1265             if( bReleaseRequestThread)
1266             {
1267
1268                 pEntry = pCommSrvc->RequestPoolHead;
1269
1270                 pPrevEntry = NULL;
1271
1272                 while( pEntry != NULL)
1273                 {
1274
1275                     if( pEntry->RequestType == AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS)
1276                     {
1277
1278                         if( pPrevEntry == NULL)
1279                         {
1280
1281                             pCommSrvc->RequestPoolHead = pEntry->fLink;
1282
1283                             if( pCommSrvc->RequestPoolHead == NULL)
1284                             {
1285
1286                                 pCommSrvc->RequestPoolTail = NULL;
1287                             }
1288                         }
1289                         else
1290                         {
1291
1292                             pPrevEntry->fLink = pEntry->fLink;
1293
1294                             if( pPrevEntry->fLink == NULL)
1295                             {
1296
1297                                 pCommSrvc->RequestPoolTail = pPrevEntry;
1298                             }
1299                         }
1300
1301                         break;
1302                     }
1303
1304                     pPrevEntry = pEntry;
1305
1306                     pEntry = pEntry->fLink;
1307                 }
1308
1309                 if( pEntry != NULL)
1310                 {
1311
1312                     //
1313                     // There might be another release entry pending
1314                     //
1315
1316                     KeSetEvent( &pCommSrvc->IrpPoolHasReleaseEntries,
1317                                 0,
1318                                 FALSE);
1319                 }
1320
1321                 //
1322                 // And release the request pool lock
1323                 //
1324
1325                 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
1326             }
1327             else
1328             {
1329
1330                 pEntry = pCommSrvc->RequestPoolHead;
1331
1332                 if( pEntry != NULL)
1333                 {
1334
1335                     pCommSrvc->RequestPoolHead = pEntry->fLink;
1336
1337                     pEntry->bLink = NULL;
1338
1339                     if( pCommSrvc->RequestPoolHead == NULL)
1340                     {
1341
1342                         pCommSrvc->RequestPoolTail = NULL;
1343                     }
1344                     else
1345                     {
1346
1347                         KeSetEvent( &pCommSrvc->IrpPoolHasEntries,
1348                                     0,
1349                                     FALSE);
1350                     }
1351                 }
1352
1353                 //
1354                 // And release the request pool lock
1355                 //
1356
1357                 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
1358             }
1359
1360             //
1361             // Insert the entry into the result pool, if we have one
1362             //
1363
1364             if( pEntry != NULL)
1365             {
1366
1367                 //
1368                 // Move the request data into the passed in buffer
1369                 //
1370
1371                 ASSERT( sizeof( AFSCommRequest) +
1372                                     pEntry->FileName.Length +
1373                                     pEntry->DataLength <= pIrpSp->Parameters.DeviceIoControl.OutputBufferLength);
1374
1375                 RtlCopyMemory( &pRequest->AuthGroup,
1376                                &pEntry->AuthGroup,
1377                                sizeof( GUID));
1378
1379                 pRequest->FileId = pEntry->FileId;
1380
1381                 pRequest->RequestType = pEntry->RequestType;
1382
1383                 pRequest->RequestIndex = pEntry->RequestIndex;
1384
1385                 pRequest->RequestFlags = pEntry->RequestFlags;
1386
1387                 pRequest->NameLength = pEntry->FileName.Length;
1388
1389                 pRequest->QueueCount = InterlockedDecrement( &pCommSrvc->QueueCount);
1390
1391                 if( pRequest->NameLength > 0)
1392                 {
1393
1394                     RtlCopyMemory( pRequest->Name,
1395                                    pEntry->FileName.Buffer,
1396                                    pRequest->NameLength);
1397                 }
1398
1399                 pRequest->DataOffset = 0;
1400
1401                 pRequest->DataLength = pEntry->DataLength;
1402
1403                 if( pRequest->DataLength > 0)
1404                 {
1405
1406                     pRequest->DataOffset = pEntry->FileName.Length;
1407
1408                     RtlCopyMemory( (void *)((char *)pRequest->Name + pRequest->DataOffset),
1409                                    pEntry->Data,
1410                                    pRequest->DataLength);
1411                 }
1412
1413                 pRequest->ResultBufferLength = 0;
1414
1415                 if( pEntry->ResultBufferLength != NULL)
1416                 {
1417
1418                     pRequest->ResultBufferLength = *(pEntry->ResultBufferLength);
1419                 }
1420
1421                 Irp->IoStatus.Information = sizeof( AFSCommRequest) +
1422                                                         pEntry->FileName.Length +
1423                                                         pEntry->DataLength;
1424
1425                 //
1426                 // If this is a synchronous request then move the request into the
1427                 // result pool
1428                 //
1429
1430                 if( BooleanFlagOn( pEntry->RequestFlags, AFS_REQUEST_FLAG_SYNCHRONOUS))
1431                 {
1432
1433                     pEntry->fLink = NULL;
1434                     pEntry->bLink = NULL;
1435
1436                     AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1437                                   AFS_TRACE_LEVEL_VERBOSE,
1438                                   "AFSProcessIrpRequest Acquiring ResultPoolLock lock %08lX EXCL %08lX\n",
1439                                   &pCommSrvc->ResultPoolLock,
1440                                   PsGetCurrentThread());
1441
1442                     AFSAcquireExcl( &pCommSrvc->ResultPoolLock,
1443                                     TRUE);
1444
1445                     if( pCommSrvc->ResultPoolHead == NULL)
1446                     {
1447
1448                         pCommSrvc->ResultPoolHead = pEntry;
1449                     }
1450                     else
1451                     {
1452
1453                         pCommSrvc->ResultPoolTail->fLink = pEntry;
1454
1455                         pEntry->bLink = pCommSrvc->ResultPoolTail;
1456                     }
1457
1458                     pCommSrvc->ResultPoolTail = pEntry;
1459
1460                     AFSReleaseResource( &pCommSrvc->ResultPoolLock);
1461                 }
1462                 else
1463                 {
1464
1465                     //
1466                     // Free up the pool entry
1467                     //
1468
1469                     ExFreePool( pEntry);
1470                 }
1471
1472                 break;
1473             }
1474         }
1475
1476 try_exit:
1477
1478         NOTHING;
1479     }
1480
1481     return ntStatus;
1482 }
1483
1484 NTSTATUS
1485 AFSProcessIrpResult( IN PIRP Irp)
1486 {
1487
1488     NTSTATUS            ntStatus = STATUS_SUCCESS;
1489     AFSDeviceExt       *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
1490     AFSCommSrvcCB      *pCommSrvc = NULL;
1491     AFSPoolEntry       *pCurrentEntry = NULL;
1492     AFSCommResult      *pResult = NULL;
1493     ULONG               ulCopyLen = 0;
1494
1495     __Enter
1496     {
1497
1498         pCommSrvc = &pDevExt->Specific.Control.CommServiceCB;
1499
1500         //
1501         // Get the request for the incoming result
1502         //
1503
1504         pResult = (AFSCommResult *)Irp->AssociatedIrp.SystemBuffer;
1505
1506         if( pResult == NULL)
1507         {
1508
1509             try_return( ntStatus = STATUS_INVALID_PARAMETER);
1510         }
1511
1512         //
1513         // Go look for our entry
1514         //
1515
1516         AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1517                       AFS_TRACE_LEVEL_VERBOSE,
1518                       "AFSProcessIrpResult Acquiring ResultPoolLock lock %08lX EXCL %08lX\n",
1519                       &pCommSrvc->ResultPoolLock,
1520                       PsGetCurrentThread());
1521
1522         AFSAcquireExcl( &pCommSrvc->ResultPoolLock,
1523                           TRUE);
1524
1525         pCurrentEntry = pCommSrvc->ResultPoolHead;
1526
1527         while( pCurrentEntry != NULL)
1528         {
1529
1530             if( pCurrentEntry->RequestIndex == pResult->RequestIndex)
1531             {
1532
1533                 //
1534                 // Found the entry so remove it from the queue
1535                 //
1536
1537                 if( pCurrentEntry->bLink == NULL)
1538                 {
1539
1540                     //
1541                     // At the head of the list
1542                     //
1543
1544                     pCommSrvc->ResultPoolHead = pCurrentEntry->fLink;
1545
1546                     if( pCommSrvc->ResultPoolHead != NULL)
1547                     {
1548
1549                         pCommSrvc->ResultPoolHead->bLink = NULL;
1550                     }
1551                 }
1552                 else
1553                 {
1554
1555                     pCurrentEntry->bLink->fLink = pCurrentEntry->fLink;
1556                 }
1557
1558                 if( pCurrentEntry->fLink == NULL)
1559                 {
1560
1561                     pCommSrvc->ResultPoolTail = pCurrentEntry->bLink;
1562
1563                     if( pCommSrvc->ResultPoolTail != NULL)
1564                     {
1565
1566                         pCommSrvc->ResultPoolTail->fLink = NULL;
1567                     }
1568                 }
1569                 else
1570                 {
1571
1572                     pCurrentEntry->fLink->bLink = pCurrentEntry->bLink;
1573                 }
1574
1575                 break;
1576             }
1577
1578             pCurrentEntry = pCurrentEntry->fLink;
1579         }
1580
1581         AFSReleaseResource( &pCommSrvc->ResultPoolLock);
1582
1583         if( pCurrentEntry == NULL)
1584         {
1585
1586             try_return( ntStatus = STATUS_INVALID_PARAMETER);
1587         }
1588
1589         //
1590         // OK, move in the result information
1591         //
1592
1593         pCurrentEntry->ResultStatus = pResult->ResultStatus;
1594
1595         if( ( pCurrentEntry->ResultStatus == STATUS_SUCCESS ||
1596               pCurrentEntry->ResultStatus == STATUS_BUFFER_OVERFLOW) &&
1597             pCurrentEntry->ResultBufferLength != NULL &&
1598             pCurrentEntry->ResultBuffer != NULL)
1599         {
1600
1601             ASSERT( pResult->ResultBufferLength <= *(pCurrentEntry->ResultBufferLength));
1602
1603             ulCopyLen = pResult->ResultBufferLength;
1604
1605             if( ulCopyLen > *(pCurrentEntry->ResultBufferLength))
1606             {
1607                 ulCopyLen = *(pCurrentEntry->ResultBufferLength);
1608             }
1609
1610             *(pCurrentEntry->ResultBufferLength) = ulCopyLen;
1611
1612             if( pResult->ResultBufferLength > 0)
1613             {
1614
1615                 RtlCopyMemory( pCurrentEntry->ResultBuffer,
1616                                pResult->ResultData,
1617                                ulCopyLen);
1618             }
1619         }
1620
1621         KeSetEvent( &pCurrentEntry->Event,
1622                     0,
1623                     FALSE);
1624
1625 try_exit:
1626
1627         if( !NT_SUCCESS( ntStatus))
1628         {
1629
1630         }
1631     }
1632
1633     return ntStatus;
1634 }