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