update for HEAD-2003091401
[reactos.git] / ntoskrnl / io / rawfs.c
1 /* $Id$
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 */