Commit b77487ae authored by robiwan's avatar robiwan

Committing Lelands patch for WDM-KS, should take care of some of the problems...

Committing Lelands patch for WDM-KS, should take care of some of the problems referenced here http://music.columbia.edu/pipermail/portaudio/2014-August/016246.html

git-svn-id: https://subversion.assembla.com/svn/portaudio/portaudio/trunk@1932 0f58301d-fd10-0410-b4af-bbb618454e57
parent cf397b6d
...@@ -1012,7 +1012,7 @@ static ULONG GetNumberOfConnectionsTo(const KSTOPOLOGY_CONNECTION* pTo, PaWinWdm ...@@ -1012,7 +1012,7 @@ static ULONG GetNumberOfConnectionsTo(const KSTOPOLOGY_CONNECTION* pTo, PaWinWdm
ULONG retval = 0; ULONG retval = 0;
unsigned i; unsigned i;
const KSTOPOLOGY_CONNECTION* connections = (const KSTOPOLOGY_CONNECTION*)(filter->connections + 1); const KSTOPOLOGY_CONNECTION* connections = (const KSTOPOLOGY_CONNECTION*)(filter->connections + 1);
PA_DEBUG(("GetNumberOfConnectionsTo: Checking %u connections...", filter->connections->Count)); PA_DEBUG(("GetNumberOfConnectionsTo: Checking %u connections...\n", filter->connections->Count));
for (i = 0; i < filter->connections->Count; ++i) for (i = 0; i < filter->connections->Count; ++i)
{ {
const KSTOPOLOGY_CONNECTION* pConn = connections + i; const KSTOPOLOGY_CONNECTION* pConn = connections + i;
...@@ -1022,6 +1022,7 @@ static ULONG GetNumberOfConnectionsTo(const KSTOPOLOGY_CONNECTION* pTo, PaWinWdm ...@@ -1022,6 +1022,7 @@ static ULONG GetNumberOfConnectionsTo(const KSTOPOLOGY_CONNECTION* pTo, PaWinWdm
++retval; ++retval;
} }
} }
PA_DEBUG(("GetNumberOfConnectionsTo: Returning %d\n", retval));
return retval; return retval;
} }
...@@ -1031,16 +1032,18 @@ static const KSTOPOLOGY_CONNECTION* FindStartConnectionFrom(ULONG startPin, PaWi ...@@ -1031,16 +1032,18 @@ static const KSTOPOLOGY_CONNECTION* FindStartConnectionFrom(ULONG startPin, PaWi
{ {
unsigned i; unsigned i;
const KSTOPOLOGY_CONNECTION* connections = (const KSTOPOLOGY_CONNECTION*)(filter->connections + 1); const KSTOPOLOGY_CONNECTION* connections = (const KSTOPOLOGY_CONNECTION*)(filter->connections + 1);
PA_DEBUG(("FindStartConnectionFrom: Checking %u connections...", filter->connections->Count)); PA_DEBUG(("FindStartConnectionFrom: Checking %u connections...\n", filter->connections->Count));
for (i = 0; i < filter->connections->Count; ++i) for (i = 0; i < filter->connections->Count; ++i)
{ {
const KSTOPOLOGY_CONNECTION* pConn = connections + i; const KSTOPOLOGY_CONNECTION* pConn = connections + i;
if (pConn->ToNode == KSFILTER_NODE && pConn->ToNodePin == startPin) if (pConn->ToNode == KSFILTER_NODE && pConn->ToNodePin == startPin)
{ {
PA_DEBUG(("FindStartConnectionFrom: returning %p\n", pConn));
return pConn; return pConn;
} }
} }
PA_DEBUG(("FindStartConnectionFrom: returning NULL\n"));
assert(FALSE); assert(FALSE);
return 0; return 0;
} }
...@@ -1049,26 +1052,36 @@ static const KSTOPOLOGY_CONNECTION* FindStartConnectionTo(ULONG startPin, PaWinW ...@@ -1049,26 +1052,36 @@ static const KSTOPOLOGY_CONNECTION* FindStartConnectionTo(ULONG startPin, PaWinW
{ {
unsigned i; unsigned i;
const KSTOPOLOGY_CONNECTION* connections = (const KSTOPOLOGY_CONNECTION*)(filter->connections + 1); const KSTOPOLOGY_CONNECTION* connections = (const KSTOPOLOGY_CONNECTION*)(filter->connections + 1);
PA_DEBUG(("FindStartConnectionTo: Checking %u connections...", filter->connections->Count)); PA_DEBUG(("FindStartConnectionTo: Checking %u connections...\n", filter->connections->Count));
for (i = 0; i < filter->connections->Count; ++i) for (i = 0; i < filter->connections->Count; ++i)
{ {
const KSTOPOLOGY_CONNECTION* pConn = connections + i; const KSTOPOLOGY_CONNECTION* pConn = connections + i;
if (pConn->FromNode == KSFILTER_NODE && pConn->FromNodePin == startPin) if (pConn->FromNode == KSFILTER_NODE && pConn->FromNodePin == startPin)
{ {
PA_DEBUG(("FindStartConnectionTo: returning %p\n", pConn));
return pConn; return pConn;
} }
} }
PA_DEBUG(("FindStartConnectionTo: returning NULL\n"));
assert(FALSE); assert(FALSE);
return 0; return 0;
} }
static ULONG GetConnectedPin(ULONG startPin, BOOL forward, PaWinWdmFilter* filter, int muxPosition, ULONG *muxInputPinId, ULONG *muxNodeId) static ULONG GetConnectedPin(ULONG startPin, BOOL forward, PaWinWdmFilter* filter, int muxPosition, ULONG *muxInputPinId, ULONG *muxNodeId)
{ {
int limit=1000;
const KSTOPOLOGY_CONNECTION *conn = NULL; const KSTOPOLOGY_CONNECTION *conn = NULL;
TFnGetConnection fnGetConnection = forward ? GetConnectionTo : GetConnectionFrom ; TFnGetConnection fnGetConnection = forward ? GetConnectionTo : GetConnectionFrom ;
PA_LOGE_;
while (1) while (1)
{ {
limit--;
if (limit == 0) {
PA_DEBUG(("GetConnectedPin: LOOP LIMIT REACHED\n"));
break;
}
if (conn == NULL) if (conn == NULL)
{ {
conn = forward ? FindStartConnectionTo(startPin, filter) : FindStartConnectionFrom(startPin, filter); conn = forward ? FindStartConnectionTo(startPin, filter) : FindStartConnectionFrom(startPin, filter);
...@@ -1114,6 +1127,7 @@ static ULONG GetConnectedPin(ULONG startPin, BOOL forward, PaWinWdmFilter* filte ...@@ -1114,6 +1127,7 @@ static ULONG GetConnectedPin(ULONG startPin, BOOL forward, PaWinWdmFilter* filte
} }
} }
} }
PA_LOGL_;
return KSFILTER_NODE; return KSFILTER_NODE;
} }
...@@ -1123,6 +1137,7 @@ static void DumpConnectionsAndNodes(PaWinWdmFilter* filter) ...@@ -1123,6 +1137,7 @@ static void DumpConnectionsAndNodes(PaWinWdmFilter* filter)
const KSTOPOLOGY_CONNECTION* connections = (const KSTOPOLOGY_CONNECTION*)(filter->connections + 1); const KSTOPOLOGY_CONNECTION* connections = (const KSTOPOLOGY_CONNECTION*)(filter->connections + 1);
const GUID* nodes = (const GUID*)(filter->nodes + 1); const GUID* nodes = (const GUID*)(filter->nodes + 1);
PA_LOGE_;
PA_DEBUG(("DumpConnectionsAndNodes: connections=%d, nodes=%d\n", filter->connections->Count, filter->nodes->Count)); PA_DEBUG(("DumpConnectionsAndNodes: connections=%d, nodes=%d\n", filter->connections->Count, filter->nodes->Count));
for (i=0; i < filter->connections->Count; ++i) for (i=0; i < filter->connections->Count; ++i)
...@@ -1147,6 +1162,7 @@ static void DumpConnectionsAndNodes(PaWinWdmFilter* filter) ...@@ -1147,6 +1162,7 @@ static void DumpConnectionsAndNodes(PaWinWdmFilter* filter)
pConn->Data4[6], pConn->Data4[7] pConn->Data4[6], pConn->Data4[7]
)); ));
} }
PA_LOGL_;
} }
...@@ -1196,6 +1212,7 @@ static PaError GetNameFromCategory(const GUID* pGUID, BOOL input, wchar_t* name, ...@@ -1196,6 +1212,7 @@ static PaError GetNameFromCategory(const GUID* pGUID, BOOL input, wchar_t* name,
PaError result = paUnanticipatedHostError; PaError result = paUnanticipatedHostError;
USHORT usbTerminalGUID = (USHORT)(pGUID->Data1 - 0xDFF219E0); USHORT usbTerminalGUID = (USHORT)(pGUID->Data1 - 0xDFF219E0);
PA_LOGE_;
if (input && usbTerminalGUID >= 0x301 && usbTerminalGUID < 0x400) if (input && usbTerminalGUID >= 0x301 && usbTerminalGUID < 0x400)
{ {
/* Output terminal name for an input !? Set it to Line! */ /* Output terminal name for an input !? Set it to Line! */
...@@ -1235,6 +1252,7 @@ static PaError GetNameFromCategory(const GUID* pGUID, BOOL input, wchar_t* name, ...@@ -1235,6 +1252,7 @@ static PaError GetNameFromCategory(const GUID* pGUID, BOOL input, wchar_t* name,
{ {
PaWinWDM_SetLastErrorInfo(result, "GetNameFromCategory: usbTerminalGUID = %04X ", usbTerminalGUID); PaWinWDM_SetLastErrorInfo(result, "GetNameFromCategory: usbTerminalGUID = %04X ", usbTerminalGUID);
} }
PA_LOGL_;
return result; return result;
} }
...@@ -1633,6 +1651,8 @@ static PaWinWdmPin* PinNew(PaWinWdmFilter* parentFilter, unsigned long pinId, Pa ...@@ -1633,6 +1651,8 @@ static PaWinWdmPin* PinNew(PaWinWdmFilter* parentFilter, unsigned long pinId, Pa
else else
{ {
KSPIN_PHYSICALCONNECTION* pc = (KSPIN_PHYSICALCONNECTION*)PaUtil_AllocateMemory(cbBytes + 2); KSPIN_PHYSICALCONNECTION* pc = (KSPIN_PHYSICALCONNECTION*)PaUtil_AllocateMemory(cbBytes + 2);
ULONG pcPin;
wchar_t symbLinkName[MAX_PATH];
PA_DEBUG(("PinNew: Physical connection found!\n")); PA_DEBUG(("PinNew: Physical connection found!\n"));
if (pc == NULL) if (pc == NULL)
{ {
...@@ -1647,144 +1667,255 @@ static PaWinWdmPin* PinNew(PaWinWdmFilter* parentFilter, unsigned long pinId, Pa ...@@ -1647,144 +1667,255 @@ static PaWinWdmPin* PinNew(PaWinWdmFilter* parentFilter, unsigned long pinId, Pa
cbBytes, cbBytes,
NULL NULL
); );
if (result == paNoError)
pcPin = pc->Pin;
wcsncpy(symbLinkName, pc->SymbolicLinkName, MAX_PATH);
PaUtil_FreeMemory( pc );
if (result != paNoError)
{ {
wchar_t symbLinkName[MAX_PATH]; /* Shouldn't happen, but fail if it does */
wcsncpy(symbLinkName, pc->SymbolicLinkName, MAX_PATH); PA_DEBUG(("PinNew: failed to retrieve physical connection!\n"));
if (symbLinkName[1] == TEXT('?')) goto error;
}
if (symbLinkName[1] == TEXT('?'))
{
symbLinkName[1] = TEXT('\\');
}
if (pin->parentFilter->topologyFilter == NULL)
{
PA_DEBUG(("PinNew: Creating topology filter '%S'\n", symbLinkName));
pin->parentFilter->topologyFilter = FilterNew(Type_kNotUsed, 0, symbLinkName, L"", &result);
if (pin->parentFilter->topologyFilter == NULL)
{ {
symbLinkName[1] = TEXT('\\'); PA_DEBUG(("PinNew: Failed creating topology filter\n"));
result = paUnanticipatedHostError;
PaWinWDM_SetLastErrorInfo(result, "Failed to create topology filter '%S'", symbLinkName);
goto error;
} }
if (pin->parentFilter->topologyFilter == NULL) /* Copy info so we have it in device info */
wcsncpy(pin->parentFilter->devInfo.topologyPath, symbLinkName, MAX_PATH);
}
else
{
/* Must be the same */
assert(wcscmp(symbLinkName, pin->parentFilter->topologyFilter->devInfo.filterPath) == 0);
}
PA_DEBUG(("PinNew: Opening topology filter..."));
result = FilterUse(pin->parentFilter->topologyFilter);
if (result == paNoError)
{
unsigned long endpointPinId;
if (pin->dataFlow == KSPIN_DATAFLOW_IN)
{ {
PA_DEBUG(("PinNew: Creating topology filter '%S'\n", symbLinkName)); /* The "endpointPinId" is what WASAPI looks at for pin names */
GUID category = {0};
PA_DEBUG(("PinNew: Checking for output endpoint pin id...\n"));
endpointPinId = GetConnectedPin(pcPin, TRUE, pin->parentFilter->topologyFilter, -1, NULL, NULL);
pin->parentFilter->topologyFilter = FilterNew(Type_kNotUsed, 0, symbLinkName, L"", &result); if (endpointPinId == KSFILTER_NODE)
if (pin->parentFilter->topologyFilter == NULL)
{ {
PA_DEBUG(("PinNew: Failed creating topology filter\n"));
result = paUnanticipatedHostError; result = paUnanticipatedHostError;
PaWinWDM_SetLastErrorInfo(result, "Failed to create topology filter '%S'", symbLinkName); PaWinWDM_SetLastErrorInfo(result, "Failed to get endpoint pin ID on topology filter!");
goto error; goto error;
} }
/* Copy info so we have it in device info */ PA_DEBUG(("PinNew: Found endpoint pin id %u\n", endpointPinId));
wcsncpy(pin->parentFilter->devInfo.topologyPath, symbLinkName, MAX_PATH);
}
else
{
/* Must be the same */
assert(wcscmp(symbLinkName, pin->parentFilter->topologyFilter->devInfo.filterPath) == 0);
}
PA_DEBUG(("PinNew: Opening topology filter..."));
result = FilterUse(pin->parentFilter->topologyFilter); /* Get pin category information */
if (result == paNoError) result = WdmGetPinPropertySimple(pin->parentFilter->topologyFilter->handle,
{ endpointPinId,
unsigned long endpointPinId; &KSPROPSETID_Pin,
KSPROPERTY_PIN_CATEGORY,
&category,
sizeof(GUID),
NULL);
if (pin->dataFlow == KSPIN_DATAFLOW_IN) if (result == paNoError)
{ {
/* The "endpointPinId" is what WASAPI looks at for pin names */ #if !PA_WDMKS_USE_CATEGORY_FOR_PIN_NAMES
GUID category = {0}; wchar_t pinName[MAX_PATH];
PA_DEBUG(("PinNew: Checking for output endpoint pin id...\n")); PA_DEBUG(("PinNew: Getting pin name property..."));
endpointPinId = GetConnectedPin(pc->Pin, TRUE, pin->parentFilter->topologyFilter, -1, NULL, NULL); /* Ok, try pin name also, and favor that if available */
result = WdmGetPinPropertySimple(pin->parentFilter->topologyFilter->handle,
endpointPinId,
&KSPROPSETID_Pin,
KSPROPERTY_PIN_NAME,
pinName,
MAX_PATH,
NULL);
if (endpointPinId == KSFILTER_NODE) if (result == paNoError && wcslen(pinName)>0)
{ {
result = paUnanticipatedHostError; wcsncpy(pin->friendlyName, pinName, MAX_PATH);
PaWinWDM_SetLastErrorInfo(result, "Failed to get endpoint pin ID on topology filter!");
goto error;
} }
else
#endif
{
result = GetNameFromCategory(&category, (pin->dataFlow == KSPIN_DATAFLOW_OUT), pin->friendlyName, MAX_PATH);
}
}
PA_DEBUG(("PinNew: Found endpoint pin id %u\n", endpointPinId)); /* Make sure we get a name for the pin */
if (wcslen(pin->friendlyName) == 0)
{
wcscpy(pin->friendlyName, kOutputName);
}
#ifdef UNICODE
PA_DEBUG(("PinNew: Pin name '%s'\n", pin->friendlyName));
#else
PA_DEBUG(("PinNew: Pin name '%S'\n", pin->friendlyName));
#endif
/* Get pin category information */ /* Set endpoint pin ID (this is the topology INPUT pin, since portmixer will always traverse the
result = WdmGetPinPropertySimple(pin->parentFilter->topologyFilter->handle, filter in audio streaming direction, see http://msdn.microsoft.com/en-us/library/windows/hardware/ff536331(v=vs.85).aspx
endpointPinId, for more information)
&KSPROPSETID_Pin, */
KSPROPERTY_PIN_CATEGORY, pin->endpointPinId = pcPin;
&category, }
sizeof(GUID), else
NULL); {
unsigned muxCount = 0;
int muxPos = 0;
/* Max 64 multiplexer inputs... sanity check :) */
for (i = 0; i < 64; ++i)
{
ULONG muxNodeIdTest = (unsigned)-1;
PA_DEBUG(("PinNew: Checking for input endpoint pin id (%d)...\n", i));
endpointPinId = GetConnectedPin(pcPin,
FALSE,
pin->parentFilter->topologyFilter,
(int)i,
NULL,
&muxNodeIdTest);
if (result == paNoError) if (endpointPinId == KSFILTER_NODE)
{ {
#if !PA_WDMKS_USE_CATEGORY_FOR_PIN_NAMES /* We're done */
wchar_t pinName[MAX_PATH]; PA_DEBUG(("PinNew: Done with inputs.\n", endpointPinId));
break;
}
else
{
/* The "endpointPinId" is what WASAPI looks at for pin names */
GUID category = {0};
PA_DEBUG(("PinNew: Getting pin name property...")); PA_DEBUG(("PinNew: Found endpoint pin id %u\n", endpointPinId));
/* Ok, try pin name also, and favor that if available */ /* Get pin category information */
result = WdmGetPinPropertySimple(pin->parentFilter->topologyFilter->handle, result = WdmGetPinPropertySimple(pin->parentFilter->topologyFilter->handle,
endpointPinId, endpointPinId,
&KSPROPSETID_Pin, &KSPROPSETID_Pin,
KSPROPERTY_PIN_NAME, KSPROPERTY_PIN_CATEGORY,
pinName, &category,
MAX_PATH, sizeof(GUID),
NULL); NULL);
if (result == paNoError && wcslen(pinName)>0) if (result == paNoError)
{ {
wcsncpy(pin->friendlyName, pinName, MAX_PATH); if (muxNodeIdTest == (unsigned)-1)
{
/* Ok, try pin name, and favor that if available */
result = WdmGetPinPropertySimple(pin->parentFilter->topologyFilter->handle,
endpointPinId,
&KSPROPSETID_Pin,
KSPROPERTY_PIN_NAME,
pin->friendlyName,
MAX_PATH,
NULL);
if (result != paNoError)
{
result = GetNameFromCategory(&category, TRUE, pin->friendlyName, MAX_PATH);
}
break;
}
else
{
result = GetNameFromCategory(&category, TRUE, NULL, 0);
if (result == paNoError)
{
++muxCount;
}
}
} }
else else
#endif
{ {
result = GetNameFromCategory(&category, (pin->dataFlow == KSPIN_DATAFLOW_OUT), pin->friendlyName, MAX_PATH); PA_DEBUG(("PinNew: Failed to get pin category"));
} }
}
}
if (wcslen(pin->friendlyName) == 0) if (muxCount == 0)
{ {
wcscpy(pin->friendlyName, L"Output"); pin->endpointPinId = endpointPinId;
} /* Make sure we get a name for the pin */
if (wcslen(pin->friendlyName) == 0)
{
wcscpy(pin->friendlyName, kInputName);
}
#ifdef UNICODE #ifdef UNICODE
PA_DEBUG(("PinNew: Pin name '%s'\n", pin->friendlyName)); PA_DEBUG(("PinNew: Input friendly name '%s'\n", pin->friendlyName));
#else #else
PA_DEBUG(("PinNew: Pin name '%S'\n", pin->friendlyName)); PA_DEBUG(("PinNew: Input friendly name '%S'\n", pin->friendlyName));
#endif #endif
}
/* Set endpoint pin ID (this is the topology INPUT pin, since portmixer will always traverse the
filter in audio streaming direction, see http://msdn.microsoft.com/en-us/library/windows/hardware/ff536331(v=vs.85).aspx
for more information)
*/
pin->endpointPinId = pc->Pin;
} }
else else // muxCount > 0
{ {
unsigned muxCount = 0; PA_DEBUG(("PinNew: Setting up %u inputs\n", muxCount));
int muxPos = 0;
/* Max 64 multiplexer inputs... sanity check :) */
for (i = 0; i < 64; ++i)
{
ULONG muxNodeIdTest = (unsigned)-1;
PA_DEBUG(("PinNew: Checking for input endpoint pin id (%d)...\n", i));
endpointPinId = GetConnectedPin(pc->Pin, /* Now we redo the operation once known how many multiplexer positions there are */
FALSE, pin->inputs = (PaWinWdmMuxedInput**)PaUtil_AllocateMemory(muxCount * sizeof(PaWinWdmMuxedInput*));
pin->parentFilter->topologyFilter, if (pin->inputs == NULL)
(int)i, {
NULL, FilterRelease(pin->parentFilter->topologyFilter);
&muxNodeIdTest); result = paInsufficientMemory;
goto error;
}
pin->inputCount = muxCount;
for (i = 0; i < muxCount; ++muxPos)
{
PA_DEBUG(("PinNew: Setting up input %u...\n", i));
if (endpointPinId == KSFILTER_NODE) if (pin->inputs[i] == NULL)
{ {
/* We're done */ pin->inputs[i] = (PaWinWdmMuxedInput*)PaUtil_AllocateMemory(sizeof(PaWinWdmMuxedInput));
PA_DEBUG(("PinNew: Done with inputs.\n", endpointPinId)); if (pin->inputs[i] == NULL)
break; {
FilterRelease(pin->parentFilter->topologyFilter);
result = paInsufficientMemory;
goto error;
}
} }
else
endpointPinId = GetConnectedPin(pcPin,
FALSE,
pin->parentFilter->topologyFilter,
muxPos,
&pin->inputs[i]->muxPinId,
&pin->inputs[i]->muxNodeId);
if (endpointPinId != KSFILTER_NODE)
{ {
/* The "endpointPinId" is what WASAPI looks at for pin names */ /* The "endpointPinId" is what WASAPI looks at for pin names */
GUID category = {0}; GUID category = {0};
PA_DEBUG(("PinNew: Found endpoint pin id %u\n", endpointPinId)); /* Set input endpoint ID */
pin->inputs[i]->endpointPinId = endpointPinId;
/* Get pin category information */ /* Get pin category information */
result = WdmGetPinPropertySimple(pin->parentFilter->topologyFilter->handle, result = WdmGetPinPropertySimple(pin->parentFilter->topologyFilter->handle,
...@@ -1797,146 +1928,41 @@ static PaWinWdmPin* PinNew(PaWinWdmFilter* parentFilter, unsigned long pinId, Pa ...@@ -1797,146 +1928,41 @@ static PaWinWdmPin* PinNew(PaWinWdmFilter* parentFilter, unsigned long pinId, Pa
if (result == paNoError) if (result == paNoError)
{ {
if (muxNodeIdTest == (unsigned)-1) /* Try pin name first, and if that is not defined, use category instead */
{
/* Ok, try pin name, and favor that if available */
result = WdmGetPinPropertySimple(pin->parentFilter->topologyFilter->handle,
endpointPinId,
&KSPROPSETID_Pin,
KSPROPERTY_PIN_NAME,
pin->friendlyName,
MAX_PATH,
NULL);
if (result != paNoError)
{
result = GetNameFromCategory(&category, TRUE, pin->friendlyName, MAX_PATH);
}
break;
}
else
{
result = GetNameFromCategory(&category, TRUE, NULL, 0);
if (result == paNoError)
{
++muxCount;
}
}
}
else
{
PA_DEBUG(("PinNew: Failed to get pin category"));
}
}
}
if (muxCount == 0)
{
pin->endpointPinId = endpointPinId;
/* Make sure we get a name for the pin */
if (wcslen(pin->friendlyName) == 0)
{
wcscpy(pin->friendlyName, kInputName);
}
#ifdef UNICODE
PA_DEBUG(("PinNew: Input friendly name '%s'\n", pin->friendlyName));
#else
PA_DEBUG(("PinNew: Input friendly name '%S'\n", pin->friendlyName));
#endif
}
else // muxCount > 0
{
PA_DEBUG(("PinNew: Setting up %u inputs\n", muxCount));
/* Now we redo the operation once known how many multiplexer positions there are */
pin->inputs = (PaWinWdmMuxedInput**)PaUtil_AllocateMemory(muxCount * sizeof(PaWinWdmMuxedInput*));
if (pin->inputs == NULL)
{