migrate substitution keywords to SVN
[reactos.git] / reactos / ntoskrnl / io / resource.c
1 /*
2 * ReactOS kernel
3 * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 /* $Id$
20 *
21 * PROJECT: ReactOS kernel
22 * FILE: ntoskrnl/io/resource.c
23 * PURPOSE: Hardware resource managment
24 * PROGRAMMER: David Welch (welch@mcmail.com)
25 * Alex Ionescu (alex@relsoft.net)
26 * UPDATE HISTORY:
27 * Created 22/05/98
28 */
29
30 /* INCLUDES *****************************************************************/
31
32 #include <ntoskrnl.h>
33 #include <internal/debug.h>
34
35 /* GLOBALS *******************************************************************/
36
37 static CONFIGURATION_INFORMATION
38 SystemConfigurationInformation = {0, 0, 0, 0, 0, 0, 0, FALSE, FALSE};
39
40 /* API Parameters to Pass in IopQueryBusDescription */
41 typedef struct IO_QUERY {
42 PINTERFACE_TYPE BusType;
43 PULONG BusNumber;
44 PCONFIGURATION_TYPE ControllerType;
45 PULONG ControllerNumber;
46 PCONFIGURATION_TYPE PeripheralType;
47 PULONG PeripheralNumber;
48 PIO_QUERY_DEVICE_ROUTINE CalloutRoutine;
49 PVOID Context;
50 } IO_QUERY, *PIO_QUERY;
51
52 PWSTR ArcTypes[42] = {
53 L"System",
54 L"CentralProcessor",
55 L"FloatingPointProcessor",
56 L"PrimaryICache",
57 L"PrimaryDCache",
58 L"SecondaryICache",
59 L"SecondaryDCache",
60 L"SecondaryCache",
61 L"EisaAdapter",
62 L"TcAdapter",
63 L"ScsiAdapter",
64 L"DtiAdapter",
65 L"MultifunctionAdapter",
66 L"DiskController",
67 L"TapeController",
68 L"CdRomController",
69 L"WormController",
70 L"SerialController",
71 L"NetworkController",
72 L"DisplayController",
73 L"ParallelController",
74 L"PointerController",
75 L"KeyboardController",
76 L"AudioController",
77 L"OtherController",
78 L"DiskPeripheral",
79 L"FloppyDiskPeripheral",
80 L"TapePeripheral",
81 L"ModemPeripheral",
82 L"MonitorPeripheral",
83 L"PrinterPeripheral",
84 L"PointerPeripheral",
85 L"KeyboardPeripheral",
86 L"TerminalPeripheral",
87 L"OtherPeripheral",
88 L"LinePeripheral",
89 L"NetworkPeripheral",
90 L"SystemMemory",
91 L"DockingInformation",
92 L"RealModeIrqRoutingTable",
93 L"RealModePCIEnumeration",
94 L"Undefined"
95 };
96
97 #define TAG_IO_RESOURCE TAG('R', 'S', 'R', 'C')
98
99 /* PRIVATE FUNCTIONS **********************************************************/
100
101 /*
102 * IopQueryDeviceDescription
103 *
104 * FUNCTION:
105 * Reads and returns Hardware information from the appropriate hardware
106 * registry key. Helper sub of IopQueryBusDescription.
107 *
108 * ARGUMENTS:
109 * Query - What the parent function wants.
110 * RootKey - Which key to look in
111 * RootKeyHandle - Handle to the key
112 * Bus - Bus Number.
113 * BusInformation - The Configuration Information Sent
114 *
115 * RETURNS:
116 * Status
117 */
118
119 NTSTATUS STDCALL
120 IopQueryDeviceDescription(
121 PIO_QUERY Query,
122 UNICODE_STRING RootKey,
123 HANDLE RootKeyHandle,
124 ULONG Bus,
125 PKEY_VALUE_FULL_INFORMATION *BusInformation)
126 {
127 NTSTATUS Status = STATUS_SUCCESS;
128
129 /* Controller Stuff */
130 UNICODE_STRING ControllerString;
131 UNICODE_STRING ControllerRootRegName = RootKey;
132 UNICODE_STRING ControllerRegName;
133 HANDLE ControllerKeyHandle;
134 PKEY_FULL_INFORMATION ControllerFullInformation = NULL;
135 PKEY_VALUE_FULL_INFORMATION ControllerInformation[3] = {NULL, NULL, NULL};
136 ULONG ControllerNumber;
137 ULONG ControllerLoop;
138 ULONG MaximumControllerNumber;
139
140 /* Peripheral Stuff */
141 UNICODE_STRING PeripheralString;
142 HANDLE PeripheralKeyHandle;
143 PKEY_FULL_INFORMATION PeripheralFullInformation;
144 PKEY_VALUE_FULL_INFORMATION PeripheralInformation[3] = {NULL, NULL, NULL};
145 ULONG PeripheralNumber;
146 ULONG PeripheralLoop;
147 ULONG MaximumPeripheralNumber;
148
149 /* Global Registry Stuff */
150 OBJECT_ATTRIBUTES ObjectAttributes;
151 ULONG LenFullInformation;
152 ULONG LenKeyFullInformation;
153 UNICODE_STRING TempString;
154 WCHAR TempBuffer[14];
155 PWSTR Strings[3] = {
156 L"Identifier",
157 L"Configuration Data",
158 L"Component Information"
159 };
160
161 /* Temporary String */
162 TempString.MaximumLength = sizeof(TempBuffer);
163 TempString.Length = 0;
164 TempString.Buffer = TempBuffer;
165
166 /* Add Controller Name to String */
167 RtlAppendUnicodeToString(&ControllerRootRegName, L"\\");
168 RtlAppendUnicodeToString(&ControllerRootRegName, ArcTypes[*Query->ControllerType]);
169
170 /* Set the Controller Number if specified */
171 if (Query->ControllerNumber && *(Query->ControllerNumber))
172 {
173 ControllerNumber = *Query->ControllerNumber;
174 MaximumControllerNumber = ControllerNumber + 1;
175 } else {
176 /* Find out how many Controller Numbers there are */
177 InitializeObjectAttributes(
178 &ObjectAttributes,
179 &ControllerRootRegName,
180 OBJ_CASE_INSENSITIVE,
181 NULL,
182 NULL);
183
184 Status = ZwOpenKey(&ControllerKeyHandle, KEY_READ, &ObjectAttributes);
185 if (NT_SUCCESS(Status))
186 {
187 /* How much buffer space */
188 ZwQueryKey(ControllerKeyHandle, KeyFullInformation, NULL, 0, &LenFullInformation);
189
190 /* Allocate it */
191 ControllerFullInformation = ExAllocatePoolWithTag(PagedPool, LenFullInformation, TAG_IO_RESOURCE);
192
193 /* Get the Information */
194 Status = ZwQueryKey(ControllerKeyHandle, KeyFullInformation, ControllerFullInformation, LenFullInformation, &LenFullInformation);
195 ZwClose(ControllerKeyHandle);
196 ControllerKeyHandle = NULL;
197 }
198
199 /* No controller was found, go back to function. */
200 if (!NT_SUCCESS(Status))
201 {
202 if (ControllerFullInformation != NULL)
203 ExFreePool(ControllerFullInformation);
204 return Status;
205 }
206
207 /* Find out Controller Numbers */
208 ControllerNumber = 0;
209 MaximumControllerNumber = ControllerFullInformation->SubKeys;
210
211 /* Free Memory */
212 ExFreePool(ControllerFullInformation);
213 ControllerFullInformation = NULL;
214 }
215
216 /* Save String */
217 ControllerRegName = ControllerRootRegName;
218
219 /* Loop through controllers */
220 for (; ControllerNumber < MaximumControllerNumber; ControllerNumber++)
221 {
222 /* Load String */
223 ControllerRootRegName = ControllerRegName;
224
225 /* Controller Number to Registry String */
226 Status = RtlIntegerToUnicodeString(ControllerNumber, 10, &TempString);
227
228 /* Create String */
229 Status |= RtlAppendUnicodeToString(&ControllerRootRegName, L"\\");
230 Status |= RtlAppendUnicodeStringToString(&ControllerRootRegName, &TempString);
231
232 /* Something messed up */
233 if (!NT_SUCCESS(Status)) break;
234
235 /* Open the Registry Key */
236 InitializeObjectAttributes(
237 &ObjectAttributes,
238 &ControllerRootRegName,
239 OBJ_CASE_INSENSITIVE,
240 NULL,
241 NULL);
242
243 Status = ZwOpenKey(&ControllerKeyHandle, KEY_READ, &ObjectAttributes);
244
245 /* Read the Configuration Data... */
246 if (NT_SUCCESS(Status))
247 {
248 for (ControllerLoop = 0; ControllerLoop < 3; ControllerLoop++)
249 {
250 /* Identifier String First */
251 RtlInitUnicodeString(&ControllerString, Strings[ControllerLoop]);
252
253 /* How much buffer space */
254 Status = ZwQueryValueKey(ControllerKeyHandle, &ControllerString, KeyValueFullInformation, NULL, 0, &LenKeyFullInformation);
255
256 if(!NT_SUCCESS(Status) && Status != STATUS_BUFFER_TOO_SMALL && Status != STATUS_BUFFER_OVERFLOW)
257 continue;
258
259 /* Allocate it */
260 ControllerInformation[ControllerLoop] = ExAllocatePoolWithTag(PagedPool, LenKeyFullInformation, TAG_IO_RESOURCE);
261
262 /* Get the Information */
263 Status = ZwQueryValueKey(ControllerKeyHandle, &ControllerString, KeyValueFullInformation, ControllerInformation[ControllerLoop], LenKeyFullInformation, &LenKeyFullInformation);
264 }
265
266 /* Clean Up */
267 ZwClose(ControllerKeyHandle);
268 ControllerKeyHandle = NULL;
269 }
270
271 /* Something messed up */
272 if (!NT_SUCCESS(Status))
273 goto EndLoop;
274
275 /* We now have Bus *AND* Controller Information.. is it enough? */
276 if (!(*Query->PeripheralType))
277 {
278 Status = Query->CalloutRoutine(
279 Query->Context,
280 &ControllerRootRegName,
281 *Query->BusType,
282 Bus,
283 BusInformation,
284 *Query->ControllerType,
285 ControllerNumber,
286 ControllerInformation,
287 0,
288 0,
289 NULL);
290 goto EndLoop;
291 }
292
293 /* Not enough...caller also wants peripheral name */
294 Status = RtlAppendUnicodeToString(&ControllerRootRegName, L"\\");
295 Status |= RtlAppendUnicodeToString(&ControllerRootRegName, ArcTypes[*Query->PeripheralType]);
296
297 /* Something messed up */
298 if (!NT_SUCCESS(Status)) goto EndLoop;
299
300 /* Set the Peripheral Number if specified */
301 if (Query->PeripheralNumber && *Query->PeripheralNumber)
302 {
303 PeripheralNumber = *Query->PeripheralNumber;
304 MaximumPeripheralNumber = PeripheralNumber + 1;
305 } else {
306 /* Find out how many Peripheral Numbers there are */
307 InitializeObjectAttributes(
308 &ObjectAttributes,
309 &ControllerRootRegName,
310 OBJ_CASE_INSENSITIVE,
311 NULL,
312 NULL);
313
314 Status = ZwOpenKey(&PeripheralKeyHandle, KEY_READ, &ObjectAttributes);
315
316 if (NT_SUCCESS(Status))
317 {
318 /* How much buffer space */
319 ZwQueryKey(PeripheralKeyHandle, KeyFullInformation, NULL, 0, &LenFullInformation);
320
321 /* Allocate it */
322 PeripheralFullInformation = ExAllocatePoolWithTag(PagedPool, LenFullInformation, TAG_IO_RESOURCE);
323
324 /* Get the Information */
325 Status = ZwQueryKey(PeripheralKeyHandle, KeyFullInformation, PeripheralFullInformation, LenFullInformation, &LenFullInformation);
326 ZwClose(PeripheralKeyHandle);
327 PeripheralKeyHandle = NULL;
328 }
329
330 /* No controller was found, go back to function but clean up first */
331 if (!NT_SUCCESS(Status))
332 {
333 Status = STATUS_SUCCESS;
334 goto EndLoop;
335 }
336
337 /* Find out Peripheral Number */
338 PeripheralNumber = 0;
339 MaximumPeripheralNumber = PeripheralFullInformation->SubKeys;
340
341 /* Free Memory */
342 ExFreePool(PeripheralFullInformation);
343 PeripheralFullInformation = NULL;
344 }
345
346 /* Save Name */
347 ControllerRegName = ControllerRootRegName;
348
349 /* Loop through Peripherals */
350 for (; PeripheralNumber < MaximumPeripheralNumber; PeripheralNumber++)
351 {
352 /* Restore Name */
353 ControllerRootRegName = ControllerRegName;
354
355 /* Peripheral Number to Registry String */
356 Status = RtlIntegerToUnicodeString(PeripheralNumber, 10, &TempString);
357
358 /* Create String */
359 Status |= RtlAppendUnicodeToString(&ControllerRootRegName, L"\\");
360 Status |= RtlAppendUnicodeStringToString(&ControllerRootRegName, &TempString);
361
362 /* Something messed up */
363 if (!NT_SUCCESS(Status)) break;
364
365 /* Open the Registry Key */
366 InitializeObjectAttributes(
367 &ObjectAttributes,
368 &ControllerRootRegName,
369 OBJ_CASE_INSENSITIVE,
370 NULL,
371 NULL);
372
373 Status = ZwOpenKey(&PeripheralKeyHandle, KEY_READ, &ObjectAttributes);
374
375 if (NT_SUCCESS(Status))
376 {
377 for (PeripheralLoop = 0; PeripheralLoop < 3; PeripheralLoop++)
378 {
379 /* Identifier String First */
380 RtlInitUnicodeString(&PeripheralString, Strings[PeripheralLoop]);
381
382 /* How much buffer space */
383 Status = ZwQueryValueKey(PeripheralKeyHandle, &PeripheralString, KeyValueFullInformation, NULL, 0, &LenKeyFullInformation);
384
385 if(!NT_SUCCESS(Status) && Status != STATUS_BUFFER_TOO_SMALL && Status != STATUS_BUFFER_OVERFLOW)
386 {
387 PeripheralInformation[PeripheralLoop] = NULL;
388 continue;
389 }
390
391 /* Allocate it */
392 PeripheralInformation[PeripheralLoop] = ExAllocatePoolWithTag(PagedPool, LenKeyFullInformation, TAG_IO_RESOURCE);
393
394 /* Get the Information */
395 Status = ZwQueryValueKey(PeripheralKeyHandle, &PeripheralString, KeyValueFullInformation, PeripheralInformation[PeripheralLoop], LenKeyFullInformation, &LenKeyFullInformation);
396 }
397
398 /* Clean Up */
399 ZwClose(PeripheralKeyHandle);
400 PeripheralKeyHandle = NULL;
401
402 /* We now have everything the caller could possibly want */
403 if (NT_SUCCESS(Status))
404 {
405 Status = Query->CalloutRoutine(
406 Query->Context,
407 &ControllerRootRegName,
408 *Query->BusType,
409 Bus,
410 BusInformation,
411 *Query->ControllerType,
412 ControllerNumber,
413 ControllerInformation,
414 *Query->PeripheralType,
415 PeripheralNumber,
416 PeripheralInformation);
417 }
418
419 /* Free the allocated memory */
420 for (PeripheralLoop = 0; PeripheralLoop < 3; PeripheralLoop++)
421 {
422 if (PeripheralInformation[PeripheralLoop])
423 {
424 ExFreePool(PeripheralInformation[PeripheralLoop]);
425 PeripheralInformation[PeripheralLoop] = NULL;
426 }
427 }
428
429 /* Something Messed up */
430 if (!NT_SUCCESS(Status)) break;
431 }
432 }
433
434 EndLoop:
435 /* Free the allocated memory */
436 for (ControllerLoop = 0; ControllerLoop < 3; ControllerLoop++)
437 {
438 if (ControllerInformation[ControllerLoop])
439 {
440 ExFreePool(ControllerInformation[ControllerLoop]);
441 ControllerInformation[ControllerLoop] = NULL;
442 }
443 }
444
445 /* Something Messed up */
446 if (!NT_SUCCESS(Status)) break;
447 }
448
449 return Status;
450 }
451
452 /*
453 * IopQueryBusDescription
454 *
455 * FUNCTION:
456 * Reads and returns Hardware information from the appropriate hardware
457 * registry key. Helper sub of IoQueryDeviceDescription. Has two modes
458 * of operation, either looking for Root Bus Types or for sub-Bus
459 * information.
460 *
461 * ARGUMENTS:
462 * Query - What the parent function wants.
463 * RootKey - Which key to look in
464 * RootKeyHandle - Handle to the key
465 * Bus - Bus Number.
466 * KeyIsRoot - Whether we are looking for Root Bus Types or
467 * information under them.
468 *
469 * RETURNS:
470 * Status
471 */
472
473 NTSTATUS STDCALL
474 IopQueryBusDescription(
475 PIO_QUERY Query,
476 UNICODE_STRING RootKey,
477 HANDLE RootKeyHandle,
478 PULONG Bus,
479 BOOLEAN KeyIsRoot)
480 {
481 NTSTATUS Status;
482 ULONG BusLoop;
483 UNICODE_STRING SubRootRegName;
484 UNICODE_STRING BusString;
485 UNICODE_STRING SubBusString;
486 ULONG LenBasicInformation = 0;
487 ULONG LenFullInformation;
488 ULONG LenKeyFullInformation;
489 ULONG LenKey;
490 HANDLE SubRootKeyHandle;
491 PKEY_FULL_INFORMATION FullInformation;
492 PKEY_BASIC_INFORMATION BasicInformation = NULL;
493 OBJECT_ATTRIBUTES ObjectAttributes;
494 PKEY_VALUE_FULL_INFORMATION BusInformation[3] = {NULL, NULL, NULL};
495
496 /* How much buffer space */
497 Status = ZwQueryKey(RootKeyHandle, KeyFullInformation, NULL, 0, &LenFullInformation);
498
499 if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_TOO_SMALL && Status != STATUS_BUFFER_OVERFLOW)
500 return Status;
501
502 /* Allocate it */
503 FullInformation = ExAllocatePoolWithTag(PagedPool, LenFullInformation, TAG_IO_RESOURCE);
504
505 if(!FullInformation)
506 return STATUS_NO_MEMORY;
507
508 /* Get the Information */
509 Status = ZwQueryKey(RootKeyHandle, KeyFullInformation, FullInformation, LenFullInformation, &LenFullInformation);
510
511 /* Everything was fine */
512 if (NT_SUCCESS(Status))
513 {
514 /* Buffer needed for all the keys under this one */
515 LenBasicInformation = FullInformation->MaxNameLen + sizeof(KEY_BASIC_INFORMATION);
516
517 /* Allocate it */
518 BasicInformation = ExAllocatePoolWithTag(PagedPool, LenBasicInformation, TAG_IO_RESOURCE);
519 }
520
521 /* Deallocate the old Buffer */
522 ExFreePool(FullInformation);
523
524 /* Try to find a Bus */
525 for (BusLoop = 0; NT_SUCCESS(Status); BusLoop++)
526 {
527 /* Bus parameter was passed and number was matched */
528 if ((Query->BusNumber) && (*(Query->BusNumber)) == *Bus) break;
529
530 /* Enumerate the Key */
531 Status = ZwEnumerateKey(
532 RootKeyHandle,
533 BusLoop,
534 KeyBasicInformation,
535 BasicInformation,
536 LenBasicInformation,
537 &LenKey);
538
539 /* Everything enumerated */
540 if (!NT_SUCCESS(Status)) break;
541
542 /* What Bus are we going to go down? (only check if this is a Root Key) */
543 if (KeyIsRoot)
544 {
545 if (wcsncmp(BasicInformation->Name, L"MultifunctionAdapter", BasicInformation->NameLength / 2) &&
546 wcsncmp(BasicInformation->Name, L"EisaAdapter", BasicInformation->NameLength / 2) &&
547 wcsncmp(BasicInformation->Name, L"TcAdapter", BasicInformation->NameLength / 2))
548 {
549 /* Nothing found, check next */
550 continue;
551 }
552 }
553
554 /* Enumerate the Bus. */
555 BusString.Buffer = BasicInformation->Name;
556 BusString.Length = BasicInformation->NameLength;
557 BusString.MaximumLength = BasicInformation->NameLength;
558
559 /* Open a handle to the Root Registry Key */
560 InitializeObjectAttributes(
561 &ObjectAttributes,
562 &BusString,
563 OBJ_CASE_INSENSITIVE,
564 RootKeyHandle,
565 NULL);
566
567 Status = ZwOpenKey(&SubRootKeyHandle, KEY_READ, &ObjectAttributes);
568
569 /* Go on if we can't */
570 if (!NT_SUCCESS(Status)) continue;
571
572 /* Key opened. Create the path */
573 SubRootRegName = RootKey;
574 RtlAppendUnicodeToString(&SubRootRegName, L"\\");
575 RtlAppendUnicodeStringToString(&SubRootRegName, &BusString);
576
577 if (!KeyIsRoot)
578 {
579 /* Parsing a SubBus-key */
580 int SubBusLoop;
581 PWSTR Strings[3] = {
582 L"Identifier",
583 L"Configuration Data",
584 L"Component Information"};
585
586 for (SubBusLoop = 0; SubBusLoop < 3; SubBusLoop++)
587 {
588 /* Identifier String First */
589 RtlInitUnicodeString(&SubBusString, Strings[SubBusLoop]);
590
591 /* How much buffer space */
592 ZwQueryValueKey(SubRootKeyHandle, &SubBusString, KeyValueFullInformation, NULL, 0, &LenKeyFullInformation);
593
594 /* Allocate it */
595 BusInformation[SubBusLoop] = ExAllocatePoolWithTag(PagedPool, LenKeyFullInformation, TAG_IO_RESOURCE);
596
597 /* Get the Information */
598 Status = ZwQueryValueKey(SubRootKeyHandle, &SubBusString, KeyValueFullInformation, BusInformation[SubBusLoop], LenKeyFullInformation, &LenKeyFullInformation);
599 }
600
601 if (NT_SUCCESS(Status))
602 {
603 /* Do we have something */
604 if (BusInformation[1] != NULL &&
605 BusInformation[1]->DataLength != 0 &&
606 /* Does it match what we want? */
607 (((PCM_FULL_RESOURCE_DESCRIPTOR)((ULONG_PTR)BusInformation[1] + BusInformation[1]->DataOffset))->InterfaceType == *(Query->BusType)))
608 {
609 /* Found a bus */
610 (*Bus)++;
611
612 /* Is it the bus we wanted */
613 if (Query->BusNumber == NULL || *(Query->BusNumber) == *Bus)
614 {
615 /* If we don't want Controller Information, we're done... call the callback */
616 if (Query->ControllerType == NULL)
617 {
618 Status = Query->CalloutRoutine(
619 Query->Context,
620 &SubRootRegName,
621 *(Query->BusType),
622 *Bus,
623 BusInformation,
624 0,
625 0,
626 NULL,
627 0,
628 0,
629 NULL);
630 } else {
631 /* We want Controller Info...get it */
632 Status = IopQueryDeviceDescription(Query, SubRootRegName, RootKeyHandle, *Bus, (PKEY_VALUE_FULL_INFORMATION*)BusInformation);
633 }
634 }
635 }
636 }
637
638 /* Free the allocated memory */
639 for (SubBusLoop = 0; SubBusLoop < 3; SubBusLoop++)
640 {
641 if (BusInformation[SubBusLoop])
642 {
643 ExFreePool(BusInformation[SubBusLoop]);
644 BusInformation[SubBusLoop] = NULL;
645 }
646 }
647
648 /* Exit the Loop if we found the bus */
649 if (Query->BusNumber != NULL && *(Query->BusNumber) == *Bus)
650 {
651 ZwClose(SubRootKeyHandle);
652 SubRootKeyHandle = NULL;
653 continue;
654 }
655 }
656
657 /* Enumerate the buses below us recursively if we haven't found the bus yet */
658 Status = IopQueryBusDescription(Query, SubRootRegName, SubRootKeyHandle, Bus, !KeyIsRoot);
659
660 /* Everything enumerated */
661 if (Status == STATUS_NO_MORE_ENTRIES) Status = STATUS_SUCCESS;
662
663 ZwClose(SubRootKeyHandle);
664 SubRootKeyHandle = NULL;
665 }
666
667 /* Free the last remaining Allocated Memory */
668 if (BasicInformation)
669 ExFreePool(BasicInformation);
670
671 return Status;
672 }
673
674 /* PUBLIC FUNCTIONS ***********************************************************/
675
676 /*
677 * @implemented
678 */
679 PCONFIGURATION_INFORMATION STDCALL
680 IoGetConfigurationInformation(VOID)
681 {
682 return(&SystemConfigurationInformation);
683 }
684
685 /*
686 * @unimplemented
687 */
688 NTSTATUS STDCALL
689 IoReportResourceUsage(PUNICODE_STRING DriverClassName,
690 PDRIVER_OBJECT DriverObject,
691 PCM_RESOURCE_LIST DriverList,
692 ULONG DriverListSize,
693 PDEVICE_OBJECT DeviceObject,
694 PCM_RESOURCE_LIST DeviceList,
695 ULONG DeviceListSize,
696 BOOLEAN OverrideConflict,
697 PBOOLEAN ConflictDetected)
698 /*
699 * FUNCTION: Reports hardware resources in the
700 * \Registry\Machine\Hardware\ResourceMap tree, so that a subsequently
701 * loaded driver cannot attempt to use the same resources.
702 * ARGUMENTS:
703 * DriverClassName - The class of driver under which the resource
704 * information should be stored.
705 * DriverObject - The driver object that was input to the
706 * DriverEntry.
707 * DriverList - Resources that claimed for the driver rather than
708 * per-device.
709 * DriverListSize - Size in bytes of the DriverList.
710 * DeviceObject - The device object for which resources should be
711 * claimed.
712 * DeviceList - List of resources which should be claimed for the
713 * device.
714 * DeviceListSize - Size of the per-device resource list in bytes.
715 * OverrideConflict - True if the resources should be cliamed
716 * even if a conflict is found.
717 * ConflictDetected - Points to a variable that receives TRUE if
718 * a conflict is detected with another driver.
719 */
720 {
721 DPRINT1("IoReportResourceUsage is unimplemented\n");
722 *ConflictDetected = FALSE;
723 return STATUS_SUCCESS;
724 }
725
726 /*
727 * @unimplemented
728 */
729 NTSTATUS STDCALL
730 IoAssignResources(PUNICODE_STRING RegistryPath,
731 PUNICODE_STRING DriverClassName,
732 PDRIVER_OBJECT DriverObject,
733 PDEVICE_OBJECT DeviceObject,
734 PIO_RESOURCE_REQUIREMENTS_LIST RequestedResources,
735 PCM_RESOURCE_LIST* AllocatedResources)
736 {
737 UNIMPLEMENTED;
738 return(STATUS_NOT_IMPLEMENTED);
739 }
740
741 /*
742 * FUNCTION:
743 * Reads and returns Hardware information from the appropriate hardware registry key.
744 *
745 * ARGUMENTS:
746 * BusType - MCA, ISA, EISA...specifies the Bus Type
747 * BusNumber - Which bus of above should be queried
748 * ControllerType - Specifices the Controller Type
749 * ControllerNumber - Which of the controllers to query.
750 * CalloutRoutine - Which function to call for each valid query.
751 * Context - Value to pass to the callback.
752 *
753 * RETURNS:
754 * Status
755 *
756 * STATUS:
757 * @implemented
758 */
759
760 NTSTATUS NTAPI
761 IoQueryDeviceDescription(PINTERFACE_TYPE BusType,
762 PULONG BusNumber,
763 PCONFIGURATION_TYPE ControllerType,
764 PULONG ControllerNumber,
765 PCONFIGURATION_TYPE PeripheralType,
766 PULONG PeripheralNumber,
767 PIO_QUERY_DEVICE_ROUTINE CalloutRoutine,
768 PVOID Context)
769 {
770 NTSTATUS Status;
771 ULONG BusLoopNumber = -1; /* Root Bus */
772 OBJECT_ATTRIBUTES ObjectAttributes;
773 UNICODE_STRING RootRegKey;
774 HANDLE RootRegHandle;
775 WCHAR RootRegString[] = L"\\REGISTRY\\MACHINE\\HARDWARE\\DESCRIPTION\\SYSTEM";
776 IO_QUERY Query;
777
778 /* Set up the String */
779 RootRegKey.Length = 0;
780 RootRegKey.MaximumLength = 2048;
781 RootRegKey.Buffer = ExAllocatePoolWithTag(PagedPool, RootRegKey.MaximumLength, TAG_IO_RESOURCE);
782 RtlAppendUnicodeToString(&RootRegKey, RootRegString);
783
784 /* Open a handle to the Root Registry Key */
785 InitializeObjectAttributes(
786 &ObjectAttributes,
787 &RootRegKey,
788 OBJ_CASE_INSENSITIVE,
789 NULL,
790 NULL);
791
792 Status = ZwOpenKey(&RootRegHandle, KEY_READ, &ObjectAttributes);
793
794 if (NT_SUCCESS(Status))
795 {
796 /* Use a helper function to loop though this key and get the info */
797 Query.BusType = BusType;
798 Query.BusNumber = BusNumber;
799 Query.ControllerType = ControllerType;
800 Query.ControllerNumber = ControllerNumber;
801 Query.PeripheralType = PeripheralType;
802 Query.PeripheralNumber = PeripheralNumber;
803 Query.CalloutRoutine = CalloutRoutine;
804 Query.Context = Context;
805 Status = IopQueryBusDescription(&Query, RootRegKey, RootRegHandle, &BusLoopNumber, TRUE);
806
807 /* Close registry */
808 ZwClose(RootRegHandle);
809 }
810
811 /* Free Memory */
812 ExFreePool(RootRegKey.Buffer);
813
814 return Status;
815 }
816
817 /*
818 * @implemented
819 */
820 NTSTATUS STDCALL
821 IoReportHalResourceUsage(PUNICODE_STRING HalDescription,
822 PCM_RESOURCE_LIST RawList,
823 PCM_RESOURCE_LIST TranslatedList,
824 ULONG ListSize)
825 /*
826 * FUNCTION:
827 * Reports hardware resources of the HAL in the
828 * \Registry\Machine\Hardware\ResourceMap tree.
829 * ARGUMENTS:
830 * HalDescription: Descriptive name of the HAL.
831 * RawList: List of raw (bus specific) resources which should be
832 * claimed for the HAL.
833 * TranslatedList: List of translated (system wide) resources which
834 * should be claimed for the HAL.
835 * ListSize: Size in bytes of the raw and translated resource lists.
836 * Both lists have the same size.
837 * RETURNS:
838 * Status.
839 */
840 {
841 OBJECT_ATTRIBUTES ObjectAttributes;
842 UNICODE_STRING Name;
843 ULONG Disposition;
844 NTSTATUS Status;
845 HANDLE ResourcemapKey;
846 HANDLE HalKey;
847 HANDLE DescriptionKey;
848
849 /* Open/Create 'RESOURCEMAP' key. */
850 RtlRosInitUnicodeStringFromLiteral(&Name,
851 L"\\Registry\\Machine\\HARDWARE\\RESOURCEMAP");
852 InitializeObjectAttributes(&ObjectAttributes,
853 &Name,
854 OBJ_CASE_INSENSITIVE | OBJ_OPENIF,
855 0,
856 NULL);
857 Status = NtCreateKey(&ResourcemapKey,
858 KEY_ALL_ACCESS,
859 &ObjectAttributes,
860 0,
861 NULL,
862 REG_OPTION_VOLATILE,
863 &Disposition);
864 if (!NT_SUCCESS(Status))
865 return(Status);
866
867 /* Open/Create 'Hardware Abstraction Layer' key */
868 RtlRosInitUnicodeStringFromLiteral(&Name,
869 L"Hardware Abstraction Layer");
870 InitializeObjectAttributes(&ObjectAttributes,
871 &Name,
872 OBJ_CASE_INSENSITIVE | OBJ_OPENIF,
873 ResourcemapKey,
874 NULL);
875 Status = NtCreateKey(&HalKey,
876 KEY_ALL_ACCESS,
877 &ObjectAttributes,
878 0,
879 NULL,
880 REG_OPTION_VOLATILE,
881 &Disposition);
882 NtClose(ResourcemapKey);
883 if (!NT_SUCCESS(Status))
884 return(Status);
885
886 /* Create 'HalDescription' key */
887 InitializeObjectAttributes(&ObjectAttributes,
888 HalDescription,
889 OBJ_CASE_INSENSITIVE,
890 HalKey,
891 NULL);
892 Status = NtCreateKey(&DescriptionKey,
893 KEY_ALL_ACCESS,
894 &ObjectAttributes,
895 0,
896 NULL,
897 REG_OPTION_VOLATILE,
898 &Disposition);
899 NtClose(HalKey);
900 if (!NT_SUCCESS(Status))
901 return(Status);
902
903 /* Add '.Raw' value. */
904 RtlRosInitUnicodeStringFromLiteral(&Name,
905 L".Raw");
906 Status = NtSetValueKey(DescriptionKey,
907 &Name,
908 0,
909 REG_RESOURCE_LIST,
910 RawList,
911 ListSize);
912 if (!NT_SUCCESS(Status))
913 {
914 NtClose(DescriptionKey);
915 return(Status);
916 }
917
918 /* Add '.Translated' value. */
919 RtlRosInitUnicodeStringFromLiteral(&Name,
920 L".Translated");
921 Status = NtSetValueKey(DescriptionKey,
922 &Name,
923 0,
924 REG_RESOURCE_LIST,
925 TranslatedList,
926 ListSize);
927 NtClose(DescriptionKey);
928
929 return(Status);
930 }
931
932 /* EOF */