1 /* 2 * pnpdump - PnP BIOS information dumper 3 */ 4 5 #include <windows.h> 6 #include <string.h> 7 #include <stdio.h> 8 #include <stdlib.h> 9 #include <conio.h> 10 11 #include <ntddk.h> 12 13 #include <pshpack1.h> 14 15 typedef struct _CM_PNP_BIOS_DEVICE_NODE 16 { 17 USHORT Size; 18 UCHAR Node; 19 ULONG ProductId; 20 UCHAR DeviceType[3]; 21 USHORT DeviceAttributes; 22 } CM_PNP_BIOS_DEVICE_NODE,*PCM_PNP_BIOS_DEVICE_NODE; 23 24 typedef struct _CM_PNP_BIOS_INSTALLATION_CHECK 25 { 26 UCHAR Signature[4]; // $PnP (ascii) 27 UCHAR Revision; 28 UCHAR Length; 29 USHORT ControlField; 30 UCHAR Checksum; 31 ULONG EventFlagAddress; // Physical address 32 USHORT RealModeEntryOffset; 33 USHORT RealModeEntrySegment; 34 USHORT ProtectedModeEntryOffset; 35 ULONG ProtectedModeCodeBaseAddress; 36 ULONG OemDeviceId; 37 USHORT RealModeDataBaseAddress; 38 ULONG ProtectedModeDataBaseAddress; 39 } CM_PNP_BIOS_INSTALLATION_CHECK, *PCM_PNP_BIOS_INSTALLATION_CHECK; 40 41 #include <poppack.h> 42 43 typedef struct _PNP_ID_NAME_ 44 { 45 char *PnpId; 46 char *DeviceName; 47 } PNP_ID_NAME, *PPNP_ID_NAME; 48 49 50 static char Hex[] = "0123456789ABCDEF"; 51 52 static PNP_ID_NAME PnpName[] = 53 { 54 /* Interrupt Controllers */ 55 {"PNP0000", "AT Interrupt Controller"}, 56 {"PNP0001", "EISA Interrupt Controller"}, 57 {"PNP0002", "MCA Interrupt Controller"}, 58 {"PNP0003", "APIC"}, 59 {"PNP0004", "Cyrix SLiC MP Interrupt Controller"}, 60 61 /* Timers */ 62 {"PNP0100", "AT Timer"}, 63 {"PNP0101", "EISA Timer"}, 64 {"PNP0102", "MCA Timer"}, 65 66 /* DMA Controllers */ 67 {"PNP0200", "AT DMA Controller"}, 68 {"PNP0201", "EISA DMA Controller"}, 69 {"PNP0202", "MCA DMA Controller"}, 70 71 /* Keyboards */ 72 {"PNP0300", "IBM PC/XT Keyboard (83 keys)"}, 73 {"PNP0301", "IBM PC/AT Keyboard (86 keys)"}, 74 {"PNP0302", "IBM PC/XT Keyboard (84 keys)"}, 75 {"PNP0303", "IBM Enhanced (101/102 keys)"}, 76 {"PNP0304", "Olivetti Keyboard (83 keys)"}, 77 {"PNP0305", "Olivetti Keyboard (102 keys)"}, 78 {"PNP0306", "Olivetti Keyboard (86 keys)"}, 79 {"PNP0307", "Microsoft Windows(R) Keyboard"}, 80 {"PNP0308", "General Input Device Emulation Interface (GIDEI) legacy"}, 81 {"PNP0309", "Olivetti Keyboard (A101/102 key)"}, 82 {"PNP030A", "AT&T 302 keyboard"}, 83 {"PNP030B", "Reserved by Microsoft"}, 84 {"PNP0320", "Japanese 101-key keyboard"}, 85 {"PNP0321", "Japanese AX keyboard"}, 86 {"PNP0322", "Japanese 106-key keyboard A01"}, 87 {"PNP0323", "Japanese 106-key keyboard 002/003"}, 88 {"PNP0324", "Japanese 106-key keyboard 001"}, 89 {"PNP0325", "Japanese Toshiba Desktop keyboard"}, 90 {"PNP0326", "Japanese Toshiba Laptop keyboard"}, 91 {"PNP0327", "Japanese Toshiba Notebook keyboard"}, 92 {"PNP0340", "Korean 84-key keyboard"}, 93 {"PNP0341", "Korean 86-key keyboard"}, 94 {"PNP0342", "Korean Enhanced keyboard"}, 95 {"PNP0343", "Korean Enhanced keyboard 101b"}, 96 {"PNP0343", "Korean Enhanced keyboard 101c"}, 97 {"PNP0344", "Korean Enhanced keyboard 103"}, 98 99 /* Parallel Ports */ 100 {"PNP0400", "Standard LPT printer port"}, 101 {"PNP0401", "ECP printer port"}, 102 103 /* Serial Ports */ 104 {"PNP0500", "Standard PC COM port"}, 105 {"PNP0501", "16550A-compatible COM port"}, 106 {"PNP0510", "Generic IRDA-compatible port"}, 107 108 /* Harddisk Controllers */ 109 {"PNP0600", "Generic ESDI/ATA/IDE harddisk controller"}, 110 {"PNP0601", "Plus Hardcard II"}, 111 {"PNP0602", "Plus Hardcard IIXL/EZ"}, 112 {"PNP0603", "Generic IDE supporting Microsoft Device Bay Specification"}, 113 114 /* Floppy Controllers */ 115 {"PNP0700", "PC standard floppy disk controller"}, 116 {"PNP0701", "Standard floppy controller supporting MS Device Bay Specification"}, 117 118 /* obsolete devices */ 119 {"PNP0800", "Microsoft Sound System compatible device"}, 120 121 /* Display Adapters */ 122 {"PNP0900", "VGA Compatible"}, 123 {"PNP0901", "Video Seven VRAM/VRAM II/1024i"}, 124 {"PNP0902", "8514/A Compatible"}, 125 {"PNP0903", "Trident VGA"}, 126 {"PNP0904", "Cirrus Logic Laptop VGA"}, 127 {"PNP0905", "Cirrus Logic VGA"}, 128 {"PNP0906", "Tseng ET4000"}, 129 {"PNP0907", "Western Digital VGA"}, 130 {"PNP0908", "Western Digital Laptop VGA"}, 131 {"PNP0909", "S3 Inc. 911/924"}, 132 {"PNP090A", "ATI Ultra Pro/Plus (Mach 32)"}, 133 {"PNP090B", "ATI Ultra (Mach 8)"}, 134 {"PNP090C", "XGA Compatible"}, 135 {"PNP090D", "ATI VGA Wonder"}, 136 {"PNP090E", "Weitek P9000 Graphics Adapter"}, 137 {"PNP090F", "Oak Technology VGA"}, 138 {"PNP0910", "Compaq QVision"}, 139 {"PNP0911", "XGA/2"}, 140 {"PNP0912", "Tseng Labs W32/W32i/W32p"}, 141 {"PNP0913", "S3 Inc. 801/928/964"}, 142 {"PNP0914", "Cirrus Logic 5429/5434 (memory mapped)"}, 143 {"PNP0915", "Compaq Advanced VGA (AVGA)"}, 144 {"PNP0916", "ATI Ultra Pro Turbo (Mach64)"}, 145 {"PNP0917", "Reserved by Microsoft"}, 146 {"PNP0918", "Matrox MGA"}, 147 {"PNP0919", "Compaq QVision 2000"}, 148 {"PNP091A", "Tseng W128"}, 149 {"PNP0930", "Chips & Technologies Super VGA"}, 150 {"PNP0931", "Chips & Technologies Accelerator"}, 151 {"PNP0940", "NCR 77c22e Super VGA"}, 152 {"PNP0941", "NCR 77c32blt"}, 153 {"PNP09FF", "Plug and Play Monitors (VESA DDC)"}, 154 155 /* Peripheral Buses */ 156 {"PNP0A00", "ISA Bus"}, 157 {"PNP0A01", "EISA Bus"}, 158 {"PNP0A02", "MCA Bus"}, 159 {"PNP0A03", "PCI Bus"}, 160 {"PNP0A04", "VESA/VL Bus"}, 161 {"PNP0A05", "Generic ACPI Bus"}, 162 {"PNP0A06", "Generic ACPI Extended-IO Bus (EIO bus)"}, 163 164 /* System devices */ 165 {"PNP0800", "AT-style speaker sound"}, 166 {"PNP0B00", "AT Real-Time Clock"}, 167 {"PNP0C00", "Plug and Play BIOS (only created by the root enumerator)"}, 168 {"PNP0C01", "System Board"}, 169 {"PNP0C02", "General Plug and Play motherboard registers."}, 170 {"PNP0C03", "Plug and Play BIOS Event Notification Interrupt"}, 171 {"PNP0C04", "Math Coprocessor"}, 172 {"PNP0C05", "APM BIOS (Version independent)"}, 173 {"PNP0C06", "Reserved for identification of early Plug and Play BIOS implementation"}, 174 {"PNP0C07", "Reserved for identification of early Plug and Play BIOS implementation"}, 175 {"PNP0C08", "ACPI system board hardware"}, 176 {"PNP0C09", "ACPI Embedded Controller"}, 177 {"PNP0C0A", "ACPI Control Method Battery"}, 178 {"PNP0C0B", "ACPI Fan"}, 179 {"PNP0C0C", "ACPI power button device"}, 180 {"PNP0C0D", "ACPI lid device"}, 181 {"PNP0C0E", "ACPI sleep button device"}, 182 {"PNP0C0F", "PCI interrupt link device"}, 183 {"PNP0C10", "ACPI system indicator device"}, 184 {"PNP0C11", "ACPI thermal zone"}, 185 {"PNP0C12", "Device Bay Controller"}, 186 187 /* PCMCIA Controllers */ 188 {"PNP0E00", "Intel 82365-Compatible PCMCIA Controller"}, 189 {"PNP0E01", "Cirrus Logic CL-PD6720 PCMCIA Controller"}, 190 {"PNP0E02", "VLSI VL82C146 PCMCIA Controller"}, 191 {"PNP0E03", "Intel 82365-compatible CardBus controller"}, 192 193 /* Mice */ 194 {"PNP0F00", "Microsoft Bus Mouse"}, 195 {"PNP0F01", "Microsoft Serial Mouse"}, 196 {"PNP0F02", "Microsoft InPort Mouse"}, 197 {"PNP0F03", "Microsoft PS/2-style Mouse"}, 198 {"PNP0F04", "Mouse Systems Mouse"}, 199 {"PNP0F05", "Mouse Systems 3-Button Mouse (COM2)"}, 200 {"PNP0F06", "Genius Mouse (COM1)"}, 201 {"PNP0F07", "Genius Mouse (COM2)"}, 202 {"PNP0F08", "Logitech Serial Mouse"}, 203 {"PNP0F09", "Microsoft BallPoint Serial Mouse"}, 204 {"PNP0F0A", "Microsoft Plug and Play Mouse"}, 205 {"PNP0F0B", "Microsoft Plug and Play BallPoint Mouse"}, 206 {"PNP0F0C", "Microsoft-compatible Serial Mouse"}, 207 {"PNP0F0D", "Microsoft-compatible InPort-compatible Mouse"}, 208 {"PNP0F0E", "Microsoft-compatible PS/2-style Mouse"}, 209 {"PNP0F0F", "Microsoft-compatible Serial BallPoint-compatible Mouse"}, 210 {"PNP0F10", "Texas Instruments QuickPort Mouse"}, 211 {"PNP0F11", "Microsoft-compatible Bus Mouse"}, 212 {"PNP0F12", "Logitech PS/2-style Mouse"}, 213 {"PNP0F13", "PS/2 Port for PS/2-style Mice"}, 214 {"PNP0F14", "Microsoft Kids Mouse"}, 215 {"PNP0F15", "Logitech bus mouse"}, 216 {"PNP0F16", "Logitech SWIFT device"}, 217 {"PNP0F17", "Logitech-compatible serial mouse"}, 218 {"PNP0F18", "Logitech-compatible bus mouse"}, 219 {"PNP0F19", "Logitech-compatible PS/2-style Mouse"}, 220 {"PNP0F1A", "Logitech-compatible SWIFT Device"}, 221 {"PNP0F1B", "HP Omnibook Mouse"}, 222 {"PNP0F1C", "Compaq LTE Trackball PS/2-style Mouse"}, 223 {"PNP0F1D", "Compaq LTE Trackball Serial Mouse"}, 224 {"PNP0F1E", "Microsoft Kids Trackball Mouse"}, 225 {"PNP0F1F", "Reserved by Microsoft Input Device Group"}, 226 {"PNP0F20", "Reserved by Microsoft Input Device Group"}, 227 {"PNP0F21", "Reserved by Microsoft Input Device Group"}, 228 {"PNP0F22", "Reserved by Microsoft Input Device Group"}, 229 {"PNP0F23", "Reserved by Microsoft Input Device Group"}, 230 {"PNP0FFF", "Reserved by Microsoft Systems"}, 231 232 /* List Terminator */ 233 {NULL, NULL} 234 }; 235 236 237 /* FUNCTIONS ****************************************************************/ 238 239 static char * 240 GetDeviceName(char *PnpId) 241 { 242 PPNP_ID_NAME IdName; 243 244 IdName = PnpName; 245 while (IdName->PnpId != NULL) 246 { 247 if (!strcmp(IdName->PnpId, PnpId)) 248 return IdName->DeviceName; 249 250 IdName++; 251 } 252 253 return "Unknown Device"; 254 } 255 256 257 LONG 258 GetPnpKey(PHKEY PnpKey) 259 { 260 LONG lError; 261 char szBuffer[80]; 262 HKEY hAdapterKey; 263 HKEY hBusKey; 264 DWORD dwBus; 265 DWORD dwType; 266 DWORD dwSize; 267 268 *PnpKey = 0; 269 270 lError = RegOpenKey(HKEY_LOCAL_MACHINE, 271 "HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter", 272 &hAdapterKey); 273 if (lError != ERROR_SUCCESS) 274 return 0; 275 276 /* Enumerate buses */ 277 for (dwBus = 0; ; dwBus++) 278 { 279 sprintf(szBuffer, "%lu", dwBus); 280 281 lError = RegOpenKey(hAdapterKey, 282 szBuffer, 283 &hBusKey); 284 if (lError != ERROR_SUCCESS) 285 { 286 RegCloseKey(hAdapterKey); 287 return lError; 288 } 289 290 dwSize = 80; 291 lError = RegQueryValueEx(hBusKey, 292 "Identifier", 293 NULL, 294 &dwType, 295 (LPBYTE)szBuffer, 296 &dwSize); 297 if (lError != ERROR_SUCCESS) 298 { 299 RegCloseKey(hBusKey); 300 RegCloseKey(hAdapterKey); 301 return lError; 302 } 303 304 if (dwType == REG_SZ && stricmp(szBuffer, "pnp bios") == 0) 305 { 306 *PnpKey = hBusKey; 307 RegCloseKey(hAdapterKey); 308 return ERROR_SUCCESS; 309 } 310 311 RegCloseKey(hBusKey); 312 } 313 314 return 1; 315 } 316 317 318 static VOID 319 PnpDecodeIrq(unsigned char *Ptr) 320 { 321 USHORT IrqMask; 322 int i; 323 324 IrqMask = *Ptr; 325 Ptr++; 326 IrqMask |= (*Ptr << 8); 327 328 printf(" IRQs:"); 329 330 for (i = 0; i < 16; i++) 331 { 332 if (IrqMask & (1 << i)) 333 { 334 printf(" %u", i); 335 } 336 } 337 338 printf("\n"); 339 } 340 341 342 static VOID 343 PnpDecodeDma(unsigned char *Ptr) 344 { 345 unsigned char DmaChannel; 346 unsigned char DmaStatus; 347 int i; 348 349 DmaChannel = *Ptr; 350 Ptr++; 351 DmaStatus = *Ptr; 352 353 printf(" DMAs:"); 354 355 for (i = 0; i < 8; i++) 356 { 357 if (DmaChannel & (1 << i)) 358 { 359 printf(" %u", i); 360 } 361 } 362 363 printf("\n"); 364 } 365 366 367 static VOID 368 PnpDecodeIoPort(unsigned char *Ptr) 369 { 370 USHORT MinBase; 371 USHORT MaxBase; 372 UCHAR Align; 373 UCHAR Length; 374 375 // Info = *Ptr; 376 Ptr++; 377 MinBase = *Ptr; 378 Ptr++; 379 MinBase += (*Ptr << 8); 380 Ptr++; 381 MaxBase = *Ptr; 382 Ptr++; 383 MaxBase += (*Ptr << 8); 384 Ptr++; 385 Align = *Ptr; 386 Ptr++; 387 Length = *Ptr; 388 389 printf(" I/O Port descriptor\n"); 390 printf(" MinBase 0x%x MaxBase 0x%x Align %u Length %u\n", 391 MinBase, MaxBase, Align, Length); 392 } 393 394 395 static VOID 396 PnpDecodeFixedIoPort(unsigned char *Ptr) 397 { 398 USHORT IoPort; 399 UCHAR Length; 400 401 IoPort = *Ptr; 402 Ptr++; 403 IoPort += (*Ptr << 8); 404 Ptr++; 405 Length = *Ptr; 406 407 printf(" Fixed I/O Port descriptor\n"); 408 printf(" PortBase 0x%hx Length 0x%x\n", 409 IoPort, Length); 410 411 #if 0 412 if (Length == 1) 413 { 414 printf(" Fixed location I/O Port descriptor: 0x%x\n", 415 IoPort); 416 } 417 else 418 { 419 printf(" Fixed location I/O Port descriptor: 0x%x - 0x%x\n", 420 IoPort, 421 IoPort + Length - 1); 422 } 423 #endif 424 } 425 426 427 static VOID 428 PnpDecodeMemory16(unsigned char *Ptr) 429 { 430 UCHAR Info; 431 USHORT MinBase; 432 USHORT MaxBase; 433 USHORT Align; 434 USHORT Length; 435 436 Info = *Ptr; 437 Ptr++; 438 439 MinBase = *Ptr; 440 Ptr++; 441 MinBase += (*Ptr << 8); 442 Ptr++; 443 444 MaxBase = *Ptr; 445 Ptr++; 446 MaxBase += (*Ptr << 8); 447 Ptr++; 448 449 Align = *Ptr; 450 Ptr++; 451 Align += (*Ptr << 8); 452 Ptr++; 453 454 Length = *Ptr; 455 Ptr++; 456 Length += (*Ptr << 8); 457 458 printf(" 16-Bit memory range descriptor\n"); 459 printf(" MinBase 0x%hx MaxBase 0x%hx Align 0x%hx Length 0x%hx Flags 0x%02x\n", 460 MinBase, MaxBase, Align,Length, Info); 461 } 462 463 464 static VOID 465 PnpDecodeMemory32(unsigned char *Ptr) 466 { 467 UCHAR Info; 468 ULONG MinBase; 469 ULONG MaxBase; 470 ULONG Align; 471 ULONG Length; 472 473 Info = *Ptr; 474 Ptr++; 475 476 MinBase = *Ptr; 477 Ptr++; 478 MinBase += (*Ptr << 8); 479 Ptr++; 480 MinBase += (*Ptr << 16); 481 Ptr++; 482 MinBase += (*Ptr << 24); 483 Ptr++; 484 485 MaxBase = *Ptr; 486 Ptr++; 487 MaxBase += (*Ptr << 8); 488 Ptr++; 489 MaxBase += (*Ptr << 16); 490 Ptr++; 491 MaxBase += (*Ptr << 24); 492 Ptr++; 493 494 Align = *Ptr; 495 Ptr++; 496 Align += (*Ptr << 8); 497 Ptr++; 498 Align += (*Ptr << 16); 499 Ptr++; 500 Align += (*Ptr << 24); 501 Ptr++; 502 503 Length = *Ptr; 504 Ptr++; 505 Length += (*Ptr << 8); 506 Ptr++; 507 Length += (*Ptr << 16); 508 Ptr++; 509 Length += (*Ptr << 24); 510 511 printf(" 32-Bit memory range descriptor\n"); 512 printf(" MinBase 0x%lx MaxBase 0x%lx Align 0x%lx Length 0x%lx Flags 0x%02x\n", 513 MinBase, MaxBase, Align,Length, Info); 514 } 515 516 517 static VOID 518 PnpDecodeFixedMemory(unsigned char *Ptr) 519 { 520 UCHAR Info; 521 ULONG Base; 522 ULONG Length; 523 524 Info = *Ptr; 525 Ptr++; 526 527 Base = *Ptr; 528 Ptr++; 529 Base += (*Ptr << 8); 530 Ptr++; 531 Base += (*Ptr << 16); 532 Ptr++; 533 Base += (*Ptr << 24); 534 Ptr++; 535 536 Length = *Ptr; 537 Ptr++; 538 Length += (*Ptr << 8); 539 Ptr++; 540 Length += (*Ptr << 16); 541 Ptr++; 542 Length += (*Ptr << 24); 543 544 printf(" 32-Bit fixed location memory range descriptor\n"); 545 printf(" Base 0x%lx Length 0x%lx Flags 0x%02x\n", 546 Base, Length, Info); 547 } 548 549 550 void PrintDeviceData (PCM_PNP_BIOS_DEVICE_NODE DeviceNode) 551 { 552 char PnpId[8]; 553 unsigned char *Ptr; 554 unsigned int TagSize; 555 unsigned int TagType; 556 557 unsigned char Id[4]; 558 559 printf ("Node: %x Size %hu (0x%hx)\n", 560 DeviceNode->Node, 561 DeviceNode->Size, 562 DeviceNode->Size); 563 564 memcpy(Id, &DeviceNode->ProductId, 4); 565 566 PnpId[0] = ((Id[0] >> 2) & 0x1F) + 0x40; 567 PnpId[1] = ((Id[0] << 3) & 0x18) + 568 ((Id[1] >> 5) & 0x07) + 0x40; 569 PnpId[2] = (Id[1] & 0x1F) + 0x40; 570 571 PnpId[3] = Hex[(Id[2] >> 4) & 0xF]; 572 PnpId[4] = Hex[Id[2] & 0x0F]; 573 574 PnpId[5] = Hex[(Id[3] >> 4) & 0x0F]; 575 PnpId[6] = Hex[Id[3] & 0x0F]; 576 PnpId[7] = 0; 577 578 printf(" '%s' (%s)\n", 579 PnpId, GetDeviceName(PnpId)); 580 581 if (DeviceNode->Size > sizeof(CM_PNP_BIOS_DEVICE_NODE)) 582 { 583 Ptr = (unsigned char *)(DeviceNode + 1); 584 while (TRUE) 585 { 586 if (*Ptr & 0x80) 587 { 588 TagType = *Ptr & 0x7F; 589 Ptr++; 590 TagSize = *Ptr; 591 Ptr++; 592 TagSize += (*Ptr << 16); 593 Ptr++; 594 595 596 switch (TagType) 597 { 598 case 1: 599 PnpDecodeMemory16(Ptr); 600 break; 601 602 case 5: 603 PnpDecodeMemory32(Ptr); 604 break; 605 606 case 6: 607 PnpDecodeFixedMemory(Ptr); 608 break; 609 610 default: 611 printf(" Large tag: type %u size %u\n", 612 TagType, 613 TagSize); 614 break; 615 } 616 } 617 else 618 { 619 TagType = (*Ptr >> 3) & 0x0F; 620 TagSize = *Ptr & 0x07; 621 Ptr++; 622 623 switch (TagType) 624 { 625 case 2: 626 printf(" Logical device ID\n"); 627 break; 628 629 case 3: 630 printf(" Compatible device ID\n"); 631 break; 632 633 case 4: 634 PnpDecodeIrq(Ptr); 635 break; 636 637 case 5: 638 PnpDecodeDma(Ptr); 639 break; 640 641 case 8: 642 PnpDecodeIoPort(Ptr); 643 break; 644 645 case 9: 646 PnpDecodeFixedIoPort(Ptr); 647 break; 648 649 case 0x0F: /* end tag */ 650 break; 651 652 default: 653 printf(" Small tag: type %u size %u\n", 654 TagType, 655 TagSize); 656 break; 657 } 658 659 /* end tag */ 660 if (TagType == 0x0F) 661 break; 662 } 663 664 Ptr = Ptr + TagSize; 665 } 666 } 667 } 668 669 670 int main (int argc, char *argv[]) 671 { 672 LONG lError; 673 HKEY hPnpKey; 674 DWORD dwType; 675 DWORD dwSize; 676 BOOL Ask; 677 PCM_FULL_RESOURCE_DESCRIPTOR lpBuffer; 678 PCM_PNP_BIOS_INSTALLATION_CHECK lpPnpInst; 679 PCM_PNP_BIOS_DEVICE_NODE lpDevNode; 680 DWORD dwDataSize; 681 DWORD dwResourceSize; 682 683 hPnpKey = 0; 684 685 Ask = TRUE; 686 if (argc >1 && (!strcmp(argv[1],"/S") || !strcmp(argv[1],"/s"))) 687 { 688 Ask = FALSE; 689 } 690 691 if (argc >1 && !strcmp(argv[1],"/?")) 692 { 693 printf("This utility prints the PnP-nodes from the registry\n"); 694 printf("\"/s\" prevents the \"Press any key\"\n\n"); 695 return 0; 696 } 697 698 lError = GetPnpKey(&hPnpKey); 699 if (lError != ERROR_SUCCESS) 700 { 701 printf("Failed to get PnP-BIOS key\n"); 702 return 0; 703 } 704 705 if (hPnpKey != 0) 706 { 707 printf("Found PnP-BIOS key\n"); 708 } 709 710 /* Allocate buffer */ 711 dwSize = 2048; 712 lpBuffer = malloc(dwSize); 713 if (lpBuffer == NULL) 714 { 715 printf("Error: malloc() failed\n"); 716 RegCloseKey(hPnpKey); 717 return 0; 718 } 719 720 do 721 { 722 lError = RegQueryValueEx(hPnpKey, 723 "Configuration Data", 724 NULL, 725 &dwType, 726 (LPBYTE)lpBuffer, 727 &dwSize); 728 if (lError == ERROR_MORE_DATA) 729 { 730 lpBuffer = realloc(lpBuffer, dwSize); 731 if (lpBuffer == NULL) 732 { 733 printf("Error: realloc() of %u bytes failed\n", (unsigned) dwSize); 734 RegCloseKey(hPnpKey); 735 return 0; 736 } 737 } 738 } 739 while (lError == ERROR_MORE_DATA); 740 if (lError != ERROR_SUCCESS) 741 { 742 printf("Failed to read 'Configuration Data' value\n"); 743 free(lpBuffer); 744 RegCloseKey(hPnpKey); 745 return 0; 746 } 747 748 // printf ("Data size: %lu\n", dwSize); 749 750 RegCloseKey(hPnpKey); 751 752 // printf("Resource count %lu\n", lpBuffer->PartialResourceList.Count); 753 754 if (lpBuffer->PartialResourceList.Count == 0) 755 { 756 printf("Invalid resource count!\n"); 757 free(lpBuffer); 758 return 0; 759 } 760 761 // printf("lpBuffer %p\n", lpBuffer); 762 763 dwResourceSize = lpBuffer->PartialResourceList.PartialDescriptors[0].u.DeviceSpecificData.DataSize; 764 // printf("ResourceSize: %lu\n", dwResourceSize); 765 766 lpPnpInst = (PCM_PNP_BIOS_INSTALLATION_CHECK) 767 ((ULONG_PTR)(&lpBuffer->PartialResourceList.PartialDescriptors[0]) + 768 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR)); 769 770 // printf("lpPnpInst %p\n", lpPnpInst); 771 772 printf("Signature '%.4s'\n", lpPnpInst->Signature); 773 if (strncmp((PCHAR)lpPnpInst->Signature, "$PnP", 4)) 774 { 775 printf("Error: Invalid PnP signature\n"); 776 free(lpBuffer); 777 return 0; 778 } 779 780 // printf("InstCheck length: %lu\n", lpPnpInst->Length); 781 782 dwDataSize = sizeof(CM_PNP_BIOS_INSTALLATION_CHECK); 783 lpDevNode = (PCM_PNP_BIOS_DEVICE_NODE)((DWORD)lpPnpInst + sizeof(CM_PNP_BIOS_INSTALLATION_CHECK)); 784 785 if (lpDevNode->Size == 0) 786 { 787 printf("Error: Device node size is zero!\n"); 788 return 0; 789 } 790 791 #if 0 792 printf("Node: %x Size %hu (0x%hx)\n", 793 lpDevNode->Node, 794 lpDevNode->Size, 795 lpDevNode->Size); 796 797 printf("Done.\n"); 798 return 0; 799 #endif 800 801 802 while (dwDataSize < dwResourceSize) 803 { 804 if (lpDevNode->Size == 0) 805 break; 806 807 printf("Node: %x Size %hu (0x%hx)\n", 808 lpDevNode->Node, 809 lpDevNode->Size, 810 lpDevNode->Size); 811 812 dwDataSize += lpDevNode->Size; 813 lpDevNode = (PCM_PNP_BIOS_DEVICE_NODE)((DWORD)lpDevNode + lpDevNode->Size); 814 } 815 816 if (Ask) 817 { 818 printf("\n Press any key...\n"); 819 getch(); 820 } 821 else 822 { 823 printf("\n"); 824 } 825 826 dwDataSize = sizeof(CM_PNP_BIOS_INSTALLATION_CHECK); 827 lpDevNode = (PCM_PNP_BIOS_DEVICE_NODE)((DWORD)lpPnpInst + sizeof(CM_PNP_BIOS_INSTALLATION_CHECK)); 828 829 while (dwDataSize < dwResourceSize) 830 { 831 if (lpDevNode->Size == 0) 832 break; 833 834 PrintDeviceData(lpDevNode); 835 836 if (Ask) 837 { 838 printf("\n Press any key...\n"); 839 getch(); 840 } 841 else 842 { 843 printf("\n"); 844 } 845 846 dwDataSize += lpDevNode->Size; 847 lpDevNode = (PCM_PNP_BIOS_DEVICE_NODE)((DWORD)lpDevNode + lpDevNode->Size); 848 } 849 850 free(lpBuffer); 851 852 return 0; 853 } 854 855 /* EOF */ 856