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