[Scummvm-git-logs] scummvm master -> fc9786231cd25a7d9fc39130560d0b8bc10d7eab

sluicebox 22204938+sluicebox at users.noreply.github.com
Wed Nov 6 20:00:41 CET 2019


This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
fc9786231c TTS: Improve Windows audio, remove sphelper-scummvm.h


Commit: fc9786231cd25a7d9fc39130560d0b8bc10d7eab
    https://github.com/scummvm/scummvm/commit/fc9786231cd25a7d9fc39130560d0b8bc10d7eab
Author: sluicebox (22204938+sluicebox at users.noreply.github.com)
Date: 2019-11-06T11:00:37-08:00

Commit Message:
TTS: Improve Windows audio, remove sphelper-scummvm.h

- Remove sphelper-scummvm.h
- Use default audio quality instead of lowest
- Add HRESULT tests
- Fix new[]/free() mismatches
- Fix voice description memory leak

Changed paths:
  R backends/text-to-speech/windows/sphelper-scummvm.h
    backends/text-to-speech/windows/windows-text-to-speech.cpp


diff --git a/backends/text-to-speech/windows/sphelper-scummvm.h b/backends/text-to-speech/windows/sphelper-scummvm.h
deleted file mode 100644
index 3fc7772..0000000
--- a/backends/text-to-speech/windows/sphelper-scummvm.h
+++ /dev/null
@@ -1,2296 +0,0 @@
-// To get sphelper.h working with MinGW, several changes had to be made
-//
-// SUMMARY OF CHANGES:
-// 1. Unneeded functions got deleted
-//       SpCreateObjectFromToken
-//       SpCreateObjectFromTokenId
-//       SpCreateDefaultObjectFromCategoryId
-//       SpCreateBestObject
-//       SpCreatePhoneConverter
-//       SpBindToFile
-//       CreatePhraseFromWordArray
-//       CreatePhraseFromText
-//
-// 2. Unneeded includes got deleted
-//       crtdbg.h
-//       SPDebug.h
-//       atlbase.h
-//       sapiddk.h
-//
-// 3. Include got added
-//       cwtype
-//
-// 4. Calls to SPDBG_ASSERT() got deleted
-// 5. CComPtr<> were replaced by plain C style pointers and code that works with
-//	  these was adjusted accordingly
-// 
-// More small changes were made throughout the whole file. The best way to
-// see all changes is probably to diff this and the original file.
-/*******************************************************************************
-* SPHelper.h *
-*------------*
-*   Description:
-*       This is the header file for core helper functions implementation.
-*-------------------------------------------------------------------------------
-*   Copyright (c) Microsoft Corporation. All rights reserved.
-*******************************************************************************/
-#ifndef SPHelper_h
-#define SPHelper_h
-
-#include <iostream>
-#ifndef _INC_MALLOC
-#include <malloc.h>
-#endif
-
-#ifndef __sapi_h__
-#include <sapi.h>
-#endif
-
-#ifndef SPError_h
-#include <sperror.h>
-#endif
-
-#ifndef _INC_LIMITS
-#include <limits.h>
-#endif
-
-#ifndef _INC_MMSYSTEM
-#include <mmsystem.h>
-#endif
-
-#ifndef __comcat_h__
-#include <comcat.h>
-#endif
-
-#ifndef _INC_MMREG
-#include <mmreg.h>
-#endif
-
-#include <cwctype>
-//=== Constants ==============================================================
-#define sp_countof(x) ((sizeof(x) / sizeof(*(x))))
-
-/*** CSpDynamicString helper class
-*
-*/
-class CSpDynamicString 
-{
-public:
-
-    WCHAR *     m_psz;
-    CSpDynamicString()
-    {
-        m_psz = NULL;
-    }
-    CSpDynamicString(ULONG cchReserve)
-    {
-        m_psz = (WCHAR *)::CoTaskMemAlloc(cchReserve * sizeof(WCHAR));
-    }
-    WCHAR * operator=(const CSpDynamicString& src)
-    {
-        if (m_psz != src.m_psz)
-        {
-            ::CoTaskMemFree(m_psz);
-            m_psz = src.Copy();
-        }
-        return m_psz;
-    }
-    WCHAR * operator=(const WCHAR * pSrc)
-    {
-        Clear();
-        if (pSrc)
-        {
-            ULONG cbNeeded = (wcslen(pSrc) + 1) * sizeof(WCHAR);
-            m_psz = (WCHAR *)::CoTaskMemAlloc(cbNeeded);
-            if (m_psz)
-            {
-                memcpy(m_psz, pSrc, cbNeeded);    
-            }
-        }
-        return m_psz;
-    }
-
-    WCHAR * operator=(const char * pSrc)
-    {
-        Clear();
-        if (pSrc)
-        {
-            ULONG cbNeeded = (lstrlenA(pSrc) + 1) * sizeof(WCHAR);
-            m_psz = (WCHAR *)::CoTaskMemAlloc(cbNeeded);
-            if (m_psz)
-            {
-                ::MultiByteToWideChar(CP_ACP, 0, pSrc, -1, m_psz, cbNeeded/sizeof(WCHAR));
-            }
-        }
-        return m_psz;
-    }
-
-    WCHAR * operator=(REFGUID rguid)
-    {
-        Clear();
-        ::StringFromCLSID(rguid, &m_psz);
-        return m_psz;
-    }
-
-
-    /*explicit*/ CSpDynamicString(const WCHAR * pSrc)
-    {
-        m_psz = NULL;
-        operator=(pSrc);
-    }
-    /*explicit*/ CSpDynamicString(const char * pSrc)
-    {
-        m_psz = NULL;
-        operator=(pSrc);
-    }
-    /*explicit*/ CSpDynamicString(const CSpDynamicString& src)
-    {
-        m_psz = src.Copy();
-    }
-    /*explicit*/ CSpDynamicString(REFGUID rguid)
-    {
-        ::StringFromCLSID(rguid, &m_psz);
-    }
-
-
-    ~CSpDynamicString()
-    {
-        ::CoTaskMemFree(m_psz);
-    }
-    unsigned int Length() const
-    {
-        return (m_psz == NULL)? 0 : wcslen(m_psz);
-    }
-
-    operator WCHAR * () const
-    {
-        return m_psz;
-    }
-    //The assert on operator& usually indicates a bug.  If this is really
-    //what is needed, however, take the address of the m_psz member explicitly.
-    WCHAR ** operator&()
-    {
-        return &m_psz;
-    }
-
-    WCHAR * Append(const WCHAR * pszSrc)
-    {
-        if (pszSrc)
-        {
-            ULONG lenSrc = wcslen(pszSrc);
-            if (lenSrc)
-            {
-                ULONG lenMe = Length();
-                WCHAR *pszNew = (WCHAR *)::CoTaskMemAlloc((lenMe + lenSrc + 1) * sizeof(WCHAR));
-                if (pszNew)
-                {
-                    if (m_psz)  // Could append to an empty string so check...
-                    {
-                        if (lenMe)
-                        {
-                            memcpy(pszNew, m_psz, lenMe * sizeof(WCHAR));
-                        }
-                        ::CoTaskMemFree(m_psz);
-                    }
-                    memcpy(pszNew + lenMe, pszSrc, (lenSrc + 1) * sizeof(WCHAR));
-                    m_psz = pszNew;
-                }
-                else
-                {
-                }
-            }
-        }
-        return m_psz;
-    }
-
-    WCHAR * Append(const WCHAR * pszSrc, const ULONG lenSrc)
-    {
-        if (pszSrc && lenSrc)
-        {
-            ULONG lenMe = Length();
-            WCHAR *pszNew = (WCHAR *)::CoTaskMemAlloc((lenMe + lenSrc + 1) * sizeof(WCHAR));
-            if (pszNew)
-            {
-                if (m_psz)  // Could append to an empty string so check...
-                {
-                    if (lenMe)
-                    {
-                        memcpy(pszNew, m_psz, lenMe * sizeof(WCHAR));
-                    }
-                    ::CoTaskMemFree(m_psz);
-                }
-                memcpy(pszNew + lenMe, pszSrc, lenSrc * sizeof(WCHAR));
-                *(pszNew + lenMe + lenSrc) = L'\0';
-                m_psz = pszNew;
-            }
-            else
-            {
-            }
-        }
-        return m_psz;
-    }
-
-    WCHAR * Append2(const WCHAR * pszSrc1, const WCHAR * pszSrc2)
-    {
-        ULONG lenSrc1 = pszSrc1 ? wcslen(pszSrc1) : 0;
-        ULONG lenSrc2 = pszSrc2 ? wcslen(pszSrc2) : 0;
-
-        if (lenSrc1 || lenSrc2)
-        {
-            ULONG lenMe = Length();
-            WCHAR *pszNew = (WCHAR *)::CoTaskMemAlloc((lenMe + lenSrc1 + lenSrc2 + 1) * sizeof(WCHAR));
-            if (pszNew)
-            {
-                if (m_psz)  // Could append to an empty string so check...
-                {
-                    if (lenMe)
-                    {
-                        memcpy(pszNew, m_psz, lenMe * sizeof(WCHAR));
-                    }
-                    ::CoTaskMemFree(m_psz);
-                }
-                // In both of these cases, we copy the trailing NULL so that we're sure it gets
-                // there (if lenSrc2 is 0 then we better copy it from pszSrc1).
-                if (lenSrc1)
-                {
-                    memcpy(pszNew + lenMe, pszSrc1, (lenSrc1 + 1) * sizeof(WCHAR));
-                }
-                if (lenSrc2)
-                {
-                    memcpy(pszNew + lenMe + lenSrc1, pszSrc2, (lenSrc2 + 1) * sizeof(WCHAR));
-                }
-                m_psz = pszNew;
-            }
-            else
-            {
-            }
-        }
-        return m_psz;
-    }
-    WCHAR * Copy() const
-    {
-        if (m_psz)
-        {
-            CSpDynamicString szNew(m_psz);
-            return szNew.Detach();
-        }
-        return NULL;
-    }
-    CHAR * CopyToChar() const
-    {
-        if (m_psz)
-        {
-            CHAR* psz;
-            ULONG cbNeeded = ::WideCharToMultiByte(CP_ACP, 0, m_psz, -1, NULL, NULL, NULL, NULL);
-            psz = (CHAR *)::CoTaskMemAlloc(cbNeeded);
-            if (psz)
-            {
-                ::WideCharToMultiByte(CP_ACP, 0, m_psz, -1, psz, cbNeeded/sizeof(CHAR), NULL, NULL);
-            }
-            return psz;
-        }
-        return NULL;
-    }
-    void Attach(WCHAR * pszSrc)
-    {
-        m_psz = pszSrc;
-    }
-    WCHAR * Detach()
-    {
-        WCHAR * s = m_psz;
-        m_psz = NULL;
-        return s;
-    }
-    void Clear()
-    {
-        ::CoTaskMemFree(m_psz);
-        m_psz = NULL;
-    }
-    bool operator!() const
-    {
-        return (m_psz == NULL);
-    }
-    HRESULT CopyToBSTR(BSTR * pbstr)
-    {
-        if (m_psz)
-        {
-            *pbstr = ::SysAllocString(m_psz);
-            if (*pbstr == NULL)
-            {
-                return E_OUTOFMEMORY;
-            }
-        }
-        else
-        {
-            *pbstr = NULL;
-        }
-        return S_OK;
-    }
-    void TrimToSize(ULONG ulNumChars)
-    {
-        if (m_psz && ulNumChars < Length())
-        {
-            m_psz[ulNumChars] = 0;
-        }
-    }
-    WCHAR * Compact()
-    {
-        if (m_psz)
-        {
-            ULONG cch = wcslen(m_psz);
-            m_psz = (WCHAR *)::CoTaskMemRealloc(m_psz, (cch + 1) * sizeof(WCHAR));
-        }
-        return m_psz;
-    }
-    WCHAR * ClearAndGrowTo(ULONG cch)
-    {
-        if (m_psz)
-        {
-            Clear();
-        }
-        m_psz = (WCHAR *)::CoTaskMemAlloc(cch * sizeof(WCHAR));
-        return m_psz;
-    }
-    WCHAR * LTrim()
-    {
-        if (m_psz)
-        {
-            WCHAR * pszRead = m_psz;
-            while (iswspace(*pszRead))
-            {
-                pszRead++;
-            }
-            if (pszRead != m_psz)
-            {
-                WCHAR * pszWrite = m_psz;
-                while (*pszRead)
-                {
-                    *pszWrite++ = *pszRead++;
-                }
-                *pszWrite = '\0';
-            }
-        }
-        return m_psz;
-    }
-    WCHAR * RTrim()
-    {
-        if (m_psz)
-        {
-            WCHAR * pszTail = m_psz + wcslen(m_psz);
-            WCHAR * pszZeroTerm = pszTail;
-            while (pszZeroTerm > m_psz && iswspace(pszZeroTerm[-1]))
-            {
-                pszZeroTerm--;
-            }
-            if (pszZeroTerm != pszTail)
-            {
-                *pszZeroTerm = '\0';
-            }
-        }
-        return m_psz;        
-    }
-    WCHAR * TrimBoth()
-    {
-        RTrim();
-        return LTrim();
-    }
-};
-
-
-
-//
-//  Simple inline function converts a ulong to a hex string.
-//
-inline void SpHexFromUlong(WCHAR * psz, ULONG ul)
-{
-    const static WCHAR szHexChars[] = L"0123456789ABCDEF";
-    if (ul == 0)
-    {
-        psz[0] = L'0';
-        psz[1] = 0;
-    }
-    else
-    {
-        ULONG ulChars = 1;
-        psz[0] = 0;
-        while (ul)
-        {
-            memmove(psz + 1, psz, ulChars * sizeof(WCHAR));
-            psz[0] = szHexChars[ul % 16];
-            ul /= 16;
-            ulChars++;
-        }
-    }
-}
-
-
-//=== Token helpers
-
-inline HRESULT SpGetTokenFromId(
-    const WCHAR * pszTokenId, 
-    ISpObjectToken ** ppToken,
-    BOOL fCreateIfNotExist = FALSE)
-{
-    
-    LPUNKNOWN pUnkOuter = nullptr;
-    HRESULT hr = ::CoCreateInstance(CLSID_SpObjectToken, pUnkOuter, CLSCTX_ALL, IID_ISpObjectToken,reinterpret_cast<void **>(ppToken));
-    
-    if (SUCCEEDED(hr))
-    {
-        (*ppToken)->SetId(NULL, pszTokenId, fCreateIfNotExist);
-    }
-    
-    return hr;
-}
-
-inline HRESULT SpGetCategoryFromId(
-    const WCHAR * pszCategoryId,
-    ISpObjectTokenCategory ** ppCategory,
-    BOOL fCreateIfNotExist = FALSE)
-{
-    LPUNKNOWN pUnkOuter = nullptr;
-    HRESULT hr = ::CoCreateInstance(CLSID_SpObjectTokenCategory, pUnkOuter, CLSCTX_ALL, IID_ISpObjectTokenCategory, reinterpret_cast<void **>(ppCategory));
-    
-    if (SUCCEEDED(hr))
-    {
-        hr = (*ppCategory)->SetId(pszCategoryId, fCreateIfNotExist);
-    }
-    
-    return hr;
-}
-
-inline HRESULT SpGetDefaultTokenIdFromCategoryId(
-    const WCHAR * pszCategoryId,
-    WCHAR ** ppszTokenId)
-{
-    HRESULT hr;
-
-    ISpObjectTokenCategory *cpCategory;
-    hr = SpGetCategoryFromId(pszCategoryId, &cpCategory);
-    
-    if (SUCCEEDED(hr))
-    {
-        hr = cpCategory->GetDefaultTokenId(ppszTokenId);
-    }
-
-    return hr;
-}
-
-inline HRESULT SpSetDefaultTokenIdForCategoryId(
-    const WCHAR * pszCategoryId,
-    const WCHAR * pszTokenId)
-{
-    HRESULT hr;
-
-    ISpObjectTokenCategory *cpCategory;
-    hr = SpGetCategoryFromId(pszCategoryId, &cpCategory);
-    
-    if (SUCCEEDED(hr))
-    {
-        hr = cpCategory->SetDefaultTokenId(pszTokenId);
-    }
-
-    return hr;
-}
-
-inline HRESULT SpGetDefaultTokenFromCategoryId(
-    const WCHAR * pszCategoryId,
-    ISpObjectToken ** ppToken,
-    BOOL fCreateCategoryIfNotExist = TRUE)
-{
-    HRESULT hr;
-
-    ISpObjectTokenCategory *cpCategory;
-    hr = SpGetCategoryFromId(pszCategoryId, &cpCategory, fCreateCategoryIfNotExist);
-
-    if (SUCCEEDED(hr))
-    {
-        WCHAR * pszTokenId;
-        hr = cpCategory->GetDefaultTokenId(&pszTokenId);
-        if (SUCCEEDED(hr))
-        {
-            hr = SpGetTokenFromId(pszTokenId, ppToken);
-            ::CoTaskMemFree(pszTokenId);
-        }
-    }
-
-    return hr;
-}
-
-inline HRESULT SpSetDefaultTokenForCategoryId(
-    const WCHAR * pszCategoryId,
-    ISpObjectToken * pToken)
-{
-    HRESULT hr;
-
-    WCHAR * pszTokenId;
-    hr = pToken->GetId(&pszTokenId);
-
-    if (SUCCEEDED(hr))
-    {
-        hr = SpSetDefaultTokenIdForCategoryId(pszCategoryId, pszTokenId);
-        ::CoTaskMemFree(pszTokenId);
-    }
-
-    return hr;
-}
-
-inline HRESULT SpSetCommonTokenData(
-    ISpObjectToken * pToken,
-    const CLSID * pclsid,
-    const WCHAR * pszLangIndependentName,
-    LANGID langid,
-    const WCHAR * pszLangDependentName,
-    ISpDataKey ** ppDataKeyAttribs)
-{
-    HRESULT hr = S_OK;
-    
-    // Set the new token's CLSID (if specified)
-    if (SUCCEEDED(hr) && pclsid)
-    {
-        CSpDynamicString dstrClsid;
-        hr = StringFromCLSID(*pclsid, &dstrClsid);
-    
-        if (SUCCEEDED(hr))
-        {
-            hr = pToken->SetStringValue(SPTOKENVALUE_CLSID, dstrClsid);
-        }
-    }
-
-    // Set the token's lang independent name
-    if (SUCCEEDED(hr) && pszLangIndependentName)
-    {
-        hr = pToken->SetStringValue(NULL, pszLangIndependentName);
-    }
-
-    // Set the token's lang dependent name
-    if (SUCCEEDED(hr) && pszLangDependentName)
-    {
-	    WCHAR szLangId[10];
-	    SpHexFromUlong(szLangId, langid);
-	    
-        hr = pToken->SetStringValue(szLangId, pszLangDependentName);
-    }
-
-    // Open the attributes key if requested
-    if (SUCCEEDED(hr) && ppDataKeyAttribs)
-    {
-        hr = pToken->CreateKey(L"Attributes", ppDataKeyAttribs);
-    }
-
-    return hr;
-}
-
-inline HRESULT SpCreateNewToken(
-    const WCHAR * pszTokenId,
-    ISpObjectToken ** ppToken)
-{
-    HRESULT hr;
-
-    // Forcefully create the token
-    hr = SpGetTokenFromId(pszTokenId, ppToken, TRUE);
-    
-    return hr;
-}
-
-inline HRESULT SpCreateNewToken(
-    const WCHAR * pszCategoryId,
-    const WCHAR * pszTokenKeyName,
-    ISpObjectToken ** ppToken)
-{
-    HRESULT hr;
-
-    // Forcefully create the category
-    ISpObjectTokenCategory *cpCategory;
-    hr = SpGetCategoryFromId(pszCategoryId, &cpCategory, TRUE);
-
-    // Come up with a token key name if one wasn't specified
-    CSpDynamicString dstrTokenKeyName;
-    if (SUCCEEDED(hr))
-    {
-        if (pszTokenKeyName == NULL)
-        {
-            GUID guidTokenKeyName;
-            hr = CoCreateGuid(&guidTokenKeyName);
-
-            if (SUCCEEDED(hr))
-            {
-                hr = StringFromCLSID(guidTokenKeyName, &dstrTokenKeyName);
-            }
-
-            if (SUCCEEDED(hr))
-            {
-                pszTokenKeyName = dstrTokenKeyName;
-            }
-        }
-    }
-
-    // Build the token id
-    CSpDynamicString dstrTokenId;
-    if (SUCCEEDED(hr))
-    {
-        dstrTokenId = pszCategoryId;
-        dstrTokenId.Append2(L"\\Tokens\\", pszTokenKeyName);
-    }
-
-    // Forcefully create the token
-    if (SUCCEEDED(hr))
-    {
-        hr = SpGetTokenFromId(dstrTokenId, ppToken, TRUE);
-    }
-    
-    return hr;
-}
-
-inline HRESULT SpCreateNewTokenEx(
-    const WCHAR * pszCategoryId,
-    const WCHAR * pszTokenKeyName,
-    const CLSID * pclsid,
-    const WCHAR * pszLangIndependentName,
-    LANGID langid,
-    const WCHAR * pszLangDependentName,
-    ISpObjectToken ** ppToken,
-    ISpDataKey ** ppDataKeyAttribs)
-{
-    HRESULT hr;
-
-    // Create the new token
-    hr = SpCreateNewToken(pszCategoryId, pszTokenKeyName, ppToken);
-
-    // Now set the extra data
-    if (SUCCEEDED(hr))
-    {
-        hr = SpSetCommonTokenData(
-                    *ppToken, 
-                    pclsid, 
-                    pszLangIndependentName, 
-                    langid, 
-                    pszLangDependentName, 
-                    ppDataKeyAttribs);
-    }
-    
-    return hr;
-}
-
-inline HRESULT SpCreateNewTokenEx(
-    const WCHAR * pszTokenId,
-    const CLSID * pclsid,
-    const WCHAR * pszLangIndependentName,
-    LANGID langid,
-    const WCHAR * pszLangDependentName,
-    ISpObjectToken ** ppToken,
-    ISpDataKey ** ppDataKeyAttribs)
-{
-    HRESULT hr;
-
-    // Create the new token
-    hr = SpCreateNewToken(pszTokenId, ppToken);
-
-    // Now set the extra data
-    if (SUCCEEDED(hr))
-    {
-        hr = SpSetCommonTokenData(
-                    *ppToken, 
-                    pclsid, 
-                    pszLangIndependentName, 
-                    langid, 
-                    pszLangDependentName, 
-                    ppDataKeyAttribs);
-    }
-    
-    return hr;
-}
-
-inline HRESULT SpEnumTokens(
-    const WCHAR * pszCategoryId, 
-    const WCHAR * pszReqAttribs, 
-    const WCHAR * pszOptAttribs, 
-    IEnumSpObjectTokens ** ppEnum)
-{
-    HRESULT hr = S_OK;
-    
-    ISpObjectTokenCategory *cpCategory;
-    hr = SpGetCategoryFromId(pszCategoryId, &cpCategory);
-    
-    if (SUCCEEDED(hr))
-    {
-        hr = cpCategory->EnumTokens(
-                    pszReqAttribs,
-                    pszOptAttribs,
-                    ppEnum);
-    }
-    
-    return hr;
-}
-
-inline HRESULT SpFindBestToken(
-    const WCHAR * pszCategoryId, 
-    const WCHAR * pszReqAttribs, 
-    const WCHAR * pszOptAttribs, 
-    ISpObjectToken **ppObjectToken)
-{
-    HRESULT hr = S_OK;
-    
-    const WCHAR *pszVendorPreferred = L"VendorPreferred";
-    const unsigned long LenVendorPreferred = wcslen(pszVendorPreferred);
-
-    // append VendorPreferred to the end of pszOptAttribs to force this preference
-    ULONG ulLen = pszOptAttribs ? wcslen(pszOptAttribs) + LenVendorPreferred + 1 : LenVendorPreferred;
-    WCHAR *pszOptAttribsVendorPref = (WCHAR*)_alloca((ulLen+1)*sizeof(WCHAR));
-    if (pszOptAttribsVendorPref)
-    {
-        if (pszOptAttribs)
-        {
-            wcscpy(pszOptAttribsVendorPref, pszOptAttribs);
-            wcscat(pszOptAttribsVendorPref, L";");
-            wcscat(pszOptAttribsVendorPref, pszVendorPreferred);
-        }
-        else
-        {
-            wcscpy(pszOptAttribsVendorPref, pszVendorPreferred);
-        }
-    }
-    else
-    {
-        hr = E_OUTOFMEMORY;
-    }
-
-    IEnumSpObjectTokens *cpEnum;
-    if (SUCCEEDED(hr))
-    {
-        hr = SpEnumTokens(pszCategoryId, pszReqAttribs, pszOptAttribsVendorPref, &cpEnum);
-    }
-
-    if (SUCCEEDED(hr))
-    {
-        hr = cpEnum->Next(1, ppObjectToken, NULL);
-        if (hr == S_FALSE)
-        {
-            *ppObjectToken = NULL;
-            hr = SPERR_NOT_FOUND;
-        }
-    }
-
-    if (hr != SPERR_NOT_FOUND)
-    {
-    }
-    
-    return hr;
-}
-
-
-/****************************************************************************
-* SpHrFromWin32 *
-*---------------*
-*   Description:
-*       This inline function works around a basic problem with the macro
-*   HRESULT_FROM_WIN32.  The macro forces the expresion in ( ) to be evaluated
-*   two times.  By using this inline function, the expression will only be
-*   evaluated once.
-*
-*   Returns:
-*       HRESULT of converted Win32 error code
-*
-*****************************************************************************/
-
-inline HRESULT SpHrFromWin32(DWORD dwErr)
-{
-    return HRESULT_FROM_WIN32(dwErr);
-}
-
-
-/****************************************************************************
-* SpHrFromLastWin32Error *
-*------------------------*
-*   Description:
-*       This simple inline function is used to return a converted HRESULT
-*   from the Win32 function ::GetLastError.  Note that using HRESULT_FROM_WIN32
-*   will evaluate the error code twice so we don't want to use:
-*
-*       HRESULT_FROM_WIN32(::GetLastError()) 
-*
-*   since that will call GetLastError twice.
-*   On Win98 and WinMe ::GetLastError() returns 0 for some functions (see MSDN).
-*   We therefore check for that and return E_FAIL. This function should only be
-*   called in an error case since it will always return an error code!
-*
-*   Returns:
-*       HRESULT for ::GetLastError()
-*
-*****************************************************************************/
-
-inline HRESULT SpHrFromLastWin32Error()
-{
-    DWORD dw = ::GetLastError();
-    return (dw == 0) ? E_FAIL : SpHrFromWin32(dw);
-}
-
-
-/****************************************************************************
-* SpGetUserDefaultUILanguage *
-*----------------------------*
-*   Description:
-*       Returns the default user interface language, using a method 
-*       appropriate to the platform (Windows 9x, Windows NT, or Windows 2000)
-*
-*   Returns:
-*       Default UI language
-*
-*****************************************************************************/
-
-inline LANGID SpGetUserDefaultUILanguage(void) 
-{
-    HRESULT hr = S_OK;
-    LANGID wUILang = 0;
-
-    OSVERSIONINFO Osv ;
-    Osv.dwOSVersionInfoSize = sizeof(Osv) ;
-    if(!GetVersionEx(&Osv)) 
-    {
-        hr = SpHrFromLastWin32Error();
-    }
-    // Get the UI language by one of three methods, depending on the system
-    else if(Osv.dwPlatformId != VER_PLATFORM_WIN32_NT) 
-    {
-        // Case 1: Running on Windows 9x. Get the system UI language from registry:
-        CHAR szData[32];
-        DWORD dwSize = sizeof(szData) ;
-        HKEY hKey;
-
-        long lRet = RegOpenKeyEx(
-                        HKEY_USERS, 
-                        ".Default\\Control Panel\\desktop\\ResourceLocale", 
-                        0, 
-                        KEY_READ, 
-                        &hKey);
-
-#ifdef _WIN32_WCE_BUG_10655
-        if (lRet == ERROR_INVALID_PARAMETER)
-        {
-            lRet = ERROR_FILE_NOT_FOUND;
-        }
-#endif // _WIN32_WCE_BUG_10655
-
-        hr = SpHrFromWin32(lRet);
-
-        if (SUCCEEDED(hr))
-        {
-            lRet = RegQueryValueEx(  
-                        hKey, 
-                        "", 
-                        NULL, 
-                        NULL, 
-                        (BYTE *)szData, 
-                        &dwSize);
-
-#ifdef _WIN32_WCE_BUG_10655
-            if(lRet == ERROR_INVALID_PARAMETER)
-            {
-                lRet = ERROR_FILE_NOT_FOUND;
-            }
-#endif //_WIN32_WCE_BUG_10655
-
-            hr = SpHrFromWin32(lRet); 
-            ::RegCloseKey(hKey) ;
-        }
-        if (SUCCEEDED(hr))
-        {
-            // Convert string to number
-            wUILang = (LANGID) strtol(szData, NULL, 16) ;
-        }
-    }
-    else if (Osv.dwMajorVersion >= 5.0) 
-    {
-    // Case 2: Running on Windows 2000 or later. Use GetUserDefaultUILanguage to find 
-    // the user's prefered UI language
-
-
-        HMODULE hMKernel32 = ::LoadLibraryW(L"kernel32.dll") ;
-        if (hMKernel32 == NULL)
-        {
-            hr = SpHrFromLastWin32Error();
-        }
-        else
-        {
-
-            LANGID (WINAPI *pfnGetUserDefaultUILanguage) () = 
-                (LANGID (WINAPI *)(void)) 
-#ifdef _WIN32_WCE
-                    GetProcAddress(hMKernel32, L"GetUserDefaultUILanguage") ;
-#else
-                    GetProcAddress(hMKernel32, "GetUserDefaultUILanguage") ;
-#endif
-
-            if(NULL != pfnGetUserDefaultUILanguage) 
-            {
-                wUILang = pfnGetUserDefaultUILanguage() ;
-            }
-            else
-            {   // GetProcAddress failed
-                hr = SpHrFromLastWin32Error();
-            }
-            ::FreeLibrary(hMKernel32);
-        }
-    }
-    else {
-    // Case 3: Running on Windows NT 4.0 or earlier. Get UI language
-    // from locale of .default user in registry:
-    // HKEY_USERS\.DEFAULT\Control Panel\International\Locale
-        
-        WCHAR szData[32]   ;
-        DWORD dwSize = sizeof(szData) ;
-        HKEY hKey          ;
-
-        LONG lRet = RegOpenKeyEx(HKEY_USERS, 
-                                    ".DEFAULT\\Control Panel\\International", 
-                                    0, 
-                                    KEY_READ, 
-                                    &hKey);
-#ifdef _WIN32_WCE_BUG_10655
-            if(lRet == ERROR_INVALID_PARAMETER)
-            {
-                lRet = ERROR_FILE_NOT_FOUND;
-            }
-#endif //_WIN32_WCE_BUG_10655
-
-        hr = SpHrFromWin32(lRet);
-
-        if (SUCCEEDED(hr))
-        {
-            lRet = RegQueryValueEx(  
-                        hKey, 
-                        "Locale",
-                        NULL, 
-                        NULL, 
-                        (BYTE *)szData, 
-                        &dwSize);
-
-#ifdef _WIN32_WCE_BUG_10655
-            if(lRet == ERROR_INVALID_PARAMETER)
-            {
-                lRet = ERROR_FILE_NOT_FOUND;
-            }
-#endif //_WIN32_WCE_BUG_10655
-
-        hr = SpHrFromWin32(lRet);
-            ::RegCloseKey(hKey);
-        }
-
-        if (SUCCEEDED(hr))
-        {
-            // Convert string to number
-            wUILang = (LANGID) wcstol(szData, NULL, 16) ;
-
-            if(0x0401 == wUILang || // Arabic
-               0x040d == wUILang || // Hebrew
-               0x041e == wUILang    // Thai
-               )
-            {
-                // Special case these to the English UI.
-                // These versions of Windows NT 4.0 were enabled only, i.e., the
-                // UI was English. However, the registry setting 
-                // HKEY_USERS\.DEFAULT\Control Panel\International\Locale was set  
-                // to the respective locale for application compatibility.
-                wUILang = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US) ;
-            }
-        }
-    }
-
-    return (wUILang ? wUILang : ::GetUserDefaultLangID());    // In failure case, try our best!
-}
-
-
-inline HRESULT SpGetDescription(ISpObjectToken * pObjToken, WCHAR ** ppszDescription, LANGID Language = SpGetUserDefaultUILanguage())
-{
-    WCHAR szLangId[10];
-    SpHexFromUlong(szLangId, Language);
-    HRESULT hr = pObjToken->GetStringValue(szLangId, ppszDescription);
-    if (hr == SPERR_NOT_FOUND)
-    {
-        hr = pObjToken->GetStringValue(NULL, ppszDescription);
-    }
-    return hr;
-}
-
-
-inline HRESULT SpSetDescription(ISpObjectToken * pObjToken, const WCHAR * pszDescription, LANGID Language = SpGetUserDefaultUILanguage(), BOOL fSetLangIndependentId = TRUE)
-{
-    WCHAR szLangId[10];
-    SpHexFromUlong(szLangId, Language);
-    HRESULT hr = pObjToken->SetStringValue(szLangId, pszDescription);
-    if (SUCCEEDED(hr) && fSetLangIndependentId)
-    {
-        hr = pObjToken->SetStringValue(NULL, pszDescription);
-    }
-    return hr;
-}
-
-/****************************************************************************
-* SpConvertStreamFormatEnum *
-*---------------------------*
-*   Description:
-*       This method converts the specified stream format into a wave format
-*   structure.
-*
-*****************************************************************************/
-inline HRESULT SpConvertStreamFormatEnum(SPSTREAMFORMAT eFormat, GUID * pFormatId, WAVEFORMATEX ** ppCoMemWaveFormatEx)
-{
-    HRESULT hr = S_OK;
-
-    if(pFormatId==NULL || ::IsBadWritePtr(pFormatId, sizeof(*pFormatId))
-        || ppCoMemWaveFormatEx==NULL || ::IsBadWritePtr(ppCoMemWaveFormatEx, sizeof(*ppCoMemWaveFormatEx)))
-    {
-        return E_INVALIDARG;
-    }
-
-    const GUID * pFmtGuid = &GUID_NULL;     // Assume failure case
-    if( eFormat >= SPSF_8kHz8BitMono && eFormat <= SPSF_48kHz16BitStereo )
-    {
-        WAVEFORMATEX * pwfex = (WAVEFORMATEX *)::CoTaskMemAlloc(sizeof(WAVEFORMATEX));
-        *ppCoMemWaveFormatEx = pwfex;
-        if (pwfex)
-        {
-            DWORD dwIndex = eFormat - SPSF_8kHz8BitMono;
-            BOOL bIsStereo = dwIndex & 0x1;
-            BOOL bIs16 = dwIndex & 0x2;
-            DWORD dwKHZ = (dwIndex & 0x3c) >> 2;
-            static const DWORD adwKHZ[] = { 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000 };
-            pwfex->wFormatTag = WAVE_FORMAT_PCM;
-            pwfex->nChannels = pwfex->nBlockAlign = (WORD)(bIsStereo ? 2 : 1);
-            pwfex->nSamplesPerSec = adwKHZ[dwKHZ];
-            pwfex->wBitsPerSample = 8;
-            if (bIs16)
-            {
-                pwfex->wBitsPerSample *= 2;
-                pwfex->nBlockAlign *= 2;
-            }
-                pwfex->nAvgBytesPerSec = pwfex->nSamplesPerSec * pwfex->nBlockAlign;
-            pwfex->cbSize = 0;
-            pFmtGuid = &SPDFID_WaveFormatEx;
-        }
-        else
-        {
-            hr = E_OUTOFMEMORY;
-        }
-    }
-    else if( eFormat == SPSF_TrueSpeech_8kHz1BitMono )
-    {
-        int NumBytes = sizeof( WAVEFORMATEX ) + 32;
-        WAVEFORMATEX * pwfex = (WAVEFORMATEX *)::CoTaskMemAlloc( NumBytes );
-        *ppCoMemWaveFormatEx = pwfex;
-        if( pwfex )
-        {
-            memset( pwfex, 0, NumBytes );
-            pwfex->wFormatTag      = WAVE_FORMAT_DSPGROUP_TRUESPEECH;
-            pwfex->nChannels       = 1;
-            pwfex->nSamplesPerSec  = 8000;
-            pwfex->nAvgBytesPerSec = 1067;
-            pwfex->nBlockAlign     = 32;
-            pwfex->wBitsPerSample  = 1;
-            pwfex->cbSize          = 32;
-            BYTE* pExtra = ((BYTE*)pwfex) + sizeof( WAVEFORMATEX );
-            pExtra[0] = 1;
-            pExtra[2] = 0xF0;
-            pFmtGuid = &SPDFID_WaveFormatEx;
-        }
-        else
-        {
-            hr = E_OUTOFMEMORY;
-        }
-    }
-    else if( (eFormat >= SPSF_CCITT_ALaw_8kHzMono    ) &&
-             (eFormat <= SPSF_CCITT_ALaw_44kHzStereo ) )
-    {
-        WAVEFORMATEX * pwfex = (WAVEFORMATEX *)::CoTaskMemAlloc( sizeof(WAVEFORMATEX) );
-        *ppCoMemWaveFormatEx = pwfex;
-        if( pwfex )
-        {
-            memset( pwfex, 0, sizeof(WAVEFORMATEX) );
-            DWORD dwIndex = eFormat - SPSF_CCITT_ALaw_8kHzMono;
-            DWORD dwKHZ = dwIndex / 2;
-            static const DWORD adwKHZ[] = { 8000, 11025, 22050, 44100 };
-            BOOL bIsStereo    = dwIndex & 0x1;
-            pwfex->wFormatTag = WAVE_FORMAT_ALAW;
-            pwfex->nChannels  = pwfex->nBlockAlign = (WORD)(bIsStereo ? 2 : 1);
-            pwfex->nSamplesPerSec  = adwKHZ[dwKHZ];
-            pwfex->wBitsPerSample  = 8;
-                pwfex->nAvgBytesPerSec = pwfex->nSamplesPerSec * pwfex->nBlockAlign;
-            pwfex->cbSize          = 0;
-            pFmtGuid = &SPDFID_WaveFormatEx;
-        }
-        else
-        {
-            hr = E_OUTOFMEMORY;
-        }
-    }
-    else if( (eFormat >= SPSF_CCITT_uLaw_8kHzMono    ) &&
-             (eFormat <= SPSF_CCITT_uLaw_44kHzStereo ) )
-    {
-        WAVEFORMATEX * pwfex = (WAVEFORMATEX *)::CoTaskMemAlloc( sizeof(WAVEFORMATEX) );
-        *ppCoMemWaveFormatEx = pwfex;
-        if( pwfex )
-        {
-            memset( pwfex, 0, sizeof(WAVEFORMATEX) );
-            DWORD dwIndex = eFormat - SPSF_CCITT_uLaw_8kHzMono;
-            DWORD dwKHZ = dwIndex / 2;
-            static const DWORD adwKHZ[] = { 8000, 11025, 22050, 44100 };
-            BOOL bIsStereo    = dwIndex & 0x1;
-            pwfex->wFormatTag = WAVE_FORMAT_MULAW;
-            pwfex->nChannels  = pwfex->nBlockAlign = (WORD)(bIsStereo ? 2 : 1);
-            pwfex->nSamplesPerSec  = adwKHZ[dwKHZ];
-            pwfex->wBitsPerSample  = 8;
-                pwfex->nAvgBytesPerSec = pwfex->nSamplesPerSec * pwfex->nBlockAlign;
-            pwfex->cbSize          = 0;
-            pFmtGuid = &SPDFID_WaveFormatEx;
-        }
-        else
-        {
-            hr = E_OUTOFMEMORY;
-        }
-    }
-    else if( (eFormat >= SPSF_ADPCM_8kHzMono    ) &&
-             (eFormat <= SPSF_ADPCM_44kHzStereo ) )
-    {
-        int NumBytes = sizeof( WAVEFORMATEX ) + 32;
-        WAVEFORMATEX * pwfex = (WAVEFORMATEX *)::CoTaskMemAlloc( NumBytes );
-        *ppCoMemWaveFormatEx = pwfex;
-        if( pwfex )
-        {
-            //--- Some of these values seem odd. We used what the codec told us.
-            static const DWORD adwKHZ[] = { 8000, 11025, 22050, 44100 };
-            static const DWORD BytesPerSec[] = { 4096, 8192, 5644, 11289, 11155, 22311, 22179, 44359 };
-            static const DWORD BlockAlign[]  = { 256, 256, 512, 1024 };
-            static const BYTE Extra811[32] =
-            {
-                0xF4, 0x01, 0x07, 0x00, 0x00, 0x01, 0x00, 0x00,
-                0x00, 0x02, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00,
-                0xC0, 0x00, 0x40, 0x00, 0xF0, 0x00, 0x00, 0x00,
-                0xCC, 0x01, 0x30, 0xFF, 0x88, 0x01, 0x18, 0xFF
-            };
-
-            static const BYTE Extra22[32] =
-            {
-                0xF4, 0x03, 0x07, 0x00, 0x00, 0x01, 0x00, 0x00,
-                0x00, 0x02, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00,
-                0xC0, 0x00, 0x40, 0x00, 0xF0, 0x00, 0x00, 0x00,
-                0xCC, 0x01, 0x30, 0xFF, 0x88, 0x01, 0x18, 0xFF
-            };
-
-            static const BYTE Extra44[32] =
-            {
-                0xF4, 0x07, 0x07, 0x00, 0x00, 0x01, 0x00, 0x00,
-                0x00, 0x02, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00,
-                0xC0, 0x00, 0x40, 0x00, 0xF0, 0x00, 0x00, 0x00,
-                0xCC, 0x01, 0x30, 0xFF, 0x88, 0x01, 0x18, 0xFF
-            };
-
-            static const BYTE* Extra[4] = { Extra811, Extra811, Extra22, Extra44 };
-            memset( pwfex, 0, NumBytes );
-            DWORD dwIndex  = eFormat - SPSF_ADPCM_8kHzMono;
-            DWORD dwKHZ    = dwIndex / 2;
-            BOOL bIsStereo = dwIndex & 0x1;
-            pwfex->wFormatTag      = WAVE_FORMAT_ADPCM;
-            pwfex->nChannels       = (WORD)(bIsStereo ? 2 : 1);
-            pwfex->nSamplesPerSec  = adwKHZ[dwKHZ];
-            pwfex->nAvgBytesPerSec = BytesPerSec[dwIndex];
-            pwfex->nBlockAlign     = (WORD)(BlockAlign[dwKHZ] * pwfex->nChannels);
-            pwfex->wBitsPerSample  = 4;
-            pwfex->cbSize          = 32;
-            BYTE* pExtra = ((BYTE*)pwfex) + sizeof( WAVEFORMATEX );
-            memcpy( pExtra, Extra[dwKHZ], 32 );
-            pFmtGuid = &SPDFID_WaveFormatEx;
-        }
-        else
-        {
-            hr = E_OUTOFMEMORY;
-        }
-    }
-    else if( (eFormat >= SPSF_GSM610_8kHzMono    ) &&
-             (eFormat <= SPSF_GSM610_44kHzMono ) )
-    {
-        int NumBytes = sizeof( WAVEFORMATEX ) + 2;
-        WAVEFORMATEX * pwfex = (WAVEFORMATEX *)::CoTaskMemAlloc( NumBytes );
-        *ppCoMemWaveFormatEx = pwfex;
-        if( pwfex )
-        {
-            //--- Some of these values seem odd. We used what the codec told us.
-            static const DWORD adwKHZ[] = { 8000, 11025, 22050, 44100 };
-            static const DWORD BytesPerSec[] = { 1625, 2239, 4478, 8957 };
-            memset( pwfex, 0, NumBytes );
-            DWORD dwIndex          = eFormat - SPSF_GSM610_8kHzMono;
-            pwfex->wFormatTag      = WAVE_FORMAT_GSM610;
-            pwfex->nChannels       = 1;
-            pwfex->nSamplesPerSec  = adwKHZ[dwIndex];
-            pwfex->nAvgBytesPerSec = BytesPerSec[dwIndex];
-            pwfex->nBlockAlign     = 65;
-            pwfex->wBitsPerSample  = 0;
-            pwfex->cbSize          = 2;
-            BYTE* pExtra = ((BYTE*)pwfex) + sizeof( WAVEFORMATEX );
-            pExtra[0] = 0x40;
-            pExtra[1] = 0x01;
-            pFmtGuid = &SPDFID_WaveFormatEx;
-        }
-        else
-        {
-            hr = E_OUTOFMEMORY;
-        }
-    }
-    else
-    {
-        *ppCoMemWaveFormatEx = NULL;
-        switch (eFormat)
-        {
-        case SPSF_NoAssignedFormat:
-            break;
-        case SPSF_Text:
-            pFmtGuid = &SPDFID_Text;
-            break;
-        default:
-            hr = E_INVALIDARG;
-            break;
-        }
-    }
-    *pFormatId = *pFmtGuid;
-    return hr;
-}
-
-class CSpStreamFormat
-{
-public:
-    GUID            m_guidFormatId;
-    WAVEFORMATEX  * m_pCoMemWaveFormatEx; 
-
-
-    static HRESULT CoMemCopyWFEX(const WAVEFORMATEX * pSrc, WAVEFORMATEX ** ppCoMemWFEX)
-    {
-        ULONG cb = sizeof(WAVEFORMATEX) + pSrc->cbSize;
-        *ppCoMemWFEX = (WAVEFORMATEX *)::CoTaskMemAlloc(cb);
-        if (*ppCoMemWFEX)
-        {
-            memcpy(*ppCoMemWFEX, pSrc, cb);
-            return S_OK;
-        }
-        else
-        {
-            return E_OUTOFMEMORY;
-        }
-    }
-
-
-    CSpStreamFormat()
-    {
-        m_guidFormatId = GUID_NULL;
-        m_pCoMemWaveFormatEx = NULL;
-    }
-
-    CSpStreamFormat(SPSTREAMFORMAT eFormat, HRESULT * phr)
-    {
-        *phr = SpConvertStreamFormatEnum(eFormat, &m_guidFormatId, &m_pCoMemWaveFormatEx);
-    }
-
-    CSpStreamFormat(const WAVEFORMATEX * pWaveFormatEx, HRESULT * phr)
-    {
-        *phr = CoMemCopyWFEX(pWaveFormatEx, &m_pCoMemWaveFormatEx);
-        m_guidFormatId = SUCCEEDED(*phr) ? SPDFID_WaveFormatEx : GUID_NULL;
-    }
-
-    ~CSpStreamFormat()
-    {
-        ::CoTaskMemFree(m_pCoMemWaveFormatEx);
-    }
-
-    void Clear()
-    {
-        ::CoTaskMemFree(m_pCoMemWaveFormatEx);
-        m_pCoMemWaveFormatEx = NULL;
-        memset(&m_guidFormatId, 0, sizeof(m_guidFormatId));
-    }
-
-    const GUID & FormatId() const 
-    {
-        return m_guidFormatId;
-    }
-
-    const WAVEFORMATEX * WaveFormatExPtr() const
-    {
-        return m_pCoMemWaveFormatEx;
-    }
-
-
-    HRESULT AssignFormat(SPSTREAMFORMAT eFormat)
-    {
-        ::CoTaskMemFree(m_pCoMemWaveFormatEx);    
-        return SpConvertStreamFormatEnum(eFormat, &m_guidFormatId, &m_pCoMemWaveFormatEx);
-    }
-
-    HRESULT AssignFormat(ISpStreamFormat * pStream)
-    {
-        ::CoTaskMemFree(m_pCoMemWaveFormatEx);
-        m_pCoMemWaveFormatEx = NULL;
-        return pStream->GetFormat(&m_guidFormatId, &m_pCoMemWaveFormatEx);
-    }
-
-    HRESULT AssignFormat(const WAVEFORMATEX * pWaveFormatEx)
-    {
-        ::CoTaskMemFree(m_pCoMemWaveFormatEx);
-        HRESULT hr = CoMemCopyWFEX(pWaveFormatEx, &m_pCoMemWaveFormatEx);
-        m_guidFormatId = SUCCEEDED(hr) ? SPDFID_WaveFormatEx : GUID_NULL;
-        return hr;
-    }
-
-    HRESULT AssignFormat(REFGUID rguidFormatId, const WAVEFORMATEX * pWaveFormatEx)
-    {
-        HRESULT hr = S_OK;
-
-        m_guidFormatId = rguidFormatId;
-        ::CoTaskMemFree(m_pCoMemWaveFormatEx);
-        m_pCoMemWaveFormatEx = NULL;
-
-        if (rguidFormatId == SPDFID_WaveFormatEx)
-        {
-            if (::IsBadReadPtr(pWaveFormatEx, sizeof(*pWaveFormatEx)))
-            {
-                hr = E_INVALIDARG;
-            }
-            else 
-            {
-                hr = CoMemCopyWFEX(pWaveFormatEx, &m_pCoMemWaveFormatEx);
-            }
-
-            if (FAILED(hr))
-            {
-                m_guidFormatId = GUID_NULL;
-            }
-        }
-
-        return hr;
-    }
-
-
-    BOOL IsEqual(REFGUID rguidFormatId, const WAVEFORMATEX * pwfex) const
-    {
-        if (rguidFormatId == m_guidFormatId)
-        {
-            if (m_pCoMemWaveFormatEx)
-            {
-                if (pwfex &&
-                    pwfex->cbSize == m_pCoMemWaveFormatEx->cbSize &&
-                    memcmp(m_pCoMemWaveFormatEx, pwfex, sizeof(WAVEFORMATEX) + pwfex->cbSize) == 0)
-                {
-                    return TRUE;
-                }
-            }
-            else
-            {
-                return (pwfex == NULL);
-            }
-        }
-        return FALSE;
-    }
-
-
-
-    HRESULT ParamValidateAssignFormat(REFGUID rguidFormatId, const WAVEFORMATEX * pWaveFormatEx, BOOL fRequireWaveFormat = FALSE)
-    {
-        if ((pWaveFormatEx && (::IsBadReadPtr(pWaveFormatEx, sizeof(*pWaveFormatEx)) || rguidFormatId != SPDFID_WaveFormatEx)) ||
-            (fRequireWaveFormat && pWaveFormatEx == NULL))
-        {
-            return E_INVALIDARG;
-        }
-        return AssignFormat(rguidFormatId, pWaveFormatEx);
-    }
-
-    SPSTREAMFORMAT ComputeFormatEnum()
-    {
-        if (m_guidFormatId == GUID_NULL)
-        {
-            return SPSF_NoAssignedFormat;
-        }
-        if (m_guidFormatId == SPDFID_Text)
-        {
-            return SPSF_Text;
-        }
-        if (m_guidFormatId != SPDFID_WaveFormatEx)
-        {
-            return SPSF_NonStandardFormat;
-        }
-        //
-        //  It is a WAVEFORMATEX.  Now determine which type it is and convert.
-        //
-        DWORD dwIndex = 0;
-        switch (m_pCoMemWaveFormatEx->wFormatTag)
-        {
-          case WAVE_FORMAT_PCM:
-          {
-            switch (m_pCoMemWaveFormatEx->nChannels)
-            {
-              case 1:
-                break;
-              case 2:
-                dwIndex |= 1;
-                break;
-              default:
-                return SPSF_ExtendedAudioFormat;
-            }
-
-            switch (m_pCoMemWaveFormatEx->wBitsPerSample)
-            {
-              case 8:
-                break;
-              case 16:
-                dwIndex |= 2;
-                break;
-              default:
-                return SPSF_ExtendedAudioFormat;
-            }
-
-            switch (m_pCoMemWaveFormatEx->nSamplesPerSec)
-            {
-              case 48000:
-                dwIndex += 4;   // Fall through
-              case 44100:
-                dwIndex += 4;   // Fall through
-              case 32000:
-                dwIndex += 4;   // Fall through
-              case 24000:
-                dwIndex += 4;   // Fall through
-              case 22050:
-                dwIndex += 4;   // Fall through
-              case 16000:
-                dwIndex += 4;   // Fall through
-              case 12000:
-                dwIndex += 4;   // Fall through
-              case 11025:
-                dwIndex += 4;   // Fall through
-              case 8000:
-                break;
-              default:
-                return SPSF_ExtendedAudioFormat;
-            }
-
-            return static_cast<SPSTREAMFORMAT>(SPSF_8kHz8BitMono + dwIndex);
-          }
-
-          case WAVE_FORMAT_DSPGROUP_TRUESPEECH:
-          {
-            return SPSF_TrueSpeech_8kHz1BitMono;
-          }
-
-          case WAVE_FORMAT_ALAW: // fall through
-          case WAVE_FORMAT_MULAW:
-          case WAVE_FORMAT_ADPCM:
-          {
-            switch (m_pCoMemWaveFormatEx->nChannels)
-            {
-              case 1:
-                break;
-              case 2:
-                dwIndex |= 1;
-                break;
-              default:
-                return SPSF_ExtendedAudioFormat;
-            }
-
-            if(m_pCoMemWaveFormatEx->wFormatTag == WAVE_FORMAT_ADPCM)
-            {
-                if(m_pCoMemWaveFormatEx->wBitsPerSample != 4)
-                {
-                    return SPSF_ExtendedAudioFormat;
-                }
-            }
-            else if(m_pCoMemWaveFormatEx->wBitsPerSample != 8)
-            {
-                return SPSF_ExtendedAudioFormat;
-            }
-
-            switch (m_pCoMemWaveFormatEx->nSamplesPerSec)
-            {
-              case 44100:
-                dwIndex += 2;   // Fall through
-              case 22050:
-                dwIndex += 2;   // Fall through
-              case 11025:
-                dwIndex += 2;   // Fall through
-              case 8000:
-                break;
-              default:
-                return SPSF_ExtendedAudioFormat;
-            }
-
-            switch( m_pCoMemWaveFormatEx->wFormatTag )
-            {
-              case WAVE_FORMAT_ALAW:
-                return static_cast<SPSTREAMFORMAT>(SPSF_CCITT_ALaw_8kHzMono + dwIndex);
-              case WAVE_FORMAT_MULAW:
-                return static_cast<SPSTREAMFORMAT>(SPSF_CCITT_uLaw_8kHzMono + dwIndex);
-              case WAVE_FORMAT_ADPCM:
-                return static_cast<SPSTREAMFORMAT>(SPSF_ADPCM_8kHzMono + dwIndex);
-            }
-          }
-
-          case WAVE_FORMAT_GSM610:
-          {
-            if( m_pCoMemWaveFormatEx->nChannels != 1 )
-            {
-                return SPSF_ExtendedAudioFormat;
-            }
-
-            switch (m_pCoMemWaveFormatEx->nSamplesPerSec)
-            {
-              case 44100:
-                dwIndex = 3;
-                break;
-              case 22050:
-                dwIndex = 2;
-                break;
-              case 11025:
-                dwIndex = 1;
-                break;
-              case 8000:
-                dwIndex = 0;
-                break;
-              default:
-                return SPSF_ExtendedAudioFormat;
-            }
-
-            return static_cast<SPSTREAMFORMAT>(SPSF_GSM610_8kHzMono + dwIndex);
-          }
-
-          default:
-            return SPSF_ExtendedAudioFormat;
-            break;
-        }
-    }
-
-    void DetachTo(CSpStreamFormat & Other)
-    {
-        ::CoTaskMemFree(Other.m_pCoMemWaveFormatEx);
-        Other.m_guidFormatId = m_guidFormatId;
-        Other.m_pCoMemWaveFormatEx = m_pCoMemWaveFormatEx;
-        m_pCoMemWaveFormatEx = NULL;
-        memset(&m_guidFormatId, 0, sizeof(m_guidFormatId));
-    }
-
-    void DetachTo(GUID * pFormatId, WAVEFORMATEX ** ppCoMemWaveFormatEx)
-    {
-        *pFormatId = m_guidFormatId;
-        *ppCoMemWaveFormatEx = m_pCoMemWaveFormatEx;
-        m_pCoMemWaveFormatEx = NULL;
-        memset(&m_guidFormatId, 0, sizeof(m_guidFormatId));
-    }
-
-    HRESULT CopyTo(GUID * pFormatId, WAVEFORMATEX ** ppCoMemWFEX) const
-    {
-        HRESULT hr = S_OK;
-        *pFormatId = m_guidFormatId;
-        if (m_pCoMemWaveFormatEx)
-        {
-            hr = CoMemCopyWFEX(m_pCoMemWaveFormatEx, ppCoMemWFEX);
-            if (FAILED(hr))
-            {
-                memset(pFormatId, 0, sizeof(*pFormatId));
-            }
-        }
-        else
-        {
-            *ppCoMemWFEX = NULL;
-        }
-        return hr;
-    }
-
-    HRESULT CopyTo(CSpStreamFormat & Other) const
-    {
-        ::CoTaskMemFree(Other.m_pCoMemWaveFormatEx);
-        return CopyTo(&Other.m_guidFormatId, &Other.m_pCoMemWaveFormatEx);
-    }
-    
-    HRESULT AssignFormat(const CSpStreamFormat & Src)
-    {
-        return Src.CopyTo(*this);
-    }
-
-
-    HRESULT ParamValidateCopyTo(GUID * pFormatId, WAVEFORMATEX ** ppCoMemWFEX) const
-    {
-        if (::IsBadWritePtr(pFormatId, sizeof(*pFormatId)) ||
-            ::IsBadWritePtr(ppCoMemWFEX, sizeof(*ppCoMemWFEX)))
-        {
-            return E_POINTER;
-        }
-        return CopyTo(pFormatId, ppCoMemWFEX);
-    }
-
-    BOOL operator==(const CSpStreamFormat & Other) const
-    {
-        return IsEqual(Other.m_guidFormatId, Other.m_pCoMemWaveFormatEx);
-    }
-    BOOL operator!=(const CSpStreamFormat & Other) const
-    {
-        return !IsEqual(Other.m_guidFormatId, Other.m_pCoMemWaveFormatEx);
-    }
-
-    ULONG SerializeSize() const
-    {
-        ULONG cb = sizeof(ULONG) + sizeof(m_guidFormatId);
-        if (m_pCoMemWaveFormatEx)
-        {
-            cb += sizeof(WAVEFORMATEX) + m_pCoMemWaveFormatEx->cbSize + 3;  // Add 3 to round up
-            cb -= cb % 4;                                                   // Round to DWORD
-        }
-        return cb;
-    }
-
-    ULONG Serialize(BYTE * pBuffer) const
-    {
-        ULONG cb = SerializeSize();
-        *((UNALIGNED ULONG *)pBuffer) = cb;
-        pBuffer += sizeof(ULONG);
-        *((UNALIGNED GUID *)pBuffer) = m_guidFormatId;
-        if (m_pCoMemWaveFormatEx)
-        {
-            pBuffer += sizeof(m_guidFormatId);
-            memcpy(pBuffer, m_pCoMemWaveFormatEx, sizeof(WAVEFORMATEX) + m_pCoMemWaveFormatEx->cbSize);
-        }
-        return cb;
-    }
-
-    HRESULT Deserialize(const BYTE * pBuffer, ULONG * pcbUsed)
-    {
-        HRESULT hr = S_OK;
-        ::CoTaskMemFree(m_pCoMemWaveFormatEx);
-        m_pCoMemWaveFormatEx = NULL;
-        *pcbUsed = *((UNALIGNED ULONG *)pBuffer);
-        pBuffer += sizeof(ULONG);
-        // Misaligment exception is generated for SHx platform.
-        // Marking pointer as UNALIGNED does not help.
-#ifndef _WIN32_WCE
-        m_guidFormatId = *((UNALIGNED GUID *)pBuffer);
-#else
-        memcpy(&m_guidFormatId, pBuffer, sizeof(GUID));
-#endif
-        if (*pcbUsed > sizeof(GUID) + sizeof(ULONG))
-        {
-            pBuffer += sizeof(m_guidFormatId);
-            hr = CoMemCopyWFEX((const WAVEFORMATEX *)pBuffer, &m_pCoMemWaveFormatEx);
-            if (FAILED(hr))
-            {
-                m_guidFormatId = GUID_NULL;
-            }
-        }
-        return hr;
-    }
-
-};
-
-
-
-// Return the default codepage given a LCID.
-// Note some of the newer locales do not have associated Windows codepages.  For these, we return UTF-8.
-
-inline UINT SpCodePageFromLcid(LCID lcid)
-{
-    char achCodePage[6];
-
-    return (0 != GetLocaleInfoA(lcid, LOCALE_IDEFAULTANSICODEPAGE, achCodePage, sizeof(achCodePage))) ? atoi(achCodePage) : 65001;
-}
-
-
-/****************************************************************************
-* SpClearEvent *
-*--------------*
-*   Description:
-*       Helper function that can be used by clients that do not use the CSpEvent
-*   class.
-*
-*   Returns:
-*
-*****************************************************************************/
-
-inline void SpClearEvent(SPEVENT * pe)
-{
-    if( pe->elParamType != SPEI_UNDEFINED)
-    {
-        if( pe->elParamType == SPET_LPARAM_IS_POINTER ||
-            pe->elParamType == SPET_LPARAM_IS_STRING)
-        {
-            ::CoTaskMemFree((void *)pe->lParam);
-        }
-        else if (pe->elParamType == SPET_LPARAM_IS_TOKEN ||
-               pe->elParamType == SPET_LPARAM_IS_OBJECT)
-        {
-            ((IUnknown*)pe->lParam)->Release();
-        }
-    }
-    memset(pe, 0, sizeof(*pe));
-}
-
-/****************************************************************************
-* SpInitEvent *
-*-------------*
-*   Description:
-*
-*   Returns:
-*
-*****************************************************************************/
-
-inline void SpInitEvent(SPEVENT * pe)
-{
-    memset(pe, 0, sizeof(*pe));
-}
-
-/****************************************************************************
-* SpEventSerializeSize *
-*----------------------*
-*   Description:
-*       Computes the required size of a buffer to serialize an event.  The caller
-*   must specify which type of serialized event is desired -- either SPSERIALIZEDEVENT
-*   or SPSERIALIZEDEVENT64.    
-*
-*   Returns:
-*       Size in bytes required to seriailze the event.
-*
-****************************************************************************/
-
-// WCE compiler does not work propertly with template
-#ifndef _WIN32_WCE
-template <class T>
-inline ULONG SpEventSerializeSize(const SPEVENT * pEvent)
-
-{
-    ULONG ulSize = sizeof(T);
-
-#else
-
-inline ULONG SpEventSerializeSize(const SPEVENT * pEvent, ULONG ulSize)
-{
-#endif //_WIN32_WCE
-
-    if( ( pEvent->elParamType == SPET_LPARAM_IS_POINTER ) && pEvent->lParam )
-    {
-        ulSize += ULONG(pEvent->wParam);
-    }
-    else if ((pEvent->elParamType == SPET_LPARAM_IS_STRING) && pEvent->lParam != NULL)
-    {
-        ulSize += (wcslen((WCHAR*)pEvent->lParam) + 1) * sizeof( WCHAR );
-    }
-    else if( pEvent->elParamType == SPET_LPARAM_IS_TOKEN )
-    {
-        CSpDynamicString dstrObjectId;
-        if( ((ISpObjectToken*)(pEvent->lParam))->GetId( &dstrObjectId ) == S_OK )
-        {
-            ulSize += (dstrObjectId.Length() + 1) * sizeof( WCHAR );
-        }
-    }
-    // Round up to nearest DWORD
-    ulSize += 3;
-    ulSize -= ulSize % 4;
-    return ulSize;
-}
-
-/****************************************************************************
-* SpSerializedEventSize *
-*-----------------------*
-*   Description:
-*       Returns the size, in bytes, used by a serialized event.  The caller can
-*   pass a pointer to either a SPSERIAILZEDEVENT or SPSERIALIZEDEVENT64 structure.
-*
-*   Returns:
-*       Number of bytes used by serizlied event
-*
-********************************************************************* RAL ***/
-
-// WCE compiler does not work propertly with template
-#ifndef _WIN32_WCE
-template <class T>
-inline ULONG SpSerializedEventSize(const T * pSerEvent)
-{
-    ULONG ulSize = sizeof(T);
-
-    if( ( pSerEvent->elParamType == SPET_LPARAM_IS_POINTER ) && pSerEvent->SerializedlParam )
-    {
-        ulSize += ULONG(pSerEvent->SerializedwParam);
-    }
-    else if ((pSerEvent->elParamType == SPET_LPARAM_IS_STRING || pSerEvent->elParamType == SPET_LPARAM_IS_TOKEN) &&
-             pSerEvent->SerializedlParam != NULL)
-    {
-        ulSize += (wcslen((WCHAR*)(pSerEvent + 1)) + 1) * sizeof( WCHAR );
-    }
-    // Round up to nearest DWORD
-    ulSize += 3;
-    ulSize -= ulSize % 4;
-    return ulSize;
-}
-
-#else //_WIN32_WCE
-
-inline ULONG SpSerializedEventSize(const SPSERIALIZEDEVENT * pSerEvent, ULONG ulSize)
-{
-    if( ( pSerEvent->elParamType == SPET_LPARAM_IS_POINTER ) && pSerEvent->SerializedlParam )
-    {
-        ulSize += ULONG(pSerEvent->SerializedwParam);
-    }
-    else if ((pSerEvent->elParamType == SPET_LPARAM_IS_STRING || pSerEvent->elParamType == SPET_LPARAM_IS_TOKEN) &&
-             pSerEvent->SerializedlParam != NULL)
-    {
-        ulSize += (wcslen((WCHAR*)(pSerEvent + 1)) + 1) * sizeof( WCHAR );
-    }
-    // Round up to nearest DWORD
-    ulSize += 3;
-    ulSize -= ulSize % 4;
-    return ulSize;
-}
-
-inline ULONG SpSerializedEventSize(const SPSERIALIZEDEVENT64 * pSerEvent, ULONG ulSize)
-{
-    if( ( pSerEvent->elParamType == SPET_LPARAM_IS_POINTER ) && pSerEvent->SerializedlParam )
-    {
-        ulSize += ULONG(pSerEvent->SerializedwParam);
-    }
-    else if ((pSerEvent->elParamType == SPET_LPARAM_IS_STRING || pSerEvent->elParamType == SPET_LPARAM_IS_TOKEN) &&
-             pSerEvent->SerializedlParam != NULL)
-    {
-        ulSize += (wcslen((WCHAR*)(pSerEvent + 1)) + 1) * sizeof( WCHAR );
-    }
-    // Round up to nearest DWORD
-    ulSize += 3;
-    ulSize -= ulSize % 4;
-    return ulSize;
-}
-
-#endif //_WIN32_WCE
-
-/*** CSpEvent helper class
-*
-*/
-class CSpEvent : public SPEVENT
-{
-public:
-    CSpEvent()
-    {
-        SpInitEvent(this);
-    }
-    ~CSpEvent()
-    {
-        SpClearEvent(this);
-    }
-    // If you need to take the address of a CSpEvent that is not const, use the AddrOf() method
-    // which will do debug checking of parameters.  If you encounter this problem when calling
-    // GetEvents from an event source, you may want to use the GetFrom() method of this class.
-    const SPEVENT * operator&()
-        {
-                return this;
-        }
-    CSpEvent * AddrOf()
-    {
-        // Note:  This method does not ASSERT since we assume the caller knows what they are doing.
-        return this;
-    }
-    void Clear()
-    {
-        SpClearEvent(this);
-    }
-    HRESULT CopyTo(SPEVENT * pDestEvent) const
-    {
-        memcpy(pDestEvent, this, sizeof(*pDestEvent));
-        if ((elParamType == SPET_LPARAM_IS_POINTER) && lParam)
-        {
-            pDestEvent->lParam = (LPARAM)::CoTaskMemAlloc(wParam);
-            if (pDestEvent->lParam)
-            {
-                memcpy((void *)pDestEvent->lParam, (void *)lParam, wParam);
-            }
-            else
-            {
-                pDestEvent->eEventId = SPEI_UNDEFINED;
-                return E_OUTOFMEMORY;
-            }
-        }
-        else if (elParamType == SPET_LPARAM_IS_STRING && lParam != NULL)
-        {
-            pDestEvent->lParam = (LPARAM)::CoTaskMemAlloc((wcslen((WCHAR*)lParam) + 1) * sizeof(WCHAR));
-            if (pDestEvent->lParam)
-            {
-                wcscpy((WCHAR*)pDestEvent->lParam, (WCHAR*)lParam);
-            }
-            else
-            {
-                pDestEvent->eEventId = SPEI_UNDEFINED;
-                return E_OUTOFMEMORY;
-            }
-        }
-        else if (elParamType == SPET_LPARAM_IS_TOKEN ||
-               elParamType == SPET_LPARAM_IS_OBJECT)
-        {
-            ((IUnknown*)lParam)->AddRef();
-        }
-        return S_OK;
-    }
-
-    HRESULT GetFrom(ISpEventSource * pEventSrc)
-    {
-        SpClearEvent(this);
-        return pEventSrc->GetEvents(1, this, NULL);
-    }
-    HRESULT CopyFrom(const SPEVENT * pSrcEvent)
-    {
-        SpClearEvent(this);
-        return static_cast<const CSpEvent *>(pSrcEvent)->CopyTo(this);
-    }
-    void Detach(SPEVENT * pDestEvent = NULL)
-    {
-        if (pDestEvent)
-        {
-            memcpy(pDestEvent, this, sizeof(*pDestEvent));
-        }
-        memset(this, 0, sizeof(*this));
-    }
-
-    template <class T>
-    ULONG SerializeSize() const
-    {
-        return SpEventSerializeSize<T>(this);
-    }
-
-    // Call this method with either SPSERIALIZEDEVENT or SPSERIALIZEDEVENT64
-    template <class T>
-    void Serialize(T * pSerEvent) const
-    {
-        pSerEvent->eEventId = this->eEventId;
-        pSerEvent->elParamType = this->elParamType;
-        pSerEvent->ulStreamNum = this->ulStreamNum;
-        pSerEvent->ullAudioStreamOffset = this->ullAudioStreamOffset;
-        pSerEvent->SerializedwParam = static_cast<ULONG>(this->wParam);
-        pSerEvent->SerializedlParam = static_cast<LONG>(this->lParam);
-        if (lParam)
-        {
-            switch(elParamType)
-            {
-            case SPET_LPARAM_IS_POINTER:
-                memcpy(pSerEvent + 1, (void *)lParam, wParam);
-                pSerEvent->SerializedlParam = sizeof(T);
-                break;
-
-            case SPET_LPARAM_IS_STRING:
-                wcscpy((WCHAR *)(pSerEvent + 1), (WCHAR*)lParam);
-                pSerEvent->SerializedlParam = sizeof(T);
-                break;
-
-            case SPET_LPARAM_IS_TOKEN:
-                {
-                    CSpDynamicString dstrObjectId;
-                    if( SUCCEEDED( ((ISpObjectToken*)lParam)->GetId( &dstrObjectId ) ) )
-                    {
-                        pSerEvent->SerializedwParam = (dstrObjectId.Length() + 1) * sizeof( WCHAR );;
-                        memcpy( pSerEvent + 1, (void *)dstrObjectId.m_psz, static_cast<ULONG>(pSerEvent->SerializedwParam) );
-                    }
-                    pSerEvent->SerializedlParam = sizeof(T);
-                }
-                break;
-
-            default:
-                break;
-            }
-        }
-    }
-
-    template <class T>
-    HRESULT Serialize(T ** ppCoMemSerEvent, ULONG * pcbSerEvent) const 
-    {
-// WCE compiler does not work propertly with template
-#ifndef _WIN32_WCE
-        *pcbSerEvent = SpEventSerializeSize<T>(this);
-#else
-        *pcbSerEvent = SpEventSerializeSize(this, sizeof(** ppCoMemSerEvent));
-#endif
-        *ppCoMemSerEvent = (T *)::CoTaskMemAlloc(*pcbSerEvent);
-        if (*ppCoMemSerEvent)
-        {
-            Serialize(*ppCoMemSerEvent);
-            return S_OK;
-        }
-        else
-        {
-            *pcbSerEvent = 0;
-            return E_OUTOFMEMORY;
-        }
-    }
-
-
-    // Call this method with either SPSERIALIZEDEVENT or SPSERIALIZEDEVENT64
-    template <class T>
-    HRESULT Deserialize(const T * pSerEvent, ULONG * pcbUsed = NULL)
-    {
-        Clear();
-        HRESULT hr = S_OK;
-        const UNALIGNED T * pTemp = pSerEvent;
-        this->eEventId = pTemp->eEventId;
-        this->elParamType = pTemp->elParamType;
-        this->ulStreamNum = pTemp->ulStreamNum;
-        this->ullAudioStreamOffset = pTemp->ullAudioStreamOffset;
-        this->wParam = static_cast<WPARAM>(pTemp->SerializedwParam);
-        this->lParam = static_cast<LPARAM>(pTemp->SerializedlParam);
-        if (pTemp->SerializedlParam)
-        {
-            ULONG cbAlloc = 0;
-            switch (pTemp->elParamType)
-            {
-            case SPET_LPARAM_IS_POINTER:
-                cbAlloc = static_cast<ULONG>(wParam);
-                break;
-
-            case SPET_LPARAM_IS_STRING:
-                cbAlloc = sizeof(WCHAR) * (1 + wcslen((const WCHAR *)(pTemp + 1)));
-                break;
-
-            case SPET_LPARAM_IS_TOKEN:
-                {
-                    ULONG ulDataOffset = ULONG(lParam);
-                    hr = SpGetTokenFromId( (const WCHAR*)(pTemp + 1),
-                                                  (ISpObjectToken **)&lParam );
-                    wParam = 0;
-                }
-                break;
-            }
-            if (cbAlloc)
-            {
-                void * pvBuff = ::CoTaskMemAlloc(cbAlloc);
-                this->lParam = (LPARAM)pvBuff;
-                if (pvBuff)
-                {
-                    memcpy(pvBuff, pTemp + 1, cbAlloc);
-                }
-                else
-                {
-                    hr = E_OUTOFMEMORY;
-                }
-            }
-        }
-
-        if( SUCCEEDED( hr ) && pcbUsed )
-        {
-// WCE compiler does not work propertly with template
-#ifndef _WIN32_WCE
-            *pcbUsed = SpEventSerializeSize<T>(this);
-#else
-            *pcbUsed = SpEventSerializeSize(this, sizeof(*pTemp));
-#endif
-        }
-        return hr;
-    }
-
-    //
-    //  Helpers for access to events.  Performs run-time checks in debug and casts
-    //  data to the appropriate types
-    //
-    SPPHONEID Phoneme() const 
-    {
-        return (SPPHONEID)LOWORD(lParam);
-    }
-    SPVISEMES Viseme() const 
-    {
-        return (SPVISEMES)LOWORD(lParam);
-    }
-    ULONG InputWordPos() const
-    {
-        return ULONG(lParam);
-    }
-    ULONG InputWordLen() const 
-    {
-        return ULONG(wParam);
-    }
-    ULONG InputSentPos() const
-    {
-        return ULONG(lParam);
-    }
-    ULONG InputSentLen() const 
-    {
-        return ULONG(wParam);
-    }
-    ISpObjectToken * ObjectToken() const
-    {
-        return (ISpObjectToken *)lParam;
-    }
-    ISpObjectToken * VoiceToken() const     // More explicit check than ObjectToken()
-    {
-        return ObjectToken();
-    }
-    BOOL PersistVoiceChange() const
-    {
-        return (BOOL)wParam;
-    }
-    IUnknown * Object() const
-    {
-        return (IUnknown*)lParam;
-    }
-    ISpRecoResult * RecoResult() const
-    {
-        return (ISpRecoResult *)Object();
-    }
-    BOOL IsPaused()
-    {
-        return (BOOL)(wParam & SPREF_AutoPause);
-    }
-    BOOL IsEmulated()
-    {
-        return (BOOL)(wParam & SPREF_Emulated);
-    }
-    const WCHAR * String() const
-    {
-        return (const WCHAR*)lParam;
-    }
-    const WCHAR * BookmarkName() const
-    {
-        return String();
-    }
-    const WCHAR * RequestTypeOfUI() const
-    {
-        return String();
-    }
-    SPRECOSTATE RecoState() const
-    {
-        return static_cast<SPRECOSTATE>(wParam);
-    }
-    const WCHAR * PropertyName() const
-    {
-        // Note: Don't use String() method here since in the case of string attributes, the elParamType
-        // field specifies LPARAM_IS_POINTER, but the attribute name IS the first string in this buffer
-        return (const WCHAR*)lParam;
-    }
-    const LONG PropertyNumValue() const 
-    {
-        return static_cast<LONG>(wParam);
-    }
-    const WCHAR * PropertyStringValue() const
-    {
-        // Search for the first NULL and return pointer to the char past it.
-	const WCHAR *psz;
-        for (psz = (const WCHAR *)lParam; *psz; psz++) {}
-        return psz + 1;
-    }
-    SPINTERFERENCE Interference() const
-    {
-        return static_cast<SPINTERFERENCE>(lParam);
-    }
-    HRESULT EndStreamResult() const
-    {
-        return static_cast<HRESULT>(lParam);
-    }
-    BOOL InputStreamReleased() const
-    {
-        return (wParam & SPESF_STREAM_RELEASED) ? TRUE : FALSE;
-    }
-};
-
-class CSpPhrasePtr
-{
-public:
-    SPPHRASE    *   m_pPhrase;
-    CSpPhrasePtr() : m_pPhrase(NULL) {}
-    CSpPhrasePtr(ISpPhrase * pPhraseObj, HRESULT * phr)
-    {
-        *phr = pPhraseObj->GetPhrase(&m_pPhrase);
-    }
-    ~CSpPhrasePtr()
-    {
-        ::CoTaskMemFree(m_pPhrase);
-    }
-        //The assert on operator& usually indicates a bug.  If this is really
-        //what is needed, however, take the address of the m_pPhrase member explicitly.
-        SPPHRASE ** operator&()
-        {
-            return &m_pPhrase;
-        }
-    operator SPPHRASE *() const
-    {
-        return m_pPhrase;
-    }
-        SPPHRASE & operator*() const
-        {
-                return *m_pPhrase;
-        }
-    SPPHRASE * operator->() const
-    {
-        return m_pPhrase;
-    }
-        bool operator!() const
-        {
-                return (m_pPhrase == NULL);
-        }
-    void Clear()
-    {
-        if (m_pPhrase)
-        {
-            ::CoTaskMemFree(m_pPhrase);
-            m_pPhrase = NULL;
-        }
-    }
-    HRESULT GetFrom(ISpPhrase * pPhraseObj)
-    {
-        Clear();
-        return pPhraseObj->GetPhrase(&m_pPhrase);
-    }
-};
-
-
-template <class T>
-class CSpCoTaskMemPtr
-{
-public:
-    T       * m_pT;
-    CSpCoTaskMemPtr() : m_pT(NULL) {}
-    CSpCoTaskMemPtr(void * pv) : m_pT((T *)pv) {}
-    CSpCoTaskMemPtr(ULONG cElements, HRESULT * phr)
-    {
-        m_pT = (T *)::CoTaskMemAlloc(cElements * sizeof(T));
-        *phr = m_pT ? S_OK : E_OUTOFMEMORY;
-    }
-    ~CSpCoTaskMemPtr()
-    {
-        ::CoTaskMemFree(m_pT);
-    }
-    void Clear()
-    {
-        if (m_pT)
-        {
-            ::CoTaskMemFree(m_pT);
-            m_pT = NULL;
-        }
-    }
-    HRESULT Alloc(ULONG cArrayElements = 1)
-    {
-        m_pT = (T *)::CoTaskMemRealloc(m_pT, sizeof(T) * cArrayElements);
-        return (m_pT ? S_OK : E_OUTOFMEMORY);
-    }
-    void Attach(void * pv)
-    {
-        Clear();
-        m_pT = (T *)pv;
-    }
-    T * Detatch()
-    {
-        T * pT = m_pT;
-        m_pT = NULL;
-        return pT;
-    }
-        //The assert on operator& usually indicates a bug.  If this is really
-        //what is needed, however, take the address of the m_pT member explicitly.
-        T ** operator&()
-        {
-                return &m_pT;
-        }
-    T * operator->()
-    {
-        return m_pT;
-    }
-    operator T *()
-    {
-        return m_pT;
-    }
-        bool operator!() const
-        {
-                return (m_pT == NULL);
-        }
-};
-
-
-#endif /* This must be the last line in the file */
diff --git a/backends/text-to-speech/windows/windows-text-to-speech.cpp b/backends/text-to-speech/windows/windows-text-to-speech.cpp
index 2b405f5..9f4ecf7 100644
--- a/backends/text-to-speech/windows/windows-text-to-speech.cpp
+++ b/backends/text-to-speech/windows/windows-text-to-speech.cpp
@@ -30,18 +30,7 @@
 #include <windows.h>
 #include <servprov.h>
 
-// Mingw-w64 is missing symbols for two guids declared in sapi.h which are used
-//  by sphelper-scummvm.h. Mingw32 doesn't include any sapi headers or libraries
-//  so the only way to currently build there is to manually use Microsoft's, in
-//  which case the guids will be defined by their library.
-#if defined(__MINGW32__) && defined(__MINGW64_VERSION_MAJOR)
-#include <initguid.h>
-DEFINE_GUID(SPDFID_Text, 0x7ceef9f9, 0x3d13, 0x11d2, 0x9e, 0xe7, 0x00, 0xc0, 0x4f, 0x79, 0x73, 0x96);
-DEFINE_GUID(SPDFID_WaveFormatEx, 0xc31adbae, 0x527f, 0x4ff5, 0xa2, 0x30, 0xf6, 0x2b, 0xb6, 0x1f, 0xf7, 0x0c);
-#endif
-
 #include <sapi.h>
-#include "backends/text-to-speech/windows/sphelper-scummvm.h"
 #include "backends/platform/sdl/win32/win32_wrapper.h"
 
 #include "backends/text-to-speech/windows/windows-text-to-speech.h"
@@ -78,16 +67,30 @@ void WindowsTextToSpeechManager::init() {
 		return;
 
 	// init audio
-	CSpStreamFormat format;
-	format.AssignFormat(SPSF_11kHz8BitMono);
-	ISpObjectToken *pToken;
-	HRESULT hr = SpGetDefaultTokenFromCategoryId(SPCAT_AUDIOOUT, &pToken);
+	ISpObjectTokenCategory *pTokenCategory;
+	HRESULT hr = CoCreateInstance(CLSID_SpObjectTokenCategory, NULL, CLSCTX_ALL, IID_ISpObjectTokenCategory, (void **)&pTokenCategory);
+	if (SUCCEEDED(hr)) {
+		hr = pTokenCategory->SetId(SPCAT_AUDIOOUT, TRUE);
+		if (SUCCEEDED(hr)) {
+			WCHAR *tokenId;
+			hr = pTokenCategory->GetDefaultTokenId(&tokenId);
+			if (SUCCEEDED(hr)) {
+				ISpObjectToken *pToken;
+				hr = CoCreateInstance(CLSID_SpObjectToken, NULL, CLSCTX_ALL, IID_ISpObjectToken, (void **)&pToken);
+				if (SUCCEEDED(hr)) {
+					hr = pToken->SetId(NULL, tokenId, FALSE);
+					if (SUCCEEDED(hr)) {
+						hr = pToken->CreateInstance(NULL, CLSCTX_ALL, IID_ISpAudio, (void **)&_audio);
+					}
+				}
+				CoTaskMemFree(tokenId);
+			}
+		}
+	}
 	if (FAILED(hr)) {
 		warning("Could not initialize TTS audio");
 		return;
 	}
-	pToken->CreateInstance(NULL, CLSCTX_ALL, IID_ISpAudio, (void **)&_audio);
-	_audio->SetFormat(format.FormatId(), format.WaveFormatExPtr());
 
 	// init voice
 	hr = CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL, IID_ISpVoice, (void **)&_voice);
@@ -348,18 +351,22 @@ void WindowsTextToSpeechManager::createVoice(void *cpVoiceToken) {
 
 	// description
 	WCHAR *descW;
-	SpGetDescription(voiceToken, &descW);
-	char *buffer = Win32::unicodeToAnsi(descW);
-	Common::String desc = buffer;
+	char *buffer;
+	Common::String desc;
+	HRESULT hr = voiceToken->GetStringValue(NULL, &descW);
+	if (SUCCEEDED(hr)) {
+		buffer = Win32::unicodeToAnsi(descW);
+		desc = buffer;
+		delete[] buffer;
+		CoTaskMemFree(descW);
+	}
+
 	if (desc == "Sample TTS Voice") {
 		// This is really bad voice, it is basicaly unusable
-		free(buffer);
 		return;
 	}
-	free(buffer);
 
 	// voice attributes
-	HRESULT hr = S_OK;
 	ISpDataKey *key = nullptr;
 	hr = voiceToken->OpenKey(L"Attributes", &key);
 
@@ -379,7 +386,7 @@ void WindowsTextToSpeechManager::createVoice(void *cpVoiceToken) {
 	}
 	buffer = Win32::unicodeToAnsi(data);
 	Common::String language = lcidToLocale(buffer);
-	free(buffer);
+	delete[] buffer;
 	CoTaskMemFree(data);
 
 	// only get the voices for the current language
@@ -397,7 +404,7 @@ void WindowsTextToSpeechManager::createVoice(void *cpVoiceToken) {
 	}
 	buffer = Win32::unicodeToAnsi(data);
 	Common::TTSVoice::Gender gender = !strcmp(buffer, "Male") ? Common::TTSVoice::MALE : Common::TTSVoice::FEMALE;
-	free(buffer);
+	delete[] buffer;
 	CoTaskMemFree(data);
 
 	// age
@@ -409,7 +416,7 @@ void WindowsTextToSpeechManager::createVoice(void *cpVoiceToken) {
 	}
 	buffer = Win32::unicodeToAnsi(data);
 	Common::TTSVoice::Age age = !strcmp(buffer, "Adult") ? Common::TTSVoice::ADULT : Common::TTSVoice::UNKNOWN_AGE;
-	free(buffer);
+	delete[] buffer;
 	CoTaskMemFree(data);
 
 	_ttsState->_availableVoices.push_back(Common::TTSVoice(gender, age, (void *) voiceToken, desc));
@@ -441,12 +448,19 @@ Common::String WindowsTextToSpeechManager::lcidToLocale(Common::String lcid) {
 
 void WindowsTextToSpeechManager::updateVoices() {
 	_ttsState->_availableVoices.clear();
-	HRESULT hr = S_OK;
 	ISpObjectToken *cpVoiceToken = nullptr;
 	IEnumSpObjectTokens *cpEnum = nullptr;
 	unsigned long ulCount = 0;
 
-	hr = SpEnumTokens(SPCAT_VOICES, NULL, NULL, &cpEnum);
+	ISpObjectTokenCategory *cpCategory;
+	HRESULT hr = CoCreateInstance(CLSID_SpObjectTokenCategory, NULL, CLSCTX_ALL, IID_ISpObjectTokenCategory, (void**)&cpCategory);
+	if (SUCCEEDED(hr)) {
+		hr = cpCategory->SetId(SPCAT_VOICES, FALSE);
+		if (SUCCEEDED(hr)) {
+			hr = cpCategory->EnumTokens(NULL, NULL, &cpEnum);
+		}
+	}
+
 	if (SUCCEEDED(hr)) {
 		hr = cpEnum->GetCount(&ulCount);
 	}





More information about the Scummvm-git-logs mailing list