1 ////////////////////////////////////////////////////////////////////
2 // Copyright (C) Alexander Telyatnikov, Ivan Keliukh, Yegor Anchishkin, SKIF Software, 1999-2013. Kiev, Ukraine
3 // All rights reserved
4 // This file was released under the GPLv2 on June 2015.
5 ////////////////////////////////////////////////////////////////////
6 /*************************************************************************
7 *
8 * File: Devcntrl.cpp
9 *
10 * Module: UDF File System Driver (Kernel mode execution only)
11 *
12 * Description:
13 *   Contains code to handle the "Device IOCTL" dispatch entry point.
14 *
15 *************************************************************************/
16 
17 #include "udffs.h"
18 
19 #include "CDRW/scsi_port.h"
20 
21 #define UDF_CURRENT_BUILD 123456789
22 
23 // define the file specific bug-check id
24 #ifdef UDF_BUG_CHECK_ID
25 #undef UDF_BUG_CHECK_ID
26 #endif
27 #define         UDF_BUG_CHECK_ID                UDF_FILE_DEVICE_CONTROL
28 
29 NTSTATUS
30 UDFGetFileAllocModeFromICB(
31     PtrUDFIrpContext PtrIrpContext,
32     PIRP             Irp
33     );
34 
35 NTSTATUS
36 UDFSetFileAllocModeFromICB(
37     PtrUDFIrpContext IrpContext,
38     PIRP             Irp
39     );
40 
41 NTSTATUS
42 UDFProcessLicenseKey(
43     PtrUDFIrpContext IrpContext,
44     PIRP             Irp
45     );
46 
47 /*#if(_WIN32_WINNT < 0x0400)
48 #define IOCTL_REDIR_QUERY_PATH   CTL_CODE(FILE_DEVICE_NETWORK_FILE_SYSTEM, 99, METHOD_NEITHER, FILE_ANY_ACCESS)
49 
50 typedef struct _QUERY_PATH_REQUEST {
51     ULONG PathNameLength;
52     PIO_SECURITY_CONTEXT SecurityContext;
53     WCHAR FilePathName[1];
54 } QUERY_PATH_REQUEST, *PQUERY_PATH_REQUEST;
55 
56 typedef struct _QUERY_PATH_RESPONSE {
57     ULONG LengthAccepted;
58 } QUERY_PATH_RESPONSE, *PQUERY_PATH_RESPONSE;
59 
60 #endif*/
61 
62 
63 /*************************************************************************
64 *
65 * Function: UDFDeviceControl()
66 *
67 * Description:
68 *   The I/O Manager will invoke this routine to handle a Device IOCTL
69 *   request
70 *
71 * Expected Interrupt Level (for execution) :
72 *
73 *  IRQL_PASSIVE_LEVEL (invocation at higher IRQL will cause execution
74 *   to be deferred to a worker thread context)
75 *
76 * Return Value: STATUS_SUCCESS/Error
77 *
78 *************************************************************************/
79 NTSTATUS
80 NTAPI
81 UDFDeviceControl(
82     PDEVICE_OBJECT          DeviceObject,       // the logical volume device object
83     PIRP                    Irp)                // I/O Request Packet
84 {
85     NTSTATUS            RC = STATUS_SUCCESS;
86     PtrUDFIrpContext    PtrIrpContext = NULL;
87     BOOLEAN             AreWeTopLevel = FALSE;
88 
89     TmPrint(("UDFDeviceControl: \n"));
90 
91     FsRtlEnterFileSystem();
92     ASSERT(DeviceObject);
93     ASSERT(Irp);
94 
95     // set the top level context
96     AreWeTopLevel = UDFIsIrpTopLevel(Irp);
97     //ASSERT(!UDFIsFSDevObj(DeviceObject));
98 
99     _SEH2_TRY {
100 
101         // get an IRP context structure and issue the request
102         PtrIrpContext = UDFAllocateIrpContext(Irp, DeviceObject);
103         if(PtrIrpContext) {
104             RC = UDFCommonDeviceControl(PtrIrpContext, Irp);
105         } else {
106             RC = STATUS_INSUFFICIENT_RESOURCES;
107             Irp->IoStatus.Status = RC;
108             Irp->IoStatus.Information = 0;
109             // complete the IRP
110             IoCompleteRequest(Irp, IO_DISK_INCREMENT);
111         }
112 
113     } _SEH2_EXCEPT(UDFExceptionFilter(PtrIrpContext, _SEH2_GetExceptionInformation())) {
114 
115         RC = UDFExceptionHandler(PtrIrpContext, Irp);
116 
117         UDFLogEvent(UDF_ERROR_INTERNAL_ERROR, RC);
118     } _SEH2_END;
119 
120     if (AreWeTopLevel) {
121         IoSetTopLevelIrp(NULL);
122     }
123 
124     FsRtlExitFileSystem();
125 
126     return(RC);
127 } // end UDFDeviceControl()
128 
129 
130 /*************************************************************************
131 *
132 * Function: UDFCommonDeviceControl()
133 *
134 * Description:
135 *   The actual work is performed here. This routine may be invoked in one'
136 *   of the two possible contexts:
137 *   (a) in the context of a system worker thread
138 *   (b) in the context of the original caller
139 *
140 * Expected Interrupt Level (for execution) :
141 *
142 *  IRQL_PASSIVE_LEVEL
143 *
144 * Return Value: STATUS_SUCCESS/Error
145 *
146 *************************************************************************/
147 NTSTATUS
148 NTAPI
149 UDFCommonDeviceControl(
150     PtrUDFIrpContext PtrIrpContext,
151     PIRP             Irp
152     )
153 {
154     NTSTATUS                RC = STATUS_SUCCESS;
155     PIO_STACK_LOCATION      IrpSp = NULL;
156 //    PIO_STACK_LOCATION      PtrNextIoStackLocation = NULL;
157     PFILE_OBJECT            FileObject = NULL;
158     PtrUDFFCB               Fcb = NULL;
159     PtrUDFCCB               Ccb = NULL;
160     PVCB                    Vcb = NULL;
161     BOOLEAN                 CompleteIrp = FALSE;
162     ULONG                   IoControlCode = 0;
163 //    PVOID                   BufferPointer = NULL;
164     BOOLEAN                 AcquiredVcb = FALSE;
165     BOOLEAN                 FSDevObj;
166     ULONG                   TrackNumber;
167     BOOLEAN                 UnsafeIoctl = TRUE;
168     UCHAR                   ScsiCommand;
169     PPREVENT_MEDIA_REMOVAL_USER_IN Buf = NULL;    // FSD buffer
170     PCDB                    Cdb;
171     PCHAR                   CdbData;
172     PCHAR                   ModeSelectData;
173 
174     UDFPrint(("UDFCommonDeviceControl\n"));
175 
176     _SEH2_TRY {
177         // First, get a pointer to the current I/O stack location
178         IrpSp = IoGetCurrentIrpStackLocation(Irp);
179         ASSERT(IrpSp);
180 
181         // Get the IoControlCode value
182         IoControlCode = IrpSp->Parameters.DeviceIoControl.IoControlCode;
183 
184         FileObject = IrpSp->FileObject;
185         ASSERT(FileObject);
186 
187         FSDevObj = UDFIsFSDevObj(PtrIrpContext->TargetDeviceObject);
188 
189         if(FSDevObj) {
190             switch (IoControlCode) {
191             case IOCTL_UDF_DISABLE_DRIVER:
192             case IOCTL_UDF_INVALIDATE_VOLUMES:
193             case IOCTL_UDF_SET_NOTIFICATION_EVENT:
194 #ifndef UDF_READ_ONLY_BUILD
195             case IOCTL_UDF_SEND_LICENSE_KEY:
196 #endif //UDF_READ_ONLY_BUILD
197             case IOCTL_UDF_REGISTER_AUTOFORMAT:
198                 break;
199             default:
200                 UDFPrint(("UDFCommonDeviceControl: STATUS_INVALID_PARAMETER %x for FsDevObj\n", IoControlCode));
201                 CompleteIrp = TRUE;
202                 try_return(RC = STATUS_INVALID_PARAMETER);
203             }
204         } else {
205             Ccb = (PtrUDFCCB)(FileObject->FsContext2);
206             if(!Ccb) {
207                 UDFPrint(("  !Ccb\n"));
208                 goto ioctl_do_default;
209             }
210             ASSERT(Ccb);
211             Fcb = Ccb->Fcb;
212             ASSERT(Fcb);
213 
214             // Check if the IOCTL is suitable for this type of File
215             if (Fcb->NodeIdentifier.NodeType == UDF_NODE_TYPE_VCB) {
216                 // Everything is acceptable for Volume
217                 Vcb = (PVCB)(Fcb);
218             } else {
219                 Vcb = Fcb->Vcb;
220                 CompleteIrp = TRUE;
221                 // For files/disrs only the following are acceptable
222                 switch (IoControlCode) {
223                 case IOCTL_UDF_GET_RETRIEVAL_POINTERS:
224                 case IOCTL_UDF_GET_FILE_ALLOCATION_MODE:
225                 case IOCTL_UDF_SET_FILE_ALLOCATION_MODE:
226                     break;
227                 default:
228                     UDFPrint(("UDFCommonDeviceControl: STATUS_INVALID_PARAMETER %x for File/Dir Obj\n", IoControlCode));
229                     try_return(RC = STATUS_INVALID_PARAMETER);
230                 }
231             }
232             // check 'safe' IOCTLs
233             switch (IoControlCode) {
234             case IOCTL_CDROM_RAW_READ:
235 
236             case IOCTL_CDROM_GET_DRIVE_GEOMETRY:
237             case IOCTL_DISK_GET_DRIVE_GEOMETRY:
238             case IOCTL_DISK_GET_PARTITION_INFO:
239             case IOCTL_DISK_GET_DRIVE_LAYOUT:
240 
241             case IOCTL_CDROM_GET_DRIVE_GEOMETRY_EX:
242             case IOCTL_DISK_GET_PARTITION_INFO_EX:
243             case IOCTL_DISK_GET_DRIVE_LAYOUT_EX:
244             case IOCTL_DISK_GET_DRIVE_GEOMETRY_EX:
245 
246             case IOCTL_STORAGE_CHECK_VERIFY:
247             case IOCTL_STORAGE_CHECK_VERIFY2:
248             case IOCTL_DISK_CHECK_VERIFY:
249             case IOCTL_CDROM_CHECK_VERIFY:
250 
251             case IOCTL_CDROM_LOAD_MEDIA:
252             case IOCTL_DISK_LOAD_MEDIA:
253             case IOCTL_STORAGE_LOAD_MEDIA:
254             case IOCTL_STORAGE_LOAD_MEDIA2:
255 
256             case IOCTL_CDROM_GET_CONFIGURATION:
257             case IOCTL_CDROM_GET_LAST_SESSION:
258             case IOCTL_CDROM_READ_TOC:
259             case IOCTL_CDROM_READ_TOC_EX:
260             case IOCTL_CDROM_PLAY_AUDIO_MSF:
261             case IOCTL_CDROM_READ_Q_CHANNEL:
262             case IOCTL_CDROM_PAUSE_AUDIO:
263             case IOCTL_CDROM_RESUME_AUDIO:
264             case IOCTL_CDROM_SEEK_AUDIO_MSF:
265             case IOCTL_CDROM_STOP_AUDIO:
266             case IOCTL_CDROM_GET_CONTROL:
267             case IOCTL_CDROM_GET_VOLUME:
268             case IOCTL_CDROM_SET_VOLUME:
269 
270             case IOCTL_CDRW_SET_SPEED:
271             case IOCTL_CDRW_GET_CAPABILITIES:
272             case IOCTL_CDRW_GET_MEDIA_TYPE_EX:
273             case IOCTL_CDRW_GET_MEDIA_TYPE:
274 
275             case IOCTL_DISK_GET_MEDIA_TYPES:
276             case IOCTL_STORAGE_GET_MEDIA_TYPES:
277             case IOCTL_STORAGE_GET_MEDIA_TYPES_EX:
278 
279             case IOCTL_DISK_IS_WRITABLE:
280 
281             case IOCTL_CDRW_GET_WRITE_MODE:
282             case IOCTL_CDRW_READ_TRACK_INFO:
283             case IOCTL_CDRW_READ_DISC_INFO:
284             case IOCTL_CDRW_BUFFER_CAPACITY:
285             case IOCTL_CDRW_GET_SIGNATURE:
286             case IOCTL_CDRW_TEST_UNIT_READY:
287             case IOCTL_CDRW_GET_LAST_ERROR:
288             case IOCTL_CDRW_MODE_SENSE:
289             case IOCTL_CDRW_LL_READ:
290             case IOCTL_CDRW_READ_ATIP:
291             case IOCTL_CDRW_READ_CD_TEXT:
292             case IOCTL_CDRW_READ_TOC_EX:
293             case IOCTL_CDRW_READ_FULL_TOC:
294             case IOCTL_CDRW_READ_PMA:
295             case IOCTL_CDRW_READ_SESSION_INFO:
296             case IOCTL_CDRW_GET_DEVICE_INFO:
297             case IOCTL_CDRW_GET_EVENT:
298 
299             case IOCTL_DVD_READ_STRUCTURE:
300 
301             case IOCTL_CDRW_GET_DEVICE_NAME:
302             case IOCTL_MOUNTDEV_QUERY_DEVICE_NAME:
303 
304             case IOCTL_UDF_GET_RETRIEVAL_POINTERS:
305             case IOCTL_UDF_GET_SPEC_RETRIEVAL_POINTERS:
306             case IOCTL_UDF_GET_FILE_ALLOCATION_MODE:
307             case IOCTL_UDF_GET_VERSION:
308             case IOCTL_UDF_IS_VOLUME_JUST_MOUNTED:
309             case IOCTL_UDF_SET_OPTIONS:
310 //            case :
311 
312             case FSCTL_IS_VOLUME_DIRTY:
313 
314                 UnsafeIoctl = FALSE;
315                 break;
316             }
317 
318             if(IoControlCode != IOCTL_CDROM_DISK_TYPE) {
319                 UDFAcquireResourceShared(&(Vcb->VCBResource), TRUE);
320             } else {
321                 UDFAcquireResourceExclusive(&(Vcb->VCBResource), TRUE);
322             }
323             AcquiredVcb = TRUE;
324         }
325 
326         UDFPrint(("UDF Irp %x, ctx %x, DevIoCtl %x\n", Irp, PtrIrpContext, IoControlCode));
327 
328         // We may wish to allow only   volume open operations.
329         switch (IoControlCode) {
330 
331         case IOCTL_SCSI_PASS_THROUGH_DIRECT:
332         case IOCTL_SCSI_PASS_THROUGH:
333 
334             if(!Irp->AssociatedIrp.SystemBuffer)
335                 goto ioctl_do_default;
336 
337             if(IoControlCode == IOCTL_SCSI_PASS_THROUGH_DIRECT) {
338                 Cdb = (PCDB)&(((PSCSI_PASS_THROUGH_DIRECT)(Irp->AssociatedIrp.SystemBuffer))->Cdb);
339                 CdbData = (PCHAR)(((PSCSI_PASS_THROUGH_DIRECT)(Irp->AssociatedIrp.SystemBuffer))->DataBuffer);
340             } else {
341                 Cdb = (PCDB)&(((PSCSI_PASS_THROUGH)(Irp->AssociatedIrp.SystemBuffer))->Cdb);
342                 if(((PSCSI_PASS_THROUGH)(Irp->AssociatedIrp.SystemBuffer))->DataBufferOffset) {
343                     CdbData = ((PCHAR)Cdb) +
344                               ((PSCSI_PASS_THROUGH)(Irp->AssociatedIrp.SystemBuffer))->DataBufferOffset;
345                 } else {
346                     CdbData = NULL;
347                 }
348             }
349             ScsiCommand = Cdb->CDB6.OperationCode;
350 
351             if(ScsiCommand == SCSIOP_WRITE_CD) {
352                 UDFPrint(("Write10, LBA %2.2x%2.2x%2.2x%2.2x\n",
353                          Cdb->WRITE_CD.LBA[0],
354                          Cdb->WRITE_CD.LBA[1],
355                          Cdb->WRITE_CD.LBA[2],
356                          Cdb->WRITE_CD.LBA[3]
357                          ));
358             } else
359             if(ScsiCommand == SCSIOP_WRITE12) {
360                 UDFPrint(("Write12, LBA %2.2x%2.2x%2.2x%2.2x\n",
361                          Cdb->CDB12READWRITE.LBA[0],
362                          Cdb->CDB12READWRITE.LBA[1],
363                          Cdb->CDB12READWRITE.LBA[2],
364                          Cdb->CDB12READWRITE.LBA[3]
365                          ));
366             } else {
367             }
368 
369             switch(ScsiCommand) {
370             case SCSIOP_MODE_SELECT: {
371 //                PMODE_PARAMETER_HEADER ParamHdr = (PMODE_PARAMETER_HEADER)CdbData;
372                 ModeSelectData = CdbData+4;
373                 switch(ModeSelectData[0]) {
374                 case MODE_PAGE_MRW2:
375                 case MODE_PAGE_WRITE_PARAMS:
376                 case MODE_PAGE_MRW:
377                     UDFPrint(("Unsafe MODE_SELECT_6 via pass-through (%2.2x)\n", ModeSelectData[0]));
378                     goto unsafe_direct_scsi_cmd;
379                 }
380                 break; }
381 
382             case SCSIOP_MODE_SELECT10: {
383 //                PMODE_PARAMETER_HEADER10 ParamHdr = (PMODE_PARAMETER_HEADER10)CdbData;
384                 ModeSelectData = CdbData+8;
385                 switch(ModeSelectData[0]) {
386                 case MODE_PAGE_MRW2:
387                 case MODE_PAGE_WRITE_PARAMS:
388                 case MODE_PAGE_MRW:
389                     UDFPrint(("Unsafe MODE_SELECT_10 via pass-through (%2.2x)\n", ModeSelectData[0]));
390                     goto unsafe_direct_scsi_cmd;
391                 }
392                 break; }
393 
394             case SCSIOP_RESERVE_TRACK:
395             case SCSIOP_SEND_CUE_SHEET:
396             case SCSIOP_SEND_DVD_STRUCTURE:
397             case SCSIOP_CLOSE_TRACK_SESSION:
398             case SCSIOP_FORMAT_UNIT:
399             case SCSIOP_WRITE6:
400             case SCSIOP_WRITE_CD:
401             case SCSIOP_BLANK:
402             case SCSIOP_WRITE12:
403             case SCSIOP_SET_STREAMING:
404                 UDFPrint(("UDF Direct media modification via pass-through (%2.2x)\n", ScsiCommand));
405 unsafe_direct_scsi_cmd:
406                 if(!(Vcb->VCBFlags & UDF_VCB_FLAGS_VOLUME_MOUNTED))
407                     goto ioctl_do_default;
408 
409                 UDFPrint(("Forget this volume\n"));
410                 // Acquire Vcb resource (Shared -> Exclusive)
411                 UDFInterlockedIncrement((PLONG)&(Vcb->VCBOpenCount));
412                 UDFReleaseResource(&(Vcb->VCBResource));
413 
414                 if(!(Vcb->VCBFlags & UDF_VCB_FLAGS_RAW_DISK)) {
415                     UDFCloseAllSystemDelayedInDir(Vcb, Vcb->RootDirFCB->FileInfo);
416                 }
417 #ifdef UDF_DELAYED_CLOSE
418                 //  Acquire exclusive access to the Vcb.
419                 UDFCloseAllDelayed(Vcb);
420 #endif //UDF_DELAYED_CLOSE
421 
422                 // allocate tmp buffer for FSD calls
423                 Buf = (PPREVENT_MEDIA_REMOVAL_USER_IN)MyAllocatePool__(NonPagedPool, sizeof(PREVENT_MEDIA_REMOVAL_USER_IN));
424                 if(!Buf)
425                     try_return(RC = STATUS_INSUFFICIENT_RESOURCES);
426 
427                 UDFAcquireResourceExclusive(&(Vcb->VCBResource), TRUE);
428                 AcquiredVcb = TRUE;
429                 UDFInterlockedDecrement((PLONG)&(Vcb->VCBOpenCount));
430 
431                 UDFDoDismountSequence(Vcb, Buf, FALSE);
432                 MyFreePool__(Buf);
433                 Buf = NULL;
434                 Vcb->MediaLockCount = 0;
435 
436                 Vcb->VCBFlags &= ~UDF_VCB_FLAGS_VOLUME_MOUNTED;
437                 Vcb->WriteSecurity = FALSE;
438 
439                 // Release the Vcb resource.
440                 UDFReleaseResource(&(Vcb->VCBResource));
441                 AcquiredVcb = FALSE;
442                 // disable Eject Request Waiter if any
443                 UDFStopEjectWaiter(Vcb);
444 
445                 // Make sure, that volume will never be quick-remounted
446                 // It is very important for ChkUdf utility and
447                 // some CD-recording libraries
448                 Vcb->SerialNumber--;
449 
450                 UDFPrint(("Forgotten\n"));
451 
452                 goto notify_media_change;
453 
454             case SCSIOP_START_STOP_UNIT:
455             case SCSIOP_DOORLOCK:
456             case SCSIOP_DOORUNLOCK:
457             case SCSIOP_MEDIUM_REMOVAL:
458                 UDFPrint(("UDF Medium/Tray control IOCTL via pass-through\n"));
459             }
460             goto ioctl_do_default;
461 
462         case IOCTL_CDRW_BLANK:
463         case IOCTL_CDRW_LL_WRITE:
464         case IOCTL_CDRW_FORMAT_UNIT:
465 
466 notify_media_change:
467 /*            Vcb->VCBFlags |= UDF_VCB_FLAGS_UNSAFE_IOCTL;
468             // Make sure, that volume will never be quick-remounted
469             // It is very important for ChkUdf utility and
470             // some CD-recording libraries
471             Vcb->SerialNumber--;
472 */          goto ioctl_do_default;
473 
474         case IOCTL_UDF_REGISTER_AUTOFORMAT: {
475 
476             UDFPrint(("UDF Register Autoformat\n"));
477             if(UDFGlobalData.AutoFormatCount) {
478                 RC = STATUS_SHARING_VIOLATION;
479             } else {
480                 UDFGlobalData.AutoFormatCount = FileObject;
481                 RC = STATUS_SUCCESS;
482             }
483             CompleteIrp = TRUE;
484             Irp->IoStatus.Information = 0;
485             break;
486         }
487 
488         case IOCTL_UDF_DISABLE_DRIVER: {
489 
490             UDFPrint(("UDF Disable driver\n"));
491             IoUnregisterFileSystem(UDFGlobalData.UDFDeviceObject);
492             // Now, delete any device objects, etc. we may have created
493             if (UDFGlobalData.UDFDeviceObject) {
494                 IoDeleteDevice(UDFGlobalData.UDFDeviceObject);
495                 UDFGlobalData.UDFDeviceObject = NULL;
496             }
497 
498             // free up any memory we might have reserved for zones/lookaside
499             //  lists
500             if (UDFGlobalData.UDFFlags & UDF_DATA_FLAGS_ZONES_INITIALIZED) {
501                 UDFDestroyZones();
502             }
503 
504             // delete the resource we may have initialized
505             if (UDFGlobalData.UDFFlags & UDF_DATA_FLAGS_RESOURCE_INITIALIZED) {
506                 // un-initialize this resource
507                 UDFDeleteResource(&(UDFGlobalData.GlobalDataResource));
508                 UDFClearFlag(UDFGlobalData.UDFFlags, UDF_DATA_FLAGS_RESOURCE_INITIALIZED);
509             }
510             RC = STATUS_SUCCESS;
511             CompleteIrp = TRUE;
512             Irp->IoStatus.Information = 0;
513             break;
514         }
515         case IOCTL_UDF_INVALIDATE_VOLUMES: {
516             UDFPrint(("UDF Invaidate volume\n"));
517             if(AcquiredVcb) {
518                 UDFReleaseResource(&(Vcb->VCBResource));
519                 AcquiredVcb = FALSE;
520             }
521             RC = UDFInvalidateVolumes( PtrIrpContext, Irp );
522             CompleteIrp = TRUE;
523             Irp->IoStatus.Information = 0;
524             break;
525         }
526 
527         case IOCTL_UDF_SET_NOTIFICATION_EVENT:
528         {
529             if (IrpSp->Parameters.DeviceIoControl.InputBufferLength != sizeof(HANDLE))
530             {
531                 RC = STATUS_INVALID_PARAMETER;
532             }
533             else
534             {
535                 HANDLE MountEventHandle = *(PHANDLE)Irp->AssociatedIrp.SystemBuffer;
536                 if (MountEventHandle)
537                 {
538                     if (!UDFGlobalData.MountEvent)
539                     {
540                         RC = ObReferenceObjectByHandle(
541                             MountEventHandle,
542                             0,
543                             NULL,
544                             UserMode,
545                             (PVOID *) &UDFGlobalData.MountEvent,
546                             NULL);
547 
548                         if (!NT_SUCCESS(RC))
549                         {
550                             UDFGlobalData.MountEvent = NULL;
551                         }
552                     }
553                     else
554                     {
555                         RC = STATUS_INVALID_PARAMETER;
556                     }
557                 }
558                 else
559                 {
560                     if (!UDFGlobalData.MountEvent)
561                     {
562                         RC = STATUS_INVALID_PARAMETER;
563                     }
564                     else
565                     {
566                         ObDereferenceObject(UDFGlobalData.MountEvent);
567                         UDFGlobalData.MountEvent = NULL;
568                     }
569                 }
570             }
571 
572             CompleteIrp = TRUE;
573             Irp->IoStatus.Information = 0;
574             break;
575         }
576 
577         case IOCTL_UDF_IS_VOLUME_JUST_MOUNTED:
578         {
579             if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(BOOLEAN))
580             {
581                 RC = STATUS_INVALID_PARAMETER;
582             }
583             else
584             {
585                 *(PBOOLEAN)Irp->AssociatedIrp.SystemBuffer = Vcb->IsVolumeJustMounted;
586                 Vcb->IsVolumeJustMounted = FALSE;
587             }
588 
589             CompleteIrp = TRUE;
590             Irp->IoStatus.Information = 0;
591             break;
592         }
593 
594 
595         //case FSCTL_GET_RETRIEVAL_POINTERS
596         case IOCTL_UDF_GET_RETRIEVAL_POINTERS: {
597             UDFPrint(("UDF: Get Retrieval Pointers\n"));
598             RC = UDFGetRetrievalPointers( PtrIrpContext, Irp, 0 );
599             CompleteIrp = TRUE;
600             break;
601         }
602         case IOCTL_UDF_GET_SPEC_RETRIEVAL_POINTERS: {
603             UDFPrint(("UDF: Get Spec Retrieval Pointers\n"));
604             PUDF_GET_SPEC_RETRIEVAL_POINTERS_IN SpecRetrPointer;
605             SpecRetrPointer = (PUDF_GET_SPEC_RETRIEVAL_POINTERS_IN)(Irp->AssociatedIrp.SystemBuffer);
606             RC = UDFGetRetrievalPointers( PtrIrpContext, Irp, SpecRetrPointer->Special );
607             CompleteIrp = TRUE;
608             break;
609         }
610         case IOCTL_UDF_GET_FILE_ALLOCATION_MODE: {
611             UDFPrint(("UDF: Get File Alloc mode (from ICB)\n"));
612             RC = UDFGetFileAllocModeFromICB( PtrIrpContext, Irp );
613             CompleteIrp = TRUE;
614             break;
615         }
616 #ifndef UDF_READ_ONLY_BUILD
617         case IOCTL_UDF_SET_FILE_ALLOCATION_MODE: {
618             UDFPrint(("UDF: Set File Alloc mode\n"));
619             RC = UDFSetFileAllocModeFromICB( PtrIrpContext, Irp );
620             CompleteIrp = TRUE;
621             break;
622         }
623 #endif //UDF_READ_ONLY_BUILD
624         case IOCTL_UDF_LOCK_VOLUME_BY_PID:
625             if(AcquiredVcb) {
626                 UDFReleaseResource(&(Vcb->VCBResource));
627                 AcquiredVcb = FALSE;
628             }
629             RC = UDFLockVolume( PtrIrpContext, Irp, GetCurrentPID() );
630             CompleteIrp = TRUE;
631             break;
632         case IOCTL_UDF_UNLOCK_VOLUME_BY_PID:
633             if(AcquiredVcb) {
634                 UDFReleaseResource(&(Vcb->VCBResource));
635                 AcquiredVcb = FALSE;
636             }
637             RC = UDFUnlockVolume( PtrIrpContext, Irp, GetCurrentPID() );
638             CompleteIrp = TRUE;
639             break;
640 #ifndef UDF_READ_ONLY_BUILD
641         case IOCTL_UDF_SEND_LICENSE_KEY:
642             RC = STATUS_SUCCESS;
643 
644             Irp->IoStatus.Information = 0;
645             Irp->IoStatus.Status = STATUS_SUCCESS;
646             CompleteIrp = TRUE;
647             break;
648 #endif //UDF_READ_ONLY_BUILD
649         case IOCTL_UDF_GET_VERSION: {
650 
651             PUDF_GET_VERSION_OUT udf_ver;
652 
653             UDFPrint(("UDFUserFsCtrlRequest: IOCTL_UDF_GET_VERSION\n"));
654 
655             Irp->IoStatus.Information = 0;
656             CompleteIrp = TRUE;
657 
658             if(!IrpSp->Parameters.DeviceIoControl.OutputBufferLength) {
659                 UDFPrint(("!OutputBufferLength\n"));
660                 try_return(RC = STATUS_SUCCESS);
661             }
662             //  Check the size of the output buffer.
663             if(IrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(UDF_GET_VERSION_OUT)) {
664                 UDFPrint(("OutputBufferLength < %x\n", sizeof(UDF_GET_VERSION_OUT)));
665                 try_return(RC = STATUS_BUFFER_TOO_SMALL);
666             }
667 
668             udf_ver = (PUDF_GET_VERSION_OUT)(Irp->AssociatedIrp.SystemBuffer);
669             if(!udf_ver) {
670                 UDFPrint(("!udf_ver\n"));
671                 try_return(RC = STATUS_INVALID_USER_BUFFER);
672             }
673 
674             RtlZeroMemory(udf_ver, IrpSp->Parameters.DeviceIoControl.OutputBufferLength);
675 
676             udf_ver->header.Length = sizeof(UDF_GET_VERSION_OUT);
677             udf_ver->header.DriverVersionMj    = 0x00010005;
678             udf_ver->header.DriverVersionMn    = 0x12;
679             udf_ver->header.DriverVersionBuild = UDF_CURRENT_BUILD;
680 
681             udf_ver->FSVersionMj = Vcb->CurrentUDFRev >> 8;
682             udf_ver->FSVersionMn = Vcb->CurrentUDFRev & 0xff;
683             udf_ver->FSFlags     = Vcb->UserFSFlags;
684             if( ((Vcb->origIntegrityType == INTEGRITY_TYPE_OPEN) &&
685                 (Vcb->CompatFlags & UDF_VCB_IC_DIRTY_RO))
686                     ||
687                (Vcb->VCBFlags & UDF_VCB_FLAGS_VOLUME_READ_ONLY) ) {
688                 UDFPrint(("  UDF_USER_FS_FLAGS_RO\n"));
689                 udf_ver->FSFlags |= UDF_USER_FS_FLAGS_RO;
690             }
691             if(Vcb->VCBFlags & UDF_VCB_FLAGS_OUR_DEVICE_DRIVER) {
692                 UDFPrint(("  UDF_USER_FS_FLAGS_OUR_DRIVER\n"));
693                 udf_ver->FSFlags |= UDF_USER_FS_FLAGS_OUR_DRIVER;
694             }
695             if(Vcb->VCBFlags & UDF_VCB_FLAGS_RAW_DISK) {
696                 UDFPrint(("  UDF_USER_FS_FLAGS_RAW\n"));
697                 udf_ver->FSFlags |= UDF_USER_FS_FLAGS_RAW;
698             }
699             if(Vcb->VCBFlags & UDF_VCB_FLAGS_MEDIA_READ_ONLY) {
700                 UDFPrint(("  UDF_USER_FS_FLAGS_MEDIA_RO\n"));
701                 udf_ver->FSFlags |= UDF_USER_FS_FLAGS_MEDIA_RO;
702             }
703             if(Vcb->FP_disc) {
704                 UDFPrint(("  UDF_USER_FS_FLAGS_FP\n"));
705                 udf_ver->FSFlags |= UDF_USER_FS_FLAGS_FP;
706             }
707             udf_ver->FSCompatFlags = Vcb->CompatFlags;
708 
709             udf_ver->FSCfgVersion = Vcb->CfgVersion;
710 
711             Irp->IoStatus.Information = sizeof(UDF_GET_VERSION_OUT);
712             RC = STATUS_SUCCESS;
713             CompleteIrp = TRUE;
714 
715             break; }
716         case IOCTL_UDF_SET_OPTIONS: {
717 
718             PUDF_SET_OPTIONS_IN udf_opt;
719             BOOLEAN PrevVerifyOnWrite;
720 
721             UDFPrint(("UDF: IOCTL_UDF_SET_OPTIONS\n"));
722 
723             Irp->IoStatus.Information = 0;
724             CompleteIrp = TRUE;
725 
726             if(IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(UDF_SET_OPTIONS_IN)) {
727                 UDFPrint(("InputBufferLength < %x\n", sizeof(UDF_SET_OPTIONS_IN)));
728                 try_return(RC = STATUS_BUFFER_TOO_SMALL);
729             }
730 
731             udf_opt = (PUDF_SET_OPTIONS_IN)(Irp->AssociatedIrp.SystemBuffer);
732             if(!udf_opt) {
733                 UDFPrint(("!udf_opt\n"));
734                 try_return(RC = STATUS_INVALID_USER_BUFFER);
735             }
736 
737             if((udf_opt->header.Flags & UDF_SET_OPTIONS_FLAG_MASK) != UDF_SET_OPTIONS_FLAG_TEMPORARY) {
738                 UDFPrint(("invalid opt target\n"));
739                 try_return(RC = STATUS_INVALID_PARAMETER);
740             }
741 
742             if(AcquiredVcb) {
743                 UDFReleaseResource(&(Vcb->VCBResource));
744                 AcquiredVcb = FALSE;
745             }
746             UDFAcquireResourceExclusive(&(Vcb->VCBResource), TRUE);
747             AcquiredVcb = TRUE;
748 
749             PrevVerifyOnWrite = Vcb->VerifyOnWrite;
750 
751             Vcb->Cfg = ((PUCHAR)(udf_opt)) + udf_opt->header.HdrLength;
752             Vcb->CfgLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength - offsetof(UDF_SET_OPTIONS_IN, Data);
753             UDFReadRegKeys(Vcb, TRUE /*update*/, TRUE /*cfg*/);
754             Vcb->Cfg = NULL;
755             Vcb->CfgLength = 0;
756             Vcb->CfgVersion++;
757             //UDFReadRegKeys(Vcb, TRUE /*update*/, TRUE);
758             if(PrevVerifyOnWrite != Vcb->VerifyOnWrite) {
759                 if(Vcb->VerifyOnWrite) {
760                     UDFVInit(Vcb);
761                 } else {
762                     WCacheFlushBlocks__(&(Vcb->FastCache), Vcb, 0, Vcb->LastLBA);
763                     UDFVFlush(Vcb);
764                     UDFVRelease(Vcb);
765                 }
766             }
767 
768             RC = STATUS_SUCCESS;
769             break; }
770 #if 0
771         case IOCTL_UDF_GET_OPTIONS_VERSION: {
772 
773             PUDF_GET_OPTIONS_VERSION_OUT udf_opt_ver;
774 
775             UDFPrint(("UDF: IOCTL_UDF_GET_OPTIONS_VERSION\n"));
776 
777             Irp->IoStatus.Information = 0;
778             CompleteIrp = TRUE;
779 
780             if(IrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(UDF_GET_OPTIONS_VERSION_OUT)) {
781                 UDFPrint(("OutputBufferLength < %x\n", sizeof(UDF_GET_OPTIONS_VERSION_OUT)));
782                 try_return(RC = STATUS_BUFFER_TOO_SMALL);
783             }
784 
785             udf_opt_ver = (PUDF_GET_OPTIONS_VERSION_OUT)(Irp->AssociatedIrp.SystemBuffer);
786             if(!udf_opt_ver) {
787                 UDFPrint(("!udf_opt-ver\n"));
788                 try_return(RC = STATUS_INVALID_USER_BUFFER);
789             }
790 /*
791             if(AcquiredVcb) {
792                 UDFReleaseResource(&(Vcb->VCBResource));
793                 AcquiredVcb = FALSE;
794             }
795             UDFAcquireResourceShared(&(Vcb->VCBResource), TRUE);
796             AcquiredVcb = TRUE;
797 */
798             udf_opt_ver->CfgVersion = Vcb->CfgVersion;
799             Irp->IoStatus.Information = sizeof(UDF_GET_OPTIONS_VERSION_OUT);
800 
801             RC = STATUS_SUCCESS;
802             break; }
803 #endif //0
804         case IOCTL_CDRW_RESET_DRIVER:
805 
806             UDFPrint(("UDF: IOCTL_CDRW_RESET_DRIVER\n"));
807             Vcb->MediaLockCount = 0;
808             Vcb->VCBFlags &= ~UDF_VCB_FLAGS_MEDIA_LOCKED;
809             goto ioctl_do_default;
810 
811         case FSCTL_ALLOW_EXTENDED_DASD_IO:
812 
813             UDFPrint(("UDFUserFsCtrlRequest: FSCTL_ALLOW_EXTENDED_DASD_IO\n"));
814             // DASD i/o is always permitted
815             // So, no-op this call
816             RC = STATUS_SUCCESS;
817 
818             Irp->IoStatus.Information = 0;
819             Irp->IoStatus.Status = STATUS_SUCCESS;
820             CompleteIrp = TRUE;
821             break;
822 
823         case FSCTL_IS_VOLUME_DIRTY:
824 
825             UDFPrint(("UDFUserFsCtrlRequest: FSCTL_IS_VOLUME_DIRTY\n"));
826             // DASD i/o is always permitted
827             // So, no-op this call
828             RC = UDFIsVolumeDirty(PtrIrpContext, Irp);
829             CompleteIrp = TRUE;
830             break;
831 
832         case IOCTL_STORAGE_EJECT_MEDIA:
833         case IOCTL_DISK_EJECT_MEDIA:
834         case IOCTL_CDROM_EJECT_MEDIA: {
835 
836             UDFPrint(("UDF Reset/Eject request\n"));
837 //            PPREVENT_MEDIA_REMOVAL_USER_IN Buf;
838 
839             if(Vcb->EjectWaiter) {
840                 UDFPrint(("  Vcb->EjectWaiter present\n"));
841                 Irp->IoStatus.Information = 0;
842                 Vcb->EjectWaiter->SoftEjectReq = TRUE;
843                 Vcb->SoftEjectReq = TRUE;
844                 CompleteIrp = TRUE;
845                 try_return(RC = STATUS_SUCCESS);
846             }
847             UDFPrint(("  !Vcb->EjectWaiter\n"));
848             goto ioctl_do_default;
849 /*
850             Buf = (PPREVENT_MEDIA_REMOVAL_USER_IN)MyAllocatePool__(NonPagedPool, sizeof(PREVENT_MEDIA_REMOVAL_USER_IN));
851             if(!Buf) try_return(RC = STATUS_INSUFFICIENT_RESOURCES);
852             // Acquire Vcb resource (Shared -> Exclusive)
853             UDFReleaseResource(&(Vcb->VCBResource));
854             UDFAcquireResourceExclusive(&(Vcb->VCBResource), TRUE);
855 
856             Vcb->Vpb->RealDevice->Flags |= DO_VERIFY_VOLUME;
857             Vcb->VCBFlags &= ~UDF_VCB_FLAGS_VOLUME_MOUNTED;
858 
859             UDFDoDismountSequence(Vcb, Buf, IoControlCode == IOCTL_CDROM_EJECT_MEDIA);
860             // disable Eject Request Waiter if any
861             MyFreePool__(Buf);
862             // Release the Vcb resource.
863             UDFReleaseResource(&(Vcb->VCBResource));
864             AcquiredVcb = FALSE;
865             UDFStopEjectWaiter(Vcb);
866             CompleteIrp = TRUE;
867             RC = STATUS_SUCCESS;
868             break;*/
869         }
870         case IOCTL_CDROM_DISK_TYPE: {
871 
872             UDFPrint(("UDF Cdrom Disk Type\n"));
873             CompleteIrp = TRUE;
874             //  Verify the Vcb in this case to detect if the volume has changed.
875             Irp->IoStatus.Information = 0;
876             RC = UDFVerifyVcb(PtrIrpContext,Vcb);
877             if(!NT_SUCCESS(RC))
878                 try_return(RC);
879 
880             //  Check the size of the output buffer.
881             if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(CDROM_DISK_DATA_USER_OUT))
882                 try_return(RC = STATUS_BUFFER_TOO_SMALL);
883 
884             //  Copy the data from the Vcb.
885             ((PCDROM_DISK_DATA_USER_OUT)(Irp->AssociatedIrp.SystemBuffer))->DiskData = CDROM_DISK_DATA_TRACK;
886             for(TrackNumber=Vcb->FirstTrackNum; TrackNumber<Vcb->LastTrackNum; TrackNumber++) {
887                 if((Vcb->TrackMap[TrackNumber].TrackParam & Trk_QSubChan_Type_Mask) ==
888                     Trk_QSubChan_Type_Audio) {
889                     ((PCDROM_DISK_DATA_USER_OUT)(Irp->AssociatedIrp.SystemBuffer))->DiskData |= CDROM_DISK_AUDIO_TRACK;
890                     break;
891                 }
892             }
893 
894             Irp->IoStatus.Information = sizeof(CDROM_DISK_DATA_USER_OUT);
895             RC = STATUS_SUCCESS;
896             break;
897         }
898 
899         case IOCTL_CDRW_LOCK_DOOR:
900         case IOCTL_STORAGE_MEDIA_REMOVAL:
901         case IOCTL_DISK_MEDIA_REMOVAL:
902         case IOCTL_CDROM_MEDIA_REMOVAL: {
903             UDFPrint(("UDF Lock/Unlock\n"));
904             PPREVENT_MEDIA_REMOVAL_USER_IN buffer; // user supplied buffer
905             buffer = (PPREVENT_MEDIA_REMOVAL_USER_IN)(Irp->AssociatedIrp.SystemBuffer);
906             if(!buffer) {
907                 if(!(Vcb->VCBFlags & UDF_VCB_FLAGS_VOLUME_MOUNTED)) {
908                     UDFPrint(("!mounted\n"));
909                     goto ioctl_do_default;
910                 }
911                 UDFPrint(("abort\n"));
912                 CompleteIrp = TRUE;
913                 Irp->IoStatus.Information = 0;
914                 UnsafeIoctl = FALSE;
915                 RC = STATUS_INVALID_PARAMETER;
916                 break;
917             }
918             if(!buffer->PreventMediaRemoval &&
919                !Vcb->MediaLockCount) {
920 
921                 UDFPrint(("!locked + unlock req\n"));
922                 if(!(Vcb->VCBFlags & UDF_VCB_FLAGS_VOLUME_MOUNTED)) {
923                     UDFPrint(("!mounted\n"));
924                     goto ioctl_do_default;
925                 }
926 #if 0
927                 // allocate tmp buffer for FSD calls
928                 Buf = (PPREVENT_MEDIA_REMOVAL_USER_IN)MyAllocatePool__(NonPagedPool, sizeof(PREVENT_MEDIA_REMOVAL_USER_IN));
929                 if(!Buf)
930                     try_return(RC = STATUS_INSUFFICIENT_RESOURCES);
931 
932                 // Acquire Vcb resource (Shared -> Exclusive)
933                 UDFInterlockedIncrement((PLONG)&(Vcb->VCBOpenCount));
934                 UDFReleaseResource(&(Vcb->VCBResource));
935 
936 #ifdef UDF_DELAYED_CLOSE
937                 //  Acquire exclusive access to the Vcb.
938                 UDFCloseAllDelayed(Vcb);
939 #endif //UDF_DELAYED_CLOSE
940 
941                 UDFAcquireResourceExclusive(&(Vcb->VCBResource), TRUE);
942                 UDFInterlockedDecrement((PLONG)&(Vcb->VCBOpenCount));
943 
944                 UDFDoDismountSequence(Vcb, Buf, FALSE);
945                 MyFreePool__(Buf);
946                 Buf = NULL;
947                 Vcb->MediaLockCount = 0;
948                 // Release the Vcb resource.
949                 UDFReleaseResource(&(Vcb->VCBResource));
950                 AcquiredVcb = FALSE;
951                 // disable Eject Request Waiter if any
952                 UDFStopEjectWaiter(Vcb);
953 #else
954                 // just ignore
955 #endif
956 ignore_lock:
957                 UDFPrint(("ignore lock/unlock\n"));
958                 CompleteIrp = TRUE;
959                 Irp->IoStatus.Information = 0;
960                 RC = STATUS_SUCCESS;
961                 break;
962             }
963             if(buffer->PreventMediaRemoval) {
964                 UDFPrint(("lock req\n"));
965                 Vcb->MediaLockCount++;
966                 Vcb->VCBFlags |= UDF_VCB_FLAGS_MEDIA_LOCKED;
967                 UnsafeIoctl = FALSE;
968             } else {
969                 UDFPrint(("unlock req\n"));
970                 if(Vcb->MediaLockCount) {
971                     UDFPrint(("lock count %d\n", Vcb->MediaLockCount));
972                     UnsafeIoctl = FALSE;
973                     Vcb->MediaLockCount--;
974                 }
975             }
976             if(!(Vcb->VCBFlags & UDF_VCB_FLAGS_VOLUME_MOUNTED)) {
977                 UDFPrint(("!mounted\n"));
978                 goto ioctl_do_default;
979             }
980             goto ignore_lock;
981         }
982         default:
983 
984             UDFPrint(("default processing Irp %x, ctx %x, DevIoCtl %x\n", Irp, PtrIrpContext, IoControlCode));
985 ioctl_do_default:
986 
987             // make sure volume is Sync'ed BEFORE sending unsafe IOCTL
988             if(Vcb && UnsafeIoctl) {
989                 UDFFlushLogicalVolume(NULL, NULL, Vcb, 0);
990                 UDFPrint(("  sync'ed\n"));
991             }
992             // Invoke the lower level driver in the chain.
993             //PtrNextIoStackLocation = IoGetNextIrpStackLocation(Irp);
994             //*PtrNextIoStackLocation = *IrpSp;
995             IoSkipCurrentIrpStackLocation(Irp);
996 /*
997             // Set a completion routine.
998             IoSetCompletionRoutine(Irp, UDFDevIoctlCompletion, PtrIrpContext, TRUE, TRUE, TRUE);
999             // Send the request.
1000 */
1001             RC = IoCallDriver(Vcb->TargetDeviceObject, Irp);
1002             if(!CompleteIrp) {
1003                 // since now we do not use IoSetCompletionRoutine()
1004                 UDFReleaseIrpContext(PtrIrpContext);
1005             }
1006             break;
1007         }
1008 
1009         if(Vcb && UnsafeIoctl) {
1010             UDFPrint(("  set UnsafeIoctl\n"));
1011             Vcb->VCBFlags |= UDF_VCB_FLAGS_UNSAFE_IOCTL;
1012         }
1013 
1014 try_exit: NOTHING;
1015 
1016     } _SEH2_FINALLY {
1017 
1018         if(AcquiredVcb) {
1019             UDFReleaseResource(&(Vcb->VCBResource));
1020             AcquiredVcb = FALSE;
1021         }
1022 
1023         if(Buf) {
1024             MyFreePool__(Buf);
1025         }
1026 
1027         if (!_SEH2_AbnormalTermination() &&
1028             CompleteIrp) {
1029             UDFPrint(("  complete Irp %x, ctx %x, status %x, iolen %x\n",
1030                 Irp, PtrIrpContext, RC, Irp->IoStatus.Information));
1031             Irp->IoStatus.Status = RC;
1032             // complete the IRP
1033             IoCompleteRequest(Irp, IO_DISK_INCREMENT);
1034             // Release the IRP context
1035             UDFReleaseIrpContext(PtrIrpContext);
1036         }
1037     } _SEH2_END;
1038 
1039     return(RC);
1040 } // end UDFCommonDeviceControl()
1041 
1042 
1043 /*************************************************************************
1044 *
1045 * Function: UDFDevIoctlCompletion()
1046 *
1047 * Description:
1048 *   Completion routine.
1049 *
1050 * Expected Interrupt Level (for execution) :
1051 *
1052 *  IRQL_PASSIVE_LEVEL
1053 *
1054 * Return Value: STATUS_SUCCESS
1055 *
1056 *************************************************************************/
1057 NTSTATUS
1058 NTAPI
1059 UDFDevIoctlCompletion(
1060    PDEVICE_OBJECT          PtrDeviceObject,
1061    PIRP                    Irp,
1062    VOID                    *Context)
1063 {
1064 /*    PIO_STACK_LOCATION      IrpSp = NULL;
1065     ULONG                   IoControlCode = 0;*/
1066     PtrUDFIrpContext       PtrIrpContext = (PtrUDFIrpContext)Context;
1067 
1068     UDFPrint(("UDFDevIoctlCompletion Irp %x, ctx %x\n", Irp, Context));
1069     if (Irp->PendingReturned) {
1070         UDFPrint(("  IoMarkIrpPending\n"));
1071         IoMarkIrpPending(Irp);
1072     }
1073 
1074     UDFReleaseIrpContext(PtrIrpContext);
1075 /*    if(Irp->IoStatus.Status == STATUS_SUCCESS) {
1076         IrpSp = IoGetCurrentIrpStackLocation(Irp);
1077         IoControlCode = IrpSp->Parameters.DeviceIoControl.IoControlCode;
1078 
1079         switch(IoControlCode) {
1080         case IOCTL_CDRW_RESET_DRIVER: {
1081             Vcb->MediaLockCount = 0;
1082         }
1083         }
1084     }*/
1085 
1086     return STATUS_SUCCESS;
1087 } // end UDFDevIoctlCompletion()
1088 
1089 
1090 /*************************************************************************
1091 *
1092 * Function: UDFHandleQueryPath()
1093 *
1094 * Description:
1095 *   Handle the MUP request.
1096 *
1097 * Expected Interrupt Level (for execution) :
1098 *
1099 *  IRQL_PASSIVE_LEVEL
1100 *
1101 * Return Value: STATUS_SUCCESS
1102 *
1103 *************************************************************************/
1104 /*NTSTATUS UDFHandleQueryPath(
1105 VOID           *BufferPointer)
1106 {
1107     NTSTATUS                    RC = STATUS_SUCCESS;
1108     PQUERY_PATH_REQUEST RequestBuffer = (PQUERY_PATH_REQUEST)BufferPointer;
1109     PQUERY_PATH_RESPONSE    ReplyBuffer = (PQUERY_PATH_RESPONSE)BufferPointer;
1110     ULONG                       LengthOfNameToBeMatched = RequestBuffer->PathNameLength;
1111     ULONG                       LengthOfMatchedName = 0;
1112     WCHAR                *NameToBeMatched = RequestBuffer->FilePathName;
1113 
1114     UDFPrint(("UDFHandleQueryPath\n"));
1115     // So here we are. Simply check the name supplied.
1116     // We can use whatever algorithm we like to determine whether the
1117     // sent in name is acceptable.
1118     // The first character in the name is always a "\"
1119     // If we like the name sent in (probably, we will like a subset
1120     // of the name), set the matching length value in LengthOfMatchedName.
1121 
1122     // if (FoundMatch) {
1123     //      ReplyBuffer->LengthAccepted = LengthOfMatchedName;
1124     // } else {
1125     //      RC = STATUS_OBJECT_NAME_NOT_FOUND;
1126     // }
1127 
1128     return(RC);
1129 }*/
1130 
1131 NTSTATUS
1132 UDFGetFileAllocModeFromICB(
1133     PtrUDFIrpContext IrpContext,
1134     PIRP             Irp
1135     )
1136 {
1137     PEXTENDED_IO_STACK_LOCATION IrpSp =
1138         (PEXTENDED_IO_STACK_LOCATION)IoGetCurrentIrpStackLocation( Irp );
1139 
1140 //    PVCB Vcb;
1141     PtrUDFFCB Fcb;
1142     PtrUDFCCB Ccb;
1143     PUDF_GET_FILE_ALLOCATION_MODE_OUT OutputBuffer;
1144 
1145     UDFPrint(("UDFGetFileAllocModeFromICB\n"));
1146 
1147     // Decode the file object, the only type of opens we accept are
1148     // user volume opens.
1149     Ccb = (PtrUDFCCB)(IrpSp->FileObject->FsContext2);
1150     Fcb = Ccb->Fcb;
1151 //    Vcb = Fcb->Vcb;
1152 
1153     Irp->IoStatus.Information = 0;
1154     if(IrpSp->Parameters.FileSystemControl.OutputBufferLength < sizeof(UDF_GET_FILE_ALLOCATION_MODE_OUT))
1155         return STATUS_BUFFER_TOO_SMALL;
1156 
1157     OutputBuffer = (PUDF_GET_FILE_ALLOCATION_MODE_OUT)(Irp->AssociatedIrp.SystemBuffer);
1158     if(!OutputBuffer)
1159         return STATUS_INVALID_USER_BUFFER;
1160 
1161     OutputBuffer->AllocMode = UDFGetFileICBAllocMode__(Fcb->FileInfo);
1162     Irp->IoStatus.Information = sizeof(UDF_GET_FILE_ALLOCATION_MODE_OUT);
1163 
1164     return STATUS_SUCCESS;
1165 } // end UDFGetFileAllocModeFromICB()
1166 
1167 #ifndef UDF_READ_ONLY_BUILD
1168 NTSTATUS
1169 UDFSetFileAllocModeFromICB(
1170     PtrUDFIrpContext IrpContext,
1171     PIRP             Irp
1172     )
1173 {
1174     PEXTENDED_IO_STACK_LOCATION IrpSp =
1175         (PEXTENDED_IO_STACK_LOCATION)IoGetCurrentIrpStackLocation( Irp );
1176 
1177     PVCB Vcb;
1178     PtrUDFFCB Fcb;
1179     PtrUDFCCB Ccb;
1180     PUDF_SET_FILE_ALLOCATION_MODE_IN InputBuffer;
1181     NTSTATUS RC;
1182     UCHAR AllocMode;
1183 
1184     UDFPrint(("UDFSetFileAllocModeFromICB\n"));
1185 
1186     Ccb = (PtrUDFCCB)(IrpSp->FileObject->FsContext2);
1187     Fcb = Ccb->Fcb;
1188     Vcb = Fcb->Vcb;
1189 
1190     Irp->IoStatus.Information = 0;
1191     if(IrpSp->Parameters.FileSystemControl.InputBufferLength < sizeof(UDF_SET_FILE_ALLOCATION_MODE_IN))
1192         return STATUS_BUFFER_TOO_SMALL;
1193 
1194     InputBuffer = (PUDF_SET_FILE_ALLOCATION_MODE_IN)(Irp->AssociatedIrp.SystemBuffer);
1195     if(!InputBuffer)
1196         return STATUS_INVALID_USER_BUFFER;
1197 
1198     UDFFlushAFile(Fcb, Ccb, &(Irp->IoStatus), 0);
1199     RC = Irp->IoStatus.Status;
1200     if(!NT_SUCCESS(RC))
1201         return RC;
1202 
1203     if(InputBuffer->AllocMode != ICB_FLAG_AD_IN_ICB) {
1204         AllocMode = UDFGetFileICBAllocMode__(Fcb->FileInfo);
1205         if(AllocMode == ICB_FLAG_AD_IN_ICB) {
1206             RC = UDFConvertFEToNonInICB(Vcb, Fcb->FileInfo, InputBuffer->AllocMode);
1207         } else
1208         if(AllocMode != InputBuffer->AllocMode) {
1209             RC = STATUS_INVALID_PARAMETER;
1210         } else {
1211             RC = STATUS_SUCCESS;
1212         }
1213     } else {
1214         RC = STATUS_INVALID_PARAMETER;
1215     }
1216 
1217     return STATUS_SUCCESS;
1218 } // end UDFSetFileAllocModeFromICB()
1219 #endif //UDF_READ_ONLY_BUILD
1220