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