📄 pcibus.c
字号:
}
rc_Close_IKey:
RegCloseKey(IKey);
rc_Close_TKey:
RegCloseKey(TKey);
return RetVal;
}
//
// Copy contents of one registry key to another.
//
static BOOL
RegCopyKey(
HKEY TKey,
HKEY IKey
)
{
HKEY TSubKey;
HKEY ISubKey;
DWORD NumSubKeys;
DWORD MaxSubKeyLen;
DWORD MaxClassLen;
DWORD NumValues;
DWORD MaxValueNameLen;
DWORD MaxValueLen;
DWORD status;
DWORD Key;
DWORD Val;
WCHAR ValName[PCI_MAX_REG_NAME];
BYTE ValData[PCI_MAX_REG_DATA];
DWORD ValLen;
DWORD ValType;
DWORD Disposition;
BOOL RetVal = TRUE;
// Get info on Template Key
status = RegQueryInfoKey(
TKey,
NULL, // class name buffer (lpszClass)
NULL, // ptr to length of class name buffer (lpcchClass)
NULL, // reserved
&NumSubKeys, // ptr to number of sub-keys (lpcSubKeys)
&MaxSubKeyLen, // ptr to longest subkey name length (lpcchMaxSubKeyLen)
&MaxClassLen, // ptr to longest class string length (lpcchMaxClassLen)
&NumValues, // ptr to number of value entries (lpcValues)
&MaxValueNameLen, // ptr to longest value name length (lpcchMaxValueNameLen)
&MaxValueLen, // ptr to longest value data length (lpcbMaxValueData)
NULL, // ptr to security descriptor length
NULL); // ptr to last write time
if (status != ERROR_SUCCESS) {
DEBUGMSG(ZONE_ENUM|ZONE_ERROR,
(TEXT("PCIBUS!RegCopyKey RegQueryInfoKey returned %d.\r\n"),
status));
return FALSE;
}
// Recurse for each sub-key
for (Key = 0; Key < NumSubKeys; Key++) {
// Get TKey sub-key according to Key
ValLen = sizeof(ValName) / sizeof(WCHAR);
status = RegEnumKeyEx(
TKey,
Key,
ValName,
&ValLen,
NULL,
NULL,
NULL,
NULL);
if (status != ERROR_SUCCESS) {
DEBUGMSG(ZONE_ENUM,
(TEXT("PCIBUS!RegCopyKey RegEnumKeyEx(%d) returned %d\r\n"),
ValName, status));
break;
}
// Open sub-key under TKey
status = RegOpenKeyEx(
TKey,
ValName,
0,
0,
&TSubKey);
if (status != ERROR_SUCCESS) {
DEBUGMSG(ZONE_ENUM|ZONE_ERROR,
(TEXT("PCIBUS!RegCopyKey RegOpenKeyEx(%s) returned %d\r\n"),
ValName, status));
continue;
}
// Open/create corresponding sub-key under IKey
status = RegCreateKeyEx(
IKey,
ValName,
0,
NULL,
0,
0,
NULL,
&ISubKey,
&Disposition);
if (status != ERROR_SUCCESS) {
DEBUGMSG(ZONE_ENUM|ZONE_ERROR,
(TEXT("PCIBUS!RegCopyKey RegCreateKeyEx(%s) returned %d\r\n"),
ValName, status));
RegCloseKey(TSubKey);
continue;
}
RegCopyKey(TSubKey, ISubKey);
RegCloseKey(TSubKey);
RegCloseKey(ISubKey);
}
// Copy values
for (Val = 0; Val < NumValues; Val++) {
// Get value names under TKey according to Val
ValLen = sizeof(ValName) / sizeof(WCHAR);
status = RegEnumValue(
TKey,
Val,
ValName,
&ValLen,
NULL,
NULL,
NULL,
NULL);
if (status != ERROR_SUCCESS) {
DEBUGMSG(ZONE_ENUM,
(TEXT("PCIBUS!RegCopyKey RegEnumValue(%d) returned %d\r\n"),
Val, status));
break;
}
// If corresponding value under IKey already exists, skip
status = RegQueryValueEx(
IKey,
ValName,
NULL,
NULL,
NULL,
NULL);
if (status == ERROR_SUCCESS) {
// Value exists, don't overwrite
continue;
}
// Read value from TKey
ValLen = sizeof(ValData);
status = RegQueryValueEx(
TKey,
ValName,
NULL,
&ValType,
ValData,
&ValLen);
if (status != ERROR_SUCCESS) {
DEBUGMSG(ZONE_ENUM,
(TEXT("PCIBUS!RegCopyKey RegQueryValueEx(%s) returned %d\r\n"),
ValName, status));
break;
}
// Write value to IKey
status = RegSetValueEx(
IKey,
ValName,
0,
ValType,
ValData,
ValLen);
if (status != ERROR_SUCCESS) {
DEBUGMSG(ZONE_ENUM|ZONE_ERROR,
(TEXT("PCIBUS!RegCopyKey RegSetValueEx(%s) returned %d.\r\n"),
ValName, status));
break;
}
}
return RetVal;
}
//
// Set value in registry.
//
static BOOL
RegSetVal(
HKEY Key,
LPCWSTR ValName,
DWORD ValType,
const PBYTE ValData,
DWORD ValLen
)
{
DWORD Status;
DWORD dwData = 0;
// If Type is DWORD, pad ValData and write as DWORD
if (ValType == REG_DWORD) {
if (ValLen > sizeof(DWORD)) {
// ValLen too big to fit into DWORD
DEBUGMSG(ZONE_ENUM|ZONE_ERROR, (L"PCIBUS!RegSetVal ERROR: ValLen (%d) > %d when ValType == REG_DWORD\r\n", ValLen, sizeof(DWORD)));
return FALSE;
}
memcpy(&dwData, ValData, ValLen);
ValLen = sizeof(dwData);
Status = RegSetValueEx(Key, ValName, 0, ValType, (PBYTE)&dwData, ValLen);
} else {
Status = RegSetValueEx(Key, ValName, 0, ValType, ValData, ValLen);
}
if (Status != ERROR_SUCCESS) {
DEBUGMSG(ZONE_ENUM|ZONE_ERROR, (L"PCIBUS!RegSetVal RegSetValueEx(%s) returned %d.\r\n", ValName, Status));
return FALSE;
}
return TRUE;
}
//
// Set list of values in registry.
//
static BOOL
RegSetList(
HKEY Key,
LPCWSTR ValName,
DWORD Num,
DWORD List[]
)
{
WCHAR ValList[2*DEVKEY_LEN];
DWORD Status;
if (Num == 0) {
return TRUE;
} else if (Num == 1) {
Status = RegSetValueEx(Key, ValName, 0, REG_DWORD, (PBYTE)List, sizeof(List[0]));
} else {
DWORD i;
PWCHAR bp = ValList;
WCHAR Item[11]; // Largest number of characters produced by _ultow is 10 + termination character
DWORD ItemSize, Size = 0;
for (i = 0; i < Num; i++) {
_ultow(List[i], Item, 16);
ItemSize = wcslen(Item) + 1;
if (Size + ItemSize >= 2*DEVKEY_LEN) {
// List too big
return FALSE;
}
wcscpy(bp, Item);
bp += ItemSize;
Size += ItemSize;
}
*bp = (WCHAR)'\0';
Size++;
Status = RegSetValueEx(Key, ValName, 0, REG_MULTI_SZ, (PBYTE)ValList, Size * sizeof(WCHAR));
}
if (Status == ERROR_SUCCESS) {
return TRUE;
} else {
return FALSE;
}
}
//
// Read list of values from registry.
//
static BOOL
RegGetList(
HKEY Key,
LPCWSTR ValName,
PDWORD pNum,
DWORD List[]
)
{
WCHAR ValList[2*DEVKEY_LEN];
DWORD ValLen = sizeof(ValList);
DWORD ValType;
DWORD MaxItems = *pNum;
DWORD Status = RegQueryValueEx(Key, ValName, NULL, &ValType, (PBYTE)ValList, &ValLen);
*pNum = 0;
if (Status != ERROR_SUCCESS) {
return FALSE;
}
if (ValType == REG_MULTI_SZ) {
// Registry entry is multiple strings
DWORD i;
PWCHAR bp;
for (bp = ValList, i = 0; i < MaxItems; i++) {
PWCHAR ep;
if (*bp == (WCHAR)'\0') break;
List[i] = wcstoul(bp, &ep, 16);
if (bp == ep) break;
(*pNum)++;
bp = ++ep;
}
if ((i == MaxItems) && (*bp != (WCHAR)'\0')) {
// There are more strings in the registry entry than there are locations on the List
return FALSE;
}
} else if (ValType == REG_DWORD) {
// Registry entry is DWORD
List[0] = *(DWORD *)ValList;
*pNum = 1;
} else {
// Registry entry is some other type; ignore
return FALSE;
}
return TRUE;
}
//
// Request SysIntr value and set in registry.
//
static BOOL
RegSetConfig(
PPCI_DEV_INFO pInfo
)
{
HKEY Key;
DWORD Status;
BOOL RetVal = TRUE;
DWORD Irq, Pin;
DWORD SysIntr;
DEBUGMSG(ZONE_FUNCTION, (L"PCIBUS!RegSetConfig '%s' (%d/%d/%d)\r\n", pInfo->RegPath, pInfo->Bus, pInfo->Device, pInfo->Function));
// Open key
Status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, pInfo->RegPath, 0, 0, &Key);
if (Status != ERROR_SUCCESS) {
DEBUGMSG(ZONE_ENUM|ZONE_ERROR, (L"PCIBUS!RegSetConfig RegOpenKeyEx(%s) returned %d.\r\n", pInfo->RegPath, Status));
return FALSE;
}
// Set Memory Base and Length values
if (!RegSetList(Key, PCIBUS_MEMBASE_VALNAME, pInfo->MemBase.Num, pInfo->MemBase.Reg)) {
RetVal = FALSE;
goto RegSetConfig_Exit;
}
if (!RegSetList(Key, PCIBUS_MEMLEN_VALNAME, pInfo->MemLen.Num, pInfo->MemLen.Reg)) {
RetVal = FALSE;
goto RegSetConfig_Exit;
}
// Set I/O Base and Length values
if (!RegSetList(Key, PCIBUS_IOBASE_VALNAME, pInfo->IoBase.Num, pInfo->IoBase.Reg)) {
RetVal = FALSE;
goto RegSetConfig_Exit;
}
if (!RegSetList(Key, PCIBUS_IOLEN_VALNAME, pInfo->IoLen.Num, pInfo->IoLen.Reg)) {
RetVal = FALSE;
goto RegSetConfig_Exit;
}
// Get IRQ and interrupt pin
switch (pInfo->Cfg->HeaderType & ~PCI_MULTIFUNCTION) {
case PCI_DEVICE_TYPE: // Devices
Irq = pInfo->Cfg->u.type0.InterruptLine;
Pin = pInfo->Cfg->u.type0.InterruptPin;
break;
case PCI_BRIDGE_TYPE: // PCI-PCI bridge
Irq = pInfo->Cfg->u.type1.InterruptLine;
Pin = pInfo->Cfg->u.type1.InterruptPin;
break;
case PCI_CARDBUS_TYPE: // PCI-Cardbus bridge
Irq = pInfo
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -