[UDFS]
[reactos.git] / reactos / drivers / filesystems / udfs / devcntrl.cpp
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