1 /* 2 * COPYRIGHT: See COPYRIGHT.TXT 3 * PROJECT: Ext2 File System Driver for WinNT/2K/XP 4 * FILE: pnp.c 5 * PROGRAMMER: Matt Wu <mattwu@163.com> 6 * HOMEPAGE: http://www.ext2fsd.com 7 * UPDATE HISTORY: 8 */ 9 10 #if (_WIN32_WINNT >= 0x0500) 11 12 /* INCLUDES *****************************************************************/ 13 14 #include "ext2fs.h" 15 16 /* GLOBALS ***************************************************************/ 17 18 extern PEXT2_GLOBAL Ext2Global; 19 20 /* DEFINITIONS *************************************************************/ 21 22 #ifdef __REACTOS__ 23 NTSTATUS NTAPI 24 #else 25 NTSTATUS 26 #endif 27 Ext2PnpCompletionRoutine ( 28 IN PDEVICE_OBJECT DeviceObject, 29 IN PIRP Irp, 30 IN PVOID Contxt ); 31 32 33 #ifdef ALLOC_PRAGMA 34 #pragma alloc_text(PAGE, Ext2Pnp) 35 #pragma alloc_text(PAGE, Ext2PnpQueryRemove) 36 #pragma alloc_text(PAGE, Ext2PnpRemove) 37 #pragma alloc_text(PAGE, Ext2PnpCancelRemove) 38 #pragma alloc_text(PAGE, Ext2PnpSurpriseRemove) 39 #endif 40 41 42 /* FUNCTIONS *************************************************************/ 43 44 45 #ifdef __REACTOS__ 46 NTSTATUS NTAPI 47 #else 48 NTSTATUS 49 #endif 50 Ext2PnpCompletionRoutine ( 51 IN PDEVICE_OBJECT DeviceObject, 52 IN PIRP Irp, 53 IN PVOID Contxt 54 ) 55 { 56 PKEVENT Event = (PKEVENT) Contxt; 57 58 KeSetEvent( Event, 0, FALSE ); 59 60 return STATUS_MORE_PROCESSING_REQUIRED; 61 62 UNREFERENCED_PARAMETER( DeviceObject ); 63 UNREFERENCED_PARAMETER( Contxt ); 64 } 65 66 67 NTSTATUS 68 Ext2Pnp (IN PEXT2_IRP_CONTEXT IrpContext) 69 { 70 NTSTATUS Status = STATUS_INVALID_PARAMETER; 71 72 PIRP Irp; 73 PIO_STACK_LOCATION IrpSp; 74 PEXT2_VCB Vcb = NULL; 75 PDEVICE_OBJECT DeviceObject; 76 77 _SEH2_TRY { 78 79 ASSERT(IrpContext); 80 81 ASSERT((IrpContext->Identifier.Type == EXT2ICX) && 82 (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT))); 83 84 DeviceObject = IrpContext->DeviceObject; 85 86 Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension; 87 88 ASSERT(Vcb != NULL); 89 90 if ( !((Vcb->Identifier.Type == EXT2VCB) && 91 (Vcb->Identifier.Size == sizeof(EXT2_VCB)))) { 92 _SEH2_LEAVE; // Status = STATUS_INVALID_PARAMETER 93 } 94 95 Irp = IrpContext->Irp; 96 IrpSp = IoGetCurrentIrpStackLocation(Irp); 97 98 SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT); 99 100 switch ( IrpSp->MinorFunction ) { 101 102 case IRP_MN_QUERY_REMOVE_DEVICE: 103 104 DEBUG(DL_PNP, ("Ext2Pnp: Ext2PnpQueryRemove...\n")); 105 Status = Ext2PnpQueryRemove(IrpContext, Vcb); 106 107 break; 108 109 case IRP_MN_REMOVE_DEVICE: 110 111 DEBUG(DL_PNP, ("Ext2Pnp: Ext2PnpRemove...\n")); 112 Status = Ext2PnpRemove(IrpContext, Vcb); 113 break; 114 115 case IRP_MN_CANCEL_REMOVE_DEVICE: 116 117 DEBUG(DL_PNP, ("Ext2Pnp: Ext2PnpCancelRemove...\n")); 118 Status = Ext2PnpCancelRemove(IrpContext, Vcb); 119 break; 120 121 case IRP_MN_SURPRISE_REMOVAL: 122 123 DEBUG(DL_PNP, ("Ext2Pnp: Ext2PnpSupriseRemove...\n")); 124 Status = Ext2PnpSurpriseRemove(IrpContext, Vcb); 125 break; 126 127 default: 128 break; 129 } 130 131 } _SEH2_FINALLY { 132 133 if (!IrpContext->ExceptionInProgress) { 134 Irp = IrpContext->Irp; 135 136 if (Irp) { 137 138 // 139 // Here we need pass the IRP to the disk driver. 140 // 141 142 IoSkipCurrentIrpStackLocation( Irp ); 143 144 Status = IoCallDriver(Vcb->TargetDeviceObject, Irp); 145 146 IrpContext->Irp = NULL; 147 } 148 149 Ext2CompleteIrpContext(IrpContext, Status); 150 } 151 } _SEH2_END; 152 153 return Status; 154 } 155 156 157 NTSTATUS 158 Ext2PnpQueryRemove ( 159 PEXT2_IRP_CONTEXT IrpContext, 160 PEXT2_VCB Vcb 161 ) 162 { 163 NTSTATUS Status = STATUS_SUCCESS; 164 KEVENT Event; 165 BOOLEAN bDeleted = FALSE; 166 BOOLEAN VcbAcquired = FALSE; 167 168 _SEH2_TRY { 169 170 CcWaitForCurrentLazyWriterActivity(); 171 172 VcbAcquired = ExAcquireResourceExclusiveLite( 173 &Vcb->MainResource, TRUE ); 174 175 Ext2FlushFiles(IrpContext, Vcb, FALSE); 176 Ext2FlushVolume(IrpContext, Vcb, FALSE); 177 178 DEBUG(DL_PNP, ("Ext2PnpQueryRemove: Ext2LockVcb: Vcb=%xh FileObject=%xh ...\n", 179 Vcb, IrpContext->FileObject)); 180 Status = Ext2LockVcb(Vcb, IrpContext->FileObject); 181 182 if (VcbAcquired) { 183 ExReleaseResourceLite(&Vcb->MainResource); 184 VcbAcquired = FALSE; 185 } 186 187 DEBUG(DL_PNP, ("Ext2PnpQueryRemove: Ext2PurgeVolume ...\n")); 188 Ext2PurgeVolume(Vcb, TRUE); 189 190 if (!NT_SUCCESS(Status)) { 191 _SEH2_LEAVE; 192 } 193 194 IoCopyCurrentIrpStackLocationToNext(IrpContext->Irp); 195 196 KeInitializeEvent( &Event, NotificationEvent, FALSE ); 197 IoSetCompletionRoutine( IrpContext->Irp, 198 Ext2PnpCompletionRoutine, 199 &Event, 200 TRUE, 201 TRUE, 202 TRUE ); 203 204 DEBUG(DL_PNP, ("Ext2PnpQueryRemove: Call lower level driver...\n")); 205 Status = IoCallDriver( Vcb->TargetDeviceObject, 206 IrpContext->Irp); 207 208 if (Status == STATUS_PENDING) { 209 KeWaitForSingleObject( &Event, 210 Executive, 211 KernelMode, 212 FALSE, 213 NULL ); 214 Status = IrpContext->Irp->IoStatus.Status; 215 } 216 217 if (NT_SUCCESS(Status)) { 218 ASSERT(!VcbAcquired); 219 DEBUG(DL_PNP, ("Ext2PnpQueryRemove: Ext2CheckDismount ...\n")); 220 bDeleted = Ext2CheckDismount(IrpContext, Vcb, TRUE); 221 DEBUG(DL_PNP, ("Ext2PnpQueryRemove: Ext2FlushVolume bDelted=%xh ...\n", bDeleted)); 222 } 223 224 } _SEH2_FINALLY { 225 226 if (VcbAcquired) { 227 ExReleaseResourceLite(&Vcb->MainResource); 228 } 229 230 IrpContext->Irp->IoStatus.Status = Status; 231 Ext2CompleteRequest( 232 IrpContext->Irp, FALSE, (CCHAR)(NT_SUCCESS(Status)? 233 IO_DISK_INCREMENT : IO_NO_INCREMENT) ); 234 235 IrpContext->Irp = NULL; 236 } _SEH2_END; 237 238 return Status; 239 } 240 241 NTSTATUS 242 Ext2PnpRemove ( 243 PEXT2_IRP_CONTEXT IrpContext, 244 PEXT2_VCB Vcb ) 245 { 246 NTSTATUS Status = STATUS_SUCCESS; 247 KEVENT Event; 248 BOOLEAN bDeleted; 249 250 _SEH2_TRY { 251 252 DEBUG(DL_PNP, ("Ext2PnpRemove by Ext2Pnp ...\n")); 253 254 CcWaitForCurrentLazyWriterActivity(); 255 ExAcquireResourceExclusiveLite( 256 &Vcb->MainResource, TRUE ); 257 Status = Ext2LockVcb(Vcb, IrpContext->FileObject); 258 ExReleaseResourceLite(&Vcb->MainResource); 259 260 // 261 // Setup the Irp. We'll send it to the lower disk driver. 262 // 263 264 IoCopyCurrentIrpStackLocationToNext(IrpContext->Irp); 265 266 KeInitializeEvent( &Event, NotificationEvent, FALSE ); 267 IoSetCompletionRoutine( IrpContext->Irp, 268 Ext2PnpCompletionRoutine, 269 &Event, 270 TRUE, 271 TRUE, 272 TRUE ); 273 274 Status = IoCallDriver( Vcb->TargetDeviceObject, 275 IrpContext->Irp); 276 277 if (Status == STATUS_PENDING) { 278 279 KeWaitForSingleObject( &Event, 280 Executive, 281 KernelMode, 282 FALSE, 283 NULL ); 284 285 Status = IrpContext->Irp->IoStatus.Status; 286 } 287 288 /* purge volume cache */ 289 Ext2PurgeVolume(Vcb, FALSE); 290 291 /* dismount volume */ 292 bDeleted = Ext2CheckDismount(IrpContext, Vcb, TRUE); 293 SetLongFlag(Vcb->Flags, VCB_DEVICE_REMOVED); 294 295 } _SEH2_FINALLY { 296 297 IrpContext->Irp->IoStatus.Status = Status; 298 Ext2CompleteRequest( 299 IrpContext->Irp, FALSE, (CCHAR)(NT_SUCCESS(Status)? 300 IO_DISK_INCREMENT : IO_NO_INCREMENT) ); 301 302 IrpContext->Irp = NULL; 303 } _SEH2_END; 304 305 return Status; 306 } 307 308 309 NTSTATUS 310 Ext2PnpSurpriseRemove ( 311 PEXT2_IRP_CONTEXT IrpContext, 312 PEXT2_VCB Vcb ) 313 { 314 NTSTATUS Status; 315 KEVENT Event; 316 BOOLEAN bDeleted; 317 318 _SEH2_TRY { 319 320 DEBUG(DL_PNP, ("Ext2PnpSupriseRemove by Ext2Pnp ...\n")); 321 322 CcWaitForCurrentLazyWriterActivity(); 323 ExAcquireResourceExclusiveLite( 324 &Vcb->MainResource, TRUE ); 325 326 Status = Ext2LockVcb(Vcb, IrpContext->FileObject); 327 328 ExReleaseResourceLite(&Vcb->MainResource); 329 330 // 331 // Setup the Irp. We'll send it to the lower disk driver. 332 // 333 334 IoCopyCurrentIrpStackLocationToNext(IrpContext->Irp); 335 336 KeInitializeEvent( &Event, NotificationEvent, FALSE ); 337 IoSetCompletionRoutine( IrpContext->Irp, 338 Ext2PnpCompletionRoutine, 339 &Event, 340 TRUE, 341 TRUE, 342 TRUE ); 343 344 Status = IoCallDriver( Vcb->TargetDeviceObject, 345 IrpContext->Irp); 346 347 if (Status == STATUS_PENDING) { 348 349 KeWaitForSingleObject( &Event, 350 Executive, 351 KernelMode, 352 FALSE, 353 NULL ); 354 355 Status = IrpContext->Irp->IoStatus.Status; 356 } 357 358 /* purge volume cache */ 359 Ext2PurgeVolume(Vcb, FALSE); 360 361 /* dismount volume */ 362 bDeleted = Ext2CheckDismount(IrpContext, Vcb, TRUE); 363 SetLongFlag(Vcb->Flags, VCB_DEVICE_REMOVED); 364 365 } _SEH2_FINALLY { 366 367 IrpContext->Irp->IoStatus.Status = Status; 368 Ext2CompleteRequest( 369 IrpContext->Irp, FALSE, (CCHAR)(NT_SUCCESS(Status)? 370 IO_DISK_INCREMENT : IO_NO_INCREMENT) ); 371 372 IrpContext->Irp = NULL; 373 } _SEH2_END; 374 375 return Status; 376 } 377 378 379 NTSTATUS 380 Ext2PnpCancelRemove ( 381 PEXT2_IRP_CONTEXT IrpContext, 382 PEXT2_VCB Vcb 383 ) 384 { 385 NTSTATUS Status; 386 387 DEBUG(DL_PNP, ("Ext2PnpCancelRemove by Ext2Pnp ...\n")); 388 389 ExAcquireResourceExclusiveLite( 390 &Vcb->MainResource, TRUE ); 391 392 Status = Ext2UnlockVcb(Vcb, IrpContext->FileObject); 393 394 ExReleaseResourceLite(&Vcb->MainResource); 395 396 IoSkipCurrentIrpStackLocation(IrpContext->Irp); 397 398 Status = IoCallDriver(Vcb->TargetDeviceObject, IrpContext->Irp); 399 400 IrpContext->Irp = NULL; 401 402 return Status; 403 } 404 405 #endif //(_WIN32_WINNT >= 0x0500) 406