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

📄 ufnmdd.cpp

📁 It permits simultaneous use of multiple USB Serial protocols.
💻 CPP
📖 第 1 页 / 共 5 页
字号:

    // Copy the interface structure
    DEBUGCHK(pConfigSource->Descriptor.bNumInterfaces);
    PREFAST_DEBUGCHK(pConfigSource->pInterfaces);
    DWORD cbInterfaces = 
        pConfigDest->Descriptor.bNumInterfaces * sizeof(UFN_INTERFACE);
    pConfigDest->pInterfaces = (PUFN_INTERFACE) LocalAlloc(0, cbInterfaces);
    if (pConfigDest->pInterfaces == NULL) {
        dwRet = GetLastError();
        DEBUGMSG(ZONE_ERROR, (_T("%s LocalAlloc failed. Error: %d\r\n"), pszFname, 
            dwRet));
        goto EXIT;
    }
    
    memcpy(pConfigDest->pInterfaces, pConfigSource->pInterfaces, cbInterfaces);

    DWORD cInterfaces = pConfigDest->Descriptor.bNumInterfaces;
    // Clear out each interface's pointers
    for (DWORD dwInterface = 0; dwInterface < cInterfaces; ++dwInterface) {
        PUFN_INTERFACE pInterfaceDest = &pConfigDest->pInterfaces[dwInterface];
        pInterfaceDest->pEndpoints = NULL;
        pInterfaceDest->pvExtended = NULL;
    }
    
    // Copy each interface's extended descriptor
    for (DWORD dwInterface = 0; dwInterface < cInterfaces; ++dwInterface) {
        PUFN_INTERFACE pInterfaceSource = &pConfigSource->pInterfaces[dwInterface];
        PUFN_INTERFACE pInterfaceDest = &pConfigDest->pInterfaces[dwInterface];

        // TODO: Fail on alternate interface
        
        dwRet = CopyExtendedDesc(&pInterfaceDest->pvExtended, 
            &pInterfaceDest->cbExtended,
            pInterfaceSource->pvExtended,
            pInterfaceSource->cbExtended);
        if (dwRet != ERROR_SUCCESS) {
            goto EXIT;
        }

        // Copy the endpoint structures
        const BYTE cEndpoints = pInterfaceSource->Descriptor.bNumEndpoints;

        if (cEndpoints > 0) {
            DWORD cbEndpoints = cEndpoints * sizeof(UFN_ENDPOINT);
            pInterfaceDest->pEndpoints = (PUFN_ENDPOINT)
                LocalAlloc(0, cbEndpoints);
            if (pInterfaceDest->pEndpoints == NULL) {
                dwRet = GetLastError();
                DEBUGMSG(ZONE_ERROR, (_T("%s LocalAlloc failed. Error: %d\r\n"), pszFname, 
                    dwRet));
                goto EXIT;
            }

            memcpy(pInterfaceDest->pEndpoints, pInterfaceSource->pEndpoints, 
                cbEndpoints);

            // Clear out each endpoint's pointers
            for (DWORD dwEndpoint = 0; dwEndpoint < cEndpoints; ++dwEndpoint) {
                PREFAST_SUPPRESS(12009, "False Positive");
                PUFN_ENDPOINT pDestEndpoint = 
                    &pInterfaceDest->pEndpoints[dwEndpoint];
                pDestEndpoint->pvExtended = NULL;
            }
            
            // Copy each endpoint's extended descriptors
            for (DWORD dwEndpoint = 0; dwEndpoint < cEndpoints; ++dwEndpoint) {
                PUFN_ENDPOINT pSourceEndpoint = 
                    &pInterfaceSource->pEndpoints[dwEndpoint];
                PUFN_ENDPOINT pDestEndpoint = 
                    &pInterfaceDest->pEndpoints[dwEndpoint];
                dwRet = CopyExtendedDesc(&pDestEndpoint->pvExtended, &pDestEndpoint->cbExtended,
                    pSourceEndpoint->pvExtended, pSourceEndpoint->cbExtended);
                if (dwRet != ERROR_SUCCESS) {
                    goto EXIT;
                }
            }
        }
    }

    dwRet = ERROR_SUCCESS;

EXIT:
    FUNCTION_LEAVE_MSG();

    return dwRet;
}


// Free all allocated data in a config tree structure.
static
VOID
FreeConfig(
    PUFN_CONFIGURATION pConfig
    )
{
    SETFNAME();
    FUNCTION_ENTER_MSG();

    PREFAST_DEBUGCHK(pConfig);

    if (pConfig->pInterfaces) {
        const DWORD cInterfaces = pConfig->Descriptor.bNumInterfaces;
        for (DWORD dwInterface = 0; dwInterface < cInterfaces; ++dwInterface) {
            PUFN_INTERFACE pInterface = &pConfig->pInterfaces[dwInterface];
            if (pInterface->pEndpoints) {
                const BYTE cEndpoints = pInterface->Descriptor.bNumEndpoints;
                for (DWORD dwEndpoint = 0; dwEndpoint < cEndpoints; ++dwEndpoint) {
                    PUFN_ENDPOINT pSourceEndpoint = 
                        &pInterface->pEndpoints[dwEndpoint];

                    // Free this endpoint's extended descriptor
                    if (pSourceEndpoint->pvExtended) {
                        LocalFree(pSourceEndpoint->pvExtended);
                    }
                }

                // Free the endpoint structures
                LocalFree(pInterface->pEndpoints);
            }

            // Free the interface's extended descriptor
            if (pInterface->pvExtended) {
                LocalFree(pInterface->pvExtended);
            }
        }

        // Free the interface structure
        LocalFree(pConfig->pInterfaces);
        pConfig->pInterfaces = NULL;
    }
    
    // Free the config's extended descriptor
    if (pConfig->pvExtended) {
        LocalFree(pConfig->pvExtended);
        pConfig->pvExtended = NULL;
    }

    FUNCTION_LEAVE_MSG();
}


#define MAX_STRING_SETS         USHRT_MAX   // LangId is a WORD so this is the max
#define MAX_STRING_SET_STRINGS  0x1000      // arbitrary value


// Copy string descriptors.
static
DWORD
CopyStrings(
    PUFN_MDD_CONTEXT    pContext,
    PCUFN_STRING_SET    pStringSets,
    DWORD               cStringSets
    )
{
    SETFNAME();
    FUNCTION_ENTER_MSG();

    ValidateContext(pContext);
    PREFAST_DEBUGCHK(pStringSets);
    DEBUGCHK(cStringSets);

    DWORD dwRet = ERROR_INVALID_PARAMETER;
    DWORD dwStringSet;
    DWORD dwString;
    DWORD cbStringSets;
    DWORD cbStringArray;
    DWORD cbStringArrays;
    DWORD cbBuffer;
    PBYTE pbBuffer;

    if (cStringSets > MAX_STRING_SETS) {
        DEBUGMSG(ZONE_ERROR, (_T("%s Too many string sets: %u\r\n"), pszFname, 
            cStringSets));
        goto EXIT;
    }

    // Get the count of bytes in the strings
    DWORD cbStrings = 0;
    DWORD cStrings = pStringSets->cStrings;
    for (dwStringSet = 0; dwStringSet < cStringSets; ++dwStringSet) {
        PCUFN_STRING_SET pStringSet = &pStringSets[dwStringSet];

        if (pStringSet->cStrings != cStrings) {
            DEBUGMSG(ZONE_ERROR, (_T("%s String count across locales do not match\r\n"), 
                pszFname));
            goto EXIT;
        }

        for (dwString = 0; dwString < pStringSet->cStrings; ++dwString) {
            LPCWSTR pszString = pStringSet->ppszStrings[dwString];
            DWORD cchString = wcslen(pszString);
            
            if (cchString >= MAX_STRING_DESC_WCHARS) {
                DEBUGMSG(ZONE_ERROR, (_T("%s String %s is too long\r\n"), pszFname,
                    pszString));
                goto EXIT;
            }
            
            cbStrings += (cchString + 1) * sizeof(WCHAR);
        }
    }

    cbStringSets = cStringSets * sizeof(UFN_STRING_SET);
    cbStringArray = pStringSets->cStrings * sizeof(*pStringSets->ppszStrings);

    if (pStringSets->cStrings > MAX_STRING_SET_STRINGS) {
        DEBUGMSG(ZONE_ERROR, (_T("%s Too many string set strings: %u\r\n"), pszFname, 
            cStringSets));
        goto EXIT;
    }
    
    cbStringArrays = cbStringArray * cStringSets;
    cbBuffer = cbStringSets + cbStringArrays + cbStrings;

    if (cbBuffer < cbStringSets || cbBuffer < cbStringArrays || cbBuffer < cbStrings) {
        DEBUGMSG(ZONE_ERROR, (_T("%s Size of the string buffer has overflowed\r\n"), pszFname));
        goto EXIT;
    }
    
    pbBuffer = (PBYTE) LocalAlloc(0, cbBuffer);
    if (pbBuffer == NULL) {
        dwRet = GetLastError();
        DEBUGMSG(ZONE_ERROR, (_T("%s LocalAlloc failed. Error: %d\r\n"), pszFname, 
            dwRet));
        goto EXIT;
    }

    pContext->pStringSets = (PUFN_STRING_SET) pbBuffer;

    // Copy string sets
    memcpy(pContext->pStringSets, pStringSets, cbStringSets);

    // Assign string pointer arrays
    pbBuffer += cbStringSets;
    for (dwStringSet = 0; dwStringSet < cStringSets; ++dwStringSet) {
        PUFN_STRING_SET pStringSetDst = &pContext->pStringSets[dwStringSet];
        pStringSetDst->ppszStrings = (LPCWSTR *) pbBuffer;
        pbBuffer += cbStringArray;
    }

    // Copy each string
    for (dwStringSet = 0; dwStringSet < cStringSets; ++dwStringSet) {
        PCUFN_STRING_SET pStringSetSrc = &pStringSets[dwStringSet];
        PUFN_STRING_SET pStringSetDst = &pContext->pStringSets[dwStringSet];

        for (dwString = 0; dwString < pStringSetSrc->cStrings; ++dwString) {
            LPCWSTR pszSrc = pStringSetSrc->ppszStrings[dwString];
            LPWSTR pszDst = (LPWSTR) pbBuffer;

            DWORD cchString = wcslen(pszSrc);
            wcsncpy(pszDst, pszSrc, cchString);
            pszDst[cchString] = 0;

            pStringSetDst->ppszStrings[dwString] = pszDst;
            pbBuffer += (cchString + 1) * sizeof(WCHAR);
        }
    }

    pContext->cStringSets = cStringSets;

    dwRet = ERROR_SUCCESS;
    
EXIT:
    FUNCTION_LEAVE_MSG();

    return dwRet;
}


// Free string descriptors in pContext.
static
VOID
FreeStrings(
    PUFN_MDD_CONTEXT pContext
    )
{
    SETFNAME();
    FUNCTION_ENTER_MSG();
    
    PREFAST_DEBUGCHK(pContext);
    
    LocalFree(pContext->pStringSets);
    pContext->pStringSets = NULL;
    pContext->cStringSets = 0;

    FUNCTION_LEAVE_MSG();
}


// Free all allocated USB structures in pContext.
static
VOID
FreeUsbStructs(
    PUFN_MDD_CONTEXT pContext
    )
{
    SETFNAME();
    FUNCTION_ENTER_MSG();

    ValidateContext(pContext);

    if (pContext->pStringSets) {
        FreeStrings(pContext);
        pContext->pStringSets = NULL;
    }

    if (pContext->pHighSpeedConfigDesc) {
        LocalFree(pContext->pHighSpeedConfigDesc);
        pContext->pHighSpeedConfigDesc = NULL;
    }

    if (pContext->pFullSpeedConfigDesc) {
        LocalFree(pContext->pFullSpeedConfigDesc);
        pContext->pFullSpeedConfigDesc = NULL;
    }

    if ( pContext->HighSpeedConfig.pInterfaces ||
         pContext->HighSpeedConfig.pvExtended ) {
        FreeConfig(&pContext->HighSpeedConfig);
    }

    if ( pContext->FullSpeedConfig.dwCount ||
         pContext->FullSpeedConfig.pvExtended ) {
        FreeConfig(&pContext->FullSpeedConfig);
    }

    FUNCTION_LEAVE_MSG();
}
    

// Copy the user-supplied USB structures to the pContext.
static
DWORD
CopyUsbStructs(
    PUFN_MDD_CONTEXT        pContext,
    PUSB_DEVICE_DESCRIPTOR  pHighSpeedDeviceDesc,
    PUFN_CONFIGURATION      pHighSpeedConfig,
    PUSB_DEVICE_DESCRIPTOR  pFullSpeedDeviceDesc,
    PUFN_CONFIGURATION      pFullSpeedConfig,
    PCUFN_STRING_SET        pStringSets,
    DWORD                   cStringSets
    )
{
    SETFNAME();
    FUNCTION_ENTER_MSG();

    DWORD dwRet = ERROR_SUCCESS;
    
    ValidateContext(pContext);
    DEBUGCHK(pHighSpeedDeviceDesc);
    DEBUGCHK(pFullSpeedDeviceDesc);
    DEBUGCHK(pHighSpeedConfig);
    DEBUGCHK(pFullSpeedConfig);
    DEBUGCHK(pStringSets || (cStringSets == 0));
    
    struct CONFIG_SPEED_VALUES {
        PUSB_DEVICE_DESCRIPTOR pDestDeviceDesc;
        PUSB_DEVICE_DESCRIPTOR pSourceDeviceDesc;
        PUFN_CONFIGURATION pDestConfig;
        PUFN_CONFIGURATION pSourceConfig;
        PUSB_CONFIGURATION_DESCRIPTOR *ppConfigDesc;
    };

    const CONFIG_SPEED_VALUES rgpConfigVals[] = { // destination-source pairs
        {
            &pContext->HighSpeedDeviceDesc, pHighSpeedDeviceDesc,
            &pContext->HighSpeedConfig, pHighSpeedConfig, 
            &pContext->pHighSpeedConfigDesc 
        },
        {
            &pContext->FullSpeedDeviceDesc, pFullSpeedDeviceDesc,
            &pContext->FullSpeedConfig, pFullSpeedConfig, 
            &pContext->pFullSpeedConfigDesc
        }
    };
        
    // Copy high and full speed structures
    for (DWORD dwConfig = 0; dwConfig < dim(rgpConfigVals); ++dwConfig) {
        const CONFIG_SPEED_VALUES *pConfigVals = &rgpConfigVals[dwConfig];

        // Copy the device descriptor
        memcpy(pConfigVals->pDestDeviceDesc, pConfigVals->pSourceDeviceDesc,
            sizeof(USB_DEVICE_DESCRIPTOR));

        // Copy the config tree structure
        dwRet = CopyConfig(pConfigVals->pDestConfig, pConfigVals->pSourceConfig);
        if (dwRet != ERROR_SUCCESS) {
            goto EXIT;
        }
        
        // Create the conglomerate configuration descriptor
        dwRet = CreateConfigDesc(pConfigVals->ppConfigDesc, pConfigVals->pDestConfig);
        if (dwRet != ERROR_SUCCESS) {
            goto EXIT;
        }

        DEBUGCHK(*pConfigVals->ppConfigDesc);
    }

    // Copy string descriptors
    if (cStringSets != 0) {
        dwRet = CopyStrings(pContext, pStringSets, cStringSets);
        if (dwRet != ERROR_SUCCESS) {
            goto EXIT;
        }

        DEBUGCHK(pContext->pStringSets);
        DEBUGCHK(pContext->cStringSets);
    }

EXIT:
    if (dwRet != ERROR_SUCCESS) {
        // Free all allocated data
        FreeUsbStructs(pContext);
    }
    
    FUNCTION_LEAVE_MSG();

    return dwRet;
}


// Finds out if endpoint 0 is supportable for these parameters.
static
DWORD
IsEndpointZeroSupportable(
    PUFN_MDD_CONTEXT pContext,
    PUSB_DEVICE_DESCRIPTOR pDeviceDesc,
    UFN_BUS_SPEED Speed
    )
{
    SETFNAME();
    FUNCTION_ENTER_MSG();

    ValidateContext(pContext);
    PREFAST_DEBUGCHK(pDeviceDesc);

    DWORD dwRet = ERROR_SUCCESS;

    USB_ENDPOINT_DESCRIPTOR EndpointDesc;
    InitializeEndpointZeroDescriptor(pContext, pDeviceDesc->bMaxPacketSize0, &EndpointDesc);
    
    if ( !ValidatePacketSize(Speed, &EndpointDesc) ||
         (pContext->PddInfo.pfnIsEndpointSupportable(pContext->PddInfo.pvPddContext, 0, Speed, 
            &EndpointDesc, 0, 0, 0) != ERROR_SUCCESS) ) {
        dwRet = ERROR_INVALID_PARAMETER;
        DEBUGMSG(ZONE_ERROR, (_T("%s Cannot satisfy %s speed EP0 packet size requirement of %u\r\n"), 
            pszFname, GetSpeedString(Speed), pDeviceDesc->bMaxPacketSize0));
        goto EXIT;
    }
    pDeviceDesc->bMaxPacketSize0 = (BYTE) EndpointDesc.wMaxPacketSize;

EXIT:
    FUNCTION_LEAVE_MSG();

    return dwRet;
}


// Finds out if an entire interface is supportable.
static
DWORD
IsInterfaceSupportable(
    PUFN_MDD_CONTEXT pContext,
    PUFN_INTERFACE pInterface,
    UFN_BUS_SPEED Speed,
    BYTE bConfiguration
    )
{
    SETFNAME();
    FUNCTION_ENTER_MSG();

    ValidateContext(pContext);
    PREFAST_DEBUGCHK(pInterface);

    DWORD dwRet = ERROR_INVALID_PARAMETER;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -