[UDFS] Fix an include. CORE-9774
[reactos.git] / reactos / drivers / filesystems / udfs / pnp.cpp
1 ////////////////////////////////////////////////////////////////////
2 // Copyright (C) Alexander Telyatnikov, Ivan Keliukh, Yegor Anchishkin, SKIF Software, 1999-2013. Kiev, Ukraine
3 // All rights reserved
4 ////////////////////////////////////////////////////////////////////
5 /*************************************************************************
6 *
7 * File: Pnp.cpp
8 *
9 * Module: UDF File System Driver (Kernel mode execution only)
10 *
11 * Description:
12 * This module implements the Plug and Play routines for UDF called by
13 * the dispatch driver.
14 *
15 *************************************************************************/
16
17 #include "udffs.h"
18
19 // define the file specific bug-check id
20 #define UDF_BUG_CHECK_ID UDF_FILE_PNP
21
22
23 NTSTATUS
24 UDFPnpQueryRemove (
25 PtrUDFIrpContext PtrIrpContext,
26 PIRP Irp,
27 PVCB Vcb
28 );
29
30 NTSTATUS
31 UDFPnpRemove (
32 PtrUDFIrpContext PtrIrpContext,
33 PIRP Irp,
34 PVCB Vcb
35 );
36
37 NTSTATUS
38 UDFPnpSurpriseRemove (
39 PtrUDFIrpContext PtrIrpContext,
40 PIRP Irp,
41 PVCB Vcb
42 );
43
44 NTSTATUS
45 UDFPnpCancelRemove (
46 PtrUDFIrpContext PtrIrpContext,
47 PIRP Irp,
48 PVCB Vcb
49 );
50
51 NTSTATUS
52 NTAPI
53 UDFPnpCompletionRoutine (
54 IN PDEVICE_OBJECT DeviceObject,
55 IN PIRP Irp,
56 IN PVOID Contxt
57 );
58
59 NTSTATUS
60 UDFCommonPnp (
61 PtrUDFIrpContext PtrIrpContext,
62 IN PIRP Irp
63 );
64
65 /*
66 This routine implements the FSD part of PnP operations
67
68 Arguments:
69
70 VolumeDeviceObject - Supplies the volume device object where the
71 file exists
72 Irp - Supplies the Irp being processed
73
74 Return Value:
75
76 NTSTATUS - The FSD status for the IRP
77
78 */
79 NTSTATUS
80 UDFPnp (
81 IN PDEVICE_OBJECT DeviceObject,
82 IN PIRP Irp
83 )
84 {
85 NTSTATUS RC;
86 PtrUDFIrpContext PtrIrpContext = NULL;
87 BOOLEAN AreWeTopLevel;
88
89 KdPrint(("UDFPnp\n"));
90 ASSERT(FALSE);
91
92 FsRtlEnterFileSystem();
93 ASSERT(DeviceObject);
94 ASSERT(Irp);
95
96 // set the top level context
97 AreWeTopLevel = UDFIsIrpTopLevel(Irp);
98
99 _SEH2_TRY {
100 // We expect there to never be a fileobject, in which case we will always
101 // wait. Since at the moment we don't have any concept of pending Pnp
102 // operations, this is a bit nitpicky.
103
104 // get an IRP context structure and issue the request
105 PtrIrpContext = UDFAllocateIrpContext(Irp, DeviceObject);
106 if(PtrIrpContext) {
107 RC = UDFCommonPnp(PtrIrpContext, Irp);
108 } else {
109 RC = STATUS_INSUFFICIENT_RESOURCES;
110 Irp->IoStatus.Status = RC;
111 Irp->IoStatus.Information = 0;
112 // complete the IRP
113 IoCompleteRequest(Irp, IO_DISK_INCREMENT);
114 }
115
116 } _SEH2_EXCEPT(UDFExceptionFilter( PtrIrpContext, _SEH2_GetExceptionInformation() )) {
117
118 RC = UDFExceptionHandler(PtrIrpContext, Irp);
119 UDFLogEvent(UDF_ERROR_INTERNAL_ERROR, RC);
120 } _SEH2_END;
121
122 if (AreWeTopLevel) {
123 IoSetTopLevelIrp(NULL);
124 }
125
126 FsRtlExitFileSystem();
127
128 return RC;
129 }
130
131 /*
132 This is the common routine for doing PnP operations called
133 by both the fsd and fsp threads
134
135 Arguments:
136
137 Irp - Supplies the Irp to process
138
139 Return Value:
140
141 NTSTATUS - The return status for the operation
142 */
143 NTSTATUS
144 UDFCommonPnp (
145 PtrUDFIrpContext PtrIrpContext,
146 IN PIRP Irp
147 )
148 {
149 NTSTATUS RC;
150 PIO_STACK_LOCATION IrpSp;
151 PVCB Vcb;
152 KdPrint(("UDFCommonPnp\n"));
153
154 _SEH2_TRY {
155 // Get the current Irp stack location.
156 IrpSp = IoGetCurrentIrpStackLocation(Irp);
157
158 // Make sure this device object really is big enough to be a volume device
159 // object. If it isn't, we need to get out before we try to reference some
160 // field that takes us past the end of an ordinary device object.
161 Vcb = (PVCB)(IrpSp->DeviceObject->DeviceExtension);
162
163 if (Vcb->NodeIdentifier.NodeType != UDF_NODE_TYPE_VCB) {
164 // We were called with something we don't understand.
165 if(Irp->Flags & IRP_INPUT_OPERATION) {
166 Irp->IoStatus.Information = 0;
167 }
168 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
169
170 IoCompleteRequest( Irp, IO_DISK_INCREMENT );
171 try_return (RC = STATUS_INVALID_PARAMETER);
172 }
173
174 // Force everything to wait.
175 PtrIrpContext->IrpContextFlags |= UDF_IRP_CONTEXT_CAN_BLOCK;
176
177 // Case on the minor code.
178 switch ( IrpSp->MinorFunction ) {
179
180 case IRP_MN_QUERY_REMOVE_DEVICE:
181 RC = UDFPnpQueryRemove( PtrIrpContext, Irp, Vcb );
182 break;
183
184 case IRP_MN_SURPRISE_REMOVAL:
185 RC = UDFPnpSurpriseRemove( PtrIrpContext, Irp, Vcb );
186 break;
187
188 case IRP_MN_REMOVE_DEVICE:
189 RC = UDFPnpRemove( PtrIrpContext, Irp, Vcb );
190 break;
191
192 /* case IRP_MN_CANCEL_REMOVE_DEVICE:
193 RC = UDFPnpCancelRemove( PtrIrpContext, Irp, Vcb );
194 break;*/
195
196 default:
197 KdPrint(("UDFCommonPnp: pass through\n"));
198 // Just pass the IRP on. As we do not need to be in the
199 // way on return, ellide ourselves out of the stack.
200 IoSkipCurrentIrpStackLocation( Irp );
201 RC = IoCallDriver(Vcb->TargetDeviceObject, Irp);
202 ASSERT(RC != STATUS_PENDING);
203
204 break;
205 }
206
207 try_exit: NOTHING;
208
209 } _SEH2_FINALLY {
210 UDFReleaseIrpContext(PtrIrpContext);
211 } _SEH2_END;
212
213 return RC;
214 }
215
216
217 /*
218 Routine Description:
219 This routine handles the PnP query remove operation. The filesystem
220 is responsible for answering whether there are any reasons it sees
221 that the volume can not go away (and the device removed). Initiation
222 of the dismount begins when we answer yes to this question.
223
224 Query will be followed by a Cancel or Remove.
225
226 Arguments:
227 Irp - Supplies the Irp to process
228 Vcb - Supplies the volume being queried.
229
230 Return Value:
231 NTSTATUS - The return status for the operation
232 */
233 NTSTATUS
234 UDFPnpQueryRemove(
235 PtrUDFIrpContext PtrIrpContext,
236 PIRP Irp,
237 PVCB Vcb
238 )
239 {
240 NTSTATUS RC;
241 KEVENT Event;
242 BOOLEAN VcbDeleted = FALSE;
243 BOOLEAN GlobalHeld = FALSE;
244 BOOLEAN VcbAcquired = FALSE;
245 PPREVENT_MEDIA_REMOVAL_USER_IN Buf = NULL;
246
247 // Having said yes to a QUERY, any communication with the
248 // underlying storage stack is undefined (and may block)
249 // until the bounding CANCEL or REMOVE is sent.
250
251 _SEH2_TRY {
252
253 // Acquire the global resource so that we can try to vaporize
254 // the volume, and the vcb resource itself.
255 UDFAcquireResourceExclusive(&(UDFGlobalData.GlobalDataResource), TRUE);
256 GlobalHeld = TRUE;
257
258 if(!(Vcb->VCBFlags & UDF_VCB_FLAGS_RAW_DISK))
259 UDFCloseAllSystemDelayedInDir(Vcb, Vcb->RootDirFCB->FileInfo);
260 #ifdef UDF_DELAYED_CLOSE
261 UDFCloseAllDelayed(Vcb);
262 #endif //UDF_DELAYED_CLOSE
263
264 UDFAcquireResourceExclusive(&(Vcb->VCBResource),TRUE);
265 VcbAcquired = TRUE;
266
267 Buf = (PPREVENT_MEDIA_REMOVAL_USER_IN)MyAllocatePool__(NonPagedPool, sizeof(PREVENT_MEDIA_REMOVAL_USER_IN));
268 // With the volume held locked, note that we must finalize as much
269 // as possible right now.
270 UDFDoDismountSequence(Vcb, Buf, FALSE);
271
272 // disable Eject Request Waiter if any
273 UDFReleaseResource( &(Vcb->VCBResource) );
274 VcbAcquired = FALSE;
275 UDFStopEjectWaiter(Vcb);
276 UDFAcquireResourceExclusive(&(Vcb->VCBResource),TRUE);
277 VcbAcquired = TRUE;
278
279 // We need to pass this down before starting the dismount, which
280 // could disconnect us immediately from the stack.
281
282 // Get the next stack location, and copy over the stack location
283 IoCopyCurrentIrpStackLocationToNext( Irp );
284
285 // Set up the completion routine
286 KeInitializeEvent( &Event, NotificationEvent, FALSE );
287 IoSetCompletionRoutine( Irp,
288 UDFPnpCompletionRoutine,
289 &Event,
290 TRUE,
291 TRUE,
292 TRUE );
293 // Send the request and wait.
294 RC = IoCallDriver(Vcb->TargetDeviceObject, Irp);
295
296 if (RC == STATUS_PENDING) {
297 KeWaitForSingleObject( &Event,
298 Executive,
299 KernelMode,
300 FALSE,
301 NULL );
302
303 RC = Irp->IoStatus.Status;
304 }
305
306 // Now if no one below us failed already, initiate the dismount
307 // on this volume, make it go away. PnP needs to see our internal
308 // streams close and drop their references to the target device.
309
310 // Since we were able to lock the volume, we are guaranteed to
311 // move this volume into dismount state and disconnect it from
312 // the underlying storage stack. The force on our part is actually
313 // unnecesary, though complete.
314
315 // What is not strictly guaranteed, though, is that the closes
316 // for the metadata streams take effect synchronously underneath
317 // of this call. This would leave references on the target device
318 // even though we are disconnected!
319 if (NT_SUCCESS( RC )) {
320 VcbDeleted = !UDFCheckForDismount( PtrIrpContext, Vcb, TRUE );
321 ASSERT( VcbDeleted );
322 }
323
324 // Release the Vcb if it could still remain.
325
326 // Note: if everything else succeeded and the Vcb is persistent because the
327 // internal streams did not vaporize, we really need to pend this IRP off on
328 // the side until the dismount is completed. I can't think of a reasonable
329 // case (in UDF) where this would actually happen, though it might still need
330 // to be implemented.
331 //
332 // The reason this is the case is that handles/fileobjects place a reference
333 // on the device objects they overly. In the filesystem case, these references
334 // are on our target devices. PnP correcly thinks that if references remain
335 // on the device objects in the stack that someone has a handle, and that this
336 // counts as a reason to not succeed the query - even though every interrogated
337 // driver thinks that it is OK.
338 ASSERT( !(NT_SUCCESS( RC ) && !VcbDeleted ));
339
340 } _SEH2_FINALLY {
341
342 if (!VcbDeleted && VcbAcquired) {
343 UDFReleaseResource( &(Vcb->VCBResource) );
344 }
345
346 if (GlobalHeld) {
347 UDFReleaseResource( &(UDFGlobalData.GlobalDataResource) );
348 }
349
350 if (!_SEH2_AbnormalTermination()) {
351 Irp->IoStatus.Status = RC;
352 // Free up the Irp Context
353 UDFReleaseIrpContext(PtrIrpContext);
354 // complete the IRP
355 IoCompleteRequest(Irp, IO_DISK_INCREMENT);
356 }
357 } _SEH2_END;
358
359 return RC;
360 } // end UDFPnpQueryRemove()
361
362
363 /*
364 Routine Description:
365 This routine handles the PnP remove operation. This is our notification
366 that the underlying storage device for the volume we have is gone, and
367 an excellent indication that the volume will never reappear. The filesystem
368 is responsible for initiation or completion of the dismount.
369
370 Arguments:
371 Irp - Supplies the Irp to process
372 Vcb - Supplies the volume being removed.
373
374 Return Value:
375 NTSTATUS - The return status for the operation
376
377 --*/
378 NTSTATUS
379 UDFPnpRemove (
380 PtrUDFIrpContext PtrIrpContext,
381 PIRP Irp,
382 PVCB Vcb
383 )
384 {
385 NTSTATUS RC;
386 KEVENT Event;
387 BOOLEAN VcbDeleted;
388 BOOLEAN VcbAcquired;
389 PPREVENT_MEDIA_REMOVAL_USER_IN Buf = NULL;
390
391 // REMOVE - a storage device is now gone. We either got
392 // QUERY'd and said yes OR got a SURPRISE OR a storage
393 // stack failed to spin back up from a sleep/stop state
394 // (the only case in which this will be the first warning).
395 //
396 // Note that it is entirely unlikely that we will be around
397 // for a REMOVE in the first two cases, as we try to intiate
398 // dismount.
399
400 // Acquire the global resource so that we can try to vaporize
401 // the volume, and the vcb resource itself.
402 UDFAcquireResourceExclusive(&(UDFGlobalData.GlobalDataResource), TRUE);
403
404 if(!(Vcb->VCBFlags & UDF_VCB_FLAGS_RAW_DISK))
405 UDFCloseAllSystemDelayedInDir(Vcb, Vcb->RootDirFCB->FileInfo);
406 #ifdef UDF_DELAYED_CLOSE
407 UDFCloseAllDelayed(Vcb);
408 #endif //UDF_DELAYED_CLOSE
409
410 UDFAcquireResourceExclusive(&(Vcb->VCBResource),TRUE);
411 VcbAcquired = TRUE;
412
413 // The device will be going away. Remove our lock (benign
414 // if we never had it).
415 if((Vcb->Vpb->Flags & VPB_LOCKED) ||
416 (Vcb->VolumeLockPID != -1) ) {
417 Vcb->Vpb->Flags &= ~VPB_LOCKED;
418 Vcb->VCBFlags &= ~UDF_VCB_FLAGS_VOLUME_LOCKED;
419 Vcb->VolumeLockFileObject = NULL;
420 Vcb->VolumeLockPID = -1;
421 RC = STATUS_SUCCESS;
422 }
423
424 // We need to pass this down before starting the dismount, which
425 // could disconnect us immediately from the stack.
426
427 // Get the next stack location, and copy over the stack location
428 IoCopyCurrentIrpStackLocationToNext( Irp );
429
430 // Set up the completion routine
431 KeInitializeEvent( &Event, NotificationEvent, FALSE );
432 IoSetCompletionRoutine( Irp,
433 UDFPnpCompletionRoutine,
434 &Event,
435 TRUE,
436 TRUE,
437 TRUE );
438
439 // Send the request and wait.
440 RC = IoCallDriver(Vcb->TargetDeviceObject, Irp);
441
442 if (RC == STATUS_PENDING) {
443
444 KeWaitForSingleObject( &Event,
445 Executive,
446 KernelMode,
447 FALSE,
448 NULL );
449
450 RC = Irp->IoStatus.Status;
451 }
452
453 _SEH2_TRY {
454
455 // Knock as many files down for this volume as we can.
456
457 // Now make our dismount happen. This may not vaporize the
458 // Vcb, of course, since there could be any number of handles
459 // outstanding if we were not preceeded by a QUERY.
460 //
461 // PnP will take care of disconnecting this stack if we
462 // couldn't get off of it immediately.
463 Vcb->Vpb->RealDevice->Flags |= DO_VERIFY_VOLUME;
464 Buf = (PPREVENT_MEDIA_REMOVAL_USER_IN)MyAllocatePool__(NonPagedPool, sizeof(PREVENT_MEDIA_REMOVAL_USER_IN));
465 if(!Buf) try_return(RC = STATUS_INSUFFICIENT_RESOURCES);
466 UDFDoDismountSequence(Vcb, Buf, FALSE);
467 Vcb->VCBFlags &= ~UDF_VCB_FLAGS_VOLUME_MOUNTED;
468 Vcb->WriteSecurity = FALSE;
469 // disable Eject Request Waiter if any
470 UDFReleaseResource( &(Vcb->VCBResource) );
471 VcbAcquired = FALSE;
472
473 UDFStopEjectWaiter(Vcb);
474
475 VcbDeleted = !UDFCheckForDismount( PtrIrpContext, Vcb, FALSE );
476
477 try_exit: NOTHING;
478
479 } _SEH2_FINALLY {
480 // Release the Vcb if it could still remain.
481 if (!VcbDeleted && VcbAcquired) {
482 UDFReleaseResource(&(Vcb->VCBResource));
483 }
484 UDFReleaseResource(&(UDFGlobalData.GlobalDataResource));
485
486 if(Buf)
487 MyFreePool__(Buf);
488
489 if (!_SEH2_AbnormalTermination()) {
490 Irp->IoStatus.Status = RC;
491 // Free up the Irp Context
492 UDFReleaseIrpContext(PtrIrpContext);
493 // complete the IRP
494 IoCompleteRequest(Irp, IO_DISK_INCREMENT);
495 }
496 } _SEH2_END;
497
498 return RC;
499 }
500
501 \f
502 NTSTATUS
503 UDFPnpSurpriseRemove (
504 PtrUDFIrpContext PtrIrpContext,
505 PIRP Irp,
506 PVCB Vcb
507 )
508
509 /*++
510
511 Routine Description:
512
513 This routine handles the PnP surprise remove operation. This is another
514 type of notification that the underlying storage device for the volume we
515 have is gone, and is excellent indication that the volume will never reappear.
516 The filesystem is responsible for initiation or completion the dismount.
517
518 For the most part, only "real" drivers care about the distinction of a
519 surprise remove, which is a result of our noticing that a user (usually)
520 physically reached into the machine and pulled something out.
521
522 Surprise will be followed by a Remove when all references have been shut down.
523
524 Arguments:
525
526 Irp - Supplies the Irp to process
527
528 Vcb - Supplies the volume being removed.
529
530 Return Value:
531
532 NTSTATUS - The return status for the operation
533
534 --*/
535
536 {
537 NTSTATUS RC;
538 KEVENT Event;
539 BOOLEAN VcbDeleted;
540 BOOLEAN VcbAcquired;
541 PPREVENT_MEDIA_REMOVAL_USER_IN Buf = NULL;
542
543 // SURPRISE - a device was physically yanked away without
544 // any warning. This means external forces.
545
546 UDFAcquireResourceExclusive(&(UDFGlobalData.GlobalDataResource), TRUE);
547
548 if(!(Vcb->VCBFlags & UDF_VCB_FLAGS_RAW_DISK))
549 UDFCloseAllSystemDelayedInDir(Vcb, Vcb->RootDirFCB->FileInfo);
550 #ifdef UDF_DELAYED_CLOSE
551 UDFCloseAllDelayed(Vcb);
552 #endif //UDF_DELAYED_CLOSE
553
554 UDFAcquireResourceExclusive(&(Vcb->VCBResource),TRUE);
555 VcbAcquired = TRUE;
556
557 // We need to pass this down before starting the dismount, which
558 // could disconnect us immediately from the stack.
559
560 // Get the next stack location, and copy over the stack location
561 IoCopyCurrentIrpStackLocationToNext( Irp );
562
563 // Set up the completion routine
564 KeInitializeEvent( &Event, NotificationEvent, FALSE );
565 IoSetCompletionRoutine( Irp,
566 UDFPnpCompletionRoutine,
567 &Event,
568 TRUE,
569 TRUE,
570 TRUE );
571
572 // Send the request and wait.
573 RC = IoCallDriver(Vcb->TargetDeviceObject, Irp);
574
575 if (RC == STATUS_PENDING) {
576
577 KeWaitForSingleObject( &Event,
578 Executive,
579 KernelMode,
580 FALSE,
581 NULL );
582
583 RC = Irp->IoStatus.Status;
584 }
585
586 _SEH2_TRY {
587 // Knock as many files down for this volume as we can.
588 Vcb->Vpb->RealDevice->Flags |= DO_VERIFY_VOLUME;
589 Buf = (PPREVENT_MEDIA_REMOVAL_USER_IN)MyAllocatePool__(NonPagedPool, sizeof(PREVENT_MEDIA_REMOVAL_USER_IN));
590 if(!Buf) try_return(RC = STATUS_INSUFFICIENT_RESOURCES);
591 UDFDoDismountSequence(Vcb, Buf, FALSE);
592 Vcb->VCBFlags &= ~UDF_VCB_FLAGS_VOLUME_MOUNTED;
593 Vcb->WriteSecurity = FALSE;
594
595 UDFReleaseResource(&(Vcb->VCBResource));
596 VcbAcquired = FALSE;
597
598 UDFStopEjectWaiter(Vcb);
599
600 // Now make our dismount happen. This may not vaporize the
601 // Vcb, of course, since there could be any number of handles
602 // outstanding since this is an out of band notification.
603 VcbDeleted = !UDFCheckForDismount( PtrIrpContext, Vcb, FALSE );
604
605 try_exit: NOTHING;
606
607 } _SEH2_FINALLY {
608
609 // Release the Vcb if it could still remain.
610 if (!VcbDeleted && VcbAcquired) {
611 UDFReleaseResource(&(Vcb->VCBResource));
612 }
613 UDFReleaseResource(&(UDFGlobalData.GlobalDataResource));
614
615 if(Buf)
616 MyFreePool__(Buf);
617
618 if (!_SEH2_AbnormalTermination()) {
619 Irp->IoStatus.Status = RC;
620 // Free up the Irp Context
621 UDFReleaseIrpContext(PtrIrpContext);
622 // complete the IRP
623 IoCompleteRequest(Irp, IO_DISK_INCREMENT);
624 }
625 } _SEH2_END;
626
627 return RC;
628 }
629
630 /*\f
631 NTSTATUS
632 UDFPnpCancelRemove (
633 PtrUDFIrpContext PtrIrpContext,
634 PIRP Irp,
635 PVCB Vcb
636 )
637
638 /*++
639
640 Routine Description:
641
642 This routine handles the PnP cancel remove operation. This is our
643 notification that a previously proposed remove (query) was eventually
644 vetoed by a component. The filesystem is responsible for cleaning up
645 and getting ready for more IO.
646
647 Arguments:
648
649 Irp - Supplies the Irp to process
650
651 Vcb - Supplies the volume being removed.
652
653 Return Value:
654
655 NTSTATUS - The return status for the operation
656
657 --*/
658
659 /*{
660 NTSTATUS RC;
661
662 // CANCEL - a previous QUERY has been rescinded as a result
663 // of someone vetoing. Since PnP cannot figure out who may
664 // have gotten the QUERY (think about it: stacked drivers),
665 // we must expect to deal with getting a CANCEL without having
666 // seen the QUERY.
667 //
668 // For UDF, this is quite easy. In fact, we can't get a
669 // CANCEL if the underlying drivers succeeded the QUERY since
670 // we disconnect the Vpb on our dismount initiation. This is
671 // actually pretty important because if PnP could get to us
672 // after the disconnect we'd be thoroughly unsynchronized
673 // with respect to the Vcb getting torn apart - merely referencing
674 // the volume device object is insufficient to keep us intact.
675
676 UDFAcquireResourceExclusive(&(Vcb->VCBResource),TRUE);
677
678 // Unlock the volume. This is benign if we never had seen
679 // a QUERY.
680 if(Vcb->Vpb->Flags & VPB_LOCKED) {
681 Vcb->Vpb->Flags &= ~VPB_LOCKED;
682 Vcb->VCBFlags &= ~UDF_VCB_FLAGS_VOLUME_LOCKED;
683 Vcb->VolumeLockFileObject = NULL;
684 RC = STATUS_SUCCESS;
685 } else {
686 RC = STATUS_NOT_LOCKED;
687 }
688
689 try {
690
691 // We must re-enable allocation support if we got through
692 // the first stages of a QUERY_REMOVE; i.e., we decided we
693 // could place a lock on the volume.
694 if (NT_SUCCESS( RC )) {
695 FatSetupAllocationSupport( PtrIrpContext, Vcb );
696 }
697
698 } finally {
699 UDFReleaseResource(&(Vcb->VCBResource));
700 }
701
702 // Send the request. The underlying driver will complete the
703 // IRP. Since we don't need to be in the way, simply ellide
704 // ourselves out of the IRP stack.
705 IoSkipCurrentIrpStackLocation( Irp );
706
707 RC = IoCallDriver(Vcb->TargetDeviceObject, Irp);
708
709 // if (!AbnormalTermination()) {
710 Irp->IoStatus.Status = RC;
711 // Free up the Irp Context
712 UDFReleaseIrpContext(PtrIrpContext);
713 // complete the IRP
714 IoCompleteRequest(Irp, IO_DISK_INCREMENT);
715 // }
716
717 return RC;
718 } */
719
720 \f
721 // Local support routine
722 NTSTATUS
723 NTAPI
724 UDFPnpCompletionRoutine (
725 IN PDEVICE_OBJECT DeviceObject,
726 IN PIRP Irp,
727 IN PVOID Contxt
728 )
729 {
730 PKEVENT Event = (PKEVENT) Contxt;
731
732 KeSetEvent( Event, 0, FALSE );
733
734 return STATUS_MORE_PROCESSING_REQUIRED;
735
736 UNREFERENCED_PARAMETER( DeviceObject );
737 UNREFERENCED_PARAMETER( Contxt );
738 }
739
740