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