2 * COPYRIGHT: See COPYRIGHT.TXT
3 * PROJECT: Ext2 File System Driver for WinNT/2K/XP
5 * PROGRAMMER: Matt Wu <mattwu@163.com>
6 * HOMEPAGE: http://www.ext2fsd.com
10 /* INCLUDES *****************************************************************/
14 /* GLOBALS ***************************************************************/
16 extern PEXT2_GLOBAL Ext2Global
;
18 /* DEFINITIONS *************************************************************/
21 Ext2DeviceControlCompletion (
22 IN PDEVICE_OBJECT DeviceObject
,
28 #pragma alloc_text(PAGE, Ext2DeviceControl)
29 #pragma alloc_text(PAGE, Ext2DeviceControlNormal)
30 #pragma alloc_text(PAGE, Ext2ProcessVolumeProperty)
31 #pragma alloc_text(PAGE, Ext2ProcessUserProperty)
32 #pragma alloc_text(PAGE, Ext2ProcessGlobalProperty)
33 #pragma alloc_text(PAGE, Ex2ProcessUserPerfStat)
34 #pragma alloc_text(PAGE, Ex2ProcessMountPoint)
36 #pragma alloc_text(PAGE, Ext2PrepareToUnload)
42 Ext2DeviceControlCompletion (
43 IN PDEVICE_OBJECT DeviceObject
,
48 if (Irp
->PendingReturned
) {
49 IoMarkIrpPending(Irp
);
52 return STATUS_SUCCESS
;
57 Ext2DeviceControlNormal (IN PEXT2_IRP_CONTEXT IrpContext
)
59 PDEVICE_OBJECT DeviceObject
;
60 BOOLEAN CompleteRequest
= TRUE
;
61 NTSTATUS Status
= STATUS_UNSUCCESSFUL
;
66 PIO_STACK_LOCATION IrpSp
;
67 PIO_STACK_LOCATION NextIrpSp
;
69 PDEVICE_OBJECT TargetDeviceObject
;
73 ASSERT(IrpContext
!= NULL
);
75 ASSERT((IrpContext
->Identifier
.Type
== EXT2ICX
) &&
76 (IrpContext
->Identifier
.Size
== sizeof(EXT2_IRP_CONTEXT
)));
78 CompleteRequest
= TRUE
;
80 DeviceObject
= IrpContext
->DeviceObject
;
82 if (IsExt2FsDevice(DeviceObject
)) {
83 Status
= STATUS_INVALID_DEVICE_REQUEST
;
87 Irp
= IrpContext
->Irp
;
88 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
90 Vcb
= (PEXT2_VCB
) IrpSp
->FileObject
->FsContext
;
92 if (!((Vcb
) && (Vcb
->Identifier
.Type
== EXT2VCB
) &&
93 (Vcb
->Identifier
.Size
== sizeof(EXT2_VCB
)))) {
94 Status
= STATUS_INVALID_PARAMETER
;
98 TargetDeviceObject
= Vcb
->TargetDeviceObject
;
101 // Pass on the IOCTL to the driver below
104 CompleteRequest
= FALSE
;
106 NextIrpSp
= IoGetNextIrpStackLocation( Irp
);
109 IoSetCompletionRoutine(
111 Ext2DeviceControlCompletion
,
117 Status
= IoCallDriver(TargetDeviceObject
, Irp
);
121 if (!IrpContext
->ExceptionInProgress
) {
123 if (!CompleteRequest
) {
124 IrpContext
->Irp
= NULL
;
127 Ext2CompleteIrpContext(IrpContext
, Status
);
139 Ext2PrepareToUnload (IN PEXT2_IRP_CONTEXT IrpContext
)
141 PDEVICE_OBJECT DeviceObject
;
142 NTSTATUS Status
= STATUS_UNSUCCESSFUL
;
143 BOOLEAN GlobalDataResourceAcquired
= FALSE
;
147 ASSERT(IrpContext
!= NULL
);
149 ASSERT((IrpContext
->Identifier
.Type
== EXT2ICX
) &&
150 (IrpContext
->Identifier
.Size
== sizeof(EXT2_IRP_CONTEXT
)));
152 DeviceObject
= IrpContext
->DeviceObject
;
154 if (IsExt2FsDevice(DeviceObject
)) {
155 Status
= STATUS_INVALID_DEVICE_REQUEST
;
159 ExAcquireResourceExclusiveLite(
160 &Ext2Global
->Resource
,
163 GlobalDataResourceAcquired
= TRUE
;
165 if (FlagOn(Ext2Global
->Flags
, EXT2_UNLOAD_PENDING
)) {
166 DEBUG(DL_ERR
, ( "Ext2PrepareUnload: Already ready to unload.\n"));
168 Status
= STATUS_ACCESS_DENIED
;
175 PLIST_ENTRY ListEntry
;
177 ListEntry
= Ext2Global
->VcbList
.Flink
;
179 while (ListEntry
!= &(Ext2Global
->VcbList
)) {
181 Vcb
= CONTAINING_RECORD(ListEntry
, EXT2_VCB
, Next
);
182 ListEntry
= ListEntry
->Flink
;
184 if (Vcb
&& (!Vcb
->ReferenceCount
) &&
185 IsFlagOn(Vcb
->Flags
, VCB_DISMOUNT_PENDING
)) {
187 Ext2ClearVpbFlag(Vcb
->Vpb
, VPB_MOUNTED
);
194 if (!IsListEmpty(&(Ext2Global
->VcbList
))) {
196 DEBUG(DL_ERR
, ( "Ext2PrepareUnload: Mounted volumes exists.\n"));
198 Status
= STATUS_ACCESS_DENIED
;
203 IoUnregisterFileSystem(Ext2Global
->DiskdevObject
);
204 IoUnregisterFileSystem(Ext2Global
->CdromdevObject
);
205 Ext2Global
->DriverObject
->DriverUnload
= DriverUnload
;
206 SetLongFlag(Ext2Global
->Flags
,EXT2_UNLOAD_PENDING
);
207 Status
= STATUS_SUCCESS
;
209 DEBUG(DL_INF
, ( "Ext2PrepareToUnload: Driver is ready to unload.\n"));
213 if (GlobalDataResourceAcquired
) {
214 ExReleaseResourceLite(&Ext2Global
->Resource
);
217 if (!IrpContext
->ExceptionInProgress
) {
218 Ext2CompleteIrpContext(IrpContext
, Status
);
227 extern CHAR gVersion
[];
232 Ext2ProcessGlobalProperty(
233 IN PDEVICE_OBJECT DeviceObject
,
234 IN PEXT2_VOLUME_PROPERTY2 Property
,
238 NTSTATUS Status
= STATUS_SUCCESS
;
239 BOOLEAN GlobalDataResourceAcquired
= FALSE
;
240 struct nls_table
* PageTable
= NULL
;
244 if (Length
< 8 || !IsFlagOn(Property
->Flags
, EXT2_FLAG_VP_SET_GLOBAL
)) {
245 Status
= STATUS_INVALID_PARAMETER
;
249 /* query Ext2Fsd's version and built date/time*/
250 if (Property
->Command
== APP_CMD_QUERY_VERSION
) {
251 PEXT2_VOLUME_PROPERTY_VERSION PVPV
=
252 (PEXT2_VOLUME_PROPERTY_VERSION
) Property
;
254 if (Length
< sizeof(EXT2_VOLUME_PROPERTY_VERSION
)) {
255 Status
= STATUS_INVALID_PARAMETER
;
259 RtlZeroMemory(&PVPV
->Date
[0], 0x20);
260 RtlZeroMemory(&PVPV
->Time
[0], 0x20);
261 RtlZeroMemory(&PVPV
->Version
[0],0x1C);
262 strncpy(&PVPV
->Version
[0], gVersion
, 0x1B);
263 strncpy(&PVPV
->Date
[0], gDate
, 0x1F);
264 strncpy(&PVPV
->Time
[0], gTime
, 0x1F);
268 /* must be property query/set commands */
269 if (Property
->Command
== APP_CMD_SET_PROPERTY
) {
270 if (Length
< sizeof(EXT2_VOLUME_PROPERTY
)) {
271 Status
= STATUS_INVALID_PARAMETER
;
274 } else if (Property
->Command
== APP_CMD_SET_PROPERTY2
) {
275 if (Length
< sizeof(EXT2_VOLUME_PROPERTY2
)) {
276 Status
= STATUS_INVALID_PARAMETER
;
279 } else if (Property
->Command
== APP_CMD_SET_PROPERTY3
) {
280 if (Length
< sizeof(EXT2_VOLUME_PROPERTY3
)) {
281 Status
= STATUS_INVALID_PARAMETER
;
285 Status
= STATUS_INVALID_PARAMETER
;
289 ExAcquireResourceExclusiveLite(&Ext2Global
->Resource
, TRUE
);
290 GlobalDataResourceAcquired
= TRUE
;
292 if (Property
->bReadonly
) {
293 ClearLongFlag(Ext2Global
->Flags
, EXT2_SUPPORT_WRITING
);
294 ClearLongFlag(Ext2Global
->Flags
, EXT3_FORCE_WRITING
);
296 SetLongFlag(Ext2Global
->Flags
, EXT2_SUPPORT_WRITING
);
297 if (Property
->bExt3Writable
) {
298 SetLongFlag(Ext2Global
->Flags
, EXT3_FORCE_WRITING
);
300 ClearLongFlag(Ext2Global
->Flags
, EXT3_FORCE_WRITING
);
304 PageTable
= load_nls(Property
->Codepage
);
306 memcpy(Ext2Global
->Codepage
.AnsiName
, Property
->Codepage
, CODEPAGE_MAXLEN
);
307 Ext2Global
->Codepage
.PageTable
= PageTable
;
310 if (Property
->Command
== APP_CMD_SET_PROPERTY2
||
311 Property
->Command
== APP_CMD_SET_PROPERTY3
) {
313 RtlZeroMemory(Ext2Global
->sHidingPrefix
, HIDINGPAT_LEN
);
314 if ((Ext2Global
->bHidingPrefix
= Property
->bHidingPrefix
)) {
315 RtlCopyMemory( Ext2Global
->sHidingPrefix
,
316 Property
->sHidingPrefix
,
319 RtlZeroMemory(Ext2Global
->sHidingSuffix
, HIDINGPAT_LEN
);
320 if ((Ext2Global
->bHidingSuffix
= Property
->bHidingSuffix
)) {
321 RtlCopyMemory( Ext2Global
->sHidingSuffix
,
322 Property
->sHidingSuffix
,
327 if (Property
->Command
== APP_CMD_SET_PROPERTY3
) {
329 PEXT2_VOLUME_PROPERTY3 Prop3
= (PEXT2_VOLUME_PROPERTY3
)Property
;
331 if (Prop3
->Flags
& EXT2_VPROP3_AUTOMOUNT
) {
332 if (Prop3
->AutoMount
)
333 SetLongFlag(Ext2Global
->Flags
, EXT2_AUTO_MOUNT
);
335 ClearLongFlag(Ext2Global
->Flags
, EXT2_AUTO_MOUNT
);
341 if (GlobalDataResourceAcquired
) {
342 ExReleaseResourceLite(&Ext2Global
->Resource
);
351 Ext2ProcessVolumeProperty(
353 IN PEXT2_VOLUME_PROPERTY2 Property
,
357 NTSTATUS Status
= STATUS_SUCCESS
;
358 BOOLEAN VcbResourceAcquired
= FALSE
;
359 struct nls_table
* PageTable
= NULL
;
363 ExAcquireResourceExclusiveLite(&Vcb
->MainResource
, TRUE
);
364 VcbResourceAcquired
= TRUE
;
366 if (Property
->Command
== APP_CMD_SET_PROPERTY
||
367 Property
->Command
== APP_CMD_QUERY_PROPERTY
) {
368 if (Length
< sizeof(EXT2_VOLUME_PROPERTY
)) {
369 Status
= STATUS_INVALID_PARAMETER
;
372 } else if (Property
->Command
== APP_CMD_SET_PROPERTY2
||
373 Property
->Command
== APP_CMD_QUERY_PROPERTY2
) {
374 if (Length
< sizeof(EXT2_VOLUME_PROPERTY2
)) {
375 Status
= STATUS_INVALID_PARAMETER
;
380 switch (Property
->Command
) {
382 case APP_CMD_SET_PROPERTY
:
383 case APP_CMD_SET_PROPERTY2
:
385 if (Property
->bReadonly
) {
387 Ext2FlushFiles(NULL
, Vcb
, FALSE
);
388 Ext2FlushVolume(NULL
, Vcb
, FALSE
);
389 SetLongFlag(Vcb
->Flags
, VCB_READ_ONLY
);
393 if (Property
->bExt3Writable
) {
394 SetLongFlag(Vcb
->Flags
, VCB_FORCE_WRITING
);
397 if (!Vcb
->IsExt3fs
) {
398 ClearLongFlag(Vcb
->Flags
, VCB_READ_ONLY
);
399 } else if (!Property
->bExt3Writable
) {
400 SetLongFlag(Vcb
->Flags
, VCB_READ_ONLY
);
401 } else if (IsFlagOn(Vcb
->Flags
, VCB_JOURNAL_RECOVER
)) {
402 ClearLongFlag(Vcb
->Flags
, VCB_READ_ONLY
);
403 Ext2RecoverJournal(NULL
, Vcb
);
404 if (IsFlagOn(Vcb
->Flags
, VCB_JOURNAL_RECOVER
)) {
405 SetLongFlag(Vcb
->Flags
, VCB_READ_ONLY
);
407 ClearLongFlag(Vcb
->Flags
, VCB_READ_ONLY
);
410 ClearLongFlag(Vcb
->Flags
, VCB_READ_ONLY
);
414 PageTable
= load_nls(Property
->Codepage
);
415 memcpy(Vcb
->Codepage
.AnsiName
, Property
->Codepage
, CODEPAGE_MAXLEN
);
416 Vcb
->Codepage
.PageTable
= PageTable
;
417 if (Vcb
->Codepage
.PageTable
) {
418 Ext2InitializeLabel(Vcb
, Vcb
->SuperBlock
);
421 if (Property
->Command
== APP_CMD_SET_PROPERTY2
) {
423 RtlZeroMemory(Vcb
->sHidingPrefix
, HIDINGPAT_LEN
);
424 if ((Vcb
->bHidingPrefix
= Property
->bHidingPrefix
) != 0) {
425 RtlCopyMemory( Vcb
->sHidingPrefix
,
426 Property
->sHidingPrefix
,
430 RtlZeroMemory(Vcb
->sHidingSuffix
, HIDINGPAT_LEN
);
431 if ((Vcb
->bHidingSuffix
= Property
->bHidingSuffix
) != 0) {
432 RtlCopyMemory( Vcb
->sHidingSuffix
,
433 Property
->sHidingSuffix
,
437 Vcb
->DrvLetter
= Property
->DrvLetter
;
442 case APP_CMD_QUERY_PROPERTY
:
443 case APP_CMD_QUERY_PROPERTY2
:
445 Property
->bExt2
= TRUE
;
446 Property
->bExt3
= Vcb
->IsExt3fs
;
447 Property
->bReadonly
= IsFlagOn(Vcb
->Flags
, VCB_READ_ONLY
);
448 if (!Property
->bReadonly
&& Vcb
->IsExt3fs
) {
449 Property
->bExt3Writable
= TRUE
;
451 Property
->bExt3Writable
= FALSE
;
454 RtlZeroMemory(Property
->Codepage
, CODEPAGE_MAXLEN
);
455 if (Vcb
->Codepage
.PageTable
) {
456 strncpy(Property
->Codepage
, Vcb
->Codepage
.PageTable
->charset
, CODEPAGE_MAXLEN
);
458 strncpy(Property
->Codepage
, "default", CODEPAGE_MAXLEN
);
461 if (Property
->Command
== APP_CMD_QUERY_PROPERTY2
) {
463 RtlCopyMemory(Property
->UUID
, Vcb
->SuperBlock
->s_uuid
, 16);
465 Property
->DrvLetter
= Vcb
->DrvLetter
;
467 if ((Property
->bHidingPrefix
= Vcb
->bHidingPrefix
) != 0) {
468 RtlCopyMemory( Property
->sHidingPrefix
,
472 RtlZeroMemory( Property
->sHidingPrefix
,
476 if ((Property
->bHidingSuffix
= Vcb
->bHidingSuffix
) != 0) {
477 RtlCopyMemory( Property
->sHidingSuffix
,
481 RtlZeroMemory( Property
->sHidingSuffix
,
489 Status
= STATUS_INVALID_PARAMETER
;
495 if (VcbResourceAcquired
) {
496 ExReleaseResourceLite(&Vcb
->MainResource
);
504 Ext2ProcessUserProperty(
505 IN PEXT2_IRP_CONTEXT IrpContext
,
506 IN PEXT2_VOLUME_PROPERTY2 Property
,
510 NTSTATUS Status
= STATUS_SUCCESS
;
511 PEXT2_VCB Vcb
= NULL
;
512 PDEVICE_OBJECT DeviceObject
= NULL
;
516 ASSERT(IrpContext
!= NULL
);
517 ASSERT((IrpContext
->Identifier
.Type
== EXT2ICX
) &&
518 (IrpContext
->Identifier
.Size
== sizeof(EXT2_IRP_CONTEXT
)));
520 if (Property
->Magic
!= EXT2_VOLUME_PROPERTY_MAGIC
) {
521 Status
= STATUS_INVALID_PARAMETER
;
525 DeviceObject
= IrpContext
->DeviceObject
;
526 if (IsExt2FsDevice(DeviceObject
)) {
527 Status
= Ext2ProcessGlobalProperty(DeviceObject
, Property
, Length
);
529 Vcb
= (PEXT2_VCB
) DeviceObject
->DeviceExtension
;
530 if (!((Vcb
) && (Vcb
->Identifier
.Type
== EXT2VCB
) &&
531 (Vcb
->Identifier
.Size
== sizeof(EXT2_VCB
)))) {
532 Status
= STATUS_INVALID_PARAMETER
;
535 Status
= Ext2ProcessVolumeProperty(Vcb
, Property
, Length
);
538 if (NT_SUCCESS(Status
)) {
539 IrpContext
->Irp
->IoStatus
.Information
= Length
;
544 if (!IrpContext
->ExceptionInProgress
) {
545 Ext2CompleteIrpContext(IrpContext
, Status
);
553 Ex2ProcessUserPerfStat(
554 IN PEXT2_IRP_CONTEXT IrpContext
,
555 IN PEXT2_QUERY_PERFSTAT QueryPerf
,
561 PEXT2_VCB Vcb
= NULL
;
563 PDEVICE_OBJECT DeviceObject
= NULL
;
565 BOOLEAN GlobalDataResourceAcquired
= FALSE
;
566 NTSTATUS Status
= STATUS_SUCCESS
;
570 ASSERT(IrpContext
!= NULL
);
571 ASSERT((IrpContext
->Identifier
.Type
== EXT2ICX
) &&
572 (IrpContext
->Identifier
.Size
== sizeof(EXT2_IRP_CONTEXT
)));
574 DeviceObject
= IrpContext
->DeviceObject
;
575 if (IsExt2FsDevice(DeviceObject
)) {
577 if (QueryPerf
->Magic
!= EXT2_QUERY_PERFSTAT_MAGIC
) {
578 Status
= STATUS_INVALID_PARAMETER
;
582 if (QueryPerf
->Command
!= IOCTL_APP_QUERY_PERFSTAT
) {
583 Status
= STATUS_INVALID_PARAMETER
;
587 if (Length
!= EXT2_QUERY_PERFSTAT_SZV1
&&
588 Length
!= EXT2_QUERY_PERFSTAT_SZV2
) {
589 Status
= STATUS_INVALID_PARAMETER
;
593 ExAcquireResourceSharedLite(&Ext2Global
->Resource
, TRUE
);
594 GlobalDataResourceAcquired
= TRUE
;
596 if (Length
== EXT2_QUERY_PERFSTAT_SZV2
) {
597 QueryPerf
->Flags
= EXT2_QUERY_PERFSTAT_VER2
;
598 QueryPerf
->PerfStatV2
= Ext2Global
->PerfStat
;
600 memcpy(&QueryPerf
->PerfStatV1
.Irps
[0], &Ext2Global
->PerfStat
.Irps
[0],
601 FIELD_OFFSET(EXT2_PERF_STATISTICS_V1
, Unit
));
602 memcpy(&QueryPerf
->PerfStatV1
.Unit
, &Ext2Global
->PerfStat
.Unit
,
603 sizeof(EXT2_STAT_ARRAY_V1
));
604 memcpy(&QueryPerf
->PerfStatV1
.Current
, &Ext2Global
->PerfStat
.Current
,
605 sizeof(EXT2_STAT_ARRAY_V1
));
606 memcpy(&QueryPerf
->PerfStatV1
.Size
, &Ext2Global
->PerfStat
.Size
,
607 sizeof(EXT2_STAT_ARRAY_V1
));
608 memcpy(&QueryPerf
->PerfStatV1
.Total
, &Ext2Global
->PerfStat
.Total
,
609 sizeof(EXT2_STAT_ARRAY_V1
));
613 Status
= STATUS_INVALID_PARAMETER
;
617 if (NT_SUCCESS(Status
)) {
618 IrpContext
->Irp
->IoStatus
.Information
= Length
;
623 if (GlobalDataResourceAcquired
) {
624 ExReleaseResourceLite(&Ext2Global
->Resource
);
627 if (!IrpContext
->ExceptionInProgress
) {
628 Ext2CompleteIrpContext(IrpContext
, Status
);
636 Ex2ProcessMountPoint(
637 IN PEXT2_IRP_CONTEXT IrpContext
,
638 IN PEXT2_MOUNT_POINT MountPoint
,
643 UNICODE_STRING Target
;
644 WCHAR Buffer
[] = L
"\\DosDevices\\Global\\Z:";
645 NTSTATUS status
= STATUS_SUCCESS
;
647 PDEVICE_OBJECT DeviceObject
= NULL
;
651 ASSERT(IrpContext
!= NULL
);
652 ASSERT((IrpContext
->Identifier
.Type
== EXT2ICX
) &&
653 (IrpContext
->Identifier
.Size
== sizeof(EXT2_IRP_CONTEXT
)));
655 DeviceObject
= IrpContext
->DeviceObject
;
656 if (!IsExt2FsDevice(DeviceObject
)) {
657 status
= STATUS_INVALID_PARAMETER
;
661 if (Length
!= sizeof(EXT2_MOUNT_POINT
) ||
662 MountPoint
->Magic
!= EXT2_APP_MOUNTPOINT_MAGIC
) {
663 status
= STATUS_INVALID_PARAMETER
;
667 RtlInitUnicodeString(&Link
, Buffer
);
668 Buffer
[12] = MountPoint
->Link
[0];
670 switch (MountPoint
->Command
) {
672 case APP_CMD_ADD_DOS_SYMLINK
:
673 RtlInitUnicodeString(&Target
, &MountPoint
->Name
[0]);
674 status
= IoCreateSymbolicLink(&Link
, &Target
);
677 case APP_CMD_DEL_DOS_SYMLINK
:
678 status
= IoDeleteSymbolicLink(&Link
);
682 status
= STATUS_INVALID_PARAMETER
;
687 if (!IrpContext
->ExceptionInProgress
) {
688 Ext2CompleteIrpContext(IrpContext
, status
);
696 Ext2DeviceControl (IN PEXT2_IRP_CONTEXT IrpContext
)
699 PIO_STACK_LOCATION irpSp
;
706 ASSERT((IrpContext
->Identifier
.Type
== EXT2ICX
) &&
707 (IrpContext
->Identifier
.Size
== sizeof(EXT2_IRP_CONTEXT
)));
709 Irp
= IrpContext
->Irp
;
711 irpSp
= IoGetCurrentIrpStackLocation(Irp
);
713 code
= irpSp
->Parameters
.DeviceIoControl
.IoControlCode
;
714 length
= irpSp
->Parameters
.DeviceIoControl
.OutputBufferLength
;
718 case IOCTL_APP_VOLUME_PROPERTY
:
719 Status
= Ext2ProcessUserProperty(
721 Irp
->AssociatedIrp
.SystemBuffer
,
726 case IOCTL_APP_QUERY_PERFSTAT
:
727 Status
= Ex2ProcessUserPerfStat(
729 Irp
->AssociatedIrp
.SystemBuffer
,
734 case IOCTL_APP_MOUNT_POINT
:
735 Status
= Ex2ProcessMountPoint(
737 Irp
->AssociatedIrp
.SystemBuffer
,
743 case IOCTL_PREPARE_TO_UNLOAD
:
744 Status
= Ext2PrepareToUnload(IrpContext
);
748 Status
= Ext2DeviceControlNormal(IrpContext
);