2 * COPYRIGHT: GNU GENERAL PUBLIC LICENSE VERSION 2
3 * PROJECT: ReiserFs file system driver for Windows NT/2000/XP/Vista.
6 * PROGRAMMER: Mark Piper, Matt Wu, Bo Brantén.
11 /* INCLUDES *****************************************************************/
15 /* GLOBALS ***************************************************************/
17 extern PRFSD_GLOBAL RfsdGlobal
;
19 /* DEFINITIONS *************************************************************/
21 typedef struct _RFSD_RW_CONTEXT
{
27 } RFSD_RW_CONTEXT
, *PRFSD_RW_CONTEXT
;
30 IO_COMPLETION_ROUTINE RfsdReadWriteBlockSyncCompletionRoutine
;
31 IO_COMPLETION_ROUTINE RfsdReadWriteBlockAsyncCompletionRoutine
;
32 IO_COMPLETION_ROUTINE RfsdMediaEjectControlCompletion
;
36 RfsdReadWriteBlockSyncCompletionRoutine (
37 IN PDEVICE_OBJECT DeviceObject
,
42 RfsdReadWriteBlockAsyncCompletionRoutine (
43 IN PDEVICE_OBJECT DeviceObject
,
48 RfsdMediaEjectControlCompletion (
49 IN PDEVICE_OBJECT DeviceObject
,
54 #pragma alloc_text(PAGE, RfsdLockUserBuffer)
55 #pragma alloc_text(PAGE, RfsdGetUserBuffer)
56 #pragma alloc_text(PAGE, RfsdReadSync)
57 #pragma alloc_text(PAGE, RfsdReadDisk)
58 #pragma alloc_text(PAGE, RfsdDiskIoControl)
59 #pragma alloc_text(PAGE, RfsdReadWriteBlocks)
60 #pragma alloc_text(PAGE, RfsdMediaEjectControl)
61 #pragma alloc_text(PAGE, RfsdDiskShutDown)
64 /* FUNCTIONS ***************************************************************/
67 RfsdLockUserBuffer (IN PIRP Irp
,
69 IN LOCK_OPERATION Operation
)
77 if (Irp
->MdlAddress
!= NULL
) {
79 return STATUS_SUCCESS
;
82 IoAllocateMdl(Irp
->UserBuffer
, Length
, FALSE
, FALSE
, Irp
);
84 if (Irp
->MdlAddress
== NULL
) {
86 return STATUS_INSUFFICIENT_RESOURCES
;
91 MmProbeAndLockPages(Irp
->MdlAddress
, Irp
->RequestorMode
, Operation
);
93 Status
= STATUS_SUCCESS
;
94 } _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER
) {
96 IoFreeMdl(Irp
->MdlAddress
);
98 Irp
->MdlAddress
= NULL
;
102 Status
= STATUS_INVALID_USER_BUFFER
;
109 RfsdGetUserBuffer (IN PIRP Irp
)
115 if (Irp
->MdlAddress
) {
117 #if (_WIN32_WINNT >= 0x0500)
118 return MmGetSystemAddressForMdlSafe(Irp
->MdlAddress
, NormalPagePriority
);
120 return MmGetSystemAddressForMdl(Irp
->MdlAddress
);
124 return Irp
->UserBuffer
;
129 RfsdReadWriteBlockSyncCompletionRoutine (
130 IN PDEVICE_OBJECT DeviceObject
,
134 PRFSD_RW_CONTEXT pContext
= (PRFSD_RW_CONTEXT
)Context
;
136 if (!NT_SUCCESS( Irp
->IoStatus
.Status
)) {
137 DbgBreak(); // [mark]
138 pContext
->MasterIrp
->IoStatus
= Irp
->IoStatus
;
141 IoFreeMdl( Irp
->MdlAddress
);
144 if (InterlockedDecrement(&pContext
->Blocks
) == 0) {
146 pContext
->MasterIrp
->IoStatus
.Information
= 0;
148 if (NT_SUCCESS(pContext
->MasterIrp
->IoStatus
.Status
)) {
150 pContext
->MasterIrp
->IoStatus
.Information
=
154 KeSetEvent( &pContext
->Event
, 0, FALSE
);
157 UNREFERENCED_PARAMETER( DeviceObject
);
159 return STATUS_MORE_PROCESSING_REQUIRED
;
163 RfsdReadWriteBlockAsyncCompletionRoutine (
164 IN PDEVICE_OBJECT DeviceObject
,
169 PRFSD_RW_CONTEXT pContext
= (PRFSD_RW_CONTEXT
)Context
;
171 if (!NT_SUCCESS( Irp
->IoStatus
.Status
)) {
172 DbgBreak(); // [mark]
173 pContext
->MasterIrp
->IoStatus
= Irp
->IoStatus
;
176 if (InterlockedDecrement(&pContext
->Blocks
) == 0) {
178 pContext
->MasterIrp
->IoStatus
.Information
= 0;
180 if (NT_SUCCESS(pContext
->MasterIrp
->IoStatus
.Status
)) {
182 pContext
->MasterIrp
->IoStatus
.Information
=
186 IoMarkIrpPending( pContext
->MasterIrp
);
188 ExFreePool(pContext
);
191 UNREFERENCED_PARAMETER( DeviceObject
);
193 return STATUS_SUCCESS
;
196 // Looks like this is really just getting an MDL (memory descriptor list) from the MM and doing its business...
197 // ... but IoCallDriver is what will actually read from the disk device to furnish non-chached or paging IO operations!
198 // NOTE: It is vital that IoCallDriver use sector-aligned offset and length (otherwise, 0xc000000d = STATUS_INVALID_PARAMETER) will result!
201 IN PRFSD_IRP_CONTEXT IrpContext
,
203 IN PRFSD_BDL RfsdBDL
, // The block-description list
204 IN ULONG Length
, // Length of data to read
205 IN ULONG Count
, // Count of blocks inside the BDL
210 PIRP MasterIrp
= IrpContext
->Irp
;
211 PIO_STACK_LOCATION IrpSp
;
212 NTSTATUS Status
= STATUS_SUCCESS
;
213 PRFSD_RW_CONTEXT pContext
= NULL
;
215 BOOLEAN bBugCheck
= FALSE
;
223 pContext
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(RFSD_RW_CONTEXT
), RFSD_POOL_TAG
);
226 Status
= STATUS_INSUFFICIENT_RESOURCES
;
230 RtlZeroMemory(pContext
, sizeof(RFSD_RW_CONTEXT
));
232 pContext
->Wait
= IrpContext
->IsSynchronous
;
233 pContext
->MasterIrp
= MasterIrp
;
234 pContext
->Blocks
= Count
;
235 pContext
->Length
= 0;
237 if (pContext
->Wait
) {
238 KeInitializeEvent(&(pContext
->Event
), NotificationEvent
, FALSE
);
241 for (i
= 0; i
< Count
; i
++) {
243 Irp
= IoMakeAssociatedIrp(
245 (CCHAR
)(Vcb
->TargetDeviceObject
->StackSize
+ 1) );
248 Status
= STATUS_INSUFFICIENT_RESOURCES
;
250 ExFreePool(pContext
);
256 Mdl
= IoAllocateMdl( (PCHAR
)MasterIrp
->UserBuffer
+
264 Status
= STATUS_INSUFFICIENT_RESOURCES
;
266 ExFreePool(pContext
);
272 IoBuildPartialMdl( MasterIrp
->MdlAddress
,
274 (PCHAR
)MasterIrp
->UserBuffer
+ RfsdBDL
[i
].Offset
,
277 IoSetNextIrpStackLocation( Irp
);
278 IrpSp
= IoGetCurrentIrpStackLocation( Irp
);
281 IrpSp
->MajorFunction
= IrpContext
->MajorFunction
;
282 IrpSp
->Parameters
.Read
.Length
= RfsdBDL
[i
].Length
;
283 IrpSp
->Parameters
.Read
.ByteOffset
.QuadPart
= RfsdBDL
[i
].Lba
;
285 IoSetCompletionRoutine(
287 ((IrpContext
->IsSynchronous
) ?
288 (&RfsdReadWriteBlockSyncCompletionRoutine
) :
289 (&RfsdReadWriteBlockAsyncCompletionRoutine
)),
295 IrpSp
= IoGetNextIrpStackLocation( Irp
);
297 IrpSp
->MajorFunction
= IrpContext
->MajorFunction
;
298 IrpSp
->Parameters
.Read
.Length
= RfsdBDL
[i
].Length
;
299 IrpSp
->Parameters
.Read
.ByteOffset
.QuadPart
= RfsdBDL
[i
].Lba
;
302 SetFlag( IrpSp
->Flags
, SL_OVERRIDE_VERIFY_VOLUME
);
305 RfsdBDL
[i
].Irp
= Irp
;
308 MasterIrp
->AssociatedIrp
.IrpCount
= Count
;
310 if (IrpContext
->IsSynchronous
) {
311 MasterIrp
->AssociatedIrp
.IrpCount
+= 1;
314 pContext
->Length
= Length
;
318 for (i
= 0; i
< Count
; i
++) {
319 Status
= IoCallDriver ( Vcb
->TargetDeviceObject
,
323 if (IrpContext
->IsSynchronous
) {
324 KeWaitForSingleObject( &(pContext
->Event
),
325 Executive
, KernelMode
, FALSE
, NULL
);
327 KeClearEvent( &(pContext
->Event
) );
332 if (IrpContext
->IsSynchronous
) {
334 Status
= MasterIrp
->IoStatus
.Status
;
337 ExFreePool(pContext
);
340 IrpContext
->Irp
= NULL
;
341 Status
= STATUS_PENDING
;
344 if (_SEH2_AbnormalTermination()) {
346 RfsdBugCheck(RFSD_BUGCHK_BLOCK
, 0, 0, 0);
349 for (i
= 0; i
< Count
; i
++) {
350 if (RfsdBDL
[i
].Irp
!= NULL
) {
351 if ( RfsdBDL
[i
].Irp
->MdlAddress
!= NULL
) {
352 IoFreeMdl( RfsdBDL
[i
].Irp
->MdlAddress
);
355 IoFreeIrp( RfsdBDL
[i
].Irp
);
373 PKEVENT Event
= NULL
;
375 IO_STATUS_BLOCK IoStatus
;
381 ASSERT(Vcb
->TargetDeviceObject
!= NULL
);
382 ASSERT(Buffer
!= NULL
);
386 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), RFSD_POOL_TAG
);
392 KeInitializeEvent(Event
, NotificationEvent
, FALSE
);
394 Irp
= IoBuildSynchronousFsdRequest(
396 Vcb
->TargetDeviceObject
,
399 (PLARGE_INTEGER
)(&Offset
),
405 Status
= STATUS_INSUFFICIENT_RESOURCES
;
410 SetFlag( IoGetNextIrpStackLocation(Irp
)->Flags
,
411 SL_OVERRIDE_VERIFY_VOLUME
);
414 Status
= IoCallDriver(Vcb
->TargetDeviceObject
, Irp
);
416 if (Status
== STATUS_PENDING
) {
417 KeWaitForSingleObject(
425 Status
= IoStatus
.Status
;
441 IN ULONGLONG Offset
, // Byte offset (relative to disk) to read from (need not be sector-aligned!)
444 IN BOOLEAN bVerify
) // True if the volume should be verified before reading
453 // Align the offset and length to the sector boundaries
454 Lba
= Offset
& (~((ULONGLONG
)SECTOR_SIZE
- 1));
455 Length
= (ULONG
)(Size
+ Offset
+ SECTOR_SIZE
- 1 - Lba
) &
456 (~((ULONG
)SECTOR_SIZE
- 1));
458 // Allocate a temporary buffer to read the sector-aligned data into
459 Buf
= ExAllocatePoolWithTag(PagedPool
, Length
, RFSD_POOL_TAG
);
461 RfsdPrint((DBG_ERROR
, "RfsdReadDisk: no enough memory.\n"));
462 Status
= STATUS_INSUFFICIENT_RESOURCES
;
468 Status
= RfsdReadSync( Vcb
,
474 if (!NT_SUCCESS(Status
)) {
475 RfsdPrint((DBG_ERROR
, "RfsdReadDisk: Read Block Device error.\n"));
480 // Copy the requested data into the user's buffer
481 RtlCopyMemory(Buffer
, &Buf
[Offset
- Lba
], Size
);
493 IN PDEVICE_OBJECT DeviceObject
,
495 IN PVOID InputBuffer
,
496 IN ULONG InputBufferSize
,
497 IN OUT PVOID OutputBuffer
,
498 IN OUT PULONG OutputBufferSize
)
500 ULONG OutBufferSize
= 0;
503 IO_STATUS_BLOCK IoStatus
;
508 ASSERT(DeviceObject
!= NULL
);
510 if (OutputBufferSize
)
512 OutBufferSize
= *OutputBufferSize
;
515 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
517 Irp
= IoBuildDeviceIoControlRequest(
530 RfsdPrint((DBG_ERROR
, "RfsdDiskIoControl: Building IRQ error!\n"));
531 return STATUS_INSUFFICIENT_RESOURCES
;
534 Status
= IoCallDriver(DeviceObject
, Irp
);
536 if (Status
== STATUS_PENDING
) {
537 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
538 Status
= IoStatus
.Status
;
541 if (OutputBufferSize
) {
542 *OutputBufferSize
= (ULONG
) IoStatus
.Information
;
549 RfsdMediaEjectControlCompletion (
550 IN PDEVICE_OBJECT DeviceObject
,
555 PKEVENT Event
= (PKEVENT
)Contxt
;
557 KeSetEvent( Event
, 0, FALSE
);
559 UNREFERENCED_PARAMETER( DeviceObject
);
561 return STATUS_SUCCESS
;
564 __drv_mustHoldCriticalRegion
566 RfsdMediaEjectControl (
567 IN PRFSD_IRP_CONTEXT IrpContext
,
575 PREVENT_MEDIA_REMOVAL Prevent
;
576 IO_STATUS_BLOCK IoStatus
;
580 ExAcquireResourceExclusiveLite(
584 if (bPrevent
!= IsFlagOn(Vcb
->Flags
, VCB_REMOVAL_PREVENTED
)) {
586 SetFlag(Vcb
->Flags
, VCB_REMOVAL_PREVENTED
);
588 ClearFlag(Vcb
->Flags
, VCB_REMOVAL_PREVENTED
);
592 ExReleaseResourceForThreadLite(
594 ExGetCurrentResourceThread());
596 Prevent
.PreventMediaRemoval
= bPrevent
;
598 KeInitializeEvent( &Event
, NotificationEvent
, FALSE
);
600 Irp
= IoBuildDeviceIoControlRequest( IOCTL_DISK_MEDIA_REMOVAL
,
601 Vcb
->TargetDeviceObject
,
603 sizeof(PREVENT_MEDIA_REMOVAL
),
611 IoSetCompletionRoutine( Irp
,
612 RfsdMediaEjectControlCompletion
,
618 Status
= IoCallDriver(Vcb
->TargetDeviceObject
, Irp
);
620 if (Status
== STATUS_PENDING
) {
621 Status
= KeWaitForSingleObject( &Event
,
631 RfsdDiskShutDown(PRFSD_VCB Vcb
)
636 IO_STATUS_BLOCK IoStatus
;
640 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
642 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_SHUTDOWN
,
643 Vcb
->TargetDeviceObject
,
651 Status
= IoCallDriver(Vcb
->TargetDeviceObject
, Irp
);
653 if (Status
== STATUS_PENDING
) {
654 KeWaitForSingleObject(&Event
,
660 Status
= IoStatus
.Status
;
663 Status
= IoStatus
.Status
;