1 /*++ 2 3 Copyright (c) 1989-2000 Microsoft Corporation 4 5 Module Name: 6 7 FspDisp.c 8 9 Abstract: 10 11 This module implements the main dispatch procedure/thread for the Cdfs 12 Fsp 13 14 15 --*/ 16 17 #include "cdprocs.h" 18 19 // 20 // The Bug check file id for this module 21 // 22 23 #define BugCheckFileId (CDFS_BUG_CHECK_FSPDISP) 24 25 26 VOID 27 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */ 28 CdFspDispatch ( 29 _In_ PVOID Context 30 ) 31 32 /*++ 33 34 Routine Description: 35 36 This is the main FSP thread routine that is executed to receive 37 and dispatch IRP requests. Each FSP thread begins its execution here. 38 There is one thread created at system initialization time and subsequent 39 threads created as needed. 40 41 Arguments: 42 43 IrpContext - IrpContext for a request to process. 44 45 Return Value: 46 47 None 48 49 --*/ 50 51 { 52 THREAD_CONTEXT ThreadContext = {0}; 53 PIRP_CONTEXT IrpContext = Context; 54 NTSTATUS Status; 55 56 PIRP Irp = IrpContext->Irp; 57 PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp ); 58 59 PVOLUME_DEVICE_OBJECT VolDo = NULL; 60 61 // 62 // If this request has an associated volume device object, remember it. 63 // 64 65 if (IrpSp->FileObject != NULL) { 66 67 VolDo = CONTAINING_RECORD( IrpSp->DeviceObject, 68 VOLUME_DEVICE_OBJECT, 69 DeviceObject ); 70 } 71 72 // 73 // Now case on the function code. For each major function code, 74 // either call the appropriate worker routine. This routine that 75 // we call is responsible for completing the IRP, and not us. 76 // That way the routine can complete the IRP and then continue 77 // post processing as required. For example, a read can be 78 // satisfied right away and then read can be done. 79 // 80 // We'll do all of the work within an exception handler that 81 // will be invoked if ever some underlying operation gets into 82 // trouble. 83 // 84 85 while ( TRUE ) { 86 87 // 88 // Set all the flags indicating we are in the Fsp. 89 // 90 91 SetFlag( IrpContext->Flags, IRP_CONTEXT_FSP_FLAGS ); 92 93 FsRtlEnterFileSystem(); 94 95 CdSetThreadContext( IrpContext, &ThreadContext ); 96 97 while (TRUE) { 98 99 _SEH2_TRY { 100 101 // 102 // Reinitialize for the next try at completing this 103 // request. 104 // 105 106 Status = 107 IrpContext->ExceptionStatus = STATUS_SUCCESS; 108 109 // 110 // Initialize the Io status field in the Irp. 111 // 112 113 Irp->IoStatus.Status = STATUS_SUCCESS; 114 Irp->IoStatus.Information = 0; 115 116 // 117 // Case on the major irp code. 118 // 119 120 switch (IrpContext->MajorFunction) { 121 122 case IRP_MJ_CREATE : 123 124 CdCommonCreate( IrpContext, Irp ); 125 break; 126 127 case IRP_MJ_CLOSE : 128 129 NT_ASSERT( FALSE ); 130 break; 131 132 case IRP_MJ_READ : 133 134 CdCommonRead( IrpContext, Irp ); 135 break; 136 137 case IRP_MJ_QUERY_INFORMATION : 138 139 CdCommonQueryInfo( IrpContext, Irp ); 140 break; 141 142 case IRP_MJ_SET_INFORMATION : 143 144 CdCommonSetInfo( IrpContext, Irp ); 145 break; 146 147 case IRP_MJ_QUERY_VOLUME_INFORMATION : 148 149 CdCommonQueryVolInfo( IrpContext, Irp ); 150 break; 151 152 case IRP_MJ_DIRECTORY_CONTROL : 153 154 CdCommonDirControl( IrpContext, Irp ); 155 break; 156 157 case IRP_MJ_FILE_SYSTEM_CONTROL : 158 159 CdCommonFsControl( IrpContext, Irp ); 160 break; 161 162 case IRP_MJ_DEVICE_CONTROL : 163 164 CdCommonDevControl( IrpContext, Irp ); 165 break; 166 167 case IRP_MJ_LOCK_CONTROL : 168 169 CdCommonLockControl( IrpContext, Irp ); 170 break; 171 172 case IRP_MJ_CLEANUP : 173 174 CdCommonCleanup( IrpContext, Irp ); 175 break; 176 177 case IRP_MJ_PNP : 178 179 NT_ASSERT( FALSE ); 180 CdCommonPnp( IrpContext, Irp ); 181 break; 182 183 default : 184 185 Status = STATUS_INVALID_DEVICE_REQUEST; 186 CdCompleteRequest( IrpContext, Irp, Status ); 187 } 188 189 } _SEH2_EXCEPT( CdExceptionFilter( IrpContext, _SEH2_GetExceptionInformation() )) { 190 191 Status = CdProcessException( IrpContext, Irp, _SEH2_GetExceptionCode() ); 192 } _SEH2_END; 193 194 // 195 // Break out of the loop if we didn't get CANT_WAIT. 196 // 197 198 if (Status != STATUS_CANT_WAIT) { break; } 199 200 // 201 // We are retrying this request. Cleanup the IrpContext for the retry. 202 // 203 204 SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_MORE_PROCESSING ); 205 CdCleanupIrpContext( IrpContext, FALSE ); 206 } 207 208 FsRtlExitFileSystem(); 209 210 // 211 // If there are any entries on this volume's overflow queue, service 212 // them. 213 // 214 215 if (VolDo != NULL) { 216 217 KIRQL SavedIrql; 218 PVOID Entry = NULL; 219 220 // 221 // We have a volume device object so see if there is any work 222 // left to do in its overflow queue. 223 // 224 225 KeAcquireSpinLock( &VolDo->OverflowQueueSpinLock, &SavedIrql ); 226 227 if (VolDo->OverflowQueueCount > 0) { 228 229 // 230 // There is overflow work to do in this volume so we'll 231 // decrement the Overflow count, dequeue the IRP, and release 232 // the Event 233 // 234 235 VolDo->OverflowQueueCount -= 1; 236 237 Entry = RemoveHeadList( &VolDo->OverflowQueue ); 238 239 } else { 240 241 VolDo->PostedRequestCount -= 1; 242 243 Entry = NULL; 244 } 245 246 KeReleaseSpinLock( &VolDo->OverflowQueueSpinLock, SavedIrql ); 247 248 // 249 // There wasn't an entry, break out of the loop and return to 250 // the Ex Worker thread. 251 // 252 253 if (Entry == NULL) { 254 255 break; 256 } 257 258 // 259 // Extract the IrpContext , Irp, set wait to TRUE, and loop. 260 // 261 262 IrpContext = CONTAINING_RECORD( Entry, 263 IRP_CONTEXT, 264 WorkQueueItem.List ); 265 266 Irp = IrpContext->Irp; 267 IrpSp = IoGetCurrentIrpStackLocation( Irp ); 268 __analysis_assert( IrpSp != 0 ); 269 270 continue; 271 } 272 273 break; 274 } 275 276 return; 277 } 278 279 280 281 282