~ubuntu-branches/ubuntu/wily/sflphone/wily

« back to all changes in this revision

Viewing changes to daemon/libs/pjproject-2.1.0/third_party/BaseClasses/wxutil.cpp

  • Committer: Package Import Robot
  • Author(s): Francois Marier, Francois Marier, Mark Purcell
  • Date: 2014-10-18 15:08:50 UTC
  • mfrom: (1.1.12)
  • mto: This revision was merged to the branch mainline in revision 29.
  • Revision ID: package-import@ubuntu.com-20141018150850-2exfk34ckb15pcwi
Tags: 1.4.1-0.1
[ Francois Marier ]
* Non-maintainer upload
* New upstream release (closes: #759576, #741130)
  - debian/rules +PJPROJECT_VERSION := 2.2.1
  - add upstream patch to fix broken TLS support
  - add patch to fix pjproject regression

[ Mark Purcell ]
* Build-Depends:
  - sflphone-daemon + libavformat-dev, libavcodec-dev, libswscale-dev,
  libavdevice-dev, libavutil-dev
  - sflphone-gnome + libclutter-gtk-1.0-dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
//------------------------------------------------------------------------------
2
 
// File: WXUtil.cpp
3
 
//
4
 
// Desc: DirectShow base classes - implements helper classes for building
5
 
//       multimedia filters.
6
 
//
7
 
// Copyright (c) 1992-2001 Microsoft Corporation.  All rights reserved.
8
 
//------------------------------------------------------------------------------
9
 
 
10
 
#include <pjmedia-videodev/config.h>
11
 
 
12
 
#if defined(PJMEDIA_VIDEO_DEV_HAS_DSHOW) && PJMEDIA_VIDEO_DEV_HAS_DSHOW != 0
13
 
 
14
 
#include <streams.h>
15
 
#define STRSAFE_NO_DEPRECATE
16
 
#include <strsafe.h>
17
 
 
18
 
 
19
 
// --- CAMEvent -----------------------
20
 
CAMEvent::CAMEvent(BOOL fManualReset, __inout_opt HRESULT *phr)
21
 
{
22
 
    m_hEvent = CreateEvent(NULL, fManualReset, FALSE, NULL);
23
 
    if (NULL == m_hEvent) {
24
 
        if (NULL != phr && SUCCEEDED(*phr)) {
25
 
            *phr = E_OUTOFMEMORY;
26
 
        }
27
 
    }
28
 
}
29
 
 
30
 
CAMEvent::CAMEvent(__inout_opt HRESULT *phr)
31
 
{
32
 
    m_hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
33
 
    if (NULL == m_hEvent) {
34
 
        if (NULL != phr && SUCCEEDED(*phr)) {
35
 
            *phr = E_OUTOFMEMORY;
36
 
        }
37
 
    }
38
 
}
39
 
 
40
 
CAMEvent::~CAMEvent()
41
 
{
42
 
    if (m_hEvent) {
43
 
        EXECUTE_ASSERT(CloseHandle(m_hEvent));
44
 
    }
45
 
}
46
 
 
47
 
 
48
 
// --- CAMMsgEvent -----------------------
49
 
// One routine.  The rest is handled in CAMEvent
50
 
 
51
 
CAMMsgEvent::CAMMsgEvent(__inout_opt HRESULT *phr) : CAMEvent(FALSE, phr)
52
 
{
53
 
}
54
 
 
55
 
BOOL CAMMsgEvent::WaitMsg(DWORD dwTimeout)
56
 
{
57
 
    // wait for the event to be signalled, or for the
58
 
    // timeout (in MS) to expire.  allow SENT messages
59
 
    // to be processed while we wait
60
 
    DWORD dwWait;
61
 
    DWORD dwStartTime = 0;
62
 
 
63
 
    // set the waiting period.
64
 
    DWORD dwWaitTime = dwTimeout;
65
 
 
66
 
    // the timeout will eventually run down as we iterate
67
 
    // processing messages.  grab the start time so that
68
 
    // we can calculate elapsed times.
69
 
    if (dwWaitTime != INFINITE) {
70
 
        dwStartTime = timeGetTime();
71
 
    }
72
 
 
73
 
    do {
74
 
        dwWait = MsgWaitForMultipleObjects(1,&m_hEvent,FALSE, dwWaitTime, QS_SENDMESSAGE);
75
 
        if (dwWait == WAIT_OBJECT_0 + 1) {
76
 
            MSG Message;
77
 
            PeekMessage(&Message,NULL,0,0,PM_NOREMOVE);
78
 
 
79
 
            // If we have an explicit length of time to wait calculate
80
 
            // the next wake up point - which might be now.
81
 
            // If dwTimeout is INFINITE, it stays INFINITE
82
 
            if (dwWaitTime != INFINITE) {
83
 
 
84
 
                DWORD dwElapsed = timeGetTime()-dwStartTime;
85
 
 
86
 
                dwWaitTime =
87
 
                    (dwElapsed >= dwTimeout)
88
 
                        ? 0  // wake up with WAIT_TIMEOUT
89
 
                        : dwTimeout-dwElapsed;
90
 
            }
91
 
        }
92
 
    } while (dwWait == WAIT_OBJECT_0 + 1);
93
 
 
94
 
    // return TRUE if we woke on the event handle,
95
 
    //        FALSE if we timed out.
96
 
    return (dwWait == WAIT_OBJECT_0);
97
 
}
98
 
 
99
 
// --- CAMThread ----------------------
100
 
 
101
 
 
102
 
CAMThread::CAMThread(__inout_opt HRESULT *phr)
103
 
    : m_EventSend(TRUE, phr),     // must be manual-reset for CheckRequest()
104
 
      m_EventComplete(FALSE, phr)
105
 
{
106
 
    m_hThread = NULL;
107
 
}
108
 
 
109
 
CAMThread::~CAMThread() {
110
 
    Close();
111
 
}
112
 
 
113
 
 
114
 
// when the thread starts, it calls this function. We unwrap the 'this'
115
 
//pointer and call ThreadProc.
116
 
DWORD WINAPI
117
 
CAMThread::InitialThreadProc(__inout LPVOID pv)
118
 
{
119
 
    HRESULT hrCoInit = CAMThread::CoInitializeHelper();
120
 
    if(FAILED(hrCoInit)) {
121
 
        DbgLog((LOG_ERROR, 1, TEXT("CoInitializeEx failed.")));
122
 
    }
123
 
 
124
 
    CAMThread * pThread = (CAMThread *) pv;
125
 
 
126
 
    HRESULT hr = pThread->ThreadProc();
127
 
 
128
 
    if(SUCCEEDED(hrCoInit)) {
129
 
        CoUninitialize();
130
 
    }
131
 
 
132
 
    return hr;
133
 
}
134
 
 
135
 
BOOL
136
 
CAMThread::Create()
137
 
{
138
 
    DWORD threadid;
139
 
 
140
 
    CAutoLock lock(&m_AccessLock);
141
 
 
142
 
    if (ThreadExists()) {
143
 
        return FALSE;
144
 
    }
145
 
 
146
 
    m_hThread = CreateThread(
147
 
                    NULL,
148
 
                    0,
149
 
                    CAMThread::InitialThreadProc,
150
 
                    this,
151
 
                    0,
152
 
                    &threadid);
153
 
 
154
 
    if (!m_hThread) {
155
 
        return FALSE;
156
 
    }
157
 
 
158
 
    return TRUE;
159
 
}
160
 
 
161
 
DWORD
162
 
CAMThread::CallWorker(DWORD dwParam)
163
 
{
164
 
    // lock access to the worker thread for scope of this object
165
 
    CAutoLock lock(&m_AccessLock);
166
 
 
167
 
    if (!ThreadExists()) {
168
 
        return (DWORD) E_FAIL;
169
 
    }
170
 
 
171
 
    // set the parameter
172
 
    m_dwParam = dwParam;
173
 
 
174
 
    // signal the worker thread
175
 
    m_EventSend.Set();
176
 
 
177
 
    // wait for the completion to be signalled
178
 
    m_EventComplete.Wait();
179
 
 
180
 
    // done - this is the thread's return value
181
 
    return m_dwReturnVal;
182
 
}
183
 
 
184
 
// Wait for a request from the client
185
 
DWORD
186
 
CAMThread::GetRequest()
187
 
{
188
 
    m_EventSend.Wait();
189
 
    return m_dwParam;
190
 
}
191
 
 
192
 
// is there a request?
193
 
BOOL
194
 
CAMThread::CheckRequest(__out_opt DWORD * pParam)
195
 
{
196
 
    if (!m_EventSend.Check()) {
197
 
        return FALSE;
198
 
    } else {
199
 
        if (pParam) {
200
 
            *pParam = m_dwParam;
201
 
        }
202
 
        return TRUE;
203
 
    }
204
 
}
205
 
 
206
 
// reply to the request
207
 
void
208
 
CAMThread::Reply(DWORD dw)
209
 
{
210
 
    m_dwReturnVal = dw;
211
 
 
212
 
    // The request is now complete so CheckRequest should fail from
213
 
    // now on
214
 
    //
215
 
    // This event should be reset BEFORE we signal the client or
216
 
    // the client may Set it before we reset it and we'll then
217
 
    // reset it (!)
218
 
 
219
 
    m_EventSend.Reset();
220
 
 
221
 
    // Tell the client we're finished
222
 
 
223
 
    m_EventComplete.Set();
224
 
}
225
 
 
226
 
HRESULT CAMThread::CoInitializeHelper()
227
 
{
228
 
    // call CoInitializeEx and tell OLE not to create a window (this
229
 
    // thread probably won't dispatch messages and will hang on
230
 
    // broadcast msgs o/w).
231
 
    //
232
 
    // If CoInitEx is not available, threads that don't call CoCreate
233
 
    // aren't affected. Threads that do will have to handle the
234
 
    // failure. Perhaps we should fall back to CoInitialize and risk
235
 
    // hanging?
236
 
    //
237
 
 
238
 
    // older versions of ole32.dll don't have CoInitializeEx
239
 
 
240
 
    HRESULT hr = E_FAIL;
241
 
    HINSTANCE hOle = GetModuleHandle(TEXT("ole32.dll"));
242
 
    if(hOle)
243
 
    {
244
 
        typedef HRESULT (STDAPICALLTYPE *PCoInitializeEx)(
245
 
            LPVOID pvReserved, DWORD dwCoInit);
246
 
        PCoInitializeEx pCoInitializeEx =
247
 
            (PCoInitializeEx)(GetProcAddress(hOle, "CoInitializeEx"));
248
 
        if(pCoInitializeEx)
249
 
        {
250
 
            hr = (*pCoInitializeEx)(0, COINIT_DISABLE_OLE1DDE );
251
 
        }
252
 
    }
253
 
    else
254
 
    {
255
 
        // caller must load ole32.dll
256
 
        DbgBreak("couldn't locate ole32.dll");
257
 
    }
258
 
 
259
 
    return hr;
260
 
}
261
 
 
262
 
 
263
 
// destructor for CMsgThread  - cleans up any messages left in the
264
 
// queue when the thread exited
265
 
CMsgThread::~CMsgThread()
266
 
{
267
 
    if (m_hThread != NULL) {
268
 
        WaitForSingleObject(m_hThread, INFINITE);
269
 
        EXECUTE_ASSERT(CloseHandle(m_hThread));
270
 
    }
271
 
 
272
 
    POSITION pos = m_ThreadQueue.GetHeadPosition();
273
 
    while (pos) {
274
 
        CMsg * pMsg = m_ThreadQueue.GetNext(pos);
275
 
        delete pMsg;
276
 
    }
277
 
    m_ThreadQueue.RemoveAll();
278
 
 
279
 
    if (m_hSem != NULL) {
280
 
        EXECUTE_ASSERT(CloseHandle(m_hSem));
281
 
    }
282
 
}
283
 
 
284
 
BOOL
285
 
CMsgThread::CreateThread(
286
 
    )
287
 
{
288
 
    m_hSem = CreateSemaphore(NULL, 0, 0x7FFFFFFF, NULL);
289
 
    if (m_hSem == NULL) {
290
 
        return FALSE;
291
 
    }
292
 
 
293
 
    m_hThread = ::CreateThread(NULL, 0, DefaultThreadProc,
294
 
                               (LPVOID)this, 0, &m_ThreadId);
295
 
    return m_hThread != NULL;
296
 
}
297
 
 
298
 
 
299
 
// This is the threads message pump.  Here we get and dispatch messages to
300
 
// clients thread proc until the client refuses to process a message.
301
 
// The client returns a non-zero value to stop the message pump, this
302
 
// value becomes the threads exit code.
303
 
 
304
 
DWORD WINAPI
305
 
CMsgThread::DefaultThreadProc(
306
 
    __inout LPVOID lpParam
307
 
    )
308
 
{
309
 
    CMsgThread *lpThis = (CMsgThread *)lpParam;
310
 
    CMsg msg;
311
 
    LRESULT lResult;
312
 
 
313
 
    // !!!
314
 
    CoInitialize(NULL);
315
 
 
316
 
    // allow a derived class to handle thread startup
317
 
    lpThis->OnThreadInit();
318
 
 
319
 
    do {
320
 
        lpThis->GetThreadMsg(&msg);
321
 
        lResult = lpThis->ThreadMessageProc(msg.uMsg,msg.dwFlags,
322
 
                                            msg.lpParam, msg.pEvent);
323
 
    } while (lResult == 0L);
324
 
 
325
 
    // !!!
326
 
    CoUninitialize();
327
 
 
328
 
    return (DWORD)lResult;
329
 
}
330
 
 
331
 
 
332
 
// Block until the next message is placed on the list m_ThreadQueue.
333
 
// copies the message to the message pointed to by *pmsg
334
 
void
335
 
CMsgThread::GetThreadMsg(__out CMsg *msg)
336
 
{
337
 
    CMsg * pmsg = NULL;
338
 
 
339
 
    // keep trying until a message appears
340
 
    while (TRUE) {
341
 
        {
342
 
            CAutoLock lck(&m_Lock);
343
 
            pmsg = m_ThreadQueue.RemoveHead();
344
 
            if (pmsg == NULL) {
345
 
                m_lWaiting++;
346
 
            } else {
347
 
                break;
348
 
            }
349
 
        }
350
 
        // the semaphore will be signalled when it is non-empty
351
 
        WaitForSingleObject(m_hSem, INFINITE);
352
 
    }
353
 
    // copy fields to caller's CMsg
354
 
    *msg = *pmsg;
355
 
 
356
 
    // this CMsg was allocated by the 'new' in PutThreadMsg
357
 
    delete pmsg;
358
 
 
359
 
}
360
 
 
361
 
// Helper function - convert int to WSTR
362
 
void WINAPI IntToWstr(int i, __out_ecount(12) LPWSTR wstr)
363
 
{
364
 
#ifdef UNICODE
365
 
    if (FAILED(StringCchPrintf(wstr, 12, L"%d", i))) {
366
 
        wstr[0] = 0;
367
 
    }
368
 
#else
369
 
    TCHAR temp[12];
370
 
    if (FAILED(StringCchPrintf(temp, NUMELMS(temp), "%d", i))) {
371
 
        wstr[0] = 0;
372
 
    } else {
373
 
        MultiByteToWideChar(CP_ACP, 0, temp, -1, wstr, 12);
374
 
    }
375
 
#endif
376
 
} // IntToWstr
377
 
 
378
 
 
379
 
#define MEMORY_ALIGNMENT        4
380
 
#define MEMORY_ALIGNMENT_LOG2   2
381
 
#define MEMORY_ALIGNMENT_MASK   MEMORY_ALIGNMENT - 1
382
 
 
383
 
void * __stdcall memmoveInternal(void * dst, const void * src, size_t count)
384
 
{
385
 
    void * ret = dst;
386
 
 
387
 
#ifdef _X86_
388
 
    if (dst <= src || (char *)dst >= ((char *)src + count)) {
389
 
 
390
 
        /*
391
 
         * Non-Overlapping Buffers
392
 
         * copy from lower addresses to higher addresses
393
 
         */
394
 
        _asm {
395
 
            mov     esi,src
396
 
            mov     edi,dst
397
 
            mov     ecx,count
398
 
            cld
399
 
            mov     edx,ecx
400
 
            and     edx,MEMORY_ALIGNMENT_MASK
401
 
            shr     ecx,MEMORY_ALIGNMENT_LOG2
402
 
            rep     movsd
403
 
            or      ecx,edx
404
 
            jz      memmove_done
405
 
            rep     movsb
406
 
memmove_done:
407
 
        }
408
 
    }
409
 
    else {
410
 
 
411
 
        /*
412
 
         * Overlapping Buffers
413
 
         * copy from higher addresses to lower addresses
414
 
         */
415
 
        _asm {
416
 
            mov     esi,src
417
 
            mov     edi,dst
418
 
            mov     ecx,count
419
 
            std
420
 
            add     esi,ecx
421
 
            add     edi,ecx
422
 
            dec     esi
423
 
            dec     edi
424
 
            rep     movsb
425
 
            cld
426
 
        }
427
 
    }
428
 
#else
429
 
    MoveMemory(dst, src, count);
430
 
#endif
431
 
 
432
 
    return ret;
433
 
}
434
 
 
435
 
HRESULT AMSafeMemMoveOffset(
436
 
    __in_bcount(dst_size) void * dst,
437
 
    __in size_t dst_size,
438
 
    __in DWORD cb_dst_offset,
439
 
    __in_bcount(src_size) const void * src,
440
 
    __in size_t src_size,
441
 
    __in DWORD cb_src_offset,
442
 
    __in size_t count)
443
 
{
444
 
    // prevent read overruns
445
 
    if( count + cb_src_offset < count ||   // prevent integer overflow
446
 
        count + cb_src_offset > src_size)  // prevent read overrun
447
 
    {
448
 
        return E_INVALIDARG;
449
 
    }
450
 
 
451
 
    // prevent write overruns
452
 
    if( count + cb_dst_offset < count ||   // prevent integer overflow
453
 
        count + cb_dst_offset > dst_size)  // prevent write overrun
454
 
    {
455
 
        return E_INVALIDARG;
456
 
    }
457
 
 
458
 
    memmoveInternal( (BYTE *)dst+cb_dst_offset, (BYTE *)src+cb_src_offset, count);
459
 
    return S_OK;
460
 
}
461
 
 
462
 
 
463
 
#ifdef DEBUG
464
 
/******************************Public*Routine******************************\
465
 
* Debug CCritSec helpers
466
 
*
467
 
* We provide debug versions of the Constructor, destructor, Lock and Unlock
468
 
* routines.  The debug code tracks who owns each critical section by
469
 
* maintaining a depth count.
470
 
*
471
 
* History:
472
 
*
473
 
\**************************************************************************/
474
 
 
475
 
CCritSec::CCritSec()
476
 
{
477
 
    InitializeCriticalSection(&m_CritSec);
478
 
    m_currentOwner = m_lockCount = 0;
479
 
    m_fTrace = FALSE;
480
 
}
481
 
 
482
 
CCritSec::~CCritSec()
483
 
{
484
 
    DeleteCriticalSection(&m_CritSec);
485
 
}
486
 
 
487
 
void CCritSec::Lock()
488
 
{
489
 
    UINT tracelevel=3;
490
 
    DWORD us = GetCurrentThreadId();
491
 
    DWORD currentOwner = m_currentOwner;
492
 
    if (currentOwner && (currentOwner != us)) {
493
 
        // already owned, but not by us
494
 
        if (m_fTrace) {
495
 
            DbgLog((LOG_LOCKING, 2, TEXT("Thread %d about to wait for lock %x owned by %d"),
496
 
                GetCurrentThreadId(), &m_CritSec, currentOwner));
497
 
            tracelevel=2;
498
 
                // if we saw the message about waiting for the critical
499
 
                // section we ensure we see the message when we get the
500
 
                // critical section
501
 
        }
502
 
    }
503
 
    EnterCriticalSection(&m_CritSec);
504
 
    if (0 == m_lockCount++) {
505
 
        // we now own it for the first time.  Set owner information
506
 
        m_currentOwner = us;
507
 
 
508
 
        if (m_fTrace) {
509
 
            DbgLog((LOG_LOCKING, tracelevel, TEXT("Thread %d now owns lock %x"), m_currentOwner, &m_CritSec));
510
 
        }
511
 
    }
512
 
}
513
 
 
514
 
void CCritSec::Unlock() {
515
 
    if (0 == --m_lockCount) {
516
 
        // about to be unowned
517
 
        if (m_fTrace) {
518
 
            DbgLog((LOG_LOCKING, 3, TEXT("Thread %d releasing lock %x"), m_currentOwner, &m_CritSec));
519
 
        }
520
 
 
521
 
        m_currentOwner = 0;
522
 
    }
523
 
    LeaveCriticalSection(&m_CritSec);
524
 
}
525
 
 
526
 
void WINAPI DbgLockTrace(CCritSec * pcCrit, BOOL fTrace)
527
 
{
528
 
    pcCrit->m_fTrace = fTrace;
529
 
}
530
 
 
531
 
BOOL WINAPI CritCheckIn(CCritSec * pcCrit)
532
 
{
533
 
    return (GetCurrentThreadId() == pcCrit->m_currentOwner);
534
 
}
535
 
 
536
 
BOOL WINAPI CritCheckIn(const CCritSec * pcCrit)
537
 
{
538
 
    return (GetCurrentThreadId() == pcCrit->m_currentOwner);
539
 
}
540
 
 
541
 
BOOL WINAPI CritCheckOut(CCritSec * pcCrit)
542
 
{
543
 
    return (GetCurrentThreadId() != pcCrit->m_currentOwner);
544
 
}
545
 
 
546
 
BOOL WINAPI CritCheckOut(const CCritSec * pcCrit)
547
 
{
548
 
    return (GetCurrentThreadId() != pcCrit->m_currentOwner);
549
 
}
550
 
#endif
551
 
 
552
 
 
553
 
STDAPI WriteBSTR(__deref_out BSTR *pstrDest, LPCWSTR szSrc)
554
 
{
555
 
    *pstrDest = SysAllocString( szSrc );
556
 
    if( !(*pstrDest) ) return E_OUTOFMEMORY;
557
 
    return NOERROR;
558
 
}
559
 
 
560
 
 
561
 
STDAPI FreeBSTR(__deref_in BSTR* pstr)
562
 
{
563
 
    if( (PVOID)*pstr == NULL ) return S_FALSE;
564
 
    SysFreeString( *pstr );
565
 
    return NOERROR;
566
 
}
567
 
 
568
 
 
569
 
// Return a wide string - allocating memory for it
570
 
// Returns:
571
 
//    S_OK          - no error
572
 
//    E_POINTER     - ppszReturn == NULL
573
 
//    E_OUTOFMEMORY - can't allocate memory for returned string
574
 
STDAPI AMGetWideString(LPCWSTR psz, __deref_out LPWSTR *ppszReturn)
575
 
{
576
 
    CheckPointer(ppszReturn, E_POINTER);
577
 
    ValidateReadWritePtr(ppszReturn, sizeof(LPWSTR));
578
 
    *ppszReturn = NULL;
579
 
    size_t nameLen;
580
 
    HRESULT hr = StringCbLengthW(psz, 100000, &nameLen);
581
 
    if (FAILED(hr)) {
582
 
        return hr;
583
 
    }
584
 
    *ppszReturn = (LPWSTR)CoTaskMemAlloc(nameLen + sizeof(WCHAR));
585
 
    if (*ppszReturn == NULL) {
586
 
       return E_OUTOFMEMORY;
587
 
    }
588
 
    CopyMemory(*ppszReturn, psz, nameLen + sizeof(WCHAR));
589
 
    return NOERROR;
590
 
}
591
 
 
592
 
// Waits for the HANDLE hObject.  While waiting messages sent
593
 
// to windows on our thread by SendMessage will be processed.
594
 
// Using this function to do waits and mutual exclusion
595
 
// avoids some deadlocks in objects with windows.
596
 
// Return codes are the same as for WaitForSingleObject
597
 
DWORD WINAPI WaitDispatchingMessages(
598
 
    HANDLE hObject,
599
 
    DWORD dwWait,
600
 
    HWND hwnd,
601
 
    UINT uMsg,
602
 
    HANDLE hEvent)
603
 
{
604
 
    BOOL bPeeked = FALSE;
605
 
    DWORD dwResult;
606
 
    DWORD dwStart = 0;
607
 
    DWORD dwThreadPriority = THREAD_PRIORITY_HIGHEST;
608
 
 
609
 
    static UINT uMsgId = 0;
610
 
 
611
 
    HANDLE hObjects[2] = { hObject, hEvent };
612
 
    if (dwWait != INFINITE && dwWait != 0) {
613
 
        dwStart = GetTickCount();
614
 
    }
615
 
    for (; ; ) {
616
 
        DWORD nCount = NULL != hEvent ? 2 : 1;
617
 
 
618
 
        //  Minimize the chance of actually dispatching any messages
619
 
        //  by seeing if we can lock immediately.
620
 
        dwResult = WaitForMultipleObjects(nCount, hObjects, FALSE, 0);
621
 
        if (dwResult < WAIT_OBJECT_0 + nCount) {
622
 
            break;
623
 
        }
624
 
 
625
 
        DWORD dwTimeOut = dwWait;
626
 
        if (dwTimeOut > 10) {
627
 
            dwTimeOut = 10;
628
 
        }
629
 
        dwResult = MsgWaitForMultipleObjects(
630
 
                             nCount,
631
 
                             hObjects,
632
 
                             FALSE,
633
 
                             dwTimeOut,
634
 
                             hwnd == NULL ? QS_SENDMESSAGE :
635
 
                                            QS_SENDMESSAGE + QS_POSTMESSAGE);
636
 
        if (dwResult == WAIT_OBJECT_0 + nCount ||
637
 
            dwResult == WAIT_TIMEOUT && dwTimeOut != dwWait) {
638
 
            MSG msg;
639
 
            if (hwnd != NULL) {
640
 
                while (PeekMessage(&msg, hwnd, uMsg, uMsg, PM_REMOVE)) {
641
 
                    DispatchMessage(&msg);
642
 
                }
643
 
            }
644
 
            // Do this anyway - the previous peek doesn't flush out the
645
 
            // messages
646
 
            PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE);
647
 
 
648
 
            if (dwWait != INFINITE && dwWait != 0) {
649
 
                DWORD dwNow = GetTickCount();
650
 
 
651
 
                // Working with differences handles wrap-around
652
 
                DWORD dwDiff = dwNow - dwStart;
653
 
                if (dwDiff > dwWait) {
654
 
                    dwWait = 0;
655
 
                } else {
656
 
                    dwWait -= dwDiff;
657
 
                }
658
 
                dwStart = dwNow;
659
 
            }
660
 
            if (!bPeeked) {
661
 
                //  Raise our priority to prevent our message queue
662
 
                //  building up
663
 
                dwThreadPriority = GetThreadPriority(GetCurrentThread());
664
 
                if (dwThreadPriority < THREAD_PRIORITY_HIGHEST) {
665
 
                    SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
666
 
                }
667
 
                bPeeked = TRUE;
668
 
            }
669
 
        } else {
670
 
            break;
671
 
        }
672
 
    }
673
 
    if (bPeeked) {
674
 
        SetThreadPriority(GetCurrentThread(), dwThreadPriority);
675
 
        if (HIWORD(GetQueueStatus(QS_POSTMESSAGE)) & QS_POSTMESSAGE) {
676
 
            if (uMsgId == 0) {
677
 
                uMsgId = RegisterWindowMessage(TEXT("AMUnblock"));
678
 
            }
679
 
            if (uMsgId != 0) {
680
 
                MSG msg;
681
 
                //  Remove old ones
682
 
                while (PeekMessage(&msg, (HWND)-1, uMsgId, uMsgId, PM_REMOVE)) {
683
 
                }
684
 
            }
685
 
            PostThreadMessage(GetCurrentThreadId(), uMsgId, 0, 0);
686
 
        }
687
 
    }
688
 
    return dwResult;
689
 
}
690
 
 
691
 
HRESULT AmGetLastErrorToHResult()
692
 
{
693
 
    DWORD dwLastError = GetLastError();
694
 
    if(dwLastError != 0)
695
 
    {
696
 
        return HRESULT_FROM_WIN32(dwLastError);
697
 
    }
698
 
    else
699
 
    {
700
 
        return E_FAIL;
701
 
    }
702
 
}
703
 
 
704
 
IUnknown* QzAtlComPtrAssign(__deref_inout_opt IUnknown** pp, __in_opt IUnknown* lp)
705
 
{
706
 
    if (lp != NULL)
707
 
        lp->AddRef();
708
 
    if (*pp)
709
 
        (*pp)->Release();
710
 
    *pp = lp;
711
 
    return lp;
712
 
}
713
 
 
714
 
/******************************************************************************
715
 
 
716
 
CompatibleTimeSetEvent
717
 
 
718
 
    CompatibleTimeSetEvent() sets the TIME_KILL_SYNCHRONOUS flag before calling
719
 
timeSetEvent() if the current operating system supports it.  TIME_KILL_SYNCHRONOUS
720
 
is supported on Windows XP and later operating systems.
721
 
 
722
 
Parameters:
723
 
- The same parameters as timeSetEvent().  See timeSetEvent()'s documentation in 
724
 
the Platform SDK for more information.
725
 
 
726
 
Return Value:
727
 
- The same return value as timeSetEvent().  See timeSetEvent()'s documentation in 
728
 
the Platform SDK for more information.
729
 
 
730
 
******************************************************************************/
731
 
MMRESULT CompatibleTimeSetEvent( UINT uDelay, UINT uResolution, __in LPTIMECALLBACK lpTimeProc, DWORD_PTR dwUser, UINT fuEvent )
732
 
{
733
 
    #if WINVER >= 0x0501
734
 
    {
735
 
        static bool fCheckedVersion = false;
736
 
        static bool fTimeKillSynchronousFlagAvailable = false; 
737
 
 
738
 
        if( !fCheckedVersion ) {
739
 
            fTimeKillSynchronousFlagAvailable = TimeKillSynchronousFlagAvailable();
740
 
            fCheckedVersion = true;
741
 
        }
742
 
 
743
 
        if( fTimeKillSynchronousFlagAvailable ) {
744
 
            fuEvent = fuEvent | TIME_KILL_SYNCHRONOUS;
745
 
        }
746
 
    }
747
 
    #endif // WINVER >= 0x0501
748
 
 
749
 
    return timeSetEvent( uDelay, uResolution, lpTimeProc, dwUser, fuEvent );
750
 
}
751
 
 
752
 
bool TimeKillSynchronousFlagAvailable( void )
753
 
{
754
 
    OSVERSIONINFO osverinfo;
755
 
 
756
 
    osverinfo.dwOSVersionInfoSize = sizeof(osverinfo);
757
 
 
758
 
    if( GetVersionEx( &osverinfo ) ) {
759
 
        
760
 
        // Windows XP's major version is 5 and its' minor version is 1.
761
 
        // timeSetEvent() started supporting the TIME_KILL_SYNCHRONOUS flag
762
 
        // in Windows XP.
763
 
        if( (osverinfo.dwMajorVersion > 5) || 
764
 
            ( (osverinfo.dwMajorVersion == 5) && (osverinfo.dwMinorVersion >= 1) ) ) {
765
 
            return true;
766
 
        }
767
 
    }
768
 
 
769
 
    return false;
770
 
}
771
 
 
772
 
 
773
 
#endif /* PJMEDIA_VIDEO_DEV_HAS_DSHOW */