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