Synchronize with trunk revision 59636 (just before Alex's CreateProcess revamp).
[reactos.git] / drivers / filesystems / cdfs / fsctl.c
1 /*
2 * ReactOS kernel
3 * Copyright (C) 2002, 2003 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19 /*
20 * COPYRIGHT: See COPYING in the top level directory
21 * PROJECT: ReactOS kernel
22 * FILE: drivers/fs/cdfs/fsctl.c
23 * PURPOSE: CDROM (ISO 9660) filesystem driver
24 * PROGRAMMER: Art Yerkes
25 * Eric Kohl
26 */
27
28 /* INCLUDES *****************************************************************/
29
30 #include "cdfs.h"
31
32 #define NDEBUG
33 #include <debug.h>
34
35 /* FUNCTIONS ****************************************************************/
36
37 static __inline
38 int msf_to_lba (UCHAR m, UCHAR s, UCHAR f)
39 {
40 return (((m * 60) + s) * 75 + f) - 150;
41 }
42
43
44 static VOID
45 CdfsGetPVDData(PUCHAR Buffer,
46 PCDINFO CdInfo)
47 {
48 PPVD Pvd;
49 USHORT i;
50 PUCHAR pc;
51 PWCHAR pw;
52
53 union
54 {
55 ULONG Value;
56 UCHAR Part[4];
57 } Serial;
58
59 Pvd = (PPVD)Buffer;
60
61 /* Calculate the volume serial number */
62 Serial.Value = 0;
63 for (i = 0; i < 2048; i += 4)
64 {
65 /* DON'T optimize this to ULONG!!! (breaks overflow) */
66 Serial.Part[3] += Buffer[i+0];
67 Serial.Part[2] += Buffer[i+1];
68 Serial.Part[1] += Buffer[i+2];
69 Serial.Part[0] += Buffer[i+3];
70 }
71 CdInfo->SerialNumber = Serial.Value;
72
73 /* Extract the volume label */
74 pc = Pvd->VolumeId;
75 pw = CdInfo->VolumeLabel;
76 for (i = 0; i < (MAXIMUM_VOLUME_LABEL_LENGTH / sizeof(WCHAR)) - 1; i++)
77 {
78 *pw++ = (WCHAR)*pc++;
79 }
80 *pw = 0;
81
82 /* Trim trailing spaces */
83 while (pw > CdInfo->VolumeLabel)
84 {
85 if (*--pw != ' ') break;
86
87 /* Remove the space */
88 *pw = '\0';
89
90 /* Decrease size */
91 i--;
92 }
93
94 CdInfo->VolumeLabelLength = i * sizeof(WCHAR);
95
96 CdInfo->VolumeSpaceSize = Pvd->VolumeSpaceSizeL;
97 CdInfo->RootStart = Pvd->RootDirRecord.ExtentLocationL;
98 CdInfo->RootSize = Pvd->RootDirRecord.DataLengthL;
99
100 DPRINT("VolumeSerial: %08lx\n", CdInfo->SerialNumber);
101 DPRINT("VolumeLabel: '%S'\n", CdInfo->VolumeLabel);
102 DPRINT("VolumeLabelLength: %lu\n", CdInfo->VolumeLabelLength);
103 DPRINT("VolumeSize: %lu\n", Pvd->VolumeSpaceSizeL);
104 DPRINT("RootStart: %lu\n", Pvd->RootDirRecord.ExtentLocationL);
105 DPRINT("RootSize: %lu\n", Pvd->RootDirRecord.DataLengthL);
106 DPRINT("PathTableSize: %lu\n", Pvd->PathTableSizeL);
107 DPRINT("PathTablePos: %lu\n", Pvd->LPathTablePos);
108 DPRINT("OptPathTablePos: %lu\n", Pvd->LOptPathTablePos);
109
110 #if 0
111 DbgPrint("******** PVD **********\n");
112 DbgPrint("VdType: %d\n", Pvd->VdType);
113 DbgPrint("StandardId: '%.*s'\n", 5, Pvd->StandardId);
114 DbgPrint("VdVersion: %d\n", Pvd->VdVersion);
115 DbgPrint("SystemId: '%.*s'\n", 32, Pvd->SystemId);
116 DbgPrint("VolumeId: '%.*s'\n", 32, Pvd->VolumeId);
117 DbgPrint("VolumeSpaceSizeL: %d (%x)\n", Pvd->VolumeSpaceSizeL, Pvd->VolumeSpaceSizeL);
118 DbgPrint("VolumeSpaceSizeM: %d (%x)\n", Pvd->VolumeSpaceSizeM, Pvd->VolumeSpaceSizeM);
119 DbgPrint("VolumeSetSize: %d (%x)\n", Pvd->VolumeSequenceNumber, Pvd->VolumeSequenceNumber);
120 DbgPrint("VolumeSequenceNumber: %d (%x)\n", Pvd->VolumeSequenceNumber, Pvd->VolumeSequenceNumber);
121 DbgPrint("LogicalBlockSize: %d (%x)\n", Pvd->LogicalBlockSize, Pvd->LogicalBlockSize);
122 DbgPrint("PathTableSizeL: %d (%x)\n", Pvd->PathTableSizeL, Pvd->PathTableSizeL);
123 DbgPrint("PathTableSizeM: %d (%x)\n", Pvd->PathTableSizeM, Pvd->PathTableSizeM);
124 DbgPrint("LPathTablePos: %d (%x)\n", Pvd->LPathTablePos, Pvd->LPathTablePos);
125 DbgPrint("LOptPathTablePos: %d (%x)\n", Pvd->LOptPathTablePos, Pvd->LOptPathTablePos);
126 DbgPrint("MPathTablePos: %d (%x)\n", Pvd->MPathTablePos, Pvd->MPathTablePos);
127 DbgPrint("MOptPathTablePos: %d (%x)\n", Pvd->MOptPathTablePos, Pvd->MOptPathTablePos);
128 DbgPrint("VolumeSetIdentifier: '%.*s'\n", 128, Pvd->VolumeSetIdentifier);
129 DbgPrint("PublisherIdentifier: '%.*s'\n", 128, Pvd->PublisherIdentifier);
130 DbgPrint("******** Root *********\n");
131 DbgPrint("RecordLength: %d\n", Pvd->RootDirRecord.RecordLength);
132 DbgPrint("ExtAttrRecordLength: %d\n", Pvd->RootDirRecord.ExtAttrRecordLength);
133 DbgPrint("ExtentLocationL: %d\n", Pvd->RootDirRecord.ExtentLocationL);
134 DbgPrint("DataLengthL: %d\n", Pvd->RootDirRecord.DataLengthL);
135 DbgPrint("Year: %d\n", Pvd->RootDirRecord.Year);
136 DbgPrint("Month: %d\n", Pvd->RootDirRecord.Month);
137 DbgPrint("Day: %d\n", Pvd->RootDirRecord.Day);
138 DbgPrint("Hour: %d\n", Pvd->RootDirRecord.Hour);
139 DbgPrint("Minute: %d\n", Pvd->RootDirRecord.Minute);
140 DbgPrint("Second: %d\n", Pvd->RootDirRecord.Second);
141 DbgPrint("TimeZone: %d\n", Pvd->RootDirRecord.TimeZone);
142 DbgPrint("FileFlags: %d\n", Pvd->RootDirRecord.FileFlags);
143 DbgPrint("FileUnitSize: %d\n", Pvd->RootDirRecord.FileUnitSize);
144 DbgPrint("InterleaveGapSize: %d\n", Pvd->RootDirRecord.InterleaveGapSize);
145 DbgPrint("VolumeSequenceNumber: %d\n", Pvd->RootDirRecord.VolumeSequenceNumber);
146 DbgPrint("FileIdLength: %d\n", Pvd->RootDirRecord.FileIdLength);
147 DbgPrint("FileId: '%.*s'\n", Pvd->RootDirRecord.FileId);
148 DbgPrint("***********************\n");
149 #endif
150 }
151
152
153 static VOID
154 CdfsGetSVDData(PUCHAR Buffer,
155 PCDINFO CdInfo)
156 {
157 PSVD Svd;
158 ULONG JolietLevel = 0;
159
160 Svd = (PSVD)Buffer;
161
162 DPRINT("EscapeSequences: '%.32s'\n", Svd->EscapeSequences);
163
164 if (strncmp((PCHAR)Svd->EscapeSequences, "%/@", 3) == 0)
165 {
166 DPRINT("Joliet extension found (UCS-2 Level 1)\n");
167 JolietLevel = 1;
168 }
169 else if (strncmp((PCHAR)Svd->EscapeSequences, "%/C", 3) == 0)
170 {
171 DPRINT("Joliet extension found (UCS-2 Level 2)\n");
172 JolietLevel = 2;
173 }
174 else if (strncmp((PCHAR)Svd->EscapeSequences, "%/E", 3) == 0)
175 {
176 DPRINT("Joliet extension found (UCS-2 Level 3)\n");
177 JolietLevel = 3;
178 }
179
180 CdInfo->JolietLevel = JolietLevel;
181
182 if (JolietLevel != 0)
183 {
184 CdInfo->RootStart = Svd->RootDirRecord.ExtentLocationL;
185 CdInfo->RootSize = Svd->RootDirRecord.DataLengthL;
186
187 DPRINT("RootStart: %lu\n", Svd->RootDirRecord.ExtentLocationL);
188 DPRINT("RootSize: %lu\n", Svd->RootDirRecord.DataLengthL);
189 }
190 }
191
192
193 static NTSTATUS
194 CdfsGetVolumeData(PDEVICE_OBJECT DeviceObject,
195 PCDINFO CdInfo)
196 {
197 PUCHAR Buffer;
198 NTSTATUS Status;
199 ULONG Sector;
200 PVD_HEADER VdHeader;
201 ULONG Size;
202 ULONG Offset;
203 ULONG i;
204 struct
205 {
206 UCHAR Length[2];
207 UCHAR FirstSession;
208 UCHAR LastSession;
209 TRACK_DATA TrackData;
210 }
211 Toc;
212
213 DPRINT("CdfsGetVolumeData\n");
214
215 Buffer = ExAllocatePool(NonPagedPool,
216 CDFS_BASIC_SECTOR);
217 if (Buffer == NULL)
218 return STATUS_INSUFFICIENT_RESOURCES;
219
220 Size = sizeof(Toc);
221 Status = CdfsDeviceIoControl(DeviceObject,
222 IOCTL_CDROM_GET_LAST_SESSION,
223 NULL,
224 0,
225 &Toc,
226 &Size,
227 TRUE);
228 if (!NT_SUCCESS(Status))
229 {
230 ExFreePool(Buffer);
231 return Status;
232 }
233
234 DPRINT("FirstSession %u, LastSession %u, FirstTrack %u\n",
235 Toc.FirstSession, Toc.LastSession, Toc.TrackData.TrackNumber);
236
237 Offset = 0;
238 for (i = 0; i < 4; i++)
239 {
240 Offset = (Offset << 8) + Toc.TrackData.Address[i];
241 }
242 CdInfo->VolumeOffset = Offset;
243
244 DPRINT("Offset of first track in last session %u\n", Offset);
245
246 CdInfo->JolietLevel = 0;
247 VdHeader = (PVD_HEADER)Buffer;
248 Buffer[0] = 0;
249
250 for (Sector = CDFS_PRIMARY_DESCRIPTOR_LOCATION; Sector < 100 && Buffer[0] != 255; Sector++)
251 {
252 /* Read the Primary Volume Descriptor (PVD) */
253 Status = CdfsReadSectors (DeviceObject,
254 Sector + Offset,
255 1,
256 Buffer,
257 TRUE);
258 if (!NT_SUCCESS(Status))
259 {
260 ExFreePool(Buffer);
261 return Status;
262 }
263
264 if (Sector == CDFS_PRIMARY_DESCRIPTOR_LOCATION)
265 {
266 DPRINT("CD-identifier: [%.5s]\n", Buffer + 1);
267
268 if (Buffer[0] != 1 || Buffer[1] != 'C' || Buffer[2] != 'D' ||
269 Buffer[3] != '0' || Buffer[4] != '0' || Buffer[5] != '1')
270 {
271 ExFreePool(Buffer);
272 return STATUS_UNRECOGNIZED_VOLUME;
273 }
274 }
275
276 switch (VdHeader->VdType)
277 {
278 case 0:
279 DPRINT("BootVolumeDescriptor found!\n");
280 break;
281
282 case 1:
283 DPRINT("PrimaryVolumeDescriptor found!\n");
284 CdfsGetPVDData(Buffer, CdInfo);
285 break;
286
287 case 2:
288 DPRINT("SupplementaryVolumeDescriptor found!\n");
289 CdfsGetSVDData(Buffer, CdInfo);
290 break;
291
292 case 3:
293 DPRINT("VolumePartitionDescriptor found!\n");
294 break;
295
296 case 255:
297 DPRINT("VolumeDescriptorSetTerminator found!\n");
298 break;
299
300 default:
301 DPRINT1("Unknown volume descriptor type %u found!\n", VdHeader->VdType);
302 break;
303 }
304 }
305
306 ExFreePool(Buffer);
307
308 return(STATUS_SUCCESS);
309 }
310
311
312 static NTSTATUS
313 CdfsMountVolume(PDEVICE_OBJECT DeviceObject,
314 PIRP Irp)
315 {
316 PDEVICE_EXTENSION DeviceExt = NULL;
317 PDEVICE_OBJECT NewDeviceObject = NULL;
318 PDEVICE_OBJECT DeviceToMount;
319 PIO_STACK_LOCATION Stack;
320 PFCB Fcb = NULL;
321 PCCB Ccb = NULL;
322 PVPB Vpb;
323 NTSTATUS Status;
324 CDINFO CdInfo;
325
326 DPRINT("CdfsMountVolume() called\n");
327
328 if (DeviceObject != CdfsGlobalData->DeviceObject)
329 {
330 Status = STATUS_INVALID_DEVICE_REQUEST;
331 goto ByeBye;
332 }
333
334 Stack = IoGetCurrentIrpStackLocation(Irp);
335 DeviceToMount = Stack->Parameters.MountVolume.DeviceObject;
336 Vpb = Stack->Parameters.MountVolume.Vpb;
337
338 Status = CdfsGetVolumeData(DeviceToMount, &CdInfo);
339 if (!NT_SUCCESS(Status))
340 {
341 goto ByeBye;
342 }
343
344 Status = IoCreateDevice(CdfsGlobalData->DriverObject,
345 sizeof(DEVICE_EXTENSION),
346 NULL,
347 FILE_DEVICE_CD_ROM_FILE_SYSTEM,
348 DeviceToMount->Characteristics,
349 FALSE,
350 &NewDeviceObject);
351 if (!NT_SUCCESS(Status))
352 goto ByeBye;
353
354 NewDeviceObject->Flags = NewDeviceObject->Flags | DO_DIRECT_IO;
355 NewDeviceObject->Flags &= ~DO_VERIFY_VOLUME;
356 DeviceExt = (PVOID)NewDeviceObject->DeviceExtension;
357 RtlZeroMemory(DeviceExt,
358 sizeof(DEVICE_EXTENSION));
359
360 Vpb->SerialNumber = CdInfo.SerialNumber;
361 Vpb->VolumeLabelLength = CdInfo.VolumeLabelLength;
362 RtlCopyMemory(Vpb->VolumeLabel, CdInfo.VolumeLabel, CdInfo.VolumeLabelLength);
363 RtlCopyMemory(&DeviceExt->CdInfo, &CdInfo, sizeof(CDINFO));
364
365 NewDeviceObject->Vpb = DeviceToMount->Vpb;
366
367 DeviceExt->VolumeDevice = NewDeviceObject;
368 DeviceExt->StorageDevice = DeviceToMount;
369 DeviceExt->StorageDevice->Vpb->DeviceObject = NewDeviceObject;
370 DeviceExt->StorageDevice->Vpb->RealDevice = DeviceExt->StorageDevice;
371 DeviceExt->StorageDevice->Vpb->Flags |= VPB_MOUNTED;
372 NewDeviceObject->StackSize = DeviceExt->StorageDevice->StackSize + 1;
373 NewDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
374
375 /* Close (and cleanup) might be called from IoCreateStreamFileObject
376 * but we use this resource from CdfsCleanup, therefore it should be
377 * initialized no later than this. */
378 ExInitializeResourceLite(&DeviceExt->DirResource);
379
380 DeviceExt->StreamFileObject = IoCreateStreamFileObject(NULL,
381 DeviceExt->StorageDevice);
382
383 Fcb = CdfsCreateFCB(NULL);
384 if (Fcb == NULL)
385 {
386 Status = STATUS_INSUFFICIENT_RESOURCES;
387 goto ByeBye;
388 }
389
390 Ccb = ExAllocatePoolWithTag(NonPagedPool,
391 sizeof(CCB),
392 TAG_CCB);
393 if (Ccb == NULL)
394 {
395 Status = STATUS_INSUFFICIENT_RESOURCES;
396 goto ByeBye;
397 }
398 RtlZeroMemory(Ccb,
399 sizeof(CCB));
400
401 DeviceExt->StreamFileObject->ReadAccess = TRUE;
402 DeviceExt->StreamFileObject->WriteAccess = FALSE;
403 DeviceExt->StreamFileObject->DeleteAccess = FALSE;
404 DeviceExt->StreamFileObject->FsContext = Fcb;
405 DeviceExt->StreamFileObject->FsContext2 = Ccb;
406 DeviceExt->StreamFileObject->SectionObjectPointer = &Fcb->SectionObjectPointers;
407 DeviceExt->StreamFileObject->PrivateCacheMap = NULL;
408 DeviceExt->StreamFileObject->Vpb = DeviceExt->Vpb;
409 Ccb->PtrFileObject = DeviceExt->StreamFileObject;
410 Fcb->FileObject = DeviceExt->StreamFileObject;
411 Fcb->DevExt = (PDEVICE_EXTENSION)DeviceExt->StorageDevice;
412
413 Fcb->Flags = FCB_IS_VOLUME_STREAM;
414
415 Fcb->RFCB.FileSize.QuadPart = (DeviceExt->CdInfo.VolumeSpaceSize + DeviceExt->CdInfo.VolumeOffset) * BLOCKSIZE;
416 Fcb->RFCB.ValidDataLength = Fcb->RFCB.AllocationSize = Fcb->RFCB.FileSize;
417
418 Fcb->Entry.ExtentLocationL = 0;
419 Fcb->Entry.DataLengthL = (DeviceExt->CdInfo.VolumeSpaceSize + DeviceExt->CdInfo.VolumeOffset) * BLOCKSIZE;
420
421 CcInitializeCacheMap(DeviceExt->StreamFileObject,
422 (PCC_FILE_SIZES)(&Fcb->RFCB.AllocationSize),
423 TRUE,
424 &(CdfsGlobalData->CacheMgrCallbacks),
425 Fcb);
426
427 ExInitializeResourceLite(&DeviceExt->VcbResource);
428
429 KeInitializeSpinLock(&DeviceExt->FcbListLock);
430 InitializeListHead(&DeviceExt->FcbListHead);
431
432 Status = STATUS_SUCCESS;
433
434 ByeBye:
435 if (!NT_SUCCESS(Status))
436 {
437 /* Cleanup */
438 if (DeviceExt && DeviceExt->StreamFileObject)
439 ObDereferenceObject(DeviceExt->StreamFileObject);
440 if (Fcb)
441 ExFreePool(Fcb);
442 if (Ccb)
443 ExFreePool(Ccb);
444 if (NewDeviceObject)
445 IoDeleteDevice(NewDeviceObject);
446 }
447
448 DPRINT("CdfsMountVolume() done (Status: %lx)\n", Status);
449
450 return(Status);
451 }
452
453
454 static NTSTATUS
455 CdfsVerifyVolume(PDEVICE_OBJECT DeviceObject,
456 PIRP Irp)
457 {
458 PDEVICE_EXTENSION DeviceExt;
459 PDEVICE_OBJECT DeviceToVerify;
460 PIO_STACK_LOCATION Stack;
461 NTSTATUS Status;
462 CDINFO CdInfo;
463
464 PLIST_ENTRY Entry;
465 PFCB Fcb;
466
467 DPRINT1 ("CdfsVerifyVolume() called\n");
468
469 #if 0
470 if (DeviceObject != CdfsGlobalData->DeviceObject)
471 {
472 DPRINT1("DeviceObject != CdfsGlobalData->DeviceObject\n");
473 return(STATUS_INVALID_DEVICE_REQUEST);
474 }
475 #endif
476
477 DeviceExt = DeviceObject->DeviceExtension;
478
479 Stack = IoGetCurrentIrpStackLocation (Irp);
480 DeviceToVerify = Stack->Parameters.VerifyVolume.DeviceObject;
481
482 FsRtlEnterFileSystem();
483 ExAcquireResourceExclusiveLite (&DeviceExt->VcbResource,
484 TRUE);
485
486 if (!(DeviceToVerify->Flags & DO_VERIFY_VOLUME))
487 {
488 DPRINT1 ("Volume has been verified!\n");
489 ExReleaseResourceLite (&DeviceExt->VcbResource);
490 FsRtlExitFileSystem();
491 return STATUS_SUCCESS;
492 }
493
494 DPRINT1 ("Device object %p Device to verify %p\n", DeviceObject, DeviceToVerify);
495
496 Status = CdfsGetVolumeData (DeviceToVerify,
497 &CdInfo);
498 if (NT_SUCCESS(Status) &&
499 CdInfo.SerialNumber == DeviceToVerify->Vpb->SerialNumber &&
500 CdInfo.VolumeLabelLength == DeviceToVerify->Vpb->VolumeLabelLength &&
501 !wcsncmp (CdInfo.VolumeLabel, DeviceToVerify->Vpb->VolumeLabel, CdInfo.VolumeLabelLength))
502 {
503 DPRINT1 ("Same volume!\n");
504
505 /* FIXME: Flush and purge metadata */
506
507 Status = STATUS_SUCCESS;
508 }
509 else
510 {
511 DPRINT1 ("Different volume!\n");
512
513 /* FIXME: force volume dismount */
514 Entry = DeviceExt->FcbListHead.Flink;
515 while (Entry != &DeviceExt->FcbListHead)
516 {
517 Fcb = (PFCB)CONTAINING_RECORD(Entry, FCB, FcbListEntry);
518 DPRINT1("OpenFile %S RefCount %ld\n", Fcb->PathName, Fcb->RefCount);
519
520 Entry = Entry->Flink;
521 }
522
523 Status = STATUS_WRONG_VOLUME;
524 }
525
526 DeviceToVerify->Flags &= ~DO_VERIFY_VOLUME;
527
528 ExReleaseResourceLite (&DeviceExt->VcbResource);
529 FsRtlExitFileSystem();
530
531 return Status;
532 }
533
534
535 NTSTATUS NTAPI
536 CdfsSetCompression(
537 IN PDEVICE_OBJECT DeviceObject,
538 IN PIRP Irp)
539 {
540 PIO_STACK_LOCATION Stack;
541 USHORT CompressionState;
542
543 UNREFERENCED_PARAMETER(DeviceObject);
544
545 Stack = IoGetCurrentIrpStackLocation(Irp);
546
547 if (Stack->Parameters.DeviceIoControl.InputBufferLength != sizeof(CompressionState))
548 return STATUS_INVALID_DEVICE_REQUEST;
549
550 CompressionState = *(USHORT *)Irp->AssociatedIrp.SystemBuffer;
551 if (CompressionState != COMPRESSION_FORMAT_NONE)
552 return STATUS_INVALID_PARAMETER;
553
554 return STATUS_SUCCESS;
555 }
556
557
558 NTSTATUS NTAPI
559 CdfsFileSystemControl(PDEVICE_OBJECT DeviceObject,
560 PIRP Irp)
561 {
562 PIO_STACK_LOCATION Stack;
563 NTSTATUS Status;
564
565 DPRINT("CdfsFileSystemControl() called\n");
566
567 Stack = IoGetCurrentIrpStackLocation(Irp);
568
569 switch (Stack->MinorFunction)
570 {
571 case IRP_MN_KERNEL_CALL:
572 case IRP_MN_USER_FS_REQUEST:
573 switch (Stack->Parameters.DeviceIoControl.IoControlCode)
574 {
575 case FSCTL_SET_COMPRESSION:
576 DPRINT("CDFS: IRP_MN_USER_FS_REQUEST / FSCTL_SET_COMPRESSION\n");
577 Status = CdfsSetCompression(DeviceObject, Irp);
578 break;
579
580 default:
581 DPRINT1("CDFS: IRP_MN_USER_FS_REQUEST / Unknown IoControlCode 0x%x\n",
582 Stack->Parameters.DeviceIoControl.IoControlCode);
583 Status = STATUS_INVALID_DEVICE_REQUEST;
584 }
585 break;
586
587 case IRP_MN_MOUNT_VOLUME:
588 DPRINT("CDFS: IRP_MN_MOUNT_VOLUME\n");
589 Status = CdfsMountVolume(DeviceObject, Irp);
590 break;
591
592 case IRP_MN_VERIFY_VOLUME:
593 DPRINT1("CDFS: IRP_MN_VERIFY_VOLUME\n");
594 Status = CdfsVerifyVolume(DeviceObject, Irp);
595 break;
596
597 default:
598 DPRINT1("CDFS FSC: MinorFunction %u\n", Stack->MinorFunction);
599 Status = STATUS_INVALID_DEVICE_REQUEST;
600 break;
601 }
602
603 Irp->IoStatus.Status = Status;
604 Irp->IoStatus.Information = 0;
605
606 IoCompleteRequest(Irp, IO_NO_INCREMENT);
607
608 return(Status);
609 }
610
611 /* EOF */