1 //------------------------------------------------------------------------------
4 // Desc: DirectShow base classes - implements helper classes for building
7 // Copyright (c) 1992-2002 Microsoft Corporation. All rights reserved.
8 //------------------------------------------------------------------------------
14 // Declare function from largeint.h we need so that PPC can build
18 // Enlarged integer divide - 64-bits / 32-bits > 32-bits
23 #define LLtoU64(x) (*(unsigned __int64*)(void*)(&(x)))
28 EnlargedUnsignedDivide (
29 IN ULARGE_INTEGER Dividend
,
34 // return remainder if necessary
35 if (Remainder
!= NULL
)
36 *Remainder
= (ULONG
)(LLtoU64(Dividend
) % Divisor
);
37 return (ULONG
)(LLtoU64(Dividend
) / Divisor
);
44 EnlargedUnsignedDivide (
45 IN ULARGE_INTEGER Dividend
,
52 mov eax
,Dividend
.LowPart
53 mov edx
,Dividend
.HighPart
66 // --- CAMEvent -----------------------
67 CAMEvent::CAMEvent(BOOL fManualReset
)
69 m_hEvent
= CreateEvent(NULL
, fManualReset
, FALSE
, NULL
);
75 EXECUTE_ASSERT(CloseHandle(m_hEvent
));
80 // --- CAMMsgEvent -----------------------
81 // One routine. The rest is handled in CAMEvent
83 BOOL
CAMMsgEvent::WaitMsg(DWORD dwTimeout
)
85 // wait for the event to be signalled, or for the
86 // timeout (in MS) to expire. allow SENT messages
87 // to be processed while we wait
91 // set the waiting period.
92 DWORD dwWaitTime
= dwTimeout
;
94 // the timeout will eventually run down as we iterate
95 // processing messages. grab the start time so that
96 // we can calculate elapsed times.
97 if (dwWaitTime
!= INFINITE
) {
98 dwStartTime
= timeGetTime();
102 dwWait
= MsgWaitForMultipleObjects(1,&m_hEvent
,FALSE
, dwWaitTime
, QS_SENDMESSAGE
);
103 if (dwWait
== WAIT_OBJECT_0
+ 1) {
105 PeekMessage(&Message
,NULL
,0,0,PM_NOREMOVE
);
107 // If we have an explicit length of time to wait calculate
108 // the next wake up point - which might be now.
109 // If dwTimeout is INFINITE, it stays INFINITE
110 if (dwWaitTime
!= INFINITE
) {
112 DWORD dwElapsed
= timeGetTime()-dwStartTime
;
115 (dwElapsed
>= dwTimeout
)
116 ? 0 // wake up with WAIT_TIMEOUT
117 : dwTimeout
-dwElapsed
;
120 } while (dwWait
== WAIT_OBJECT_0
+ 1);
122 // return TRUE if we woke on the event handle,
123 // FALSE if we timed out.
124 return (dwWait
== WAIT_OBJECT_0
);
127 // --- CAMThread ----------------------
130 CAMThread::CAMThread()
131 : m_EventSend(TRUE
) // must be manual-reset for CheckRequest()
136 CAMThread::~CAMThread() {
141 // when the thread starts, it calls this function. We unwrap the 'this'
142 //pointer and call ThreadProc.
144 CAMThread::InitialThreadProc(LPVOID pv
)
146 HRESULT hrCoInit
= CAMThread::CoInitializeHelper();
147 if(FAILED(hrCoInit
)) {
148 DbgLog((LOG_ERROR
, 1, TEXT("CoInitializeEx failed.")));
151 CAMThread
* pThread
= (CAMThread
*) pv
;
153 HRESULT hr
= pThread
->ThreadProc();
155 if(SUCCEEDED(hrCoInit
)) {
167 CAutoLock
lock(&m_AccessLock
);
169 if (ThreadExists()) {
173 m_hThread
= CreateThread(
176 CAMThread::InitialThreadProc
,
189 CAMThread::CallWorker(DWORD dwParam
)
191 // lock access to the worker thread for scope of this object
192 CAutoLock
lock(&m_AccessLock
);
194 if (!ThreadExists()) {
195 return (DWORD
) E_FAIL
;
201 // signal the worker thread
204 // wait for the completion to be signalled
205 m_EventComplete
.Wait();
207 // done - this is the thread's return value
208 return m_dwReturnVal
;
211 // Wait for a request from the client
213 CAMThread::GetRequest()
219 // is there a request?
221 CAMThread::CheckRequest(DWORD
* pParam
)
223 if (!m_EventSend
.Check()) {
233 // reply to the request
235 CAMThread::Reply(DWORD dw
)
239 // The request is now complete so CheckRequest should fail from
242 // This event should be reset BEFORE we signal the client or
243 // the client may Set it before we reset it and we'll then
248 // Tell the client we're finished
250 m_EventComplete
.Set();
253 HRESULT
CAMThread::CoInitializeHelper()
255 // call CoInitializeEx and tell OLE not to create a window (this
256 // thread probably won't dispatch messages and will hang on
257 // broadcast msgs o/w).
259 // If CoInitEx is not available, threads that don't call CoCreate
260 // aren't affected. Threads that do will have to handle the
261 // failure. Perhaps we should fall back to CoInitialize and risk
265 // older versions of ole32.dll don't have CoInitializeEx
268 HINSTANCE hOle
= GetModuleHandle(TEXT("ole32.dll"));
271 typedef HRESULT (STDAPICALLTYPE
*PCoInitializeEx
)(
272 LPVOID pvReserved
, DWORD dwCoInit
);
273 PCoInitializeEx pCoInitializeEx
=
274 (PCoInitializeEx
)(GetProcAddress(hOle
, "CoInitializeEx"));
277 hr
= (*pCoInitializeEx
)(0, COINIT_DISABLE_OLE1DDE
);
282 // caller must load ole32.dll
283 DbgBreak("couldn't locate ole32.dll");
290 // destructor for CMsgThread - cleans up any messages left in the
291 // queue when the thread exited
292 CMsgThread::~CMsgThread()
294 if (m_hThread
!= NULL
) {
295 WaitForSingleObject(m_hThread
, INFINITE
);
296 EXECUTE_ASSERT(CloseHandle(m_hThread
));
299 POSITION pos
= m_ThreadQueue
.GetHeadPosition();
301 CMsg
* pMsg
= m_ThreadQueue
.GetNext(pos
);
304 m_ThreadQueue
.RemoveAll();
306 if (m_hSem
!= NULL
) {
307 EXECUTE_ASSERT(CloseHandle(m_hSem
));
312 CMsgThread::CreateThread(
315 m_hSem
= CreateSemaphore(NULL
, 0, 0x7FFFFFFF, NULL
);
316 if (m_hSem
== NULL
) {
320 m_hThread
= ::CreateThread(NULL
, 0, DefaultThreadProc
,
321 (LPVOID
)this, 0, &m_ThreadId
);
322 return m_hThread
!= NULL
;
326 // This is the threads message pump. Here we get and dispatch messages to
327 // clients thread proc until the client refuses to process a message.
328 // The client returns a non-zero value to stop the message pump, this
329 // value becomes the threads exit code.
332 CMsgThread::DefaultThreadProc(
336 CMsgThread
*lpThis
= (CMsgThread
*)lpParam
;
343 // allow a derived class to handle thread startup
344 lpThis
->OnThreadInit();
347 lpThis
->GetThreadMsg(&msg
);
348 lResult
= lpThis
->ThreadMessageProc(msg
.uMsg
,msg
.dwFlags
,
349 msg
.lpParam
, msg
.pEvent
);
350 } while (lResult
== 0L);
355 return (DWORD
)lResult
;
359 // Block until the next message is placed on the list m_ThreadQueue.
360 // copies the message to the message pointed to by *pmsg
362 CMsgThread::GetThreadMsg(CMsg
*msg
)
366 // keep trying until a message appears
369 CAutoLock
lck(&m_Lock
);
370 pmsg
= m_ThreadQueue
.RemoveHead();
377 // the semaphore will be signalled when it is non-empty
378 WaitForSingleObject(m_hSem
, INFINITE
);
380 // copy fields to caller's CMsg
383 // this CMsg was allocated by the 'new' in PutThreadMsg
389 // NOTE: as we need to use the same binaries on Win95 as on NT this code should
390 // be compiled WITHOUT unicode being defined. Otherwise we will not pick up
391 // these internal routines and the binary will not run on Win95.
394 // Windows 95 doesn't implement this, so we provide an implementation.
402 LPWSTR lpReturn
= lpString1
;
403 while (*lpString1
++ = *lpString2
++);
408 // Windows 95 doesn't implement this, so we provide an implementation.
418 LPWSTR lpReturn
= lpString1
;
420 while (--iMaxLength
&& (*lpString1
++ = *lpString2
++));
422 // If we ran out of room (which will be the case if
423 // iMaxLength is now 0) we still need to terminate the
425 if (!iMaxLength
) *lpString1
= L
'\0';
438 WCHAR c1
= *lpString1
;
439 WCHAR c2
= *lpString2
;
441 return (int) c1
- (int) c2
;
442 } while (*lpString1
++ && *lpString2
++);
455 WCHAR c1
= *lpString1
;
456 WCHAR c2
= *lpString2
;
457 if (c1
>= L
'A' && c1
<= L
'Z')
458 c1
-= (WCHAR
) (L
'A' - L
'a');
459 if (c2
>= L
'A' && c2
<= L
'Z')
460 c2
-= (WCHAR
) (L
'A' - L
'a');
463 return (int) c1
- (int) c2
;
464 } while (*lpString1
++ && *lpString2
++);
477 while (*(lpString
+(++i
)))
483 int WINAPIV
wsprintfWInternal(LPWSTR wszOut
, LPCWSTR pszFmt
, ...)
485 char fmt
[256]; // !!!
486 char ach
[256]; // !!!
490 va_start(va
, pszFmt
);
491 WideCharToMultiByte(GetACP(), 0, pszFmt
, -1, fmt
, 256, NULL
, NULL
);
492 i
= wvsprintfA(ach
, fmt
, va
);
495 MultiByteToWideChar(CP_ACP
, 0, ach
, -1, wszOut
, i
+1);
501 // need to provide the implementations in unicode for non-unicode
502 // builds linking with the unicode strmbase.lib
503 LPWSTR WINAPI
lstrcpyWInternal(
508 return lstrcpyW(lpString1
, lpString2
);
511 LPWSTR WINAPI
lstrcpynWInternal(
517 return lstrcpynW(lpString1
, lpString2
, iMaxLength
);
520 int WINAPI
lstrcmpWInternal(
525 return lstrcmpW(lpString1
, lpString2
);
529 int WINAPI
lstrcmpiWInternal(
534 return lstrcmpiW(lpString1
, lpString2
);
538 int WINAPI
lstrlenWInternal(
542 return lstrlenW(lpString
);
546 int WINAPIV
wsprintfWInternal(
547 LPWSTR wszOut
, LPCWSTR pszFmt
, ...)
550 va_start(va
, pszFmt
);
551 int i
= wvsprintfW(wszOut
, pszFmt
, va
);
558 // Helper function - convert int to WSTR
559 void WINAPI
IntToWstr(int i
, LPWSTR wstr
)
562 wsprintf(wstr
, L
"%d", i
);
565 wsprintf(temp
, "%d", i
);
566 MultiByteToWideChar(CP_ACP
, 0, temp
, -1, wstr
, 32);
572 void * memchrInternal(const void *pv
, int c
, size_t sz
)
574 BYTE
*pb
= (BYTE
*) pv
;
585 #define MEMORY_ALIGNMENT 4
586 #define MEMORY_ALIGNMENT_LOG2 2
587 #define MEMORY_ALIGNMENT_MASK MEMORY_ALIGNMENT - 1
589 void * __stdcall
memmoveInternal(void * dst
, const void * src
, size_t count
)
594 if (dst
<= src
|| (char *)dst
>= ((char *)src
+ count
)) {
597 * Non-Overlapping Buffers
598 * copy from lower addresses to higher addresses
606 and edx
,MEMORY_ALIGNMENT_MASK
607 shr ecx
,MEMORY_ALIGNMENT_LOG2
618 * Overlapping Buffers
619 * copy from higher addresses to lower addresses
635 MoveMemory(dst
, src
, count
);
641 /* Arithmetic functions to help with time format conversions
645 // work around bug in version 12.00.8385 of the alpha compiler where
646 // UInt32x32To64 sign-extends its arguments (?)
648 #define UInt32x32To64(a, b) (((ULONGLONG)((ULONG)(a)) & 0xffffffff) * ((ULONGLONG)((ULONG)(b)) & 0xffffffff))
651 /* Compute (a * b + d) / c */
652 LONGLONG WINAPI
llMulDiv(LONGLONG a
, LONGLONG b
, LONGLONG c
, LONGLONG d
)
654 /* Compute the absolute values to avoid signed arithmetic problems */
655 ULARGE_INTEGER ua
, ub
;
658 ua
.QuadPart
= (DWORDLONG
)(a
>= 0 ? a
: -a
);
659 ub
.QuadPart
= (DWORDLONG
)(b
>= 0 ? b
: -b
);
660 uc
= (DWORDLONG
)(c
>= 0 ? c
: -c
);
661 BOOL bSign
= (a
< 0) ^ (b
< 0);
663 /* Do long multiplication */
665 p
[0].QuadPart
= UInt32x32To64(ua
.LowPart
, ub
.LowPart
);
667 /* This next computation cannot overflow into p[1].HighPart because
668 the max number we can compute here is:
670 (2 ** 32 - 1) * (2 ** 32 - 1) + // ua.LowPart * ub.LowPart
671 (2 ** 32) * (2 ** 31) * (2 ** 32 - 1) * 2 // x.LowPart * y.HighPart * 2
673 == 2 ** 96 - 2 ** 64 + (2 ** 64 - 2 ** 33 + 1)
674 == 2 ** 96 - 2 ** 33 + 1
679 x
.QuadPart
= UInt32x32To64(ua
.LowPart
, ub
.HighPart
) +
680 UInt32x32To64(ua
.HighPart
, ub
.LowPart
) +
682 p
[0].HighPart
= x
.LowPart
;
683 p
[1].QuadPart
= UInt32x32To64(ua
.HighPart
, ub
.HighPart
) + x
.HighPart
;
686 ULARGE_INTEGER ud
[2];
688 ud
[0].QuadPart
= (DWORDLONG
)(-d
);
691 ud
[1].QuadPart
= (DWORDLONG
)(LONGLONG
)-1;
693 ud
[1].QuadPart
= (DWORDLONG
)0;
696 ud
[0].QuadPart
= (DWORDLONG
)d
;
698 ud
[1].QuadPart
= (DWORDLONG
)(LONGLONG
)-1;
700 ud
[1].QuadPart
= (DWORDLONG
)0;
703 /* Now do extended addition */
704 ULARGE_INTEGER uliTotal
;
707 uliTotal
.QuadPart
= (DWORDLONG
)ud
[0].LowPart
+ p
[0].LowPart
;
708 p
[0].LowPart
= uliTotal
.LowPart
;
710 /* Propagate carry */
711 uliTotal
.LowPart
= uliTotal
.HighPart
;
712 uliTotal
.HighPart
= 0;
714 /* Add 2nd most ls DWORDs */
715 uliTotal
.QuadPart
+= (DWORDLONG
)ud
[0].HighPart
+ p
[0].HighPart
;
716 p
[0].HighPart
= uliTotal
.LowPart
;
718 /* Propagate carry */
719 uliTotal
.LowPart
= uliTotal
.HighPart
;
720 uliTotal
.HighPart
= 0;
722 /* Add MS DWORDLONGs - no carry expected */
723 p
[1].QuadPart
+= ud
[1].QuadPart
+ uliTotal
.QuadPart
;
725 /* Now see if we got a sign change from the addition */
726 if ((LONG
)p
[1].HighPart
< 0) {
729 /* Negate the current value (ugh!) */
730 p
[0].QuadPart
= ~p
[0].QuadPart
;
731 p
[1].QuadPart
= ~p
[1].QuadPart
;
733 p
[1].QuadPart
+= (p
[0].QuadPart
== 0);
737 /* Now for the division */
743 /* This will catch c == 0 and overflow */
744 if (uc
<= p
[1].QuadPart
) {
745 return bSign
? (LONGLONG
)0x8000000000000000 :
746 (LONGLONG
)0x7FFFFFFFFFFFFFFF;
751 /* Do the division */
752 /* If the dividend is a DWORD_LONG use the compiler */
753 if (p
[1].QuadPart
== 0) {
754 ullResult
= p
[0].QuadPart
/ uc
;
755 return bSign
? -(LONGLONG
)ullResult
: (LONGLONG
)ullResult
;
758 /* If the divisor is a DWORD then its simpler */
761 if (ulic
.HighPart
== 0) {
762 ULARGE_INTEGER uliDividend
;
763 ULARGE_INTEGER uliResult
;
764 DWORD dwDivisor
= (DWORD
)uc
;
765 // ASSERT(p[1].HighPart == 0 && p[1].LowPart < dwDivisor);
766 uliDividend
.HighPart
= p
[1].LowPart
;
767 uliDividend
.LowPart
= p
[0].HighPart
;
769 uliResult
.HighPart
= (DWORD
)(uliDividend
.QuadPart
/ dwDivisor
);
770 p
[0].HighPart
= (DWORD
)(uliDividend
.QuadPart
% dwDivisor
);
771 uliResult
.LowPart
= 0;
772 uliResult
.QuadPart
= p
[0].QuadPart
/ dwDivisor
+ uliResult
.QuadPart
;
774 /* NOTE - this routine will take exceptions if
775 the result does not fit in a DWORD
777 if (uliDividend
.QuadPart
>= (DWORDLONG
)dwDivisor
) {
778 uliResult
.HighPart
= EnlargedUnsignedDivide(
783 uliResult
.HighPart
= 0;
785 uliResult
.LowPart
= EnlargedUnsignedDivide(
790 return bSign
? -(LONGLONG
)uliResult
.QuadPart
:
791 (LONGLONG
)uliResult
.QuadPart
;
797 /* OK - do long division */
798 for (int i
= 0; i
< 64; i
++) {
801 /* Shift 128 bit p left 1 */
803 if ((p
[0].HighPart
& 0x80000000) != 0) {
809 if (uc
<= p
[1].QuadPart
) {
815 return bSign
? - (LONGLONG
)ullResult
: (LONGLONG
)ullResult
;
818 LONGLONG WINAPI
Int64x32Div32(LONGLONG a
, LONG b
, LONG c
, LONG d
)
824 /* Compute the absolute values to avoid signed arithmetic problems */
825 ua
.QuadPart
= (DWORDLONG
)(a
>= 0 ? a
: -a
);
826 ub
= (DWORD
)(b
>= 0 ? b
: -b
);
827 uc
= (DWORD
)(c
>= 0 ? c
: -c
);
828 BOOL bSign
= (a
< 0) ^ (b
< 0);
830 /* Do long multiplication */
833 p0
.QuadPart
= UInt32x32To64(ua
.LowPart
, ub
);
835 if (ua
.HighPart
!= 0) {
837 x
.QuadPart
= UInt32x32To64(ua
.HighPart
, ub
) + p0
.HighPart
;
838 p0
.HighPart
= x
.LowPart
;
850 // Cast d to LONGLONG first otherwise -0x80000000 sign extends
853 ud0
.QuadPart
= (DWORDLONG
)(-(LONGLONG
)d
);
861 ud0
.QuadPart
= (DWORDLONG
)d
;
868 /* Now do extended addition */
869 ULARGE_INTEGER uliTotal
;
872 uliTotal
.QuadPart
= (DWORDLONG
)ud0
.LowPart
+ p0
.LowPart
;
873 p0
.LowPart
= uliTotal
.LowPart
;
875 /* Propagate carry */
876 uliTotal
.LowPart
= uliTotal
.HighPart
;
877 uliTotal
.HighPart
= 0;
879 /* Add 2nd most ls DWORDs */
880 uliTotal
.QuadPart
+= (DWORDLONG
)ud0
.HighPart
+ p0
.HighPart
;
881 p0
.HighPart
= uliTotal
.LowPart
;
883 /* Add MS DWORDLONGs - no carry expected */
884 p1
+= ud1
+ uliTotal
.HighPart
;
886 /* Now see if we got a sign change from the addition */
890 /* Negate the current value (ugh!) */
891 p0
.QuadPart
= ~p0
.QuadPart
;
894 p1
+= (p0
.QuadPart
== 0);
898 /* Now for the division */
904 /* This will catch c == 0 and overflow */
906 return bSign
? (LONGLONG
)0x8000000000000000 :
907 (LONGLONG
)0x7FFFFFFFFFFFFFFF;
910 /* Do the division */
912 /* If the divisor is a DWORD then its simpler */
913 ULARGE_INTEGER uliDividend
;
914 ULARGE_INTEGER uliResult
;
915 DWORD dwDivisor
= uc
;
916 uliDividend
.HighPart
= p1
;
917 uliDividend
.LowPart
= p0
.HighPart
;
918 /* NOTE - this routine will take exceptions if
919 the result does not fit in a DWORD
921 if (uliDividend
.QuadPart
>= (DWORDLONG
)dwDivisor
) {
922 uliResult
.HighPart
= EnlargedUnsignedDivide(
927 uliResult
.HighPart
= 0;
929 uliResult
.LowPart
= EnlargedUnsignedDivide(
933 return bSign
? -(LONGLONG
)uliResult
.QuadPart
:
934 (LONGLONG
)uliResult
.QuadPart
;
938 /******************************Public*Routine******************************\
939 * Debug CCritSec helpers
941 * We provide debug versions of the Constructor, destructor, Lock and Unlock
942 * routines. The debug code tracks who owns each critical section by
943 * maintaining a depth count.
947 \**************************************************************************/
951 InitializeCriticalSection(&m_CritSec
);
952 m_currentOwner
= m_lockCount
= 0;
956 CCritSec::~CCritSec()
958 DeleteCriticalSection(&m_CritSec
);
961 void CCritSec::Lock()
964 DWORD us
= GetCurrentThreadId();
965 DWORD currentOwner
= m_currentOwner
;
966 if (currentOwner
&& (currentOwner
!= us
)) {
967 // already owned, but not by us
969 DbgLog((LOG_LOCKING
, 2, TEXT("Thread %d about to wait for lock %x owned by %d"),
970 GetCurrentThreadId(), &m_CritSec
, currentOwner
));
972 // if we saw the message about waiting for the critical
973 // section we ensure we see the message when we get the
977 EnterCriticalSection(&m_CritSec
);
978 if (0 == m_lockCount
++) {
979 // we now own it for the first time. Set owner information
983 DbgLog((LOG_LOCKING
, tracelevel
, TEXT("Thread %d now owns lock %x"), m_currentOwner
, &m_CritSec
));
988 void CCritSec::Unlock() {
989 if (0 == --m_lockCount
) {
990 // about to be unowned
992 DbgLog((LOG_LOCKING
, 3, TEXT("Thread %d releasing lock %x"), m_currentOwner
, &m_CritSec
));
997 LeaveCriticalSection(&m_CritSec
);
1000 void WINAPI
DbgLockTrace(CCritSec
* pcCrit
, BOOL fTrace
)
1002 pcCrit
->m_fTrace
= fTrace
;
1005 BOOL WINAPI
CritCheckIn(CCritSec
* pcCrit
)
1007 return (GetCurrentThreadId() == pcCrit
->m_currentOwner
);
1010 BOOL WINAPI
CritCheckIn(const CCritSec
* pcCrit
)
1012 return (GetCurrentThreadId() == pcCrit
->m_currentOwner
);
1015 BOOL WINAPI
CritCheckOut(CCritSec
* pcCrit
)
1017 return (GetCurrentThreadId() != pcCrit
->m_currentOwner
);
1020 BOOL WINAPI
CritCheckOut(const CCritSec
* pcCrit
)
1022 return (GetCurrentThreadId() != pcCrit
->m_currentOwner
);
1027 STDAPI
WriteBSTR(BSTR
*pstrDest
, LPCWSTR szSrc
)
1029 *pstrDest
= SysAllocString( szSrc
);
1030 if( !(*pstrDest
) ) return E_OUTOFMEMORY
;
1035 STDAPI
FreeBSTR(BSTR
* pstr
)
1037 if( *pstr
== NULL
) return S_FALSE
;
1038 SysFreeString( *pstr
);
1043 // Return a wide string - allocating memory for it
1046 // E_POINTER - ppszReturn == NULL
1047 // E_OUTOFMEMORY - can't allocate memory for returned string
1048 STDAPI
AMGetWideString(LPCWSTR psz
, LPWSTR
*ppszReturn
)
1050 CheckPointer(ppszReturn
, E_POINTER
);
1051 ValidateReadWritePtr(ppszReturn
, sizeof(LPWSTR
));
1052 DWORD nameLen
= sizeof(WCHAR
) * (lstrlenW(psz
)+1);
1053 *ppszReturn
= (LPWSTR
)CoTaskMemAlloc(nameLen
);
1054 if (*ppszReturn
== NULL
) {
1055 return E_OUTOFMEMORY
;
1057 CopyMemory(*ppszReturn
, psz
, nameLen
);
1061 // Waits for the HANDLE hObject. While waiting messages sent
1062 // to windows on our thread by SendMessage will be processed.
1063 // Using this function to do waits and mutual exclusion
1064 // avoids some deadlocks in objects with windows.
1065 // Return codes are the same as for WaitForSingleObject
1066 DWORD WINAPI
WaitDispatchingMessages(
1073 BOOL bPeeked
= FALSE
;
1076 DWORD dwThreadPriority
;
1078 static UINT uMsgId
= 0;
1080 HANDLE hObjects
[2] = { hObject
, hEvent
};
1081 if (dwWait
!= INFINITE
&& dwWait
!= 0) {
1082 dwStart
= GetTickCount();
1085 DWORD nCount
= NULL
!= hEvent
? 2 : 1;
1087 // Minimize the chance of actually dispatching any messages
1088 // by seeing if we can lock immediately.
1089 dwResult
= WaitForMultipleObjects(nCount
, hObjects
, FALSE
, 0);
1090 if (dwResult
< WAIT_OBJECT_0
+ nCount
) {
1094 DWORD dwTimeOut
= dwWait
;
1095 if (dwTimeOut
> 10) {
1098 dwResult
= MsgWaitForMultipleObjects(
1103 hwnd
== NULL
? QS_SENDMESSAGE
:
1104 QS_SENDMESSAGE
+ QS_POSTMESSAGE
);
1105 if (dwResult
== WAIT_OBJECT_0
+ nCount
||
1106 dwResult
== WAIT_TIMEOUT
&& dwTimeOut
!= dwWait
) {
1109 while (PeekMessage(&msg
, hwnd
, uMsg
, uMsg
, PM_REMOVE
)) {
1110 DispatchMessage(&msg
);
1113 // Do this anyway - the previous peek doesn't flush out the
1115 PeekMessage(&msg
, NULL
, 0, 0, PM_NOREMOVE
);
1117 if (dwWait
!= INFINITE
&& dwWait
!= 0) {
1118 DWORD dwNow
= GetTickCount();
1120 // Working with differences handles wrap-around
1121 DWORD dwDiff
= dwNow
- dwStart
;
1122 if (dwDiff
> dwWait
) {
1130 // Raise our priority to prevent our message queue
1132 dwThreadPriority
= GetThreadPriority(GetCurrentThread());
1133 if (dwThreadPriority
< THREAD_PRIORITY_HIGHEST
) {
1134 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST
);
1143 SetThreadPriority(GetCurrentThread(), dwThreadPriority
);
1144 if (HIWORD(GetQueueStatus(QS_POSTMESSAGE
)) & QS_POSTMESSAGE
) {
1146 uMsgId
= RegisterWindowMessage(TEXT("AMUnblock"));
1151 while (PeekMessage(&msg
, (HWND
)-1, uMsgId
, uMsgId
, PM_REMOVE
)) {
1154 PostThreadMessage(GetCurrentThreadId(), uMsgId
, 0, 0);
1160 HRESULT
AmGetLastErrorToHResult()
1162 DWORD dwLastError
= GetLastError();
1163 if(dwLastError
!= 0)
1165 return HRESULT_FROM_WIN32(dwLastError
);
1173 IUnknown
* QzAtlComPtrAssign(IUnknown
** pp
, IUnknown
* lp
)
1183 /******************************************************************************
1185 CompatibleTimeSetEvent
1187 CompatibleTimeSetEvent() sets the TIME_KILL_SYNCHRONOUS flag before calling
1188 timeSetEvent() if the current operating system supports it. TIME_KILL_SYNCHRONOUS
1189 is supported on Windows XP and later operating systems.
1192 - The same parameters as timeSetEvent(). See timeSetEvent()'s documentation in
1193 the Platform SDK for more information.
1196 - The same return value as timeSetEvent(). See timeSetEvent()'s documentation in
1197 the Platform SDK for more information.
1199 ******************************************************************************/
1200 MMRESULT
CompatibleTimeSetEvent( UINT uDelay
, UINT uResolution
, LPTIMECALLBACK lpTimeProc
, DWORD_PTR dwUser
, UINT fuEvent
)
1202 #if WINVER >= 0x0501
1204 static bool fCheckedVersion
= false;
1205 static bool fTimeKillSynchronousFlagAvailable
= false;
1207 if( !fCheckedVersion
) {
1208 fTimeKillSynchronousFlagAvailable
= TimeKillSynchronousFlagAvailable();
1209 fCheckedVersion
= true;
1212 if( fTimeKillSynchronousFlagAvailable
) {
1213 fuEvent
= fuEvent
| TIME_KILL_SYNCHRONOUS
;
1216 #endif // WINVER >= 0x0501
1218 return timeSetEvent( uDelay
, uResolution
, lpTimeProc
, dwUser
, fuEvent
);
1221 bool TimeKillSynchronousFlagAvailable( void )
1223 OSVERSIONINFO osverinfo
;
1225 osverinfo
.dwOSVersionInfoSize
= sizeof(osverinfo
);
1227 if( GetVersionEx( &osverinfo
) ) {
1229 // Windows XP's major version is 5 and its' minor version is 1.
1230 // timeSetEvent() started supporting the TIME_KILL_SYNCHRONOUS flag
1232 if( (osverinfo
.dwMajorVersion
> 5) ||
1233 ( (osverinfo
.dwMajorVersion
== 5) && (osverinfo
.dwMinorVersion
>= 1) ) ) {