refactored COM initialization for dsound, asio and wasapi to new source file pa_win_coinitialize.c. fixes com uninitialisation bugs in error cases. resolves ticket #128

This commit is contained in:
rossb 2011-05-09 20:05:34 +00:00
commit 52ab9d6600
5 changed files with 301 additions and 90 deletions

View file

@ -75,6 +75,8 @@
#include "pa_debugprint.h"
#include "pa_ringbuffer.h"
#include "pa_win_coinitialize.h"
#ifndef NTDDI_VERSION
#undef WINVER
@ -370,6 +372,8 @@ typedef struct
/* implementation specific data goes here */
PaWinUtilComInitializationResult comInitializationResult;
//in case we later need the synch
IMMDeviceEnumerator *enumerator;
@ -512,8 +516,6 @@ void *PaWasapi_ReallocateMemory(void *ptr, size_t size);
void PaWasapi_FreeMemory(void *ptr);
// Local statics
static volatile BOOL g_WasapiCOMInit = FALSE;
static volatile DWORD g_WasapiInitThread = 0;
// ------------------------------------------------------------------------------------------
#define LogHostError(HRES) __LogHostError(HRES, __FUNCTION__, __FILE__, __LINE__)
@ -1057,26 +1059,6 @@ PaError PaWasapi_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiInd
return paNoError;
}
/*
If COM is already initialized CoInitialize will either return
FALSE, or RPC_E_CHANGED_MODE if it was initialised in a different
threading mode. In either case we shouldn't consider it an error
but we need to be careful to not call CoUninitialize() if
RPC_E_CHANGED_MODE was returned.
*/
hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
if (FAILED(hr) && (hr != RPC_E_CHANGED_MODE))
{
PRINT(("WASAPI: failed CoInitialize"));
return paUnanticipatedHostError;
}
if (hr != RPC_E_CHANGED_MODE)
g_WasapiCOMInit = TRUE;
// Memorize calling thread id and report warning on Uninitialize if calling thread is different
// as CoInitialize must match CoUninitialize in the same thread.
g_WasapiInitThread = GetCurrentThreadId();
paWasapi = (PaWasapiHostApiRepresentation *)PaUtil_AllocateMemory( sizeof(PaWasapiHostApiRepresentation) );
if (paWasapi == NULL)
{
@ -1084,6 +1066,12 @@ PaError PaWasapi_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiInd
goto error;
}
result = PaWinUtil_CoInitialize( paWASAPI, &paWasapi->comInitializationResult );
if( result != paNoError )
{
goto error;
}
paWasapi->allocations = PaUtil_CreateAllocationGroup();
if (paWasapi->allocations == NULL)
{
@ -1454,26 +1442,12 @@ static void Terminate( PaUtilHostApiRepresentation *hostApi )
PaUtil_DestroyAllocationGroup(paWasapi->allocations);
}
PaWinUtil_CoUninitialize( paWASAPI, &paWasapi->comInitializationResult );
PaUtil_FreeMemory(paWasapi);
// Close AVRT
CloseAVRT();
// Uninit COM (checking calling thread we won't unitialize user's COM if one is calling
// Pa_Unitialize by mistake from not initializing thread)
if (g_WasapiCOMInit)
{
DWORD calling_thread_id = GetCurrentThreadId();
if (g_WasapiInitThread != calling_thread_id)
{
PRINT(("WASAPI: failed CoUninitializes calling thread[%d] does not match initializing thread[%d]\n",
calling_thread_id, g_WasapiInitThread));
}
else
{
CoUninitialize();
}
}
}
// ------------------------------------------------------------------------------------------