1 /* 2 * COPYRIGHT: See COPYRIGHT.TXT 3 * PROJECT: Ext2 File System Driver for WinNT/2K/XP 4 * FILE: devctl.c 5 * PROGRAMMER: Matt Wu <mattwu@163.com> 6 * HOMEPAGE: http://www.ext2fsd.com 7 * UPDATE HISTORY: 8 */ 9 10 /* INCLUDES *****************************************************************/ 11 12 #include "ext2fs.h" 13 14 /* GLOBALS ***************************************************************/ 15 16 extern PEXT2_GLOBAL Ext2Global; 17 18 /* DEFINITIONS *************************************************************/ 19 20 #ifdef __REACTOS__ 21 NTSTATUS NTAPI 22 #else 23 NTSTATUS 24 #endif 25 Ext2DeviceControlCompletion ( 26 IN PDEVICE_OBJECT DeviceObject, 27 IN PIRP Irp, 28 IN PVOID Context); 29 30 31 #ifdef ALLOC_PRAGMA 32 #pragma alloc_text(PAGE, Ext2DeviceControl) 33 #pragma alloc_text(PAGE, Ext2DeviceControlNormal) 34 #pragma alloc_text(PAGE, Ext2ProcessVolumeProperty) 35 #pragma alloc_text(PAGE, Ext2ProcessUserProperty) 36 #pragma alloc_text(PAGE, Ext2ProcessGlobalProperty) 37 #pragma alloc_text(PAGE, Ex2ProcessUserPerfStat) 38 #pragma alloc_text(PAGE, Ex2ProcessMountPoint) 39 #if EXT2_UNLOAD 40 #pragma alloc_text(PAGE, Ext2PrepareToUnload) 41 #endif 42 #endif 43 44 45 #ifdef __REACTOS__ 46 NTSTATUS NTAPI 47 #else 48 NTSTATUS 49 #endif 50 Ext2DeviceControlCompletion ( 51 IN PDEVICE_OBJECT DeviceObject, 52 IN PIRP Irp, 53 IN PVOID Context 54 ) 55 { 56 if (Irp->PendingReturned) { 57 IoMarkIrpPending(Irp); 58 } 59 60 return STATUS_SUCCESS; 61 } 62 63 64 NTSTATUS 65 Ext2DeviceControlNormal (IN PEXT2_IRP_CONTEXT IrpContext) 66 { 67 PDEVICE_OBJECT DeviceObject; 68 BOOLEAN CompleteRequest = TRUE; 69 NTSTATUS Status = STATUS_UNSUCCESSFUL; 70 71 PEXT2_VCB Vcb; 72 73 PIRP Irp; 74 PIO_STACK_LOCATION IrpSp; 75 PIO_STACK_LOCATION NextIrpSp; 76 77 PDEVICE_OBJECT TargetDeviceObject; 78 79 _SEH2_TRY { 80 81 ASSERT(IrpContext != NULL); 82 83 ASSERT((IrpContext->Identifier.Type == EXT2ICX) && 84 (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT))); 85 86 CompleteRequest = TRUE; 87 88 DeviceObject = IrpContext->DeviceObject; 89 90 if (IsExt2FsDevice(DeviceObject)) { 91 Status = STATUS_INVALID_DEVICE_REQUEST; 92 _SEH2_LEAVE; 93 } 94 95 Irp = IrpContext->Irp; 96 IrpSp = IoGetCurrentIrpStackLocation(Irp); 97 98 Vcb = (PEXT2_VCB) IrpSp->FileObject->FsContext; 99 100 if (!((Vcb) && (Vcb->Identifier.Type == EXT2VCB) && 101 (Vcb->Identifier.Size == sizeof(EXT2_VCB)))) { 102 Status = STATUS_INVALID_PARAMETER; 103 _SEH2_LEAVE; 104 } 105 106 TargetDeviceObject = Vcb->TargetDeviceObject; 107 108 // 109 // Pass on the IOCTL to the driver below 110 // 111 112 CompleteRequest = FALSE; 113 114 NextIrpSp = IoGetNextIrpStackLocation( Irp ); 115 *NextIrpSp = *IrpSp; 116 117 IoSetCompletionRoutine( 118 Irp, 119 Ext2DeviceControlCompletion, 120 NULL, 121 FALSE, 122 TRUE, 123 TRUE ); 124 125 Status = IoCallDriver(TargetDeviceObject, Irp); 126 127 } _SEH2_FINALLY { 128 129 if (!IrpContext->ExceptionInProgress) { 130 if (IrpContext) { 131 if (!CompleteRequest) { 132 IrpContext->Irp = NULL; 133 } 134 135 Ext2CompleteIrpContext(IrpContext, Status); 136 } 137 } 138 } _SEH2_END; 139 140 return Status; 141 } 142 143 144 #if EXT2_UNLOAD 145 146 NTSTATUS 147 Ext2PrepareToUnload (IN PEXT2_IRP_CONTEXT IrpContext) 148 { 149 PDEVICE_OBJECT DeviceObject; 150 NTSTATUS Status = STATUS_UNSUCCESSFUL; 151 BOOLEAN GlobalDataResourceAcquired = FALSE; 152 153 _SEH2_TRY { 154 155 ASSERT(IrpContext != NULL); 156 157 ASSERT((IrpContext->Identifier.Type == EXT2ICX) && 158 (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT))); 159 160 DeviceObject = IrpContext->DeviceObject; 161 162 if (IsExt2FsDevice(DeviceObject)) { 163 Status = STATUS_INVALID_DEVICE_REQUEST; 164 _SEH2_LEAVE; 165 } 166 167 ExAcquireResourceExclusiveLite( 168 &Ext2Global->Resource, 169 TRUE ); 170 171 GlobalDataResourceAcquired = TRUE; 172 173 if (FlagOn(Ext2Global->Flags, EXT2_UNLOAD_PENDING)) { 174 DEBUG(DL_ERR, ( "Ext2PrepareUnload: Already ready to unload.\n")); 175 176 Status = STATUS_ACCESS_DENIED; 177 178 _SEH2_LEAVE; 179 } 180 181 { 182 PEXT2_VCB Vcb; 183 PLIST_ENTRY ListEntry; 184 185 ListEntry = Ext2Global->VcbList.Flink; 186 187 while (ListEntry != &(Ext2Global->VcbList)) { 188 189 Vcb = CONTAINING_RECORD(ListEntry, EXT2_VCB, Next); 190 ListEntry = ListEntry->Flink; 191 192 if (Vcb && (!Vcb->ReferenceCount) && 193 IsFlagOn(Vcb->Flags, VCB_DISMOUNT_PENDING)) { 194 Ext2RemoveVcb(Vcb); 195 Ext2ClearVpbFlag(Vcb->Vpb, VPB_MOUNTED); 196 197 Ext2DestroyVcb(Vcb); 198 } 199 } 200 } 201 202 if (!IsListEmpty(&(Ext2Global->VcbList))) { 203 204 DEBUG(DL_ERR, ( "Ext2PrepareUnload: Mounted volumes exists.\n")); 205 206 Status = STATUS_ACCESS_DENIED; 207 208 _SEH2_LEAVE; 209 } 210 211 IoUnregisterFileSystem(Ext2Global->DiskdevObject); 212 IoUnregisterFileSystem(Ext2Global->CdromdevObject); 213 Ext2Global->DriverObject->DriverUnload = DriverUnload; 214 SetLongFlag(Ext2Global->Flags ,EXT2_UNLOAD_PENDING); 215 Status = STATUS_SUCCESS; 216 217 DEBUG(DL_INF, ( "Ext2PrepareToUnload: Driver is ready to unload.\n")); 218 219 } _SEH2_FINALLY { 220 221 if (GlobalDataResourceAcquired) { 222 ExReleaseResourceLite(&Ext2Global->Resource); 223 } 224 225 if (!IrpContext->ExceptionInProgress) { 226 Ext2CompleteIrpContext(IrpContext, Status); 227 } 228 } _SEH2_END; 229 230 return Status; 231 } 232 233 #endif 234 235 extern CHAR gVersion[]; 236 extern CHAR gTime[]; 237 extern CHAR gDate[]; 238 239 NTSTATUS 240 Ext2ProcessGlobalProperty( 241 IN PDEVICE_OBJECT DeviceObject, 242 IN PEXT2_VOLUME_PROPERTY3 Property3, 243 IN ULONG Length 244 ) 245 { 246 PEXT2_VOLUME_PROPERTY3 Property2 = (PVOID)Property3; 247 PEXT2_VOLUME_PROPERTY Property = (PVOID)Property3; 248 struct nls_table * PageTable = NULL; 249 250 NTSTATUS Status = STATUS_SUCCESS; 251 BOOLEAN GlobalDataResourceAcquired = FALSE; 252 253 _SEH2_TRY { 254 255 if (Length < 8 || !IsFlagOn(Property->Flags, EXT2_FLAG_VP_SET_GLOBAL)) { 256 Status = STATUS_INVALID_PARAMETER; 257 _SEH2_LEAVE; 258 } 259 260 /* query Ext2Fsd's version and built date/time*/ 261 if (Property->Command == APP_CMD_QUERY_VERSION) { 262 PEXT2_VOLUME_PROPERTY_VERSION PVPV = 263 (PEXT2_VOLUME_PROPERTY_VERSION) Property; 264 265 if (Length < sizeof(EXT2_VOLUME_PROPERTY_VERSION)) { 266 Status = STATUS_INVALID_PARAMETER; 267 _SEH2_LEAVE; 268 } 269 270 RtlZeroMemory(&PVPV->Date[0], 0x20); 271 RtlZeroMemory(&PVPV->Time[0], 0x20); 272 RtlZeroMemory(&PVPV->Version[0],0x1C); 273 strncpy(&PVPV->Version[0], gVersion, 0x1B); 274 strncpy(&PVPV->Date[0], gDate, 0x1F); 275 strncpy(&PVPV->Time[0], gTime, 0x1F); 276 _SEH2_LEAVE; 277 } 278 279 /* must be property query/set commands */ 280 if (Property->Command == APP_CMD_SET_PROPERTY) { 281 if (Length < sizeof(EXT2_VOLUME_PROPERTY)) { 282 Status = STATUS_INVALID_PARAMETER; 283 _SEH2_LEAVE; 284 } 285 } else if (Property->Command == APP_CMD_SET_PROPERTY2) { 286 if (Length < sizeof(EXT2_VOLUME_PROPERTY2)) { 287 Status = STATUS_INVALID_PARAMETER; 288 _SEH2_LEAVE; 289 } 290 } else if (Property->Command == APP_CMD_SET_PROPERTY3) { 291 if (Length < sizeof(EXT2_VOLUME_PROPERTY3)) { 292 Status = STATUS_INVALID_PARAMETER; 293 _SEH2_LEAVE; 294 } 295 } else { 296 Status = STATUS_INVALID_PARAMETER; 297 _SEH2_LEAVE; 298 } 299 300 ExAcquireResourceExclusiveLite(&Ext2Global->Resource, TRUE); 301 GlobalDataResourceAcquired = TRUE; 302 303 304 switch (Property->Command) { 305 306 case APP_CMD_SET_PROPERTY3: 307 308 if (Property3->Flags2 & EXT2_VPROP3_AUTOMOUNT) { 309 if (Property3->AutoMount) 310 SetLongFlag(Ext2Global->Flags, EXT2_AUTO_MOUNT); 311 else 312 ClearLongFlag(Ext2Global->Flags, EXT2_AUTO_MOUNT); 313 } 314 315 case APP_CMD_SET_PROPERTY2: 316 317 RtlZeroMemory(Ext2Global->sHidingPrefix, HIDINGPAT_LEN); 318 if ((Ext2Global->bHidingPrefix = Property2->bHidingPrefix)) { 319 RtlCopyMemory( Ext2Global->sHidingPrefix, 320 Property2->sHidingPrefix, 321 HIDINGPAT_LEN - 1); 322 } 323 RtlZeroMemory(Ext2Global->sHidingSuffix, HIDINGPAT_LEN); 324 if ((Ext2Global->bHidingSuffix = Property2->bHidingSuffix)) { 325 RtlCopyMemory( Ext2Global->sHidingSuffix, 326 Property2->sHidingSuffix, 327 HIDINGPAT_LEN - 1); 328 } 329 330 case APP_CMD_SET_PROPERTY: 331 332 if (Property->bReadonly) { 333 ClearLongFlag(Ext2Global->Flags, EXT2_SUPPORT_WRITING); 334 ClearLongFlag(Ext2Global->Flags, EXT3_FORCE_WRITING); 335 } else { 336 SetLongFlag(Ext2Global->Flags, EXT2_SUPPORT_WRITING); 337 if (Property->bExt3Writable) { 338 SetLongFlag(Ext2Global->Flags, EXT3_FORCE_WRITING); 339 } else { 340 ClearLongFlag(Ext2Global->Flags, EXT3_FORCE_WRITING); 341 } 342 } 343 344 PageTable = load_nls(Property->Codepage); 345 if (PageTable) { 346 memcpy(Ext2Global->Codepage.AnsiName, Property->Codepage, CODEPAGE_MAXLEN); 347 Ext2Global->Codepage.PageTable = PageTable; 348 } 349 350 break; 351 352 default: 353 break; 354 } 355 356 } _SEH2_FINALLY { 357 358 if (GlobalDataResourceAcquired) { 359 ExReleaseResourceLite(&Ext2Global->Resource); 360 } 361 } _SEH2_END; 362 363 return Status; 364 } 365 366 367 NTSTATUS 368 Ext2ProcessVolumeProperty( 369 IN PEXT2_VCB Vcb, 370 IN PEXT2_VOLUME_PROPERTY3 Property3, 371 IN ULONG Length 372 ) 373 { 374 struct nls_table * PageTable = NULL; 375 PEXT2_VOLUME_PROPERTY2 Property2 = (PVOID)Property3; 376 PEXT2_VOLUME_PROPERTY Property = (PVOID)Property3; 377 NTSTATUS Status = STATUS_SUCCESS; 378 BOOLEAN VcbResourceAcquired = FALSE; 379 380 _SEH2_TRY { 381 382 ExAcquireResourceExclusiveLite(&Vcb->MainResource, TRUE); 383 VcbResourceAcquired = TRUE; 384 385 if (Property->Command == APP_CMD_SET_PROPERTY || 386 Property->Command == APP_CMD_QUERY_PROPERTY) { 387 if (Length < sizeof(EXT2_VOLUME_PROPERTY)) { 388 Status = STATUS_INVALID_PARAMETER; 389 _SEH2_LEAVE; 390 } 391 } else if (Property->Command == APP_CMD_SET_PROPERTY2 || 392 Property->Command == APP_CMD_QUERY_PROPERTY2) { 393 if (Length < sizeof(EXT2_VOLUME_PROPERTY2)) { 394 Status = STATUS_INVALID_PARAMETER; 395 _SEH2_LEAVE; 396 } 397 } else if (Property->Command == APP_CMD_SET_PROPERTY3 || 398 Property->Command == APP_CMD_QUERY_PROPERTY3) { 399 if (Length < sizeof(EXT2_VOLUME_PROPERTY3)) { 400 Status = STATUS_INVALID_PARAMETER; 401 _SEH2_LEAVE; 402 } 403 } 404 405 switch (Property->Command) { 406 407 case APP_CMD_SET_PROPERTY3: 408 409 if (Property3->Flags2 & EXT2_VPROP3_AUTOMOUNT) { 410 if (Property3->AutoMount) 411 SetLongFlag(Ext2Global->Flags, EXT2_AUTO_MOUNT); 412 else 413 ClearLongFlag(Ext2Global->Flags, EXT2_AUTO_MOUNT); 414 } 415 if (Property3->Flags2 & EXT2_VPROP3_USERIDS) { 416 SetFlag(Vcb->Flags, VCB_USER_IDS); 417 Vcb->uid = Property3->uid; 418 Vcb->gid = Property3->gid; 419 if (Property3->EIDS) { 420 Vcb->euid = Property3->euid; 421 Vcb->egid = Property3->egid; 422 SetFlag(Vcb->Flags, VCB_USER_EIDS); 423 } else { 424 Vcb->euid = Vcb->egid = 0; 425 ClearFlag(Vcb->Flags, VCB_USER_EIDS); 426 } 427 } else { 428 ClearFlag(Vcb->Flags, VCB_USER_IDS); 429 ClearFlag(Vcb->Flags, VCB_USER_EIDS); 430 Vcb->uid = Vcb->gid = 0; 431 Vcb->euid = Vcb->egid = 0; 432 } 433 434 case APP_CMD_SET_PROPERTY2: 435 436 RtlZeroMemory(Vcb->sHidingPrefix, HIDINGPAT_LEN); 437 #ifdef __REACTOS__ 438 if (Vcb->bHidingPrefix == Property2->bHidingPrefix) { 439 #else 440 if (Vcb->bHidingPrefix = Property2->bHidingPrefix) { 441 #endif 442 RtlCopyMemory( Vcb->sHidingPrefix, 443 Property2->sHidingPrefix, 444 HIDINGPAT_LEN - 1); 445 } 446 447 RtlZeroMemory(Vcb->sHidingSuffix, HIDINGPAT_LEN); 448 #ifdef __REACTOS__ 449 if (Vcb->bHidingSuffix == Property2->bHidingSuffix) { 450 #else 451 if (Vcb->bHidingSuffix = Property2->bHidingSuffix) { 452 #endif 453 RtlCopyMemory( Vcb->sHidingSuffix, 454 Property2->sHidingSuffix, 455 HIDINGPAT_LEN - 1); 456 } 457 Vcb->DrvLetter = Property2->DrvLetter; 458 459 case APP_CMD_SET_PROPERTY: 460 461 if (Property->bReadonly) { 462 if (IsFlagOn(Vcb->Flags, VCB_INITIALIZED)) { 463 Ext2FlushFiles(NULL, Vcb, FALSE); 464 Ext2FlushVolume(NULL, Vcb, FALSE); 465 } 466 SetLongFlag(Vcb->Flags, VCB_READ_ONLY); 467 468 } else { 469 470 if (Property->bExt3Writable) { 471 SetLongFlag(Vcb->Flags, VCB_FORCE_WRITING); 472 } 473 474 if (!Vcb->IsExt3fs) { 475 ClearLongFlag(Vcb->Flags, VCB_READ_ONLY); 476 } else if (!Property->bExt3Writable) { 477 SetLongFlag(Vcb->Flags, VCB_READ_ONLY); 478 } else if (IsFlagOn(Vcb->Flags, VCB_JOURNAL_RECOVER)) { 479 ClearLongFlag(Vcb->Flags, VCB_READ_ONLY); 480 Ext2RecoverJournal(NULL, Vcb); 481 if (IsFlagOn(Vcb->Flags, VCB_JOURNAL_RECOVER)) { 482 SetLongFlag(Vcb->Flags, VCB_READ_ONLY); 483 } else { 484 ClearLongFlag(Vcb->Flags, VCB_READ_ONLY); 485 } 486 } else { 487 ClearLongFlag(Vcb->Flags, VCB_READ_ONLY); 488 } 489 } 490 491 PageTable = load_nls(Property->Codepage); 492 memcpy(Vcb->Codepage.AnsiName, Property->Codepage, CODEPAGE_MAXLEN); 493 Vcb->Codepage.PageTable = PageTable; 494 if (Vcb->Codepage.PageTable) { 495 Ext2InitializeLabel(Vcb, Vcb->SuperBlock); 496 } 497 498 break; 499 500 case APP_CMD_QUERY_PROPERTY3: 501 502 if (IsFlagOn(Ext2Global->Flags, EXT2_AUTO_MOUNT)) { 503 SetFlag(Property3->Flags2, EXT2_VPROP3_AUTOMOUNT); 504 Property3->AutoMount = TRUE; 505 } else { 506 ClearFlag(Property3->Flags2, EXT2_VPROP3_AUTOMOUNT); 507 Property3->AutoMount = FALSE; 508 } 509 510 if (IsFlagOn(Vcb->Flags, VCB_USER_IDS)) { 511 SetFlag(Property3->Flags2, EXT2_VPROP3_USERIDS); 512 Property3->uid = Vcb->uid; 513 Property3->gid = Vcb->gid; 514 if (IsFlagOn(Vcb->Flags, VCB_USER_EIDS)) { 515 Property3->EIDS = TRUE; 516 Property3->euid = Vcb->euid; 517 Property3->egid = Vcb->egid; 518 } else { 519 Property3->EIDS = FALSE; 520 } 521 } else { 522 ClearFlag(Property3->Flags2, EXT2_VPROP3_USERIDS); 523 } 524 525 case APP_CMD_QUERY_PROPERTY2: 526 527 RtlCopyMemory(Property2->UUID, Vcb->SuperBlock->s_uuid, 16); 528 Property2->DrvLetter = Vcb->DrvLetter; 529 530 #ifdef __REACTOS__ 531 if (Property2->bHidingPrefix == Vcb->bHidingPrefix) { 532 #else 533 if (Property2->bHidingPrefix = Vcb->bHidingPrefix) { 534 #endif 535 RtlCopyMemory( Property2->sHidingPrefix, 536 Vcb->sHidingPrefix, 537 HIDINGPAT_LEN); 538 } else { 539 RtlZeroMemory( Property2->sHidingPrefix, 540 HIDINGPAT_LEN); 541 } 542 543 #ifdef __REACTOS__ 544 if (Property2->bHidingSuffix == Vcb->bHidingSuffix) { 545 #else 546 if (Property2->bHidingSuffix = Vcb->bHidingSuffix) { 547 #endif 548 RtlCopyMemory( Property2->sHidingSuffix, 549 Vcb->sHidingSuffix, 550 HIDINGPAT_LEN); 551 } else { 552 RtlZeroMemory( Property2->sHidingSuffix, 553 HIDINGPAT_LEN); 554 } 555 556 case APP_CMD_QUERY_PROPERTY: 557 558 Property->bExt2 = TRUE; 559 Property->bExt3 = Vcb->IsExt3fs; 560 Property->bReadonly = IsFlagOn(Vcb->Flags, VCB_READ_ONLY); 561 if (!Property->bReadonly && Vcb->IsExt3fs) { 562 Property->bExt3Writable = TRUE; 563 } else { 564 Property->bExt3Writable = FALSE; 565 } 566 567 RtlZeroMemory(Property->Codepage, CODEPAGE_MAXLEN); 568 if (Vcb->Codepage.PageTable) { 569 strncpy(Property->Codepage, Vcb->Codepage.PageTable->charset, CODEPAGE_MAXLEN); 570 } else { 571 strncpy(Property->Codepage, "default", CODEPAGE_MAXLEN); 572 } 573 break; 574 575 default: 576 Status = STATUS_INVALID_PARAMETER; 577 break; 578 } 579 580 } _SEH2_FINALLY { 581 582 if (VcbResourceAcquired) { 583 ExReleaseResourceLite(&Vcb->MainResource); 584 } 585 } _SEH2_END; 586 587 return Status; 588 } 589 590 NTSTATUS 591 Ext2ProcessUserProperty( 592 IN PEXT2_IRP_CONTEXT IrpContext, 593 IN PEXT2_VOLUME_PROPERTY3 Property, 594 IN ULONG Length 595 ) 596 { 597 NTSTATUS Status = STATUS_SUCCESS; 598 PEXT2_VCB Vcb = NULL; 599 PDEVICE_OBJECT DeviceObject = NULL; 600 601 _SEH2_TRY { 602 603 ASSERT(IrpContext != NULL); 604 ASSERT((IrpContext->Identifier.Type == EXT2ICX) && 605 (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT))); 606 607 if (Property->Magic != EXT2_VOLUME_PROPERTY_MAGIC) { 608 Status = STATUS_INVALID_PARAMETER; 609 _SEH2_LEAVE; 610 } 611 612 DeviceObject = IrpContext->DeviceObject; 613 if (IsExt2FsDevice(DeviceObject)) { 614 Status = Ext2ProcessGlobalProperty(DeviceObject, Property, Length); 615 } else { 616 Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension; 617 if (!((Vcb) && (Vcb->Identifier.Type == EXT2VCB) && 618 (Vcb->Identifier.Size == sizeof(EXT2_VCB)))) { 619 Status = STATUS_INVALID_PARAMETER; 620 _SEH2_LEAVE; 621 } 622 Status = Ext2ProcessVolumeProperty(Vcb, Property, Length); 623 } 624 625 if (NT_SUCCESS(Status)) { 626 IrpContext->Irp->IoStatus.Information = Length; 627 } 628 629 } _SEH2_FINALLY { 630 631 if (!IrpContext->ExceptionInProgress) { 632 Ext2CompleteIrpContext(IrpContext, Status); 633 } 634 } _SEH2_END; 635 636 return Status; 637 } 638 639 NTSTATUS 640 Ex2ProcessUserPerfStat( 641 IN PEXT2_IRP_CONTEXT IrpContext, 642 IN PEXT2_QUERY_PERFSTAT QueryPerf, 643 IN ULONG Length 644 ) 645 { 646 647 #ifndef __REACTOS__ 648 PEXT2_VCB Vcb = NULL; 649 #endif 650 PDEVICE_OBJECT DeviceObject = NULL; 651 652 BOOLEAN GlobalDataResourceAcquired = FALSE; 653 NTSTATUS Status = STATUS_SUCCESS; 654 655 _SEH2_TRY { 656 657 ASSERT(IrpContext != NULL); 658 ASSERT((IrpContext->Identifier.Type == EXT2ICX) && 659 (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT))); 660 661 DeviceObject = IrpContext->DeviceObject; 662 if (IsExt2FsDevice(DeviceObject)) { 663 664 if (QueryPerf->Magic != EXT2_QUERY_PERFSTAT_MAGIC) { 665 Status = STATUS_INVALID_PARAMETER; 666 _SEH2_LEAVE; 667 } 668 669 if (QueryPerf->Command != IOCTL_APP_QUERY_PERFSTAT) { 670 Status = STATUS_INVALID_PARAMETER; 671 _SEH2_LEAVE; 672 } 673 674 if (Length != EXT2_QUERY_PERFSTAT_SZV1 && 675 Length != EXT2_QUERY_PERFSTAT_SZV2) { 676 Status = STATUS_INVALID_PARAMETER; 677 _SEH2_LEAVE; 678 } 679 680 ExAcquireResourceSharedLite(&Ext2Global->Resource, TRUE); 681 GlobalDataResourceAcquired = TRUE; 682 683 if (Length == EXT2_QUERY_PERFSTAT_SZV2) { 684 QueryPerf->Flags = EXT2_QUERY_PERFSTAT_VER2; 685 QueryPerf->PerfStatV2 = Ext2Global->PerfStat; 686 } else { 687 memcpy(&QueryPerf->PerfStatV1.Irps[0], &Ext2Global->PerfStat.Irps[0], 688 FIELD_OFFSET(EXT2_PERF_STATISTICS_V1, Unit)); 689 memcpy(&QueryPerf->PerfStatV1.Unit, &Ext2Global->PerfStat.Unit, 690 sizeof(EXT2_STAT_ARRAY_V1)); 691 memcpy(&QueryPerf->PerfStatV1.Current, &Ext2Global->PerfStat.Current, 692 sizeof(EXT2_STAT_ARRAY_V1)); 693 memcpy(&QueryPerf->PerfStatV1.Size, &Ext2Global->PerfStat.Size, 694 sizeof(EXT2_STAT_ARRAY_V1)); 695 memcpy(&QueryPerf->PerfStatV1.Total, &Ext2Global->PerfStat.Total, 696 sizeof(EXT2_STAT_ARRAY_V1)); 697 } 698 699 } else { 700 Status = STATUS_INVALID_PARAMETER; 701 _SEH2_LEAVE; 702 } 703 704 if (NT_SUCCESS(Status)) { 705 IrpContext->Irp->IoStatus.Information = Length; 706 } 707 708 } _SEH2_FINALLY { 709 710 if (GlobalDataResourceAcquired) { 711 ExReleaseResourceLite(&Ext2Global->Resource); 712 } 713 714 if (!IrpContext->ExceptionInProgress) { 715 Ext2CompleteIrpContext(IrpContext, Status); 716 } 717 } _SEH2_END 718 719 return Status; 720 } 721 722 NTSTATUS 723 Ex2ProcessMountPoint( 724 IN PEXT2_IRP_CONTEXT IrpContext, 725 IN PEXT2_MOUNT_POINT MountPoint, 726 IN ULONG Length 727 ) 728 { 729 UNICODE_STRING Link; 730 UNICODE_STRING Target; 731 WCHAR Buffer[] = L"\\DosDevices\\Global\\Z:"; 732 NTSTATUS status = STATUS_SUCCESS; 733 734 PDEVICE_OBJECT DeviceObject = NULL; 735 736 _SEH2_TRY { 737 738 ASSERT(IrpContext != NULL); 739 ASSERT((IrpContext->Identifier.Type == EXT2ICX) && 740 (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT))); 741 742 DeviceObject = IrpContext->DeviceObject; 743 if (!IsExt2FsDevice(DeviceObject)) { 744 status = STATUS_INVALID_PARAMETER; 745 _SEH2_LEAVE; 746 } 747 748 if (Length != sizeof(EXT2_MOUNT_POINT) || 749 MountPoint->Magic != EXT2_APP_MOUNTPOINT_MAGIC) { 750 status = STATUS_INVALID_PARAMETER; 751 _SEH2_LEAVE; 752 } 753 754 RtlInitUnicodeString(&Link, Buffer); 755 Buffer[12] = MountPoint->Link[0]; 756 757 switch (MountPoint->Command) { 758 759 case APP_CMD_ADD_DOS_SYMLINK: 760 RtlInitUnicodeString(&Target, &MountPoint->Name[0]); 761 status = IoCreateSymbolicLink(&Link, &Target); 762 break; 763 764 case APP_CMD_DEL_DOS_SYMLINK: 765 status = IoDeleteSymbolicLink(&Link); 766 break; 767 768 default: 769 status = STATUS_INVALID_PARAMETER; 770 } 771 772 } _SEH2_FINALLY { 773 774 if (!IrpContext->ExceptionInProgress) { 775 Ext2CompleteIrpContext(IrpContext, status); 776 } 777 } _SEH2_END; 778 779 return status; 780 } 781 782 NTSTATUS 783 Ext2DeviceControl (IN PEXT2_IRP_CONTEXT IrpContext) 784 { 785 PIRP Irp; 786 PIO_STACK_LOCATION irpSp; 787 ULONG code; 788 ULONG length; 789 NTSTATUS Status; 790 791 ASSERT(IrpContext); 792 793 ASSERT((IrpContext->Identifier.Type == EXT2ICX) && 794 (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT))); 795 796 Irp = IrpContext->Irp; 797 798 irpSp = IoGetCurrentIrpStackLocation(Irp); 799 800 code = irpSp->Parameters.DeviceIoControl.IoControlCode; 801 length = irpSp->Parameters.DeviceIoControl.OutputBufferLength; 802 803 switch (code) { 804 805 case IOCTL_APP_VOLUME_PROPERTY: 806 Status = Ext2ProcessUserProperty( 807 IrpContext, 808 Irp->AssociatedIrp.SystemBuffer, 809 length 810 ); 811 break; 812 813 case IOCTL_APP_QUERY_PERFSTAT: 814 Status = Ex2ProcessUserPerfStat( 815 IrpContext, 816 Irp->AssociatedIrp.SystemBuffer, 817 length 818 ); 819 break; 820 821 case IOCTL_APP_MOUNT_POINT: 822 Status = Ex2ProcessMountPoint( 823 IrpContext, 824 Irp->AssociatedIrp.SystemBuffer, 825 length 826 ); 827 break; 828 829 #if EXT2_UNLOAD 830 case IOCTL_PREPARE_TO_UNLOAD: 831 Status = Ext2PrepareToUnload(IrpContext); 832 break; 833 #endif 834 default: 835 Status = Ext2DeviceControlNormal(IrpContext); 836 } 837 838 return Status; 839 } 840