2003-06-07 Casper S. Hornstrup <chorns@users.sourceforge.net>
[reactos.git] / reactos / ntoskrnl / io / rawfs.c
1 /* $Id: rawfs.c,v 1.3 2003/06/07 11:34:36 chorns Exp $
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/io/rawfs.c
6 * PURPOSE: Raw filesystem driver
7 * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
8 * UPDATE HISTORY:
9 * Created 13/04/2003
10 */
11
12 /* INCLUDES *****************************************************************/
13
14 #include <ddk/ntddk.h>
15 #include <ddk/ntifs.h>
16 #include <reactos/bugcodes.h>
17
18 #define NDEBUG
19 #include <internal/debug.h>
20
21 /* TYPES *******************************************************************/
22
23 typedef struct _RAWFS_GLOBAL_DATA
24 {
25 PDRIVER_OBJECT DriverObject;
26 PDEVICE_OBJECT DeviceObject;
27 ULONG Flags;
28 ERESOURCE VolumeListLock;
29 LIST_ENTRY VolumeListHead;
30 NPAGED_LOOKASIDE_LIST FcbLookasideList;
31 NPAGED_LOOKASIDE_LIST CcbLookasideList;
32 } RAWFS_GLOBAL_DATA, *PRAWFS_GLOBAL_DATA, VCB, *PVCB;
33
34 typedef struct _RAWFS_DEVICE_EXTENSION
35 {
36 KSPIN_LOCK FcbListLock;
37 LIST_ENTRY FcbListHead;
38 PDEVICE_OBJECT StorageDevice;
39 ULONG Flags;
40 struct _RAWFS_FCB *VolumeFcb;
41 LIST_ENTRY VolumeListEntry;
42 } RAWFS_DEVICE_EXTENSION, *PRAWFS_DEVICE_EXTENSION;
43
44 typedef struct _RAWFS_IRP_CONTEXT
45 {
46 PIRP Irp;
47 PDEVICE_OBJECT DeviceObject;
48 PRAWFS_DEVICE_EXTENSION DeviceExt;
49 ULONG Flags;
50 WORK_QUEUE_ITEM WorkQueueItem;
51 PIO_STACK_LOCATION Stack;
52 UCHAR MajorFunction;
53 UCHAR MinorFunction;
54 PFILE_OBJECT FileObject;
55 } RAWFS_IRP_CONTEXT, *PRAWFS_IRP_CONTEXT;
56
57 #define IRPCONTEXT_CANWAIT 0x0001
58
59 #define FCB_CACHE_INITIALIZED 0x0001
60 #define FCB_DELETE_PENDING 0x0002
61 #define FCB_IS_FAT 0x0004
62 #define FCB_IS_PAGE_FILE 0x0008
63 #define FCB_IS_VOLUME 0x0010
64
65 typedef struct _RAWFS_FCB
66 {
67 /* Start FCB header required by ReactOS/Windows NT */
68 FSRTL_COMMON_FCB_HEADER RFCB;
69 SECTION_OBJECT_POINTERS SectionObjectPointers;
70 ERESOURCE MainResource;
71 ERESOURCE PagingIoResource;
72 /* End FCB header required by ReactOS/Windows NT */
73
74 /* Reference count */
75 LONG RefCount;
76
77 /* List of FCB's for this volume */
78 LIST_ENTRY FcbListEntry;
79
80 /* Pointer to the parent fcb */
81 struct _RAWFS_FCB* ParentFcb;
82
83 /* Flags for the FCB */
84 ULONG Flags;
85
86 /* Pointer to the file object which has initialized the fcb */
87 PFILE_OBJECT FileObject;
88 } RAWFS_FCB, *PRAWFS_FCB;
89
90 typedef struct _RAWFS_CCB
91 {
92 LARGE_INTEGER CurrentByteOffset;
93 } RAWFS_CCB, *PRAWFS_CCB;
94
95 /* GLOBALS ******************************************************************/
96
97 #define TAG_IRP TAG('R', 'I', 'R', 'P')
98
99 static PDRIVER_OBJECT RawFsDriverObject;
100 static PDEVICE_OBJECT DiskDeviceObject;
101 static PDEVICE_OBJECT CdromDeviceObject;
102 static PDEVICE_OBJECT TapeDeviceObject;
103 static NPAGED_LOOKASIDE_LIST IrpContextLookasideList;
104 static LONG RawFsQueueCount = 0;
105
106 /* FUNCTIONS *****************************************************************/
107
108 BOOLEAN
109 RawFsIsRawFileSystemDeviceObject(IN PDEVICE_OBJECT DeviceObject)
110 {
111 DPRINT("RawFsIsRawFileSystemDeviceObject(DeviceObject %x)\n", DeviceObject);
112
113 if (DeviceObject == DiskDeviceObject)
114 return TRUE;
115 if (DeviceObject == CdromDeviceObject)
116 return TRUE;
117 if (DeviceObject == TapeDeviceObject)
118 return TRUE;
119 return FALSE;
120 }
121
122 static NTSTATUS
123 RawFsDispatchRequest(IN PRAWFS_IRP_CONTEXT IrpContext);
124
125 /*static */NTSTATUS
126 RawFsReadDisk(IN PDEVICE_OBJECT pDeviceObject,
127 IN PLARGE_INTEGER ReadOffset,
128 IN ULONG ReadLength,
129 IN OUT PUCHAR Buffer)
130 {
131 IO_STATUS_BLOCK IoStatus;
132 NTSTATUS Status;
133 KEVENT Event;
134 PIRP Irp;
135
136 KeInitializeEvent(&Event, NotificationEvent, FALSE);
137
138 DPRINT("RawFsReadDisk(pDeviceObject %x, Offset %I64x, Length %d, Buffer %x)\n",
139 pDeviceObject, ReadOffset->QuadPart, ReadLength, Buffer);
140
141 DPRINT ("Building synchronous FSD Request...\n");
142 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ,
143 pDeviceObject,
144 Buffer,
145 ReadLength,
146 ReadOffset,
147 &Event,
148 &IoStatus);
149 if (Irp == NULL)
150 {
151 DPRINT("IoBuildSynchronousFsdRequest() failed\n");
152 return STATUS_UNSUCCESSFUL;
153 }
154
155 DPRINT("Calling IO Driver... with irp %x\n", Irp);
156 Status = IoCallDriver(pDeviceObject, Irp);
157
158 DPRINT("Waiting for IO Operation for %x\n", Irp);
159 if (Status == STATUS_PENDING)
160 {
161 DPRINT("Operation pending\n");
162 KeWaitForSingleObject (&Event, Suspended, KernelMode, FALSE, NULL);
163 DPRINT("Getting IO Status... for %x\n", Irp);
164 Status = IoStatus.Status;
165 }
166
167 if (!NT_SUCCESS(Status))
168 {
169 DPRINT("RawFsReadDisk() failed. Status %x\n", Status);
170 DPRINT("(pDeviceObject %x, Offset %I64x, Size %d, Buffer %x\n",
171 pDeviceObject, ReadOffset->QuadPart, ReadLength, Buffer);
172 return Status;
173 }
174 DPRINT("Block request succeeded for %x\n", Irp);
175 return STATUS_SUCCESS;
176 }
177
178 /*static */NTSTATUS
179 RawFsWriteDisk(IN PDEVICE_OBJECT pDeviceObject,
180 IN PLARGE_INTEGER WriteOffset,
181 IN ULONG WriteLength,
182 IN PUCHAR Buffer)
183 {
184 IO_STATUS_BLOCK IoStatus;
185 NTSTATUS Status;
186 KEVENT Event;
187 PIRP Irp;
188
189 DPRINT("RawFsWriteDisk(pDeviceObject %x, Offset %I64x, Size %d, Buffer %x)\n",
190 pDeviceObject, WriteOffset->QuadPart, WriteLength, Buffer);
191
192 KeInitializeEvent(&Event, NotificationEvent, FALSE);
193
194 DPRINT("Building synchronous FSD Request...\n");
195 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_WRITE,
196 pDeviceObject,
197 Buffer,
198 WriteLength,
199 WriteOffset,
200 &Event,
201 &IoStatus);
202 if (!Irp)
203 {
204 DPRINT("IoBuildSynchronousFsdRequest()\n");
205 return(STATUS_UNSUCCESSFUL);
206 }
207
208 DPRINT("Calling IO Driver...\n");
209 Status = IoCallDriver(pDeviceObject, Irp);
210
211 DPRINT("Waiting for IO Operation...\n");
212 if (Status == STATUS_PENDING)
213 {
214 KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL);
215 DPRINT("Getting IO Status...\n");
216 Status = IoStatus.Status;
217 }
218 if (!NT_SUCCESS(Status))
219 {
220 DPRINT("RawFsWriteDisk() failed. Status %x\n", Status);
221 DPRINT("(pDeviceObject %x, Offset %I64x, Size %d, Buffer %x\n",
222 pDeviceObject, WriteOffset->QuadPart, WriteLength, Buffer);
223 return Status;
224 }
225
226 return STATUS_SUCCESS;
227 }
228
229 static NTSTATUS
230 RawFsBlockDeviceIoControl(IN PDEVICE_OBJECT DeviceObject,
231 IN ULONG CtlCode,
232 IN PVOID InputBuffer,
233 IN ULONG InputBufferSize,
234 IN OUT PVOID OutputBuffer,
235 IN OUT PULONG pOutputBufferSize)
236 {
237 ULONG OutputBufferSize = 0;
238 KEVENT Event;
239 PIRP Irp;
240 IO_STATUS_BLOCK IoStatus;
241 NTSTATUS Status;
242
243 DPRINT("RawFsBlockDeviceIoControl(DeviceObject %x, CtlCode %x, "
244 "InputBuffer %x, InputBufferSize %x, OutputBuffer %x, "
245 "POutputBufferSize %x (%x)\n", DeviceObject, CtlCode,
246 InputBuffer, InputBufferSize, OutputBuffer, pOutputBufferSize,
247 pOutputBufferSize ? *pOutputBufferSize : 0);
248
249 if (pOutputBufferSize)
250 {
251 OutputBufferSize = *pOutputBufferSize;
252 }
253
254 KeInitializeEvent(&Event, NotificationEvent, FALSE);
255
256 DPRINT("Building device I/O control request ...\n");
257 Irp = IoBuildDeviceIoControlRequest(CtlCode,
258 DeviceObject,
259 InputBuffer,
260 InputBufferSize,
261 OutputBuffer,
262 OutputBufferSize,
263 FALSE,
264 &Event,
265 &IoStatus);
266 if (Irp == NULL)
267 {
268 DPRINT("IoBuildDeviceIoControlRequest failed\n");
269 return STATUS_INSUFFICIENT_RESOURCES;
270 }
271
272 DPRINT("Calling IO Driver... with irp %x\n", Irp);
273 Status = IoCallDriver(DeviceObject, Irp);
274
275 DPRINT("Waiting for IO Operation for %x\n", Irp);
276 if (Status == STATUS_PENDING)
277 {
278 DPRINT("Operation pending\n");
279 KeWaitForSingleObject (&Event, Suspended, KernelMode, FALSE, NULL);
280 DPRINT("Getting IO Status... for %x\n", Irp);
281 Status = IoStatus.Status;
282 }
283 if (OutputBufferSize)
284 {
285 *pOutputBufferSize = OutputBufferSize;
286 }
287 DPRINT("Returning Status %x\n", Status);
288 return Status;
289 }
290
291 static PRAWFS_FCB
292 RawFsNewFCB(IN PRAWFS_GLOBAL_DATA pGlobalData)
293 {
294 PRAWFS_FCB Fcb;
295
296 Fcb = ExAllocateFromNPagedLookasideList(&pGlobalData->FcbLookasideList);
297 memset(Fcb, 0, sizeof(RAWFS_FCB));
298 ExInitializeResourceLite(&Fcb->PagingIoResource);
299 ExInitializeResourceLite(&Fcb->MainResource);
300 // FsRtlInitializeFileLock(&Fcb->FileLock, NULL, NULL);
301 return Fcb;
302 }
303
304 static VOID
305 RawFsDestroyFCB(IN PRAWFS_GLOBAL_DATA pGlobalData, IN PRAWFS_FCB pFcb)
306 {
307 //FsRtlUninitializeFileLock(&pFcb->FileLock);
308 ExDeleteResourceLite(&pFcb->PagingIoResource);
309 ExDeleteResourceLite(&pFcb->MainResource);
310 ExFreeToNPagedLookasideList(&pGlobalData->FcbLookasideList, pFcb);
311 }
312
313 static PRAWFS_CCB
314 RawFsNewCCB(PRAWFS_GLOBAL_DATA pGlobalData)
315 {
316 PRAWFS_CCB Ccb;
317
318 Ccb = ExAllocateFromNPagedLookasideList(&pGlobalData->CcbLookasideList);
319 memset(Ccb, 0, sizeof(RAWFS_CCB));
320 return Ccb;
321 }
322
323 /*static */VOID
324 RawFsDestroyCCB(PRAWFS_GLOBAL_DATA pGlobalData, PRAWFS_CCB pCcb)
325 {
326 ExFreeToNPagedLookasideList(&pGlobalData->CcbLookasideList, pCcb);
327 }
328
329 static PRAWFS_IRP_CONTEXT
330 RawFsAllocateIrpContext(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
331 {
332 PRAWFS_GLOBAL_DATA GlobalData;
333 PRAWFS_IRP_CONTEXT IrpContext;
334 UCHAR MajorFunction;
335
336 DPRINT("RawFsAllocateIrpContext(DeviceObject %x, Irp %x)\n", DeviceObject, Irp);
337
338 assert(DeviceObject);
339 assert(Irp);
340
341 GlobalData = (PRAWFS_GLOBAL_DATA) DeviceObject->DeviceExtension;
342 IrpContext = ExAllocateFromNPagedLookasideList(&IrpContextLookasideList);
343 if (IrpContext)
344 {
345 RtlZeroMemory(IrpContext, sizeof(IrpContext));
346 IrpContext->Irp = Irp;
347 IrpContext->DeviceObject = DeviceObject;
348 IrpContext->DeviceExt = DeviceObject->DeviceExtension;
349 IrpContext->Stack = IoGetCurrentIrpStackLocation(Irp);
350 assert(IrpContext->Stack);
351 MajorFunction = IrpContext->MajorFunction = IrpContext->Stack->MajorFunction;
352 IrpContext->MinorFunction = IrpContext->Stack->MinorFunction;
353 IrpContext->FileObject = IrpContext->Stack->FileObject;
354 if (MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL ||
355 MajorFunction == IRP_MJ_DEVICE_CONTROL ||
356 MajorFunction == IRP_MJ_SHUTDOWN)
357 {
358 IrpContext->Flags |= IRPCONTEXT_CANWAIT;
359 }
360 else if (MajorFunction != IRP_MJ_CLEANUP &&
361 MajorFunction != IRP_MJ_CLOSE &&
362 IoIsOperationSynchronous(Irp))
363 {
364 IrpContext->Flags |= IRPCONTEXT_CANWAIT;
365 }
366 }
367 return IrpContext;
368 }
369
370 static VOID
371 RawFsFreeIrpContext(IN PRAWFS_IRP_CONTEXT IrpContext)
372 {
373 DPRINT("RawFsFreeIrpContext(IrpContext %x)\n", IrpContext);
374
375 assert(IrpContext);
376
377 ExFreeToNPagedLookasideList(&IrpContextLookasideList, IrpContext);
378 }
379
380 static VOID
381 STDCALL RawFsDoRequest(PVOID IrpContext)
382 {
383 ULONG Count;
384
385 DPRINT("RawFsDoRequest(IrpContext %x), MajorFunction %x, %d\n",
386 IrpContext, ((PRAWFS_IRP_CONTEXT) IrpContext)->MajorFunction, Count);
387
388 Count = InterlockedDecrement(&RawFsQueueCount);
389 RawFsDispatchRequest((PRAWFS_IRP_CONTEXT) IrpContext);
390 }
391
392 static NTSTATUS
393 RawFsQueueRequest(PRAWFS_IRP_CONTEXT IrpContext)
394 {
395 ULONG Count;
396
397 DPRINT("RawFsQueueRequest (IrpContext %x), %d\n", IrpContext, Count);
398
399 assert(IrpContext != NULL);
400 assert(IrpContext->Irp != NULL);
401
402 Count = InterlockedIncrement(&RawFsQueueCount);
403
404 IrpContext->Flags |= IRPCONTEXT_CANWAIT;
405 IoMarkIrpPending (IrpContext->Irp);
406 ExInitializeWorkItem (&IrpContext->WorkQueueItem, RawFsDoRequest, IrpContext);
407 ExQueueWorkItem(&IrpContext->WorkQueueItem, CriticalWorkQueue);
408 return STATUS_PENDING;
409 }
410
411 static NTSTATUS
412 RawFsClose(IN PRAWFS_IRP_CONTEXT IrpContext)
413 {
414 DPRINT("RawFsClose(IrpContext %x)\n", IrpContext);
415 UNIMPLEMENTED
416 return STATUS_NOT_IMPLEMENTED;
417 }
418
419 static NTSTATUS
420 RawFsCreateFile(IN PRAWFS_IRP_CONTEXT IrpContext)
421 {
422 PRAWFS_DEVICE_EXTENSION DeviceExt;
423 PRAWFS_GLOBAL_DATA GlobalData;
424 PIO_STACK_LOCATION IoSp;
425 PFILE_OBJECT FileObject;
426 ULONG RequestedDisposition;
427 ULONG RequestedOptions;
428 PRAWFS_FCB pFcb;
429 PRAWFS_CCB pCcb;
430
431 GlobalData = (PRAWFS_GLOBAL_DATA) IrpContext->DeviceObject->DeviceExtension;
432 IoSp = IoGetCurrentIrpStackLocation(IrpContext->Irp);
433 RequestedDisposition = ((IoSp->Parameters.Create.Options >> 24) & 0xff);
434 RequestedOptions = IoSp->Parameters.Create.Options & FILE_VALID_OPTION_FLAGS;
435 FileObject = IoSp->FileObject;
436 DeviceExt = IrpContext->DeviceObject->DeviceExtension;
437
438 if (FileObject->FileName.Length == 0 &&
439 FileObject->RelatedFileObject == NULL)
440 {
441 /* This a open operation for the volume itself */
442 if (RequestedDisposition == FILE_CREATE
443 || RequestedDisposition == FILE_OVERWRITE_IF
444 || RequestedDisposition == FILE_SUPERSEDE)
445 {
446 return STATUS_ACCESS_DENIED;
447 }
448 if (RequestedOptions & FILE_DIRECTORY_FILE)
449 {
450 return STATUS_NOT_A_DIRECTORY;
451 }
452 pFcb = DeviceExt->VolumeFcb;
453 pCcb = RawFsNewCCB(GlobalData);
454 if (pCcb == NULL)
455 {
456 return (STATUS_INSUFFICIENT_RESOURCES);
457 }
458
459 FileObject->Flags |= FO_FCB_IS_VALID;
460 FileObject->SectionObjectPointer = &pFcb->SectionObjectPointers;
461 FileObject->FsContext = pFcb;
462 FileObject->FsContext2 = pCcb;
463 pFcb->RefCount++;
464
465 IrpContext->Irp->IoStatus.Information = FILE_OPENED;
466 return(STATUS_SUCCESS);
467 }
468
469 /* This filesystem driver only supports volume access */
470 return(STATUS_INVALID_PARAMETER);
471 }
472
473 static NTSTATUS
474 RawFsCreate(IN PRAWFS_IRP_CONTEXT IrpContext)
475 {
476 NTSTATUS Status;
477
478 DPRINT("RawFsCreate(IrpContext %x)\n", IrpContext);
479
480 assert(IrpContext);
481
482 if (RawFsIsRawFileSystemDeviceObject(IrpContext->DeviceObject))
483 {
484 /* DeviceObject represents FileSystem instead of logical volume */
485 DPRINT("RawFsCreate() called with file system\n");
486 IrpContext->Irp->IoStatus.Information = FILE_OPENED;
487 IrpContext->Irp->IoStatus.Status = STATUS_SUCCESS;
488 IoCompleteRequest(IrpContext->Irp, IO_DISK_INCREMENT);
489 RawFsFreeIrpContext(IrpContext);
490 return STATUS_SUCCESS;
491 }
492
493 if (!(IrpContext->Flags & IRPCONTEXT_CANWAIT))
494 {
495 return RawFsQueueRequest(IrpContext);
496 }
497
498 IrpContext->Irp->IoStatus.Information = 0;
499
500 Status = RawFsCreateFile(IrpContext);
501
502 IrpContext->Irp->IoStatus.Status = Status;
503 IoCompleteRequest(IrpContext->Irp,
504 NT_SUCCESS(Status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT);
505 RawFsFreeIrpContext(IrpContext);
506
507 return Status;
508 }
509
510 static NTSTATUS
511 RawFsRead(IN PRAWFS_IRP_CONTEXT IrpContext)
512 {
513 DPRINT("RawFsRead(IrpContext %x)\n", IrpContext);
514 UNIMPLEMENTED
515 return STATUS_NOT_IMPLEMENTED;
516 }
517
518 static NTSTATUS
519 RawFsWrite(IN PRAWFS_IRP_CONTEXT IrpContext)
520 {
521 DPRINT("RawFsWrite(IrpContext %x)\n", IrpContext);
522 UNIMPLEMENTED
523 return STATUS_NOT_IMPLEMENTED;
524 }
525
526 static NTSTATUS
527 RawFsMount(IN PRAWFS_IRP_CONTEXT IrpContext)
528 {
529 PRAWFS_GLOBAL_DATA GlobalData;
530 PDEVICE_OBJECT DeviceObject = NULL;
531 PRAWFS_DEVICE_EXTENSION DeviceExt = NULL;
532 PRAWFS_FCB VolumeFcb = NULL;
533 PRAWFS_FCB Fcb = NULL;
534 PARTITION_INFORMATION PartitionInfo;
535 DISK_GEOMETRY DiskGeometry;
536 LARGE_INTEGER VolumeSize;
537 NTSTATUS Status;
538 ULONG Size;
539
540 DPRINT("RawFsMount(IrpContext %x)\n", IrpContext);
541
542 assert(IrpContext);
543
544 if (!RawFsIsRawFileSystemDeviceObject(IrpContext->DeviceObject))
545 {
546 Status = STATUS_INVALID_DEVICE_REQUEST;
547 DPRINT("Not for me\n");
548 goto ByeBye;
549 }
550
551 GlobalData = (PRAWFS_GLOBAL_DATA) IrpContext->DeviceObject->DeviceExtension;
552
553 Status = IoCreateDevice(GlobalData->DriverObject,
554 sizeof(RAWFS_DEVICE_EXTENSION),
555 NULL,
556 FILE_DEVICE_FILE_SYSTEM,
557 0,
558 FALSE,
559 &DeviceObject);
560 if (!NT_SUCCESS(Status))
561 {
562 goto ByeBye;
563 }
564
565 DeviceObject->Flags |= DO_DIRECT_IO;
566 DeviceExt = (PVOID) DeviceObject->DeviceExtension;
567 RtlZeroMemory(DeviceExt, sizeof(RAWFS_DEVICE_EXTENSION));
568
569 /* Use same vpb as device disk */
570 DeviceObject->Vpb = IrpContext->Stack->Parameters.MountVolume.DeviceObject->Vpb;
571 DeviceExt->StorageDevice = IrpContext->Stack->Parameters.MountVolume.DeviceObject;
572 DeviceExt->StorageDevice->Vpb->DeviceObject = DeviceObject;
573 DeviceExt->StorageDevice->Vpb->RealDevice = DeviceExt->StorageDevice;
574 DeviceExt->StorageDevice->Vpb->Flags |= VPB_MOUNTED;
575 DeviceObject->StackSize = DeviceExt->StorageDevice->StackSize + 1;
576 DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
577
578 KeInitializeSpinLock(&DeviceExt->FcbListLock);
579 InitializeListHead(&DeviceExt->FcbListHead);
580
581 /* First try getting harddisk geometry then try getting CD-ROM geometry */
582 Size = sizeof(DISK_GEOMETRY);
583 Status = RawFsBlockDeviceIoControl(
584 IrpContext->Stack->Parameters.MountVolume.DeviceObject,
585 IOCTL_DISK_GET_DRIVE_GEOMETRY,
586 NULL,
587 0,
588 &DiskGeometry,
589 &Size);
590 if (!NT_SUCCESS(Status))
591 {
592 DPRINT("RawFsBlockDeviceIoControl failed with status 0x%.08x\n", Status);
593 goto ByeBye;
594 }
595 if (DiskGeometry.MediaType == FixedMedia)
596 {
597 // We have found a hard disk
598 Size = sizeof(PARTITION_INFORMATION);
599 Status = RawFsBlockDeviceIoControl(
600 IrpContext->Stack->Parameters.MountVolume.DeviceObject,
601 IOCTL_DISK_GET_PARTITION_INFO,
602 NULL,
603 0,
604 &PartitionInfo,
605 &Size);
606 if (!NT_SUCCESS(Status))
607 {
608 DPRINT("RawFsBlockDeviceIoControl() failed (%x)\n", Status);
609 goto ByeBye;
610 }
611 #ifndef NDEBUG
612 DbgPrint("Partition Information:\n");
613 DbgPrint("StartingOffset %u\n", PartitionInfo.StartingOffset.QuadPart);
614 DbgPrint("PartitionLength %u\n", PartitionInfo.PartitionLength.QuadPart);
615 DbgPrint("HiddenSectors %u\n", PartitionInfo.HiddenSectors);
616 DbgPrint("PartitionNumber %u\n", PartitionInfo.PartitionNumber);
617 DbgPrint("PartitionType %u\n", PartitionInfo.PartitionType);
618 DbgPrint("BootIndicator %u\n", PartitionInfo.BootIndicator);
619 DbgPrint("RecognizedPartition %u\n", PartitionInfo.RecognizedPartition);
620 DbgPrint("RewritePartition %u\n", PartitionInfo.RewritePartition);
621 #endif
622 VolumeSize.QuadPart = PartitionInfo.PartitionLength.QuadPart;
623 }
624 else if (DiskGeometry.MediaType > Unknown && DiskGeometry.MediaType <= RemovableMedia)
625 {
626 Status = STATUS_UNRECOGNIZED_VOLUME;
627 goto ByeBye;
628 }
629
630 VolumeFcb = RawFsNewFCB(GlobalData);
631 if (VolumeFcb == NULL)
632 {
633 Status = STATUS_INSUFFICIENT_RESOURCES;
634 goto ByeBye;
635 }
636
637 VolumeFcb->Flags = FCB_IS_VOLUME;
638 VolumeFcb->RFCB.FileSize.QuadPart = VolumeSize.QuadPart;
639 VolumeFcb->RFCB.ValidDataLength.QuadPart = VolumeFcb->RFCB.FileSize.QuadPart;
640 VolumeFcb->RFCB.AllocationSize.QuadPart = VolumeFcb->RFCB.FileSize.QuadPart;
641 DeviceExt->VolumeFcb = VolumeFcb;
642
643 ExAcquireResourceExclusiveLite(&GlobalData->VolumeListLock, TRUE);
644 InsertHeadList(&GlobalData->VolumeListHead, &DeviceExt->VolumeListEntry);
645 ExReleaseResourceLite(&GlobalData->VolumeListLock);
646
647 /* No serial number */
648 DeviceObject->Vpb->SerialNumber = 0;
649
650 /* Set volume label (no label) */
651 *(DeviceObject->Vpb->VolumeLabel) = 0;
652 DeviceObject->Vpb->VolumeLabelLength = 0;
653
654 Status = STATUS_SUCCESS;
655
656 ByeBye:
657 if (!NT_SUCCESS(Status))
658 {
659 DPRINT("RAWFS: RawFsMount() Status 0x%.08x\n", Status);
660
661 if (Fcb)
662 RawFsDestroyFCB(GlobalData, Fcb);
663 if (DeviceObject)
664 IoDeleteDevice(DeviceObject);
665 if (VolumeFcb)
666 RawFsDestroyFCB(GlobalData, VolumeFcb);
667 }
668 return Status;
669 }
670
671 static NTSTATUS
672 RawFsFileSystemControl(IN PRAWFS_IRP_CONTEXT IrpContext)
673 {
674 NTSTATUS Status;
675
676 DPRINT("RawFsFileSystemControl(IrpContext %x)\n", IrpContext);
677
678 assert (IrpContext);
679
680 switch (IrpContext->MinorFunction)
681 {
682 case IRP_MN_USER_FS_REQUEST:
683 DPRINT("RawFs FSC: IRP_MN_USER_FS_REQUEST\n");
684 Status = STATUS_INVALID_DEVICE_REQUEST;
685 break;
686
687 case IRP_MN_MOUNT_VOLUME:
688 DPRINT("RawFs FSC: IRP_MN_MOUNT_VOLUME\n");
689 Status = RawFsMount(IrpContext);
690 break;
691
692 case IRP_MN_VERIFY_VOLUME:
693 DPRINT("RawFs FSC: IRP_MN_VERIFY_VOLUME\n");
694 Status = STATUS_INVALID_DEVICE_REQUEST;
695 break;
696
697 default:
698 DPRINT("RawFs FSC: MinorFunction %d\n", IrpContext->MinorFunction);
699 Status = STATUS_INVALID_DEVICE_REQUEST;
700 break;
701 }
702
703 IrpContext->Irp->IoStatus.Status = Status;
704 IrpContext->Irp->IoStatus.Information = 0;
705
706 IoCompleteRequest(IrpContext->Irp, IO_NO_INCREMENT);
707 RawFsFreeIrpContext(IrpContext);
708 return Status;
709 }
710
711 static NTSTATUS
712 RawFsQueryInformation(IN PRAWFS_IRP_CONTEXT IrpContext)
713 {
714 DPRINT("RawFsQueryInformation(IrpContext %x)\n", IrpContext);
715 UNIMPLEMENTED
716 return STATUS_NOT_IMPLEMENTED;
717 }
718
719 static NTSTATUS
720 RawFsSetInformation(IN PRAWFS_IRP_CONTEXT IrpContext)
721 {
722 DPRINT("RawFsSetInformation(IrpContext %x)\n", IrpContext);
723 UNIMPLEMENTED
724 return STATUS_NOT_IMPLEMENTED;
725 }
726
727 static NTSTATUS
728 RawFsDirectoryControl(IN PRAWFS_IRP_CONTEXT IrpContext)
729 {
730 DPRINT("RawFsDirectoryControl(IrpContext %x)\n", IrpContext);
731 UNIMPLEMENTED
732 return STATUS_NOT_IMPLEMENTED;
733 }
734
735 static NTSTATUS
736 RawFsQueryVolumeInformation(IN PRAWFS_IRP_CONTEXT IrpContext)
737 {
738 DPRINT("RawFsQueryVolumeInformation(IrpContext %x)\n", IrpContext);
739 UNIMPLEMENTED
740 return STATUS_NOT_IMPLEMENTED;
741 }
742
743 static NTSTATUS
744 RawFsSetVolumeInformation(IN PRAWFS_IRP_CONTEXT IrpContext)
745 {
746 DPRINT("RawFsSetVolumeInformation(IrpContext %x)\n", IrpContext);
747 UNIMPLEMENTED
748 return STATUS_NOT_IMPLEMENTED;
749 }
750
751 static NTSTATUS
752 RawFsLockControl(IN PRAWFS_IRP_CONTEXT IrpContext)
753 {
754 DPRINT("RawFsLockControl(IrpContext %x)\n", IrpContext);
755 UNIMPLEMENTED
756 return STATUS_NOT_IMPLEMENTED;
757 }
758
759 static NTSTATUS
760 RawFsCleanup(IN PRAWFS_IRP_CONTEXT IrpContext)
761 {
762 DPRINT("RawFsCleanup(IrpContext %x)\n", IrpContext);
763 UNIMPLEMENTED
764 return STATUS_NOT_IMPLEMENTED;
765 }
766
767 static NTSTATUS
768 RawFsFlush(IN PRAWFS_IRP_CONTEXT IrpContext)
769 {
770 DPRINT("RawFsFlush(IrpContext %x)\n", IrpContext);
771 UNIMPLEMENTED
772 return STATUS_NOT_IMPLEMENTED;
773 }
774
775 static NTSTATUS STDCALL
776 RawFsShutdown(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
777 {
778 DPRINT("RawFsShutdown(DeviceObject %x, Irp %x)\n", DeviceObject, Irp);
779
780 /*
781 * Note: Do NOT call UNIMPLEMENTED here!
782 * This function must finish in order to shutdown ReactOS properly!
783 */
784
785 return STATUS_NOT_IMPLEMENTED;
786 }
787
788 static NTSTATUS
789 RawFsDispatchRequest(IN PRAWFS_IRP_CONTEXT IrpContext)
790 {
791 DPRINT("RawFsDispatchRequest(IrpContext %x), MajorFunction %x\n",
792 IrpContext, IrpContext->MajorFunction);
793
794 assert (IrpContext);
795
796 switch (IrpContext->MajorFunction)
797 {
798 case IRP_MJ_CLOSE:
799 return RawFsClose(IrpContext);
800 case IRP_MJ_CREATE:
801 return RawFsCreate (IrpContext);
802 case IRP_MJ_READ:
803 return RawFsRead (IrpContext);
804 case IRP_MJ_WRITE:
805 return RawFsWrite (IrpContext);
806 case IRP_MJ_FILE_SYSTEM_CONTROL:
807 return RawFsFileSystemControl(IrpContext);
808 case IRP_MJ_QUERY_INFORMATION:
809 return RawFsQueryInformation (IrpContext);
810 case IRP_MJ_SET_INFORMATION:
811 return RawFsSetInformation (IrpContext);
812 case IRP_MJ_DIRECTORY_CONTROL:
813 return RawFsDirectoryControl(IrpContext);
814 case IRP_MJ_QUERY_VOLUME_INFORMATION:
815 return RawFsQueryVolumeInformation(IrpContext);
816 case IRP_MJ_SET_VOLUME_INFORMATION:
817 return RawFsSetVolumeInformation(IrpContext);
818 case IRP_MJ_LOCK_CONTROL:
819 return RawFsLockControl(IrpContext);
820 case IRP_MJ_CLEANUP:
821 return RawFsCleanup(IrpContext);
822 case IRP_MJ_FLUSH_BUFFERS:
823 return RawFsFlush(IrpContext);
824 default:
825 DPRINT1("Unexpected major function %x\n", IrpContext->MajorFunction);
826 IrpContext->Irp->IoStatus.Status = STATUS_DRIVER_INTERNAL_ERROR;
827 IoCompleteRequest(IrpContext->Irp, IO_NO_INCREMENT);
828 RawFsFreeIrpContext(IrpContext);
829 return STATUS_DRIVER_INTERNAL_ERROR;
830 }
831 }
832
833 static NTSTATUS STDCALL
834 RawFsBuildRequest(IN PDEVICE_OBJECT DeviceObject,
835 IN PIRP Irp)
836 {
837 PRAWFS_IRP_CONTEXT IrpContext;
838 NTSTATUS Status;
839
840 DPRINT("RawFsBuildRequest(DeviceObject %x, Irp %x)\n", DeviceObject, Irp);
841
842 assert(DeviceObject);
843 assert(Irp);
844
845 IrpContext = RawFsAllocateIrpContext(DeviceObject, Irp);
846 if (IrpContext == NULL)
847 {
848 Status = STATUS_INSUFFICIENT_RESOURCES;
849 Irp->IoStatus.Status = Status;
850 IoCompleteRequest(Irp, IO_NO_INCREMENT);
851 }
852 else
853 {
854 if (KeGetCurrentIrql() <= PASSIVE_LEVEL)
855 {
856 FsRtlEnterFileSystem();
857 }
858 else
859 {
860 DPRINT1("RawFs is entered at irql = %d\n", KeGetCurrentIrql());
861 }
862 Status = RawFsDispatchRequest(IrpContext);
863 if (KeGetCurrentIrql() <= PASSIVE_LEVEL)
864 {
865 FsRtlExitFileSystem();
866 }
867 }
868 return Status;
869 }
870
871 NTSTATUS STDCALL
872 RawFsDriverEntry(IN PDRIVER_OBJECT DriverObject,
873 IN PUNICODE_STRING RegistryPath)
874 {
875 PRAWFS_GLOBAL_DATA DeviceData;
876 NTSTATUS Status;
877
878 RawFsDriverObject = DriverObject;
879
880 Status = IoCreateDevice(DriverObject,
881 sizeof(RAWFS_GLOBAL_DATA),
882 NULL,
883 FILE_DEVICE_DISK_FILE_SYSTEM,
884 0,
885 FALSE,
886 &DiskDeviceObject);
887 if (!NT_SUCCESS(Status))
888 {
889 CPRINT("IoCreateDevice() failed with status 0x%.08x\n", Status);
890 KeBugCheck(PHASE1_INITIALIZATION_FAILED);
891 return(Status);
892 }
893 DeviceData = DiskDeviceObject->DeviceExtension;
894 RtlZeroMemory(DeviceData, sizeof(RAWFS_GLOBAL_DATA));
895 DeviceData->DriverObject = DriverObject;
896 DeviceData->DeviceObject = DiskDeviceObject;
897 DiskDeviceObject->Flags |= DO_DIRECT_IO;
898
899
900 Status = IoCreateDevice(DriverObject,
901 sizeof(RAWFS_GLOBAL_DATA),
902 NULL,
903 FILE_DEVICE_CD_ROM_FILE_SYSTEM,
904 0,
905 FALSE,
906 &CdromDeviceObject);
907 if (!NT_SUCCESS(Status))
908 {
909 CPRINT("IoCreateDevice() failed with status 0x%.08x\n", Status);
910 KeBugCheck(PHASE1_INITIALIZATION_FAILED);
911 return(Status);
912 }
913 DeviceData = CdromDeviceObject->DeviceExtension;
914 RtlZeroMemory (DeviceData, sizeof(RAWFS_GLOBAL_DATA));
915 DeviceData->DriverObject = DriverObject;
916 DeviceData->DeviceObject = CdromDeviceObject;
917 CdromDeviceObject->Flags |= DO_DIRECT_IO;
918
919
920 Status = IoCreateDevice(DriverObject,
921 sizeof(RAWFS_GLOBAL_DATA),
922 NULL,
923 FILE_DEVICE_TAPE_FILE_SYSTEM,
924 0,
925 FALSE,
926 &TapeDeviceObject);
927 if (!NT_SUCCESS(Status))
928 {
929 CPRINT("IoCreateDevice() failed with status 0x%.08x\n", Status);
930 KeBugCheck(PHASE1_INITIALIZATION_FAILED);
931 return(Status);
932 }
933 DeviceData = TapeDeviceObject->DeviceExtension;
934 RtlZeroMemory (DeviceData, sizeof(RAWFS_GLOBAL_DATA));
935 DeviceData->DriverObject = DriverObject;
936 DeviceData->DeviceObject = TapeDeviceObject;
937 TapeDeviceObject->Flags |= DO_DIRECT_IO;
938
939
940 DriverObject->MajorFunction[IRP_MJ_CLOSE] = (PDRIVER_DISPATCH) RawFsBuildRequest;
941 DriverObject->MajorFunction[IRP_MJ_CREATE] = (PDRIVER_DISPATCH) RawFsBuildRequest;
942 DriverObject->MajorFunction[IRP_MJ_READ] = (PDRIVER_DISPATCH) RawFsBuildRequest;
943 DriverObject->MajorFunction[IRP_MJ_WRITE] = (PDRIVER_DISPATCH) RawFsBuildRequest;
944 DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = (PDRIVER_DISPATCH) RawFsBuildRequest;
945 DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] = (PDRIVER_DISPATCH) RawFsBuildRequest;
946 DriverObject->MajorFunction[IRP_MJ_SET_INFORMATION] = (PDRIVER_DISPATCH) RawFsBuildRequest;
947 DriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL] = (PDRIVER_DISPATCH) RawFsBuildRequest;
948 DriverObject->MajorFunction[IRP_MJ_QUERY_VOLUME_INFORMATION] = (PDRIVER_DISPATCH) RawFsBuildRequest;
949 DriverObject->MajorFunction[IRP_MJ_SET_VOLUME_INFORMATION] = (PDRIVER_DISPATCH) RawFsBuildRequest;
950 DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = (PDRIVER_DISPATCH) RawFsShutdown;
951 DriverObject->MajorFunction[IRP_MJ_LOCK_CONTROL] = (PDRIVER_DISPATCH) RawFsBuildRequest;
952 DriverObject->MajorFunction[IRP_MJ_CLEANUP] = (PDRIVER_DISPATCH) RawFsBuildRequest;
953 DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = (PDRIVER_DISPATCH) RawFsBuildRequest;
954 DriverObject->DriverUnload = NULL;
955
956 ExInitializeNPagedLookasideList(&IrpContextLookasideList,
957 NULL, NULL, 0, sizeof(RAWFS_IRP_CONTEXT), TAG_IRP, 0);
958
959
960 IoRegisterFileSystem(DiskDeviceObject);
961 IoRegisterFileSystem(CdromDeviceObject);
962 IoRegisterFileSystem(TapeDeviceObject);
963
964 return STATUS_SUCCESS;
965 }
966
967 /* EOF */