d207c4ca27540aa5c831258ea76601e754cd303d
[reactos.git] / reactos / ntoskrnl / io / rawfs.c
1 /* $Id: rawfs.c,v 1.12 2004/08/15 16:39:03 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 <ntoskrnl.h>
15 #define NDEBUG
16 #include <internal/debug.h>
17
18 /* TYPES *******************************************************************/
19
20 typedef struct _RAWFS_GLOBAL_DATA
21 {
22 PDRIVER_OBJECT DriverObject;
23 PDEVICE_OBJECT DeviceObject;
24 ULONG Flags;
25 ERESOURCE VolumeListLock;
26 LIST_ENTRY VolumeListHead;
27 NPAGED_LOOKASIDE_LIST FcbLookasideList;
28 NPAGED_LOOKASIDE_LIST CcbLookasideList;
29 } RAWFS_GLOBAL_DATA, *PRAWFS_GLOBAL_DATA, VCB, *PVCB;
30
31 typedef struct _RAWFS_DEVICE_EXTENSION
32 {
33 KSPIN_LOCK FcbListLock;
34 LIST_ENTRY FcbListHead;
35 PDEVICE_OBJECT StorageDevice;
36 ULONG Flags;
37 struct _RAWFS_FCB *VolumeFcb;
38 LIST_ENTRY VolumeListEntry;
39 } RAWFS_DEVICE_EXTENSION, *PRAWFS_DEVICE_EXTENSION;
40
41 typedef struct _RAWFS_IRP_CONTEXT
42 {
43 PIRP Irp;
44 PDEVICE_OBJECT DeviceObject;
45 PRAWFS_DEVICE_EXTENSION DeviceExt;
46 ULONG Flags;
47 WORK_QUEUE_ITEM WorkQueueItem;
48 PIO_STACK_LOCATION Stack;
49 UCHAR MajorFunction;
50 UCHAR MinorFunction;
51 PFILE_OBJECT FileObject;
52 } RAWFS_IRP_CONTEXT, *PRAWFS_IRP_CONTEXT;
53
54 #define IRPCONTEXT_CANWAIT 0x0001
55
56 #define FCB_CACHE_INITIALIZED 0x0001
57 #define FCB_DELETE_PENDING 0x0002
58 #define FCB_IS_FAT 0x0004
59 #define FCB_IS_PAGE_FILE 0x0008
60 #define FCB_IS_VOLUME 0x0010
61
62 typedef struct _RAWFS_FCB
63 {
64 /* Start FCB header required by ReactOS/Windows NT */
65 FSRTL_COMMON_FCB_HEADER RFCB;
66 SECTION_OBJECT_POINTERS SectionObjectPointers;
67 ERESOURCE MainResource;
68 ERESOURCE PagingIoResource;
69 /* End FCB header required by ReactOS/Windows NT */
70
71 /* Reference count */
72 LONG RefCount;
73
74 /* List of FCB's for this volume */
75 LIST_ENTRY FcbListEntry;
76
77 /* Pointer to the parent fcb */
78 struct _RAWFS_FCB* ParentFcb;
79
80 /* Flags for the FCB */
81 ULONG Flags;
82
83 /* Pointer to the file object which has initialized the fcb */
84 PFILE_OBJECT FileObject;
85 } RAWFS_FCB, *PRAWFS_FCB;
86
87 typedef struct _RAWFS_CCB
88 {
89 LARGE_INTEGER CurrentByteOffset;
90 } RAWFS_CCB, *PRAWFS_CCB;
91
92 /* GLOBALS ******************************************************************/
93
94 #define TAG_IRP TAG('R', 'I', 'R', 'P')
95
96 static PDRIVER_OBJECT RawFsDriverObject;
97 static PDEVICE_OBJECT DiskDeviceObject;
98 static PDEVICE_OBJECT CdromDeviceObject;
99 static PDEVICE_OBJECT TapeDeviceObject;
100 static NPAGED_LOOKASIDE_LIST IrpContextLookasideList;
101 static LONG RawFsQueueCount = 0;
102
103 /* FUNCTIONS *****************************************************************/
104
105 BOOLEAN
106 RawFsIsRawFileSystemDeviceObject(IN PDEVICE_OBJECT DeviceObject)
107 {
108 DPRINT("RawFsIsRawFileSystemDeviceObject(DeviceObject %x)\n", DeviceObject);
109
110 if (DeviceObject == DiskDeviceObject)
111 return TRUE;
112 if (DeviceObject == CdromDeviceObject)
113 return TRUE;
114 if (DeviceObject == TapeDeviceObject)
115 return TRUE;
116 return FALSE;
117 }
118
119 static NTSTATUS
120 RawFsDispatchRequest(IN PRAWFS_IRP_CONTEXT IrpContext);
121
122 /*static */NTSTATUS
123 RawFsReadDisk(IN PDEVICE_OBJECT pDeviceObject,
124 IN PLARGE_INTEGER ReadOffset,
125 IN ULONG ReadLength,
126 IN OUT PUCHAR Buffer)
127 {
128 IO_STATUS_BLOCK IoStatus;
129 NTSTATUS Status;
130 KEVENT Event;
131 PIRP Irp;
132
133 KeInitializeEvent(&Event, NotificationEvent, FALSE);
134
135 DPRINT("RawFsReadDisk(pDeviceObject %x, Offset %I64x, Length %d, Buffer %x)\n",
136 pDeviceObject, ReadOffset->QuadPart, ReadLength, Buffer);
137
138 DPRINT ("Building synchronous FSD Request...\n");
139 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ,
140 pDeviceObject,
141 Buffer,
142 ReadLength,
143 ReadOffset,
144 &Event,
145 &IoStatus);
146 if (Irp == NULL)
147 {
148 DPRINT("IoBuildSynchronousFsdRequest() failed\n");
149 return STATUS_UNSUCCESSFUL;
150 }
151
152 DPRINT("Calling IO Driver... with irp %x\n", Irp);
153 Status = IoCallDriver(pDeviceObject, Irp);
154
155 DPRINT("Waiting for IO Operation for %x\n", Irp);
156 if (Status == STATUS_PENDING)
157 {
158 DPRINT("Operation pending\n");
159 KeWaitForSingleObject (&Event, Suspended, KernelMode, FALSE, NULL);
160 DPRINT("Getting IO Status... for %x\n", Irp);
161 Status = IoStatus.Status;
162 }
163
164 if (!NT_SUCCESS(Status))
165 {
166 DPRINT("RawFsReadDisk() failed. Status %x\n", Status);
167 DPRINT("(pDeviceObject %x, Offset %I64x, Size %d, Buffer %x\n",
168 pDeviceObject, ReadOffset->QuadPart, ReadLength, Buffer);
169 return Status;
170 }
171 DPRINT("Block request succeeded for %x\n", Irp);
172 return STATUS_SUCCESS;
173 }
174
175 /*static */NTSTATUS
176 RawFsWriteDisk(IN PDEVICE_OBJECT pDeviceObject,
177 IN PLARGE_INTEGER WriteOffset,
178 IN ULONG WriteLength,
179 IN PUCHAR Buffer)
180 {
181 IO_STATUS_BLOCK IoStatus;
182 NTSTATUS Status;
183 KEVENT Event;
184 PIRP Irp;
185
186 DPRINT("RawFsWriteDisk(pDeviceObject %x, Offset %I64x, Size %d, Buffer %x)\n",
187 pDeviceObject, WriteOffset->QuadPart, WriteLength, Buffer);
188
189 KeInitializeEvent(&Event, NotificationEvent, FALSE);
190
191 DPRINT("Building synchronous FSD Request...\n");
192 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_WRITE,
193 pDeviceObject,
194 Buffer,
195 WriteLength,
196 WriteOffset,
197 &Event,
198 &IoStatus);
199 if (!Irp)
200 {
201 DPRINT("IoBuildSynchronousFsdRequest()\n");
202 return(STATUS_UNSUCCESSFUL);
203 }
204
205 DPRINT("Calling IO Driver...\n");
206 Status = IoCallDriver(pDeviceObject, Irp);
207
208 DPRINT("Waiting for IO Operation...\n");
209 if (Status == STATUS_PENDING)
210 {
211 KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL);
212 DPRINT("Getting IO Status...\n");
213 Status = IoStatus.Status;
214 }
215 if (!NT_SUCCESS(Status))
216 {
217 DPRINT("RawFsWriteDisk() failed. Status %x\n", Status);
218 DPRINT("(pDeviceObject %x, Offset %I64x, Size %d, Buffer %x\n",
219 pDeviceObject, WriteOffset->QuadPart, WriteLength, Buffer);
220 return Status;
221 }
222
223 return STATUS_SUCCESS;
224 }
225
226 static NTSTATUS
227 RawFsBlockDeviceIoControl(IN PDEVICE_OBJECT DeviceObject,
228 IN ULONG CtlCode,
229 IN PVOID InputBuffer,
230 IN ULONG InputBufferSize,
231 IN OUT PVOID OutputBuffer,
232 IN OUT PULONG pOutputBufferSize)
233 {
234 ULONG OutputBufferSize = 0;
235 KEVENT Event;
236 PIRP Irp;
237 IO_STATUS_BLOCK IoStatus;
238 NTSTATUS Status;
239
240 DPRINT("RawFsBlockDeviceIoControl(DeviceObject %x, CtlCode %x, "
241 "InputBuffer %x, InputBufferSize %x, OutputBuffer %x, "
242 "POutputBufferSize %x (%x)\n", DeviceObject, CtlCode,
243 InputBuffer, InputBufferSize, OutputBuffer, pOutputBufferSize,
244 pOutputBufferSize ? *pOutputBufferSize : 0);
245
246 if (pOutputBufferSize)
247 {
248 OutputBufferSize = *pOutputBufferSize;
249 }
250
251 KeInitializeEvent(&Event, NotificationEvent, FALSE);
252
253 DPRINT("Building device I/O control request ...\n");
254 Irp = IoBuildDeviceIoControlRequest(CtlCode,
255 DeviceObject,
256 InputBuffer,
257 InputBufferSize,
258 OutputBuffer,
259 OutputBufferSize,
260 FALSE,
261 &Event,
262 &IoStatus);
263 if (Irp == NULL)
264 {
265 DPRINT("IoBuildDeviceIoControlRequest failed\n");
266 return STATUS_INSUFFICIENT_RESOURCES;
267 }
268
269 DPRINT("Calling IO Driver... with irp %x\n", Irp);
270 Status = IoCallDriver(DeviceObject, Irp);
271
272 DPRINT("Waiting for IO Operation for %x\n", Irp);
273 if (Status == STATUS_PENDING)
274 {
275 DPRINT("Operation pending\n");
276 KeWaitForSingleObject (&Event, Suspended, KernelMode, FALSE, NULL);
277 DPRINT("Getting IO Status... for %x\n", Irp);
278 Status = IoStatus.Status;
279 }
280 if (OutputBufferSize)
281 {
282 *pOutputBufferSize = OutputBufferSize;
283 }
284 DPRINT("Returning Status %x\n", Status);
285 return Status;
286 }
287
288 static PRAWFS_FCB
289 RawFsNewFCB(IN PRAWFS_GLOBAL_DATA pGlobalData)
290 {
291 PRAWFS_FCB Fcb;
292
293 Fcb = ExAllocateFromNPagedLookasideList(&pGlobalData->FcbLookasideList);
294 memset(Fcb, 0, sizeof(RAWFS_FCB));
295 ExInitializeResourceLite(&Fcb->PagingIoResource);
296 ExInitializeResourceLite(&Fcb->MainResource);
297 // FsRtlInitializeFileLock(&Fcb->FileLock, NULL, NULL);
298 return Fcb;
299 }
300
301 static VOID
302 RawFsDestroyFCB(IN PRAWFS_GLOBAL_DATA pGlobalData, IN PRAWFS_FCB pFcb)
303 {
304 //FsRtlUninitializeFileLock(&pFcb->FileLock);
305 ExDeleteResourceLite(&pFcb->PagingIoResource);
306 ExDeleteResourceLite(&pFcb->MainResource);
307 ExFreeToNPagedLookasideList(&pGlobalData->FcbLookasideList, pFcb);
308 }
309
310 static PRAWFS_CCB
311 RawFsNewCCB(PRAWFS_GLOBAL_DATA pGlobalData)
312 {
313 PRAWFS_CCB Ccb;
314
315 Ccb = ExAllocateFromNPagedLookasideList(&pGlobalData->CcbLookasideList);
316 memset(Ccb, 0, sizeof(RAWFS_CCB));
317 return Ccb;
318 }
319
320 /*static */VOID
321 RawFsDestroyCCB(PRAWFS_GLOBAL_DATA pGlobalData, PRAWFS_CCB pCcb)
322 {
323 ExFreeToNPagedLookasideList(&pGlobalData->CcbLookasideList, pCcb);
324 }
325
326 static PRAWFS_IRP_CONTEXT
327 RawFsAllocateIrpContext(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
328 {
329 PRAWFS_GLOBAL_DATA GlobalData;
330 PRAWFS_IRP_CONTEXT IrpContext;
331 UCHAR MajorFunction;
332
333 DPRINT("RawFsAllocateIrpContext(DeviceObject %x, Irp %x)\n", DeviceObject, Irp);
334
335 assert(DeviceObject);
336 assert(Irp);
337
338 GlobalData = (PRAWFS_GLOBAL_DATA) DeviceObject->DeviceExtension;
339 IrpContext = ExAllocateFromNPagedLookasideList(&IrpContextLookasideList);
340 if (IrpContext)
341 {
342 RtlZeroMemory(IrpContext, sizeof(IrpContext));
343 IrpContext->Irp = Irp;
344 IrpContext->DeviceObject = DeviceObject;
345 IrpContext->DeviceExt = DeviceObject->DeviceExtension;
346 IrpContext->Stack = IoGetCurrentIrpStackLocation(Irp);
347 assert(IrpContext->Stack);
348 MajorFunction = IrpContext->MajorFunction = IrpContext->Stack->MajorFunction;
349 IrpContext->MinorFunction = IrpContext->Stack->MinorFunction;
350 IrpContext->FileObject = IrpContext->Stack->FileObject;
351 if (MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL ||
352 MajorFunction == IRP_MJ_DEVICE_CONTROL ||
353 MajorFunction == IRP_MJ_SHUTDOWN)
354 {
355 IrpContext->Flags |= IRPCONTEXT_CANWAIT;
356 }
357 else if (MajorFunction != IRP_MJ_CLEANUP &&
358 MajorFunction != IRP_MJ_CLOSE &&
359 IoIsOperationSynchronous(Irp))
360 {
361 IrpContext->Flags |= IRPCONTEXT_CANWAIT;
362 }
363 }
364 return IrpContext;
365 }
366
367 static VOID
368 RawFsFreeIrpContext(IN PRAWFS_IRP_CONTEXT IrpContext)
369 {
370 DPRINT("RawFsFreeIrpContext(IrpContext %x)\n", IrpContext);
371
372 assert(IrpContext);
373
374 ExFreeToNPagedLookasideList(&IrpContextLookasideList, IrpContext);
375 }
376
377 static VOID
378 STDCALL RawFsDoRequest(PVOID IrpContext)
379 {
380 ULONG Count;
381
382 Count = InterlockedDecrement(&RawFsQueueCount);
383
384 DPRINT("RawFsDoRequest(IrpContext %x), MajorFunction %x, %d\n",
385 IrpContext, ((PRAWFS_IRP_CONTEXT) IrpContext)->MajorFunction, Count);
386
387 RawFsDispatchRequest((PRAWFS_IRP_CONTEXT) IrpContext);
388 }
389
390 static NTSTATUS
391 RawFsQueueRequest(PRAWFS_IRP_CONTEXT IrpContext)
392 {
393 ULONG Count;
394
395 assert(IrpContext != NULL);
396 assert(IrpContext->Irp != NULL);
397
398 Count = InterlockedIncrement(&RawFsQueueCount);
399
400 DPRINT("RawFsQueueRequest (IrpContext %x), %d\n", IrpContext, Count);
401
402 IrpContext->Flags |= IRPCONTEXT_CANWAIT;
403 IoMarkIrpPending (IrpContext->Irp);
404 ExInitializeWorkItem (&IrpContext->WorkQueueItem, RawFsDoRequest, IrpContext);
405 ExQueueWorkItem(&IrpContext->WorkQueueItem, CriticalWorkQueue);
406 return STATUS_PENDING;
407 }
408
409 static NTSTATUS
410 RawFsClose(IN PRAWFS_IRP_CONTEXT IrpContext)
411 {
412 DPRINT("RawFsClose(IrpContext %x)\n", IrpContext);
413 UNIMPLEMENTED;
414 return STATUS_NOT_IMPLEMENTED;
415 }
416
417 static NTSTATUS
418 RawFsCreateFile(IN PRAWFS_IRP_CONTEXT IrpContext)
419 {
420 PRAWFS_DEVICE_EXTENSION DeviceExt;
421 PRAWFS_GLOBAL_DATA GlobalData;
422 PIO_STACK_LOCATION IoSp;
423 PFILE_OBJECT FileObject;
424 ULONG RequestedDisposition;
425 ULONG RequestedOptions;
426 PRAWFS_FCB pFcb;
427 PRAWFS_CCB pCcb;
428
429 GlobalData = (PRAWFS_GLOBAL_DATA) IrpContext->DeviceObject->DeviceExtension;
430 IoSp = IoGetCurrentIrpStackLocation(IrpContext->Irp);
431 RequestedDisposition = ((IoSp->Parameters.Create.Options >> 24) & 0xff);
432 RequestedOptions = IoSp->Parameters.Create.Options & FILE_VALID_OPTION_FLAGS;
433 FileObject = IoSp->FileObject;
434 DeviceExt = IrpContext->DeviceObject->DeviceExtension;
435
436 if (FileObject->FileName.Length == 0 &&
437 FileObject->RelatedFileObject == NULL)
438 {
439 /* This a open operation for the volume itself */
440 if (RequestedDisposition == FILE_CREATE
441 || RequestedDisposition == FILE_OVERWRITE_IF
442 || RequestedDisposition == FILE_SUPERSEDE)
443 {
444 return STATUS_ACCESS_DENIED;
445 }
446 if (RequestedOptions & FILE_DIRECTORY_FILE)
447 {
448 return STATUS_NOT_A_DIRECTORY;
449 }
450 pFcb = DeviceExt->VolumeFcb;
451 pCcb = RawFsNewCCB(GlobalData);
452 if (pCcb == NULL)
453 {
454 return (STATUS_INSUFFICIENT_RESOURCES);
455 }
456
457 FileObject->Flags |= FO_FCB_IS_VALID;
458 FileObject->SectionObjectPointer = &pFcb->SectionObjectPointers;
459 FileObject->FsContext = pFcb;
460 FileObject->FsContext2 = pCcb;
461 pFcb->RefCount++;
462
463 IrpContext->Irp->IoStatus.Information = FILE_OPENED;
464 return(STATUS_SUCCESS);
465 }
466
467 /* This filesystem driver only supports volume access */
468 return(STATUS_INVALID_PARAMETER);
469 }
470
471 static NTSTATUS
472 RawFsCreate(IN PRAWFS_IRP_CONTEXT IrpContext)
473 {
474 NTSTATUS Status;
475
476 DPRINT("RawFsCreate(IrpContext %x)\n", IrpContext);
477
478 assert(IrpContext);
479
480 if (RawFsIsRawFileSystemDeviceObject(IrpContext->DeviceObject))
481 {
482 /* DeviceObject represents FileSystem instead of logical volume */
483 DPRINT("RawFsCreate() called with file system\n");
484 IrpContext->Irp->IoStatus.Information = FILE_OPENED;
485 IrpContext->Irp->IoStatus.Status = STATUS_SUCCESS;
486 IoCompleteRequest(IrpContext->Irp, IO_DISK_INCREMENT);
487 RawFsFreeIrpContext(IrpContext);
488 return STATUS_SUCCESS;
489 }
490
491 if (!(IrpContext->Flags & IRPCONTEXT_CANWAIT))
492 {
493 return RawFsQueueRequest(IrpContext);
494 }
495
496 IrpContext->Irp->IoStatus.Information = 0;
497
498 Status = RawFsCreateFile(IrpContext);
499
500 IrpContext->Irp->IoStatus.Status = Status;
501 IoCompleteRequest(IrpContext->Irp,
502 (CCHAR)(NT_SUCCESS(Status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT));
503 RawFsFreeIrpContext(IrpContext);
504
505 return Status;
506 }
507
508 static NTSTATUS
509 RawFsRead(IN PRAWFS_IRP_CONTEXT IrpContext)
510 {
511 DPRINT("RawFsRead(IrpContext %x)\n", IrpContext);
512 UNIMPLEMENTED;
513 return STATUS_NOT_IMPLEMENTED;
514 }
515
516 static NTSTATUS
517 RawFsWrite(IN PRAWFS_IRP_CONTEXT IrpContext)
518 {
519 DPRINT("RawFsWrite(IrpContext %x)\n", IrpContext);
520 UNIMPLEMENTED;
521 return STATUS_NOT_IMPLEMENTED;
522 }
523
524 static NTSTATUS
525 RawFsMount(IN PRAWFS_IRP_CONTEXT IrpContext)
526 {
527 PRAWFS_GLOBAL_DATA GlobalData = NULL;
528 PDEVICE_OBJECT DeviceObject = NULL;
529 PRAWFS_DEVICE_EXTENSION DeviceExt = NULL;
530 PRAWFS_FCB VolumeFcb = NULL;
531 PRAWFS_FCB Fcb = NULL;
532 PARTITION_INFORMATION PartitionInfo;
533 DISK_GEOMETRY DiskGeometry;
534 LARGE_INTEGER VolumeSize;
535 NTSTATUS Status;
536 ULONG Size;
537
538 DPRINT("RawFsMount(IrpContext %x)\n", IrpContext);
539
540 assert(IrpContext);
541
542 if (!RawFsIsRawFileSystemDeviceObject(IrpContext->DeviceObject))
543 {
544 Status = STATUS_INVALID_DEVICE_REQUEST;
545 DPRINT("Not for me\n");
546 goto ByeBye;
547 }
548
549 GlobalData = (PRAWFS_GLOBAL_DATA) IrpContext->DeviceObject->DeviceExtension;
550
551 Status = IoCreateDevice(GlobalData->DriverObject,
552 sizeof(RAWFS_DEVICE_EXTENSION),
553 NULL,
554 FILE_DEVICE_FILE_SYSTEM,
555 0,
556 FALSE,
557 &DeviceObject);
558 if (!NT_SUCCESS(Status))
559 {
560 goto ByeBye;
561 }
562
563 DeviceObject->Flags |= DO_DIRECT_IO;
564 DeviceExt = (PVOID) DeviceObject->DeviceExtension;
565 RtlZeroMemory(DeviceExt, sizeof(RAWFS_DEVICE_EXTENSION));
566
567 /* Use same vpb as device disk */
568 DeviceObject->Vpb = IrpContext->Stack->Parameters.MountVolume.DeviceObject->Vpb;
569 DeviceExt->StorageDevice = IrpContext->Stack->Parameters.MountVolume.DeviceObject;
570 DeviceExt->StorageDevice->Vpb->DeviceObject = DeviceObject;
571 DeviceExt->StorageDevice->Vpb->RealDevice = DeviceExt->StorageDevice;
572 DeviceExt->StorageDevice->Vpb->Flags |= VPB_MOUNTED;
573 DeviceObject->StackSize = DeviceExt->StorageDevice->StackSize + 1;
574 DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
575
576 KeInitializeSpinLock(&DeviceExt->FcbListLock);
577 InitializeListHead(&DeviceExt->FcbListHead);
578
579 /* First try getting harddisk geometry then try getting CD-ROM geometry */
580 Size = sizeof(DISK_GEOMETRY);
581 Status = RawFsBlockDeviceIoControl(
582 IrpContext->Stack->Parameters.MountVolume.DeviceObject,
583 IOCTL_DISK_GET_DRIVE_GEOMETRY,
584 NULL,
585 0,
586 &DiskGeometry,
587 &Size);
588 if (!NT_SUCCESS(Status))
589 {
590 DPRINT("RawFsBlockDeviceIoControl failed with status 0x%.08x\n", Status);
591 goto ByeBye;
592 }
593 if (DiskGeometry.MediaType == FixedMedia)
594 {
595 // We have found a hard disk
596 Size = sizeof(PARTITION_INFORMATION);
597 Status = RawFsBlockDeviceIoControl(
598 IrpContext->Stack->Parameters.MountVolume.DeviceObject,
599 IOCTL_DISK_GET_PARTITION_INFO,
600 NULL,
601 0,
602 &PartitionInfo,
603 &Size);
604 if (!NT_SUCCESS(Status))
605 {
606 DPRINT("RawFsBlockDeviceIoControl() failed (%x)\n", Status);
607 goto ByeBye;
608 }
609 #ifndef NDEBUG
610 DbgPrint("Partition Information:\n");
611 DbgPrint("StartingOffset %u\n", PartitionInfo.StartingOffset.QuadPart);
612 DbgPrint("PartitionLength %u\n", PartitionInfo.PartitionLength.QuadPart);
613 DbgPrint("HiddenSectors %u\n", PartitionInfo.HiddenSectors);
614 DbgPrint("PartitionNumber %u\n", PartitionInfo.PartitionNumber);
615 DbgPrint("PartitionType %u\n", PartitionInfo.PartitionType);
616 DbgPrint("BootIndicator %u\n", PartitionInfo.BootIndicator);
617 DbgPrint("RecognizedPartition %u\n", PartitionInfo.RecognizedPartition);
618 DbgPrint("RewritePartition %u\n", PartitionInfo.RewritePartition);
619 #endif
620 VolumeSize.QuadPart = PartitionInfo.PartitionLength.QuadPart;
621 }
622 else if (DiskGeometry.MediaType > Unknown && DiskGeometry.MediaType <= RemovableMedia)
623 {
624 Status = STATUS_UNRECOGNIZED_VOLUME;
625 goto ByeBye;
626 }
627
628 VolumeFcb = RawFsNewFCB(GlobalData);
629 if (VolumeFcb == NULL)
630 {
631 Status = STATUS_INSUFFICIENT_RESOURCES;
632 goto ByeBye;
633 }
634
635 VolumeFcb->Flags = FCB_IS_VOLUME;
636 VolumeFcb->RFCB.FileSize.QuadPart = VolumeSize.QuadPart;
637 VolumeFcb->RFCB.ValidDataLength.QuadPart = VolumeFcb->RFCB.FileSize.QuadPart;
638 VolumeFcb->RFCB.AllocationSize.QuadPart = VolumeFcb->RFCB.FileSize.QuadPart;
639 DeviceExt->VolumeFcb = VolumeFcb;
640
641 KeEnterCriticalRegion();
642 ExAcquireResourceExclusiveLite(&GlobalData->VolumeListLock, TRUE);
643 InsertHeadList(&GlobalData->VolumeListHead, &DeviceExt->VolumeListEntry);
644 ExReleaseResourceLite(&GlobalData->VolumeListLock);
645 KeLeaveCriticalRegion();
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 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED, Status, 0, 0, 0);
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 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED, Status, 0, 0, 0);
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 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED, Status, 0, 0, 0);
930 return(Status);
931 }
932 DeviceData = TapeDeviceObject->DeviceExtension;
933 RtlZeroMemory (DeviceData, sizeof(RAWFS_GLOBAL_DATA));
934 DeviceData->DriverObject = DriverObject;
935 DeviceData->DeviceObject = TapeDeviceObject;
936 TapeDeviceObject->Flags |= DO_DIRECT_IO;
937
938
939 DriverObject->MajorFunction[IRP_MJ_CLOSE] = (PDRIVER_DISPATCH) RawFsBuildRequest;
940 DriverObject->MajorFunction[IRP_MJ_CREATE] = (PDRIVER_DISPATCH) RawFsBuildRequest;
941 DriverObject->MajorFunction[IRP_MJ_READ] = (PDRIVER_DISPATCH) RawFsBuildRequest;
942 DriverObject->MajorFunction[IRP_MJ_WRITE] = (PDRIVER_DISPATCH) RawFsBuildRequest;
943 DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = (PDRIVER_DISPATCH) RawFsBuildRequest;
944 DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] = (PDRIVER_DISPATCH) RawFsBuildRequest;
945 DriverObject->MajorFunction[IRP_MJ_SET_INFORMATION] = (PDRIVER_DISPATCH) RawFsBuildRequest;
946 DriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL] = (PDRIVER_DISPATCH) RawFsBuildRequest;
947 DriverObject->MajorFunction[IRP_MJ_QUERY_VOLUME_INFORMATION] = (PDRIVER_DISPATCH) RawFsBuildRequest;
948 DriverObject->MajorFunction[IRP_MJ_SET_VOLUME_INFORMATION] = (PDRIVER_DISPATCH) RawFsBuildRequest;
949 DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = (PDRIVER_DISPATCH) RawFsShutdown;
950 DriverObject->MajorFunction[IRP_MJ_LOCK_CONTROL] = (PDRIVER_DISPATCH) RawFsBuildRequest;
951 DriverObject->MajorFunction[IRP_MJ_CLEANUP] = (PDRIVER_DISPATCH) RawFsBuildRequest;
952 DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = (PDRIVER_DISPATCH) RawFsBuildRequest;
953 DriverObject->DriverUnload = NULL;
954
955 ExInitializeNPagedLookasideList(&IrpContextLookasideList,
956 NULL, NULL, 0, sizeof(RAWFS_IRP_CONTEXT), TAG_IRP, 0);
957
958
959 IoRegisterFileSystem(DiskDeviceObject);
960 IoRegisterFileSystem(CdromDeviceObject);
961 IoRegisterFileSystem(TapeDeviceObject);
962
963 return STATUS_SUCCESS;
964 }
965
966 /* EOF */