2133 lines
65 KiB
C
2133 lines
65 KiB
C
|
||
/*++
|
||
|
||
Copyright (c) 1994-2000 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
mapper.c
|
||
|
||
Abstract:
|
||
|
||
This module contains the code that manipulates the ARC firmware
|
||
tree and other elements in the registry.
|
||
|
||
Author:
|
||
|
||
Bob Rinne (BobRi) 15-Oct-1994
|
||
|
||
Environment:
|
||
|
||
Kernel mode
|
||
|
||
Revision History :
|
||
|
||
--*/
|
||
|
||
#include "pnpmgrp.h"
|
||
#pragma hdrstop
|
||
|
||
#ifdef POOL_TAGGING
|
||
#undef ExAllocatePool
|
||
#define ExAllocatePool(a,b) ExAllocatePoolWithTag(a,b,'rpaM')
|
||
#endif
|
||
|
||
|
||
//
|
||
// This contains information obtained by checking the firmware
|
||
// tree of the registry
|
||
//
|
||
|
||
typedef struct _FIRMWARE_CONFIGURATION {
|
||
struct _FIRMWARE_CONFIGURATION *Next;
|
||
INTERFACE_TYPE BusType;
|
||
ULONG BusNumber;
|
||
CONFIGURATION_TYPE ControllerType;
|
||
ULONG ControllerNumber;
|
||
CONFIGURATION_TYPE PeripheralType;
|
||
ULONG PeripheralNumber;
|
||
ULONG NumberBases;
|
||
ULONG ResourceDescriptorSize;
|
||
PVOID ResourceDescriptor;
|
||
ULONG IdentifierLength;
|
||
ULONG IdentifierType;
|
||
PVOID Identifier;
|
||
WCHAR const* PnPId;
|
||
BOOLEAN NewlyCreated;
|
||
} FIRMWARE_CONFIGURATION, *PFIRMWARE_CONFIGURATION;
|
||
|
||
//
|
||
// Device extension information
|
||
//
|
||
|
||
typedef struct _DEVICE_EXTENSION {
|
||
PDEVICE_OBJECT DeviceObject;
|
||
PDRIVER_OBJECT DriverObject;
|
||
INTERFACE_TYPE InterfaceType;
|
||
ULONG BusNumber;
|
||
PFIRMWARE_CONFIGURATION FirmwareList;
|
||
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
|
||
//
|
||
// mapping table from firmware to enum
|
||
//
|
||
|
||
typedef struct _FIRMWARE_IDENT_TO_PNP_ID {
|
||
PWCHAR FirmwareName;
|
||
PWCHAR PnPId;
|
||
} FIRMWARE_IDENT_TO_PNP_ID, *PFIRMWARE_IDENT_TO_PNP_ID;
|
||
|
||
//
|
||
// table to hold seed information for a firmware tree entry.
|
||
//
|
||
|
||
#define OPTIONS_NONE 0x00000000
|
||
#define OPTIONS_INSERT_PNP_ID 0x00000001
|
||
#define OPTIONS_INSERT_DEVICEDESC 0x00000002
|
||
#define OPTIONS_INSERT_COMPATIBLE_IDS 0x00000004
|
||
#define OPTIONS_INSERT_PHANTOM_MARKER 0x00000008
|
||
typedef struct _MAPPER_SEED {
|
||
PWCHAR ValueName;
|
||
ULONG ValueType;
|
||
ULONG DwordValueContent;
|
||
ULONG Options;
|
||
} MAPPER_SEED, *PMAPPER_SEED;
|
||
|
||
//
|
||
// table to hold key names and attributes for construction
|
||
// in the root enumerator tree
|
||
//
|
||
|
||
#define KEY_SEED_REQUIRED 0x00000000
|
||
#define KEY_SEED_DEVICE_PARAMETERS 0x00000001
|
||
typedef struct _KEY_SEED {
|
||
PWCHAR KeyName;
|
||
ULONG Attribute;
|
||
ULONG Options;
|
||
} KEY_SEED, *PKEY_SEED;
|
||
|
||
|
||
//
|
||
// All the data here is INIT only
|
||
//
|
||
|
||
#ifdef ALLOC_DATA_PRAGMA
|
||
#pragma const_seg("INITCONST")
|
||
#pragma data_seg("INITDATA")
|
||
#endif
|
||
|
||
DEVICE_EXTENSION MapperDeviceExtension;
|
||
|
||
//
|
||
// This table is used to translate the firmware tree information
|
||
// to the root enumerator PNP id for keyboard devices.
|
||
//
|
||
|
||
const FIRMWARE_IDENT_TO_PNP_ID KeyboardMap[] = {
|
||
L"XT_83KEY", L"*PNP0300",
|
||
L"PCAT_86KEY", L"*PNP0301",
|
||
L"PCXT_84KEY", L"*PNP0302",
|
||
L"XT_84KEY", L"*PNP0302",
|
||
L"101-KEY", L"*PNP0303",
|
||
L"OLI_83KEY", L"*PNP0304",
|
||
L"ATT_301", L"*PNP0304",
|
||
L"OLI_102KEY", L"*PNP0305",
|
||
L"OLI_86KEY", L"*PNP0306",
|
||
L"OLI_A101_102KEY", L"*PNP0309",
|
||
L"ATT_302", L"*PNP030a",
|
||
L"PCAT_ENHANCED", L"*PNP030b",
|
||
L"PC98_106KEY", L"*nEC1300",
|
||
L"PC98_LaptopKEY", L"*nEC1300",
|
||
L"PC98_N106KEY", L"*PNP0303",
|
||
NULL, NULL
|
||
};
|
||
|
||
#define PS2_KEYBOARD_COMPATIBLE_ID L"PS2_KEYBOARD"
|
||
#define PS2_MOUSE_COMPATIBLE_ID L"PS2_MOUSE"
|
||
|
||
//
|
||
// This table is used to translate the firmware tree information
|
||
// to the root enumerator PNP id for pointer devices.
|
||
//
|
||
|
||
const FIRMWARE_IDENT_TO_PNP_ID PointerMap[] = {
|
||
L"PS2 MOUSE", L"*PNP0F0E",
|
||
L"SERIAL MOUSE", L"*PNP0F0C",
|
||
L"MICROSOFT PS2 MOUSE", L"*PNP0F03",
|
||
L"LOGITECH PS2 MOUSE", L"*PNP0F12",
|
||
L"MICROSOFT INPORT MOUSE", L"*PNP0F02",
|
||
L"MICROSOFT SERIAL MOUSE", L"*PNP0F01",
|
||
L"MICROSOFT BALLPOINT SERIAL MOUSE", L"*PNP0F09",
|
||
L"LOGITECH SERIAL MOUSE", L"*PNP0F08",
|
||
L"MICROSOFT BUS MOUSE", L"*PNP0F00",
|
||
L"NEC PC-9800 BUS MOUSE", L"*nEC1F00",
|
||
NULL, NULL
|
||
};
|
||
|
||
//
|
||
// the MapperValueSeed table is a NULL terminated table (i.e. the name
|
||
// pointer is NULL) that contains the list of values and their type
|
||
// for insertion in a newly created root enumerator key.
|
||
//
|
||
|
||
const MAPPER_SEED MapperValueSeed[] = {
|
||
REGSTR_VALUE_HARDWAREID, REG_MULTI_SZ, 0, OPTIONS_INSERT_PNP_ID,
|
||
REGSTR_VALUE_COMPATIBLEIDS, REG_MULTI_SZ, 0, OPTIONS_INSERT_COMPATIBLE_IDS,
|
||
REGSTR_VAL_FIRMWAREIDENTIFIED, REG_DWORD, 1, OPTIONS_NONE,
|
||
REGSTR_VAL_DEVDESC, REG_SZ, 0, OPTIONS_INSERT_DEVICEDESC,
|
||
REGSTR_VAL_PHANTOM, REG_DWORD, 1, OPTIONS_INSERT_PHANTOM_MARKER,
|
||
NULL, 0, 0, 0
|
||
};
|
||
|
||
//
|
||
// the MapperKeySeed table is a NULL terminated table (i.e. the name
|
||
// pointer is NULL) that contains the list of keys to and their
|
||
// attributes (volatile or non-volatile) for keys to be created under
|
||
// a newly created root enumerator key.
|
||
//
|
||
// The preceeding backslash is required on all entries in this table.
|
||
//
|
||
|
||
const KEY_SEED MapperKeySeed[] = {
|
||
L"\\Control", REG_OPTION_VOLATILE, KEY_SEED_REQUIRED,
|
||
L"\\LogConf", REG_OPTION_NON_VOLATILE, KEY_SEED_REQUIRED,
|
||
L"", REG_OPTION_NON_VOLATILE, KEY_SEED_DEVICE_PARAMETERS,
|
||
NULL, 0, 0
|
||
};
|
||
|
||
//
|
||
// SerialId is used as the PNP id for all serial controllers.
|
||
// NOTE: there is no code to detect presense of a 16550.
|
||
//
|
||
|
||
const WCHAR SerialId[] = L"*PNP0501"; // RDR should be two entries. *PNP0501 is 16550
|
||
|
||
//
|
||
// ParallelId is used as the PNP id for all parallel controllers.
|
||
// NOTE: there is no code to detect presense of ECP support.
|
||
//
|
||
|
||
const WCHAR ParallelId[] = L"*PNP0400"; // RDR should be two entries. *PNP0401 is ECP
|
||
|
||
//
|
||
// FloppyId is used as the PNP id for all floppy peripherals.
|
||
//
|
||
|
||
const WCHAR FloppyId[] = L"*PNP0700";
|
||
|
||
//
|
||
// ATAId is here, but not used - there is nothing in the firmware
|
||
// tree for the IDE controller.
|
||
//
|
||
|
||
const WCHAR ATAId[] = L"*PNP0600";
|
||
|
||
//
|
||
// Proto type declarations
|
||
//
|
||
|
||
FIRMWARE_IDENT_TO_PNP_ID const*
|
||
MapperFindIdentMatch(
|
||
FIRMWARE_IDENT_TO_PNP_ID const* IdentTable,
|
||
PWCHAR String
|
||
);
|
||
|
||
WCHAR const*
|
||
MapperTranslatePnPId(
|
||
CONFIGURATION_TYPE PeripheralType,
|
||
PKEY_VALUE_FULL_INFORMATION Identifier
|
||
);
|
||
|
||
NTSTATUS
|
||
MapperPeripheralCallback(
|
||
IN PVOID Context,
|
||
IN PUNICODE_STRING PathName,
|
||
IN INTERFACE_TYPE BusType,
|
||
IN ULONG BusNumber,
|
||
IN PKEY_VALUE_FULL_INFORMATION *BusInformation,
|
||
IN CONFIGURATION_TYPE ControllerType,
|
||
IN ULONG ControllerNumber,
|
||
IN PKEY_VALUE_FULL_INFORMATION *ControllerInformation,
|
||
IN CONFIGURATION_TYPE PeripheralType,
|
||
IN ULONG PeripheralNumber,
|
||
IN PKEY_VALUE_FULL_INFORMATION *PeripheralInformation
|
||
);
|
||
|
||
NTSTATUS
|
||
MapperCallback(
|
||
IN PVOID Context,
|
||
IN PUNICODE_STRING PathName,
|
||
IN INTERFACE_TYPE BusType,
|
||
IN ULONG BusNumber,
|
||
IN PKEY_VALUE_FULL_INFORMATION *BusInformation,
|
||
IN CONFIGURATION_TYPE ControllerType,
|
||
IN ULONG ControllerNumber,
|
||
IN PKEY_VALUE_FULL_INFORMATION *ControllerInformation,
|
||
IN CONFIGURATION_TYPE PeripheralType,
|
||
IN ULONG PeripheralNumber,
|
||
IN PKEY_VALUE_FULL_INFORMATION *PeripheralInformation
|
||
);
|
||
|
||
VOID
|
||
MapperMarkKey(
|
||
IN HANDLE Handle,
|
||
IN PUNICODE_STRING PathName,
|
||
IN PFIRMWARE_CONFIGURATION FirmwareEntry
|
||
);
|
||
|
||
VOID
|
||
MapperSeedKey(
|
||
IN HANDLE Handle,
|
||
IN PUNICODE_STRING PathName,
|
||
IN PFIRMWARE_CONFIGURATION FirmwareEntry,
|
||
IN BOOLEAN DeviceIsPhantom
|
||
);
|
||
|
||
PCM_RESOURCE_LIST
|
||
MapperAdjustResourceList (
|
||
IN PCM_RESOURCE_LIST ResourceList,
|
||
IN WCHAR const* PnPId,
|
||
IN OUT PULONG Size
|
||
);
|
||
|
||
NTSTATUS
|
||
ComPortDBAdd(
|
||
IN HANDLE DeviceParamKey,
|
||
IN PWSTR PortName
|
||
);
|
||
|
||
#ifdef ALLOC_PRAGMA
|
||
#pragma alloc_text(INIT, MapperFindIdentMatch)
|
||
#pragma alloc_text(INIT, MapperTranslatePnPId)
|
||
#pragma alloc_text(INIT, MapperPeripheralCallback)
|
||
#pragma alloc_text(INIT, MapperCallback)
|
||
#pragma alloc_text(INIT, MapperProcessFirmwareTree)
|
||
#pragma alloc_text(INIT, MapperMarkKey)
|
||
#pragma alloc_text(INIT, MapperSeedKey)
|
||
#pragma alloc_text(INIT, MapperFreeList)
|
||
#pragma alloc_text(INIT, MapperConstructRootEnumTree)
|
||
#pragma alloc_text(INIT, MapperAdjustResourceList)
|
||
#pragma alloc_text(INIT, ComPortDBAdd)
|
||
#pragma alloc_text(INIT, MapperPhantomizeDetectedComPorts)
|
||
#endif
|
||
|
||
FIRMWARE_IDENT_TO_PNP_ID const*
|
||
MapperFindIdentMatch(
|
||
FIRMWARE_IDENT_TO_PNP_ID const* IdentTable,
|
||
PWCHAR String
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Given a table of strings to match, find the match for
|
||
the identifier given.
|
||
|
||
Arguments:
|
||
|
||
Return Value:
|
||
|
||
A pointer to the ident table entry for the match if found
|
||
NULL if not found.
|
||
|
||
--*/
|
||
|
||
{
|
||
FIRMWARE_IDENT_TO_PNP_ID const* entry;
|
||
|
||
entry = IdentTable;
|
||
while (entry->FirmwareName) {
|
||
if (!wcscmp(String, entry->FirmwareName)) {
|
||
return entry;
|
||
}
|
||
entry++;
|
||
}
|
||
return NULL;
|
||
}
|
||
|
||
WCHAR const*
|
||
MapperTranslatePnPId(
|
||
CONFIGURATION_TYPE PeripheralType,
|
||
PKEY_VALUE_FULL_INFORMATION Identifier
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Given the peripheral type and a location in the firmware tree
|
||
this routine will determine the PnP Id to be used when constructing
|
||
the root enumeration portion of the registry.
|
||
|
||
Arguments:
|
||
|
||
PeripheralType - the type of item being translated (keyboard, mouse, etc)
|
||
PathName - the registry path name into the firmware tree for
|
||
this device.
|
||
|
||
Return Value:
|
||
|
||
A pointer to the PnP Id string if a map is found.
|
||
|
||
--*/
|
||
|
||
{
|
||
FIRMWARE_IDENT_TO_PNP_ID const* identMap;
|
||
PWSTR identifierString = NULL;
|
||
WCHAR const* idStr;
|
||
|
||
if (Identifier) {
|
||
identifierString = (PWSTR)((PUCHAR)Identifier + Identifier->DataOffset);
|
||
IopDbgPrint((IOP_MAPPER_INFO_LEVEL,
|
||
"Mapper: identifier = %ws\n\tType = ",
|
||
identifierString));
|
||
}
|
||
|
||
idStr = NULL;
|
||
switch (PeripheralType) {
|
||
case DiskController:
|
||
IopDbgPrint((IOP_MAPPER_INFO_LEVEL,
|
||
"%s (%d)\n",
|
||
"DiskController",
|
||
PeripheralType));
|
||
idStr = FloppyId;
|
||
break;
|
||
|
||
case SerialController:
|
||
IopDbgPrint((IOP_MAPPER_INFO_LEVEL,
|
||
"%s (%d)\n",
|
||
"SerialController",
|
||
PeripheralType));
|
||
idStr = SerialId;
|
||
break;
|
||
|
||
case ParallelController:
|
||
IopDbgPrint((IOP_MAPPER_INFO_LEVEL,
|
||
"%s (%d)\n",
|
||
"ParallelController",
|
||
PeripheralType));
|
||
idStr = ParallelId;
|
||
break;
|
||
|
||
case PointerController:
|
||
IopDbgPrint((IOP_MAPPER_INFO_LEVEL,
|
||
"%s (%d)\n",
|
||
"PointerController",
|
||
PeripheralType));
|
||
idStr = PointerMap[0].PnPId;
|
||
break;
|
||
|
||
case KeyboardController:
|
||
IopDbgPrint((IOP_MAPPER_INFO_LEVEL,
|
||
"%s (%d)\n",
|
||
"KeyboardController",
|
||
PeripheralType));
|
||
idStr = KeyboardMap[0].PnPId;
|
||
break;
|
||
|
||
case DiskPeripheral:
|
||
IopDbgPrint((IOP_MAPPER_INFO_LEVEL,
|
||
"%s (%d)\n",
|
||
"DiskPeripheral",
|
||
PeripheralType));
|
||
break;
|
||
|
||
case FloppyDiskPeripheral:
|
||
IopDbgPrint((IOP_MAPPER_INFO_LEVEL,
|
||
"%s (%d)\n",
|
||
"FloppyDiskPeripheral",
|
||
PeripheralType));
|
||
idStr = FloppyId;
|
||
break;
|
||
|
||
case PointerPeripheral:
|
||
if (identifierString) {
|
||
identMap = MapperFindIdentMatch(PointerMap, identifierString);
|
||
if (identMap) {
|
||
IopDbgPrint((IOP_MAPPER_INFO_LEVEL,
|
||
"%ws\n",
|
||
identMap->PnPId));
|
||
idStr = identMap->PnPId;
|
||
} else {
|
||
IopDbgPrint((IOP_MAPPER_ERROR_LEVEL,
|
||
"Mapper: No pointer match found\n"));
|
||
}
|
||
} else {
|
||
IopDbgPrint((IOP_MAPPER_ERROR_LEVEL,
|
||
"Mapper: No identifier specified\n"));
|
||
}
|
||
break;
|
||
|
||
case KeyboardPeripheral:
|
||
if (identifierString) {
|
||
identMap = MapperFindIdentMatch(KeyboardMap, identifierString);
|
||
|
||
if (identMap) {
|
||
IopDbgPrint((IOP_MAPPER_INFO_LEVEL,
|
||
"%ws\n",
|
||
identMap->PnPId));
|
||
idStr = identMap->PnPId;
|
||
} else {
|
||
IopDbgPrint((IOP_MAPPER_ERROR_LEVEL,
|
||
"Mapper: No keyboard match found\n"));
|
||
}
|
||
} else {
|
||
IopDbgPrint((IOP_MAPPER_ERROR_LEVEL,
|
||
"Mapper: No identifier specified\n"));
|
||
}
|
||
break;
|
||
|
||
default:
|
||
IopDbgPrint((IOP_MAPPER_ERROR_LEVEL,
|
||
"Mapper: Unknown device (%d)\n",
|
||
PeripheralType));
|
||
break;
|
||
}
|
||
return idStr;
|
||
}
|
||
|
||
|
||
NTSTATUS
|
||
MapperPeripheralCallback(
|
||
IN PVOID Context,
|
||
IN PUNICODE_STRING PathName,
|
||
IN INTERFACE_TYPE BusType,
|
||
IN ULONG BusNumber,
|
||
IN PKEY_VALUE_FULL_INFORMATION *BusInformation,
|
||
IN CONFIGURATION_TYPE ControllerType,
|
||
IN ULONG ControllerNumber,
|
||
IN PKEY_VALUE_FULL_INFORMATION *ControllerInformation,
|
||
IN CONFIGURATION_TYPE PeripheralType,
|
||
IN ULONG PeripheralNumber,
|
||
IN PKEY_VALUE_FULL_INFORMATION *PeripheralInformation
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is used to acquire firmware tree information about
|
||
pointer devices in the system.
|
||
|
||
Arguments:
|
||
|
||
Context - Pointer to the device extension.
|
||
PathName - unicode registry path.
|
||
BusType - Internal, Isa, ...
|
||
BusNumber - Which bus if we are on a multibus system.
|
||
BusInformation - Configuration information about the bus. Not Used.
|
||
ControllerType - serial or ata disk.
|
||
ControllerNumber - Which controller if there is more than one
|
||
controller in the system.
|
||
ControllerInformation - Array of pointers to the three pieces of
|
||
registry information.
|
||
PeripheralType - Undefined for this call.
|
||
PeripheralNumber - Undefined for this call.
|
||
PeripheralInformation - Undefined for this call.
|
||
|
||
Return Value:
|
||
|
||
STATUS_SUCCESS if everything went ok, or STATUS_INSUFFICIENT_RESOURCES
|
||
if it couldn't map the base csr or acquire the device object, or
|
||
all of the resource information couldn't be acquired.
|
||
|
||
--*/
|
||
|
||
{
|
||
PFIRMWARE_CONFIGURATION firmwareEntry = Context;
|
||
PKEY_VALUE_FULL_INFORMATION information;
|
||
ULONG dataLength;
|
||
PWCHAR ptr;
|
||
PVOID temp;
|
||
|
||
UNREFERENCED_PARAMETER( BusType );
|
||
UNREFERENCED_PARAMETER( BusNumber );
|
||
UNREFERENCED_PARAMETER( BusInformation );
|
||
UNREFERENCED_PARAMETER( ControllerType );
|
||
UNREFERENCED_PARAMETER( ControllerNumber );
|
||
|
||
IopDbgPrint((IOP_MAPPER_INFO_LEVEL,
|
||
"Mapper: peripheral registry location is\n %ws\n",
|
||
PathName->Buffer));
|
||
|
||
if (!ControllerInformation) {
|
||
IopDbgPrint((IOP_MAPPER_VERBOSE_LEVEL,
|
||
"Mapper: No component information\n"));
|
||
}
|
||
if (!PeripheralInformation) {
|
||
IopDbgPrint((IOP_MAPPER_VERBOSE_LEVEL,
|
||
"Mapper: No peripheral information\n"));
|
||
return STATUS_SUCCESS;
|
||
}
|
||
|
||
//
|
||
// Map the PnP Id for this device.
|
||
//
|
||
|
||
if (PeripheralInformation[IoQueryDeviceIdentifier]) {
|
||
information = PeripheralInformation[IoQueryDeviceIdentifier];
|
||
firmwareEntry->PnPId = MapperTranslatePnPId(PeripheralType, information);
|
||
|
||
if (firmwareEntry->PnPId) {
|
||
//
|
||
// Remember the peripheral's identifier (if it has one, and it's a REG_SZ value)
|
||
// for use as the default PnP device description.
|
||
//
|
||
|
||
if (((dataLength = information->DataLength) > sizeof(WCHAR)) &&
|
||
(information->Type == REG_SZ)) {
|
||
|
||
ptr = (PWCHAR) ((PUCHAR)information + information->DataOffset);
|
||
|
||
if (*ptr) {
|
||
temp = ExAllocatePool(NonPagedPool, dataLength);
|
||
if (temp) {
|
||
|
||
//
|
||
// If there's already an identifier here (from the peripheral's
|
||
// controller) then wipe it out.
|
||
//
|
||
|
||
if(firmwareEntry->Identifier) {
|
||
ExFreePool(firmwareEntry->Identifier);
|
||
}
|
||
|
||
//
|
||
// Move the data
|
||
//
|
||
|
||
firmwareEntry->Identifier = temp;
|
||
firmwareEntry->IdentifierType = information->Type;
|
||
firmwareEntry->IdentifierLength = dataLength;
|
||
RtlCopyMemory(temp, ptr, dataLength);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
//
|
||
// Save the ordinals for the peripheral type and number
|
||
//
|
||
|
||
firmwareEntry->PeripheralType = PeripheralType;
|
||
firmwareEntry->PeripheralNumber = PeripheralNumber;
|
||
|
||
return STATUS_SUCCESS;
|
||
}
|
||
|
||
NTSTATUS
|
||
MapperCallback(
|
||
IN PVOID Context,
|
||
IN PUNICODE_STRING PathName,
|
||
IN INTERFACE_TYPE BusType,
|
||
IN ULONG BusNumber,
|
||
IN PKEY_VALUE_FULL_INFORMATION *BusInformation,
|
||
IN CONFIGURATION_TYPE ControllerType,
|
||
IN ULONG ControllerNumber,
|
||
IN PKEY_VALUE_FULL_INFORMATION *ControllerInformation,
|
||
IN CONFIGURATION_TYPE PeripheralType,
|
||
IN ULONG PeripheralNumber,
|
||
IN PKEY_VALUE_FULL_INFORMATION *PeripheralInformation
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is used to acquire firmware tree information about
|
||
pointer devices in the system.
|
||
|
||
Arguments:
|
||
|
||
Context - Pointer to the device extension.
|
||
PathName - unicode registry path.
|
||
BusType - Internal, Isa, ...
|
||
BusNumber - Which bus if we are on a multibus system.
|
||
BusInformation - Configuration information about the bus. Not Used.
|
||
ControllerType - serial or ata disk.
|
||
ControllerNumber - Which controller if there is more than one
|
||
controller in the system.
|
||
ControllerInformation - Array of pointers to the three pieces of
|
||
registry information.
|
||
PeripheralType - Undefined for this call.
|
||
PeripheralNumber - Undefined for this call.
|
||
PeripheralInformation - Undefined for this call.
|
||
|
||
Return Value:
|
||
|
||
STATUS_SUCCESS if everything went ok, or STATUS_INSUFFICIENT_RESOURCES
|
||
if it couldn't map the base csr or acquire the device object, or
|
||
all of the resource information couldn't be acquired.
|
||
|
||
--*/
|
||
|
||
{
|
||
PDEVICE_EXTENSION deviceExtension = Context;
|
||
PCM_FULL_RESOURCE_DESCRIPTOR controllerData;
|
||
PKEY_VALUE_FULL_INFORMATION information;
|
||
PFIRMWARE_CONFIGURATION firmwareEntry;
|
||
CONFIGURATION_TYPE peripheralType;
|
||
PUCHAR buffer;
|
||
ULONG dataLength;
|
||
|
||
UNREFERENCED_PARAMETER( BusInformation );
|
||
UNREFERENCED_PARAMETER( PeripheralType );
|
||
UNREFERENCED_PARAMETER( PeripheralNumber );
|
||
UNREFERENCED_PARAMETER( PeripheralInformation );
|
||
|
||
//
|
||
// If entry is found, but there is no information just return
|
||
//
|
||
|
||
information = ControllerInformation[IoQueryDeviceConfigurationData];
|
||
if (information == NULL) {
|
||
|
||
return STATUS_SUCCESS;
|
||
}
|
||
|
||
dataLength = information->DataLength;
|
||
if (dataLength == 0) {
|
||
|
||
return STATUS_SUCCESS;
|
||
}
|
||
|
||
//
|
||
// Setup to capture the information from the firmware tree
|
||
//
|
||
|
||
firmwareEntry = ExAllocatePool(NonPagedPool, sizeof(FIRMWARE_CONFIGURATION));
|
||
if (!firmwareEntry) {
|
||
|
||
return STATUS_INSUFFICIENT_RESOURCES;
|
||
}
|
||
RtlZeroMemory(firmwareEntry, sizeof(FIRMWARE_CONFIGURATION));
|
||
|
||
//
|
||
// Save information concerning the controller
|
||
//
|
||
|
||
firmwareEntry->ControllerType = ControllerType;
|
||
firmwareEntry->ControllerNumber = ControllerNumber;
|
||
firmwareEntry->BusNumber = BusNumber;
|
||
firmwareEntry->BusType = BusType;
|
||
|
||
//
|
||
// Save the resource descriptor
|
||
//
|
||
|
||
buffer = firmwareEntry->ResourceDescriptor = ExAllocatePool(NonPagedPool,
|
||
dataLength);
|
||
|
||
if (!buffer) {
|
||
ExFreePool(firmwareEntry);
|
||
return STATUS_INSUFFICIENT_RESOURCES;
|
||
}
|
||
|
||
//
|
||
// Save the configuration information on this controller.
|
||
//
|
||
|
||
controllerData = (PCM_FULL_RESOURCE_DESCRIPTOR)
|
||
((PUCHAR)information + information->DataOffset);
|
||
RtlCopyMemory(buffer, controllerData, dataLength);
|
||
firmwareEntry->ResourceDescriptorSize = dataLength;
|
||
|
||
//
|
||
// If there is a device identifier save it.
|
||
//
|
||
|
||
information = ControllerInformation[IoQueryDeviceIdentifier];
|
||
if (information != NULL) {
|
||
PWCHAR ptr;
|
||
|
||
dataLength = information->DataLength;
|
||
if (dataLength != 0) {
|
||
|
||
ptr = (PWCHAR) ((PUCHAR)information + information->DataOffset);
|
||
if (ControllerType == ParallelController) {
|
||
PWCHAR tmpChar;
|
||
|
||
//
|
||
// Some extra mapping is performed here to
|
||
// translate the firmware names to LPT names.
|
||
//
|
||
|
||
*ptr++ = (WCHAR) 'L';
|
||
*ptr++ = (WCHAR) 'P';
|
||
*ptr++ = (WCHAR) 'T';
|
||
|
||
//
|
||
// Find the number.
|
||
//
|
||
|
||
tmpChar = ptr;
|
||
while (*tmpChar) {
|
||
if ((*tmpChar >= (WCHAR) '0') &&
|
||
(*tmpChar <= (WCHAR) '9')) {
|
||
break;
|
||
}
|
||
tmpChar++;
|
||
}
|
||
|
||
if (*tmpChar) {
|
||
while (*tmpChar) {
|
||
*ptr++ = *tmpChar++;
|
||
}
|
||
*ptr = (WCHAR) 0;
|
||
|
||
//
|
||
// Update the datalength to be 4 wchars and eos and
|
||
// restore the pointer.
|
||
//
|
||
|
||
ptr = (PWCHAR) ((PUCHAR)information + information->DataOffset);
|
||
dataLength = 10;
|
||
} else {
|
||
dataLength = 0;
|
||
IopDbgPrint((IOP_MAPPER_ERROR_LEVEL,
|
||
"Mapper: no parallel port number!\n"));
|
||
}
|
||
}
|
||
|
||
if (dataLength) {
|
||
firmwareEntry->Identifier = ExAllocatePool(NonPagedPool,
|
||
dataLength);
|
||
if (firmwareEntry->Identifier) {
|
||
|
||
//
|
||
// Move the data
|
||
//
|
||
|
||
firmwareEntry->IdentifierType = information->Type;
|
||
firmwareEntry->IdentifierLength = dataLength;
|
||
RtlCopyMemory(firmwareEntry->Identifier, ptr, dataLength);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
//
|
||
// For some controllers, search the peripheral information
|
||
//
|
||
|
||
switch (ControllerType) {
|
||
case SerialController:
|
||
case ParallelController:
|
||
//
|
||
// Don't look for a peripheral.
|
||
//
|
||
peripheralType = (CONFIGURATION_TYPE) 0;
|
||
break;
|
||
case DiskController:
|
||
peripheralType = FloppyDiskPeripheral;
|
||
break;
|
||
case KeyboardController:
|
||
peripheralType = KeyboardPeripheral;
|
||
break;
|
||
case PointerController:
|
||
peripheralType = PointerPeripheral;
|
||
break;
|
||
default:
|
||
peripheralType = (CONFIGURATION_TYPE) 0;
|
||
break;
|
||
}
|
||
|
||
IopDbgPrint((IOP_MAPPER_INFO_LEVEL,
|
||
"Mapper: registry location is\n %ws\n",
|
||
PathName->Buffer));
|
||
|
||
IopDbgPrint((IOP_MAPPER_INFO_LEVEL,
|
||
"Mapper: ControllerInformation[] -\n\tIdent: %x -\n\tData: %x -\n\tInformation: %x\n",
|
||
ControllerInformation[0],
|
||
ControllerInformation[1],
|
||
ControllerInformation[2]));
|
||
|
||
if (peripheralType) {
|
||
IopDbgPrint((IOP_MAPPER_INFO_LEVEL,
|
||
"Mapper: searching for peripheral type %d\n",
|
||
peripheralType));
|
||
|
||
IoQueryDeviceDescription(&BusType,
|
||
&BusNumber,
|
||
&ControllerType,
|
||
&ControllerNumber,
|
||
&peripheralType,
|
||
NULL,
|
||
MapperPeripheralCallback,
|
||
firmwareEntry);
|
||
}
|
||
|
||
//
|
||
// firmwareEntry->PnPId will be NULL if there are no peripherals of this
|
||
// type in the tree or if the peripheral's description doesn't match one of
|
||
// those in our table.
|
||
//
|
||
// firmwareEntry->PeripheralType will be equal to peripheralType if we found
|
||
// one of the proper type regardless of whether or not it is in the table.
|
||
//
|
||
// So this test just ensures that we fallback to the controller IDs in the
|
||
// case were there is no peripheral entry. If there is a peripheral entry
|
||
// that we don't understand we will suppress the entire node.
|
||
//
|
||
// This prevents creating devices with hw ids of bogus as we were seeing on
|
||
// the SGI x86 ARC machines.
|
||
//
|
||
|
||
if (!firmwareEntry->PnPId && firmwareEntry->PeripheralType == 0) {
|
||
|
||
//
|
||
// Attempt to get PnPId from the controller type.
|
||
//
|
||
|
||
firmwareEntry->PnPId = MapperTranslatePnPId(ControllerType, NULL);
|
||
|
||
if (!firmwareEntry->PnPId) {
|
||
IopDbgPrint((IOP_MAPPER_INFO_LEVEL,
|
||
"Mapper: NO PnP Id for\n ==> %ws\n",
|
||
PathName->Buffer));
|
||
}
|
||
}
|
||
|
||
IopDbgPrint((IOP_MAPPER_INFO_LEVEL,
|
||
"Mapper: constructed name %d_%d_%d_%d_%d_%d\n",
|
||
firmwareEntry->BusType,
|
||
firmwareEntry->BusNumber,
|
||
firmwareEntry->ControllerType,
|
||
firmwareEntry->ControllerNumber,
|
||
firmwareEntry->PeripheralType,
|
||
firmwareEntry->PeripheralNumber));
|
||
|
||
if (firmwareEntry->PnPId) {
|
||
|
||
//
|
||
// Link into chain of entries.
|
||
//
|
||
|
||
firmwareEntry->Next = deviceExtension->FirmwareList;
|
||
deviceExtension->FirmwareList = firmwareEntry;
|
||
} else {
|
||
|
||
//
|
||
// No map found - don't remember this entry.
|
||
//
|
||
|
||
ExFreePool(buffer);
|
||
if(firmwareEntry->Identifier) {
|
||
ExFreePool(firmwareEntry->Identifier);
|
||
}
|
||
ExFreePool(firmwareEntry);
|
||
}
|
||
return STATUS_SUCCESS;
|
||
}
|
||
|
||
|
||
VOID
|
||
MapperProcessFirmwareTree(
|
||
IN BOOLEAN OnlyProcessSerialPorts
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Query the information in the firmware tree to know what
|
||
system board devices were located. This will cause a FirmwareList
|
||
to be created on the device extention passed.
|
||
|
||
Arguments:
|
||
|
||
OnlyProcessSerialPorts - if non-zero, then we'll only look at serial ports.
|
||
This is done on ACPI machines where, in general, we don't want to pay
|
||
attention to ntdetect/firmware information (but we have to for serial
|
||
ports so that legacy add-in ISA serial ports and modems are detected
|
||
automatically as in previous versions of NT as well as Win9x).
|
||
|
||
Return Value:
|
||
|
||
None
|
||
|
||
--*/
|
||
|
||
{
|
||
INTERFACE_TYPE interfaceType;
|
||
ULONG index;
|
||
CONFIGURATION_TYPE sc;
|
||
CONFIGURATION_TYPE controllerTypes[] = { PointerController,
|
||
KeyboardController,
|
||
ParallelController,
|
||
DiskController,
|
||
FloppyDiskPeripheral,
|
||
SerialController // must be last
|
||
};
|
||
#define CONTROLLER_TYPES_COUNT (sizeof(controllerTypes) / sizeof(controllerTypes[0]))
|
||
|
||
PAGED_CODE();
|
||
|
||
//
|
||
// Locate all firmware controller information and save its resource usage.
|
||
//
|
||
// It's pretty inefficient to be going through all interface types, when we
|
||
// really only care about a very small subset of non-PnP buses (e.g., ISA,
|
||
// EISA, maybe Internal).
|
||
//
|
||
|
||
for (interfaceType = 0; interfaceType < MaximumInterfaceType; interfaceType++) {
|
||
|
||
IopDbgPrint((IOP_MAPPER_VERBOSE_LEVEL,
|
||
"Mapper: searching on interface ===> %d\n",
|
||
interfaceType));
|
||
|
||
if(OnlyProcessSerialPorts) {
|
||
|
||
//
|
||
// Start out at the last element of the array, so we only process
|
||
// SerialControllers.
|
||
//
|
||
|
||
index = CONTROLLER_TYPES_COUNT - 1;
|
||
} else {
|
||
index = 0;
|
||
}
|
||
|
||
for ( ; index < CONTROLLER_TYPES_COUNT; index++) {
|
||
sc = controllerTypes[index];
|
||
|
||
IoQueryDeviceDescription(&interfaceType,
|
||
NULL,
|
||
&sc,
|
||
NULL,
|
||
NULL,
|
||
NULL,
|
||
MapperCallback,
|
||
&MapperDeviceExtension);
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
VOID
|
||
MapperMarkKey(
|
||
IN HANDLE Handle,
|
||
IN PUNICODE_STRING PathName,
|
||
IN PFIRMWARE_CONFIGURATION FirmwareEntry
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Record in the root enum key that the firmware mapper found this entry.
|
||
Migrate configuration information entries.
|
||
|
||
Arguments:
|
||
|
||
Handle - handle to the key
|
||
PathName - base path name to this key
|
||
FirmwareEntry - information from the firmware tree.
|
||
|
||
Return Value:
|
||
|
||
None
|
||
|
||
--*/
|
||
|
||
{
|
||
OBJECT_ATTRIBUTES objectAttributes;
|
||
PCM_RESOURCE_LIST resourceList;
|
||
UNICODE_STRING unicodeName;
|
||
NTSTATUS status;
|
||
HANDLE subKeyHandle;
|
||
PWCHAR wcptr;
|
||
ULONG disposition;
|
||
ULONG buffer;
|
||
USHORT originalLength;
|
||
|
||
//
|
||
// Mark that this entry was in the firmware tree.
|
||
//
|
||
|
||
buffer = 1;
|
||
PiWstrToUnicodeString(&unicodeName, REGSTR_VAL_FIRMWAREIDENTIFIED);
|
||
|
||
ZwSetValueKey(Handle,
|
||
&unicodeName,
|
||
0,
|
||
REG_DWORD,
|
||
&buffer,
|
||
sizeof(ULONG));
|
||
|
||
//
|
||
// Create the control subkey
|
||
//
|
||
|
||
IopDbgPrint((IOP_MAPPER_INFO_LEVEL,
|
||
"Mapper: marking existing key\n"));
|
||
originalLength = PathName->Length;
|
||
wcptr = (PWCHAR) ((PUCHAR)PathName->Buffer + PathName->Length);
|
||
wcptr++; // locate eos
|
||
|
||
//
|
||
// Build the volatile control key
|
||
//
|
||
|
||
InitializeObjectAttributes(&objectAttributes,
|
||
PathName,
|
||
OBJ_CASE_INSENSITIVE,
|
||
NULL,
|
||
NULL);
|
||
RtlAppendUnicodeToString(PathName, L"\\Control");
|
||
status = ZwCreateKey(&subKeyHandle,
|
||
KEY_READ | KEY_WRITE,
|
||
&objectAttributes,
|
||
0,
|
||
NULL,
|
||
REG_OPTION_VOLATILE,
|
||
&disposition);
|
||
|
||
if (NT_SUCCESS(status)) {
|
||
|
||
//
|
||
// Create the found by firmware volatile.
|
||
//
|
||
|
||
buffer = 1;
|
||
PiWstrToUnicodeString(&unicodeName, REGSTR_VAL_FIRMWAREMEMBER);
|
||
|
||
ZwSetValueKey(subKeyHandle,
|
||
&unicodeName,
|
||
0,
|
||
REG_DWORD,
|
||
&buffer,
|
||
sizeof(ULONG));
|
||
ZwClose(subKeyHandle);
|
||
|
||
} else {
|
||
|
||
//
|
||
// ignore failures
|
||
//
|
||
|
||
IopDbgPrint((IOP_MAPPER_ERROR_LEVEL,
|
||
"Mapper: failed to mark control key %x\n",
|
||
status));
|
||
}
|
||
|
||
//
|
||
// if there is a resource descriptor, restore path and open LogConf key.
|
||
//
|
||
|
||
if (FirmwareEntry->ResourceDescriptor) {
|
||
PathName->Length = originalLength;
|
||
*wcptr = (WCHAR) 0;
|
||
|
||
InitializeObjectAttributes(&objectAttributes,
|
||
PathName,
|
||
OBJ_CASE_INSENSITIVE,
|
||
NULL,
|
||
NULL);
|
||
RtlAppendUnicodeToString(PathName, L"\\LogConf");
|
||
status = ZwCreateKey(&subKeyHandle,
|
||
KEY_READ | KEY_WRITE,
|
||
&objectAttributes,
|
||
0,
|
||
NULL,
|
||
REG_OPTION_VOLATILE,
|
||
&disposition);
|
||
|
||
if (NT_SUCCESS(status)) {
|
||
ULONG size;
|
||
|
||
//
|
||
// two entries need to be made:
|
||
// BootConfig:REG_RESOURCE_LIST
|
||
// BasicConfigVector:REG_RESOURCE_REQUIREMENTS_LIST
|
||
//
|
||
|
||
size = sizeof(CM_RESOURCE_LIST) -
|
||
sizeof(CM_FULL_RESOURCE_DESCRIPTOR) +
|
||
FirmwareEntry->ResourceDescriptorSize;
|
||
|
||
resourceList = ExAllocatePool(NonPagedPool, size);
|
||
|
||
if (resourceList) {
|
||
|
||
resourceList->Count = 1;
|
||
RtlCopyMemory(&resourceList->List[0],
|
||
FirmwareEntry->ResourceDescriptor,
|
||
FirmwareEntry->ResourceDescriptorSize);
|
||
|
||
resourceList = MapperAdjustResourceList (
|
||
resourceList,
|
||
FirmwareEntry->PnPId,
|
||
&size
|
||
);
|
||
|
||
PiWstrToUnicodeString(&unicodeName,
|
||
L"BootConfig");
|
||
ZwSetValueKey(subKeyHandle,
|
||
&unicodeName,
|
||
0,
|
||
REG_RESOURCE_LIST,
|
||
resourceList,
|
||
size);
|
||
#if 0
|
||
//
|
||
// Now do the resource requirements list.
|
||
//
|
||
|
||
reqList = IopCmResourcesToIoResources(0, resourceList);
|
||
|
||
if (reqList) {
|
||
PiWstrToUnicodeString(&unicodeName,
|
||
L"BasicConfigVector");
|
||
ZwSetValueKey(subKeyHandle,
|
||
&unicodeName,
|
||
0,
|
||
REG_RESOURCE_REQUIREMENTS_LIST,
|
||
reqList,
|
||
reqList->ListSize);
|
||
ExFreePool(reqList);
|
||
}
|
||
#endif
|
||
ExFreePool(resourceList);
|
||
}
|
||
|
||
ZwClose(subKeyHandle);
|
||
|
||
} else {
|
||
|
||
//
|
||
// ignore errors
|
||
//
|
||
|
||
IopDbgPrint((IOP_MAPPER_ERROR_LEVEL,
|
||
"Mapper: failed to update logconf key %x\n",
|
||
status));
|
||
}
|
||
}
|
||
|
||
//
|
||
// Restore path passed in.
|
||
//
|
||
|
||
PathName->Length = originalLength;
|
||
*wcptr = (WCHAR) 0;
|
||
}
|
||
|
||
VOID
|
||
MapperSeedKey(
|
||
IN HANDLE Handle,
|
||
IN PUNICODE_STRING PathName,
|
||
IN PFIRMWARE_CONFIGURATION FirmwareEntry,
|
||
IN BOOLEAN DeviceIsPhantom
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine seeds a registry key with enough information
|
||
to get PnP to run the class installer on the devnode.
|
||
|
||
Arguments:
|
||
|
||
Handle - handle to the key
|
||
|
||
PathName - base path name to this key
|
||
|
||
FirmwareEntry - information from the firmware tree
|
||
|
||
DeviceIsPhantom - if non-zero, add "Phantom" value entry so the root
|
||
enumerator will skip this device instance (i.e., not turn it into a
|
||
devnode)
|
||
|
||
Return Value:
|
||
|
||
None
|
||
|
||
--*/
|
||
|
||
{
|
||
#define SEED_BUFFER_SIZE (512 * sizeof(WCHAR))
|
||
UNICODE_STRING unicodeName;
|
||
OBJECT_ATTRIBUTES objectAttributes;
|
||
MAPPER_SEED const* valueSeed;
|
||
KEY_SEED const* keySeed;
|
||
NTSTATUS status;
|
||
HANDLE subKeyHandle;
|
||
WCHAR const* pnpid;
|
||
PWCHAR buffer;
|
||
PWCHAR wcptr;
|
||
ULONG disposition;
|
||
ULONG size;
|
||
USHORT originalLength;
|
||
|
||
buffer = ExAllocatePool(NonPagedPool, SEED_BUFFER_SIZE);
|
||
if (!buffer) {
|
||
return;
|
||
}
|
||
RtlZeroMemory(buffer, SEED_BUFFER_SIZE);
|
||
|
||
//
|
||
// Create subkeys.
|
||
//
|
||
|
||
originalLength = PathName->Length;
|
||
wcptr = (PWCHAR) ((PUCHAR)PathName->Buffer + PathName->Length);
|
||
|
||
for (keySeed = MapperKeySeed; keySeed->KeyName; keySeed++) {
|
||
|
||
//
|
||
// Reset the base path for the next key to seed.
|
||
//
|
||
|
||
*wcptr = (WCHAR) 0;
|
||
PathName->Length = originalLength;
|
||
RtlAppendUnicodeToString(PathName, keySeed->KeyName);
|
||
|
||
//
|
||
// Only build a device parameters key if there is something
|
||
// to put in the key (i.e., this is a serial or parallel port).
|
||
//
|
||
|
||
if (keySeed->Options & KEY_SEED_DEVICE_PARAMETERS) {
|
||
if (((FirmwareEntry->ControllerType != SerialController) && (FirmwareEntry->ControllerType != ParallelController)) ||
|
||
!FirmwareEntry->Identifier) {
|
||
continue;
|
||
}
|
||
|
||
status = IopOpenDeviceParametersSubkey( &subKeyHandle,
|
||
NULL,
|
||
PathName,
|
||
KEY_READ | KEY_WRITE
|
||
);
|
||
if (NT_SUCCESS(status)) {
|
||
status = STATUS_SUCCESS;
|
||
} else {
|
||
status = STATUS_UNSUCCESSFUL;
|
||
}
|
||
} else {
|
||
|
||
//
|
||
// need to construct this key.
|
||
//
|
||
|
||
InitializeObjectAttributes(&objectAttributes,
|
||
PathName,
|
||
OBJ_CASE_INSENSITIVE,
|
||
NULL,
|
||
NULL);
|
||
status = ZwCreateKey(&subKeyHandle,
|
||
KEY_READ | KEY_WRITE,
|
||
&objectAttributes,
|
||
0,
|
||
NULL,
|
||
keySeed->Attribute,
|
||
&disposition);
|
||
}
|
||
|
||
if (NT_SUCCESS(status)) {
|
||
|
||
//
|
||
// Check to see if this is the parameters key and
|
||
// migrate the parameter information.
|
||
//
|
||
|
||
if (keySeed->Options & KEY_SEED_DEVICE_PARAMETERS) {
|
||
|
||
if (FirmwareEntry->ControllerType == SerialController) {
|
||
|
||
ComPortDBAdd(subKeyHandle, (PWSTR)FirmwareEntry->Identifier);
|
||
} else {
|
||
//
|
||
// to get here there must be identifier information
|
||
// in the FirmwareEntry, so that check is not performed.
|
||
//
|
||
// NOTE: this will only happen once - when the key is
|
||
// created -- perhaps this needs to happen on every
|
||
// boot.
|
||
//
|
||
|
||
PiWstrToUnicodeString(&unicodeName,
|
||
L"DosDeviceName");
|
||
ZwSetValueKey(subKeyHandle,
|
||
&unicodeName,
|
||
0,
|
||
FirmwareEntry->IdentifierType,
|
||
FirmwareEntry->Identifier,
|
||
FirmwareEntry->IdentifierLength);
|
||
}
|
||
}
|
||
ZwClose(subKeyHandle);
|
||
} else {
|
||
|
||
//
|
||
// ignore failures
|
||
//
|
||
|
||
IopDbgPrint((IOP_MAPPER_ERROR_LEVEL,
|
||
"Mapper: failed to build control key %x\n",
|
||
status));
|
||
}
|
||
}
|
||
|
||
//
|
||
// Undo the mangling of the path name performed in the loop above.
|
||
//
|
||
|
||
*wcptr = (WCHAR) 0;
|
||
PathName->Length = originalLength;
|
||
|
||
//
|
||
// Create values.
|
||
//
|
||
|
||
pnpid = FirmwareEntry->PnPId;
|
||
for (valueSeed = MapperValueSeed; valueSeed->ValueName; valueSeed++) {
|
||
|
||
if (valueSeed->ValueType == REG_DWORD) {
|
||
|
||
if ((valueSeed->Options == OPTIONS_INSERT_PHANTOM_MARKER) &&
|
||
!DeviceIsPhantom) {
|
||
|
||
//
|
||
// Device isn't a phantom--we don't want to mark it as such.
|
||
//
|
||
|
||
continue;
|
||
}
|
||
|
||
size = sizeof(ULONG);
|
||
RtlCopyMemory(buffer, &valueSeed->DwordValueContent, size);
|
||
|
||
} else if (valueSeed->Options == OPTIONS_INSERT_PNP_ID) {
|
||
|
||
size = (ULONG)((wcslen(pnpid) + 2) * sizeof(WCHAR)); // eos multi_sz
|
||
if (FirmwareEntry->BusType == Eisa) {
|
||
|
||
//
|
||
// need a mult_sz of EISA\PNPblah *PNPblah
|
||
//
|
||
|
||
RtlZeroMemory(buffer, SEED_BUFFER_SIZE);
|
||
wcptr = (PWCHAR)pnpid;
|
||
wcptr++;
|
||
swprintf(buffer, L"EISA\\%s", wcptr);
|
||
|
||
wcptr = buffer;
|
||
while (*wcptr) {
|
||
wcptr++;
|
||
}
|
||
wcptr++; // step past eos for 1st string
|
||
|
||
RtlCopyMemory(wcptr, pnpid, size);
|
||
|
||
size += (ULONG)((PUCHAR)wcptr - (PUCHAR)buffer);
|
||
} else {
|
||
RtlCopyMemory(buffer, pnpid, size - sizeof(WCHAR));
|
||
buffer[size / sizeof(WCHAR) - 1] = L'\0';
|
||
}
|
||
} else if (valueSeed->Options == OPTIONS_INSERT_COMPATIBLE_IDS) {
|
||
if (FirmwareEntry->PeripheralType == KeyboardPeripheral) {
|
||
size = sizeof(PS2_KEYBOARD_COMPATIBLE_ID);
|
||
RtlCopyMemory(buffer, PS2_KEYBOARD_COMPATIBLE_ID, size);
|
||
} else if (FirmwareEntry->PeripheralType == PointerPeripheral &&
|
||
(wcscmp(pnpid, L"*PNP0F0E") == 0 ||
|
||
wcscmp(pnpid, L"*PNP0F03") == 0 ||
|
||
wcscmp(pnpid, L"*PNP0F12") == 0)) {
|
||
size = sizeof(PS2_MOUSE_COMPATIBLE_ID);
|
||
RtlCopyMemory(buffer, PS2_MOUSE_COMPATIBLE_ID, size);
|
||
} else {
|
||
continue;
|
||
}
|
||
buffer[size / 2] = L'\0'; // 2nd NUL for MULTI_SZ
|
||
size += sizeof(L'\0');
|
||
} else if (valueSeed->Options == OPTIONS_INSERT_DEVICEDESC) {
|
||
size = FirmwareEntry->IdentifierLength;
|
||
RtlCopyMemory(buffer, FirmwareEntry->Identifier, size);
|
||
} else {
|
||
IopDbgPrint((IOP_MAPPER_ERROR_LEVEL, "Mapper: NO VALUE TYPE!\n"));
|
||
ASSERT(FALSE);
|
||
continue;
|
||
}
|
||
|
||
RtlInitUnicodeString(&unicodeName,
|
||
valueSeed->ValueName);
|
||
ZwSetValueKey(Handle,
|
||
&unicodeName,
|
||
0,
|
||
valueSeed->ValueType,
|
||
buffer,
|
||
size);
|
||
}
|
||
ExFreePool(buffer);
|
||
}
|
||
|
||
|
||
VOID
|
||
MapperFreeList(
|
||
VOID
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine walks through the list of firmware entries
|
||
and frees all allocated memory.
|
||
|
||
Arguments:
|
||
|
||
None
|
||
|
||
Return Value:
|
||
|
||
None
|
||
|
||
--*/
|
||
|
||
{
|
||
PDEVICE_EXTENSION deviceExtension = &MapperDeviceExtension;
|
||
PFIRMWARE_CONFIGURATION tempEntry;
|
||
PFIRMWARE_CONFIGURATION firmwareEntry;
|
||
|
||
firmwareEntry = deviceExtension->FirmwareList;
|
||
while (firmwareEntry) {
|
||
|
||
//
|
||
// free allocated structures associated with the firmware entry
|
||
//
|
||
|
||
if (firmwareEntry->ResourceDescriptor) {
|
||
ExFreePool(firmwareEntry->ResourceDescriptor);
|
||
}
|
||
if (firmwareEntry->Identifier) {
|
||
ExFreePool(firmwareEntry->Identifier);
|
||
}
|
||
|
||
//
|
||
// free this entry and move to the next
|
||
//
|
||
|
||
tempEntry = firmwareEntry->Next;
|
||
ExFreePool(firmwareEntry);
|
||
firmwareEntry = tempEntry;
|
||
}
|
||
}
|
||
|
||
VOID
|
||
MapperConstructRootEnumTree(
|
||
IN BOOLEAN CreatePhantomDevices
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine walks through the list of firmware entries
|
||
in the device extension and migrates the information into
|
||
the root enumerator's tree in the registry.
|
||
|
||
Arguments:
|
||
|
||
CreatePhantomDevices - If non-zero, then the device instances are created
|
||
as "phantoms" (i.e., they are marked with the "Phantom" value entry so
|
||
that the root enumerator will ignore them). The only time these device
|
||
instance registry keys will ever turn into real live devnodes is if the
|
||
class installer (in response to DIF_FIRSTTIMESETUP or DIF_DETECT)
|
||
decides that these devices aren't duplicates of any PnP-enumerated
|
||
devnodes, and subsequently registers and installs them.
|
||
|
||
Return Value:
|
||
|
||
None
|
||
|
||
--*/
|
||
|
||
{
|
||
#define ENUM_KEY_BUFFER_SIZE (1024 * sizeof(WCHAR))
|
||
#define INSTANCE_BUFFER_SIZE (256 * sizeof(WCHAR))
|
||
UNICODE_STRING enumKey;
|
||
PFIRMWARE_CONFIGURATION firmwareEntry;
|
||
OBJECT_ATTRIBUTES objectAttributes;
|
||
NTSTATUS status;
|
||
BOOLEAN keyPresent;
|
||
PWCHAR registryBase;
|
||
PWCHAR instanceBuffer;
|
||
HANDLE handle;
|
||
ULONG disposition;
|
||
PVOID buffer;
|
||
PDEVICE_EXTENSION DeviceExtension = &MapperDeviceExtension;
|
||
|
||
PAGED_CODE();
|
||
|
||
//
|
||
// allocate space needed for the registry path into the root
|
||
// enumerator tree. Note, limited size on path length.
|
||
//
|
||
|
||
buffer = ExAllocatePool(NonPagedPool, ENUM_KEY_BUFFER_SIZE);
|
||
|
||
if (!buffer) {
|
||
MapperFreeList();
|
||
IopDbgPrint((IOP_MAPPER_ERROR_LEVEL,
|
||
"Mapper: could not allocate memory for registry update\n"));
|
||
return;
|
||
}
|
||
|
||
instanceBuffer = ExAllocatePool(NonPagedPool, INSTANCE_BUFFER_SIZE);
|
||
if (!instanceBuffer) {
|
||
MapperFreeList();
|
||
ExFreePool(buffer);
|
||
IopDbgPrint((IOP_MAPPER_ERROR_LEVEL,
|
||
"Mapper: could not allocate memory for instance buffer\n"));
|
||
return;
|
||
}
|
||
|
||
InitializeObjectAttributes(&objectAttributes,
|
||
&enumKey,
|
||
OBJ_CASE_INSENSITIVE,
|
||
NULL,
|
||
NULL);
|
||
|
||
#if UMODETEST
|
||
registryBase = L"\\Registry\\Machine\\System\\TestControlSet\\Enum\\Root\\";
|
||
#else
|
||
registryBase = L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\Root\\";
|
||
#endif
|
||
|
||
firmwareEntry = DeviceExtension->FirmwareList;
|
||
while (firmwareEntry) {
|
||
|
||
//
|
||
// Construct the base for the path for this entry.
|
||
//
|
||
|
||
|
||
PiWstrToUnicodeString(&enumKey, NULL);
|
||
enumKey.MaximumLength = ENUM_KEY_BUFFER_SIZE;
|
||
enumKey.Buffer = buffer;
|
||
RtlZeroMemory(buffer, ENUM_KEY_BUFFER_SIZE);
|
||
RtlAppendUnicodeToString(&enumKey, registryBase);
|
||
RtlAppendUnicodeToString(&enumKey, firmwareEntry->PnPId);
|
||
|
||
//
|
||
// Build the pnp Key.
|
||
//
|
||
|
||
status = ZwCreateKey(&handle,
|
||
KEY_READ | KEY_WRITE,
|
||
&objectAttributes,
|
||
0,
|
||
NULL,
|
||
REG_OPTION_NON_VOLATILE,
|
||
&disposition);
|
||
|
||
if (NT_SUCCESS(status)) {
|
||
|
||
//
|
||
// Do not need the handle, so close it
|
||
// Remember if the key was present prior to call
|
||
//
|
||
|
||
ZwClose(handle);
|
||
keyPresent = (disposition == REG_OPENED_EXISTING_KEY) ? TRUE : FALSE;
|
||
IopDbgPrint((IOP_MAPPER_INFO_LEVEL,
|
||
"Mapper: Key was %s\n",
|
||
keyPresent ? "Present" : "Created"));
|
||
|
||
//
|
||
// Construct the instance name.
|
||
//
|
||
|
||
RtlZeroMemory(instanceBuffer, INSTANCE_BUFFER_SIZE);
|
||
swprintf(instanceBuffer,
|
||
L"\\%d_%d_%d_%d_%d_%d",
|
||
firmwareEntry->BusType,
|
||
firmwareEntry->BusNumber,
|
||
firmwareEntry->ControllerType,
|
||
firmwareEntry->ControllerNumber,
|
||
firmwareEntry->PeripheralType,
|
||
firmwareEntry->PeripheralNumber);
|
||
RtlAppendUnicodeToString(&enumKey, instanceBuffer);
|
||
|
||
status = ZwCreateKey(&handle,
|
||
KEY_READ | KEY_WRITE,
|
||
&objectAttributes,
|
||
0,
|
||
NULL,
|
||
REG_OPTION_NON_VOLATILE,
|
||
&disposition);
|
||
|
||
if (NT_SUCCESS(status)) {
|
||
|
||
if (firmwareEntry->ResourceDescriptor) {
|
||
IopDbgPrint((IOP_MAPPER_INFO_LEVEL,
|
||
"Mapper: firmware entry has resources %x\n",
|
||
firmwareEntry->ResourceDescriptor));
|
||
}
|
||
|
||
if (firmwareEntry->Identifier) {
|
||
IopDbgPrint((IOP_MAPPER_INFO_LEVEL,
|
||
"Mapper: firmware entry has identifier %x\n",
|
||
firmwareEntry->Identifier));
|
||
}
|
||
|
||
//
|
||
// If the key already exists because it was explicitly migrated
|
||
// during textmode setup, we should still consider it a "new key".
|
||
//
|
||
if (disposition != REG_CREATED_NEW_KEY) {
|
||
PKEY_VALUE_FULL_INFORMATION keyValueInformation;
|
||
UNICODE_STRING unicodeString;
|
||
|
||
status = IopGetRegistryValue(handle,
|
||
REGSTR_VALUE_MIGRATED,
|
||
&keyValueInformation);
|
||
if (NT_SUCCESS(status)) {
|
||
|
||
if ((keyValueInformation->Type == REG_DWORD) &&
|
||
(keyValueInformation->DataLength == sizeof(ULONG)) &&
|
||
((*(PULONG)KEY_VALUE_DATA(keyValueInformation)) != 0)) {
|
||
disposition = REG_CREATED_NEW_KEY;
|
||
}
|
||
|
||
ExFreePool(keyValueInformation);
|
||
|
||
PiWstrToUnicodeString(&unicodeString, REGSTR_VALUE_MIGRATED);
|
||
ZwDeleteValueKey(handle, &unicodeString);
|
||
}
|
||
}
|
||
|
||
//
|
||
// Only if this is a new entry do we see the key.
|
||
//
|
||
|
||
if (disposition == REG_CREATED_NEW_KEY) {
|
||
|
||
//
|
||
// Remember the fact that the key was newly-created for the
|
||
// PnP BIOS case where we need to come along and "phantomize"
|
||
// all newly-created ntdetect COM ports.
|
||
//
|
||
|
||
firmwareEntry->NewlyCreated = TRUE;
|
||
|
||
//
|
||
// Create enough information to get pnp to
|
||
// install drivers
|
||
//
|
||
|
||
MapperSeedKey(handle,
|
||
&enumKey,
|
||
firmwareEntry,
|
||
CreatePhantomDevices
|
||
);
|
||
}
|
||
MapperMarkKey(handle,
|
||
&enumKey,
|
||
firmwareEntry);
|
||
ZwClose(handle);
|
||
|
||
} else {
|
||
IopDbgPrint((IOP_MAPPER_ERROR_LEVEL,
|
||
"Mapper: create of instance key failed %x\n",
|
||
status));
|
||
}
|
||
|
||
} else {
|
||
IopDbgPrint((IOP_MAPPER_ERROR_LEVEL,
|
||
"Mapper: create pnp key failed %x\n",
|
||
status));
|
||
}
|
||
|
||
firmwareEntry = firmwareEntry->Next;
|
||
}
|
||
ExFreePool(instanceBuffer);
|
||
}
|
||
|
||
PCM_RESOURCE_LIST
|
||
MapperAdjustResourceList (
|
||
IN PCM_RESOURCE_LIST ResourceList,
|
||
IN WCHAR const* PnPId,
|
||
IN OUT PULONG Size
|
||
)
|
||
{
|
||
PCM_PARTIAL_RESOURCE_LIST partialResourceList;
|
||
PCM_PARTIAL_RESOURCE_DESCRIPTOR problemPartialDescriptors;
|
||
PCM_PARTIAL_RESOURCE_DESCRIPTOR partialDescriptors;
|
||
PCM_RESOURCE_LIST newResourceList;
|
||
ULONG i;
|
||
|
||
newResourceList = ResourceList;
|
||
|
||
#if _X86_
|
||
if (KeI386MachineType == MACHINE_TYPE_EISA) {
|
||
|
||
PCM_FULL_RESOURCE_DESCRIPTOR fullDescriptor;
|
||
PCM_PARTIAL_RESOURCE_DESCRIPTOR partialDescriptor;
|
||
PUCHAR nextDescriptor;
|
||
ULONG j;
|
||
ULONG lastResourceIndex;
|
||
|
||
fullDescriptor = &ResourceList->List[0];
|
||
|
||
for (i = 0; i < ResourceList->Count; i++) {
|
||
|
||
partialResourceList = &fullDescriptor->PartialResourceList;
|
||
|
||
for (j = 0; j < partialResourceList->Count; j++) {
|
||
partialDescriptor = &partialResourceList->PartialDescriptors[j];
|
||
|
||
if (partialDescriptor->Type == CmResourceTypePort) {
|
||
if (partialDescriptor->u.Port.Start.HighPart == 0 &&
|
||
(partialDescriptor->u.Port.Start.LowPart & 0x00000300) == 0) {
|
||
partialDescriptor->Flags |= CM_RESOURCE_PORT_16_BIT_DECODE;
|
||
}
|
||
}
|
||
}
|
||
|
||
nextDescriptor = (PUCHAR)fullDescriptor + sizeof(CM_FULL_RESOURCE_DESCRIPTOR);
|
||
|
||
//
|
||
// account for any resource descriptors in addition to the single
|
||
// imbedded one I've already accounted for (if there aren't any,
|
||
// then I'll end up subtracting off the extra imbedded descriptor
|
||
// from the previous step)
|
||
//
|
||
//
|
||
// finally, account for any extra device specific data at the end of
|
||
// the last partial resource descriptor (if any)
|
||
//
|
||
if (partialResourceList->Count > 0) {
|
||
|
||
nextDescriptor += (partialResourceList->Count - 1) *
|
||
sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
|
||
|
||
lastResourceIndex = partialResourceList->Count - 1;
|
||
|
||
if (partialResourceList->PartialDescriptors[lastResourceIndex].Type ==
|
||
CmResourceTypeDeviceSpecific) {
|
||
|
||
nextDescriptor += partialResourceList->PartialDescriptors[lastResourceIndex].
|
||
u.DeviceSpecificData.DataSize;
|
||
}
|
||
}
|
||
|
||
fullDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)nextDescriptor;
|
||
}
|
||
}
|
||
#endif
|
||
|
||
if (wcscmp(PnPId, FloppyId) == 0) {
|
||
|
||
if (ResourceList->Count == 1) {
|
||
|
||
partialResourceList = &ResourceList->List->PartialResourceList;
|
||
|
||
partialDescriptors = partialResourceList->PartialDescriptors;
|
||
|
||
//
|
||
// Look for the one and only one 8 byte port resource
|
||
//
|
||
problemPartialDescriptors = NULL;
|
||
for (i=0; i<partialResourceList->Count; i++) {
|
||
|
||
if ((partialDescriptors[i].Type == CmResourceTypePort) &&
|
||
(partialDescriptors[i].u.Port.Length == 8)) {
|
||
|
||
if (problemPartialDescriptors == NULL) {
|
||
|
||
problemPartialDescriptors = partialDescriptors + i;
|
||
} else {
|
||
|
||
problemPartialDescriptors = NULL;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (problemPartialDescriptors) {
|
||
|
||
problemPartialDescriptors->u.Port.Length = 6;
|
||
|
||
newResourceList = ExAllocatePool (
|
||
NonPagedPool,
|
||
*Size + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR)
|
||
);
|
||
if (newResourceList) {
|
||
|
||
RtlCopyMemory (
|
||
newResourceList,
|
||
ResourceList,
|
||
*Size
|
||
);
|
||
|
||
//
|
||
// pick out the new partial resource descriptor
|
||
//
|
||
partialDescriptors = newResourceList->List->
|
||
PartialResourceList.PartialDescriptors;
|
||
partialDescriptors += newResourceList->List->PartialResourceList.Count;
|
||
|
||
RtlCopyMemory (
|
||
partialDescriptors,
|
||
problemPartialDescriptors,
|
||
sizeof(*partialDescriptors)
|
||
);
|
||
|
||
partialDescriptors->u.Port.Start.QuadPart += 7;
|
||
partialDescriptors->u.Port.Length = 1;
|
||
|
||
//
|
||
// we got one more now
|
||
//
|
||
newResourceList->List->PartialResourceList.Count++;
|
||
*Size += sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
|
||
|
||
ExFreePool (ResourceList);
|
||
|
||
} else {
|
||
|
||
newResourceList = ResourceList;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
return newResourceList;
|
||
}
|
||
|
||
NTSTATUS
|
||
ComPortDBAdd(
|
||
IN HANDLE DeviceParamKey,
|
||
IN PWSTR PortName
|
||
)
|
||
{
|
||
UNICODE_STRING portNameString;
|
||
UNICODE_STRING portPrefixString;
|
||
UNICODE_STRING comDBName;
|
||
UNICODE_STRING valueName;
|
||
PKEY_VALUE_PARTIAL_INFORMATION valueInfo;
|
||
ULONG valueInfoLength;
|
||
ULONG returnedLength;
|
||
HANDLE comDBKey;
|
||
ULONG portNo;
|
||
NTSTATUS status;
|
||
|
||
RtlInitUnicodeString(&portNameString, PortName);
|
||
|
||
if (portNameString.Length > 3 * sizeof(WCHAR)) {
|
||
portNameString.Length = 3 * sizeof(WCHAR);
|
||
}
|
||
|
||
PiWstrToUnicodeString(&portPrefixString, L"COM");
|
||
|
||
if (RtlCompareUnicodeString(&portNameString, &portPrefixString, TRUE) == 0) {
|
||
portNo = _wtol(&PortName[3]);
|
||
|
||
if (portNo > 0 && portNo <= 256) {
|
||
|
||
#if UMODETEST
|
||
PiWstrToUnicodeString(&comDBName, L"\\Registry\\Machine\\System\\TestControlSet\\Control\\COM Name Arbiter");
|
||
#else
|
||
PiWstrToUnicodeString(&comDBName, L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\COM Name Arbiter");
|
||
#endif
|
||
|
||
status = IopCreateRegistryKeyEx( &comDBKey,
|
||
NULL,
|
||
&comDBName,
|
||
KEY_ALL_ACCESS,
|
||
REG_OPTION_NON_VOLATILE,
|
||
NULL
|
||
);
|
||
|
||
if (NT_SUCCESS(status)) {
|
||
|
||
PiWstrToUnicodeString(&valueName, L"ComDB Merge");
|
||
|
||
#define COMPORT_DB_MERGE_SIZE 32 // 256 / 8
|
||
|
||
valueInfoLength = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + COMPORT_DB_MERGE_SIZE;
|
||
valueInfo = ExAllocatePool(PagedPool, valueInfoLength);
|
||
|
||
if (valueInfo != NULL) {
|
||
|
||
status = ZwQueryValueKey( comDBKey,
|
||
&valueName,
|
||
KeyValuePartialInformation,
|
||
valueInfo,
|
||
valueInfoLength,
|
||
&returnedLength);
|
||
|
||
if (status == STATUS_OBJECT_NAME_NOT_FOUND) {
|
||
|
||
valueInfo->Type = REG_BINARY;
|
||
valueInfo->DataLength = COMPORT_DB_MERGE_SIZE;
|
||
RtlZeroMemory(valueInfo->Data, valueInfo->DataLength);
|
||
status = STATUS_SUCCESS;
|
||
}
|
||
|
||
if (NT_SUCCESS(status)) {
|
||
portNo--;
|
||
valueInfo->Data[ portNo / 8 ] |= 1 << (portNo % 8);
|
||
|
||
status = ZwSetValueKey( comDBKey,
|
||
&valueName,
|
||
0,
|
||
valueInfo->Type,
|
||
valueInfo->Data,
|
||
valueInfo->DataLength );
|
||
|
||
ASSERT(NT_SUCCESS(status));
|
||
}
|
||
|
||
ExFreePool(valueInfo);
|
||
}
|
||
|
||
ZwClose(comDBKey);
|
||
}
|
||
}
|
||
}
|
||
|
||
PiWstrToUnicodeString( &valueName, L"DosDeviceName" );
|
||
|
||
status = ZwSetValueKey( DeviceParamKey,
|
||
&valueName,
|
||
0,
|
||
REG_SZ,
|
||
PortName,
|
||
(ULONG)((wcslen(PortName) + 1) * sizeof(WCHAR)) );
|
||
|
||
return status;
|
||
}
|
||
|
||
|
||
VOID
|
||
MapperPhantomizeDetectedComPorts (
|
||
VOID
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine turns all newly-created firmware/ntdetect COM ports into
|
||
phantoms.
|
||
|
||
Arguments:
|
||
|
||
None
|
||
|
||
Return Value:
|
||
|
||
None
|
||
|
||
--*/
|
||
{
|
||
PFIRMWARE_CONFIGURATION firmwareEntry;
|
||
NTSTATUS status;
|
||
PWCHAR registryBase;
|
||
PWCHAR instanceBuffer;
|
||
HANDLE handle;
|
||
PWCHAR buffer;
|
||
PDEVICE_EXTENSION DeviceExtension = &MapperDeviceExtension;
|
||
UNICODE_STRING enumKey;
|
||
OBJECT_ATTRIBUTES objectAttributes;
|
||
UNICODE_STRING unicodeName;
|
||
ULONG regValue;
|
||
|
||
//
|
||
// allocate space needed for the registry path into the root
|
||
// enumerator tree. Note, limited size on path length.
|
||
//
|
||
|
||
buffer = ExAllocatePool(NonPagedPool, ENUM_KEY_BUFFER_SIZE);
|
||
|
||
if (!buffer) {
|
||
IopDbgPrint((IOP_MAPPER_ERROR_LEVEL,
|
||
"Mapper: could not allocate memory for registry update\n"));
|
||
return;
|
||
}
|
||
|
||
instanceBuffer = ExAllocatePool(NonPagedPool, INSTANCE_BUFFER_SIZE);
|
||
if (!instanceBuffer) {
|
||
ExFreePool(buffer);
|
||
IopDbgPrint((IOP_MAPPER_ERROR_LEVEL,
|
||
"Mapper: could not allocate memory for instance buffer\n"));
|
||
return;
|
||
}
|
||
|
||
InitializeObjectAttributes(&objectAttributes,
|
||
&enumKey,
|
||
OBJ_CASE_INSENSITIVE,
|
||
NULL,
|
||
NULL);
|
||
|
||
#if UMODETEST
|
||
registryBase = L"\\Registry\\Machine\\System\\TestControlSet\\Enum\\Root\\";
|
||
#else
|
||
registryBase = L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\Root\\";
|
||
#endif
|
||
|
||
firmwareEntry = DeviceExtension->FirmwareList;
|
||
while (firmwareEntry) {
|
||
|
||
//
|
||
// Construct the base for the path for this entry.
|
||
//
|
||
|
||
|
||
if ((firmwareEntry->ControllerType == SerialController) &&
|
||
firmwareEntry->NewlyCreated) {
|
||
|
||
PiWstrToUnicodeString(&enumKey, NULL);
|
||
enumKey.MaximumLength = ENUM_KEY_BUFFER_SIZE;
|
||
enumKey.Buffer = buffer;
|
||
RtlZeroMemory(buffer, ENUM_KEY_BUFFER_SIZE);
|
||
RtlAppendUnicodeToString(&enumKey, registryBase);
|
||
RtlAppendUnicodeToString(&enumKey, firmwareEntry->PnPId);
|
||
|
||
//
|
||
// Construct the instance name.
|
||
//
|
||
|
||
RtlZeroMemory(instanceBuffer, INSTANCE_BUFFER_SIZE);
|
||
swprintf(instanceBuffer,
|
||
L"\\%d_%d_%d_%d_%d_%d",
|
||
firmwareEntry->BusType,
|
||
firmwareEntry->BusNumber,
|
||
firmwareEntry->ControllerType,
|
||
firmwareEntry->ControllerNumber,
|
||
firmwareEntry->PeripheralType,
|
||
firmwareEntry->PeripheralNumber);
|
||
RtlAppendUnicodeToString(&enumKey, instanceBuffer);
|
||
|
||
status = ZwOpenKey(&handle,
|
||
KEY_READ | KEY_WRITE,
|
||
&objectAttributes
|
||
);
|
||
|
||
if (NT_SUCCESS(status)) {
|
||
|
||
PiWstrToUnicodeString(&unicodeName, REGSTR_VAL_PHANTOM);
|
||
regValue = 1;
|
||
ZwSetValueKey(handle,
|
||
&unicodeName,
|
||
0,
|
||
REG_DWORD,
|
||
®Value,
|
||
sizeof(regValue)
|
||
);
|
||
|
||
ZwClose(handle);
|
||
}
|
||
}
|
||
|
||
firmwareEntry = firmwareEntry->Next;
|
||
}
|
||
|
||
ExFreePool (buffer);
|
||
ExFreePool (instanceBuffer);
|
||
}
|