1 /*++ 2 3 Copyright (C) Microsoft Corporation, 1991 - 2010 4 5 Module Name: 6 7 disk.c 8 9 Abstract: 10 11 SCSI disk class driver 12 13 Environment: 14 15 kernel mode only 16 17 Notes: 18 19 Revision History: 20 21 --*/ 22 23 #include "ntddk.h" 24 #include "scsi.h" 25 #include <wmidata.h> 26 #include "classpnp.h" 27 28 #include <wmistr.h> 29 #include "ntstrsafe.h" 30 31 // 32 // Set component ID for DbgPrintEx calls 33 // 34 #ifndef DEBUG_COMP_ID 35 #define DEBUG_COMP_ID DPFLTR_DISK_ID 36 #endif 37 38 // 39 // Include header file and setup GUID for tracing 40 // 41 #include <storswtr.h> 42 #define WPP_GUID_DISK (945186BF, 3DD6, 4f3f, 9C8E, 9EDD3FC9D558) 43 #ifndef WPP_CONTROL_GUIDS 44 #define WPP_CONTROL_GUIDS WPP_CONTROL_GUIDS_NORMAL_FLAGS(WPP_GUID_DISK) 45 #endif 46 47 48 #ifdef ExAllocatePool 49 #undef ExAllocatePool 50 #define ExAllocatePool #NT_ASSERT(FALSE) 51 #endif 52 53 #define DISK_TAG_GENERAL ' DcS' // "ScD " - generic tag 54 #define DISK_TAG_SMART 'aDcS' // "ScDa" - SMART allocations 55 #define DISK_TAG_INFO_EXCEPTION 'ADcS' // "ScDA" - Info Exceptions 56 #define DISK_TAG_DISABLE_CACHE 'CDcS' // "ScDC" - disable cache paths 57 #define DISK_TAG_CCONTEXT 'cDcS' // "ScDc" - disk allocated completion context 58 #define DISK_TAG_DISK_GEOM 'GDcS' // "ScDG" - disk geometry buffer 59 #define DISK_TAG_UPDATE_GEOM 'gDcS' // "ScDg" - update disk geometry paths 60 #define DISK_TAG_SENSE_INFO 'IDcS' // "ScDI" - sense info buffers 61 #define DISK_TAG_PNP_ID 'iDcS' // "ScDp" - pnp ids 62 #define DISK_TAG_MODE_DATA 'MDcS' // "ScDM" - mode data buffer 63 #define DISK_CACHE_MBR_CHECK 'mDcS' // "ScDM" - mbr checksum code 64 #define DISK_TAG_NAME 'NDcS' // "ScDN" - disk name code 65 #define DISK_TAG_READ_CAP 'PDcS' // "ScDP" - read capacity buffer 66 #define DISK_TAG_PART_LIST 'pDcS' // "ScDp" - disk partition lists 67 #define DISK_TAG_SRB 'SDcS' // "ScDS" - srb allocation 68 #define DISK_TAG_START 'sDcS' // "ScDs" - start device paths 69 #define DISK_TAG_UPDATE_CAP 'UDcS' // "ScDU" - update capacity path 70 #define DISK_TAG_WI_CONTEXT 'WDcS' // "ScDW" - work-item context 71 72 #ifdef __REACTOS__ 73 #undef MdlMappingNoExecute 74 #define MdlMappingNoExecute 0 75 #define NonPagedPoolNx NonPagedPool 76 #define NonPagedPoolNxCacheAligned NonPagedPoolCacheAligned 77 #undef POOL_NX_ALLOCATION 78 #define POOL_NX_ALLOCATION 0 79 #endif 80 81 82 #if defined(_X86_) || defined(_AMD64_) 83 84 // 85 // Disk device data 86 // 87 88 typedef enum _DISK_GEOMETRY_SOURCE { 89 DiskGeometryUnknown, 90 DiskGeometryFromBios, 91 DiskGeometryFromPort, 92 DiskGeometryFromNec98, 93 DiskGeometryGuessedFromBios, 94 DiskGeometryFromDefault, 95 DiskGeometryFromNT4 96 } DISK_GEOMETRY_SOURCE, *PDISK_GEOMETRY_SOURCE; 97 #endif 98 99 // 100 // Context for requests that can be combined and sent down 101 // 102 103 typedef struct _DISK_GROUP_CONTEXT 104 { 105 // 106 // Queue of requests whose representative is currently outstanding at the port driver 107 // 108 LIST_ENTRY CurrList; 109 110 // 111 // The representative for the above queue 112 // 113 PIRP CurrIrp; 114 115 // 116 // Queue of requests whose representative is waiting to go down 117 // 118 LIST_ENTRY NextList; 119 120 // 121 // The representative for the above queue 122 // 123 PIRP NextIrp; 124 125 // 126 // The srb associated with this group 127 // 128 #if (NTDDI_VERSION >= NTDDI_WIN8) 129 130 union { 131 SCSI_REQUEST_BLOCK Srb; 132 STORAGE_REQUEST_BLOCK SrbEx; 133 UCHAR SrbExBuffer[CLASS_SRBEX_SCSI_CDB16_BUFFER_SIZE]; 134 } Srb; 135 136 #else 137 SCSI_REQUEST_BLOCK Srb; 138 #endif 139 140 // 141 // The spinlock that will synchronize access to this context 142 // 143 KSPIN_LOCK Spinlock; 144 145 // 146 // This event will allow for the requests to be sent down synchronously 147 // 148 KEVENT Event; 149 150 151 #if DBG 152 153 // 154 // This counter maintains the number of requests currently tagged 155 // to the request that is waiting to go down 156 // 157 ULONG DbgTagCount; 158 159 // 160 // This counter maintains the number of requests that were avoided 161 // 162 ULONG DbgSavCount; 163 164 // 165 // This counter maintains the total number of times that we combined 166 // requests and the respective number of requests that were tagged 167 // 168 ULONG DbgRefCount[64]; 169 170 #endif 171 172 } DISK_GROUP_CONTEXT, *PDISK_GROUP_CONTEXT; 173 174 // 175 // Write cache setting as defined by the user 176 // 177 typedef enum _DISK_USER_WRITE_CACHE_SETTING 178 { 179 DiskWriteCacheDisable = 0, 180 DiskWriteCacheEnable = 1, 181 DiskWriteCacheDefault = -1 182 183 } DISK_USER_WRITE_CACHE_SETTING, *PDISK_USER_WRITE_CACHE_SETTING; 184 185 typedef struct _DISK_DATA { 186 187 // 188 // This field is the ordinal of a partition as it appears on a disk. 189 // 190 191 ULONG PartitionOrdinal; 192 193 // 194 // How has this disk been partitioned? Either EFI or MBR. 195 // 196 197 PARTITION_STYLE PartitionStyle; 198 199 union { 200 201 struct { 202 203 // 204 // Disk signature (from MBR) 205 // 206 207 ULONG Signature; 208 209 // 210 // MBR checksum 211 // 212 213 ULONG MbrCheckSum; 214 215 // 216 // Number of hidden sectors for BPB. 217 // 218 219 ULONG HiddenSectors; 220 221 // 222 // Partition type of this device object 223 // 224 // This field is set by: 225 // 226 // 1. Initially set according to the partition list entry 227 // partition type returned by IoReadPartitionTable. 228 // 229 // 2. Subsequently set by the 230 // IOCTL_DISK_SET_PARTITION_INFORMATION I/O control 231 // function when IoSetPartitionInformation function 232 // successfully updates the partition type on the disk. 233 // 234 235 UCHAR PartitionType; 236 237 // 238 // Boot indicator - indicates whether this partition is a 239 // bootable (active) partition for this device 240 // 241 // This field is set according to the partition list entry boot 242 // indicator returned by IoReadPartitionTable. 243 // 244 245 BOOLEAN BootIndicator; 246 247 } Mbr; 248 249 struct { 250 251 // 252 // The DiskGUID field from the EFI partition header. 253 // 254 255 GUID DiskId; 256 257 // 258 // Partition type of this device object. 259 // 260 261 GUID PartitionType; 262 263 // 264 // Unique partition identifier for this partition. 265 // 266 267 GUID PartitionId; 268 269 // 270 // EFI partition attributes for this partition. 271 // 272 273 ULONG64 Attributes; 274 275 // 276 // EFI partition name of this partition. 277 // 278 279 WCHAR PartitionName[36]; 280 281 } Efi; 282 283 #ifdef _MSC_VER 284 #pragma warning(suppress: 4201) //this is intended to be an unnamed union 285 #endif 286 }; 287 288 struct { 289 // 290 // This flag is set when the well known name is created (through 291 // DiskCreateSymbolicLinks) and cleared when destroying it 292 // (by calling DiskDeleteSymbolicLinks). 293 // 294 295 unsigned int WellKnownNameCreated : 1; 296 297 // 298 // This flag is set when the PhysicalDriveN link is created (through 299 // DiskCreateSymbolicLinks) and is cleared when destroying it (through 300 // DiskDeleteSymbolicLinks) 301 // 302 303 unsigned int PhysicalDriveLinkCreated : 1; 304 305 } LinkStatus; 306 307 // 308 // ReadyStatus - STATUS_SUCCESS indicates that the drive is ready for 309 // use. Any error status is to be returned as an explaination for why 310 // a request is failed. 311 // 312 // This was done solely for the zero-length partition case of having no 313 // media in a removable disk drive. When that occurs, and a read is sent 314 // to the zero-length non-partition-zero PDO that was created, we had to 315 // be able to fail the request with a reasonable value. This may not have 316 // been the best way to do this, but it works. 317 // 318 319 NTSTATUS ReadyStatus; 320 321 // 322 // SCSI address used for SMART operations. 323 // 324 325 SCSI_ADDRESS ScsiAddress; 326 327 // 328 // What type of failure prediction mechanism is available 329 // 330 331 FAILURE_PREDICTION_METHOD FailurePredictionCapability; 332 BOOLEAN AllowFPPerfHit; 333 334 // 335 // Indicates that the SCSI Informational Exceptions mode page is supported. 336 // Note that this only indicates *support* and does not necessarily 337 // indicate that Informational Exception reporting via sense code is 338 // actually enabled. 339 // 340 BOOLEAN ScsiInfoExceptionsSupported; 341 342 // 343 // Indicates if failure prediction is actually enabled (via whatever) 344 // method is applicable as indicated by FailurePredictionCapability. 345 // 346 BOOLEAN FailurePredictionEnabled; 347 348 #if defined(_X86_) || defined(_AMD64_) 349 // 350 // This flag indiciates that a non-default geometry for this drive has 351 // already been determined by the disk driver. This field is ignored 352 // for removable media drives. 353 // 354 355 DISK_GEOMETRY_SOURCE GeometrySource; 356 357 // 358 // If GeometryDetermined is TRUE this will contain the geometry which was 359 // reported by the firmware or by the BIOS. For removable media drives 360 // this will contain the last geometry used when media was present. 361 // 362 363 DISK_GEOMETRY RealGeometry; 364 #endif 365 366 // 367 // This mutex prevents more than one IOCTL_DISK_VERIFY from being 368 // sent down to the disk. This greatly reduces the possibility of 369 // a Denial-of-Service attack 370 // 371 372 KMUTEX VerifyMutex; 373 374 // 375 // This allows for parallel flush requests to be combined into one so as to 376 // reduce the number of outstanding requests that are sent down to the disk 377 // 378 379 DISK_GROUP_CONTEXT FlushContext; 380 381 // 382 // The user-specified disk write cache setting 383 // 384 385 DISK_USER_WRITE_CACHE_SETTING WriteCacheOverride; 386 387 388 } DISK_DATA, *PDISK_DATA; 389 390 // 391 // Define a general structure of identfing disk controllers with bad 392 // hardware. 393 // 394 395 #define HackDisableTaggedQueuing (0x01) 396 #define HackDisableSynchronousTransfers (0x02) 397 #define HackDisableSpinDown (0x04) 398 #define HackDisableWriteCache (0x08) 399 #define HackCauseNotReportableHack (0x10) 400 #define HackRequiresStartUnitCommand (0x20) 401 402 403 #define DiskDeviceParameterSubkey L"Disk" 404 #define DiskDeviceUserWriteCacheSetting L"UserWriteCacheSetting" 405 #define DiskDeviceCacheIsPowerProtected L"CacheIsPowerProtected" 406 407 408 #define FUNCTIONAL_EXTENSION_SIZE sizeof(FUNCTIONAL_DEVICE_EXTENSION) + sizeof(DISK_DATA) 409 410 #define MODE_DATA_SIZE 192 411 #define VALUE_BUFFER_SIZE 2048 412 #define SCSI_DISK_TIMEOUT 10 413 #define PARTITION0_LIST_SIZE 4 414 415 #define MAX_MEDIA_TYPES 4 416 typedef struct _DISK_MEDIA_TYPES_LIST { 417 PCCHAR VendorId; 418 PCCHAR ProductId; 419 PCCHAR Revision; 420 const ULONG NumberOfTypes; 421 const ULONG NumberOfSides; 422 const STORAGE_MEDIA_TYPE MediaTypes[MAX_MEDIA_TYPES]; 423 } DISK_MEDIA_TYPES_LIST, *PDISK_MEDIA_TYPES_LIST; 424 425 // 426 // WMI reregistration structures used for reregister work item 427 // 428 typedef struct 429 { 430 SINGLE_LIST_ENTRY Next; 431 PDEVICE_OBJECT DeviceObject; 432 PIRP Irp; 433 } DISKREREGREQUEST, *PDISKREREGREQUEST; 434 435 #define MAX_SECTORS_PER_VERIFY 0x100 436 437 // 438 // This is based off 100ns units 439 // 440 #define ONE_MILLI_SECOND ((ULONGLONG)10 * 1000) 441 442 // 443 // Context for the work-item 444 // 445 typedef struct _DISK_VERIFY_WORKITEM_CONTEXT 446 { 447 PIRP Irp; 448 PSCSI_REQUEST_BLOCK Srb; 449 PIO_WORKITEM WorkItem; 450 451 } DISK_VERIFY_WORKITEM_CONTEXT, *PDISK_VERIFY_WORKITEM_CONTEXT; 452 453 // 454 // Poll for Failure Prediction every hour 455 // 456 #define DISK_DEFAULT_FAILURE_POLLING_PERIOD 1 * 60 * 60 457 458 #define CHECK_IRQL() \ 459 if (KeGetCurrentIrql() >= DISPATCH_LEVEL) { \ 460 NT_ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL); \ 461 return STATUS_INVALID_LEVEL; \ 462 } 463 464 // 465 // Static global lookup tables. 466 // 467 468 extern CLASSPNP_SCAN_FOR_SPECIAL_INFO DiskBadControllers[]; 469 extern const DISK_MEDIA_TYPES_LIST DiskMediaTypes[]; 470 extern const DISK_MEDIA_TYPES_LIST DiskMediaTypesExclude[]; 471 472 #if defined(__REACTOS__) && defined(_MSC_VER) 473 # pragma section("PAGECONS", read) 474 # pragma section("PAGEDATA", read,write) 475 #endif 476 // 477 // Macros 478 // 479 480 // 481 // Routine prototypes. 482 // 483 484 485 DRIVER_INITIALIZE DriverEntry; 486 487 VOID 488 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */ 489 DiskUnload( 490 IN PDRIVER_OBJECT DriverObject 491 ); 492 493 NTSTATUS 494 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */ 495 DiskAddDevice( 496 IN PDRIVER_OBJECT DriverObject, 497 IN PDEVICE_OBJECT Pdo 498 ); 499 500 NTSTATUS 501 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */ 502 DiskInitFdo( 503 IN PDEVICE_OBJECT Fdo 504 ); 505 506 NTSTATUS 507 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */ 508 DiskStartFdo( 509 IN PDEVICE_OBJECT Fdo 510 ); 511 512 NTSTATUS 513 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */ 514 DiskStopDevice( 515 IN PDEVICE_OBJECT DeviceObject, 516 IN UCHAR Type 517 ); 518 519 NTSTATUS 520 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */ 521 DiskRemoveDevice( 522 IN PDEVICE_OBJECT DeviceObject, 523 IN UCHAR Type 524 ); 525 526 NTSTATUS 527 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */ 528 DiskReadWriteVerification( 529 IN PDEVICE_OBJECT DeviceObject, 530 IN PIRP Irp 531 ); 532 533 NTSTATUS 534 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */ 535 DiskDeviceControl( 536 IN PDEVICE_OBJECT DeviceObject, 537 IN PIRP Irp 538 ); 539 540 VOID 541 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */ 542 DiskFdoProcessError( 543 PDEVICE_OBJECT DeviceObject, 544 PSCSI_REQUEST_BLOCK Srb, 545 NTSTATUS *Status, 546 BOOLEAN *Retry 547 ); 548 549 NTSTATUS 550 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */ 551 DiskShutdownFlush( 552 IN PDEVICE_OBJECT DeviceObject, 553 IN PIRP Irp 554 ); 555 556 NTSTATUS 557 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */ 558 DiskGetCacheInformation( 559 IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, 560 IN PDISK_CACHE_INFORMATION CacheInfo 561 ); 562 563 NTSTATUS 564 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */ 565 DiskSetCacheInformation( 566 IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, 567 IN PDISK_CACHE_INFORMATION CacheInfo 568 ); 569 570 VOID 571 DiskLogCacheInformation( 572 IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, 573 IN PDISK_CACHE_INFORMATION CacheInfo, 574 IN NTSTATUS Status 575 ); 576 577 NTSTATUS 578 DiskIoctlGetCacheSetting( 579 IN PDEVICE_OBJECT DeviceObject, 580 IN PIRP Irp 581 ); 582 583 NTSTATUS 584 DiskIoctlSetCacheSetting( 585 IN PDEVICE_OBJECT DeviceObject, 586 IN PIRP Irp 587 ); 588 589 IO_WORKITEM_ROUTINE DisableWriteCache; 590 591 IO_WORKITEM_ROUTINE DiskIoctlVerifyThread; 592 593 VOID 594 DiskFlushDispatch( 595 IN PDEVICE_OBJECT Fdo, 596 IN PDISK_GROUP_CONTEXT FlushContext 597 ); 598 599 IO_COMPLETION_ROUTINE DiskFlushComplete; 600 601 602 NTSTATUS 603 DiskModeSelect( 604 IN PDEVICE_OBJECT DeviceObject, 605 _In_reads_bytes_(Length) PCHAR ModeSelectBuffer, 606 IN ULONG Length, 607 IN BOOLEAN SavePage 608 ); 609 610 // 611 // We need to validate that the self test subcommand is valid and 612 // appropriate. Right now we allow subcommands 0, 1 and 2 which are non 613 // captive mode tests. Once we figure out a way to know if it is safe to 614 // run a captive test then we can allow captive mode tests. Also if the 615 // atapi 5 spec is ever updated to denote that bit 7 is the captive 616 // mode bit, we can allow any request that does not have bit 7 set. Until 617 // that is done we want to be sure 618 // 619 #define DiskIsValidSmartSelfTest(Subcommand) \ 620 ( ((Subcommand) == SMART_OFFLINE_ROUTINE_OFFLINE) || \ 621 ((Subcommand) == SMART_SHORT_SELFTEST_OFFLINE) || \ 622 ((Subcommand) == SMART_EXTENDED_SELFTEST_OFFLINE) ) 623 624 625 NTSTATUS 626 DiskPerformSmartCommand( 627 IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, 628 IN ULONG SrbControlCode, 629 IN UCHAR Command, 630 IN UCHAR Feature, 631 IN UCHAR SectorCount, 632 IN UCHAR SectorNumber, 633 IN OUT PSRB_IO_CONTROL SrbControl, 634 OUT PULONG BufferSize 635 ); 636 637 NTSTATUS 638 DiskGetInfoExceptionInformation( 639 IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, 640 OUT PMODE_INFO_EXCEPTIONS ReturnPageData 641 ); 642 643 NTSTATUS 644 DiskSetInfoExceptionInformation( 645 IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, 646 IN PMODE_INFO_EXCEPTIONS PageData 647 ); 648 649 #if (NTDDI_VERSION >= NTDDI_WINBLUE) 650 NTSTATUS 651 DiskGetModePage( 652 _In_ PDEVICE_OBJECT Fdo, 653 _In_ UCHAR PageMode, 654 _In_ UCHAR PageControl, 655 _In_ PMODE_PARAMETER_HEADER ModeData, 656 _Inout_ PULONG ModeDataSize, 657 _Out_ PVOID* PageData 658 ); 659 660 NTSTATUS 661 DiskEnableInfoExceptions( 662 _In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, 663 _In_ BOOLEAN Enable 664 ); 665 #endif // (NTDDI_VERSION >= NTDDI_WINBLUE) 666 667 NTSTATUS 668 DiskDetectFailurePrediction( 669 PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, 670 PFAILURE_PREDICTION_METHOD FailurePredictCapability, 671 BOOLEAN ScsiAddressAvailable 672 ); 673 674 NTSTATUS 675 DiskCreateFdo( 676 IN PDRIVER_OBJECT DriverObject, 677 IN PDEVICE_OBJECT LowerDeviceObject, 678 IN PULONG DeviceCount, 679 IN BOOLEAN DasdAccessOnly 680 ); 681 682 VOID 683 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */ 684 DiskSetSpecialHacks( 685 IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, 686 IN ULONG_PTR Data 687 ); 688 689 VOID 690 ResetBus( 691 IN PDEVICE_OBJECT DeviceObject 692 ); 693 694 NTSTATUS 695 DiskGenerateDeviceName( 696 IN ULONG DeviceNumber, 697 OUT PCCHAR *RawName 698 ); 699 700 VOID 701 DiskCreateSymbolicLinks( 702 IN PDEVICE_OBJECT DeviceObject 703 ); 704 705 VOID 706 DiskDeleteSymbolicLinks( 707 IN PDEVICE_OBJECT DeviceObject 708 ); 709 710 711 NTSTATUS 712 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */ 713 DiskFdoQueryWmiRegInfo( 714 IN PDEVICE_OBJECT DeviceObject, 715 OUT ULONG *RegFlags, 716 OUT PUNICODE_STRING InstanceName 717 ); 718 719 NTSTATUS 720 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */ 721 DiskFdoQueryWmiRegInfoEx( 722 IN PDEVICE_OBJECT DeviceObject, 723 OUT ULONG *RegFlags, 724 OUT PUNICODE_STRING InstanceName, 725 OUT PUNICODE_STRING MofName 726 ); 727 728 NTSTATUS 729 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */ 730 DiskFdoQueryWmiDataBlock( 731 IN PDEVICE_OBJECT DeviceObject, 732 IN PIRP Irp, 733 IN ULONG GuidIndex, 734 IN ULONG BufferAvail, 735 OUT PUCHAR Buffer 736 ); 737 738 NTSTATUS 739 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */ 740 DiskFdoSetWmiDataBlock( 741 IN PDEVICE_OBJECT DeviceObject, 742 IN PIRP Irp, 743 IN ULONG GuidIndex, 744 IN ULONG BufferSize, 745 IN PUCHAR Buffer 746 ); 747 748 NTSTATUS 749 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */ 750 DiskFdoSetWmiDataItem( 751 IN PDEVICE_OBJECT DeviceObject, 752 IN PIRP Irp, 753 IN ULONG GuidIndex, 754 IN ULONG DataItemId, 755 IN ULONG BufferSize, 756 IN PUCHAR Buffer 757 ); 758 759 NTSTATUS 760 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */ 761 DiskFdoExecuteWmiMethod( 762 IN PDEVICE_OBJECT DeviceObject, 763 IN PIRP Irp, 764 IN ULONG GuidIndex, 765 IN ULONG MethodId, 766 IN ULONG InBufferSize, 767 IN ULONG OutBufferSize, 768 IN PUCHAR Buffer 769 ); 770 771 NTSTATUS 772 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */ 773 DiskWmiFunctionControl( 774 IN PDEVICE_OBJECT DeviceObject, 775 IN PIRP Irp, 776 IN ULONG GuidIndex, 777 IN CLASSENABLEDISABLEFUNCTION Function, 778 IN BOOLEAN Enable 779 ); 780 781 NTSTATUS 782 DiskReadFailurePredictStatus( 783 PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, 784 PSTORAGE_FAILURE_PREDICT_STATUS DiskSmartStatus 785 ); 786 787 NTSTATUS 788 DiskReadFailurePredictData( 789 PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, 790 PSTORAGE_FAILURE_PREDICT_DATA DiskSmartData 791 ); 792 793 NTSTATUS 794 DiskEnableDisableFailurePrediction( 795 PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, 796 BOOLEAN Enable 797 ); 798 799 NTSTATUS 800 DiskEnableDisableFailurePredictPolling( 801 PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, 802 BOOLEAN Enable, 803 ULONG PollTimeInSeconds 804 ); 805 806 NTSTATUS DiskInitializeReregistration( 807 VOID 808 ); 809 810 extern GUIDREGINFO DiskWmiFdoGuidList[]; 811 812 #if defined(_X86_) || defined(_AMD64_) 813 NTSTATUS 814 DiskReadDriveCapacity( 815 IN PDEVICE_OBJECT Fdo 816 ); 817 #else 818 #define DiskReadDriveCapacity(Fdo) ClassReadDriveCapacity(Fdo) 819 #endif 820 821 822 #if defined(_X86_) || defined(_AMD64_) 823 824 NTSTATUS 825 DiskSaveDetectInfo( 826 PDRIVER_OBJECT DriverObject 827 ); 828 829 VOID 830 DiskCleanupDetectInfo( 831 IN PDRIVER_OBJECT DriverObject 832 ); 833 834 VOID 835 DiskDriverReinitialization ( 836 IN PDRIVER_OBJECT DriverObject, 837 IN PVOID Nothing, 838 IN ULONG Count 839 ); 840 841 #endif 842 843 #if defined(_X86_) || defined(_AMD64_) 844 NTSTATUS 845 DiskGetDetectInfo( 846 IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, 847 OUT PDISK_DETECTION_INFO DetectInfo 848 ); 849 850 NTSTATUS 851 DiskReadSignature( 852 IN PDEVICE_OBJECT Fdo 853 ); 854 855 BOOLEAN 856 DiskIsNT4Geometry( 857 IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension 858 ); 859 860 #else 861 #define DiskGetDetectInfo(FdoExtension, DetectInfo) (STATUS_UNSUCCESSFUL) 862 #endif 863 864 865 #define DiskHashGuid(Guid) (((PULONG) &Guid)[0] ^ ((PULONG) &Guid)[0] ^ ((PULONG) &Guid)[0] ^ ((PULONG) &Guid)[0]) 866 867 868 NTSTATUS 869 DiskDetermineMediaTypes( 870 IN PDEVICE_OBJECT Fdo, 871 IN PIRP Irp, 872 IN UCHAR MediumType, 873 IN UCHAR DensityCode, 874 IN BOOLEAN MediaPresent, 875 IN BOOLEAN IsWritable 876 ); 877 878 NTSTATUS 879 DiskIoctlGetLengthInfo( 880 IN PDEVICE_OBJECT DeviceObject, 881 IN PIRP Irp 882 ); 883 884 NTSTATUS 885 DiskIoctlGetDriveGeometry( 886 IN PDEVICE_OBJECT DeviceObject, 887 IN OUT PIRP Irp 888 ); 889 890 NTSTATUS 891 DiskIoctlGetDriveGeometryEx( 892 IN PDEVICE_OBJECT DeviceObject, 893 IN PIRP Irp 894 ); 895 896 NTSTATUS 897 DiskIoctlGetCacheInformation( 898 IN PDEVICE_OBJECT DeviceObject, 899 IN OUT PIRP Irp 900 ); 901 902 NTSTATUS 903 DiskIoctlSetCacheInformation( 904 IN PDEVICE_OBJECT DeviceObject, 905 IN OUT PIRP Irp 906 ); 907 908 NTSTATUS 909 DiskIoctlGetMediaTypesEx( 910 IN PDEVICE_OBJECT DeviceObject, 911 IN OUT PIRP Irp 912 ); 913 914 NTSTATUS 915 DiskIoctlPredictFailure( 916 IN PDEVICE_OBJECT DeviceObject, 917 IN OUT PIRP Irp 918 ); 919 920 NTSTATUS 921 DiskIoctlEnableFailurePrediction( 922 IN PDEVICE_OBJECT DeviceObject, 923 IN OUT PIRP Irp 924 ); 925 926 NTSTATUS 927 DiskIoctlVerify( 928 IN PDEVICE_OBJECT DeviceObject, 929 IN OUT PIRP Irp 930 ); 931 932 NTSTATUS 933 DiskIoctlReassignBlocks( 934 IN PDEVICE_OBJECT DeviceObject, 935 IN OUT PIRP Irp 936 ); 937 938 NTSTATUS 939 DiskIoctlReassignBlocksEx( 940 IN PDEVICE_OBJECT DeviceObject, 941 IN OUT PIRP Irp 942 ); 943 944 NTSTATUS 945 DiskIoctlIsWritable( 946 IN PDEVICE_OBJECT DeviceObject, 947 IN OUT PIRP Irp 948 ); 949 950 NTSTATUS 951 DiskIoctlSetVerify( 952 IN PDEVICE_OBJECT DeviceObject, 953 IN OUT PIRP Irp 954 ); 955 956 NTSTATUS 957 DiskIoctlClearVerify( 958 IN PDEVICE_OBJECT DeviceObject, 959 IN OUT PIRP Irp 960 ); 961 962 NTSTATUS 963 DiskIoctlUpdateDriveSize( 964 IN PDEVICE_OBJECT DeviceObject, 965 IN OUT PIRP Irp 966 ); 967 968 NTSTATUS 969 DiskIoctlGetVolumeDiskExtents( 970 IN PDEVICE_OBJECT DeviceObject, 971 IN OUT PIRP Irp 972 ); 973 974 NTSTATUS 975 DiskIoctlSmartGetVersion( 976 IN PDEVICE_OBJECT DeviceObject, 977 IN OUT PIRP Irp 978 ); 979 980 NTSTATUS 981 DiskIoctlSmartReceiveDriveData( 982 IN PDEVICE_OBJECT DeviceObject, 983 IN OUT PIRP Irp 984 ); 985 986 NTSTATUS 987 DiskIoctlSmartSendDriveCommand( 988 IN PDEVICE_OBJECT DeviceObject, 989 IN OUT PIRP Irp 990 ); 991 992 FORCEINLINE // __REACTOS__ 993 PCDB 994 GetSrbScsiData( 995 _In_ PSTORAGE_REQUEST_BLOCK SrbEx, 996 _In_opt_ PUCHAR CdbLength8, 997 _In_opt_ PULONG CdbLength32, 998 _In_opt_ PUCHAR ScsiStatus, 999 _In_opt_ PVOID *SenseInfoBuffer, 1000 _In_opt_ PUCHAR SenseInfoBufferLength 1001 ) 1002 /*++ 1003 1004 Routine Description: 1005 1006 Helper function to retrieve SCSI related fields from an extended SRB. If SRB is 1007 not a SRB_FUNCTION_EXECUTE_SCSI or not an extended SRB, default values will be returned. 1008 1009 Arguments: 1010 1011 SrbEx - Pointer to extended SRB. 1012 1013 CdbLength8 - Pointer to buffer to hold CdbLength field value for 1014 SRBEX_DATA_SCSI_CDB16 or SRBEX_DATA_SCSI_CDB32 1015 1016 CdbLength32 - Pointer to buffer to hold CdbLength field value for 1017 SRBEX_DATA_SCSI_CDB_VAR 1018 1019 ScsiStatus - Pointer to buffer to hold ScsiStatus field value. 1020 1021 SenseInfoBuffer - Pointer to buffer to hold SenseInfoBuffer value. 1022 1023 SenseInfoBufferLength - Pointer to buffer to hold SenseInfoBufferLength value. 1024 1025 Return Value: 1026 1027 Pointer to Cdb field or NULL if SRB is not a SRB_FUNCTION_EXECUTE_SCSI. 1028 1029 --*/ 1030 { 1031 PCDB Cdb = NULL; 1032 ULONG i; 1033 PSRBEX_DATA SrbExData = NULL; 1034 BOOLEAN FoundEntry = FALSE; 1035 1036 if ((SrbEx->Function == SRB_FUNCTION_STORAGE_REQUEST_BLOCK) && 1037 (SrbEx->SrbFunction == SRB_FUNCTION_EXECUTE_SCSI)) { 1038 NT_ASSERT(SrbEx->NumSrbExData > 0); 1039 1040 for (i = 0; i < SrbEx->NumSrbExData; i++) { 1041 1042 // Skip any invalid offsets 1043 if ((SrbEx->SrbExDataOffset[i] < sizeof(STORAGE_REQUEST_BLOCK)) || 1044 (SrbEx->SrbExDataOffset[i] > SrbEx->SrbLength)){ 1045 // Catch any invalid offsets 1046 NT_ASSERT(FALSE); 1047 continue; 1048 } 1049 1050 SrbExData = (PSRBEX_DATA)((PUCHAR)SrbEx + SrbEx->SrbExDataOffset[i]); 1051 1052 switch (SrbExData->Type) { 1053 1054 case SrbExDataTypeScsiCdb16: 1055 if (SrbEx->SrbExDataOffset[i] + sizeof(SRBEX_DATA_SCSI_CDB16) <= SrbEx->SrbLength) { 1056 FoundEntry = TRUE; 1057 if (CdbLength8) { 1058 *CdbLength8 = ((PSRBEX_DATA_SCSI_CDB16) SrbExData)->CdbLength; 1059 } 1060 1061 if (((PSRBEX_DATA_SCSI_CDB16) SrbExData)->CdbLength > 0) { 1062 Cdb = (PCDB)((PSRBEX_DATA_SCSI_CDB16) SrbExData)->Cdb; 1063 } 1064 1065 if (ScsiStatus) { 1066 *ScsiStatus = 1067 ((PSRBEX_DATA_SCSI_CDB16) SrbExData)->ScsiStatus; 1068 } 1069 1070 if (SenseInfoBuffer) { 1071 *SenseInfoBuffer = 1072 ((PSRBEX_DATA_SCSI_CDB16) SrbExData)->SenseInfoBuffer; 1073 } 1074 1075 if (SenseInfoBufferLength) { 1076 *SenseInfoBufferLength = 1077 ((PSRBEX_DATA_SCSI_CDB16) SrbExData)->SenseInfoBufferLength; 1078 } 1079 1080 } else { 1081 // Catch invalid offset 1082 NT_ASSERT(FALSE); 1083 } 1084 break; 1085 1086 case SrbExDataTypeScsiCdb32: 1087 if (SrbEx->SrbExDataOffset[i] + sizeof(SRBEX_DATA_SCSI_CDB32) <= SrbEx->SrbLength) { 1088 FoundEntry = TRUE; 1089 if (CdbLength8) { 1090 *CdbLength8 = ((PSRBEX_DATA_SCSI_CDB32) SrbExData)->CdbLength; 1091 } 1092 1093 if (((PSRBEX_DATA_SCSI_CDB32) SrbExData)->CdbLength > 0) { 1094 Cdb = (PCDB)((PSRBEX_DATA_SCSI_CDB32) SrbExData)->Cdb; 1095 } 1096 1097 if (ScsiStatus) { 1098 *ScsiStatus = 1099 ((PSRBEX_DATA_SCSI_CDB32) SrbExData)->ScsiStatus; 1100 } 1101 1102 if (SenseInfoBuffer) { 1103 *SenseInfoBuffer = 1104 ((PSRBEX_DATA_SCSI_CDB32) SrbExData)->SenseInfoBuffer; 1105 } 1106 1107 if (SenseInfoBufferLength) { 1108 *SenseInfoBufferLength = 1109 ((PSRBEX_DATA_SCSI_CDB32) SrbExData)->SenseInfoBufferLength; 1110 } 1111 1112 } else { 1113 // Catch invalid offset 1114 NT_ASSERT(FALSE); 1115 } 1116 break; 1117 1118 case SrbExDataTypeScsiCdbVar: 1119 if (SrbEx->SrbExDataOffset[i] + sizeof(SRBEX_DATA_SCSI_CDB_VAR) <= SrbEx->SrbLength) { 1120 FoundEntry = TRUE; 1121 if (CdbLength32) { 1122 *CdbLength32 = ((PSRBEX_DATA_SCSI_CDB_VAR) SrbExData)->CdbLength; 1123 } 1124 1125 if (((PSRBEX_DATA_SCSI_CDB_VAR) SrbExData)->CdbLength > 0) { 1126 Cdb = (PCDB)((PSRBEX_DATA_SCSI_CDB_VAR) SrbExData)->Cdb; 1127 } 1128 1129 if (ScsiStatus) { 1130 *ScsiStatus = 1131 ((PSRBEX_DATA_SCSI_CDB_VAR) SrbExData)->ScsiStatus; 1132 } 1133 1134 if (SenseInfoBuffer) { 1135 *SenseInfoBuffer = 1136 ((PSRBEX_DATA_SCSI_CDB_VAR) SrbExData)->SenseInfoBuffer; 1137 } 1138 1139 if (SenseInfoBufferLength) { 1140 *SenseInfoBufferLength = 1141 ((PSRBEX_DATA_SCSI_CDB_VAR) SrbExData)->SenseInfoBufferLength; 1142 } 1143 1144 } else { 1145 // Catch invalid offset 1146 NT_ASSERT(FALSE); 1147 } 1148 break; 1149 } 1150 1151 if (FoundEntry) { 1152 break; 1153 } 1154 } 1155 1156 } else { 1157 1158 if (CdbLength8) { 1159 *CdbLength8 = 0; 1160 } 1161 1162 if (CdbLength32) { 1163 *CdbLength32 = 0; 1164 } 1165 1166 if (ScsiStatus) { 1167 *ScsiStatus = 0; 1168 } 1169 1170 if (SenseInfoBuffer) { 1171 *SenseInfoBuffer = NULL; 1172 } 1173 1174 if (SenseInfoBufferLength) { 1175 *SenseInfoBufferLength = 0; 1176 } 1177 } 1178 1179 return Cdb; 1180 } 1181 1182 FORCEINLINE // __REACTOS__ 1183 VOID 1184 SetSrbScsiData( 1185 _In_ PSTORAGE_REQUEST_BLOCK SrbEx, 1186 _In_ UCHAR CdbLength8, 1187 _In_ ULONG CdbLength32, 1188 _In_ UCHAR ScsiStatus, 1189 _In_opt_ PVOID SenseInfoBuffer, 1190 _In_ UCHAR SenseInfoBufferLength 1191 ) 1192 /*++ 1193 1194 Routine Description: 1195 1196 Helper function to set SCSI related fields from an extended SRB. If SRB is 1197 not a SRB_FUNCTION_EXECUTE_SCSI or not an extended SRB, no modifications will 1198 be made 1199 1200 Arguments: 1201 1202 SrbEx - Pointer to extended SRB. 1203 1204 CdbLength8 - CdbLength field value for SRBEX_DATA_SCSI_CDB16 1205 or SRBEX_DATA_SCSI_CDB32 1206 1207 CdbLength32 - CdbLength field value for SRBEX_DATA_SCSI_CDB_VAR 1208 1209 ScsiStatus - ScsiStatus field value. 1210 1211 SenseInfoBuffer - SenseInfoBuffer value. 1212 1213 SenseInfoBufferLength - SenseInfoBufferLength value. 1214 1215 Return Value: 1216 1217 None 1218 1219 --*/ 1220 { 1221 ULONG i; 1222 PSRBEX_DATA SrbExData = NULL; 1223 BOOLEAN FoundEntry = FALSE; 1224 1225 if ((SrbEx->Function == SRB_FUNCTION_STORAGE_REQUEST_BLOCK) && 1226 (SrbEx->SrbFunction == SRB_FUNCTION_EXECUTE_SCSI)) { 1227 NT_ASSERT(SrbEx->NumSrbExData > 0); 1228 1229 for (i = 0; i < SrbEx->NumSrbExData; i++) { 1230 1231 // Skip any invalid offsets 1232 if ((SrbEx->SrbExDataOffset[i] < sizeof(STORAGE_REQUEST_BLOCK)) || 1233 (SrbEx->SrbExDataOffset[i] > SrbEx->SrbLength)){ 1234 // Catch any invalid offsets 1235 NT_ASSERT(FALSE); 1236 continue; 1237 } 1238 1239 SrbExData = (PSRBEX_DATA)((PUCHAR)SrbEx + SrbEx->SrbExDataOffset[i]); 1240 1241 switch (SrbExData->Type) { 1242 1243 case SrbExDataTypeScsiCdb16: 1244 if (SrbEx->SrbExDataOffset[i] + sizeof(SRBEX_DATA_SCSI_CDB16) <= SrbEx->SrbLength) { 1245 FoundEntry = TRUE; 1246 ((PSRBEX_DATA_SCSI_CDB16) SrbExData)->CdbLength = CdbLength8; 1247 ((PSRBEX_DATA_SCSI_CDB16) SrbExData)->ScsiStatus = ScsiStatus; 1248 ((PSRBEX_DATA_SCSI_CDB16) SrbExData)->SenseInfoBuffer = SenseInfoBuffer; 1249 ((PSRBEX_DATA_SCSI_CDB16) SrbExData)->SenseInfoBufferLength = SenseInfoBufferLength; 1250 } else { 1251 // Catch invalid offset 1252 NT_ASSERT(FALSE); 1253 } 1254 break; 1255 1256 case SrbExDataTypeScsiCdb32: 1257 if (SrbEx->SrbExDataOffset[i] + sizeof(SRBEX_DATA_SCSI_CDB32) <= SrbEx->SrbLength) { 1258 FoundEntry = TRUE; 1259 ((PSRBEX_DATA_SCSI_CDB32) SrbExData)->CdbLength = CdbLength8; 1260 ((PSRBEX_DATA_SCSI_CDB32) SrbExData)->ScsiStatus = ScsiStatus; 1261 ((PSRBEX_DATA_SCSI_CDB32) SrbExData)->SenseInfoBuffer = SenseInfoBuffer; 1262 ((PSRBEX_DATA_SCSI_CDB32) SrbExData)->SenseInfoBufferLength = SenseInfoBufferLength; 1263 } else { 1264 // Catch invalid offset 1265 NT_ASSERT(FALSE); 1266 } 1267 break; 1268 1269 case SrbExDataTypeScsiCdbVar: 1270 if (SrbEx->SrbExDataOffset[i] + sizeof(SRBEX_DATA_SCSI_CDB_VAR) <= SrbEx->SrbLength) { 1271 FoundEntry = TRUE; 1272 ((PSRBEX_DATA_SCSI_CDB_VAR) SrbExData)->CdbLength = CdbLength32; 1273 ((PSRBEX_DATA_SCSI_CDB_VAR) SrbExData)->ScsiStatus = ScsiStatus; 1274 ((PSRBEX_DATA_SCSI_CDB_VAR) SrbExData)->SenseInfoBuffer = SenseInfoBuffer; 1275 ((PSRBEX_DATA_SCSI_CDB_VAR) SrbExData)->SenseInfoBufferLength = SenseInfoBufferLength; 1276 } else { 1277 // Catch invalid offset 1278 NT_ASSERT(FALSE); 1279 } 1280 break; 1281 } 1282 1283 if (FoundEntry) { 1284 break; 1285 } 1286 } 1287 1288 } 1289 1290 return; 1291 } 1292 1293