771 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
		
		
			
		
	
	
			771 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| 
								 | 
							
								//------------------------------------------------------------------------------
							 | 
						||
| 
								 | 
							
								// File: WXUtil.cpp
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// Desc: DirectShow base classes - implements helper classes for building
							 | 
						||
| 
								 | 
							
								//       multimedia filters.
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// Copyright (c) 1992-2001 Microsoft Corporation.  All rights reserved.
							 | 
						||
| 
								 | 
							
								//------------------------------------------------------------------------------
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <streams.h>
							 | 
						||
| 
								 | 
							
								#define STRSAFE_NO_DEPRECATE
							 | 
						||
| 
								 | 
							
								#include <strsafe.h>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#pragma warning(disable: 4996)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// --- CAMEvent -----------------------
							 | 
						||
| 
								 | 
							
								CAMEvent::CAMEvent(BOOL fManualReset, __inout_opt HRESULT *phr)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    m_hEvent = CreateEvent(NULL, fManualReset, FALSE, NULL);
							 | 
						||
| 
								 | 
							
								    if (NULL == m_hEvent) {
							 | 
						||
| 
								 | 
							
								        if (NULL != phr && SUCCEEDED(*phr)) {
							 | 
						||
| 
								 | 
							
								            *phr = E_OUTOFMEMORY;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								CAMEvent::CAMEvent(__inout_opt HRESULT *phr)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    m_hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
							 | 
						||
| 
								 | 
							
								    if (NULL == m_hEvent) {
							 | 
						||
| 
								 | 
							
								        if (NULL != phr && SUCCEEDED(*phr)) {
							 | 
						||
| 
								 | 
							
								            *phr = E_OUTOFMEMORY;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								CAMEvent::~CAMEvent()
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    if (m_hEvent) {
							 | 
						||
| 
								 | 
							
									EXECUTE_ASSERT(CloseHandle(m_hEvent));
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// --- CAMMsgEvent -----------------------
							 | 
						||
| 
								 | 
							
								// One routine.  The rest is handled in CAMEvent
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								CAMMsgEvent::CAMMsgEvent(__inout_opt HRESULT *phr) : CAMEvent(FALSE, phr)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								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(__inout_opt HRESULT *phr)
							 | 
						||
| 
								 | 
							
								    : m_EventSend(TRUE, phr),     // must be manual-reset for CheckRequest()
							 | 
						||
| 
								 | 
							
								      m_EventComplete(FALSE, phr)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    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(__inout LPVOID pv)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    HRESULT hrCoInit = CAMThread::CoInitializeHelper();
							 | 
						||
| 
								 | 
							
								    if(FAILED(hrCoInit)) {
							 | 
						||
| 
								 | 
							
								        DbgLog((LOG_ERROR, 1, TEXT("CoInitializeEx failed.")));
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    CAMThread * pThread = (CAMThread *) pv;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    HRESULT hr = pThread->ThreadProc();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if(SUCCEEDED(hrCoInit)) {
							 | 
						||
| 
								 | 
							
								        CoUninitialize();
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return hr;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								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(__out_opt 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(
							 | 
						||
| 
								 | 
							
								    __inout 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(__out 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;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// Helper function - convert int to WSTR
							 | 
						||
| 
								 | 
							
								void WINAPI IntToWstr(int i, __out_ecount(12) LPWSTR wstr)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								#ifdef UNICODE
							 | 
						||
| 
								 | 
							
								    if (FAILED(StringCchPrintf(wstr, 12, L"%d", i))) {
							 | 
						||
| 
								 | 
							
								        wstr[0] = 0;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
								    TCHAR temp[12];
							 | 
						||
| 
								 | 
							
								    if (FAILED(StringCchPrintf(temp, NUMELMS(temp), "%d", i))) {
							 | 
						||
| 
								 | 
							
								        wstr[0] = 0;
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								        MultiByteToWideChar(CP_ACP, 0, temp, -1, wstr, 12);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								} // IntToWstr
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#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;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								HRESULT AMSafeMemMoveOffset(
							 | 
						||
| 
								 | 
							
								    __in_bcount(dst_size) void * dst,
							 | 
						||
| 
								 | 
							
								    __in size_t dst_size,
							 | 
						||
| 
								 | 
							
								    __in DWORD cb_dst_offset,
							 | 
						||
| 
								 | 
							
								    __in_bcount(src_size) const void * src,
							 | 
						||
| 
								 | 
							
								    __in size_t src_size,
							 | 
						||
| 
								 | 
							
								    __in DWORD cb_src_offset,
							 | 
						||
| 
								 | 
							
								    __in size_t count)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    // prevent read overruns
							 | 
						||
| 
								 | 
							
								    if( count + cb_src_offset < count ||   // prevent integer overflow
							 | 
						||
| 
								 | 
							
								        count + cb_src_offset > src_size)  // prevent read overrun
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        return E_INVALIDARG;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // prevent write overruns
							 | 
						||
| 
								 | 
							
								    if( count + cb_dst_offset < count ||   // prevent integer overflow
							 | 
						||
| 
								 | 
							
								        count + cb_dst_offset > dst_size)  // prevent write overrun
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        return E_INVALIDARG;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    memmoveInternal( (BYTE *)dst+cb_dst_offset, (BYTE *)src+cb_src_offset, count);
							 | 
						||
| 
								 | 
							
								    return S_OK;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#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;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        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));
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        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 CritCheckIn(const CCritSec * pcCrit)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    return (GetCurrentThreadId() == pcCrit->m_currentOwner);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								BOOL WINAPI CritCheckOut(CCritSec * pcCrit)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    return (GetCurrentThreadId() != pcCrit->m_currentOwner);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								BOOL WINAPI CritCheckOut(const CCritSec * pcCrit)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    return (GetCurrentThreadId() != pcCrit->m_currentOwner);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								STDAPI WriteBSTR(__deref_out BSTR *pstrDest, LPCWSTR szSrc)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    *pstrDest = SysAllocString( szSrc );
							 | 
						||
| 
								 | 
							
								    if( !(*pstrDest) ) return E_OUTOFMEMORY;
							 | 
						||
| 
								 | 
							
								    return NOERROR;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								STDAPI FreeBSTR(__deref_in BSTR* pstr)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    if( (PVOID)*pstr == NULL ) return S_FALSE;
							 | 
						||
| 
								 | 
							
								    SysFreeString( *pstr );
							 | 
						||
| 
								 | 
							
								    return NOERROR;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// 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, __deref_out LPWSTR *ppszReturn)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    CheckPointer(ppszReturn, E_POINTER);
							 | 
						||
| 
								 | 
							
								    ValidateReadWritePtr(ppszReturn, sizeof(LPWSTR));
							 | 
						||
| 
								 | 
							
								    *ppszReturn = NULL;
							 | 
						||
| 
								 | 
							
								    size_t nameLen;
							 | 
						||
| 
								 | 
							
								    HRESULT hr = StringCbLengthW(psz, 100000, &nameLen);
							 | 
						||
| 
								 | 
							
								    if (FAILED(hr)) {
							 | 
						||
| 
								 | 
							
								        return hr;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    *ppszReturn = (LPWSTR)CoTaskMemAlloc(nameLen + sizeof(WCHAR));
							 | 
						||
| 
								 | 
							
								    if (*ppszReturn == NULL) {
							 | 
						||
| 
								 | 
							
								       return E_OUTOFMEMORY;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    CopyMemory(*ppszReturn, psz, nameLen + sizeof(WCHAR));
							 | 
						||
| 
								 | 
							
								    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,
							 | 
						||
| 
								 | 
							
								    HANDLE hEvent)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    BOOL bPeeked = FALSE;
							 | 
						||
| 
								 | 
							
								    DWORD dwResult;
							 | 
						||
| 
								 | 
							
								    DWORD dwStart;
							 | 
						||
| 
								 | 
							
								    DWORD dwThreadPriority;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    static UINT uMsgId = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    HANDLE hObjects[2] = { hObject, hEvent };
							 | 
						||
| 
								 | 
							
								    if (dwWait != INFINITE && dwWait != 0) {
							 | 
						||
| 
								 | 
							
								        dwStart = GetTickCount();
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    for (; ; ) {
							 | 
						||
| 
								 | 
							
								        DWORD nCount = NULL != hEvent ? 2 : 1;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        //  Minimize the chance of actually dispatching any messages
							 | 
						||
| 
								 | 
							
								        //  by seeing if we can lock immediately.
							 | 
						||
| 
								 | 
							
								        dwResult = WaitForMultipleObjects(nCount, hObjects, FALSE, 0);
							 | 
						||
| 
								 | 
							
								        if (dwResult < WAIT_OBJECT_0 + nCount) {
							 | 
						||
| 
								 | 
							
								            break;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        DWORD dwTimeOut = dwWait;
							 | 
						||
| 
								 | 
							
								        if (dwTimeOut > 10) {
							 | 
						||
| 
								 | 
							
								            dwTimeOut = 10;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        dwResult = MsgWaitForMultipleObjects(
							 | 
						||
| 
								 | 
							
								                             nCount,
							 | 
						||
| 
								 | 
							
								                             hObjects,
							 | 
						||
| 
								 | 
							
								                             FALSE,
							 | 
						||
| 
								 | 
							
								                             dwTimeOut,
							 | 
						||
| 
								 | 
							
								                             hwnd == NULL ? QS_SENDMESSAGE :
							 | 
						||
| 
								 | 
							
								                                            QS_SENDMESSAGE + QS_POSTMESSAGE);
							 | 
						||
| 
								 | 
							
								        if (dwResult == WAIT_OBJECT_0 + nCount ||
							 | 
						||
| 
								 | 
							
								            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;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								HRESULT AmGetLastErrorToHResult()
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    DWORD dwLastError = GetLastError();
							 | 
						||
| 
								 | 
							
								    if(dwLastError != 0)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        return HRESULT_FROM_WIN32(dwLastError);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    else
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        return E_FAIL;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								IUnknown* QzAtlComPtrAssign(__deref_inout_opt IUnknown** pp, __in_opt IUnknown* lp)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    if (lp != NULL)
							 | 
						||
| 
								 | 
							
								        lp->AddRef();
							 | 
						||
| 
								 | 
							
								    if (*pp)
							 | 
						||
| 
								 | 
							
								        (*pp)->Release();
							 | 
						||
| 
								 | 
							
								    *pp = lp;
							 | 
						||
| 
								 | 
							
								    return lp;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/******************************************************************************
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								CompatibleTimeSetEvent
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    CompatibleTimeSetEvent() sets the TIME_KILL_SYNCHRONOUS flag before calling
							 | 
						||
| 
								 | 
							
								timeSetEvent() if the current operating system supports it.  TIME_KILL_SYNCHRONOUS
							 | 
						||
| 
								 | 
							
								is supported on Windows XP and later operating systems.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Parameters:
							 | 
						||
| 
								 | 
							
								- The same parameters as timeSetEvent().  See timeSetEvent()'s documentation in 
							 | 
						||
| 
								 | 
							
								the Platform SDK for more information.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Return Value:
							 | 
						||
| 
								 | 
							
								- The same return value as timeSetEvent().  See timeSetEvent()'s documentation in 
							 | 
						||
| 
								 | 
							
								the Platform SDK for more information.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								******************************************************************************/
							 | 
						||
| 
								 | 
							
								MMRESULT CompatibleTimeSetEvent( UINT uDelay, UINT uResolution, __in LPTIMECALLBACK lpTimeProc, DWORD_PTR dwUser, UINT fuEvent )
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    #if WINVER >= 0x0501
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        static bool fCheckedVersion = false;
							 | 
						||
| 
								 | 
							
								        static bool fTimeKillSynchronousFlagAvailable = false; 
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if( !fCheckedVersion ) {
							 | 
						||
| 
								 | 
							
								            fTimeKillSynchronousFlagAvailable = TimeKillSynchronousFlagAvailable();
							 | 
						||
| 
								 | 
							
								            fCheckedVersion = true;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if( fTimeKillSynchronousFlagAvailable ) {
							 | 
						||
| 
								 | 
							
								            fuEvent = fuEvent | TIME_KILL_SYNCHRONOUS;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    #endif // WINVER >= 0x0501
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return timeSetEvent( uDelay, uResolution, lpTimeProc, dwUser, fuEvent );
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								bool TimeKillSynchronousFlagAvailable( void )
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    OSVERSIONINFO osverinfo;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    osverinfo.dwOSVersionInfoSize = sizeof(osverinfo);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if( GetVersionEx( &osverinfo ) ) {
							 | 
						||
| 
								 | 
							
								        
							 | 
						||
| 
								 | 
							
								        // Windows XP's major version is 5 and its' minor version is 1.
							 | 
						||
| 
								 | 
							
								        // timeSetEvent() started supporting the TIME_KILL_SYNCHRONOUS flag
							 | 
						||
| 
								 | 
							
								        // in Windows XP.
							 | 
						||
| 
								 | 
							
								        if( (osverinfo.dwMajorVersion > 5) || 
							 | 
						||
| 
								 | 
							
								            ( (osverinfo.dwMajorVersion == 5) && (osverinfo.dwMinorVersion >= 1) ) ) {
							 | 
						||
| 
								 | 
							
								            return true;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return false;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 |