|
|
//==========================================================================;
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
// PURPOSE.
//
// Copyright (c) 1992 - 1998 Microsoft Corporation. All Rights Reserved.
//
//--------------------------------------------------------------------------;
//
// helper classes for building multimedia filters
//
#include <streams.h>
//
// Declare function from largeint.h we need so that PPC can build
//
//
// Enlarged integer divide - 64-bits / 32-bits > 32-bits
//
#ifndef _X86_
#define LLtoU64(x) (*(unsigned __int64*)(void*)(&(x)))
__inline ULONG WINAPI EnlargedUnsignedDivide ( IN ULARGE_INTEGER Dividend, IN ULONG Divisor, IN PULONG Remainder ) { // return remainder if necessary
if (Remainder != NULL) *Remainder = (ULONG)(LLtoU64(Dividend) % Divisor); return (ULONG)(LLtoU64(Dividend) / Divisor); }
#else
__inline ULONG WINAPI EnlargedUnsignedDivide ( IN ULARGE_INTEGER Dividend, IN ULONG Divisor, IN PULONG Remainder ) { ULONG ulResult; _asm { mov eax,Dividend.LowPart mov edx,Dividend.HighPart mov ecx,Remainder div Divisor or ecx,ecx jz short label mov [ecx],edx label: mov ulResult,eax } return ulResult; } #endif
// --- CAMEvent -----------------------
CAMEvent::CAMEvent(BOOL fManualReset) { m_hEvent = CreateEvent(NULL, fManualReset, FALSE, NULL); ASSERT(m_hEvent); }
CAMEvent::~CAMEvent() { if (m_hEvent) { EXECUTE_ASSERT(CloseHandle(m_hEvent)); } }
// --- CAMMsgEvent -----------------------
// One routine. The rest is handled in CAMEvent
BOOL CAMMsgEvent::WaitMsg(DWORD dwTimeout) { // wait for the event to be signalled, or for the
// timeout (in MS) to expire. allow SENT messages
// to be processed while we wait
DWORD dwWait; DWORD dwStartTime;
// set the waiting period.
DWORD dwWaitTime = dwTimeout;
// the timeout will eventually run down as we iterate
// processing messages. grab the start time so that
// we can calculate elapsed times.
if (dwWaitTime != INFINITE) { dwStartTime = timeGetTime(); }
do { dwWait = MsgWaitForMultipleObjects(1,&m_hEvent,FALSE, dwWaitTime, QS_SENDMESSAGE); if (dwWait == WAIT_OBJECT_0 + 1) { MSG Message; PeekMessage(&Message,NULL,0,0,PM_NOREMOVE);
// If we have an explicit length of time to wait calculate
// the next wake up point - which might be now.
// If dwTimeout is INFINITE, it stays INFINITE
if (dwWaitTime != INFINITE) {
DWORD dwElapsed = timeGetTime()-dwStartTime;
dwWaitTime = (dwElapsed >= dwTimeout) ? 0 // wake up with WAIT_TIMEOUT
: dwTimeout-dwElapsed; } } } while (dwWait == WAIT_OBJECT_0 + 1);
// return TRUE if we woke on the event handle,
// FALSE if we timed out.
return (dwWait == WAIT_OBJECT_0); }
// --- CAMThread ----------------------
CAMThread::CAMThread() : m_EventSend(TRUE) // must be manual-reset for CheckRequest()
{ m_hThread = NULL; }
CAMThread::~CAMThread() { Close(); }
// when the thread starts, it calls this function. We unwrap the 'this'
//pointer and call ThreadProc.
DWORD WINAPI CAMThread::InitialThreadProc(LPVOID pv) { CAMThread * pThread = (CAMThread *) pv;
return pThread->ThreadProc(); }
BOOL CAMThread::Create() { DWORD threadid;
CAutoLock lock(&m_AccessLock);
if (ThreadExists()) { return FALSE; }
m_hThread = CreateThread( NULL, 0, CAMThread::InitialThreadProc, this, 0, &threadid);
if (!m_hThread) { return FALSE; }
return TRUE; }
DWORD CAMThread::CallWorker(DWORD dwParam) { // lock access to the worker thread for scope of this object
CAutoLock lock(&m_AccessLock);
if (!ThreadExists()) { return (DWORD) E_FAIL; }
// set the parameter
m_dwParam = dwParam;
// signal the worker thread
m_EventSend.Set();
// wait for the completion to be signalled
m_EventComplete.Wait();
// done - this is the thread's return value
return m_dwReturnVal; }
// Wait for a request from the client
DWORD CAMThread::GetRequest() { m_EventSend.Wait(); return m_dwParam; }
// is there a request?
BOOL CAMThread::CheckRequest(DWORD * pParam) { if (!m_EventSend.Check()) { return FALSE; } else { if (pParam) { *pParam = m_dwParam; } return TRUE; } }
// reply to the request
void CAMThread::Reply(DWORD dw) { m_dwReturnVal = dw;
// The request is now complete so CheckRequest should fail from
// now on
//
// This event should be reset BEFORE we signal the client or
// the client may Set it before we reset it and we'll then
// reset it (!)
m_EventSend.Reset();
// Tell the client we're finished
m_EventComplete.Set(); }
HRESULT CAMThread::CoInitializeHelper() { // call CoInitializeEx and tell OLE not to create a window (this
// thread probably won't dispatch messages and will hang on
// broadcast msgs o/w).
//
// If CoInitEx is not available, threads that don't call CoCreate
// aren't affected. Threads that do will have to handle the
// failure. Perhaps we should fall back to CoInitialize and risk
// hanging?
//
// older versions of ole32.dll don't have CoInitializeEx
HRESULT hr = E_FAIL; HINSTANCE hOle = GetModuleHandle(TEXT("ole32.dll")); if(hOle) { typedef HRESULT (STDAPICALLTYPE *PCoInitializeEx)( LPVOID pvReserved, DWORD dwCoInit); PCoInitializeEx pCoInitializeEx = (PCoInitializeEx)(GetProcAddress(hOle, "CoInitializeEx")); if(pCoInitializeEx) { hr = (*pCoInitializeEx)(0, COINIT_DISABLE_OLE1DDE ); } } else { // caller must load ole32.dll
DbgBreak("couldn't locate ole32.dll"); }
return hr; }
// destructor for CMsgThread - cleans up any messages left in the
// queue when the thread exited
CMsgThread::~CMsgThread() { if (m_hThread != NULL) { WaitForSingleObject(m_hThread, INFINITE); EXECUTE_ASSERT(CloseHandle(m_hThread)); }
POSITION pos = m_ThreadQueue.GetHeadPosition(); while (pos) { CMsg * pMsg = m_ThreadQueue.GetNext(pos); delete pMsg; } m_ThreadQueue.RemoveAll();
if (m_hSem != NULL) { EXECUTE_ASSERT(CloseHandle(m_hSem)); } }
BOOL CMsgThread::CreateThread( ) { m_hSem = CreateSemaphore(NULL, 0, 0x7FFFFFFF, NULL); if (m_hSem == NULL) { return FALSE; }
m_hThread = ::CreateThread(NULL, 0, DefaultThreadProc, (LPVOID)this, 0, &m_ThreadId); return m_hThread != NULL; }
// This is the threads message pump. Here we get and dispatch messages to
// clients thread proc until the client refuses to process a message.
// The client returns a non-zero value to stop the message pump, this
// value becomes the threads exit code.
DWORD WINAPI CMsgThread::DefaultThreadProc( LPVOID lpParam ) { CMsgThread *lpThis = (CMsgThread *)lpParam; CMsg msg; LRESULT lResult;
// !!!
CoInitialize(NULL);
// allow a derived class to handle thread startup
lpThis->OnThreadInit();
do { lpThis->GetThreadMsg(&msg); lResult = lpThis->ThreadMessageProc(msg.uMsg,msg.dwFlags, msg.lpParam, msg.pEvent); } while (lResult == 0L);
// !!!
CoUninitialize();
return (DWORD)lResult; }
// Block until the next message is placed on the list m_ThreadQueue.
// copies the message to the message pointed to by *pmsg
void CMsgThread::GetThreadMsg(CMsg *msg) { CMsg * pmsg = NULL;
// keep trying until a message appears
while (TRUE) { { CAutoLock lck(&m_Lock); pmsg = m_ThreadQueue.RemoveHead(); if (pmsg == NULL) { m_lWaiting++; } else { break; } } // the semaphore will be signalled when it is non-empty
WaitForSingleObject(m_hSem, INFINITE); } // copy fields to caller's CMsg
*msg = *pmsg;
// this CMsg was allocated by the 'new' in PutThreadMsg
delete pmsg;
}
// NOTE: as we need to use the same binaries on Win95 as on NT this code should
// be compiled WITHOUT unicode being defined. Otherwise we will not pick up
// these internal routines and the binary will not run on Win95.
#ifndef UNICODE
// Windows 95 doesn't implement this, so we provide an implementation.
LPWSTR WINAPI lstrcpyWInternal( LPWSTR lpString1, LPCWSTR lpString2 ) { LPWSTR lpReturn = lpString1; while (*lpString1++ = *lpString2++);
return lpReturn; }
// Windows 95 doesn't implement this, so we provide an implementation.
LPWSTR WINAPI lstrcpynWInternal( LPWSTR lpString1, LPCWSTR lpString2, int iMaxLength ) { ASSERT(iMaxLength); LPWSTR lpReturn = lpString1; if (iMaxLength) { while (--iMaxLength && (*lpString1++ = *lpString2++));
// If we ran out of room (which will be the case if
// iMaxLength is now 0) we still need to terminate the
// string.
if (!iMaxLength) *lpString1 = L'\0'; } return lpReturn; }
int WINAPI lstrcmpWInternal( LPCWSTR lpString1, LPCWSTR lpString2 ) { do { WCHAR c1 = *lpString1; WCHAR c2 = *lpString2; if (c1 != c2) return (int) c1 - (int) c2; } while (*lpString1++ && *lpString2++); return 0; }
int WINAPI lstrcmpiWInternal( LPCWSTR lpString1, LPCWSTR lpString2 ) { do { WCHAR c1 = *lpString1; WCHAR c2 = *lpString2; if (c1 >= L'A' && c1 <= L'Z') c1 -= (WCHAR) (L'A' - L'a'); if (c2 >= L'A' && c2 <= L'Z') c2 -= (WCHAR) (L'A' - L'a'); if (c1 != c2) return (int) c1 - (int) c2; } while (*lpString1++ && *lpString2++);
return 0; }
int WINAPI lstrlenWInternal( LPCWSTR lpString ) { int i = -1; while (*(lpString+(++i))) ; return i; }
int WINAPIV wsprintfWInternal(LPWSTR wszOut, LPCWSTR pszFmt, ...) { char fmt[256]; // !!!
char ach[256]; // !!!
int i;
va_list va; va_start(va, pszFmt); WideCharToMultiByte(GetACP(), 0, pszFmt, -1, fmt, 256, NULL, NULL); i = wvsprintfA(ach, fmt, va); va_end(va);
MultiByteToWideChar(CP_ACP, 0, ach, -1, wszOut, i+1);
return i; } #else
// need to provide the implementations in unicode for non-unicode
// builds linking with the unicode strmbase.lib
LPWSTR WINAPI lstrcpyWInternal( LPWSTR lpString1, LPCWSTR lpString2 ) { return lstrcpyW(lpString1, lpString2); }
LPWSTR WINAPI lstrcpynWInternal( LPWSTR lpString1, LPCWSTR lpString2, int iMaxLength ) { return lstrcpynW(lpString1, lpString2, iMaxLength); }
int WINAPI lstrcmpWInternal( LPCWSTR lpString1, LPCWSTR lpString2 ) { return lstrcmpW(lpString1, lpString2); }
int WINAPI lstrcmpiWInternal( LPCWSTR lpString1, LPCWSTR lpString2 ) { return lstrcmpiW(lpString1, lpString2); }
int WINAPI lstrlenWInternal( LPCWSTR lpString ) { return lstrlenW(lpString); }
int WINAPIV wsprintfWInternal( LPWSTR wszOut, LPCWSTR pszFmt, ...) { va_list va; va_start(va, pszFmt); int i = wvsprintfW(wszOut, pszFmt, va); va_end(va); return i; } #endif
// Helper function - convert int to WSTR
void WINAPI IntToWstr(int i, LPWSTR wstr) { #ifdef UNICODE
wsprintf(wstr, L"%d", i); #else
TCHAR temp[32]; wsprintf(temp, "%d", i); MultiByteToWideChar(CP_ACP, 0, temp, -1, wstr, 32); #endif
} // IntToWstr
#if 0
void * memchrInternal(const void *pv, int c, size_t sz) { BYTE *pb = (BYTE *) pv; while (sz--) { if (*pb == c) return (void *) pb; pb++; } return NULL; } #endif
#define MEMORY_ALIGNMENT 4
#define MEMORY_ALIGNMENT_LOG2 2
#define MEMORY_ALIGNMENT_MASK MEMORY_ALIGNMENT - 1
void * __stdcall memmoveInternal(void * dst, const void * src, size_t count) { void * ret = dst;
#ifdef _X86_
if (dst <= src || (char *)dst >= ((char *)src + count)) {
/*
* Non-Overlapping Buffers * copy from lower addresses to higher addresses */ _asm { mov esi,src mov edi,dst mov ecx,count cld mov edx,ecx and edx,MEMORY_ALIGNMENT_MASK shr ecx,MEMORY_ALIGNMENT_LOG2 rep movsd or ecx,edx jz memmove_done rep movsb memmove_done: } } else {
/*
* Overlapping Buffers * copy from higher addresses to lower addresses */ _asm { mov esi,src mov edi,dst mov ecx,count std add esi,ecx add edi,ecx dec esi dec edi rep movsb cld } } #else
MoveMemory(dst, src, count); #endif
return ret; }
/* Arithmetic functions to help with time format conversions
*/
/* Compute (a * b + d) / c */ LONGLONG WINAPI llMulDiv(LONGLONG a, LONGLONG b, LONGLONG c, LONGLONG d) { /* Compute the absolute values to avoid signed arithmetic problems */ ULARGE_INTEGER ua, ub; DWORDLONG uc;
ua.QuadPart = (DWORDLONG)(a >= 0 ? a : -a); ub.QuadPart = (DWORDLONG)(b >= 0 ? b : -b); uc = (DWORDLONG)(c >= 0 ? c : -c); BOOL bSign = (a < 0) ^ (b < 0);
/* Do long multiplication */ ULARGE_INTEGER p[2]; p[0].QuadPart = UInt32x32To64(ua.LowPart, ub.LowPart);
/* This next computation cannot overflow into p[1].HighPart because
the max number we can compute here is:
(2 ** 32 - 1) * (2 ** 32 - 1) + // ua.LowPart * ub.LowPart
(2 ** 32) * (2 ** 31) * (2 ** 32 - 1) * 2 // x.LowPart * y.HighPart * 2
== 2 ** 96 - 2 ** 64 + (2 ** 64 - 2 ** 33 + 1) == 2 ** 96 - 2 ** 33 + 1 < 2 ** 96 */
ULARGE_INTEGER x; x.QuadPart = UInt32x32To64(ua.LowPart, ub.HighPart) + UInt32x32To64(ua.HighPart, ub.LowPart) + p[0].HighPart; p[0].HighPart = x.LowPart; p[1].QuadPart = UInt32x32To64(ua.HighPart, ub.HighPart) + x.HighPart;
if (d != 0) { ULARGE_INTEGER ud[2]; if (bSign) { ud[0].QuadPart = (DWORDLONG)(-d); if (d > 0) { /* -d < 0 */ ud[1].QuadPart = (DWORDLONG)(LONGLONG)-1; } else { ud[1].QuadPart = (DWORDLONG)0; } } else { ud[0].QuadPart = (DWORDLONG)d; if (d < 0) { ud[1].QuadPart = (DWORDLONG)(LONGLONG)-1; } else { ud[1].QuadPart = (DWORDLONG)0; } } /* Now do extended addition */ ULARGE_INTEGER uliTotal;
/* Add ls DWORDs */ uliTotal.QuadPart = (DWORDLONG)ud[0].LowPart + p[0].LowPart; p[0].LowPart = uliTotal.LowPart;
/* Propagate carry */ uliTotal.LowPart = uliTotal.HighPart; uliTotal.HighPart = 0;
/* Add 2nd most ls DWORDs */ uliTotal.QuadPart += (DWORDLONG)ud[0].HighPart + p[0].HighPart; p[0].HighPart = uliTotal.LowPart;
/* Propagate carry */ uliTotal.LowPart = uliTotal.HighPart; uliTotal.HighPart = 0;
/* Add MS DWORDLONGs - no carry expected */ p[1].QuadPart += ud[1].QuadPart + uliTotal.QuadPart;
/* Now see if we got a sign change from the addition */ if ((LONG)p[1].HighPart < 0) { bSign = !bSign;
/* Negate the current value (ugh!) */ p[0].QuadPart = ~p[0].QuadPart; p[1].QuadPart = ~p[1].QuadPart; p[0].QuadPart += 1; p[1].QuadPart += (p[0].QuadPart == 0); } }
/* Now for the division */ if (c < 0) { bSign = !bSign; }
/* This will catch c == 0 and overflow */ if (uc <= p[1].QuadPart) { return bSign ? (LONGLONG)0x8000000000000000 : (LONGLONG)0x7FFFFFFFFFFFFFFF; }
DWORDLONG ullResult;
/* Do the division */ /* If the dividend is a DWORD_LONG use the compiler */ if (p[1].QuadPart == 0) { ullResult = p[0].QuadPart / uc; return bSign ? -(LONGLONG)ullResult : (LONGLONG)ullResult; }
/* If the divisor is a DWORD then its simpler */ ULARGE_INTEGER ulic; ulic.QuadPart = uc; if (ulic.HighPart == 0) { ULARGE_INTEGER uliDividend; ULARGE_INTEGER uliResult; DWORD dwDivisor = (DWORD)uc; // ASSERT(p[1].HighPart == 0 && p[1].LowPart < dwDivisor);
uliDividend.HighPart = p[1].LowPart; uliDividend.LowPart = p[0].HighPart; #ifndef USE_LARGEINT
uliResult.HighPart = (DWORD)(uliDividend.QuadPart / dwDivisor); p[0].HighPart = (DWORD)(uliDividend.QuadPart % dwDivisor); uliResult.LowPart = 0; uliResult.QuadPart = p[0].QuadPart / dwDivisor + uliResult.QuadPart; #else
/* NOTE - this routine will take exceptions if
the result does not fit in a DWORD */ if (uliDividend.QuadPart >= (DWORDLONG)dwDivisor) { uliResult.HighPart = EnlargedUnsignedDivide( uliDividend, dwDivisor, &p[0].HighPart); } else { uliResult.HighPart = 0; } uliResult.LowPart = EnlargedUnsignedDivide( p[0], dwDivisor, NULL); #endif
return bSign ? -(LONGLONG)uliResult.QuadPart : (LONGLONG)uliResult.QuadPart; }
ullResult = 0;
/* OK - do long division */ for (int i = 0; i < 64; i++) { ullResult <<= 1;
/* Shift 128 bit p left 1 */ p[1].QuadPart <<= 1; if ((p[0].HighPart & 0x80000000) != 0) { p[1].LowPart++; } p[0].QuadPart <<= 1;
/* Compare */ if (uc <= p[1].QuadPart) { p[1].QuadPart -= uc; ullResult += 1; } }
return bSign ? - (LONGLONG)ullResult : (LONGLONG)ullResult; }
LONGLONG WINAPI Int64x32Div32(LONGLONG a, LONG b, LONG c, LONG d) { ULARGE_INTEGER ua; DWORD ub; DWORD uc;
/* Compute the absolute values to avoid signed arithmetic problems */ ua.QuadPart = (DWORDLONG)(a >= 0 ? a : -a); ub = (DWORD)(b >= 0 ? b : -b); uc = (DWORD)(c >= 0 ? c : -c); BOOL bSign = (a < 0) ^ (b < 0);
/* Do long multiplication */ ULARGE_INTEGER p0; DWORD p1; p0.QuadPart = UInt32x32To64(ua.LowPart, ub);
if (ua.HighPart != 0) { ULARGE_INTEGER x; x.QuadPart = UInt32x32To64(ua.HighPart, ub) + p0.HighPart; p0.HighPart = x.LowPart; p1 = x.HighPart; } else { p1 = 0; }
if (d != 0) { ULARGE_INTEGER ud0; DWORD ud1;
if (bSign) { //
// Cast d to LONGLONG first otherwise -0x80000000 sign extends
// incorrectly
//
ud0.QuadPart = (DWORDLONG)(-(LONGLONG)d); if (d > 0) { /* -d < 0 */ ud1 = (DWORD)-1; } else { ud1 = (DWORD)0; } } else { ud0.QuadPart = (DWORDLONG)d; if (d < 0) { ud1 = (DWORD)-1; } else { ud1 = (DWORD)0; } } /* Now do extended addition */ ULARGE_INTEGER uliTotal;
/* Add ls DWORDs */ uliTotal.QuadPart = (DWORDLONG)ud0.LowPart + p0.LowPart; p0.LowPart = uliTotal.LowPart;
/* Propagate carry */ uliTotal.LowPart = uliTotal.HighPart; uliTotal.HighPart = 0;
/* Add 2nd most ls DWORDs */ uliTotal.QuadPart += (DWORDLONG)ud0.HighPart + p0.HighPart; p0.HighPart = uliTotal.LowPart;
/* Add MS DWORDLONGs - no carry expected */ p1 += ud1 + uliTotal.HighPart;
/* Now see if we got a sign change from the addition */ if ((LONG)p1 < 0) { bSign = !bSign;
/* Negate the current value (ugh!) */ p0.QuadPart = ~p0.QuadPart; p1 = ~p1; p0.QuadPart += 1; p1 += (p0.QuadPart == 0); } }
/* Now for the division */ if (c < 0) { bSign = !bSign; }
/* This will catch c == 0 and overflow */ if (uc <= p1) { return bSign ? (LONGLONG)0x8000000000000000 : (LONGLONG)0x7FFFFFFFFFFFFFFF; }
/* Do the division */
/* If the divisor is a DWORD then its simpler */ ULARGE_INTEGER uliDividend; ULARGE_INTEGER uliResult; DWORD dwDivisor = uc; uliDividend.HighPart = p1; uliDividend.LowPart = p0.HighPart; /* NOTE - this routine will take exceptions if
the result does not fit in a DWORD */ if (uliDividend.QuadPart >= (DWORDLONG)dwDivisor) { uliResult.HighPart = EnlargedUnsignedDivide( uliDividend, dwDivisor, &p0.HighPart); } else { uliResult.HighPart = 0; } uliResult.LowPart = EnlargedUnsignedDivide( p0, dwDivisor, NULL); return bSign ? -(LONGLONG)uliResult.QuadPart : (LONGLONG)uliResult.QuadPart; }
#ifdef DEBUG
/******************************Public*Routine******************************\
* Debug CCritSec helpers * * We provide debug versions of the Constructor, destructor, Lock and Unlock * routines. The debug code tracks who owns each critical section by * maintaining a depth count. * * History: * \**************************************************************************/
CCritSec::CCritSec() { InitializeCriticalSection(&m_CritSec); m_currentOwner = m_lockCount = 0; m_fTrace = FALSE; }
CCritSec::~CCritSec() { DeleteCriticalSection(&m_CritSec); }
void CCritSec::Lock() { UINT tracelevel=3; DWORD us = GetCurrentThreadId(); DWORD currentOwner = m_currentOwner; if (currentOwner && (currentOwner != us)) { // already owned, but not by us
if (m_fTrace) { DbgLog((LOG_LOCKING, 2, TEXT("Thread %d about to wait for lock %x owned by %d"), GetCurrentThreadId(), &m_CritSec, currentOwner)); tracelevel=2; // if we saw the message about waiting for the critical
// section we ensure we see the message when we get the
// critical section
} } EnterCriticalSection(&m_CritSec); if (0 == m_lockCount++) { // we now own it for the first time. Set owner information
m_currentOwner = us; //ASSERT(((PRTL_CRITICAL_SECTION)&m_CritSec)->OwningThread == (HANDLE)m_currentOwner);
// only valid on NT
if (m_fTrace) { DbgLog((LOG_LOCKING, tracelevel, TEXT("Thread %d now owns lock %x"), m_currentOwner, &m_CritSec)); } } }
void CCritSec::Unlock() { if (0 == --m_lockCount) { // about to be unowned
if (m_fTrace) { DbgLog((LOG_LOCKING, 3, TEXT("Thread %d releasing lock %x"), m_currentOwner, &m_CritSec)); //ASSERT(((PRTL_CRITICAL_SECTION)&m_CritSec)->OwningThread == (HANDLE)m_currentOwner);
// only valid on NT
} m_currentOwner = 0; } LeaveCriticalSection(&m_CritSec); }
void WINAPI DbgLockTrace(CCritSec * pcCrit, BOOL fTrace) { pcCrit->m_fTrace = fTrace; }
BOOL WINAPI CritCheckIn(CCritSec * pcCrit) { return (GetCurrentThreadId() == pcCrit->m_currentOwner); }
BOOL WINAPI CritCheckOut(CCritSec * pcCrit) { return (GetCurrentThreadId() != pcCrit->m_currentOwner); } #endif
typedef BSTR (STDAPICALLTYPE *LPSYSALLOCSTRING)(const OLECHAR FAR *);
// Dyna-link to SysAllocString to copy BSTR strings
STDAPI WriteBSTR(BSTR *pstrDest, LPCWSTR szSrc) { LPSYSALLOCSTRING lpfnSysAllocString; HINSTANCE hInst; static const char szSysAllocString[] = "SysAllocString";
//
// Try to get the Ole32Aut.dll module handle.
//
hInst = LoadOLEAut32(); if (hInst == NULL) { DWORD dwError = GetLastError(); return HRESULT_FROM_WIN32(dwError); } lpfnSysAllocString = (LPSYSALLOCSTRING)GetProcAddress(hInst, szSysAllocString); if (lpfnSysAllocString == NULL) { DWORD dwError = GetLastError(); return HRESULT_FROM_WIN32(dwError); }
*pstrDest = (*lpfnSysAllocString)(szSrc);
return S_OK; }
// Free an OLE BSTR through the task allocator
STDAPI FreeBSTR(BSTR* pstr) { if (*pstr != NULL) { // get pointer to string
DWORD* p = (DWORD*) (*pstr);
// back up to point at DWORD length
p--;
// set pointer to null
*pstr = NULL;
// and free this
CoTaskMemFree(p);
return S_OK; } else { return S_FALSE; } }
// Return a wide string - allocating memory for it
// Returns:
// S_OK - no error
// E_POINTER - ppszReturn == NULL
// E_OUTOFMEMORY - can't allocate memory for returned string
STDAPI AMGetWideString(LPCWSTR psz, LPWSTR *ppszReturn) { CheckPointer(ppszReturn, E_POINTER); ValidateReadWritePtr(ppszReturn, sizeof(LPWSTR)); DWORD nameLen = sizeof(WCHAR) * (lstrlenW(psz)+1); *ppszReturn = (LPWSTR)CoTaskMemAlloc(nameLen); if (*ppszReturn == NULL) { return E_OUTOFMEMORY; } CopyMemory(*ppszReturn, psz, nameLen); return NOERROR; }
// Waits for the HANDLE hObject. While waiting messages sent
// to windows on our thread by SendMessage will be processed.
// Using this function to do waits and mutual exclusion
// avoids some deadlocks in objects with windows.
// Return codes are the same as for WaitForSingleObject
DWORD WINAPI WaitDispatchingMessages(HANDLE hObject, DWORD dwWait, HWND hwnd, UINT uMsg) { BOOL bPeeked = FALSE; DWORD dwResult; DWORD dwStart; DWORD dwThreadPriority;
static UINT uMsgId = 0;
if (dwWait != INFINITE && dwWait != 0) { dwStart = GetTickCount(); } for (; ; ) { DWORD dwTimeOut = dwWait; if (dwTimeOut > 10) { dwTimeOut = 10; } dwResult = MsgWaitForMultipleObjects( 1, &hObject, FALSE, dwTimeOut, hwnd == NULL ? QS_SENDMESSAGE : QS_SENDMESSAGE + QS_POSTMESSAGE); if (dwResult == WAIT_OBJECT_0 + 1 || dwResult == WAIT_TIMEOUT && dwTimeOut != dwWait) { MSG msg; if (hwnd != NULL) { while (PeekMessage(&msg, hwnd, uMsg, uMsg, PM_REMOVE)) { DispatchMessage(&msg); } } // Do this anyway - the previous peek doesn't flush out the
// messages
PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE);
if (dwWait != INFINITE && dwWait != 0) { DWORD dwNow = GetTickCount();
// Working with differences handles wrap-around
DWORD dwDiff = dwNow - dwStart; if (dwDiff > dwWait) { dwWait = 0; } else { dwWait -= dwDiff; } dwStart = dwNow; } if (!bPeeked) { // Raise our priority to prevent our message queue
// building up
dwThreadPriority = GetThreadPriority(GetCurrentThread()); if (dwThreadPriority < THREAD_PRIORITY_HIGHEST) { SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST); } bPeeked = TRUE; } } else { break; } } if (bPeeked) { SetThreadPriority(GetCurrentThread(), dwThreadPriority); if (HIWORD(GetQueueStatus(QS_POSTMESSAGE)) & QS_POSTMESSAGE) { if (uMsgId == 0) { uMsgId = RegisterWindowMessage(TEXT("AMUnblock")); } if (uMsgId != 0) { MSG msg; // Remove old ones
while (PeekMessage(&msg, (HWND)-1, uMsgId, uMsgId, PM_REMOVE)) { } } PostThreadMessage(GetCurrentThreadId(), uMsgId, 0, 0); } } return dwResult; }
|