* #27232: jni: added pjproject checkout as regular git content
We will remove it once the next release of pjsip (with Android support)
comes out and is merged into SFLphone.
diff --git a/jni/pjproject-android/.svn/pristine/ee/ee0c7e8b6fc1a3c21502f57ab0e0718b76475fd0.svn-base b/jni/pjproject-android/.svn/pristine/ee/ee0c7e8b6fc1a3c21502f57ab0e0718b76475fd0.svn-base
new file mode 100644
index 0000000..2ba243b
--- /dev/null
+++ b/jni/pjproject-android/.svn/pristine/ee/ee0c7e8b6fc1a3c21502f57ab0e0718b76475fd0.svn-base
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioPropertySheet
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="pjproject-vs8-wm5-release-defaults"
+ InheritedPropertySheets=".\pjproject-vs8-wm5-common-defaults.vsprops"
+ >
+</VisualStudioPropertySheet>
diff --git a/jni/pjproject-android/.svn/pristine/ee/ee7431d43d42682beda7672ebf89554da3edac02.svn-base b/jni/pjproject-android/.svn/pristine/ee/ee7431d43d42682beda7672ebf89554da3edac02.svn-base
new file mode 100644
index 0000000..291e2b0
--- /dev/null
+++ b/jni/pjproject-android/.svn/pristine/ee/ee7431d43d42682beda7672ebf89554da3edac02.svn-base
@@ -0,0 +1,213 @@
+/* $Id$ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef __PJSIP_AUTH_SIP_AUTH_AKA_H__
+#define __PJSIP_AUTH_SIP_AUTH_AKA_H__
+
+/**
+ * @file sip_auth_aka.h
+ * @brief SIP Digest AKA Authorization Module.
+ */
+
+#include <pjsip/sip_auth.h>
+
+PJ_BEGIN_DECL
+
+/**
+ * @defgroup PJSIP_AUTH_AKA_API Digest AKAv1 and AKAv2 Authentication API
+ * @ingroup PJSIP_AUTH_API
+ * @brief Digest AKAv1 and AKAv2 Authentication API
+ * @{
+ *
+ * This module implements HTTP digest authentication using Authentication
+ * and Key Agreement (AKA) version 1 and version 2 (AKAv1-MD5 and AKAv2-MD5),
+ * as specified in RFC 3310 and RFC 4169. SIP AKA authentication is used
+ * by 3GPP and IMS systems.
+ *
+ * @section pjsip_aka_using Using Digest AKA Authentication
+ *
+ * Support for digest AKA authentication is currently made optional, so
+ * application needs to declare \a PJSIP_HAS_DIGEST_AKA_AUTH to non-zero
+ * in <tt>config_site.h</tt> to enable AKA support:
+ *
+ @code
+ #define PJSIP_HAS_DIGEST_AKA_AUTH 1
+ @endcode
+
+ *
+ * In addition, application would need to link with <b>libmilenage</b>
+ * library from \a third_party directory.
+ *
+ * Application then specifies digest AKA credential by initializing the
+ * authentication credential as follows:
+ *
+ @code
+
+ pjsip_cred_info cred;
+
+ pj_bzero(&cred, sizeof(cred));
+
+ cred.scheme = pj_str("Digest");
+ cred.realm = pj_str("ims-domain.test");
+ cred.username = pj_str("user@ims-domain.test");
+ cred.data_type = PJSIP_CRED_DATA_PLAIN_PASSWD | PJSIP_CRED_DATA_EXT_AKA;
+ cred.data = pj_str("password");
+
+ // AKA extended info
+ cred.ext.aka.k = pj_str("password");
+ cred.ext.aka.cb = &pjsip_auth_create_aka_response
+
+ @endcode
+ *
+ * Description:
+ * - To support AKA, application adds \a PJSIP_CRED_DATA_EXT_AKA flag in the
+ * \a data_type field. This indicates that extended information specific to
+ * AKA authentication is available in the credential, and that response
+ * digest computation will use the callback function instead of the usual MD5
+ * digest computation.
+ *
+ * - The \a scheme for the credential is "Digest".
+ *
+ * - The \a realm is the expected realm in the challenge. Application may
+ * also specify wildcard realm ("*") if it wishes to respond to any realms
+ * in the challenge.
+ *
+ * - The \a data field is optional. Application may fill this with the password
+ * if it wants to support both MD5 and AKA MD5 in a single credential. The
+ * pjsip_auth_create_aka_response() function will use this field if the
+ * challenge indicates "MD5" as the algorithm instead of "AKAv1-MD5" or
+ * "AKAv2-MD5".
+ *
+ * - The \a ext.aka.k field specifies the permanent subscriber key to be used
+ * for AKA authentication. Application may specify binary password containing
+ * NULL character in this key, since the length of the key is indicated in
+ * the \a slen field of the string.
+ *
+ * - The \a ext.aka.cb field specifies the callback function to calculate the
+ * response digest. Application can specify pjsip_auth_create_aka_response()
+ * in this field to use PJSIP's implementation, but it's free to provide
+ * it's own function.
+ *
+ * - Optionally application may set \a ext.aka.op and \a ext.aka.amf in the
+ * credential to specify AKA Operator variant key and AKA Authentication
+ * Management Field information.
+ */
+
+/**
+ * Length of Authentication Key (AK) in bytes.
+ */
+#define PJSIP_AKA_AKLEN 6
+
+/**
+ * Length of Authentication Management Field (AMF) in bytes.
+ */
+#define PJSIP_AKA_AMFLEN 2
+
+/**
+ * Length of AUTN in bytes.
+ */
+#define PJSIP_AKA_AUTNLEN 16
+
+/**
+ * Length of Confidentiality Key (CK) in bytes.
+ */
+#define PJSIP_AKA_CKLEN 16
+
+/**
+ * Length of Integrity Key (AK) in bytes.
+ */
+#define PJSIP_AKA_IKLEN 16
+
+/**
+ * Length of permanent/subscriber Key (K) in bytes.
+ */
+#define PJSIP_AKA_KLEN 16
+
+/**
+ * Length of AKA authentication code in bytes.
+ */
+#define PJSIP_AKA_MACLEN 8
+
+/**
+ * Length of operator key in bytes.
+ */
+#define PJSIP_AKA_OPLEN 16
+
+/**
+ * Length of random challenge (RAND) in bytes.
+ */
+#define PJSIP_AKA_RANDLEN 16
+
+/**
+ * Length of response digest in bytes.
+ */
+#define PJSIP_AKA_RESLEN 8
+
+/**
+ * Length of sequence number (SQN) in bytes.
+ */
+#define PJSIP_AKA_SQNLEN 6
+
+/**
+ * This function creates MD5, AKAv1-MD5, or AKAv2-MD5 response for
+ * the specified challenge in \a chal, according to the algorithm
+ * specified in the challenge, and based on the information in the
+ * credential \a cred.
+ *
+ * Application may register this function as \a ext.aka.cb field of
+ * #pjsip_cred_info structure to make PJSIP automatically call this
+ * function to calculate the response digest. To do so, it needs to
+ * add \a PJSIP_CRED_DATA_EXT_AKA flag in the \a data_type field of
+ * the credential, and fills up other AKA specific information in
+ * the credential.
+ *
+ * @param pool Pool to allocate memory.
+ * @param chal The authentication challenge sent by server in 401
+ * or 401 response, as either Proxy-Authenticate or
+ * WWW-Authenticate header.
+ * @param cred The credential to be used.
+ * @param method The request method.
+ * @param auth The digest credential where the digest response
+ * will be placed to. Upon calling this function, the
+ * nonce, nc, cnonce, qop, uri, and realm fields of
+ * this structure must have been set by caller. Upon
+ * return, the \a response field will be initialized
+ * by this function.
+ *
+ * @return PJ_SUCCESS if response has been created successfully.
+ */
+PJ_DECL(pj_status_t) pjsip_auth_create_aka_response(
+ pj_pool_t *pool,
+ const pjsip_digest_challenge*chal,
+ const pjsip_cred_info *cred,
+ const pj_str_t *method,
+ pjsip_digest_credential *auth);
+
+
+/**
+ * @}
+ */
+
+
+
+PJ_END_DECL
+
+
+#endif /* __PJSIP_AUTH_SIP_AUTH_AKA_H__ */
+
diff --git a/jni/pjproject-android/.svn/pristine/ee/eee9b2b3acbd68f8c7a6c4f239076789f26dcb4a.svn-base b/jni/pjproject-android/.svn/pristine/ee/eee9b2b3acbd68f8c7a6c4f239076789f26dcb4a.svn-base
new file mode 100644
index 0000000..59474ed
--- /dev/null
+++ b/jni/pjproject-android/.svn/pristine/ee/eee9b2b3acbd68f8c7a6c4f239076789f26dcb4a.svn-base
@@ -0,0 +1,773 @@
+//------------------------------------------------------------------------------
+// File: WXUtil.cpp
+//
+// Desc: DirectShow base classes - implements helper classes for building
+// multimedia filters.
+//
+// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
+//------------------------------------------------------------------------------
+
+#include <pjmedia-videodev/config.h>
+
+#if defined(PJMEDIA_VIDEO_DEV_HAS_DSHOW) && PJMEDIA_VIDEO_DEV_HAS_DSHOW != 0
+
+#include <streams.h>
+#define STRSAFE_NO_DEPRECATE
+#include <strsafe.h>
+
+
+// --- 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 = 0;
+
+ // 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 = 0;
+ DWORD dwThreadPriority = THREAD_PRIORITY_HIGHEST;
+
+ 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;
+}
+
+
+#endif /* PJMEDIA_VIDEO_DEV_HAS_DSHOW */