⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pcibus.c

📁 PCI总线的驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
    }
    
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 + -