Add .keep guard files in order to restore lost but empty directories we had with...
[reactos.git] / drivers / filesystems / ext2 / src / fsctrl.c
1 /*************************************************************************
2 *
3 * File: fsctrl.c
4 *
5 * Module: Ext2 File System Driver (Kernel mode execution only)
6 *
7 * Description:
8 * Contains code to handle the various File System Control calls.
9 *
10 * Author: Manoj Paul Joseph
11 *
12 *
13 *************************************************************************/
14
15
16
17 #include "ext2fsd.h"
18
19
20
21 // define the file specific bug-check id
22 #define EXT2_BUG_CHECK_ID EXT2_FILE_FILE_CONTROL
23 #define DEBUG_LEVEL (DEBUG_TRACE_FSCTRL)
24
25
26 NTSTATUS
27 Ext2MountVolume(
28 IN PIRP Irp,
29 IN PIO_STACK_LOCATION IrpSp );
30
31 NTSTATUS
32 Ext2GetPartitionInfo(
33 IN PDEVICE_OBJECT TargetDeviceObject,
34 IN PPARTITION_INFORMATION PartitionInformation
35 );
36
37 NTSTATUS
38 Ext2GetDriveLayout(
39 IN PDEVICE_OBJECT TargetDeviceObject,
40 IN PDRIVE_LAYOUT_INFORMATION DriveLayoutInformation,
41 IN int BufferSize
42 );
43
44 BOOLEAN
45 Ext2PerformVerifyDiskRead(
46 IN PDEVICE_OBJECT TargetDeviceObject,
47 IN PVOID Buffer,
48 IN LONGLONG Lbo,
49 IN ULONG NumberOfBytesToRead
50 );
51
52 NTSTATUS Ext2UserFileSystemRequest(
53 IN PIRP Irp,
54 IN PIO_STACK_LOCATION IrpSp );
55
56
57 /*************************************************************************
58 *
59 * Function: Ext2FileSystemControl
60 *
61 * Description:
62 * The I/O Manager will invoke this routine to handle a
63 * File System Control IRP
64 *
65 * Expected Interrupt Level (for execution) :
66 *
67 * ???
68 *
69 * Arguments:
70 *
71 * DeviceObject - Supplies the volume device object where the
72 * file exists
73 *
74 * Irp - Supplies the Irp being processed
75 *
76 *
77 * Return Value:
78 *
79 * NTSTATUS - The FSD status for the IRP
80 *
81 *************************************************************************/
82 NTSTATUS NTAPI
83 Ext2FileSystemControl(
84 IN PDEVICE_OBJECT DeviceObject,
85 IN PIRP Irp
86 )
87 {
88
89 NTSTATUS Status = STATUS_SUCCESS;
90 PIO_STACK_LOCATION IrpSp;
91
92 DebugTrace(DEBUG_TRACE_IRP_ENTRY, "File System Control IRP Received...", 0);
93
94 // Ext2BreakPoint();
95
96 FsRtlEnterFileSystem();
97
98 ASSERT(DeviceObject);
99 ASSERT(Irp);
100
101 //
102 // Get a pointer to the current Irp stack location
103 //
104 IrpSp = IoGetCurrentIrpStackLocation( Irp );
105
106
107 if( IrpSp->MinorFunction == IRP_MN_MOUNT_VOLUME )
108 {
109 DebugTrace(DEBUG_TRACE_MOUNT, "Mount Request Received...", 0);
110 Status = Ext2MountVolume ( Irp, IrpSp );
111 Ext2CompleteRequest( Irp, Status );
112 }
113 else if( IrpSp->MinorFunction == IRP_MN_USER_FS_REQUEST )
114 {
115 DebugTrace(DEBUG_TRACE_FSCTRL, "IRP_MN_USER_FS_REQUEST received...", 0);
116 Status = Ext2UserFileSystemRequest( Irp, IrpSp );
117 Ext2CompleteRequest( Irp, Status );
118 }
119 else
120 {
121 if( IrpSp->MinorFunction == IRP_MN_VERIFY_VOLUME )
122 {
123 DebugTrace(DEBUG_TRACE_FSCTRL, "IRP_MN_VERIFY_VOLUME received...", 0);
124 }
125 else if( IrpSp->MinorFunction == IRP_MN_LOAD_FILE_SYSTEM )
126 {
127 DebugTrace(DEBUG_TRACE_FSCTRL, "IRP_MN_LOAD_FILE_SYSTEM received...", 0);
128 }
129 else
130 {
131 DebugTrace(DEBUG_TRACE_FSCTRL, "Unknown Minor IRP code received...", 0);
132 }
133
134 Status = STATUS_INVALID_DEVICE_REQUEST;
135 Ext2CompleteRequest( Irp, Status );
136 }
137
138 FsRtlExitFileSystem();
139
140 return Status;
141 }
142
143
144
145 /*************************************************************************
146 *
147 * Function: Ext2MountVolume()
148 *
149 * Description:
150 * This routine verifies and mounts the volume;
151 * Called by FSCTRL IRP handler to attempt a
152 * volume mount.
153 *
154 * Expected Interrupt Level (for execution) :
155 *
156 * IRQL_PASSIVE_LEVEL
157 *
158 *
159 * Arguments:
160 *
161 * Irp - Supplies the Irp being processed
162 * IrpSp - Irp Stack Location pointer
163 *
164 * Return Value:
165 *
166 * NTSTATUS - The Mount status
167 *
168 *************************************************************************/
169 NTSTATUS
170 Ext2MountVolume (
171 IN PIRP Irp,
172 IN PIO_STACK_LOCATION IrpSp )
173 {
174
175 // Volume Parameter Block
176 PVPB PtrVPB;
177
178 // The target device object
179 PDEVICE_OBJECT TargetDeviceObject = NULL;
180
181 // The new volume device object (to be created if partition is Ext2)
182 PDEVICE_OBJECT PtrVolumeDeviceObject = NULL;
183
184 // Return Status
185 NTSTATUS Status = STATUS_UNRECOGNIZED_VOLUME;
186
187 // Number of bytes to read for Volume verification...
188 unsigned long NumberOfBytesToRead = 0;
189
190 // Starting Offset for 'read'
191 LONGLONG StartingOffset = 0;
192
193 // Boot Sector information...
194 PPACKED_BOOT_SECTOR BootSector = NULL;
195
196 // Ext2 Super Block information...
197 PEXT2_SUPER_BLOCK SuperBlock = NULL;
198
199 // Volume Control Block
200 PtrExt2VCB PtrVCB = NULL;
201
202 // The File Object for the root directory
203 PFILE_OBJECT PtrRootFileObject = NULL;
204
205 // Flag
206 int WeClearedVerifyRequiredBit;
207
208 // Used by a for loop...
209 unsigned int i;
210
211 //
212 LARGE_INTEGER VolumeByteOffset;
213
214 unsigned long LogicalBlockSize = 0;
215
216 // Buffer Control Block
217 PBCB PtrBCB = NULL;
218
219 // Cache Buffer - used for pinned access of volume...
220 PVOID PtrCacheBuffer = NULL;
221
222 PEXT2_GROUP_DESCRIPTOR PtrGroupDescriptor = NULL;
223
224 // Inititalising variables
225
226 PtrVPB = IrpSp->Parameters.MountVolume.Vpb;
227 TargetDeviceObject = IrpSp->Parameters.MountVolume.DeviceObject;
228
229 try
230 {
231 //
232 // 1. Reading in Volume meta data
233 //
234
235 // Temporarily clear the DO_VERIFY_VOLUME Flag
236 WeClearedVerifyRequiredBit = 0;
237 if ( Ext2IsFlagOn( PtrVPB->RealDevice->Flags, DO_VERIFY_VOLUME ) )
238 {
239 Ext2ClearFlag( PtrVPB->RealDevice->Flags, DO_VERIFY_VOLUME );
240 WeClearedVerifyRequiredBit = 1;
241 }
242
243 // Allocating memory for reading in Boot Sector...
244 NumberOfBytesToRead = Ext2Align( sizeof( EXT2_SUPER_BLOCK ), TargetDeviceObject->SectorSize );
245 BootSector = Ext2AllocatePool( PagedPool, NumberOfBytesToRead );
246 RtlZeroMemory( BootSector, NumberOfBytesToRead );
247
248 // Reading in Boot Sector
249 StartingOffset = 0L;
250 Ext2PerformVerifyDiskRead ( TargetDeviceObject,
251 BootSector, StartingOffset, NumberOfBytesToRead );
252
253 // Reject a volume that contains fat artifacts
254
255 DebugTrace(DEBUG_TRACE_MOUNT, "OEM[%s]", BootSector->Oem);
256 if (BootSector->Oem[0])
257 {
258 try_return();
259 }
260
261 // Allocating memory for reading in Super Block...
262
263 SuperBlock = Ext2AllocatePool( PagedPool, NumberOfBytesToRead );
264 RtlZeroMemory( SuperBlock, NumberOfBytesToRead );
265 StartingOffset = 1024;
266
267 // Reading in the Super Block...
268 Ext2PerformVerifyDiskRead ( TargetDeviceObject,
269 SuperBlock, StartingOffset, NumberOfBytesToRead );
270
271 // Resetting the DO_VERIFY_VOLUME Flag
272 if( WeClearedVerifyRequiredBit )
273 {
274 PtrVPB->RealDevice->Flags |= DO_VERIFY_VOLUME;
275 }
276
277 // Verifying the Super Block..
278 if( SuperBlock->s_magic == EXT2_SUPER_MAGIC )
279 {
280 //
281 // Found a valid super block.
282 // No more tests for now.
283 // Assuming that this is an ext2 partition...
284 // Going ahead with mount.
285 //
286 DebugTrace(DEBUG_TRACE_MOUNT, "Valid Ext2 partition detected\nMounting %s...", SuperBlock->s_volume_name);
287 //
288 // 2. Creating a volume device object
289 //
290 if (!NT_SUCCESS( IoCreateDevice(
291 Ext2GlobalData.Ext2DriverObject, // (This) Driver object
292 Ext2QuadAlign( sizeof(Ext2VCB) ), // Device Extension
293 NULL, // Device Name - no name ;)
294 FILE_DEVICE_DISK_FILE_SYSTEM, // Disk File System
295 0, // DeviceCharacteristics
296 FALSE, // Not an exclusive device
297 (PDEVICE_OBJECT *)&PtrVolumeDeviceObject)) // The Volume Device Object
298 )
299 {
300 try_return();
301 }
302
303 //
304 // Our alignment requirement is the larger of the processor alignment requirement
305 // already in the volume device object and that in the TargetDeviceObject
306 //
307
308 if (TargetDeviceObject->AlignmentRequirement > PtrVolumeDeviceObject->AlignmentRequirement)
309 {
310 PtrVolumeDeviceObject->AlignmentRequirement = TargetDeviceObject->AlignmentRequirement;
311 }
312
313 //
314 // Clearing the Device Initialising Flag
315 //
316 Ext2ClearFlag( PtrVolumeDeviceObject->Flags, DO_DEVICE_INITIALIZING);
317
318
319 //
320 // Setting the Stack Size for the newly created Volume Device Object
321 //
322 PtrVolumeDeviceObject->StackSize = (CCHAR)(TargetDeviceObject->StackSize + 1);
323
324
325 //
326 // 3. Creating the link between Target Device Object
327 // and the Volume Device Object via the Volume Parameter Block
328 //
329 PtrVPB->DeviceObject = PtrVolumeDeviceObject;
330
331 // Remembring the Volume parameters in the VPB bock
332 for( i = 0; i < 16 ; i++ )
333 {
334 PtrVPB->VolumeLabel[i] = SuperBlock->s_volume_name[i];
335 if( SuperBlock->s_volume_name[i] == 0 )
336 break;
337 }
338 PtrVPB->VolumeLabelLength = i * 2;
339 PtrVPB->SerialNumber = ((ULONG*)SuperBlock->s_uuid)[0];
340
341 //
342 // 4. Initialise the Volume Comtrol Block
343 //
344 {
345 LARGE_INTEGER AllocationSize;
346
347 AllocationSize .QuadPart =
348 ( EXT2_MIN_BLOCK_SIZE << SuperBlock->s_log_block_size ) *
349 SuperBlock->s_blocks_count;
350
351 Ext2InitializeVCB(
352 PtrVolumeDeviceObject,
353 TargetDeviceObject,
354 PtrVPB,
355 &AllocationSize);
356 PtrVCB = (PtrExt2VCB)(PtrVolumeDeviceObject->DeviceExtension);
357 ASSERT( PtrVCB );
358 }
359
360 PtrVCB->InodesCount = SuperBlock->s_inodes_count;
361 PtrVCB->BlocksCount = SuperBlock->s_blocks_count;
362 PtrVCB->ReservedBlocksCount = SuperBlock->s_r_blocks_count;
363 PtrVCB->FreeBlocksCount = SuperBlock->s_free_blocks_count;
364 PtrVCB->FreeInodesCount = SuperBlock->s_free_inodes_count;
365 PtrVCB->LogBlockSize = SuperBlock->s_log_block_size;
366 PtrVCB->InodesPerGroup = SuperBlock->s_inodes_per_group;
367 PtrVCB->BlocksPerGroup = SuperBlock->s_blocks_per_group;
368 PtrVCB->NoOfGroups = ( SuperBlock->s_blocks_count - SuperBlock->s_first_data_block
369 + SuperBlock->s_blocks_per_group - 1 )
370 / SuperBlock->s_blocks_per_group;
371 if( SuperBlock->s_rev_level )
372 {
373 PtrVCB->InodeSize = SuperBlock->s_inode_size;
374 }
375 else
376 {
377 PtrVCB->InodeSize = sizeof( EXT2_INODE );
378 }
379
380 PtrVCB->PtrGroupDescriptors = Ext2AllocatePool( NonPagedPool, sizeof( Ext2GroupDescriptors ) * PtrVCB->NoOfGroups );
381
382 RtlZeroMemory( PtrVCB->PtrGroupDescriptors , sizeof( Ext2GroupDescriptors ) * PtrVCB->NoOfGroups );
383
384 //
385 // Attempting to Read in some matadata from the Cache...
386 // using pin access...
387 //
388 LogicalBlockSize = EXT2_MIN_BLOCK_SIZE << PtrVCB->LogBlockSize;
389
390 //
391 // Reading Group Descriptors...
392 //
393 if( PtrVCB->LogBlockSize )
394 {
395 // First block contains the descriptors...
396 VolumeByteOffset.QuadPart = LogicalBlockSize;
397 }
398 else
399 {
400 // Second block contains the descriptors...
401 VolumeByteOffset.QuadPart = LogicalBlockSize * 2;
402 }
403
404 NumberOfBytesToRead = PtrVCB->NoOfGroups * sizeof( struct ext2_group_desc );
405 NumberOfBytesToRead = Ext2Align( NumberOfBytesToRead, LogicalBlockSize );
406
407 if (!CcMapData( PtrVCB->PtrStreamFileObject,
408 &VolumeByteOffset,
409 NumberOfBytesToRead,
410 TRUE,
411 &PtrBCB,
412 &PtrCacheBuffer ))
413 {
414 DebugTrace(DEBUG_TRACE_ERROR, "Cache read failiure while reading in volume meta data", 0);
415 try_return( Status = STATUS_INSUFFICIENT_RESOURCES );
416 }
417 else
418 {
419 //
420 // Saving up Often Used Group Descriptor Information in the VCB...
421 //
422 unsigned int DescIndex ;
423
424 DebugTrace(DEBUG_TRACE_MISC, "Cache hit while reading in volume meta data", 0);
425 PtrGroupDescriptor = (PEXT2_GROUP_DESCRIPTOR )PtrCacheBuffer;
426 for( DescIndex = 0; DescIndex < PtrVCB->NoOfGroups; DescIndex++ )
427 {
428 PtrVCB->PtrGroupDescriptors[ DescIndex ].InodeTablesBlock
429 = PtrGroupDescriptor[ DescIndex ].bg_inode_table;
430
431 PtrVCB->PtrGroupDescriptors[ DescIndex ].InodeBitmapBlock
432 = PtrGroupDescriptor[ DescIndex ].bg_inode_bitmap
433 ;
434 PtrVCB->PtrGroupDescriptors[ DescIndex ].BlockBitmapBlock
435 = PtrGroupDescriptor[ DescIndex ].bg_block_bitmap
436 ;
437 PtrVCB->PtrGroupDescriptors[ DescIndex ].FreeBlocksCount
438 = PtrGroupDescriptor[ DescIndex ].bg_free_blocks_count;
439
440 PtrVCB->PtrGroupDescriptors[ DescIndex ].FreeInodesCount
441 = PtrGroupDescriptor[ DescIndex ].bg_free_inodes_count;
442 }
443 CcUnpinData( PtrBCB );
444 PtrBCB = NULL;
445 }
446
447 //
448 // 5. Creating a Root Directory FCB
449 //
450 PtrRootFileObject = IoCreateStreamFileObject(NULL, TargetDeviceObject );
451 if( !PtrRootFileObject )
452 {
453 try_return();
454 }
455 //
456 // Associate the file stream with the Volume parameter block...
457 // I do it now
458 //
459 PtrRootFileObject->Vpb = PtrVCB->PtrVPB;
460
461 PtrRootFileObject->ReadAccess = TRUE;
462 PtrRootFileObject->WriteAccess = TRUE;
463
464 {
465 PtrExt2ObjectName PtrObjectName;
466 LARGE_INTEGER ZeroSize;
467
468 PtrObjectName = Ext2AllocateObjectName();
469 RtlInitUnicodeString( &PtrObjectName->ObjectName, L"\\" );
470 Ext2CopyWideCharToUnicodeString( &PtrObjectName->ObjectName, L"\\" );
471
472
473 ZeroSize.QuadPart = 0;
474 if ( !NT_SUCCESS( Ext2CreateNewFCB(
475 &PtrVCB->PtrRootDirectoryFCB, // Root FCB
476 ZeroSize, // AllocationSize,
477 ZeroSize, // EndOfFile,
478 PtrRootFileObject, // The Root Dircetory File Object
479 PtrVCB,
480 PtrObjectName ) ) )
481 {
482 try_return();
483 }
484
485
486 PtrVCB->PtrRootDirectoryFCB->FCBFlags |= EXT2_FCB_DIRECTORY | EXT2_FCB_ROOT_DIRECTORY;
487
488
489 }
490
491 PtrVCB->PtrRootDirectoryFCB->DcbFcb.Dcb.PtrDirFileObject = PtrRootFileObject;
492 PtrVCB->PtrRootDirectoryFCB->INodeNo = EXT2_ROOT_INO;
493 PtrRootFileObject->SectionObjectPointer = &(PtrVCB->PtrRootDirectoryFCB->NTRequiredFCB.SectionObject);
494 RtlInitUnicodeString( &PtrRootFileObject->FileName, L"\\" );
495
496 Ext2InitializeFCBInodeInfo( PtrVCB->PtrRootDirectoryFCB );
497
498 //
499 // Initiating caching for root directory...
500 //
501
502 CcInitializeCacheMap(PtrRootFileObject,
503 (PCC_FILE_SIZES)(&(PtrVCB->PtrRootDirectoryFCB->NTRequiredFCB.CommonFCBHeader.AllocationSize)),
504 TRUE, // We will utilize pin access for directories
505 &(Ext2GlobalData.CacheMgrCallBacks), // callbacks
506 PtrVCB->PtrRootDirectoryFCB ); // The context used in callbacks
507
508
509 //
510 // 6. Update the VCB Flags
511 //
512 PtrVCB->VCBFlags |= EXT2_VCB_FLAGS_VOLUME_MOUNTED ; // | EXT2_VCB_FLAGS_VOLUME_READ_ONLY;
513
514
515 //
516 // 7. Mount Success
517 //
518 Status = STATUS_SUCCESS;
519
520 {
521 //
522 // This block is for testing....
523 // To be removed...
524
525 /*
526 EXT2_INODE Inode ;
527 Ext2ReadInode( PtrVCB, 100, &Inode );
528 DebugTrace( DEBUG_TRACE_MISC, "Inode size= %lX [FS Ctrl]", Inode.i_size );
529 Ext2DeallocInode( NULL, PtrVCB, 0xfb6 );
530 */
531 }
532
533 // ObDereferenceObject( TargetDeviceObject );
534 }
535 else
536 {
537 DebugTrace(DEBUG_TRACE_MOUNT, "Failing mount. Partition not Ext2...", 0);
538 }
539
540 try_exit: NOTHING;
541 }
542 finally
543 {
544 // Freeing Allocated Memory...
545 if( SuperBlock != NULL )
546 {
547 DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [FS Ctrl]", SuperBlock );
548 ExFreePool( SuperBlock );
549 }
550 if( BootSector != NULL )
551 {
552 DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [FS Ctrl]", BootSector);
553 ExFreePool( BootSector );
554 }
555
556 // start unwinding if we were unsuccessful
557 if (!NT_SUCCESS( Status ))
558 {
559
560 }
561 }
562
563 return Status;
564 }
565
566 /*************************************************************************
567 *
568 * Function: Ext2MountVolume()
569 *
570 * Description:
571 * This routine is used for querying the partition information.
572 *
573 * Expected Interrupt Level (for execution) :
574 * IRQL_PASSIVE_LEVEL
575 *
576 * Arguments:
577 *
578 * TargetDeviceObject - The target of the query
579 * PartitionInformation - Receives the result of the query
580 *
581 * Return Value:
582 *
583 * NTSTATUS - The return status for the operation
584 *
585 *************************************************************************/
586 NTSTATUS
587 Ext2GetPartitionInfo (
588 IN PDEVICE_OBJECT TargetDeviceObject,
589 IN PPARTITION_INFORMATION PartitionInformation
590 )
591 {
592 PIRP Irp;
593 KEVENT *PtrEvent = NULL;
594 NTSTATUS Status;
595 IO_STATUS_BLOCK Iosb;
596
597 //
598 // Query the partition table
599 //
600 PtrEvent = ( KEVENT * )Ext2AllocatePool( NonPagedPool, Ext2QuadAlign( sizeof( KEVENT ) ) );
601
602
603
604
605 KeInitializeEvent( PtrEvent, NotificationEvent, FALSE );
606
607 Irp = IoBuildDeviceIoControlRequest( IOCTL_DISK_GET_PARTITION_INFO,
608 TargetDeviceObject,
609 NULL,
610 0,
611 PartitionInformation,
612 sizeof(PARTITION_INFORMATION),
613 FALSE,
614 PtrEvent,
615 &Iosb );
616
617 if ( Irp == NULL )
618 {
619 DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [FS Ctrl]", PtrEvent);
620 ExFreePool( PtrEvent );
621 return 0;
622 }
623
624 Status = IoCallDriver( TargetDeviceObject, Irp );
625
626 if ( Status == STATUS_PENDING ) {
627
628 (VOID) KeWaitForSingleObject( PtrEvent,
629 Executive,
630 KernelMode,
631 FALSE,
632 (PLARGE_INTEGER)NULL );
633
634 Status = Iosb.Status;
635 }
636 DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [FS Ctrl]", PtrEvent);
637 ExFreePool( PtrEvent );
638 return Status;
639 }
640
641 /*************************************************************************
642 *
643 * Function: Ext2MountVolume()
644 *
645 * Description:
646 * This routine is used for querying the Drive Layout Information.
647 *
648 * Expected Interrupt Level (for execution) :
649 * IRQL_PASSIVE_LEVEL
650 *
651 * Arguments:
652 *
653 * TargetDeviceObject - The target of the query
654 * PartitionInformation - Receives the result of the query
655 *
656 * Return Value:
657 *
658 * NTSTATUS - The return status for the operation
659 *
660 *************************************************************************/
661 NTSTATUS Ext2GetDriveLayout (
662 IN PDEVICE_OBJECT TargetDeviceObject,
663 IN PDRIVE_LAYOUT_INFORMATION DriveLayoutInformation,
664 IN int BufferSize
665 )
666 {
667 PIRP Irp;
668 KEVENT *PtrEvent = NULL;
669 NTSTATUS Status;
670 IO_STATUS_BLOCK Iosb;
671
672 //
673 // Query the partition table
674 //
675 PtrEvent = ( KEVENT * )Ext2AllocatePool( NonPagedPool, Ext2QuadAlign( sizeof( KEVENT ) ) );
676 KeInitializeEvent( PtrEvent, NotificationEvent, FALSE );
677 Irp = IoBuildDeviceIoControlRequest( IOCTL_DISK_GET_DRIVE_LAYOUT,
678 TargetDeviceObject,
679 NULL,
680 0,
681 DriveLayoutInformation,
682 BufferSize,
683 FALSE,
684 PtrEvent,
685 &Iosb );
686
687 if ( Irp == NULL )
688 {
689 DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [FS Ctrl]", PtrEvent);
690 ExFreePool( PtrEvent );
691 return 0;
692 }
693
694 Status = IoCallDriver( TargetDeviceObject, Irp );
695
696 if ( Status == STATUS_PENDING ) {
697
698 (VOID) KeWaitForSingleObject( PtrEvent,
699 Executive,
700 KernelMode,
701 FALSE,
702 (PLARGE_INTEGER)NULL );
703
704 Status = Iosb.Status;
705 }
706 DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [FS Ctrl]", PtrEvent);
707 ExFreePool( PtrEvent );
708 return Status;
709 }
710
711
712 /*************************************************************************
713 *
714 * Function: Ext2MountVolume()
715 *
716 * Description:
717 * This routine is used for performing a verify read...
718 *
719 * Expected Interrupt Level (for execution) :
720 * IRQL_PASSIVE_LEVEL
721 *
722 * Arguments:
723 * TargetDeviceObject - The target of the query
724 * PartitionInformation - Receives the result of the query
725 *
726 * Return Value:
727 * NTSTATUS - The return status for the operation
728 *
729 *************************************************************************/
730 BOOLEAN Ext2PerformVerifyDiskRead(
731 IN PDEVICE_OBJECT TargetDeviceObject,
732 IN PVOID Buffer,
733 IN LONGLONG Lbo,
734 IN ULONG NumberOfBytesToRead )
735 {
736 KEVENT Event;
737 PIRP Irp;
738 LARGE_INTEGER ByteOffset;
739 NTSTATUS Status;
740 IO_STATUS_BLOCK Iosb;
741
742 //
743 // Initialize the event we're going to use
744 //
745 KeInitializeEvent( &Event, NotificationEvent, FALSE );
746
747 //
748 // Build the irp for the operation
749 //
750 ByteOffset.QuadPart = Lbo;
751 Irp = IoBuildSynchronousFsdRequest( IRP_MJ_READ,
752 TargetDeviceObject,
753 Buffer,
754 NumberOfBytesToRead,
755 &ByteOffset,
756 &Event,
757 &Iosb );
758
759 if ( Irp == NULL )
760 {
761 Status = FALSE;
762 }
763
764 Ext2SetFlag( IoGetNextIrpStackLocation( Irp )->Flags, SL_OVERRIDE_VERIFY_VOLUME );
765
766 //
767 // Call the device to do the read and wait for it to finish.
768 //
769 Status = IoCallDriver( TargetDeviceObject, Irp );
770 if (Status == STATUS_PENDING)
771 {
772 (VOID)KeWaitForSingleObject( &Event, Executive, KernelMode, FALSE, (PLARGE_INTEGER)NULL );
773 Status = Iosb.Status;
774 }
775
776 ASSERT(Status != STATUS_VERIFY_REQUIRED);
777
778 //
779 // Special case this error code because this probably means we used
780 // the wrong sector size and we want to reject STATUS_WRONG_VOLUME.
781 //
782
783 if (Status == STATUS_INVALID_PARAMETER)
784 {
785 DbgPrint("Ext2PerformVerifyDiskRead Invalid Param\n");
786 return FALSE;
787 }
788
789 if (Status == STATUS_NO_MEDIA_IN_DEVICE)
790 {
791 DebugTrace(DEBUG_TRACE_MOUNT, "NO MEDIA in DEVICE!", 0);
792 return FALSE;
793 }
794
795 //
796 // If it doesn't succeed then either return or raise the error.
797 //
798
799 if (!NT_SUCCESS(Status))
800 {
801 DbgPrint("Ext2PerformVerifyDiskRead Fail Status %x\n",Status);
802 return FALSE;
803 }
804
805 //
806 // And return to our caller
807 //
808 return TRUE;
809 }
810
811 /*************************************************************************
812 *
813 * Function: Ext2UserFileSystemRequest()
814 *
815 * Description:
816 * This routine handles User File System Requests
817 *
818 * Expected Interrupt Level (for execution) :
819 *
820 * IRQL_PASSIVE_LEVEL
821 *
822 *
823 * Arguments:
824 *
825 * Irp - Supplies the Irp being processed
826 * IrpSp - Irp Stack Location pointer
827 *
828 * Return Value: NT_STATUS
829 *
830 *************************************************************************/
831 NTSTATUS Ext2UserFileSystemRequest (
832 IN PIRP Irp,
833 IN PIO_STACK_LOCATION IrpSp )
834 {
835 NTSTATUS Status = STATUS_INVALID_DEVICE_REQUEST;
836 ULONG FsControlCode;
837
838 IrpSp = IoGetCurrentIrpStackLocation( Irp );
839
840 try
841 {
842 #ifdef _GNU_NTIFS_
843 FsControlCode = ((PEXTENDED_IO_STACK_LOCATION)IrpSp)->Parameters.FileSystemControl.FsControlCode;
844 #else
845 FsControlCode = IrpSp->Parameters.FileSystemControl.FsControlCode;
846 #endif
847
848 switch ( FsControlCode )
849 {
850
851 case FSCTL_REQUEST_OPLOCK_LEVEL_1:
852 DebugTrace(DEBUG_TRACE_FSCTRL, "FSCTL_REQUEST_OPLOCK_LEVEL_1", 0);
853 break;
854 case FSCTL_REQUEST_OPLOCK_LEVEL_2:
855 DebugTrace(DEBUG_TRACE_FSCTRL, " FSCTL ", 0);
856 break;
857 case FSCTL_REQUEST_BATCH_OPLOCK:
858 DebugTrace(DEBUG_TRACE_FSCTRL, " FSCTL_REQUEST_OPLOCK_LEVEL_2 ", 0);
859 break;
860 case FSCTL_OPLOCK_BREAK_ACKNOWLEDGE:
861 DebugTrace(DEBUG_TRACE_MISC, " FSCTL_OPLOCK_BREAK_ACKNOWLEDGE ", 0);
862 break;
863 case FSCTL_OPBATCH_ACK_CLOSE_PENDING:
864 DebugTrace(DEBUG_TRACE_FSCTRL, " FSCTL_OPBATCH_ACK_CLOSE_PENDING ", 0);
865 break;
866 case FSCTL_OPLOCK_BREAK_NOTIFY:
867 DebugTrace(DEBUG_TRACE_FSCTRL, " FSCTL_OPLOCK_BREAK_NOTIFY ", 0);
868 break;
869 case FSCTL_OPLOCK_BREAK_ACK_NO_2:
870 DebugTrace(DEBUG_TRACE_FSCTRL, " FSCTL_OPLOCK_BREAK_ACK_NO_2 ", 0);
871 break;
872 case FSCTL_LOCK_VOLUME:
873 DebugTrace(DEBUG_TRACE_FSCTRL, " FSCTL_LOCK_VOLUME ", 0);
874 break;
875 case FSCTL_UNLOCK_VOLUME:
876 DebugTrace(DEBUG_TRACE_FSCTRL, " FSCTL_UNLOCK_VOLUME ", 0);
877 break;
878 case FSCTL_DISMOUNT_VOLUME:
879 DebugTrace(DEBUG_TRACE_FSCTRL, " FSCTL_DISMOUNT_VOLUME ", 0);
880 break;
881 case FSCTL_MARK_VOLUME_DIRTY:
882 DebugTrace(DEBUG_TRACE_FSCTRL, " FSCTL_MARK_VOLUME_DIRTY ", 0);
883 break;
884 case FSCTL_IS_VOLUME_DIRTY:
885 DebugTrace(DEBUG_TRACE_FSCTRL, " FSCTL_IS_VOLUME_DIRTY ", 0);
886 break;
887 case FSCTL_IS_VOLUME_MOUNTED:
888 Status = Ext2VerifyVolume(Irp, IrpSp );
889 DebugTrace(DEBUG_TRACE_FSCTRL, " FSCTL_IS_VOLUME_MOUNTED ", 0);
890 break;
891 case FSCTL_IS_PATHNAME_VALID:
892 DebugTrace(DEBUG_TRACE_FSCTRL, " FSCTL_IS_PATHNAME_VALID ", 0);
893 break;
894 case FSCTL_QUERY_RETRIEVAL_POINTERS:
895 DebugTrace(DEBUG_TRACE_FSCTRL, " FSCTL_QUERY_RETRIEVAL_POINTERS ", 0);
896 break;
897 case FSCTL_QUERY_FAT_BPB:
898 DebugTrace(DEBUG_TRACE_FSCTRL, " FSCTL_QUERY_FAT_BPB ", 0);
899 break;
900 case FSCTL_FILESYSTEM_GET_STATISTICS:
901 DebugTrace(DEBUG_TRACE_FSCTRL, " FSCTL_FILESYSTEM_GET_STATISTICS ", 0);
902 break;
903 case FSCTL_GET_VOLUME_BITMAP:
904 DebugTrace(DEBUG_TRACE_FSCTRL, " FSCTL_GET_VOLUME_BITMAP ", 0);
905 break;
906 case FSCTL_GET_RETRIEVAL_POINTERS:
907 DebugTrace(DEBUG_TRACE_FSCTRL, " FSCTL_GET_RETRIEVAL_POINTERS ", 0);
908 break;
909 case FSCTL_MOVE_FILE:
910 DebugTrace(DEBUG_TRACE_FSCTRL, " FSCTL_MOVE_FILE ", 0);
911 break;
912 case FSCTL_ALLOW_EXTENDED_DASD_IO:
913 DebugTrace(DEBUG_TRACE_FSCTRL, " FSCTL_ALLOW_EXTENDED_DASD_IO ", 0);
914 break;
915 default :
916 DebugTrace(DEBUG_TRACE_FSCTRL, "Unknown FSCTRL !!!", 0);
917
918 }
919 }
920 finally
921 {
922
923 }
924 return Status;
925 }
926
927
928
929 NTSTATUS NTAPI Ext2VerifyVolume (
930 IN PIRP Irp,
931 IN PIO_STACK_LOCATION IrpSp )
932 {
933
934 PVPB PtrVPB;
935
936 PtrVPB = IrpSp->Parameters.VerifyVolume.Vpb;
937 if( IrpSp->FileObject )
938 {
939 PtrVPB = IrpSp->FileObject->Vpb;
940 }
941 if( !PtrVPB )
942 {
943 PtrVPB = IrpSp->Parameters.VerifyVolume.Vpb;
944 }
945
946 if( !PtrVPB )
947 {
948 return STATUS_WRONG_VOLUME;
949 }
950
951
952 if ( Ext2IsFlagOn( PtrVPB->RealDevice->Flags, DO_VERIFY_VOLUME ) )
953 {
954 //
955 // Not doing a verify!
956 // Just acting as if everyting is fine!
957 // THis should do for now
958 //
959 Ext2ClearFlag( PtrVPB->RealDevice->Flags, DO_VERIFY_VOLUME );
960
961 }
962 return STATUS_SUCCESS;
963 }