📄 wxutil.cpp
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
//==========================================================================;
//
// 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.
//
//
//--------------------------------------------------------------------------;
//
// helper classes for building multimedia filters
//
#include <streams.h>
#include <dsthread.h>
#include <dsthread.cpp>
//
// 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 = _internal_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, TEXT("CoInitializeEx")));
if(pCoInitializeEx)
{
#ifndef UNDER_CE
hr = (*pCoInitializeEx)(0, COINIT_DISABLE_OLE1DDE);
#else
hr = (*pCoInitializeEx)(0, COINIT_MULTITHREADED);
#endif
}
}
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 = ::_internal_CreateThread(NULL, 0, DefaultThreadProc,
(LPVOID)this, 0, &m_ThreadId);
return m_hThread != NULL;
}
int CMsgThread::GetThreadPriority() {
return ::_internal_GetThreadPriority(m_hThread);
}
BOOL CMsgThread::SetThreadPriority(int nPriority) {
return ::_internal_SetThreadPriority(m_hThread, nPriority);
}
// 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;
// !!!
#ifndef UNDER_CE
CoInitialize(NULL);
#else
CoInitializeEx(NULL, COINIT_MULTITHREADED);
#endif // UNDER_CE
// 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -