📄 legacy.c
字号:
parameters[0].Flags = RTL_QUERY_REGISTRY_SUBKEY;
parameters[1].Flags = RTL_QUERY_REGISTRY_DIRECT;
parameters[1].Name = L"PortAddress";
parameters[1].EntryContext = &userData.UserPort.LowPart;
parameters[1].DefaultType = REG_DWORD;
parameters[1].DefaultData = &zero;
parameters[1].DefaultLength = sizeof(ULONG);
parameters[2].Flags = RTL_QUERY_REGISTRY_DIRECT;
parameters[2].Name = L"Interrupt";
parameters[2].EntryContext = &userData.UserVector;
parameters[2].DefaultType = REG_DWORD;
parameters[2].DefaultData = &zero;
parameters[2].DefaultLength = sizeof(ULONG);
parameters[3].Flags = RTL_QUERY_REGISTRY_DIRECT;
parameters[3].Name = DEFAULT_DIRECTORY;
parameters[3].EntryContext = &userData.UserSymbolicLink;
parameters[3].DefaultType = REG_SZ;
parameters[3].DefaultData = L"";
parameters[3].DefaultLength = 0;
parameters[4].Flags = RTL_QUERY_REGISTRY_DIRECT;
parameters[4].Name = L"InterruptStatus";
parameters[4].EntryContext = &userData.UserInterruptStatus.LowPart;
parameters[4].DefaultType = REG_DWORD;
parameters[4].DefaultData = &zero;
parameters[4].DefaultLength = sizeof(ULONG);
parameters[5].Flags = RTL_QUERY_REGISTRY_DIRECT;
parameters[5].Name = L"PortIndex";
parameters[5].EntryContext = &userData.UserPortIndex;
parameters[5].DefaultType = REG_DWORD;
parameters[5].DefaultData = &zero;
parameters[5].DefaultLength = sizeof(ULONG);
parameters[6].Flags = RTL_QUERY_REGISTRY_DIRECT;
parameters[6].Name = L"BusNumber";
parameters[6].EntryContext = &userData.UserBusNumber;
parameters[6].DefaultType = REG_DWORD;
parameters[6].DefaultData = &zero;
parameters[6].DefaultLength = sizeof(ULONG);
parameters[7].Flags = RTL_QUERY_REGISTRY_DIRECT;
parameters[7].Name = L"BusType";
parameters[7].EntryContext = &userData.UserInterfaceType;
parameters[7].DefaultType = REG_DWORD;
parameters[7].DefaultData = &defaultInterfaceType;
parameters[7].DefaultLength = sizeof(ULONG);
parameters[8].Flags = RTL_QUERY_REGISTRY_DIRECT;
parameters[8].Name = L"ClockRate";
parameters[8].EntryContext = &userData.UserClockRate;
parameters[8].DefaultType = REG_DWORD;
parameters[8].DefaultData = &badValue;
parameters[8].DefaultLength = sizeof(ULONG);
parameters[9].Flags = RTL_QUERY_REGISTRY_DIRECT;
parameters[9].Name = L"Indexed";
parameters[9].EntryContext = &userData.UserIndexed;
parameters[9].DefaultType = REG_DWORD;
parameters[9].DefaultData = &badValue;
parameters[9].DefaultLength = sizeof(ULONG);
parameters[10].Flags = RTL_QUERY_REGISTRY_DIRECT;
parameters[10].Name = L"InterruptMode";
parameters[10].EntryContext = &userData.UserInterruptMode;
parameters[10].DefaultType = REG_DWORD;
parameters[10].DefaultData = &defaultInterruptMode;
parameters[10].DefaultLength = sizeof(ULONG);
parameters[11].Flags = RTL_QUERY_REGISTRY_DIRECT;
parameters[11].Name = L"AddressSpace";
parameters[11].EntryContext = &userData.UserAddressSpace;
parameters[11].DefaultType = REG_DWORD;
parameters[11].DefaultData = &defaultAddressSpace;
parameters[11].DefaultLength = sizeof(ULONG);
parameters[12].Flags = RTL_QUERY_REGISTRY_DIRECT;
parameters[12].Name = L"InterruptLevel";
parameters[12].EntryContext = &userData.UserLevel;
parameters[12].DefaultType = REG_DWORD;
parameters[12].DefaultData = &zero;
parameters[12].DefaultLength = sizeof(ULONG);
parameters[13].Flags = RTL_QUERY_REGISTRY_DIRECT;
parameters[13].Name = L"DisablePort";
parameters[13].EntryContext = &userData.DisablePort;
parameters[13].DefaultType = REG_DWORD;
parameters[13].DefaultData = &badValue;
parameters[13].DefaultLength = sizeof(ULONG);
parameters[14].Flags = RTL_QUERY_REGISTRY_DIRECT;
parameters[14].Name = L"ForceFifoEnable";
parameters[14].EntryContext = &userData.ForceFIFOEnable;
parameters[14].DefaultType = REG_DWORD;
parameters[14].DefaultData = &badValue;
parameters[14].DefaultLength = sizeof(ULONG);
parameters[15].Flags = RTL_QUERY_REGISTRY_DIRECT;
parameters[15].Name = L"RxFIFO";
parameters[15].EntryContext = &userData.RxFIFO;
parameters[15].DefaultType = REG_DWORD;
parameters[15].DefaultData = &badValue;
parameters[15].DefaultLength = sizeof(ULONG);
parameters[16].Flags = RTL_QUERY_REGISTRY_DIRECT;
parameters[16].Name = L"TxFIFO";
parameters[16].EntryContext = &userData.TxFIFO;
parameters[16].DefaultType = REG_DWORD;
parameters[16].DefaultData = &badValue;
parameters[16].DefaultLength = sizeof(ULONG);
parameters[17].Flags = RTL_QUERY_REGISTRY_DIRECT;
parameters[17].Name = L"MaskInverted";
parameters[17].EntryContext = &userData.MaskInverted;
parameters[17].DefaultType = REG_DWORD;
parameters[17].DefaultData = &zero;
parameters[17].DefaultLength = sizeof(ULONG);
parameters[18].Flags = RTL_QUERY_REGISTRY_DIRECT;
parameters[18].Name = L"PnPDeviceID";
parameters[18].EntryContext = &PnPID;
parameters[18].DefaultType = REG_SZ;
parameters[18].DefaultData = L"";
parameters[18].DefaultLength = 0;
parameters[19].Flags = RTL_QUERY_REGISTRY_DIRECT;
parameters[19].Name = L"LegacyDiscovered";
parameters[19].EntryContext = &legacyDiscovered;
parameters[19].DefaultType = REG_DWORD;
parameters[19].DefaultData = &zero;
parameters[19].DefaultLength = sizeof(ULONG);
//
// This is for a buggy Digi serial.ini that worked with pre-NT5.0
// by accident. DO NOT USE "Interrupt Status" in the future; its
// use is deprecated. Use the correct "InterruptStatus"
//
parameters[20].Flags = RTL_QUERY_REGISTRY_DIRECT;
parameters[20].Name = L"Interrupt Status";
parameters[20].EntryContext = &brokenStatus;
parameters[20].DefaultType = REG_DWORD;
parameters[20].DefaultData = &zero;
parameters[20].DefaultLength = sizeof(ULONG);
i = 0;
while (TRUE) {
NTSTATUS status;
ULONG actuallyReturned;
PDEVICE_OBJECT newDevObj = NULL;
PSERIAL_DEVICE_EXTENSION deviceExtension;
PDEVICE_OBJECT lowerDevice;
//
// We lie about the length of the buffer, so that we can
// MAKE SURE that the name it returns can be padded with
// a NULL.
//
status = ZwEnumerateKey(
parametersKey,
i,
KeyBasicInformation,
userSubKey,
sizeof(KEY_BASIC_INFORMATION)+(sizeof(WCHAR)*255),
&actuallyReturned
);
if (status == STATUS_NO_MORE_ENTRIES) {
break;
}
if (status == STATUS_BUFFER_OVERFLOW) {
SerialLogError(
DriverObject,
NULL,
SerialPhysicalZero,
SerialPhysicalZero,
0,
0,
0,
84,
STATUS_SUCCESS,
SERIAL_UNABLE_TO_ACCESS_CONFIG,
0,
NULL,
0,
NULL
);
SerialDbgPrintEx(SERERRORS, "Overflowed the enumerate buffer\n"
"for subkey #%d of %wZ\n", i,parametersPath);
i++;
continue;
}
if (!NT_SUCCESS(status)) {
SerialLogError(
DriverObject,
NULL,
SerialPhysicalZero,
SerialPhysicalZero,
0,
0,
0,
85,
STATUS_SUCCESS,
SERIAL_UNABLE_TO_ACCESS_CONFIG,
0,
NULL,
0,
NULL
);
SerialDbgPrintEx(SERERRORS, "Bad status returned: %x \n"
"on enumeration for subkey # %d of %wZ\n", status, i,
parametersPath);
i++;
continue;
}
//
// Pad the name returned with a null.
//
RtlZeroMemory(
((PUCHAR)(&userSubKey->Name[0]))+userSubKey->NameLength,
sizeof(WCHAR)
);
parameters[0].Name = &userSubKey->Name[0];
//
// Make sure that the physical addresses start
// out clean.
//
RtlZeroMemory(&userData.UserPort, sizeof(userData.UserPort));
RtlZeroMemory(&userData.UserInterruptStatus,
sizeof(userData.UserInterruptStatus));
//
// Make sure the symbolic link buffer starts clean
//
RtlZeroMemory(userData.UserSymbolicLink.Buffer,
userData.UserSymbolicLink.MaximumLength);
userData.UserSymbolicLink.Length = 0;
status = RtlQueryRegistryValues(
RTL_REGISTRY_ABSOLUTE,
parametersPath.Buffer,
parameters,
NULL,
NULL
);
if (!NT_SUCCESS(status)) {
SerialLogError(
DriverObject,
NULL,
SerialPhysicalZero,
SerialPhysicalZero,
0,
0,
0,
86,
STATUS_SUCCESS,
SERIAL_INVALID_USER_CONFIG,
userSubKey->NameLength+sizeof(WCHAR),
&userSubKey->Name[0],
0,
NULL
);
SerialDbgPrintEx(SERERRORS, "Bad status returned: %x \n"
"for the value entries of\n"
"%ws\n", status, parameters[0].Name);
i++;
continue;
}
//
// Well! Some supposedly valid information was found!
//
// We'll see about that.
//
//
// If this is PnP, skip it -- it will be found by an enumerator
//
if (PnPID.Length != 0) {
i++;
continue;
}
//
// If this was found on a previous boot, skip it -- PnP will send
// us an add_device()/start_device() for it.
//
if (legacyDiscovered != 0) {
i++;
continue;
}
//
// Let's just jam the WCHAR null at the end of the
// user symbolic link. Remember that we left room for
// one when we allocated it's buffer.
//
RtlZeroMemory(((PUCHAR)(&userData.UserSymbolicLink.Buffer[0]))
+ userData.UserSymbolicLink.Length, sizeof(WCHAR));
//
// See if this has a busted serial.ini and convert it over.
//
if (brokenStatus != 0) {
userData.UserInterruptStatus.LowPart = brokenStatus;
}
//
// Call a function to validate the data.
//
if (SerialIsUserDataValid(DriverObject, userSubKey, parameters,
defaultInterfaceType, &userData) == FALSE) {
i++;
continue;
}
//
// Well ok, I guess we can take the data.
// There be other tests later on to make
// sure it doesn't have any other kinds
// of conflicts.
//
//
// Report this device to the PnP Manager and create the device object
// Also update the registry entry for this device so we don't enumerate
// it next time.
//
//
// Build resource lists
//
status = SerialBuildResourceList(resourceList, &countOfPartials,
&userData);
if (!NT_SUCCESS(status)) {
i++;
continue;
}
ASSERT(countOfPartials >= 2);
status = SerialTranslateResourceList(DriverObject, userSubKey,
trResourceList, resourceList,
countOfPartials, &userData);
if (!NT_SUCCESS(status)) {
i++;
continue;
}
status = SerialBuildRequirementsList(pRequiredList, countOfPartials,
&userData);
if (!NT_SUCCESS(status)) {
i++;
continue;
}
newPdo = NULL;
//
// We want **untranslated** resources passed to this call
// since it calls IoReportResourceUsage() for us.
//
status = IoReportDetectedDevice(
DriverObject,
InterfaceTypeUndefined,
-1,
-1,
resourceList,
pRequiredList,
FALSE,
&newPdo
);
//
// If we fail, we can keep going but we need to see this device next
// time, so we won't write its discovery into the registry.
//
if (!NT_SUCCESS(status)) {
if (status == STATUS_INSUFFICIENT_RESOURCES) {
SerialLogError(DriverObject, NULL, userData.UserPort,
SerialPhysicalZero, 0, 0, 0, 89, status,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -