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