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