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