* #36737: switch back to svn repo, remove assert in sip_transaction.c
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 */