This commit is contained in:
FluorescentCIAAfricanAmerican
2020-04-22 12:56:21 -04:00
commit 3bf9df6b27
15370 changed files with 5489726 additions and 0 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+854
View File
@@ -0,0 +1,854 @@
/*******************************************************************************
* SPDDKHLP.h *
*------------*
* Description:
* This is the header file for core helper functions implementation.
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
*******************************************************************************/
#ifndef SPDDKHLP_h
#define SPDDKHLP_h
#ifndef SPHelper_h
#include <sphelper.h>
#endif
#include <sapiddk.h>
#ifndef SPError_h
#include <SPError.h>
#endif
#ifndef SPDebug_h
#include <SPDebug.h>
#endif
#ifndef _INC_LIMITS
#include <limits.h>
#endif
#ifndef _INC_CRTDBG
#include <crtdbg.h>
#endif
#ifndef _INC_MALLOC
#include <malloc.h>
#endif
#ifndef _INC_MMSYSTEM
#include <mmsystem.h>
#endif
#ifndef __comcat_h__
#include <comcat.h>
#endif
//=== Constants ==============================================================
#define sp_countof(x) ((sizeof(x) / sizeof(*(x))))
#define SP_IS_BAD_WRITE_PTR(p) ( SPIsBadWritePtr( p, sizeof(*(p)) ))
#define SP_IS_BAD_READ_PTR(p) ( SPIsBadReadPtr( p, sizeof(*(p)) ))
#define SP_IS_BAD_CODE_PTR(p) ( ::IsBadCodePtr((FARPROC)(p) )
#define SP_IS_BAD_INTERFACE_PTR(p) ( SPIsBadInterfacePtr( (p) ) )
#define SP_IS_BAD_VARIANT_PTR(p) ( SPIsBadVARIANTPtr( (p) ) )
#define SP_IS_BAD_STRING_PTR(p) ( SPIsBadStringPtr( (p) ) )
#define SP_IS_BAD_OPTIONAL_WRITE_PTR(p) ((p) && SPIsBadWritePtr( p, sizeof(*(p)) ))
#define SP_IS_BAD_OPTIONAL_READ_PTR(p) ((p) && SPIsBadReadPtr( p, sizeof(*(p)) ))
#define SP_IS_BAD_OPTIONAL_INTERFACE_PTR(p) ((p) && SPIsBadInterfacePtr(p))
#define SP_IS_BAD_OPTIONAL_STRING_PTR(p) ((p) && SPIsBadStringPtr(p))
//=== Class, Enum, Struct, Template, and Union Declarations ==================
//=== Inlines ================================================================
/*** Pointer validation functions
*/
// TODO: Add decent debug output for bad parameters
inline BOOL SPIsBadStringPtr( const WCHAR * psz, ULONG cMaxChars = 0xFFFF )
{
BOOL IsBad = false;
__try
{
do
{
if( *psz++ == 0 ) return IsBad;
}
while( --cMaxChars );
}
__except( GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION )
{
IsBad = true;
}
return IsBad;
}
inline BOOL SPIsBadReadPtr( const void* pMem, UINT Size )
{
#ifdef _DEBUG
BOOL bIsBad = ::IsBadReadPtr( pMem, Size );
SPDBG_ASSERT(!bIsBad);
return bIsBad;
#else
return ::IsBadReadPtr( pMem, Size );
#endif
}
inline BOOL SPIsBadWritePtr( void* pMem, UINT Size )
{
#ifdef _DEBUG
BOOL bIsBad = ::IsBadWritePtr( pMem, Size );
SPDBG_ASSERT(!bIsBad);
return bIsBad;
#else
return ::IsBadWritePtr( pMem, Size );
#endif
}
inline BOOL SPIsBadInterfacePtr( const IUnknown* pUnknown )
{
#ifdef _DEBUG
BOOL bIsBad = ( ::IsBadReadPtr( pUnknown, sizeof( *pUnknown ) ) ||
::IsBadCodePtr( (FARPROC)((void**)pUnknown)[0] ))?
(true):(false);
SPDBG_ASSERT(!bIsBad);
return bIsBad;
#else
return ( ::IsBadReadPtr( pUnknown, sizeof( *pUnknown ) ) ||
::IsBadCodePtr( (FARPROC)((void**)pUnknown)[0] ))?
(true):(false);
#endif
}
inline BOOL SPIsBadVARIANTPtr( const VARIANT* pVar )
{
#ifdef _DEBUG
BOOL bIsBad = ::IsBadReadPtr( pVar, sizeof( *pVar ) );
SPDBG_ASSERT(!bIsBad);
return bIsBad;
#else
return ::IsBadReadPtr( pVar, sizeof( *pVar ) );
#endif
}
#ifdef __ATLCOM_H__ //--- Only enable these if ATL is being used
//
// Helper functions can be used to implement GetObjectToken/SetObjectToken for objects that
// support ISpObjectWithToken
//
inline HRESULT SpGenericSetObjectToken(ISpObjectToken * pCallersToken, CComPtr<ISpObjectToken> & cpObjToken)
{
HRESULT hr = S_OK;
if (SP_IS_BAD_INTERFACE_PTR(pCallersToken))
{
hr = E_INVALIDARG;
}
else
{
if (cpObjToken)
{
hr = SPERR_ALREADY_INITIALIZED;
}
else
{
cpObjToken = pCallersToken;
}
}
return hr;
}
inline HRESULT SpGenericGetObjectToken(ISpObjectToken ** ppCallersToken, CComPtr<ISpObjectToken> & cpObjToken)
{
HRESULT hr = S_OK;
if (SP_IS_BAD_WRITE_PTR(ppCallersToken))
{
hr = E_POINTER;
}
else
{
*ppCallersToken = cpObjToken;
if (*ppCallersToken)
{
(*ppCallersToken)->AddRef();
}
else
{
hr = S_FALSE;
}
}
return hr;
}
#endif // __ATLCOM_H__
//
// Helper class for SPSTATEINFO sturcture automatically initializes and cleans up
// the structure + provides a few helper functions.
//
class CSpStateInfo : public SPSTATEINFO
{
public:
CSpStateInfo()
{
cAllocatedEntries = NULL;
pTransitions = NULL;
}
~CSpStateInfo()
{
::CoTaskMemFree(pTransitions);
}
SPTRANSITIONENTRY * FirstEpsilon()
{
return pTransitions;
}
SPTRANSITIONENTRY * FirstRule()
{
return pTransitions + cEpsilons;
}
SPTRANSITIONENTRY * FirstWord()
{
return pTransitions + cEpsilons + cRules;
}
SPTRANSITIONENTRY * FirstSpecialTransition()
{
return pTransitions + cEpsilons + cRules + cWords;
}
};
//
// This basic queue implementation can be used to maintin linked lists of classes. The class T
// must contain the member m_pNext which is used by this template to point to the next element.
// If the bPurgeWhenDeleted is TRUE then all of the elements in the queue will be deleted
// when the queue is deleted, otherwise they will not.
// If bMaintainCount is TRUE then a running count will be maintained, and GetCount() will be
// efficent. If it is FALSE then a running count will not be maintained, and GetCount() will
// be an order N operation. If you do not require a count, then
//
template <class T, BOOL bPurgeWhenDeleted> class CSpBasicList;
template <class T, BOOL bPurgeWhenDeleted = TRUE, BOOL bMaintainCount = FALSE>
class CSpBasicQueue
{
public:
T * m_pHead;
T * m_pTail;
ULONG m_cElements; // Warning! Use GetCount() -- Not maintained if bMaintainCount is FALSE.
CSpBasicQueue()
{
m_pHead = NULL;
if (bMaintainCount)
{
m_cElements = 0;
}
}
~CSpBasicQueue()
{
if (bPurgeWhenDeleted)
{
Purge();
}
}
HRESULT CreateNode(T ** ppNode)
{
*ppNode = new T;
if (*ppNode)
{
return S_OK;
}
else
{
return E_OUTOFMEMORY;
}
}
T * GetNext(const T * pNode)
{
return pNode->m_pNext;
}
T * Item(ULONG i)
{
T * pNode = m_pHead;
while (pNode && i)
{
i--;
pNode = pNode->m_pNext;
}
return pNode;
}
void InsertAfter(T * pPrev, T * pNewNode)
{
if (pPrev)
{
pNewNode->m_pNext = pPrev->m_pNext;
pPrev->m_pNext = pNewNode;
if (pNewNode->m_pNext == NULL)
{
m_pTail = pNewNode;
}
if (bMaintainCount) ++m_cElements;
}
else
{
InsertHead(pNewNode);
}
}
void InsertTail(T * pNode)
{
pNode->m_pNext = NULL;
if (m_pHead)
{
m_pTail->m_pNext = pNode;
}
else
{
m_pHead = pNode;
}
m_pTail = pNode;
if (bMaintainCount) ++m_cElements;
}
void InsertHead(T * pNode)
{
pNode->m_pNext = m_pHead;
if (m_pHead == NULL)
{
m_pTail = pNode;
}
m_pHead = pNode;
if (bMaintainCount) ++m_cElements;
}
T * RemoveHead()
{
T * pNode = m_pHead;
if (pNode)
{
m_pHead = pNode->m_pNext;
if (bMaintainCount) --m_cElements;
}
return pNode;
}
T * RemoveTail()
{
T * pNode = m_pHead;
if (pNode)
{
if (pNode == m_pTail)
{
m_pHead = NULL;
}
else
{
T * pPrev;
do
{
pPrev = pNode;
pNode = pNode->m_pNext;
} while ( pNode != m_pTail );
pPrev->m_pNext = NULL;
m_pTail = pPrev;
}
if (bMaintainCount) --m_cElements;
}
return pNode;
}
void Purge()
{
while (m_pHead)
{
T * pDie = m_pHead;
m_pHead = pDie->m_pNext;
delete pDie;
}
if (bMaintainCount) m_cElements = 0;
}
void ExplicitPurge()
{
T * pDie;
BYTE * pb;
while (m_pHead)
{
pDie = m_pHead;
m_pHead = pDie->m_pNext;
pDie->~T();
pb = reinterpret_cast<BYTE *>(pDie);
delete [] pb;
}
if (bMaintainCount) m_cElements = 0;
}
T * GetTail() const
{
if (m_pHead)
{
return m_pTail;
}
return NULL;
}
T * GetHead() const
{
return m_pHead;
}
BOOL IsEmpty() const
{
return m_pHead == NULL;
}
BOOL Remove(T * pNode)
{
if (m_pHead == pNode)
{
m_pHead = pNode->m_pNext;
if (bMaintainCount) --m_cElements;
return TRUE;
}
else
{
T * pCur = m_pHead;
while (pCur)
{
T * pNext = pCur->m_pNext;
if (pNext == pNode)
{
if ((pCur->m_pNext = pNode->m_pNext) == NULL)
{
m_pTail = pCur;
}
if (bMaintainCount) --m_cElements;
return TRUE;
}
pCur = pNext;
}
}
return FALSE;
}
void MoveAllToHeadOf(CSpBasicQueue & DestQueue)
{
if (m_pHead)
{
m_pTail->m_pNext = DestQueue.m_pHead;
if (DestQueue.m_pHead == NULL)
{
DestQueue.m_pTail = m_pTail;
}
DestQueue.m_pHead = m_pHead;
m_pHead = NULL;
if (bMaintainCount)
{
DestQueue.m_cElements += m_cElements;
m_cElements = 0;
}
}
}
void MoveAllToList(CSpBasicList<T, bPurgeWhenDeleted> & List)
{
if (m_pHead)
{
m_pTail->m_pNext = List.m_pFirst;
List.m_pFirst = m_pHead;
m_pHead = NULL;
}
if (bMaintainCount)
{
m_cElements = 0;
}
}
BOOL MoveToList(T * pNode, CSpBasicList<T, bPurgeWhenDeleted> & List)
{
BOOL bFound = Remove(pNode);
if (bFound)
{
List.AddNode(pNode);
}
return bFound;
}
ULONG GetCount() const
{
if (bMaintainCount)
{
return m_cElements;
}
else
{
ULONG c = 0;
for (T * pNode = m_pHead;
pNode;
pNode = pNode->m_pNext, c++) {}
return c;
}
}
//
// The following functions require the class T to implement a static function:
//
// LONG Compare(const T * pElem1, const T * pElem2)
//
// which returns < 0 if pElem1 is less than pElem2, 0 if they are equal, and > 0 if
// pElem1 is greater than pElem2.
//
void InsertSorted(T * pNode)
{
if (m_pHead)
{
if (T::Compare(pNode, m_pTail) >= 0)
{
pNode->m_pNext = NULL;
m_pTail->m_pNext = pNode;
m_pTail = pNode;
}
else
{
//
// We don't have to worry about walking off of the end of the list here since
// we have already checked the tail.
//
T ** ppNext = &m_pHead;
while (T::Compare(pNode, *ppNext) >= 0)
{
ppNext = &((*ppNext)->m_pNext);
}
pNode->m_pNext = *ppNext;
*ppNext = pNode;
}
}
else
{
pNode->m_pNext = NULL;
m_pHead = m_pTail = pNode;
}
if (bMaintainCount) ++m_cElements;
}
HRESULT InsertSortedUnique(T * pNode)
{
HRESULT hr = S_OK;
if (m_pHead)
{
if (T::Compare(pNode, m_pTail) > 0)
{
pNode->m_pNext = NULL;
m_pTail->m_pNext = pNode;
m_pTail = pNode;
}
else
{
//
// We don't have to worry about walking off of the end of the list here since
// we have already checked the tail.
//
T ** ppNext = &m_pHead;
while (T::Compare(pNode, *ppNext) > 0)
{
ppNext = &((*ppNext)->m_pNext);
}
if (T::Compare(pNode, *ppNext) != 0)
{
pNode->m_pNext = *ppNext;
*ppNext = pNode;
}
else
{
delete pNode;
hr = S_FALSE;
}
}
}
else
{
pNode->m_pNext = NULL;
m_pHead = m_pTail = pNode;
}
if (bMaintainCount) ++m_cElements;
return hr;
}
//
// These functions must support the "==" operator for the TFIND type.
//
template <class TFIND>
T * Find(TFIND & FindVal) const
{
for (T * pNode = m_pHead; pNode && (!(*pNode == FindVal)); pNode = pNode->m_pNext)
{}
return pNode;
}
template <class TFIND>
T * FindNext(const T * pCurNode, TFIND & FindVal) const
{
for (T * pNode = pCurNode->m_pNext; pNode && (!(*pNode == FindVal)); pNode = pNode->m_pNext)
{}
return pNode;
}
//
// Searches for and removes a single list element
//
template <class TFIND>
T * FindAndRemove(TFIND & FindVal)
{
T * pNode = m_pHead;
if (pNode)
{
if (*pNode == FindVal)
{
m_pHead = pNode->m_pNext;
if (bMaintainCount) --m_cElements;
}
else
{
T * pPrev = pNode;
for (pNode = pNode->m_pNext;
pNode;
pPrev = pNode, pNode = pNode->m_pNext)
{
if (*pNode == FindVal)
{
pPrev->m_pNext = pNode->m_pNext;
if (pNode->m_pNext == NULL)
{
m_pTail = pPrev;
}
if (bMaintainCount) --m_cElements;
break;
}
}
}
}
return pNode;
}
//
// Searches for and deletes all list elements that match
//
template <class TFIND>
void FindAndDeleteAll(TFIND & FindVal)
{
T * pNode = m_pHead;
while (pNode && *pNode == FindVal)
{
m_pHead = pNode->m_pNext;
delete pNode;
if (bMaintainCount) --m_cElements;
pNode = m_pHead;
}
T * pPrev = pNode;
while (pNode)
{
T * pNext = pNode->m_pNext;
if (*pNode == FindVal)
{
pPrev->m_pNext = pNext;
delete pNode;
if (bMaintainCount) --m_cElements;
}
else
{
pPrev = pNode;
}
pNode = pNext;
}
m_pTail = pPrev; // Just always set it in case we removed the tail.
}
};
template <class T, BOOL bPurgeWhenDeleted = TRUE>
class CSpBasicList
{
public:
T * m_pFirst;
CSpBasicList() : m_pFirst(NULL) {}
~CSpBasicList()
{
if (bPurgeWhenDeleted)
{
Purge();
}
}
void Purge()
{
while (m_pFirst)
{
T * pNext = m_pFirst->m_pNext;
delete m_pFirst;
m_pFirst = pNext;
}
}
void ExplicitPurge()
{
T * pDie;
BYTE * pb;
while (m_pFirst)
{
pDie = m_pFirst;
m_pFirst = pDie->m_pNext;
pDie->~T();
pb = reinterpret_cast<BYTE *>(pDie);
delete [] pb;
}
}
HRESULT RemoveFirstOrAllocateNew(T ** ppNode)
{
if (m_pFirst)
{
*ppNode = m_pFirst;
m_pFirst = m_pFirst->m_pNext;
}
else
{
*ppNode = new T;
if (*ppNode == NULL)
{
return E_OUTOFMEMORY;
}
}
return S_OK;
}
void AddNode(T * pNode)
{
pNode->m_pNext = m_pFirst;
m_pFirst = pNode;
}
T * GetFirst()
{
return m_pFirst;
}
T * RemoveFirst()
{
T * pNode = m_pFirst;
if (pNode)
{
m_pFirst = pNode->m_pNext;
}
return pNode;
}
};
#define STACK_ALLOC(TYPE, COUNT) (TYPE *)_alloca(sizeof(TYPE) * (COUNT))
#define STACK_ALLOC_AND_ZERO(TYPE, COUNT) (TYPE *)memset(_alloca(sizeof(TYPE) * (COUNT)), 0, (sizeof(TYPE) * (COUNT)))
#define STACK_ALLOC_AND_COPY(TYPE, COUNT, SOURCE) (TYPE *)memcpy(_alloca(sizeof(TYPE) * (COUNT)), (SOURCE), (sizeof(TYPE) * (COUNT)))
inline HRESULT SpGetSubTokenFromToken(
ISpObjectToken * pToken,
const WCHAR * pszSubKeyName,
ISpObjectToken ** ppToken,
BOOL fCreateIfNotExist = FALSE)
{
SPDBG_FUNC("SpGetTokenFromDataKey");
HRESULT hr = S_OK;
if (SP_IS_BAD_INTERFACE_PTR(pToken) ||
SP_IS_BAD_STRING_PTR(pszSubKeyName) ||
SP_IS_BAD_WRITE_PTR(ppToken))
{
hr = E_POINTER;
}
// First, either create or open the datakey for the new token
CComPtr<ISpDataKey> cpDataKeyForNewToken;
if (SUCCEEDED(hr))
{
if (fCreateIfNotExist)
{
hr = pToken->CreateKey(pszSubKeyName, &cpDataKeyForNewToken);
}
else
{
hr = pToken->OpenKey(pszSubKeyName, &cpDataKeyForNewToken);
}
}
// The sub token's category will be the token id of it's parent token
CSpDynamicString dstrCategoryId;
if (SUCCEEDED(hr))
{
hr = pToken->GetId(&dstrCategoryId);
}
// The sub token's token id will be it's category id + "\\" the key name
CSpDynamicString dstrTokenId;
if (SUCCEEDED(hr))
{
dstrTokenId = dstrCategoryId;
dstrTokenId.Append2(L"\\", pszSubKeyName);
}
// Now create the token and initalize it
CComPtr<ISpObjectTokenInit> cpTokenInit;
if (SUCCEEDED(hr))
{
hr = cpTokenInit.CoCreateInstance(CLSID_SpObjectToken);
}
if (SUCCEEDED(hr))
{
hr = cpTokenInit->InitFromDataKey(dstrCategoryId, dstrTokenId, cpDataKeyForNewToken);
}
if (SUCCEEDED(hr))
{
*ppToken = cpTokenInit.Detach();
}
SPDBG_REPORT_ON_FAIL(hr);
return hr;
}
template<class T>
HRESULT SpCreateObjectFromSubToken(ISpObjectToken * pToken, const WCHAR * pszSubKeyName, T ** ppObject,
IUnknown * pUnkOuter = NULL, DWORD dwClsCtxt = CLSCTX_ALL)
{
SPDBG_FUNC("SpCreateObjectFromSubToken");
HRESULT hr;
CComPtr<ISpObjectToken> cpSubToken;
hr = SpGetSubTokenFromToken(pToken, pszSubKeyName, &cpSubToken);
if (SUCCEEDED(hr))
{
hr = SpCreateObjectFromToken(cpSubToken, ppObject, pUnkOuter, dwClsCtxt);
}
SPDBG_REPORT_ON_FAIL(hr);
return hr;
}
#endif /* This must be the last line in the file */
+636
View File
@@ -0,0 +1,636 @@
/*******************************************************************************
* SPDebug.h *
*-----------*
* Description:
* This header file contains debug output services for SAPI5
*-------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
*******************************************************************************/
#pragma once
#include <TCHAR.h>
#include <crtdbg.h>
#ifdef ASSERT_WITH_STACK
#include "AssertWithStack.h"
#endif
const TCHAR g_szSpDebugKey[] = _T("SPDebug");
const TCHAR g_szSpDebugFuncTraceReportMode[] = _T("FuncTraceMode");
const TCHAR g_szSpDebugFuncTraceReportFile[] = _T("FuncTraceFile");
const TCHAR g_szSpDebugParamInfoReportMode[] = _T("ParamInfoMode");
const TCHAR g_szSpDebugParamInfoReportFile[] = _T("ParamInfoFile");
const TCHAR g_szSpDebugDumpInfoReportMode[] = _T("DumpInfoMode");
const TCHAR g_szSpDebugDumpInfoReportFile[] = _T("DumpInfoFile");
const TCHAR g_szSpDebugAssertReportMode[] = _T("AssertMode");
const TCHAR g_szSpDebugAssertReportFile[] = _T("AssertFile");
const TCHAR g_szSpDebugHRFailReportMode[] = _T("HRFailMode");
const TCHAR g_szSpDebugHRFailReportFile[] = _T("HRFailFile");
const TCHAR g_szSpDebugAssertSettingsReReadEachTime[] = _T("AssertSettingsReReadEachTime");
const TCHAR g_szSpDebugServerOnStart[] = _T("DebugServerOnStart");
const TCHAR g_szSpDebugClientOnStart[] = _T("DebugClientOnStart");
const TCHAR g_szSpDebugLog[] = _T("c:\\spdebug.log");
#ifdef _DEBUG
class CSpDebug
{
public:
CSpDebug()
{
m_mutex = NULL;
m_reportModePrev = -1;
m_hfilePrev = NULL;
Read();
}
~CSpDebug()
{
if (m_mutex != NULL)
{
CloseHandle(m_mutex);
}
}
BOOL FuncTrace(BOOL fEnter = TRUE)
{
return fEnter
? Enter(_CRT_WARN, m_FuncTraceMode, m_szFuncTraceFile)
: Leave();
}
BOOL ParamInfo(BOOL fEnter = TRUE)
{
return fEnter
? Enter(_CRT_WARN, m_ParamInfoMode, m_szParamInfoFile)
: Leave();
}
BOOL DumpInfo(BOOL fEnter = TRUE)
{
return fEnter
? Enter(_CRT_WARN, m_DumpInfoMode, m_szDumpInfoFile)
: Leave();
}
BOOL Assert(BOOL fEnter = TRUE)
{
if (m_fAssertSettingsReReadEachTime)
Read();
return fEnter
? Enter(_CRT_ASSERT, m_AssertMode, m_szAssertFile)
: Leave();
}
BOOL HRFail(BOOL fEnter = TRUE)
{
return fEnter
? Enter(_CRT_WARN, m_HRFailMode, m_szHRFailFile)
: Leave();
}
BOOL DebugServerOnStart()
{
return m_fDebugServerOnStart;
}
BOOL DebugClientOnStart()
{
return m_fDebugClientOnStart;
}
private:
void Read()
{
HKEY hkeyDebug;
RegCreateKeyEx(
HKEY_CLASSES_ROOT,
g_szSpDebugKey,
0,
NULL,
0,
KEY_READ | KEY_WRITE,
NULL,
&hkeyDebug,
NULL);
if (hkeyDebug == NULL)
{
RegCreateKeyEx(
HKEY_CLASSES_ROOT,
g_szSpDebugKey,
0,
NULL,
0,
KEY_READ,
NULL,
&hkeyDebug,
NULL);
}
DWORD dw = sizeof(m_fAssertSettingsReReadEachTime);
if (RegQueryValueEx(
hkeyDebug,
g_szSpDebugAssertSettingsReReadEachTime,
NULL,
NULL,
LPBYTE(&m_fAssertSettingsReReadEachTime),
&dw) != ERROR_SUCCESS)
{
m_fAssertSettingsReReadEachTime = FALSE;
RegSetValueEx(
hkeyDebug,
g_szSpDebugAssertSettingsReReadEachTime,
NULL,
REG_DWORD,
LPBYTE(&m_fAssertSettingsReReadEachTime),
sizeof(m_fAssertSettingsReReadEachTime));
}
ReadFor(
hkeyDebug,
g_szSpDebugFuncTraceReportMode,
g_szSpDebugFuncTraceReportFile,
&m_FuncTraceMode,
m_szFuncTraceFile,
0,
g_szSpDebugLog);
ReadFor(
hkeyDebug,
g_szSpDebugParamInfoReportMode,
g_szSpDebugParamInfoReportFile,
&m_ParamInfoMode,
m_szParamInfoFile,
0,
g_szSpDebugLog);
ReadFor(
hkeyDebug,
g_szSpDebugDumpInfoReportMode,
g_szSpDebugDumpInfoReportFile,
&m_DumpInfoMode,
m_szDumpInfoFile,
_CRTDBG_MODE_DEBUG,
g_szSpDebugLog);
ReadFor(
hkeyDebug,
g_szSpDebugAssertReportMode,
g_szSpDebugAssertReportFile,
&m_AssertMode,
m_szAssertFile,
_CRTDBG_MODE_WNDW,
g_szSpDebugLog);
ReadFor(
hkeyDebug,
g_szSpDebugHRFailReportMode,
g_szSpDebugHRFailReportFile,
&m_HRFailMode,
m_szHRFailFile,
_CRTDBG_MODE_DEBUG,
g_szSpDebugLog);
dw = sizeof(m_fDebugServerOnStart);
if (RegQueryValueEx(
hkeyDebug,
g_szSpDebugServerOnStart,
NULL,
NULL,
LPBYTE(&m_fDebugServerOnStart),
&dw) != ERROR_SUCCESS)
{
m_fDebugServerOnStart = FALSE;
RegSetValueEx(
hkeyDebug,
g_szSpDebugServerOnStart,
NULL,
REG_DWORD,
LPBYTE(&m_fDebugServerOnStart),
sizeof(m_fDebugServerOnStart));
}
dw = sizeof(m_fDebugClientOnStart);
if (RegQueryValueEx(
hkeyDebug,
g_szSpDebugClientOnStart,
NULL,
NULL,
LPBYTE(&m_fDebugClientOnStart),
&dw) != ERROR_SUCCESS)
{
m_fDebugClientOnStart = FALSE;
RegSetValueEx(
hkeyDebug,
g_szSpDebugClientOnStart,
NULL,
REG_DWORD,
LPBYTE(&m_fDebugClientOnStart),
sizeof(m_fDebugClientOnStart));
}
RegCloseKey(hkeyDebug);
}
void ReadFor(
HKEY hkey,
const TCHAR * pszModeValueName,
const TCHAR * pszFileValueName,
DWORD * pdwModeValue,
TCHAR * pszFileValue,
DWORD dwDefaultModeValue,
const TCHAR * pszDefaultFileValue)
{
DWORD dw = sizeof(*pdwModeValue);
if (RegQueryValueEx(
hkey,
pszModeValueName,
NULL,
NULL,
LPBYTE(pdwModeValue),
&dw) != ERROR_SUCCESS)
{
*pdwModeValue = dwDefaultModeValue;
RegSetValueEx(
hkey,
pszModeValueName,
NULL,
REG_DWORD,
LPBYTE(pdwModeValue),
sizeof(*pdwModeValue));
}
dw = MAX_PATH;
if (RegQueryValueEx(
hkey,
pszFileValueName,
NULL,
NULL,
LPBYTE(pszFileValue),
&dw) != ERROR_SUCCESS)
{
_tcscpy(pszFileValue, pszDefaultFileValue);
RegSetValueEx(
hkey,
pszFileValueName,
NULL,
REG_SZ,
LPBYTE(pszFileValue),
MAX_PATH);
}
}
BOOL Enter(int reportType, DWORD &reportMode, TCHAR * pszFile)
{
if (reportMode != 0)
{
// We'll hold the mutex, until the caller also calls Leave
if (m_mutex == NULL)
{
m_mutex = CreateMutex(NULL, FALSE, _T("SpDebug"));
}
WaitForSingleObject(m_mutex, INFINITE);
m_reportType = reportType;
m_reportModePrev = _CrtSetReportMode(reportType, reportMode);
if (reportMode & _CRTDBG_MODE_FILE)
{
HANDLE hfile = CreateFile(
pszFile,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ,
NULL,
OPEN_ALWAYS,
0,
NULL);
SetFilePointer(hfile, 0, NULL, FILE_END);
m_hfilePrev = (_HFILE)_CrtSetReportFile(reportType, (_HFILE)hfile);
}
return TRUE;
}
return FALSE;
}
BOOL Leave()
{
int reportMode = _CrtSetReportMode(m_reportType, m_reportModePrev);
if (reportMode & _CRTDBG_MODE_FILE)
{
CloseHandle((_HFILE)_CrtSetReportFile(m_reportType, (_HFILE)m_hfilePrev));
}
ReleaseMutex(m_mutex);
return TRUE;
}
private:
HANDLE m_mutex;
int m_reportType;
int m_reportModePrev;
_HFILE m_hfilePrev;
BOOL m_fAssertSettingsReReadEachTime;
DWORD m_FuncTraceMode;
TCHAR m_szFuncTraceFile[MAX_PATH + 1];
DWORD m_ParamInfoMode;
TCHAR m_szParamInfoFile[MAX_PATH + 1];
DWORD m_DumpInfoMode;
TCHAR m_szDumpInfoFile[MAX_PATH + 1];
DWORD m_AssertMode;
TCHAR m_szAssertFile[MAX_PATH + 1];
DWORD m_HRFailMode;
TCHAR m_szHRFailFile[MAX_PATH + 1];
BOOL m_fDebugServerOnStart;
BOOL m_fDebugClientOnStart;
};
inline CSpDebug *PSpDebug()
{
static CSpDebug debug;
return &debug;
}
class CSpFuncTrace
{
public:
CSpFuncTrace(PCHAR pFuncName)
{
m_pFuncName = pFuncName;
if (PSpDebug()->FuncTrace())
{
_RPT1( _CRT_WARN, "\nEntering Function: %s\n", m_pFuncName );
PSpDebug()->FuncTrace(FALSE);
}
}
~CSpFuncTrace()
{
if (PSpDebug()->FuncTrace())
{
_RPT1( _CRT_WARN, "Leaving Function: %s\n", m_pFuncName );
PSpDebug()->FuncTrace(FALSE);
}
}
private:
PCHAR m_pFuncName;
};
#endif // _DEBUG
//=== User macros ==============================================================
#ifdef _DEBUG
#define SPDBG_FUNC(name) \
CSpFuncTrace functrace(name)
#if defined(ASSERT_WITH_STACK) && !defined(_WIN64)
#define SPDBG_REPORT_ON_FAIL(hr) \
do \
{ \
HRESULT _hr = (hr); \
if (FAILED(_hr) && PSpDebug()->HRFail()) \
{ \
SYSTEMTIME sysTime; \
GetLocalTime(&sysTime); \
CHAR pszHrWithTime[100]; \
sprintf(pszHrWithTime, "%lX\n\n%d.%d.%d %02d:%02d:%02d", \
_hr, \
sysTime.wMonth,sysTime.wDay,sysTime.wYear, \
sysTime.wHour,sysTime.wMinute,sysTime.wSecond); \
PCHAR pszStack = \
(PCHAR)_alloca( \
cchMaxAssertStackLevelStringLen * \
cfrMaxAssertStackLevels + 1); \
GetStringFromStackLevels(0, 10, pszStack); \
_RPT4(_CRT_WARN, \
"%s(%d): Failed HR = %s\n\n%s\n", \
__FILE__, \
__LINE__, \
pszHrWithTime, \
pszStack); \
PSpDebug()->HRFail(FALSE); \
} \
} while (0)
#else // ASSERT_WITH_STACK & !_WIN64
#define SPDBG_REPORT_ON_FAIL(hr) \
do \
{ \
HRESULT _hr = (hr); \
if (FAILED(_hr) && PSpDebug()->HRFail()) \
{ \
_RPT3(_CRT_WARN, "%s(%d): Failed HR = %lX\n", __FILE__, __LINE__, (_hr) );\
PSpDebug()->HRFail(FALSE); \
} \
} while (0)
#endif // ASSERT_WITH_STACK
#define SPDBG_ASSERT(expr) \
do \
{ \
if (!(expr)) \
{ \
if (PSpDebug()->Assert()) \
{ \
_ASSERTE( expr ); \
PSpDebug()->Assert(FALSE); \
} \
} \
} \
while (0)
#define SPDBG_VERIFY(expr) \
SPDBG_ASSERT(expr)
#define SPDBG_PMSG0(format) \
do \
{ \
if (PSpDebug()->ParamInfo()) \
{ \
_RPT0(_CRT_WARN, format); \
PSpDebug()->ParamInfo(FALSE); \
} \
} while (0)
#define SPDBG_PMSG1(format, arg1) \
do \
{ \
if (PSpDebug()->ParamInfo()) \
{ \
_RPT1(_CRT_WARN, format, arg1); \
PSpDebug()->ParamInfo(FALSE); \
} \
} while (0)
#define SPDBG_PMSG2(format, arg1, arg2) \
do \
{ \
if (PSpDebug()->ParamInfo()) \
{ \
_RPT2(_CRT_WARN, format, arg1, arg2); \
PSpDebug()->ParamInfo(FALSE); \
} \
} while (0)
#define SPDBG_PMSG3(format, arg1, arg2, arg3) \
do \
{ \
if (PSpDebug()->ParamInfo()) \
{ \
_RPT3(_CRT_WARN, format, arg1, arg2, arg3); \
PSpDebug()->ParamInfo(FALSE); \
} \
} while (0)
#define SPDBG_PMSG4(format, arg1, arg2, arg3, arg4) \
do \
{ \
if (PSpDebug()->ParamInfo()) \
{ \
_RPT4(_CRT_WARN, format, arg1, arg2, arg3, arg4); \
PSpDebug()->ParamInfo(FALSE); \
} \
} while (0)
#define SPDBG_DMSG0(format) \
do \
{ \
if (PSpDebug()->DumpInfo()) \
{ \
_RPT0(_CRT_WARN, format); \
PSpDebug()->DumpInfo(FALSE); \
} \
} while (0)
#define SPDBG_DMSG1(format, arg1) \
do \
{ \
if (PSpDebug()->DumpInfo()) \
{ \
_RPT1(_CRT_WARN, format, arg1); \
PSpDebug()->DumpInfo(FALSE); \
} \
} while (0)
#define SPDBG_DMSG2(format, arg1, arg2) \
do \
{ \
if (PSpDebug()->DumpInfo()) \
{ \
_RPT2(_CRT_WARN, format, arg1, arg2); \
PSpDebug()->DumpInfo(FALSE); \
} \
} while (0)
#define SPDBG_DMSG3(format, arg1, arg2, arg3) \
do \
{ \
if (PSpDebug()->DumpInfo()) \
{ \
_RPT3(_CRT_WARN, format, arg1, arg2, arg3); \
PSpDebug()->DumpInfo(FALSE); \
} \
} while (0)
#define SPDBG_DMSG4(format, arg1, arg2, arg3, arg4) \
do \
{ \
if (PSpDebug()->DumpInfo()) \
{ \
_RPT4(_CRT_WARN, format, arg1, arg2, arg3, arg4); \
PSpDebug()->DumpInfo(FALSE); \
} \
} while (0)
#define SPDBG_RETURN(hr) \
{ \
HRESULT __hr = (hr); \
if (FAILED(__hr)) \
{ \
SPDBG_REPORT_ON_FAIL(__hr); \
} \
return __hr; \
}
#define SPDBG_DEBUG_SERVER_ON_START() \
{ \
if (PSpDebug()->DebugServerOnStart()) \
{ \
if (MessageBox( \
GetDesktopWindow(), \
_T("Attach Debugger to the SAPI Server process?"), \
_T("SAPI"), \
MB_YESNO) == IDYES) \
{ \
USES_CONVERSION; \
TCHAR szCommand[MAX_PATH + 1]; \
wsprintf( \
szCommand, \
_T("msdev -p %d"), \
GetCurrentProcessId()); \
system(T2A(szCommand)); \
} \
} \
}
#define SPDBG_DEBUG_CLIENT_ON_START() \
{ \
if (PSpDebug()->DebugClientOnStart()) \
{ \
TCHAR szModule[MAX_PATH + 1]; \
szModule[0] = '\0'; \
TCHAR * pszSapiServer = \
_T("sapisvr.exe"); \
GetModuleFileName( \
NULL, \
szModule, \
MAX_PATH); \
if ((_tcslen(szModule) <= \
_tcslen(pszSapiServer) || \
_tcsicmp( \
szModule + \
_tcslen(szModule) - \
_tcslen(pszSapiServer), \
pszSapiServer) != 0) && \
MessageBox( \
GetDesktopWindow(), \
_T("Attach Debugger to the SAPI Client process?"), \
_T("SAPI"), \
MB_YESNO) == IDYES) \
{ \
USES_CONVERSION; \
TCHAR szCommand[MAX_PATH + 1]; \
wsprintf( \
szCommand, \
_T("msdev -p %d"), \
GetCurrentProcessId()); \
system(T2A(szCommand)); \
} \
} \
}
#else // _DEBUG
#define SPDBG_FUNC(name)
#define SPDBG_REPORT_ON_FAIL(hr)
#define SPDBG_ASSERT(expr)
#define SPDBG_VERIFY(expr) (expr)
#define SPDBG_PMSG0(format)
#define SPDBG_PMSG1(format, arg1)
#define SPDBG_PMSG2(format, arg1, arg2)
#define SPDBG_PMSG3(format, arg1, arg2, arg3)
#define SPDBG_PMSG4(format, arg1, arg2, arg3, arg4)
#define SPDBG_DMSG0(format)
#define SPDBG_DMSG1(format, arg1)
#define SPDBG_DMSG2(format, arg1, arg2)
#define SPDBG_DMSG3(format, arg1, arg2, arg3)
#define SPDBG_DMSG4(format, arg1, arg2, arg3, arg4)
#define SPDBG_RETURN(hr) return (hr)
#define SPDBG_DEBUG_SERVER_ON_START()
#define SPDBG_DEBUG_CLIENT_ON_START()
#endif // _DEBUG
+559
View File
@@ -0,0 +1,559 @@
/*******************************************************************************
* SPError.h *
*-----------*
* Description:
* This header file contains the custom error codes specific to SAPI5
*-------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
*******************************************************************************/
#ifndef SPError_h
#define SPError_h
#ifndef _WINERROR_
#include <winerror.h>
#endif
#define FACILITY_SAPI FACILITY_ITF
#define SAPI_ERROR_BASE 0x5000
#define MAKE_SAPI_HRESULT(sev, err) MAKE_HRESULT(sev, FACILITY_SAPI, err)
#define MAKE_SAPI_ERROR(err) MAKE_SAPI_HRESULT(SEVERITY_ERROR, err + SAPI_ERROR_BASE)
#define MAKE_SAPI_SCODE(scode) MAKE_SAPI_HRESULT(SEVERITY_SUCCESS, scode + SAPI_ERROR_BASE)
/*** SPERR_UNINITIALIZED 0x80045001 -2147201023
* The object has not been properly initialized.
*/
#define SPERR_UNINITIALIZED MAKE_SAPI_ERROR(0x001)
/*** SPERR_ALREADY_INITIALIZED 0x80045002 -2147201022
* The object has already been initialized.
*/
#define SPERR_ALREADY_INITIALIZED MAKE_SAPI_ERROR(0x002)
/*** SPERR_UNSUPPORTED_FORMAT 0x80045003 -2147201021
* The caller has specified an unsupported format.
*/
#define SPERR_UNSUPPORTED_FORMAT MAKE_SAPI_ERROR(0x003)
/*** SPERR_INVALID_FLAGS 0x80045004 -2147201020
* The caller has specified invalid flags for this operation.
*/
#define SPERR_INVALID_FLAGS MAKE_SAPI_ERROR(0x004)
/*** SP_END_OF_STREAM 0x00045005 282629
* The operation has reached the end of stream.
*/
#define SP_END_OF_STREAM MAKE_SAPI_SCODE(0x005)
/*** SPERR_DEVICE_BUSY 0x80045006 -2147201018
* The wave device is busy.
*/
#define SPERR_DEVICE_BUSY MAKE_SAPI_ERROR(0x006)
/*** SPERR_DEVICE_NOT_SUPPORTED 0x80045007 -2147201017
* The wave device is not supported.
*/
#define SPERR_DEVICE_NOT_SUPPORTED MAKE_SAPI_ERROR(0x007)
/*** SPERR_DEVICE_NOT_ENABLED 0x80045008 -2147201016
* The wave device is not enabled.
*/
#define SPERR_DEVICE_NOT_ENABLED MAKE_SAPI_ERROR(0x008)
/*** SPERR_NO_DRIVER 0x80045009 -2147201015
* There is no wave driver installed.
*/
#define SPERR_NO_DRIVER MAKE_SAPI_ERROR(0x009)
/*** SPERR_FILEMUSTBEUNICODE 0x8004500a -2147201014
* The file must be Unicode.
*/
#define SPERR_FILE_MUST_BE_UNICODE MAKE_SAPI_ERROR(0x00a)
/*** SP_INSUFFICIENTDATA 0x0004500b 282635
*
*/
#define SP_INSUFFICIENT_DATA MAKE_SAPI_SCODE(0x00b)
/*** SPERR_INVALID_PHRASE_ID 0x8004500c -2147201012
* The phrase ID specified does not exist or is out of range.
*/
#define SPERR_INVALID_PHRASE_ID MAKE_SAPI_ERROR(0x00c)
/*** SPERR_BUFFER_TOO_SMALL 0x8004500d -2147201011
* The caller provided a buffer too small to return a result.
*/
#define SPERR_BUFFER_TOO_SMALL MAKE_SAPI_ERROR(0x00d)
/*** SPERR_FORMAT_NOT_SPECIFIED 0x8004500e -2147201010
* Caller did not specify a format prior to opening a stream.
*/
#define SPERR_FORMAT_NOT_SPECIFIED MAKE_SAPI_ERROR(0x00e)
/*** SPERR_AUDIO_STOPPED 0x8004500f -2147201009
* This method is deprecated. Use SP_AUDIO_STOPPED instead.
*/
#define SPERR_AUDIO_STOPPED MAKE_SAPI_ERROR(0x00f)
/*** SP_AUDIO_PAUSED 0x00045010 282640
* This will be returned only on input (read) streams when the stream is paused. Reads on
* paused streams will not block, and this return code indicates that all of the data has been
* removed from the stream.
*/
#define SP_AUDIO_PAUSED MAKE_SAPI_SCODE(0x010)
/*** SPERR_RULE_NOT_FOUND 0x80045011 -2147201007
* Invalid rule name passed to ActivateGrammar.
*/
#define SPERR_RULE_NOT_FOUND MAKE_SAPI_ERROR(0x011)
/*** SPERR_TTS_ENGINE_EXCEPTION 0x80045012 -2147201006
* An exception was raised during a call to the current TTS driver.
*/
#define SPERR_TTS_ENGINE_EXCEPTION MAKE_SAPI_ERROR(0x012)
/*** SPERR_TTS_NLP_EXCEPTION 0x80045013 -2147201005
* An exception was raised during a call to an application sentence filter.
*/
#define SPERR_TTS_NLP_EXCEPTION MAKE_SAPI_ERROR(0x013)
/*** SPERR_ENGINE_BUSY 0x80045014 -2147201004
* In speech recognition, the current method can not be performed while
* a grammar rule is active.
*/
#define SPERR_ENGINE_BUSY MAKE_SAPI_ERROR(0x014)
/*** SP_AUDIO_CONVERSION_ENABLED 0x00045015 282645
* The operation was successful, but only with automatic stream format conversion.
*/
#define SP_AUDIO_CONVERSION_ENABLED MAKE_SAPI_SCODE(0x015)
/*** SP_NO_HYPOTHESIS_AVAILABLE 0x00045016 282646
* There is currently no hypothesis recognition available.
*/
#define SP_NO_HYPOTHESIS_AVAILABLE MAKE_SAPI_SCODE(0x016)
/*** SPERR_CANT_CREATE 0x80045017 -2147201001
* Can not create a new object instance for the specified object category.
*/
#define SPERR_CANT_CREATE MAKE_SAPI_ERROR(0x017)
/*** SP_ALREADY_IN_LEX 0x00045018 282648
* The word, pronunciation, or POS pair being added is already in lexicon.
*/
#define SP_ALREADY_IN_LEX MAKE_SAPI_SCODE(0x018)
/*** SPERR_NOT_IN_LEX 0x80045019 -2147200999
* The word does not exist in the lexicon.
*/
#define SPERR_NOT_IN_LEX MAKE_SAPI_ERROR(0x019)
/*** SP_LEX_NOTHING_TO_SYNC 0x0004501a 282650
* The client is currently synced with the lexicon.
*/
#define SP_LEX_NOTHING_TO_SYNC MAKE_SAPI_SCODE(0x01a)
/*** SPERR_LEX_VERY_OUT_OF_SYNC 0x8004501b -2147200997
* The client is excessively out of sync with the lexicon. Mismatches may not be incrementally sync'd.
*/
#define SPERR_LEX_VERY_OUT_OF_SYNC MAKE_SAPI_ERROR(0x01b)
/*** SPERR_UNDEFINED_FORWARD_RULE_REF 0x8004501c -2147200996
* A rule reference in a grammar was made to a named rule that was never defined.
*/
#define SPERR_UNDEFINED_FORWARD_RULE_REF MAKE_SAPI_ERROR(0x01c)
/*** SPERR_EMPTY_RULE 0x8004501d -2147200995
* A non-dynamic grammar rule that has no body.
*/
#define SPERR_EMPTY_RULE MAKE_SAPI_ERROR(0x01d)
/*** SPERR_GRAMMAR_COMPILER_INTERNAL_ERROR 0x8004501e -2147200994
* The grammar compiler failed due to an internal state error.
*/
#define SPERR_GRAMMAR_COMPILER_INTERNAL_ERROR MAKE_SAPI_ERROR(0x01e)
/*** SPERR_RULE_NOT_DYNAMIC 0x8004501f -2147200993
* An attempt was made to modify a non-dynamic rule.
*/
#define SPERR_RULE_NOT_DYNAMIC MAKE_SAPI_ERROR(0x01f)
/*** SPERR_DUPLICATE_RULE_NAME 0x80045020 -2147200992
* A rule name was duplicated.
*/
#define SPERR_DUPLICATE_RULE_NAME MAKE_SAPI_ERROR(0x020)
/*** SPERR_DUPLICATE_RESOURCE_NAME 0x80045021 -2147200991
* A resource name was duplicated for a given rule.
*/
#define SPERR_DUPLICATE_RESOURCE_NAME MAKE_SAPI_ERROR(0x021)
/*** SPERR_TOO_MANY_GRAMMARS 0x80045022 -2147200990
* Too many grammars have been loaded.
*/
#define SPERR_TOO_MANY_GRAMMARS MAKE_SAPI_ERROR(0x022)
/*** SPERR_CIRCULAR_REFERENCE 0x80045023 -2147200989
* Circular reference in import rules of grammars.
*/
#define SPERR_CIRCULAR_REFERENCE MAKE_SAPI_ERROR(0x023)
/*** SPERR_INVALID_IMPORT 0x80045024 -2147200988
* A rule reference to an imported grammar that could not be resolved.
*/
#define SPERR_INVALID_IMPORT MAKE_SAPI_ERROR(0x024)
/*** SPERR_INVALID_WAV_FILE 0x80045025 -2147200987
* The format of the WAV file is not supported.
*/
#define SPERR_INVALID_WAV_FILE MAKE_SAPI_ERROR(0x025)
/*** SP_REQUEST_PENDING 0x00045026 282662
* This success code indicates that an SR method called with the SPRIF_ASYNC flag is
* being processed. When it has finished processing, an SPFEI_ASYNC_COMPLETED event will be generated.
*/
#define SP_REQUEST_PENDING MAKE_SAPI_SCODE(0x026)
/*** SPERR_ALL_WORDS_OPTIONAL 0x80045027 -2147200985
* A grammar rule was defined with a null path through the rule. That is, it is possible
* to satisfy the rule conditions with no words.
*/
#define SPERR_ALL_WORDS_OPTIONAL MAKE_SAPI_ERROR(0x027)
/*** SPERR_INSTANCE_CHANGE_INVALID 0x80045028 -2147200984
* It is not possible to change the current engine or input. This occurs in the
* following cases:
*
* 1) SelectEngine called while a recognition context exists, or
* 2) SetInput called in the shared instance case.
*/
#define SPERR_INSTANCE_CHANGE_INVALID MAKE_SAPI_ERROR(0x028)
/*** SPERR_RULE_NAME_ID_CONFLICT 0x80045029 -2147200983
* A rule exists with matching IDs (names) but different names (IDs).
*/
#define SPERR_RULE_NAME_ID_CONFLICT MAKE_SAPI_ERROR(0x029)
/*** SPERR_NO_RULES 0x8004502a -2147200982
* A grammar contains no top-level, dynamic, or exported rules. There is no possible
* way to activate or otherwise use any rule in this grammar.
*/
#define SPERR_NO_RULES MAKE_SAPI_ERROR(0x02a)
/*** SPERR_CIRCULAR_RULE_REF 0x8004502b -2147200981
* Rule 'A' refers to a second rule 'B' which, in turn, refers to rule 'A'.
*/
#define SPERR_CIRCULAR_RULE_REF MAKE_SAPI_ERROR(0x02b)
/*** SP_NO_PARSE_FOUND 0x0004502c 282668
* Parse path cannot be parsed given the currently active rules.
*/
#define SP_NO_PARSE_FOUND MAKE_SAPI_SCODE(0x02c)
/*** SPERR_NO_PARSE_FOUND 0x8004502d -2147200979
* Parse path cannot be parsed given the currently active rules.
*/
#define SPERR_INVALID_HANDLE MAKE_SAPI_ERROR(0x02d)
/*** SPERR_REMOTE_CALL_TIMED_OUT 0x8004502e -2147200978
* A marshaled remote call failed to respond.
*/
#define SPERR_REMOTE_CALL_TIMED_OUT MAKE_SAPI_ERROR(0x02e)
/*** SPERR_AUDIO_BUFFER_OVERFLOW 0x8004502f -2147200977
* This will only be returned on input (read) streams when the stream is paused because
* the SR driver has not retrieved data recently.
*/
#define SPERR_AUDIO_BUFFER_OVERFLOW MAKE_SAPI_ERROR(0x02f)
/*** SPERR_NO_AUDIO_DATA 0x80045030 -2147200976
* The result does not contain any audio, nor does the portion of the element chain of the result
* contain any audio.
*/
#define SPERR_NO_AUDIO_DATA MAKE_SAPI_ERROR(0x030)
/*** SPERR_DEAD_ALTERNATE 0x80045031 -2147200975
* This alternate is no longer a valid alternate to the result it was obtained from.
* Returned from ISpPhraseAlt methods.
*/
#define SPERR_DEAD_ALTERNATE MAKE_SAPI_ERROR(0x031)
/*** SPERR_HIGH_LOW_CONFIDENCE 0x80045032 -2147200974
* The result does not contain any audio, nor does the portion of the element chain of the result
* contain any audio. Returned from ISpResult::GetAudio and ISpResult::SpeakAudio.
*/
#define SPERR_HIGH_LOW_CONFIDENCE MAKE_SAPI_ERROR(0x032)
/*** SPERR_INVALID_FORMAT_STRING 0x80045033 -2147200973
* The XML format string for this RULEREF is invalid, e.g. not a GUID or REFCLSID.
*/
#define SPERR_INVALID_FORMAT_STRING MAKE_SAPI_ERROR(0x033)
/*** SP_UNSUPPORTED_ON_STREAM_INPUT 0x00045034 282676
* The operation is not supported for stream input.
*/
#define SP_UNSUPPORTED_ON_STREAM_INPUT MAKE_SAPI_SCODE(0x034)
/*** SPERR_APPLEX_READ_ONLY 0x80045035 -2147200971
* The operation is invalid for all but newly created application lexicons.
*/
#define SPERR_APPLEX_READ_ONLY MAKE_SAPI_ERROR(0x035)
/*** SPERR_NO_TERMINATING_RULE_PATH 0x80045036 -2147200970
*
*/
#define SPERR_NO_TERMINATING_RULE_PATH MAKE_SAPI_ERROR(0x036)
/*** SP_WORD_EXISTS_WITHOUT_PRONUNCIATION 0x00045037 282679
* The word exists but without pronunciation.
*/
#define SP_WORD_EXISTS_WITHOUT_PRONUNCIATION MAKE_SAPI_SCODE(0x037)
/*** SPERR_STREAM_CLOSED 0x80045038 -2147200968
* An operation was attempted on a stream object that has been closed.
*/
#define SPERR_STREAM_CLOSED MAKE_SAPI_ERROR(0x038)
// --- The following error codes are taken directly from WIN32 ---
/*** SPERR_NO_MORE_ITEMS 0x80045039 -2147200967
* When enumerating items, the requested index is greater than the count of items.
*/
#define SPERR_NO_MORE_ITEMS MAKE_SAPI_ERROR(0x039)
/*** SPERR_NOT_FOUND 0x8004503a -2147200966
* The requested data item (data key, value, etc.) was not found.
*/
#define SPERR_NOT_FOUND MAKE_SAPI_ERROR(0x03a)
/*** SPERR_INVALID_AUDIO_STATE 0x8004503b -2147200965
* Audio state passed to SetState() is invalid.
*/
#define SPERR_INVALID_AUDIO_STATE MAKE_SAPI_ERROR(0x03b)
/*** SPERR_GENERIC_MMSYS_ERROR 0x8004503c -2147200964
* A generic MMSYS error not caught by _MMRESULT_TO_HRESULT.
*/
#define SPERR_GENERIC_MMSYS_ERROR MAKE_SAPI_ERROR(0x03c)
/*** SPERR_MARSHALER_EXCEPTION 0x8004503d -2147200963
* An exception was raised during a call to the marshaling code.
*/
#define SPERR_MARSHALER_EXCEPTION MAKE_SAPI_ERROR(0x03d)
/*** SPERR_NOT_DYNAMIC_GRAMMAR 0x8004503e -2147200962
* Attempt was made to manipulate a non-dynamic grammar.
*/
#define SPERR_NOT_DYNAMIC_GRAMMAR MAKE_SAPI_ERROR(0x03e)
/*** SPERR_AMBIGUOUS_PROPERTY 0x8004503f -2147200961
* Cannot add ambiguous property.
*/
#define SPERR_AMBIGUOUS_PROPERTY MAKE_SAPI_ERROR(0x03f)
/*** SPERR_INVALID_REGISTRY_KEY 0x80045040 -2147200960
* The key specified is invalid.
*/
#define SPERR_INVALID_REGISTRY_KEY MAKE_SAPI_ERROR(0x040)
/*** SPERR_INVALID_TOKEN_ID 0x80045041 -2147200959
* The token specified is invalid.
*/
#define SPERR_INVALID_TOKEN_ID MAKE_SAPI_ERROR(0x041)
/*** SPERR_XML_BAD_SYNTAX 0x80045042 -2147200958
* The xml parser failed due to bad syntax.
*/
#define SPERR_XML_BAD_SYNTAX MAKE_SAPI_ERROR(0x042)
/*** SPERR_XML_RESOURCE_NOT_FOUND 0x80045043 -2147200957
* The xml parser failed to load a required resource (e.g., voice, phoneconverter, etc.).
*/
#define SPERR_XML_RESOURCE_NOT_FOUND MAKE_SAPI_ERROR(0x043)
/*** SPERR_TOKEN_IN_USE 0x80045044 -2147200956
* Attempted to remove registry data from a token that is already in use elsewhere.
*/
#define SPERR_TOKEN_IN_USE MAKE_SAPI_ERROR(0x044)
/*** SPERR_TOKEN_DELETED 0x80045045 -2147200955
* Attempted to perform an action on an object token that has had associated registry key deleted.
*/
#define SPERR_TOKEN_DELETED MAKE_SAPI_ERROR(0x045)
/*** SPERR_MULTI_LINGUAL_NOT_SUPPORTED 0x80045046 -2147200954
* The selected voice was registered as multi-lingual. SAPI does not support multi-lingual registration.
*/
#define SPERR_MULTI_LINGUAL_NOT_SUPPORTED MAKE_SAPI_ERROR(0x046)
/*** SPERR_EXPORT_DYNAMIC_RULE 0x80045047 -2147200953
* Exported rules cannot refer directly or indirectly to a dynamic rule.
*/
#define SPERR_EXPORT_DYNAMIC_RULE MAKE_SAPI_ERROR(0x047)
/*** SPERR_STGF_ERROR 0x80045048 -2147200952
* Error parsing the SAPI Text Grammar Format (XML grammar).
*/
#define SPERR_STGF_ERROR MAKE_SAPI_ERROR(0x048)
/*** SPERR_WORDFORMAT_ERROR 0x80045049 -2147200951
* Incorrect word format, probably due to incorrect pronunciation string.
*/
#define SPERR_WORDFORMAT_ERROR MAKE_SAPI_ERROR(0x049)
/*** SPERR_STREAM_NOT_ACTIVE 0x8004504a -2147200950
* Methods associated with active audio stream cannot be called unless stream is active.
*/
#define SPERR_STREAM_NOT_ACTIVE MAKE_SAPI_ERROR(0x04a)
/*** SPERR_ENGINE_RESPONSE_INVALID 0x8004504b -2147200949
* Arguments or data supplied by the engine are in an invalid format or are inconsistent.
*/
#define SPERR_ENGINE_RESPONSE_INVALID MAKE_SAPI_ERROR(0x04b)
/*** SPERR_SR_ENGINE_EXCEPTION 0x8004504c -2147200948
* An exception was raised during a call to the current SR engine.
*/
#define SPERR_SR_ENGINE_EXCEPTION MAKE_SAPI_ERROR(0x04c)
/*** SPERR_STREAM_POS_INVALID 0x8004504d -2147200947
* Stream position information supplied from engine is inconsistent.
*/
#define SPERR_STREAM_POS_INVALID MAKE_SAPI_ERROR(0x04d)
/*** SP_RECOGNIZER_INACTIVE 0x0004504e 282702
* Operation could not be completed because the recognizer is inactive. It is inactive either
* because the recognition state is currently inactive or because no rules are active .
*/
#define SP_RECOGNIZER_INACTIVE MAKE_SAPI_SCODE(0x04e)
/*** SPERR_REMOTE_CALL_ON_WRONG_THREAD 0x8004504f -2147200945
* When making a remote call to the server, the call was made on the wrong thread.
*/
#define SPERR_REMOTE_CALL_ON_WRONG_THREAD MAKE_SAPI_ERROR(0x04f)
/*** SPERR_REMOTE_PROCESS_TERMINATED 0x80045050 -2147200944
* The remote process terminated unexpectedly.
*/
#define SPERR_REMOTE_PROCESS_TERMINATED MAKE_SAPI_ERROR(0x050)
/*** SPERR_REMOTE_PROCESS_ALREADY_RUNNING 0x80045051 -2147200943
* The remote process is already running; it cannot be started a second time.
*/
#define SPERR_REMOTE_PROCESS_ALREADY_RUNNING MAKE_SAPI_ERROR(0x051)
/*** SPERR_LANGID_MISMATCH 0x80045052 -2147200942
* An attempt to load a CFG grammar with a LANGID different than other loaded grammars.
*/
#define SPERR_LANGID_MISMATCH MAKE_SAPI_ERROR(0x052)
/*** SP_PARTIAL_PARSE_FOUND 0x00045053 282707
* A grammar-ending parse has been found that does not use all available words.
*/
#define SP_PARTIAL_PARSE_FOUND MAKE_SAPI_SCODE(0x053)
/*** SPERR_NOT_TOPLEVEL_RULE 0x80045054 -2147200940
* An attempt to deactivate or activate a non-toplevel rule.
*/
#define SPERR_NOT_TOPLEVEL_RULE MAKE_SAPI_ERROR(0x054)
/*** SP_NO_RULE_ACTIVE 0x00045055 282709
* An attempt to parse when no rule was active.
*/
#define SP_NO_RULE_ACTIVE MAKE_SAPI_SCODE(0x055)
/*** SPERR_LEX_REQUIRES_COOKIE 0x80045056 -2147200938
* An attempt to ask a container lexicon for all words at once.
*/
#define SPERR_LEX_REQUIRES_COOKIE MAKE_SAPI_ERROR(0x056)
/*** SP_STREAM_UNINITIALIZED 0x00045057 282711
* An attempt to activate a rule/dictation/etc without calling SetInput
* first in the inproc case.
*/
#define SP_STREAM_UNINITIALIZED MAKE_SAPI_SCODE(0x057)
// Error x058 is not used in SAPI 5.0
/*** SPERR_UNSUPPORTED_LANG 0x80045059 -2147200935
* The requested language is not supported.
*/
#define SPERR_UNSUPPORTED_LANG MAKE_SAPI_ERROR(0x059)
/*** SPERR_VOICE_PAUSED 0x8004505a -2147200934
* The operation cannot be performed because the voice is currently paused.
*/
#define SPERR_VOICE_PAUSED MAKE_SAPI_ERROR(0x05a)
/*** SPERR_AUDIO_BUFFER_UNDERFLOW 0x8004505b -2147200933
* This will only be returned on input (read) streams when the real time audio device
* stops returning data for a long period of time.
*/
#define SPERR_AUDIO_BUFFER_UNDERFLOW MAKE_SAPI_ERROR(0x05b)
/*** SPERR_AUDIO_STOPPED_UNEXPECTEDLY 0x8004505c -2147200932
* An audio device stopped returning data from the Read() method even though it was in
* the run state. This error is only returned in the END_SR_STREAM event.
*/
#define SPERR_AUDIO_STOPPED_UNEXPECTEDLY MAKE_SAPI_ERROR(0x05c)
/*** SPERR_NO_WORD_PRONUNCIATION 0x8004505d -2147200931
* The SR engine is unable to add this word to a grammar. The application may need to supply
* an explicit pronunciation for this word.
*/
#define SPERR_NO_WORD_PRONUNCIATION MAKE_SAPI_ERROR(0x05d)
/*** SPERR_ALTERNATES_WOULD_BE_INCONSISTENT 0x8004505e -2147200930
* An attempt to call ScaleAudio on a recognition result having previously
* called GetAlternates. Allowing the call to succeed would result in
* the previously created alternates located in incorrect audio stream positions.
*/
#define SPERR_ALTERNATES_WOULD_BE_INCONSISTENT MAKE_SAPI_ERROR(0x05e)
/*** SPERR_NOT_SUPPORTED_FOR_SHARED_RECOGNIZER 0x8004505f -2147200929
* The method called is not supported for the shared recognizer.
* For example, ISpRecognizer::GetInputStream().
*/
#define SPERR_NOT_SUPPORTED_FOR_SHARED_RECOGNIZER MAKE_SAPI_ERROR(0x05f)
/*** SPERR_TIMEOUT 0x80045060 -2147200928
* A task could not complete because the SR engine had timed out.
*/
#define SPERR_TIMEOUT MAKE_SAPI_ERROR(0x060)
/*** SPERR_REENTER_SYNCHRONIZE 0x80045061 -2147200927
* A SR engine called synchronize while inside of a synchronize call.
*/
#define SPERR_REENTER_SYNCHRONIZE MAKE_SAPI_ERROR(0x061)
/*** SPERR_STATE_WITH_NO_ARCS 0x80045062 -2147200926
* The grammar contains a node no arcs.
*/
#define SPERR_STATE_WITH_NO_ARCS MAKE_SAPI_ERROR(0x062)
/*** SPERR_NOT_ACTIVE_SESSION 0x80045063 -2147200925
* Neither audio output and input is supported for non-active console sessions.
*/
#define SPERR_NOT_ACTIVE_SESSION MAKE_SAPI_ERROR(0x063)
/*** SPERR_ALREADY_DELETED 0x80045064 -2147200924
* The object is a stale reference and is invalid to use.
* For example having a ISpeechGrammarRule object reference and then calling
* ISpeechRecoGrammar::Reset() will cause the rule object to be invalidated.
* Calling any methods after this will result in this error.
*/
#define SPERR_ALREADY_DELETED MAKE_SAPI_ERROR(0x064)
/*** SP_AUDIO_STOPPED 0x00045065 282725
* This can be returned from Read or Write calls audio streams when the stream is stopped.
*/
#define SP_AUDIO_STOPPED MAKE_SAPI_SCODE(0x065)
#endif //--- This must be the last line in the file
+605
View File
@@ -0,0 +1,605 @@
/*******************************************************************************
* SPEventQ.h *
*------------*
* Description:
* This is the header file for the SAPI5 event queue implementation.
*-------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
*******************************************************************************/
#ifndef SPEventQ_h
#define SPEventQ_h
#ifndef SPHelper_h
#include <SPHelper.h>
#endif
#ifndef SPCollec_h
#include <SPCollec.h>
#endif
//=== Inline helpers for copying and deleting events ============================
//=== Class definition ==========================================================
class CSpEventNode : public CSpEvent
{
public:
CSpEventNode * m_pNext;
static LONG Compare(const CSpEventNode * p1, const CSpEventNode *p2)
{
// Assumes offsets DO or DO NOT reset when stream number changes
if (p1->ulStreamNum < p2->ulStreamNum)
{
return -1;
}
else if (p1->ulStreamNum > p2->ulStreamNum)
{
return 1;
}
else if (p1->ullAudioStreamOffset < p2->ullAudioStreamOffset)
{
return -1;
}
else if (p1->ullAudioStreamOffset > p2->ullAudioStreamOffset)
{
return 1;
}
return 0;
}
};
typedef CSpBasicQueue<CSpEventNode, TRUE, TRUE> CSpEventList;
#define DECLARE_SPNOTIFYSOURCE_METHODS(T) \
STDMETHODIMP SetNotifySink(ISpNotifySink * pNotifySink) \
{ return T._SetNotifySink(pNotifySink); } \
STDMETHODIMP SetNotifyWindowMessage(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) \
{ return T._SetNotifyWindowMessage(hWnd, Msg, wParam, lParam); } \
STDMETHODIMP SetNotifyCallbackFunction(SPNOTIFYCALLBACK * pfnCallback, WPARAM wParam, LPARAM lParam) \
{ return T._SetNotifyCallbackFunction(pfnCallback, wParam, lParam); } \
STDMETHODIMP SetNotifyCallbackInterface(ISpNotifyCallback * pSpCallback, WPARAM wParam, LPARAM lParam) \
{ return T._SetNotifyCallbackInterface(pSpCallback, wParam, lParam); } \
STDMETHODIMP SetNotifyWin32Event() \
{ return T._SetNotifyWin32Event(); } \
STDMETHODIMP WaitForNotifyEvent(DWORD dwMilliseconds) \
{ return T._WaitForNotifyEvent(dwMilliseconds); } \
STDMETHODIMP_(HANDLE) GetNotifyEventHandle() \
{ return T._GetNotifyEventHandle(); }
#define DECLARE_SPEVENTSOURCE_METHODS(T) \
DECLARE_SPNOTIFYSOURCE_METHODS(T) \
STDMETHODIMP SetInterest(ULONGLONG ullEventInterest, ULONGLONG ullQueuedInterest) \
{ return T._SetInterest(ullEventInterest, ullQueuedInterest); } \
STDMETHODIMP GetEvents(ULONG ulCount, SPEVENT* pEventArray, ULONG * pulFetched) \
{ return T._GetEvents(ulCount, pEventArray, pulFetched); } \
STDMETHODIMP GetInfo(SPEVENTSOURCEINFO *pInfo) \
{ return T._GetInfo(pInfo); }
class CSpEventSource
{
public:
CSpEventSource(CComObjectRootEx<CComMultiThreadModel> * pParent) :
m_pParent(pParent)
{
m_ullEventInterest = 0; m_ullQueuedInterest = 0;
m_ulStreamNum = 0;
}
HRESULT _SetNotifySink(ISpNotifySink * pNotifySink);
HRESULT _SetNotifyWindowMessage(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
HRESULT _SetNotifyCallbackFunction(SPNOTIFYCALLBACK * pfnCallback, WPARAM wParam, LPARAM lParam);
HRESULT _SetNotifyCallbackInterface(ISpNotifyCallback * pSpCallback, WPARAM wParam, LPARAM lParam);
HRESULT _SetNotifyWin32Event();
HRESULT _WaitForNotifyEvent(DWORD dwMilliseconds);
HANDLE _GetNotifyEventHandle();
HRESULT _SetInterest(ULONGLONG ullEventInterest , ULONGLONG ullQueuedInterest);
HRESULT _GetEvents( ULONG ulCount, SPEVENT* pEventArray, ULONG * pulFetched );
HRESULT _GetInfo(SPEVENTSOURCEINFO *pInfo );
/*--- Non interface methods ---*/
HRESULT _CompleteEvents( ULONGLONG ullPos = 0xFFFFFFFFFFFFFFFF );
inline void _MoveAllToFreeList(CSpEventList * pList);
inline void _RemoveAllEvents();
inline HRESULT _AddEvent(const SPEVENT & Event);
inline HRESULT _AddEvents(const SPEVENT* pEventArray, ULONG ulCount);
inline HRESULT _DeserializeAndAddEvent(const BYTE * pBuffer, ULONG * pcbUsed);
inline HRESULT _GetStreamNumber(const ULONGLONG ullAudioOffset, ULONG *pulStreamNum);
//=== Data members ==============================
public:
ULONGLONG m_ullEventInterest;
ULONGLONG m_ullQueuedInterest;
ULONG m_ulStreamNum;
CSpEventList m_PendingList;
CSpEventList m_CompletedList;
CSpEventList m_FreeList;
CComPtr<ISpNotifySink> m_cpNotifySink;
CComPtr<ISpNotifyTranslator> m_cpEventTranslator; // If non-NULL then Win32 events being used
CComObjectRootEx<CComMultiThreadModel> * m_pParent;
CComAutoCriticalSection m_NotifyObjChangeCrit; // Critical section used to make sure that
// the notify object (m_cpNotifySink) not changed
// while waiting on it.
};
//
//=== Inlines =========================================================
//
//
// WARNING: If this logic changes, you will need to change the logic in SetNotifyWin32Event also.
//
inline HRESULT CSpEventSource::_SetNotifySink(ISpNotifySink * pNotifySink)
{
if (SP_IS_BAD_OPTIONAL_INTERFACE_PTR(pNotifySink))
{
return E_INVALIDARG;
}
else
{
m_pParent->Lock();
m_NotifyObjChangeCrit.Lock();
m_cpEventTranslator.Release();
m_cpNotifySink = pNotifySink;
if (m_cpNotifySink && m_CompletedList.GetHead())
{
m_cpNotifySink->Notify();
}
m_NotifyObjChangeCrit.Unlock();
m_pParent->Unlock();
return S_OK;
}
}
/****************************************************************************
* CSpEventSource::_SetNotifyWindowMessage *
*-----------------------------------------*
* Description:
*
* Returns:
*
********************************************************************* RAL ***/
inline HRESULT CSpEventSource::_SetNotifyWindowMessage(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
SPDBG_FUNC("CSpEventSource::_SetNotifyWindowMessage");
HRESULT hr = S_OK;
CComPtr<ISpNotifyTranslator> cpTranslator;
hr = cpTranslator.CoCreateInstance(CLSID_SpNotifyTranslator);
if (SUCCEEDED(hr))
{
hr = cpTranslator->InitWindowMessage(hWnd, Msg, wParam, lParam);
}
if (SUCCEEDED(hr))
{
hr = _SetNotifySink(cpTranslator);
}
return hr;
}
/****************************************************************************
* CSpEventSource::_SetNotifyCallbackFunction *
*--------------------------------------------*
* Description:
*
* Returns:
*
********************************************************************* RAL ***/
inline HRESULT CSpEventSource::_SetNotifyCallbackFunction(SPNOTIFYCALLBACK * pfnCallback, WPARAM wParam, LPARAM lParam)
{
SPDBG_FUNC("CSpEventSource::_SetNotifyCallbackFunction");
HRESULT hr = S_OK;
CComPtr<ISpNotifyTranslator> cpTranslator;
hr = cpTranslator.CoCreateInstance(CLSID_SpNotifyTranslator);
if (SUCCEEDED(hr))
{
hr = cpTranslator->InitCallback(pfnCallback, wParam, lParam);
}
if (SUCCEEDED(hr))
{
hr = _SetNotifySink(cpTranslator);
}
return hr;
}
/****************************************************************************
* CSpEventSource::_SetNotifyCallbackInterface *
*---------------------------------------------*
* Description:
*
* Returns:
*
********************************************************************* RAL ***/
inline HRESULT CSpEventSource::_SetNotifyCallbackInterface(ISpNotifyCallback * pSpCallback, WPARAM wParam, LPARAM lParam)
{
SPDBG_FUNC("CSpEventSource::_SetNotifyCallbackInterface");
HRESULT hr = S_OK;
CComPtr<ISpNotifyTranslator> cpTranslator;
hr = cpTranslator.CoCreateInstance(CLSID_SpNotifyTranslator);
if (SUCCEEDED(hr))
{
hr = cpTranslator->InitSpNotifyCallback(pSpCallback, wParam, lParam);
}
if (SUCCEEDED(hr))
{
hr = _SetNotifySink(cpTranslator);
}
return hr;
}
/****************************************************************************
* CSpEventSource::_SetNotifyWin32Event *
*--------------------------------------*
* Description:
*
* Returns:
*
********************************************************************* RAL ***/
inline HRESULT CSpEventSource::_SetNotifyWin32Event(void)
{
SPDBG_FUNC("CSpEventSource::_SetNotifyWin32Event");
HRESULT hr = S_OK;
CComPtr<ISpNotifyTranslator> cpTranslator;
hr = cpTranslator.CoCreateInstance(CLSID_SpNotifyTranslator);
if (SUCCEEDED(hr))
{
hr = cpTranslator->InitWin32Event(NULL, TRUE);
}
if (SUCCEEDED(hr))
{
//
// In this case we do NOT call _SetNotify sink since we want to set the cpEventTranslator
//
m_pParent->Lock();
m_NotifyObjChangeCrit.Lock();
m_cpEventTranslator = cpTranslator;
m_cpNotifySink = cpTranslator;
if (m_cpNotifySink && m_CompletedList.GetHead())
{
m_cpNotifySink->Notify();
}
m_NotifyObjChangeCrit.Unlock();
m_pParent->Unlock();
}
return hr;
}
/****************************************************************************
* CSpEventSource::_WaitForNotifyEvent *
*-------------------------------------*
* Description:
*
* Returns:
*
********************************************************************* RAL ***/
inline HRESULT CSpEventSource::_WaitForNotifyEvent(DWORD dwMilliseconds)
{
SPDBG_FUNC("CSpEventSource::_WaitForNotifyEvent");
HRESULT hr = S_OK;
m_NotifyObjChangeCrit.Lock();
if (m_cpEventTranslator)
{
hr = m_cpEventTranslator->Wait(dwMilliseconds);
}
else
{
if (m_cpNotifySink)
{
hr = SPERR_ALREADY_INITIALIZED;
}
else
{
hr = _SetNotifyWin32Event();
if (SUCCEEDED(hr))
{
hr = m_cpEventTranslator->Wait(dwMilliseconds);
}
}
}
m_NotifyObjChangeCrit.Unlock();
return hr;
}
/****************************************************************************
* CSpEventSource::_GetNotifyEventHandle *
*---------------------------------------*
* Description:
*
* Returns:
*
********************************************************************* RAL ***/
inline HANDLE CSpEventSource::_GetNotifyEventHandle()
{
HANDLE h = NULL;
SPDBG_FUNC("CSpEventSource::_GetNotifyEventHandle");
m_NotifyObjChangeCrit.Lock();
if (!m_cpNotifySink)
{
_SetNotifyWin32Event();
}
if (m_cpEventTranslator)
{
h = m_cpEventTranslator->GetEventHandle();
}
m_NotifyObjChangeCrit.Unlock();
return h;
}
inline HRESULT CSpEventSource::_SetInterest( ULONGLONG ullEventInterest, ULONGLONG ullQueuedInterest )
{
HRESULT hr = S_OK;
m_pParent->Lock();
if(ullEventInterest && SPFEI_FLAGCHECK != (ullEventInterest & SPFEI_FLAGCHECK))
{
hr = E_INVALIDARG;
}
else if(ullQueuedInterest && SPFEI_FLAGCHECK != (ullQueuedInterest & SPFEI_FLAGCHECK))
{
hr = E_INVALIDARG;
}
else if ((ullQueuedInterest | ullEventInterest) != ullEventInterest)
{
hr = E_INVALIDARG;
}
else
{
m_ullEventInterest = ullEventInterest;
m_ullQueuedInterest = ullQueuedInterest;
}
m_pParent->Unlock();
return hr;
}
//
// Same as AddEvents except: No param validation, and caller must take the critical section
// prior to calling.
//
inline HRESULT CSpEventSource::_AddEvents( const SPEVENT* pEventArray, ULONG ulCount )
{
HRESULT hr = S_OK;
for( ULONG i = 0; i < ulCount && SUCCEEDED(hr = _AddEvent(pEventArray[i])); ++i ) {}
return hr;
}
inline HRESULT CSpEventSource::_AddEvent(const SPEVENT & Event)
{
SPDBG_ASSERT(Event.eEventId < 64);
SPDBG_ASSERT(Event.elParamType == SPET_LPARAM_IS_UNDEFINED ||
Event.elParamType == SPET_LPARAM_IS_TOKEN ||
Event.elParamType == SPET_LPARAM_IS_OBJECT ||
Event.elParamType == SPET_LPARAM_IS_POINTER ||
Event.elParamType == SPET_LPARAM_IS_STRING);
#ifdef _DEBUG
if (Event.eEventId == SPEI_VOICE_CHANGE)
{
SPDBG_ASSERT(Event.elParamType == SPET_LPARAM_IS_TOKEN);
}
else if (Event.eEventId == SPEI_RECOGNITION || Event.eEventId == SPEI_FALSE_RECOGNITION || Event.eEventId == SPEI_HYPOTHESIS)
{
SPDBG_ASSERT(Event.elParamType == SPET_LPARAM_IS_OBJECT);
}
else if (Event.eEventId ==SPEI_REQUEST_UI || Event.eEventId == SPEI_TTS_BOOKMARK)
{
SPDBG_ASSERT(Event.elParamType == SPET_LPARAM_IS_STRING);
}
#endif
if ( (1i64 << Event.eEventId) & m_ullEventInterest )
{
CSpEventNode *pNode = m_FreeList.RemoveHead();
if (pNode == NULL)
{
pNode = new CSpEventNode();
if (pNode == NULL)
{
return E_OUTOFMEMORY;
}
}
pNode->CopyFrom(&Event);
m_PendingList.InsertSorted(pNode);
}
return S_OK;
}
inline HRESULT CSpEventSource::
_DeserializeAndAddEvent(const BYTE *pBuffer, ULONG * pcbUsed)
{
HRESULT hr = S_OK;
const SPEVENT * pSrcEvent = (const SPEVENT *)pBuffer;
SPDBG_ASSERT(pSrcEvent->eEventId < 64);
if ( (1i64 << pSrcEvent->eEventId) & m_ullEventInterest )
{
CSpEventNode *pNode = m_FreeList.RemoveHead();
if (pNode == NULL)
{
pNode = new CSpEventNode();
if (pNode == NULL)
{
hr = E_OUTOFMEMORY;
}
}
if (SUCCEEDED(hr))
{
hr = pNode->Deserialize(((const SPSERIALIZEDEVENT64 *)(pBuffer)), pcbUsed);
if (SUCCEEDED(hr))
{
m_PendingList.InsertSorted(pNode);
}
else
{
m_FreeList.InsertHead(pNode);
}
}
}
else
{
// WCE compiler does not work propertly with template
#ifndef _WIN32_WCE
*pcbUsed = SpEventSerializeSize<SPSERIALIZEDEVENT64>(pSrcEvent);
#else
*pcbUsed = SpEventSerializeSize(pSrcEvent, sizeof(SPSERIALIZEDEVENT64));
#endif
}
return hr;
}
inline HRESULT CSpEventSource::_GetEvents( ULONG ulCount, SPEVENT* pEventArray, ULONG *pulFetched )
{
HRESULT hr = S_OK;
m_pParent->Lock();
if( SPIsBadWritePtr( pEventArray, sizeof( SPEVENT ) * ulCount ) ||
SP_IS_BAD_OPTIONAL_WRITE_PTR(pulFetched) )
{
hr = E_INVALIDARG;
}
else
{
ULONG ulCopied = 0;
ULONG ulRemaining = ulCount;
CSpEventNode * pCur = m_CompletedList.m_pHead;
CSpEventNode * pLastCopied = NULL;
while (ulRemaining && pCur)
{
pCur->Detach(pEventArray + ulCopied);
pLastCopied = pCur;
ulCopied++;
pCur = pCur->m_pNext;
ulRemaining--;
}
if (ulCopied)
{
if (m_FreeList.m_pHead == NULL)
{
m_FreeList.m_pTail = pLastCopied;
}
pLastCopied->m_pNext = m_FreeList.m_pHead;
m_FreeList.m_pHead = m_CompletedList.m_pHead;
m_CompletedList.m_pHead = pCur;
m_CompletedList.m_cElements -= ulCopied;
m_FreeList.m_cElements += ulCopied;
}
if (ulCopied < ulCount)
{
hr = S_FALSE;
}
if (pulFetched)
{
*pulFetched = ulCopied;
}
}
m_pParent->Unlock();
return hr;
}
inline HRESULT CSpEventSource::_GetInfo( SPEVENTSOURCEINFO * pInfo )
{
HRESULT hr = S_OK;
m_pParent->Lock();
if( SP_IS_BAD_WRITE_PTR( pInfo ) )
{
hr = E_POINTER;
}
else
{
pInfo->ulCount = m_CompletedList.GetCount();
pInfo->ullEventInterest = m_ullEventInterest;
pInfo->ullQueuedInterest= m_ullQueuedInterest;
}
m_pParent->Unlock();
return hr;
}
//
// The caller must call this function with the critical section owned
//
inline HRESULT CSpEventSource::_CompleteEvents( ULONGLONG ullPos )
{
HRESULT hr = S_OK;
if (m_PendingList.m_pHead && m_PendingList.m_pHead->ullAudioStreamOffset <= ullPos)
{
BOOL bNotify = FALSE;
while (m_PendingList.m_pHead &&
m_PendingList.m_pHead->ullAudioStreamOffset <= ullPos)
{
CSpEventNode *pNode = m_PendingList.RemoveHead();
if(pNode->ulStreamNum != m_ulStreamNum)
{
m_ulStreamNum = pNode->ulStreamNum;
}
if ( (1i64 << pNode->eEventId) & m_ullEventInterest )
{
bNotify = TRUE;
//
// NOTE: If we're forwarding events to an event sink then we'll only
// pay attention to the Interest flags. If we're going to notify, then
// we'll only queue completed events that the user has explicitly asked
// us to store as completed events.
//
if ( (1i64 << pNode->eEventId) & m_ullQueuedInterest )
{
m_CompletedList.InsertSorted(pNode);
}
else
{
pNode->Clear();
m_FreeList.InsertHead(pNode);
}
}
else
{
pNode->Clear();
m_FreeList.InsertHead(pNode);
}
}
if (bNotify && m_cpNotifySink)
{
hr = m_cpNotifySink->Notify();
}
}
return hr;
};
inline void CSpEventSource::_MoveAllToFreeList(CSpEventList * pList)
{
CSpEventNode * pNode;
while ((pNode = pList->RemoveHead()) != NULL)
{
pNode->Clear();
m_FreeList.InsertHead(pNode);
}
}
inline void CSpEventSource::_RemoveAllEvents( )
{
m_pParent->Lock();
_MoveAllToFreeList(&m_CompletedList);
_MoveAllToFreeList(&m_PendingList);
m_pParent->Unlock();
}
inline HRESULT CSpEventSource::_GetStreamNumber(const ULONGLONG ullAudioOffset, ULONG *pulStreamNum)
{
CSpEventNode *pNode = m_PendingList.m_pHead;
*pulStreamNum = m_ulStreamNum;
for(;pNode && pNode->ullAudioStreamOffset <= ullAudioOffset; pNode = pNode->m_pNext)
{
*pulStreamNum = pNode->ulStreamNum;
}
return S_OK;
}
#endif //--- This must be the last line in this file
File diff suppressed because it is too large Load Diff
+253
View File
@@ -0,0 +1,253 @@
/*******************************************************************************
* SPUIHelp.h *
*------------*
* Description:
* This is the header file for user-interface helper functions. Note that
* unlike SpHelper.H, this file requires the use of ATL.
*-------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
*******************************************************************************/
#ifndef SPUIHelp_h
#define SPUIHelp_h
#ifndef __sapi_h__
#include <sapi.h>
#endif
#ifndef SPError_h
#include <SPError.h>
#endif
#ifndef SPDebug_h
#include <SPDebug.h>
#endif
#ifndef SPHelper_h
#include <SPHelper.h>
#endif
#ifndef __ATLBASE_H__
#include <ATLBASE.h>
#endif
#ifndef __ATLCONV_H__
#include <ATLCONV.H>
#endif
/****************************************************************************
*
*
*
********************************************************************* RAL ***/
//
// Dont call this function directly. Use SpInitTokenComboBox or SpInitTokenListBox.
//
inline HRESULT SpInitTokenList(UINT MsgAddString, UINT MsgSetItemData, UINT MsgSetCurSel,
HWND hwnd, const WCHAR * pszCatName,
const WCHAR * pszRequiredAttrib, const WCHAR * pszOptionalAttrib)
{
HRESULT hr;
ISpObjectToken * pToken; // NOTE: Not a CComPtr! Be Careful.
CComPtr<IEnumSpObjectTokens> cpEnum;
hr = SpEnumTokens(pszCatName, pszRequiredAttrib, pszOptionalAttrib, &cpEnum);
if (hr == S_OK)
{
bool fSetDefault = false;
while (cpEnum->Next(1, &pToken, NULL) == S_OK)
{
CSpDynamicString dstrDesc;
hr = SpGetDescription(pToken, &dstrDesc);
if (SUCCEEDED(hr))
{
USES_CONVERSION;
LRESULT i = ::SendMessage(hwnd, MsgAddString, 0, (LPARAM)W2T(dstrDesc));
if (i == CB_ERR || i == CB_ERRSPACE) // Note: CB_ and LB_ errors are identical values...
{
hr = E_OUTOFMEMORY;
}
else
{
::SendMessage(hwnd, MsgSetItemData, i, (LPARAM)pToken);
if (!fSetDefault)
{
::SendMessage(hwnd, MsgSetCurSel, i, 0);
fSetDefault = true;
}
}
}
if (FAILED(hr))
{
pToken->Release();
}
}
}
else
{
hr = SPERR_NO_MORE_ITEMS;
}
return hr;
}
inline HRESULT SpInitTokenComboBox(HWND hwnd, const WCHAR * pszCatName,
const WCHAR * pszRequiredAttrib = NULL, const WCHAR * pszOptionalAttrib = NULL)
{
return SpInitTokenList(CB_ADDSTRING, CB_SETITEMDATA, CB_SETCURSEL, hwnd, pszCatName, pszRequiredAttrib, pszOptionalAttrib);
}
inline HRESULT SpInitTokenListBox(HWND hwnd, const WCHAR * pszCatName,
const WCHAR * pszRequiredAttrib = NULL, const WCHAR * pszOptionalAttrib = NULL)
{
return SpInitTokenList(LB_ADDSTRING, LB_SETITEMDATA, LB_SETCURSEL, hwnd, pszCatName, pszRequiredAttrib, pszOptionalAttrib);
}
//
// Dont call this function directly. Use SpDestoyTokenComboBox or SpDestroyTokenListBox.
//
inline void SpDestroyTokenList(UINT MsgGetCount, UINT MsgGetItemData, HWND hwnd)
{
LRESULT c = ::SendMessage(hwnd, MsgGetCount, 0, 0);
for (LRESULT i = 0; i < c; i++)
{
IUnknown * pUnkObj = (IUnknown *)::SendMessage(hwnd, MsgGetItemData, i, 0);
if (pUnkObj)
{
pUnkObj->Release();
}
}
}
inline void SpDestroyTokenComboBox(HWND hwnd)
{
SpDestroyTokenList(CB_GETCOUNT, CB_GETITEMDATA, hwnd);
}
inline void SpDestroyTokenListBox(HWND hwnd)
{
SpDestroyTokenList(LB_GETCOUNT, LB_GETITEMDATA, hwnd);
}
inline ISpObjectToken * SpGetComboBoxToken(HWND hwnd, WPARAM Index)
{
return (ISpObjectToken *)::SendMessage(hwnd, CB_GETITEMDATA, Index, 0);
}
inline ISpObjectToken * SpGetListBoxToken(HWND hwnd, WPARAM Index)
{
return (ISpObjectToken *)::SendMessage(hwnd, LB_GETITEMDATA, Index, 0);
}
inline ISpObjectToken * SpGetCurSelComboBoxToken(HWND hwnd)
{
LRESULT i = ::SendMessage(hwnd, CB_GETCURSEL, 0, 0);
return (i == CB_ERR) ? NULL : SpGetComboBoxToken(hwnd, i);
}
inline ISpObjectToken * SpGetCurSelListBoxToken(HWND hwnd)
{
LRESULT i = ::SendMessage(hwnd, LB_GETCURSEL, 0, 0);
return (i == LB_ERR) ? NULL : SpGetListBoxToken(hwnd, i);
}
//
// Don't call this directly. Use SpUpdateCurSelComboBoxToken or SpUpdateCurSelListBoxToken
//
inline HRESULT SpUpdateCurSelToken(UINT MsgDelString, UINT MsgInsertString, UINT MsgGetItemData, UINT MsgSetItemData, UINT MsgGetCurSel, UINT MsgSetCurSel,
HWND hwnd)
{
HRESULT hr = S_OK;
LRESULT i = ::SendMessage(hwnd, MsgGetCurSel, 0, 0);
if (i != CB_ERR)
{
ISpObjectToken * pToken = (ISpObjectToken *)::SendMessage(hwnd, MsgGetItemData, i, 0);
CSpDynamicString dstrDesc;
hr = SpGetDescription(pToken, &dstrDesc);
if (SUCCEEDED(hr))
{
USES_CONVERSION;
::SendMessage(hwnd, MsgDelString, i, 0);
::SendMessage(hwnd, MsgInsertString, i, (LPARAM)W2T(dstrDesc));
::SendMessage(hwnd, MsgSetItemData, i, (LPARAM)pToken);
::SendMessage(hwnd, MsgSetCurSel, i, 0);
}
}
return hr;
}
inline HRESULT SpUpdateCurSelComboBoxToken(HWND hwnd)
{
return SpUpdateCurSelToken(CB_DELETESTRING, CB_INSERTSTRING, CB_GETITEMDATA, CB_SETITEMDATA, CB_GETCURSEL, CB_SETCURSEL, hwnd);
}
inline HRESULT SpUpdateCurSelListBoxToken(HWND hwnd)
{
return SpUpdateCurSelToken(LB_DELETESTRING, LB_INSERTSTRING, LB_GETITEMDATA, LB_SETITEMDATA, LB_GETCURSEL, LB_SETCURSEL, hwnd);
}
inline HRESULT SpAddTokenToList(UINT MsgAddString, UINT MsgSetItemData, UINT MsgSetCurSel, HWND hwnd, ISpObjectToken * pToken)
{
CSpDynamicString dstrDesc;
HRESULT hr = SpGetDescription(pToken, &dstrDesc);
if (SUCCEEDED(hr))
{
USES_CONVERSION;
LRESULT i = ::SendMessage(hwnd, MsgAddString, 0, (LPARAM)W2T(dstrDesc));
if (i == CB_ERR || i == CB_ERRSPACE) // Note: CB_ and LB_ errors are identical values...
{
hr = E_OUTOFMEMORY;
}
else
{
::SendMessage(hwnd, MsgSetItemData, i, (LPARAM)pToken);
::SendMessage(hwnd, MsgSetCurSel, i, 0);
pToken->AddRef();
}
}
return hr;
}
inline HRESULT SpAddTokenToComboBox(HWND hwnd, ISpObjectToken * pToken)
{
return SpAddTokenToList(CB_ADDSTRING, CB_SETITEMDATA, CB_SETCURSEL, hwnd, pToken);
}
inline HRESULT SpAddTokenToListBox(HWND hwnd, ISpObjectToken * pToken)
{
return SpAddTokenToList(LB_ADDSTRING, LB_SETITEMDATA, LB_SETCURSEL, hwnd, pToken);
}
inline HRESULT SpDeleteCurSelToken(UINT MsgGetCurSel, UINT MsgSetCurSel, UINT MsgGetItemData, UINT MsgDeleteString, HWND hwnd)
{
HRESULT hr = S_OK;
LRESULT i = ::SendMessage(hwnd, MsgGetCurSel, 0, 0);
if (i == CB_ERR)
{
hr = S_FALSE;
}
else
{
ISpObjectToken * pToken = (ISpObjectToken *)::SendMessage(hwnd, MsgGetItemData, i, 0);
if (pToken)
{
pToken->Release();
}
::SendMessage(hwnd, MsgDeleteString, i, 0);
::SendMessage(hwnd, MsgSetCurSel, i, 0);
}
return hr;
}
inline HRESULT SpDeleteCurSelComboBoxToken(HWND hwnd)
{
return SpDeleteCurSelToken(CB_GETCURSEL, CB_SETCURSEL, CB_GETITEMDATA, CB_DELETESTRING, hwnd);
}
inline HRESULT SpDeleteCurSelListBoxToken(HWND hwnd)
{
return SpDeleteCurSelToken(LB_GETCURSEL, CB_SETCURSEL, LB_GETITEMDATA, LB_DELETESTRING, hwnd);
}
#endif /* #ifndef SPUIHelp_h -- This must be the last line in the file */
Binary file not shown.