1 /* 2 * COPYRIGHT: See COPYRIGHT.TXT 3 * PROJECT: Ext2 File System Driver for WinNT/2K/XP 4 * FILE: dispatch.c 5 * PROGRAMMER: Matt Wu <mattwu@163.com> 6 * HOMEPAGE: http://www.ext2fsd.com 7 * UPDATE HISTORY: 8 */ 9 10 /* INCLUDES *****************************************************************/ 11 12 #include "ext2fs.h" 13 14 /* GLOBALS ***************************************************************/ 15 16 extern PEXT2_GLOBAL Ext2Global; 17 18 /* DEFINITIONS *************************************************************/ 19 20 #ifdef ALLOC_PRAGMA 21 #pragma alloc_text(PAGE, Ext2QueueRequest) 22 #pragma alloc_text(PAGE, Ext2DeQueueRequest) 23 #endif 24 25 /* 26 * Ext2OplockComplete 27 * 28 * callback routine of FsRtlCheckOplock when an oplock break has 29 * completed, allowing an Irp to resume execution. 30 * 31 * Arguments: 32 * 33 * Context: the IrpContext to be queued 34 * Irp: the I/O request packet 35 * 36 * Return Value: 37 * N/A 38 */ 39 40 #ifdef __REACTOS__ 41 VOID NTAPI 42 #else 43 VOID 44 #endif 45 Ext2OplockComplete ( 46 IN PVOID Context, 47 IN PIRP Irp 48 ) 49 { 50 // 51 // Check on the return value in the Irp. 52 // 53 54 if (Irp->IoStatus.Status == STATUS_SUCCESS) { 55 56 // 57 // queue the Irp context in the workqueue. 58 // 59 60 Ext2QueueRequest((PEXT2_IRP_CONTEXT)Context); 61 62 } else { 63 64 // 65 // complete the request in case of failure 66 // 67 68 Ext2CompleteIrpContext( (PEXT2_IRP_CONTEXT) Context, 69 Irp->IoStatus.Status ); 70 } 71 72 return; 73 } 74 75 76 /* 77 * Ext2LockIrp 78 * 79 * performs buffer locking if we need pend the process of the Irp 80 * 81 * Arguments: 82 * Context: the irp context 83 * Irp: the I/O request packet. 84 * 85 * Return Value: 86 * N/A 87 */ 88 89 #ifdef __REACTOS__ 90 VOID NTAPI 91 #else 92 VOID 93 #endif 94 Ext2LockIrp ( 95 IN PVOID Context, 96 IN PIRP Irp 97 ) 98 { 99 PIO_STACK_LOCATION IrpSp; 100 PEXT2_IRP_CONTEXT IrpContext; 101 102 if (Irp == NULL) { 103 return; 104 } 105 106 IrpSp = IoGetCurrentIrpStackLocation(Irp); 107 108 IrpContext = (PEXT2_IRP_CONTEXT) Context; 109 110 if ( IrpContext->MajorFunction == IRP_MJ_READ || 111 IrpContext->MajorFunction == IRP_MJ_WRITE ) { 112 113 // 114 // lock the user's buffer to MDL, if the I/O is bufferred 115 // 116 117 if (!IsFlagOn(IrpContext->MinorFunction, IRP_MN_MDL)) { 118 119 Ext2LockUserBuffer( Irp, IrpSp->Parameters.Write.Length, 120 (IrpContext->MajorFunction == IRP_MJ_READ) ? 121 IoWriteAccess : IoReadAccess ); 122 } 123 124 } else if (IrpContext->MajorFunction == IRP_MJ_DIRECTORY_CONTROL 125 && IrpContext->MinorFunction == IRP_MN_QUERY_DIRECTORY) { 126 127 ULONG Length = ((PEXTENDED_IO_STACK_LOCATION) IrpSp)->Parameters.QueryDirectory.Length; 128 Ext2LockUserBuffer(Irp, Length, IoWriteAccess); 129 130 } else if (IrpContext->MajorFunction == IRP_MJ_QUERY_EA) { 131 132 ULONG Length = ((PEXTENDED_IO_STACK_LOCATION) IrpSp)->Parameters.QueryEa.Length; 133 Ext2LockUserBuffer(Irp, Length, IoWriteAccess); 134 135 } else if (IrpContext->MajorFunction == IRP_MJ_SET_EA) { 136 ULONG Length = ((PEXTENDED_IO_STACK_LOCATION) IrpSp)->Parameters.SetEa.Length; 137 Ext2LockUserBuffer(Irp, Length, IoReadAccess); 138 139 } else if ( (IrpContext->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL) && 140 (IrpContext->MinorFunction == IRP_MN_USER_FS_REQUEST) ) { 141 PEXTENDED_IO_STACK_LOCATION EIrpSp = (PEXTENDED_IO_STACK_LOCATION)IrpSp; 142 if ( (EIrpSp->Parameters.FileSystemControl.FsControlCode == FSCTL_GET_VOLUME_BITMAP) || 143 (EIrpSp->Parameters.FileSystemControl.FsControlCode == FSCTL_GET_RETRIEVAL_POINTERS) || 144 (EIrpSp->Parameters.FileSystemControl.FsControlCode == FSCTL_GET_RETRIEVAL_POINTER_BASE) ) { 145 ULONG Length = EIrpSp->Parameters.FileSystemControl.OutputBufferLength; 146 Ext2LockUserBuffer(Irp, Length, IoWriteAccess); 147 } 148 } 149 150 // Mark the request as pending status 151 152 IoMarkIrpPending( Irp ); 153 154 return; 155 } 156 157 NTSTATUS 158 Ext2QueueRequest (IN PEXT2_IRP_CONTEXT IrpContext) 159 { 160 ASSERT(IrpContext); 161 162 ASSERT((IrpContext->Identifier.Type == EXT2ICX) && 163 (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT))); 164 165 /* set the flags of "can wait" and "queued" */ 166 SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT); 167 SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_REQUEUED); 168 169 /* make sure the buffer is kept valid in system context */ 170 Ext2LockIrp(IrpContext, IrpContext->Irp); 171 172 /* initialize workite*/ 173 ExInitializeWorkItem( 174 &IrpContext->WorkQueueItem, 175 Ext2DeQueueRequest, 176 IrpContext ); 177 178 /* dispatch it */ 179 ExQueueWorkItem(&IrpContext->WorkQueueItem, CriticalWorkQueue); 180 181 return STATUS_PENDING; 182 } 183 184 185 #ifdef __REACTOS__ 186 VOID NTAPI 187 #else 188 VOID 189 #endif 190 Ext2DeQueueRequest (IN PVOID Context) 191 { 192 PEXT2_IRP_CONTEXT IrpContext; 193 194 IrpContext = (PEXT2_IRP_CONTEXT) Context; 195 196 ASSERT(IrpContext); 197 198 ASSERT((IrpContext->Identifier.Type == EXT2ICX) && 199 (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT))); 200 201 _SEH2_TRY { 202 203 _SEH2_TRY { 204 205 FsRtlEnterFileSystem(); 206 207 if (!IrpContext->IsTopLevel) { 208 IoSetTopLevelIrp((PIRP) FSRTL_FSP_TOP_LEVEL_IRP); 209 } 210 211 Ext2DispatchRequest(IrpContext); 212 213 } _SEH2_EXCEPT (Ext2ExceptionFilter(IrpContext, _SEH2_GetExceptionInformation())) { 214 215 Ext2ExceptionHandler(IrpContext); 216 } _SEH2_END; 217 218 } _SEH2_FINALLY { 219 220 IoSetTopLevelIrp(NULL); 221 222 FsRtlExitFileSystem(); 223 } _SEH2_END; 224 } 225 226 227 NTSTATUS 228 Ext2DispatchRequest (IN PEXT2_IRP_CONTEXT IrpContext) 229 { 230 ASSERT(IrpContext); 231 232 ASSERT((IrpContext->Identifier.Type == EXT2ICX) && 233 (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT))); 234 235 switch (IrpContext->MajorFunction) { 236 237 case IRP_MJ_CREATE: 238 return Ext2Create(IrpContext); 239 240 case IRP_MJ_CLOSE: 241 return Ext2Close(IrpContext); 242 243 case IRP_MJ_READ: 244 return Ext2Read(IrpContext); 245 246 case IRP_MJ_WRITE: 247 return Ext2Write(IrpContext); 248 249 case IRP_MJ_FLUSH_BUFFERS: 250 return Ext2Flush(IrpContext); 251 252 case IRP_MJ_QUERY_INFORMATION: 253 return Ext2QueryFileInformation(IrpContext); 254 255 case IRP_MJ_SET_INFORMATION: 256 return Ext2SetFileInformation(IrpContext); 257 258 case IRP_MJ_QUERY_VOLUME_INFORMATION: 259 return Ext2QueryVolumeInformation(IrpContext); 260 261 case IRP_MJ_SET_VOLUME_INFORMATION: 262 return Ext2SetVolumeInformation(IrpContext); 263 264 case IRP_MJ_DIRECTORY_CONTROL: 265 return Ext2DirectoryControl(IrpContext); 266 267 case IRP_MJ_FILE_SYSTEM_CONTROL: 268 return Ext2FileSystemControl(IrpContext); 269 270 case IRP_MJ_DEVICE_CONTROL: 271 return Ext2DeviceControl(IrpContext); 272 273 case IRP_MJ_LOCK_CONTROL: 274 return Ext2LockControl(IrpContext); 275 276 case IRP_MJ_CLEANUP: 277 return Ext2Cleanup(IrpContext); 278 279 case IRP_MJ_SHUTDOWN: 280 return Ext2ShutDown(IrpContext); 281 282 case IRP_MJ_QUERY_EA: 283 return Ext2QueryEa(IrpContext); 284 285 case IRP_MJ_SET_EA: 286 return Ext2SetEa(IrpContext); 287 288 #if (_WIN32_WINNT >= 0x0500) 289 case IRP_MJ_PNP: 290 return Ext2Pnp(IrpContext); 291 #endif //(_WIN32_WINNT >= 0x0500) 292 default: 293 DEBUG(DL_ERR, ( "Ext2DispatchRequest: Unexpected major function: %xh\n", 294 IrpContext->MajorFunction)); 295 296 Ext2CompleteIrpContext(IrpContext, STATUS_DRIVER_INTERNAL_ERROR); 297 298 return STATUS_DRIVER_INTERNAL_ERROR; 299 } 300 } 301 302 303 #ifdef __REACTOS__ 304 NTSTATUS NTAPI 305 #else 306 NTSTATUS 307 #endif 308 Ext2BuildRequest (PDEVICE_OBJECT DeviceObject, PIRP Irp) 309 { 310 BOOLEAN AtIrqlPassiveLevel = FALSE; 311 BOOLEAN IsTopLevelIrp = FALSE; 312 PEXT2_IRP_CONTEXT IrpContext = NULL; 313 NTSTATUS Status = STATUS_UNSUCCESSFUL; 314 315 _SEH2_TRY { 316 317 _SEH2_TRY { 318 319 #if EXT2_DEBUG 320 Ext2DbgPrintCall(DeviceObject, Irp); 321 #endif 322 323 AtIrqlPassiveLevel = (KeGetCurrentIrql() == PASSIVE_LEVEL); 324 325 if (AtIrqlPassiveLevel) { 326 FsRtlEnterFileSystem(); 327 } 328 329 if (!IoGetTopLevelIrp()) { 330 IsTopLevelIrp = TRUE; 331 IoSetTopLevelIrp(Irp); 332 } 333 334 IrpContext = Ext2AllocateIrpContext(DeviceObject, Irp); 335 336 if (!IrpContext) { 337 338 Status = STATUS_INSUFFICIENT_RESOURCES; 339 Irp->IoStatus.Status = Status; 340 341 Ext2CompleteRequest(Irp, TRUE, IO_NO_INCREMENT); 342 343 } else { 344 345 if ((IrpContext->MajorFunction == IRP_MJ_CREATE) && 346 !AtIrqlPassiveLevel) { 347 348 DbgBreak(); 349 } 350 351 Status = Ext2DispatchRequest(IrpContext); 352 } 353 } _SEH2_EXCEPT (Ext2ExceptionFilter(IrpContext, _SEH2_GetExceptionInformation())) { 354 355 Status = Ext2ExceptionHandler(IrpContext); 356 } _SEH2_END; 357 358 } _SEH2_FINALLY { 359 360 if (IsTopLevelIrp) { 361 IoSetTopLevelIrp(NULL); 362 } 363 364 if (AtIrqlPassiveLevel) { 365 FsRtlExitFileSystem(); 366 } 367 } _SEH2_END; 368 369 return Status; 370 } 371