1 /*++ 2 3 Copyright (C) Microsoft Corporation, 1991 - 1999 4 5 Module Name: 6 7 classwmi.c 8 9 Abstract: 10 11 SCSI class driver routines 12 13 Environment: 14 15 kernel mode only 16 17 Notes: 18 19 20 Revision History: 21 22 --*/ 23 24 #ifndef __REACTOS__ 25 #include "stddef.h" 26 #include "ntddk.h" 27 #include "scsi.h" 28 29 #include "classpnp.h" 30 31 #include "mountdev.h" 32 33 #include <stdarg.h> 34 #endif 35 36 #include "classp.h" 37 #include <wmistr.h> 38 #include <wmidata.h> 39 // #include <classlog.h> __REACTOS__ 40 41 #ifdef DEBUG_USE_WPP 42 #include "classwmi.tmh" 43 #endif 44 45 #define TIME_STRING_LENGTH 25 46 47 BOOLEAN 48 ClassFindGuid( 49 PGUIDREGINFO GuidList, 50 ULONG GuidCount, 51 LPGUID Guid, 52 PULONG GuidIndex 53 ); 54 55 NTSTATUS 56 ClassQueryInternalDataBlock( 57 IN PDEVICE_OBJECT DeviceObject, 58 IN PIRP Irp, 59 IN ULONG GuidIndex, 60 IN ULONG BufferAvail, 61 OUT PUCHAR Buffer 62 ); 63 64 PWCHAR 65 ConvertTickToDateTime( 66 IN LARGE_INTEGER Tick, 67 _Out_writes_(TIME_STRING_LENGTH) PWCHAR String 68 ); 69 70 BOOLEAN 71 ClassFindInternalGuid( 72 LPGUID Guid, 73 PULONG GuidIndex 74 ); 75 76 77 // 78 // This is the name for the MOF resource that must be part of all drivers that 79 // register via this interface. 80 #define MOFRESOURCENAME L"MofResourceName" 81 82 // 83 // What can be paged ??? 84 #ifdef ALLOC_PRAGMA 85 #pragma alloc_text(PAGE, ClassSystemControl) 86 #pragma alloc_text(PAGE, ClassFindGuid) 87 #pragma alloc_text(PAGE, ClassFindInternalGuid) 88 #endif 89 90 #ifdef __REACTOS__ 91 #define MSStorageDriver_ClassErrorLogGuid {0xD5A9A51E, 0x03F9, 0x404d, {0x97, 0x22, 0x15, 0xF9, 0x0E, 0xB0, 0x70, 0x38}} 92 #endif 93 94 // 95 // Define WMI interface to all class drivers 96 // 97 GUIDREGINFO wmiClassGuids[] = 98 { 99 { 100 MSStorageDriver_ClassErrorLogGuid, 1, 0 101 } 102 }; 103 104 #define MSStorageDriver_ClassErrorLogGuid_Index 0 105 #define NUM_CLASS_WMI_GUIDS (sizeof(wmiClassGuids) / sizeof(GUIDREGINFO)) 106 107 108 /*++//////////////////////////////////////////////////////////////////////////// 109 110 ClassFindGuid() 111 112 Routine Description: 113 114 This routine will search the list of guids registered and return 115 the index for the one that was registered. 116 117 Arguments: 118 119 GuidList is the list of guids to search 120 121 GuidCount is the count of guids in the list 122 123 Guid is the guid being searched for 124 125 *GuidIndex returns the index to the guid 126 127 Return Value: 128 129 TRUE if guid is found else FALSE 130 131 --*/ 132 BOOLEAN 133 ClassFindGuid( 134 PGUIDREGINFO GuidList, 135 ULONG GuidCount, 136 LPGUID Guid, 137 PULONG GuidIndex 138 ) 139 { 140 ULONG i; 141 142 PAGED_CODE(); 143 144 for (i = 0; i < GuidCount; i++) 145 { 146 if (IsEqualGUID(Guid, &GuidList[i].Guid)) 147 { 148 *GuidIndex = i; 149 return(TRUE); 150 } 151 } 152 return(FALSE); 153 } // end ClassFindGuid() 154 155 /*++//////////////////////////////////////////////////////////////////////////// 156 157 ClassFindInternalGuid() 158 159 Routine Description: 160 161 This routine will search the list of internal guids registered and return 162 the index for the one that was registered. 163 164 Arguments: 165 166 Guid is the guid being searched for 167 168 *GuidIndex returns the index to the guid 169 170 Return Value: 171 172 TRUE if guid is found else FALSE 173 174 --*/ 175 BOOLEAN 176 ClassFindInternalGuid( 177 LPGUID Guid, 178 PULONG GuidIndex 179 ) 180 { 181 ULONG i; 182 183 PAGED_CODE(); 184 185 for (i = 0; i < NUM_CLASS_WMI_GUIDS; i++) 186 { 187 if (IsEqualGUID(Guid, &wmiClassGuids[i].Guid)) 188 { 189 *GuidIndex = i; 190 return(TRUE); 191 } 192 } 193 194 return(FALSE); 195 } // end ClassFindGuid() 196 197 /*++//////////////////////////////////////////////////////////////////////////// 198 199 ClassSystemControl() 200 201 Routine Description: 202 203 Dispatch routine for IRP_MJ_SYSTEM_CONTROL. This routine will process 204 all wmi requests received, forwarding them if they are not for this 205 driver or determining if the guid is valid and if so passing it to 206 the driver specific function for handing wmi requests. 207 208 Arguments: 209 210 DeviceObject - Supplies a pointer to the device object for this request. 211 212 Irp - Supplies the Irp making the request. 213 214 Return Value: 215 216 status 217 218 --*/ 219 NTSTATUS 220 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */ 221 ClassSystemControl( 222 IN PDEVICE_OBJECT DeviceObject, 223 IN PIRP Irp 224 ) 225 { 226 PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension; 227 PCLASS_DRIVER_EXTENSION driverExtension; 228 PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp); 229 ULONG isRemoved; 230 ULONG bufferSize; 231 PUCHAR buffer; 232 NTSTATUS status; 233 UCHAR minorFunction; 234 ULONG guidIndex = (ULONG)-1; 235 PCLASS_WMI_INFO classWmiInfo; 236 BOOLEAN isInternalGuid = FALSE; 237 238 PAGED_CODE(); 239 240 // 241 // Make sure device has not been removed 242 isRemoved = ClassAcquireRemoveLock(DeviceObject, Irp); 243 if(isRemoved) 244 { 245 Irp->IoStatus.Status = STATUS_DEVICE_DOES_NOT_EXIST; 246 ClassReleaseRemoveLock(DeviceObject, Irp); 247 ClassCompleteRequest(DeviceObject, Irp, IO_NO_INCREMENT); 248 return STATUS_DEVICE_DOES_NOT_EXIST; 249 } 250 251 // 252 // If the irp is not a WMI irp or it is not targetted at this device 253 // or this device has not regstered with WMI then just forward it on. 254 minorFunction = irpStack->MinorFunction; 255 if ((minorFunction > IRP_MN_EXECUTE_METHOD) || 256 (irpStack->Parameters.WMI.ProviderId != (ULONG_PTR)DeviceObject) || 257 ((minorFunction != IRP_MN_REGINFO) && 258 (commonExtension->GuidCount == 0))) 259 { 260 // 261 // CONSIDER: Do I need to hang onto lock until IoCallDriver returns ? 262 IoSkipCurrentIrpStackLocation(Irp); 263 ClassReleaseRemoveLock(DeviceObject, Irp); 264 return(IoCallDriver(commonExtension->LowerDeviceObject, Irp)); 265 } 266 267 buffer = (PUCHAR)irpStack->Parameters.WMI.Buffer; 268 bufferSize = irpStack->Parameters.WMI.BufferSize; 269 270 if (minorFunction != IRP_MN_REGINFO) 271 { 272 // 273 // For all requests other than query registration info we are passed 274 // a guid. Determine if the guid is one that is supported by the 275 // device. 276 if (commonExtension->GuidRegInfo != NULL && 277 ClassFindGuid(commonExtension->GuidRegInfo, 278 commonExtension->GuidCount, 279 (LPGUID)irpStack->Parameters.WMI.DataPath, 280 &guidIndex)) 281 { 282 isInternalGuid = FALSE; 283 status = STATUS_SUCCESS; 284 } else if (ClassFindInternalGuid((LPGUID)irpStack->Parameters.WMI.DataPath, 285 &guidIndex)) { 286 isInternalGuid = TRUE; 287 status = STATUS_SUCCESS; 288 } else { 289 status = STATUS_WMI_GUID_NOT_FOUND; 290 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_WMI, "WMI GUID not found!")); 291 } 292 293 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_WMI, "WMI Find Guid = %x, isInternalGuid = %x", status, isInternalGuid)); 294 if (NT_SUCCESS(status) && 295 ((minorFunction == IRP_MN_QUERY_SINGLE_INSTANCE) || 296 (minorFunction == IRP_MN_CHANGE_SINGLE_INSTANCE) || 297 (minorFunction == IRP_MN_CHANGE_SINGLE_ITEM) || 298 (minorFunction == IRP_MN_EXECUTE_METHOD))) 299 { 300 if ( (((PWNODE_HEADER)buffer)->Flags) & 301 WNODE_FLAG_STATIC_INSTANCE_NAMES) 302 { 303 if ( ((PWNODE_SINGLE_INSTANCE)buffer)->InstanceIndex != 0 ) 304 { 305 status = STATUS_WMI_INSTANCE_NOT_FOUND; 306 } 307 } else { 308 status = STATUS_WMI_INSTANCE_NOT_FOUND; 309 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_WMI, "WMI Instance not found!")); 310 } 311 } 312 313 if (! NT_SUCCESS(status)) 314 { 315 Irp->IoStatus.Status = status; 316 ClassReleaseRemoveLock(DeviceObject, Irp); 317 ClassCompleteRequest(DeviceObject, Irp, IO_NO_INCREMENT); 318 return(status); 319 } 320 } 321 322 driverExtension = commonExtension->DriverExtension; 323 324 classWmiInfo = commonExtension->IsFdo ? 325 &driverExtension->InitData.FdoData.ClassWmiInfo : 326 &driverExtension->InitData.PdoData.ClassWmiInfo; 327 switch(minorFunction) 328 { 329 case IRP_MN_REGINFO: 330 { 331 ULONG guidCount; 332 PGUIDREGINFO guidList; 333 PWMIREGINFOW wmiRegInfo; 334 PWMIREGGUIDW wmiRegGuid; 335 PUNICODE_STRING regPath; 336 PWCHAR stringPtr; 337 ULONG retSize; 338 ULONG registryPathOffset; 339 ULONG mofResourceOffset; 340 ULONG bufferNeeded; 341 ULONG i; 342 ULONG_PTR nameInfo; 343 ULONG nameSize, nameOffset, nameFlags; 344 UNICODE_STRING name, mofName; 345 PCLASS_QUERY_WMI_REGINFO_EX ClassQueryWmiRegInfoEx; 346 347 name.Buffer = NULL; 348 name.Length = 0; 349 name.MaximumLength = 0; 350 nameFlags = 0; 351 352 ClassQueryWmiRegInfoEx = commonExtension->IsFdo ? 353 driverExtension->ClassFdoQueryWmiRegInfoEx : 354 driverExtension->ClassPdoQueryWmiRegInfoEx; 355 356 if ((classWmiInfo->GuidRegInfo != NULL) && 357 (classWmiInfo->ClassQueryWmiRegInfo != NULL) && 358 (ClassQueryWmiRegInfoEx == NULL)) 359 { 360 status = classWmiInfo->ClassQueryWmiRegInfo( 361 DeviceObject, 362 &nameFlags, 363 &name); 364 365 RtlInitUnicodeString(&mofName, MOFRESOURCENAME); 366 367 } else if ((classWmiInfo->GuidRegInfo != NULL) && (ClassQueryWmiRegInfoEx != NULL)) { 368 RtlInitUnicodeString(&mofName, L""); 369 370 status = (*ClassQueryWmiRegInfoEx)( 371 DeviceObject, 372 &nameFlags, 373 &name, 374 &mofName); 375 } else { 376 RtlInitUnicodeString(&mofName, L""); 377 nameFlags = WMIREG_FLAG_INSTANCE_PDO; 378 status = STATUS_SUCCESS; 379 } 380 381 if (NT_SUCCESS(status) && 382 (! (nameFlags & WMIREG_FLAG_INSTANCE_PDO) && 383 (name.Buffer == NULL))) 384 { 385 // 386 // if PDO flag not specified then an instance name must be 387 status = STATUS_INVALID_DEVICE_REQUEST; 388 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_WMI, "Invalid Device Request!")); 389 } 390 391 if (NT_SUCCESS(status)) 392 { 393 guidList = classWmiInfo->GuidRegInfo; 394 guidCount = (classWmiInfo->GuidRegInfo == NULL ? 0 : classWmiInfo->GuidCount) + NUM_CLASS_WMI_GUIDS; 395 396 nameOffset = sizeof(WMIREGINFO) + 397 guidCount * sizeof(WMIREGGUIDW); 398 399 if (nameFlags & WMIREG_FLAG_INSTANCE_PDO) 400 { 401 nameSize = 0; 402 nameInfo = commonExtension->IsFdo ? 403 (ULONG_PTR)((PFUNCTIONAL_DEVICE_EXTENSION)commonExtension)->LowerPdo : 404 (ULONG_PTR)DeviceObject; 405 } else { 406 nameFlags |= WMIREG_FLAG_INSTANCE_LIST; 407 nameSize = name.Length + sizeof(USHORT); 408 nameInfo = nameOffset; 409 } 410 411 mofResourceOffset = nameOffset + nameSize; 412 413 registryPathOffset = mofResourceOffset + 414 mofName.Length + sizeof(USHORT); 415 416 regPath = &driverExtension->RegistryPath; 417 418 bufferNeeded = registryPathOffset + regPath->Length; 419 bufferNeeded += sizeof(USHORT); 420 421 if (bufferNeeded <= bufferSize) 422 { 423 retSize = bufferNeeded; 424 425 commonExtension->GuidCount = guidCount; 426 commonExtension->GuidRegInfo = guidList; 427 428 wmiRegInfo = (PWMIREGINFO)buffer; 429 wmiRegInfo->BufferSize = bufferNeeded; 430 wmiRegInfo->NextWmiRegInfo = 0; 431 wmiRegInfo->MofResourceName = mofResourceOffset; 432 wmiRegInfo->RegistryPath = registryPathOffset; 433 wmiRegInfo->GuidCount = guidCount; 434 435 for (i = 0; i < classWmiInfo->GuidCount; i++) 436 { 437 wmiRegGuid = &wmiRegInfo->WmiRegGuid[i]; 438 wmiRegGuid->Guid = guidList[i].Guid; 439 wmiRegGuid->Flags = guidList[i].Flags | nameFlags; 440 wmiRegGuid->InstanceInfo = nameInfo; 441 wmiRegGuid->InstanceCount = 1; 442 } 443 for (i = 0; i < NUM_CLASS_WMI_GUIDS; i++) 444 { 445 wmiRegGuid = &wmiRegInfo->WmiRegGuid[i + classWmiInfo->GuidCount]; 446 wmiRegGuid->Guid = wmiClassGuids[i].Guid; 447 wmiRegGuid->Flags = wmiClassGuids[i].Flags | nameFlags; 448 wmiRegGuid->InstanceInfo = nameInfo; 449 wmiRegGuid->InstanceCount = 1; 450 } 451 452 if ( nameFlags & WMIREG_FLAG_INSTANCE_LIST) 453 { 454 bufferNeeded = nameOffset + sizeof(WCHAR); 455 bufferNeeded += name.Length; 456 457 if (bufferSize >= bufferNeeded){ 458 stringPtr = (PWCHAR)((PUCHAR)buffer + nameOffset); 459 *stringPtr++ = name.Length; 460 RtlCopyMemory(stringPtr, name.Buffer, name.Length); 461 } 462 else { 463 NT_ASSERT(bufferSize >= bufferNeeded); 464 status = STATUS_INVALID_BUFFER_SIZE; 465 } 466 } 467 468 bufferNeeded = mofResourceOffset + sizeof(WCHAR); 469 bufferNeeded += mofName.Length; 470 471 if (bufferSize >= bufferNeeded){ 472 stringPtr = (PWCHAR)((PUCHAR)buffer + mofResourceOffset); 473 *stringPtr++ = mofName.Length; 474 RtlCopyMemory(stringPtr, mofName.Buffer, mofName.Length); 475 } 476 else { 477 NT_ASSERT(bufferSize >= bufferNeeded); 478 status = STATUS_INVALID_BUFFER_SIZE; 479 } 480 481 bufferNeeded = registryPathOffset + sizeof(WCHAR); 482 bufferNeeded += regPath->Length; 483 484 if (bufferSize >= bufferNeeded){ 485 stringPtr = (PWCHAR)((PUCHAR)buffer + registryPathOffset); 486 *stringPtr++ = regPath->Length; 487 RtlCopyMemory(stringPtr, 488 regPath->Buffer, 489 regPath->Length); 490 } 491 else { 492 493 NT_ASSERT(bufferSize >= bufferNeeded); 494 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_WMI, "Invalid Buffer Size!")); 495 status = STATUS_INVALID_BUFFER_SIZE; 496 } 497 498 } else { 499 *((PULONG)buffer) = bufferNeeded; 500 retSize = sizeof(ULONG); 501 } 502 } else { 503 retSize = 0; 504 } 505 506 FREE_POOL(name.Buffer); 507 508 Irp->IoStatus.Status = status; 509 Irp->IoStatus.Information = retSize; 510 ClassReleaseRemoveLock(DeviceObject, Irp); 511 ClassCompleteRequest(DeviceObject, Irp, IO_NO_INCREMENT); 512 return(status); 513 } 514 515 case IRP_MN_QUERY_ALL_DATA: 516 { 517 PWNODE_ALL_DATA wnode; 518 ULONG bufferAvail; 519 520 wnode = (PWNODE_ALL_DATA)buffer; 521 522 if (bufferSize < sizeof(WNODE_ALL_DATA)) 523 { 524 bufferAvail = 0; 525 } else { 526 bufferAvail = bufferSize - sizeof(WNODE_ALL_DATA); 527 } 528 529 wnode->DataBlockOffset = sizeof(WNODE_ALL_DATA); 530 531 NT_ASSERT(guidIndex != (ULONG)-1); 532 _Analysis_assume_(isInternalGuid); 533 if (isInternalGuid) 534 { 535 status = ClassQueryInternalDataBlock( 536 DeviceObject, 537 Irp, 538 guidIndex, 539 bufferAvail, 540 buffer + sizeof(WNODE_ALL_DATA)); 541 } else { 542 status = classWmiInfo->ClassQueryWmiDataBlock( 543 DeviceObject, 544 Irp, 545 guidIndex, 546 bufferAvail, 547 buffer + sizeof(WNODE_ALL_DATA)); 548 } 549 break; 550 } 551 552 case IRP_MN_QUERY_SINGLE_INSTANCE: 553 { 554 PWNODE_SINGLE_INSTANCE wnode; 555 ULONG dataBlockOffset; 556 557 wnode = (PWNODE_SINGLE_INSTANCE)buffer; 558 559 dataBlockOffset = wnode->DataBlockOffset; 560 561 NT_ASSERT(guidIndex != (ULONG)-1); 562 _Analysis_assume_(isInternalGuid); 563 if (isInternalGuid) 564 { 565 status = ClassQueryInternalDataBlock( 566 DeviceObject, 567 Irp, 568 guidIndex, 569 bufferSize - dataBlockOffset, 570 (PUCHAR)wnode + dataBlockOffset); 571 } else { 572 status = classWmiInfo->ClassQueryWmiDataBlock( 573 DeviceObject, 574 Irp, 575 guidIndex, 576 bufferSize - dataBlockOffset, 577 (PUCHAR)wnode + dataBlockOffset); 578 } 579 break; 580 } 581 582 case IRP_MN_CHANGE_SINGLE_INSTANCE: 583 { 584 PWNODE_SINGLE_INSTANCE wnode; 585 586 wnode = (PWNODE_SINGLE_INSTANCE)buffer; 587 _Analysis_assume_(isInternalGuid); 588 if (isInternalGuid) 589 { 590 status = ClassWmiCompleteRequest(DeviceObject, 591 Irp, 592 STATUS_WMI_GUID_NOT_FOUND, 593 0, 594 IO_NO_INCREMENT); 595 } else { 596 597 NT_ASSERT(guidIndex != (ULONG)-1); 598 599 status = classWmiInfo->ClassSetWmiDataBlock( 600 DeviceObject, 601 Irp, 602 guidIndex, 603 wnode->SizeDataBlock, 604 (PUCHAR)wnode + wnode->DataBlockOffset); 605 } 606 607 break; 608 } 609 610 case IRP_MN_CHANGE_SINGLE_ITEM: 611 { 612 PWNODE_SINGLE_ITEM wnode; 613 614 wnode = (PWNODE_SINGLE_ITEM)buffer; 615 616 NT_ASSERT(guidIndex != (ULONG)-1); 617 _Analysis_assume_(isInternalGuid); 618 if (isInternalGuid) 619 { 620 status = ClassWmiCompleteRequest(DeviceObject, 621 Irp, 622 STATUS_WMI_GUID_NOT_FOUND, 623 0, 624 IO_NO_INCREMENT); 625 } else { 626 627 NT_ASSERT(guidIndex != (ULONG)-1); 628 629 status = classWmiInfo->ClassSetWmiDataItem( 630 DeviceObject, 631 Irp, 632 guidIndex, 633 wnode->ItemId, 634 wnode->SizeDataItem, 635 (PUCHAR)wnode + wnode->DataBlockOffset); 636 637 } 638 639 break; 640 } 641 642 case IRP_MN_EXECUTE_METHOD: 643 { 644 PWNODE_METHOD_ITEM wnode; 645 646 wnode = (PWNODE_METHOD_ITEM)buffer; 647 _Analysis_assume_(isInternalGuid); 648 if (isInternalGuid) 649 { 650 status = ClassWmiCompleteRequest(DeviceObject, 651 Irp, 652 STATUS_WMI_GUID_NOT_FOUND, 653 0, 654 IO_NO_INCREMENT); 655 } else { 656 657 NT_ASSERT(guidIndex != (ULONG)-1); 658 659 status = classWmiInfo->ClassExecuteWmiMethod( 660 DeviceObject, 661 Irp, 662 guidIndex, 663 wnode->MethodId, 664 wnode->SizeDataBlock, 665 bufferSize - wnode->DataBlockOffset, 666 buffer + wnode->DataBlockOffset); 667 } 668 669 break; 670 } 671 672 case IRP_MN_ENABLE_EVENTS: 673 { 674 _Analysis_assume_(isInternalGuid); 675 if (isInternalGuid) 676 { 677 status = ClassWmiCompleteRequest(DeviceObject, 678 Irp, 679 STATUS_WMI_GUID_NOT_FOUND, 680 0, 681 IO_NO_INCREMENT); 682 } else { 683 684 NT_ASSERT(guidIndex != (ULONG)-1); 685 686 status = classWmiInfo->ClassWmiFunctionControl( 687 DeviceObject, 688 Irp, 689 guidIndex, 690 EventGeneration, 691 TRUE); 692 } 693 break; 694 } 695 696 case IRP_MN_DISABLE_EVENTS: 697 { 698 _Analysis_assume_(isInternalGuid); 699 if (isInternalGuid) 700 { 701 status = ClassWmiCompleteRequest(DeviceObject, 702 Irp, 703 STATUS_WMI_GUID_NOT_FOUND, 704 0, 705 IO_NO_INCREMENT); 706 } else { 707 708 NT_ASSERT(guidIndex != (ULONG)-1); 709 710 status = classWmiInfo->ClassWmiFunctionControl( 711 DeviceObject, 712 Irp, 713 guidIndex, 714 EventGeneration, 715 FALSE); 716 } 717 break; 718 } 719 720 case IRP_MN_ENABLE_COLLECTION: 721 { 722 _Analysis_assume_(isInternalGuid); 723 if (isInternalGuid) 724 { 725 status = ClassWmiCompleteRequest(DeviceObject, 726 Irp, 727 STATUS_WMI_GUID_NOT_FOUND, 728 0, 729 IO_NO_INCREMENT); 730 } else { 731 732 NT_ASSERT(guidIndex != (ULONG)-1); 733 734 status = classWmiInfo->ClassWmiFunctionControl( 735 DeviceObject, 736 Irp, 737 guidIndex, 738 DataBlockCollection, 739 TRUE); 740 } 741 break; 742 } 743 744 case IRP_MN_DISABLE_COLLECTION: 745 { 746 _Analysis_assume_(isInternalGuid); 747 if (isInternalGuid) 748 { 749 status = ClassWmiCompleteRequest(DeviceObject, 750 Irp, 751 STATUS_WMI_GUID_NOT_FOUND, 752 0, 753 IO_NO_INCREMENT); 754 } else { 755 756 NT_ASSERT(guidIndex != (ULONG)-1); 757 758 status = classWmiInfo->ClassWmiFunctionControl( 759 DeviceObject, 760 Irp, 761 guidIndex, 762 DataBlockCollection, 763 FALSE); 764 } 765 766 break; 767 } 768 769 default: 770 { 771 status = STATUS_INVALID_DEVICE_REQUEST; 772 break; 773 } 774 775 } 776 777 return(status); 778 } // end ClassSystemControl() 779 780 781 NTSTATUS 782 ClassQueryInternalDataBlock( 783 IN PDEVICE_OBJECT DeviceObject, 784 IN PIRP Irp, 785 IN ULONG GuidIndex, 786 IN ULONG BufferAvail, 787 OUT PUCHAR Buffer 788 ) 789 /*++ 790 791 Routine Description: 792 793 This routine allows querying for the contents of an internal WMI 794 data block. When the driver has finished filling the data block it 795 must call ClassWmiCompleteRequest to complete the irp. 796 797 Arguments: 798 799 DeviceObject is the device whose data block is being queried 800 801 Irp is the Irp that makes this request 802 803 GuidIndex is the index into the list of guids provided when the 804 device registered 805 806 BufferAvail on has the maximum size available to write the data 807 block. 808 809 Buffer on return is filled with the returned data block 810 811 812 Return Value: 813 814 status 815 816 --*/ 817 { 818 NTSTATUS status; 819 #ifndef __REACTOS__ // WMI in not a thing on ReactOS yet 820 ULONG sizeNeeded = 0, i; 821 PFUNCTIONAL_DEVICE_EXTENSION fdoExt = DeviceObject->DeviceExtension; 822 if (GuidIndex == MSStorageDriver_ClassErrorLogGuid_Index) { 823 824 // 825 // NOTE - ClassErrorLog is still using SCSI_REQUEST_BLOCK and will not be 826 // updated to support extended SRB until classpnp is updated to send >16 827 // byte CDBs. Extended SRBs will be translated to SCSI_REQUEST_BLOCK. 828 // 829 sizeNeeded = MSStorageDriver_ClassErrorLog_SIZE; 830 if (BufferAvail >= sizeNeeded) { 831 PMSStorageDriver_ClassErrorLog errorLog = (PMSStorageDriver_ClassErrorLog) Buffer; 832 PMSStorageDriver_ClassErrorLogEntry logEntry; 833 PMSStorageDriver_ScsiRequestBlock srbBlock; 834 PMSStorageDriver_SenseData senseData; 835 PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData; 836 PCLASS_ERROR_LOG_DATA fdoLogEntry; 837 PSCSI_REQUEST_BLOCK fdoSRBBlock; 838 PSENSE_DATA fdoSenseData; 839 errorLog->numEntries = NUM_ERROR_LOG_ENTRIES; 840 for (i = 0; i < NUM_ERROR_LOG_ENTRIES; i++) { 841 fdoLogEntry = &fdoData->ErrorLogs[i]; 842 fdoSRBBlock = &fdoLogEntry->Srb; 843 fdoSenseData = &fdoLogEntry->SenseData; 844 logEntry = &errorLog->logEntries[i]; 845 srbBlock = &logEntry->srb; 846 senseData = &logEntry->senseData; 847 logEntry->tickCount = fdoLogEntry->TickCount.QuadPart; 848 logEntry->portNumber = fdoLogEntry->PortNumber; 849 logEntry->errorPaging = (fdoLogEntry->ErrorPaging == 0 ? FALSE : TRUE); 850 logEntry->errorRetried = (fdoLogEntry->ErrorRetried == 0 ? FALSE : TRUE); 851 logEntry->errorUnhandled = (fdoLogEntry->ErrorUnhandled == 0 ? FALSE : TRUE); 852 logEntry->errorReserved = fdoLogEntry->ErrorReserved; 853 RtlMoveMemory(logEntry->reserved, fdoLogEntry->Reserved, sizeof(logEntry->reserved)); 854 ConvertTickToDateTime(fdoLogEntry->TickCount, logEntry->eventTime); 855 856 srbBlock->length = fdoSRBBlock->Length; 857 srbBlock->function = fdoSRBBlock->Function; 858 srbBlock->srbStatus = fdoSRBBlock->SrbStatus; 859 srbBlock->scsiStatus = fdoSRBBlock->ScsiStatus; 860 srbBlock->pathID = fdoSRBBlock->PathId; 861 srbBlock->targetID = fdoSRBBlock->TargetId; 862 srbBlock->lun = fdoSRBBlock->Lun; 863 srbBlock->queueTag = fdoSRBBlock->QueueTag; 864 srbBlock->queueAction = fdoSRBBlock->QueueAction; 865 srbBlock->cdbLength = fdoSRBBlock->CdbLength; 866 srbBlock->senseInfoBufferLength = fdoSRBBlock->SenseInfoBufferLength; 867 srbBlock->srbFlags = fdoSRBBlock->SrbFlags; 868 srbBlock->dataTransferLength = fdoSRBBlock->DataTransferLength; 869 srbBlock->timeOutValue = fdoSRBBlock->TimeOutValue; 870 srbBlock->dataBuffer = (ULONGLONG) fdoSRBBlock->DataBuffer; 871 srbBlock->senseInfoBuffer = (ULONGLONG) fdoSRBBlock->SenseInfoBuffer; 872 srbBlock->nextSRB = (ULONGLONG) fdoSRBBlock->NextSrb; 873 srbBlock->originalRequest = (ULONGLONG) fdoSRBBlock->OriginalRequest; 874 srbBlock->srbExtension = (ULONGLONG) fdoSRBBlock->SrbExtension; 875 srbBlock->internalStatus = fdoSRBBlock->InternalStatus; 876 #if defined(_WIN64) 877 srbBlock->reserved = fdoSRBBlock->Reserved; 878 #else 879 srbBlock->reserved = 0; 880 #endif 881 RtlMoveMemory(srbBlock->cdb, fdoSRBBlock->Cdb, sizeof(srbBlock->cdb)); 882 883 // 884 // Note: Sense data has been converted into Fixed format before it was 885 // put in the log. Therefore, no conversion is needed here. 886 // 887 senseData->errorCode = fdoSenseData->ErrorCode; 888 senseData->valid = (fdoSenseData->Valid == 0 ? FALSE : TRUE); 889 senseData->segmentNumber = fdoSenseData->SegmentNumber; 890 senseData->senseKey = fdoSenseData->SenseKey; 891 senseData->reserved = (fdoSenseData->Reserved == 0 ? FALSE : TRUE); 892 senseData->incorrectLength = (fdoSenseData->IncorrectLength == 0 ? FALSE : TRUE); 893 senseData->endOfMedia = (fdoSenseData->EndOfMedia == 0 ? FALSE : TRUE); 894 senseData->fileMark = (fdoSenseData->FileMark == 0 ? FALSE : TRUE); 895 RtlMoveMemory(senseData->information, fdoSenseData->Information, sizeof(senseData->information)); 896 senseData->additionalSenseLength = fdoSenseData->AdditionalSenseLength; 897 RtlMoveMemory(senseData->commandSpecificInformation, fdoSenseData->CommandSpecificInformation, sizeof(senseData->commandSpecificInformation)); 898 senseData->additionalSenseCode = fdoSenseData->AdditionalSenseCode; 899 senseData->additionalSenseCodeQualifier = fdoSenseData->AdditionalSenseCodeQualifier; 900 senseData->fieldReplaceableUnitCode = fdoSenseData->FieldReplaceableUnitCode; 901 RtlMoveMemory(senseData->senseKeySpecific, fdoSenseData->SenseKeySpecific, sizeof(senseData->senseKeySpecific)); 902 } 903 status = STATUS_SUCCESS; 904 } else { 905 status = STATUS_BUFFER_TOO_SMALL; 906 } 907 } else if (GuidIndex > 0 && GuidIndex < NUM_CLASS_WMI_GUIDS) { 908 status = STATUS_WMI_INSTANCE_NOT_FOUND; 909 } else { 910 status = STATUS_WMI_GUID_NOT_FOUND; 911 } 912 #else 913 ULONG sizeNeeded = 0; 914 status = STATUS_WMI_GUID_NOT_FOUND; 915 #endif 916 status = ClassWmiCompleteRequest(DeviceObject, 917 Irp, 918 status, 919 sizeNeeded, 920 IO_NO_INCREMENT); 921 return status; 922 } 923 924 PWCHAR 925 ConvertTickToDateTime( 926 IN LARGE_INTEGER Tick, 927 _Out_writes_(TIME_STRING_LENGTH) PWCHAR String 928 ) 929 930 /*++ 931 932 Routine Description: 933 934 This routine converts a tick count to a datetime (MOF) data type 935 936 Arguments: 937 938 Tick - The tick count that needs to be converted 939 String - The buffer to hold the time string, must be able to hold WCHAR[25] 940 941 Return Value: 942 943 The time string 944 945 --*/ 946 947 { 948 LARGE_INTEGER nowTick, nowTime, time; 949 ULONG maxInc = 0; 950 TIME_FIELDS timeFields = {0}; 951 WCHAR outDateTime[TIME_STRING_LENGTH + 1]; 952 953 nowTick.QuadPart = 0; 954 nowTime.QuadPart = 0; 955 // 956 // Translate the tick count to a system time 957 // 958 KeQueryTickCount(&nowTick); 959 maxInc = KeQueryTimeIncrement(); 960 KeQuerySystemTime(&nowTime); 961 time.QuadPart = nowTime.QuadPart - ((nowTick.QuadPart - Tick.QuadPart) * maxInc); 962 963 RtlTimeToTimeFields(&time, &timeFields); 964 965 // 966 // The buffer String is of size MAX_PATH. Use that to specify the buffer size. 967 // 968 //yyyymmddhhmmss.mmmmmmsutc 969 RtlStringCbPrintfW(outDateTime, sizeof(outDateTime), L"%04d%02d%02d%02d%02d%02d.%03d***+000", timeFields.Year, timeFields.Month, timeFields.Day, timeFields.Hour, timeFields.Minute, timeFields.Second, timeFields.Milliseconds); 970 RtlMoveMemory(String, outDateTime, sizeof(WCHAR) * TIME_STRING_LENGTH); 971 return String; 972 } 973 974 /*++//////////////////////////////////////////////////////////////////////////// 975 976 ClassWmiCompleteRequest() 977 978 Routine Description: 979 980 981 This routine will do the work of completing a WMI irp. Depending upon the 982 the WMI request this routine will fixup the returned WNODE appropriately. 983 984 NOTE: This routine assumes that the ClassRemoveLock is held and it will 985 release it. 986 987 Arguments: 988 989 DeviceObject - Supplies a pointer to the device object for this request. 990 991 Irp - Supplies the Irp making the request. 992 993 Status - Status to complete the irp with. STATUS_BUFFER_TOO_SMALL is used 994 to indicate that more buffer is required for the data requested. 995 996 BufferUsed - number of bytes of actual data to return (not including WMI 997 specific structures) 998 999 PriorityBoost - priority boost to pass to ClassCompleteRequest 1000 1001 Return Value: 1002 1003 status 1004 1005 --*/ 1006 SCSIPORT_API 1007 NTSTATUS 1008 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */ 1009 ClassWmiCompleteRequest( 1010 _In_ PDEVICE_OBJECT DeviceObject, 1011 _Inout_ PIRP Irp, 1012 _In_ NTSTATUS Status, 1013 _In_ ULONG BufferUsed, 1014 _In_ CCHAR PriorityBoost 1015 ) 1016 { 1017 PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp); 1018 PUCHAR buffer; 1019 ULONG retSize; 1020 UCHAR minorFunction; 1021 1022 minorFunction = irpStack->MinorFunction; 1023 buffer = (PUCHAR)irpStack->Parameters.WMI.Buffer; 1024 1025 switch(minorFunction) 1026 { 1027 case IRP_MN_QUERY_ALL_DATA: 1028 { 1029 PWNODE_ALL_DATA wnode; 1030 PWNODE_TOO_SMALL wnodeTooSmall; 1031 ULONG bufferNeeded; 1032 1033 wnode = (PWNODE_ALL_DATA)buffer; 1034 1035 bufferNeeded = sizeof(WNODE_ALL_DATA) + BufferUsed; 1036 1037 if (NT_SUCCESS(Status)) 1038 { 1039 retSize = bufferNeeded; 1040 wnode->WnodeHeader.BufferSize = bufferNeeded; 1041 KeQuerySystemTime(&wnode->WnodeHeader.TimeStamp); 1042 wnode->WnodeHeader.Flags |= WNODE_FLAG_FIXED_INSTANCE_SIZE; 1043 wnode->FixedInstanceSize = BufferUsed; 1044 wnode->InstanceCount = 1; 1045 1046 } else if (Status == STATUS_BUFFER_TOO_SMALL) { 1047 wnodeTooSmall = (PWNODE_TOO_SMALL)wnode; 1048 1049 wnodeTooSmall->WnodeHeader.BufferSize = sizeof(WNODE_TOO_SMALL); 1050 wnodeTooSmall->WnodeHeader.Flags = WNODE_FLAG_TOO_SMALL; 1051 wnodeTooSmall->SizeNeeded = sizeof(WNODE_ALL_DATA) + BufferUsed; 1052 retSize = sizeof(WNODE_TOO_SMALL); 1053 Status = STATUS_SUCCESS; 1054 } else { 1055 retSize = 0; 1056 } 1057 break; 1058 } 1059 1060 case IRP_MN_QUERY_SINGLE_INSTANCE: 1061 { 1062 PWNODE_SINGLE_INSTANCE wnode; 1063 PWNODE_TOO_SMALL wnodeTooSmall; 1064 ULONG bufferNeeded; 1065 1066 wnode = (PWNODE_SINGLE_INSTANCE)buffer; 1067 1068 bufferNeeded = wnode->DataBlockOffset + BufferUsed; 1069 1070 if (NT_SUCCESS(Status)) 1071 { 1072 retSize = bufferNeeded; 1073 wnode->WnodeHeader.BufferSize = bufferNeeded; 1074 KeQuerySystemTime(&wnode->WnodeHeader.TimeStamp); 1075 wnode->SizeDataBlock = BufferUsed; 1076 1077 } else if (Status == STATUS_BUFFER_TOO_SMALL) { 1078 wnodeTooSmall = (PWNODE_TOO_SMALL)wnode; 1079 1080 wnodeTooSmall->WnodeHeader.BufferSize = sizeof(WNODE_TOO_SMALL); 1081 wnodeTooSmall->WnodeHeader.Flags = WNODE_FLAG_TOO_SMALL; 1082 wnodeTooSmall->SizeNeeded = bufferNeeded; 1083 retSize = sizeof(WNODE_TOO_SMALL); 1084 Status = STATUS_SUCCESS; 1085 } else { 1086 retSize = 0; 1087 } 1088 break; 1089 } 1090 1091 case IRP_MN_EXECUTE_METHOD: 1092 { 1093 PWNODE_METHOD_ITEM wnode; 1094 PWNODE_TOO_SMALL wnodeTooSmall; 1095 ULONG bufferNeeded; 1096 1097 wnode = (PWNODE_METHOD_ITEM)buffer; 1098 1099 bufferNeeded = wnode->DataBlockOffset + BufferUsed; 1100 1101 if (NT_SUCCESS(Status)) 1102 { 1103 retSize = bufferNeeded; 1104 wnode->WnodeHeader.BufferSize = bufferNeeded; 1105 KeQuerySystemTime(&wnode->WnodeHeader.TimeStamp); 1106 wnode->SizeDataBlock = BufferUsed; 1107 1108 } else if (Status == STATUS_BUFFER_TOO_SMALL) { 1109 wnodeTooSmall = (PWNODE_TOO_SMALL)wnode; 1110 1111 wnodeTooSmall->WnodeHeader.BufferSize = sizeof(WNODE_TOO_SMALL); 1112 wnodeTooSmall->WnodeHeader.Flags = WNODE_FLAG_TOO_SMALL; 1113 wnodeTooSmall->SizeNeeded = bufferNeeded; 1114 retSize = sizeof(WNODE_TOO_SMALL); 1115 Status = STATUS_SUCCESS; 1116 } else { 1117 retSize = 0; 1118 } 1119 break; 1120 } 1121 1122 default: 1123 { 1124 // 1125 // All other requests don't return any data 1126 retSize = 0; 1127 break; 1128 } 1129 1130 } 1131 1132 Irp->IoStatus.Status = Status; 1133 Irp->IoStatus.Information = retSize; 1134 ClassReleaseRemoveLock(DeviceObject, Irp); 1135 ClassCompleteRequest(DeviceObject, Irp, PriorityBoost); 1136 return(Status); 1137 } // end ClassWmiCompleteRequest() 1138 1139 /*++//////////////////////////////////////////////////////////////////////////// 1140 1141 ClassWmiFireEvent() 1142 1143 Routine Description: 1144 1145 This routine will fire a WMI event using the data buffer passed. This 1146 routine may be called at or below DPC level 1147 1148 Arguments: 1149 1150 DeviceObject - Supplies a pointer to the device object for this event 1151 1152 Guid is pointer to the GUID that represents the event 1153 1154 InstanceIndex is the index of the instance of the event 1155 1156 EventDataSize is the number of bytes of data that is being fired with 1157 with the event 1158 1159 EventData is the data that is fired with the events. This may be NULL 1160 if there is no data associated with the event 1161 1162 1163 Return Value: 1164 1165 status 1166 1167 --*/ 1168 _IRQL_requires_max_(DISPATCH_LEVEL) 1169 NTSTATUS 1170 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */ 1171 ClassWmiFireEvent( 1172 _In_ PDEVICE_OBJECT DeviceObject, 1173 _In_ LPGUID Guid, 1174 _In_ ULONG InstanceIndex, 1175 _In_ ULONG EventDataSize, 1176 _In_reads_bytes_(EventDataSize) PVOID EventData 1177 ) 1178 { 1179 1180 ULONG sizeNeeded; 1181 PWNODE_SINGLE_INSTANCE event; 1182 NTSTATUS status; 1183 1184 if (EventData == NULL) 1185 { 1186 EventDataSize = 0; 1187 } 1188 1189 sizeNeeded = sizeof(WNODE_SINGLE_INSTANCE) + EventDataSize; 1190 1191 event = ExAllocatePoolWithTag(NonPagedPoolNx, sizeNeeded, CLASS_TAG_WMI); 1192 if (event != NULL) 1193 { 1194 RtlZeroMemory(event, sizeNeeded); 1195 event->WnodeHeader.Guid = *Guid; 1196 event->WnodeHeader.ProviderId = IoWMIDeviceObjectToProviderId(DeviceObject); 1197 event->WnodeHeader.BufferSize = sizeNeeded; 1198 event->WnodeHeader.Flags = WNODE_FLAG_SINGLE_INSTANCE | 1199 WNODE_FLAG_EVENT_ITEM | 1200 WNODE_FLAG_STATIC_INSTANCE_NAMES; 1201 KeQuerySystemTime(&event->WnodeHeader.TimeStamp); 1202 1203 event->InstanceIndex = InstanceIndex; 1204 event->SizeDataBlock = EventDataSize; 1205 event->DataBlockOffset = sizeof(WNODE_SINGLE_INSTANCE); 1206 if (EventData != NULL) 1207 { 1208 RtlCopyMemory( &event->VariableData, EventData, EventDataSize); 1209 } 1210 1211 status = IoWMIWriteEvent(event); 1212 if (! NT_SUCCESS(status)) 1213 { 1214 FREE_POOL(event); 1215 } 1216 } else { 1217 status = STATUS_INSUFFICIENT_RESOURCES; 1218 } 1219 1220 return(status); 1221 } // end ClassWmiFireEvent() 1222