📄 ufnmdd.cpp
字号:
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
DWORD cEndpoints = pInterfaceSource->Descriptor.bNumEndpoints;
if (cEndpoints > 0) {
DWORD cbEndpoints;
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) {
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) {
DWORD 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();
}
// 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;
// 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);
cbStringArrays = cbStringArray * cStringSets;
cbBuffer = cbStringSets + cbStringArrays + cbStrings;
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;
DWORD cEndpoints = pInterface->Descriptor.bNumEndpoints;
if ( cEndpoints && (pInterface->pEndpoints == NULL) ) {
DEBUGMSG(ZONE_ERROR, (_T("%s No endpoint structure provided\r\n"),
pszFname));
goto EXIT;
}
DWORD dwEndpoint;
for (dwEndpoint = 0; dwEndpoint < cEndpoints; ++dwEndpoint) {
PUFN_ENDPOINT pEndpoint = &pInterface->pEndpoints[dwEndpoint];
if (!ValidatePacketSize(Speed, &pEndpoint->Descriptor)) {
DEBUGMSG(ZONE_ERROR, (_T("%s Invalid packet size for endpoint 0x%x\r\n"),
pszFname, pEndpoint->Descriptor.bEndpointAddress));
goto EXIT;
}
// Do not check endoint 0.
for (DWORD dwPipe = 1; dwPipe < pContext->PddInfo.dwEndpointCount; ++dwPipe) {
PCPipe pPipe = &pContext->pPipes[dwPipe];
if (pPipe->IsReserved(Speed)) {
continue;
}
if (pContext->PddInfo.pfnIsEndpointSupportable(pContext->PddInfo.pvPddContext,
pPipe->GetPhysicalEndpoint(), Speed,
&pEndpoint->Descriptor, bConfiguration, pInterface->Descriptor.bInterfaceNumber,
pInterface->Descriptor.bAlternateSetting) == ERROR_SUCCESS) {
DEBUGMSG(ZONE_FUNCTION,
(_T("%s Endpoint index %u can be supported by physical endpoint %u\r\n"),
pszFname, dwEndpoint, pPipe->GetPhysicalEndpoint()));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -