test2
[test_vsfilter.git] / src / filters / BaseClasses / wxutil.cpp
blob4e1181ec6020c7ce951edf06fba4794c6e88d6fd
1 //------------------------------------------------------------------------------
2 // File: WXUtil.cpp
3 //
4 // Desc: DirectShow base classes - implements helper classes for building
5 // multimedia filters.
6 //
7 // Copyright (c) 1992-2002 Microsoft Corporation. All rights reserved.
8 //------------------------------------------------------------------------------
11 #include <streams.h>
14 // Declare function from largeint.h we need so that PPC can build
18 // Enlarged integer divide - 64-bits / 32-bits > 32-bits
21 #ifndef _X86_
23 #define LLtoU64(x) (*(unsigned __int64*)(void*)(&(x)))
25 __inline
26 ULONG
27 WINAPI
28 EnlargedUnsignedDivide (
29 IN ULARGE_INTEGER Dividend,
30 IN ULONG Divisor,
31 IN PULONG Remainder
34 // return remainder if necessary
35 if (Remainder != NULL)
36 *Remainder = (ULONG)(LLtoU64(Dividend) % Divisor);
37 return (ULONG)(LLtoU64(Dividend) / Divisor);
40 #else
41 __inline
42 ULONG
43 WINAPI
44 EnlargedUnsignedDivide (
45 IN ULARGE_INTEGER Dividend,
46 IN ULONG Divisor,
47 IN PULONG Remainder
50 ULONG ulResult;
51 _asm {
52 mov eax,Dividend.LowPart
53 mov edx,Dividend.HighPart
54 mov ecx,Remainder
55 div Divisor
56 or ecx,ecx
57 jz short label
58 mov [ecx],edx
59 label:
60 mov ulResult,eax
62 return ulResult;
64 #endif
66 // --- CAMEvent -----------------------
67 CAMEvent::CAMEvent(BOOL fManualReset)
69 m_hEvent = CreateEvent(NULL, fManualReset, FALSE, NULL);
72 CAMEvent::~CAMEvent()
74 if (m_hEvent) {
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
88 DWORD dwWait;
89 DWORD dwStartTime;
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();
101 do {
102 dwWait = MsgWaitForMultipleObjects(1,&m_hEvent,FALSE, dwWaitTime, QS_SENDMESSAGE);
103 if (dwWait == WAIT_OBJECT_0 + 1) {
104 MSG Message;
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;
114 dwWaitTime =
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()
133 m_hThread = NULL;
136 CAMThread::~CAMThread() {
137 Close();
141 // when the thread starts, it calls this function. We unwrap the 'this'
142 //pointer and call ThreadProc.
143 DWORD WINAPI
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)) {
156 CoUninitialize();
159 return hr;
162 BOOL
163 CAMThread::Create()
165 DWORD threadid;
167 CAutoLock lock(&m_AccessLock);
169 if (ThreadExists()) {
170 return FALSE;
173 m_hThread = CreateThread(
174 NULL,
176 CAMThread::InitialThreadProc,
177 this,
179 &threadid);
181 if (!m_hThread) {
182 return FALSE;
185 return TRUE;
188 DWORD
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;
198 // set the parameter
199 m_dwParam = dwParam;
201 // signal the worker thread
202 m_EventSend.Set();
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
212 DWORD
213 CAMThread::GetRequest()
215 m_EventSend.Wait();
216 return m_dwParam;
219 // is there a request?
220 BOOL
221 CAMThread::CheckRequest(DWORD * pParam)
223 if (!m_EventSend.Check()) {
224 return FALSE;
225 } else {
226 if (pParam) {
227 *pParam = m_dwParam;
229 return TRUE;
233 // reply to the request
234 void
235 CAMThread::Reply(DWORD dw)
237 m_dwReturnVal = dw;
239 // The request is now complete so CheckRequest should fail from
240 // now on
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
244 // reset it (!)
246 m_EventSend.Reset();
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
262 // hanging?
265 // older versions of ole32.dll don't have CoInitializeEx
267 HRESULT hr = E_FAIL;
268 HINSTANCE hOle = GetModuleHandle(TEXT("ole32.dll"));
269 if(hOle)
271 typedef HRESULT (STDAPICALLTYPE *PCoInitializeEx)(
272 LPVOID pvReserved, DWORD dwCoInit);
273 PCoInitializeEx pCoInitializeEx =
274 (PCoInitializeEx)(GetProcAddress(hOle, "CoInitializeEx"));
275 if(pCoInitializeEx)
277 hr = (*pCoInitializeEx)(0, COINIT_DISABLE_OLE1DDE );
280 else
282 // caller must load ole32.dll
283 DbgBreak("couldn't locate ole32.dll");
286 return hr;
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();
300 while (pos) {
301 CMsg * pMsg = m_ThreadQueue.GetNext(pos);
302 delete pMsg;
304 m_ThreadQueue.RemoveAll();
306 if (m_hSem != NULL) {
307 EXECUTE_ASSERT(CloseHandle(m_hSem));
311 BOOL
312 CMsgThread::CreateThread(
315 m_hSem = CreateSemaphore(NULL, 0, 0x7FFFFFFF, NULL);
316 if (m_hSem == NULL) {
317 return FALSE;
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.
331 DWORD WINAPI
332 CMsgThread::DefaultThreadProc(
333 LPVOID lpParam
336 CMsgThread *lpThis = (CMsgThread *)lpParam;
337 CMsg msg;
338 LRESULT lResult;
340 // !!!
341 CoInitialize(NULL);
343 // allow a derived class to handle thread startup
344 lpThis->OnThreadInit();
346 do {
347 lpThis->GetThreadMsg(&msg);
348 lResult = lpThis->ThreadMessageProc(msg.uMsg,msg.dwFlags,
349 msg.lpParam, msg.pEvent);
350 } while (lResult == 0L);
352 // !!!
353 CoUninitialize();
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
361 void
362 CMsgThread::GetThreadMsg(CMsg *msg)
364 CMsg * pmsg = NULL;
366 // keep trying until a message appears
367 while (TRUE) {
369 CAutoLock lck(&m_Lock);
370 pmsg = m_ThreadQueue.RemoveHead();
371 if (pmsg == NULL) {
372 m_lWaiting++;
373 } else {
374 break;
377 // the semaphore will be signalled when it is non-empty
378 WaitForSingleObject(m_hSem, INFINITE);
380 // copy fields to caller's CMsg
381 *msg = *pmsg;
383 // this CMsg was allocated by the 'new' in PutThreadMsg
384 delete pmsg;
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.
393 #ifndef UNICODE
394 // Windows 95 doesn't implement this, so we provide an implementation.
395 LPWSTR
396 WINAPI
397 lstrcpyWInternal(
398 LPWSTR lpString1,
399 LPCWSTR lpString2
402 LPWSTR lpReturn = lpString1;
403 while (*lpString1++ = *lpString2++);
405 return lpReturn;
408 // Windows 95 doesn't implement this, so we provide an implementation.
409 LPWSTR
410 WINAPI
411 lstrcpynWInternal(
412 LPWSTR lpString1,
413 LPCWSTR lpString2,
414 int iMaxLength
417 ASSERT(iMaxLength);
418 LPWSTR lpReturn = lpString1;
419 if (iMaxLength) {
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
424 // string.
425 if (!iMaxLength) *lpString1 = L'\0';
427 return lpReturn;
431 WINAPI
432 lstrcmpWInternal(
433 LPCWSTR lpString1,
434 LPCWSTR lpString2
437 do {
438 WCHAR c1 = *lpString1;
439 WCHAR c2 = *lpString2;
440 if (c1 != c2)
441 return (int) c1 - (int) c2;
442 } while (*lpString1++ && *lpString2++);
443 return 0;
448 WINAPI
449 lstrcmpiWInternal(
450 LPCWSTR lpString1,
451 LPCWSTR lpString2
454 do {
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');
462 if (c1 != c2)
463 return (int) c1 - (int) c2;
464 } while (*lpString1++ && *lpString2++);
466 return 0;
471 WINAPI
472 lstrlenWInternal(
473 LPCWSTR lpString
476 int i = -1;
477 while (*(lpString+(++i)))
479 return i;
483 int WINAPIV wsprintfWInternal(LPWSTR wszOut, LPCWSTR pszFmt, ...)
485 char fmt[256]; // !!!
486 char ach[256]; // !!!
487 int i;
489 va_list va;
490 va_start(va, pszFmt);
491 WideCharToMultiByte(GetACP(), 0, pszFmt, -1, fmt, 256, NULL, NULL);
492 i = wvsprintfA(ach, fmt, va);
493 va_end(va);
495 MultiByteToWideChar(CP_ACP, 0, ach, -1, wszOut, i+1);
497 return i;
499 #else
501 // need to provide the implementations in unicode for non-unicode
502 // builds linking with the unicode strmbase.lib
503 LPWSTR WINAPI lstrcpyWInternal(
504 LPWSTR lpString1,
505 LPCWSTR lpString2
508 return lstrcpyW(lpString1, lpString2);
511 LPWSTR WINAPI lstrcpynWInternal(
512 LPWSTR lpString1,
513 LPCWSTR lpString2,
514 int iMaxLength
517 return lstrcpynW(lpString1, lpString2, iMaxLength);
520 int WINAPI lstrcmpWInternal(
521 LPCWSTR lpString1,
522 LPCWSTR lpString2
525 return lstrcmpW(lpString1, lpString2);
529 int WINAPI lstrcmpiWInternal(
530 LPCWSTR lpString1,
531 LPCWSTR lpString2
534 return lstrcmpiW(lpString1, lpString2);
538 int WINAPI lstrlenWInternal(
539 LPCWSTR lpString
542 return lstrlenW(lpString);
546 int WINAPIV wsprintfWInternal(
547 LPWSTR wszOut, LPCWSTR pszFmt, ...)
549 va_list va;
550 va_start(va, pszFmt);
551 int i = wvsprintfW(wszOut, pszFmt, va);
552 va_end(va);
553 return i;
555 #endif
558 // Helper function - convert int to WSTR
559 void WINAPI IntToWstr(int i, LPWSTR wstr)
561 #ifdef UNICODE
562 wsprintf(wstr, L"%d", i);
563 #else
564 TCHAR temp[32];
565 wsprintf(temp, "%d", i);
566 MultiByteToWideChar(CP_ACP, 0, temp, -1, wstr, 32);
567 #endif
568 } // IntToWstr
571 #if 0
572 void * memchrInternal(const void *pv, int c, size_t sz)
574 BYTE *pb = (BYTE *) pv;
575 while (sz--) {
576 if (*pb == c)
577 return (void *) pb;
578 pb++;
580 return NULL;
582 #endif
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)
591 void * ret = dst;
593 #ifdef _X86_
594 if (dst <= src || (char *)dst >= ((char *)src + count)) {
597 * Non-Overlapping Buffers
598 * copy from lower addresses to higher addresses
600 _asm {
601 mov esi,src
602 mov edi,dst
603 mov ecx,count
605 mov edx,ecx
606 and edx,MEMORY_ALIGNMENT_MASK
607 shr ecx,MEMORY_ALIGNMENT_LOG2
608 rep movsd
609 or ecx,edx
610 jz memmove_done
611 rep movsb
612 memmove_done:
615 else {
618 * Overlapping Buffers
619 * copy from higher addresses to lower addresses
621 _asm {
622 mov esi,src
623 mov edi,dst
624 mov ecx,count
626 add esi,ecx
627 add edi,ecx
628 dec esi
629 dec edi
630 rep movsb
634 #else
635 MoveMemory(dst, src, count);
636 #endif
638 return ret;
641 /* Arithmetic functions to help with time format conversions
644 #ifdef _M_ALPHA
645 // work around bug in version 12.00.8385 of the alpha compiler where
646 // UInt32x32To64 sign-extends its arguments (?)
647 #undef UInt32x32To64
648 #define UInt32x32To64(a, b) (((ULONGLONG)((ULONG)(a)) & 0xffffffff) * ((ULONGLONG)((ULONG)(b)) & 0xffffffff))
649 #endif
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;
656 DWORDLONG uc;
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 */
664 ULARGE_INTEGER p[2];
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
675 < 2 ** 96
678 ULARGE_INTEGER x;
679 x.QuadPart = UInt32x32To64(ua.LowPart, ub.HighPart) +
680 UInt32x32To64(ua.HighPart, ub.LowPart) +
681 p[0].HighPart;
682 p[0].HighPart = x.LowPart;
683 p[1].QuadPart = UInt32x32To64(ua.HighPart, ub.HighPart) + x.HighPart;
685 if (d != 0) {
686 ULARGE_INTEGER ud[2];
687 if (bSign) {
688 ud[0].QuadPart = (DWORDLONG)(-d);
689 if (d > 0) {
690 /* -d < 0 */
691 ud[1].QuadPart = (DWORDLONG)(LONGLONG)-1;
692 } else {
693 ud[1].QuadPart = (DWORDLONG)0;
695 } else {
696 ud[0].QuadPart = (DWORDLONG)d;
697 if (d < 0) {
698 ud[1].QuadPart = (DWORDLONG)(LONGLONG)-1;
699 } else {
700 ud[1].QuadPart = (DWORDLONG)0;
703 /* Now do extended addition */
704 ULARGE_INTEGER uliTotal;
706 /* Add ls DWORDs */
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) {
727 bSign = !bSign;
729 /* Negate the current value (ugh!) */
730 p[0].QuadPart = ~p[0].QuadPart;
731 p[1].QuadPart = ~p[1].QuadPart;
732 p[0].QuadPart += 1;
733 p[1].QuadPart += (p[0].QuadPart == 0);
737 /* Now for the division */
738 if (c < 0) {
739 bSign = !bSign;
743 /* This will catch c == 0 and overflow */
744 if (uc <= p[1].QuadPart) {
745 return bSign ? (LONGLONG)0x8000000000000000 :
746 (LONGLONG)0x7FFFFFFFFFFFFFFF;
749 DWORDLONG ullResult;
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 */
759 ULARGE_INTEGER ulic;
760 ulic.QuadPart = uc;
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;
768 #ifndef USE_LARGEINT
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;
773 #else
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(
779 uliDividend,
780 dwDivisor,
781 &p[0].HighPart);
782 } else {
783 uliResult.HighPart = 0;
785 uliResult.LowPart = EnlargedUnsignedDivide(
786 p[0],
787 dwDivisor,
788 NULL);
789 #endif
790 return bSign ? -(LONGLONG)uliResult.QuadPart :
791 (LONGLONG)uliResult.QuadPart;
795 ullResult = 0;
797 /* OK - do long division */
798 for (int i = 0; i < 64; i++) {
799 ullResult <<= 1;
801 /* Shift 128 bit p left 1 */
802 p[1].QuadPart <<= 1;
803 if ((p[0].HighPart & 0x80000000) != 0) {
804 p[1].LowPart++;
806 p[0].QuadPart <<= 1;
808 /* Compare */
809 if (uc <= p[1].QuadPart) {
810 p[1].QuadPart -= uc;
811 ullResult += 1;
815 return bSign ? - (LONGLONG)ullResult : (LONGLONG)ullResult;
818 LONGLONG WINAPI Int64x32Div32(LONGLONG a, LONG b, LONG c, LONG d)
820 ULARGE_INTEGER ua;
821 DWORD ub;
822 DWORD uc;
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 */
831 ULARGE_INTEGER p0;
832 DWORD p1;
833 p0.QuadPart = UInt32x32To64(ua.LowPart, ub);
835 if (ua.HighPart != 0) {
836 ULARGE_INTEGER x;
837 x.QuadPart = UInt32x32To64(ua.HighPart, ub) + p0.HighPart;
838 p0.HighPart = x.LowPart;
839 p1 = x.HighPart;
840 } else {
841 p1 = 0;
844 if (d != 0) {
845 ULARGE_INTEGER ud0;
846 DWORD ud1;
848 if (bSign) {
850 // Cast d to LONGLONG first otherwise -0x80000000 sign extends
851 // incorrectly
853 ud0.QuadPart = (DWORDLONG)(-(LONGLONG)d);
854 if (d > 0) {
855 /* -d < 0 */
856 ud1 = (DWORD)-1;
857 } else {
858 ud1 = (DWORD)0;
860 } else {
861 ud0.QuadPart = (DWORDLONG)d;
862 if (d < 0) {
863 ud1 = (DWORD)-1;
864 } else {
865 ud1 = (DWORD)0;
868 /* Now do extended addition */
869 ULARGE_INTEGER uliTotal;
871 /* Add ls DWORDs */
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 */
887 if ((LONG)p1 < 0) {
888 bSign = !bSign;
890 /* Negate the current value (ugh!) */
891 p0.QuadPart = ~p0.QuadPart;
892 p1 = ~p1;
893 p0.QuadPart += 1;
894 p1 += (p0.QuadPart == 0);
898 /* Now for the division */
899 if (c < 0) {
900 bSign = !bSign;
904 /* This will catch c == 0 and overflow */
905 if (uc <= p1) {
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(
923 uliDividend,
924 dwDivisor,
925 &p0.HighPart);
926 } else {
927 uliResult.HighPart = 0;
929 uliResult.LowPart = EnlargedUnsignedDivide(
931 dwDivisor,
932 NULL);
933 return bSign ? -(LONGLONG)uliResult.QuadPart :
934 (LONGLONG)uliResult.QuadPart;
937 #ifdef DEBUG
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.
945 * History:
947 \**************************************************************************/
949 CCritSec::CCritSec()
951 InitializeCriticalSection(&m_CritSec);
952 m_currentOwner = m_lockCount = 0;
953 m_fTrace = FALSE;
956 CCritSec::~CCritSec()
958 DeleteCriticalSection(&m_CritSec);
961 void CCritSec::Lock()
963 UINT tracelevel=3;
964 DWORD us = GetCurrentThreadId();
965 DWORD currentOwner = m_currentOwner;
966 if (currentOwner && (currentOwner != us)) {
967 // already owned, but not by us
968 if (m_fTrace) {
969 DbgLog((LOG_LOCKING, 2, TEXT("Thread %d about to wait for lock %x owned by %d"),
970 GetCurrentThreadId(), &m_CritSec, currentOwner));
971 tracelevel=2;
972 // if we saw the message about waiting for the critical
973 // section we ensure we see the message when we get the
974 // critical section
977 EnterCriticalSection(&m_CritSec);
978 if (0 == m_lockCount++) {
979 // we now own it for the first time. Set owner information
980 m_currentOwner = us;
982 if (m_fTrace) {
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
991 if (m_fTrace) {
992 DbgLog((LOG_LOCKING, 3, TEXT("Thread %d releasing lock %x"), m_currentOwner, &m_CritSec));
995 m_currentOwner = 0;
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);
1024 #endif
1027 STDAPI WriteBSTR(BSTR *pstrDest, LPCWSTR szSrc)
1029 *pstrDest = SysAllocString( szSrc );
1030 if( !(*pstrDest) ) return E_OUTOFMEMORY;
1031 return NOERROR;
1035 STDAPI FreeBSTR(BSTR* pstr)
1037 if( *pstr == NULL ) return S_FALSE;
1038 SysFreeString( *pstr );
1039 return NOERROR;
1043 // Return a wide string - allocating memory for it
1044 // Returns:
1045 // S_OK - no error
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);
1058 return NOERROR;
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(
1067 HANDLE hObject,
1068 DWORD dwWait,
1069 HWND hwnd,
1070 UINT uMsg,
1071 HANDLE hEvent)
1073 BOOL bPeeked = FALSE;
1074 DWORD dwResult;
1075 DWORD dwStart;
1076 DWORD dwThreadPriority;
1078 static UINT uMsgId = 0;
1080 HANDLE hObjects[2] = { hObject, hEvent };
1081 if (dwWait != INFINITE && dwWait != 0) {
1082 dwStart = GetTickCount();
1084 for (; ; ) {
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) {
1091 break;
1094 DWORD dwTimeOut = dwWait;
1095 if (dwTimeOut > 10) {
1096 dwTimeOut = 10;
1098 dwResult = MsgWaitForMultipleObjects(
1099 nCount,
1100 hObjects,
1101 FALSE,
1102 dwTimeOut,
1103 hwnd == NULL ? QS_SENDMESSAGE :
1104 QS_SENDMESSAGE + QS_POSTMESSAGE);
1105 if (dwResult == WAIT_OBJECT_0 + nCount ||
1106 dwResult == WAIT_TIMEOUT && dwTimeOut != dwWait) {
1107 MSG msg;
1108 if (hwnd != NULL) {
1109 while (PeekMessage(&msg, hwnd, uMsg, uMsg, PM_REMOVE)) {
1110 DispatchMessage(&msg);
1113 // Do this anyway - the previous peek doesn't flush out the
1114 // messages
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) {
1123 dwWait = 0;
1124 } else {
1125 dwWait -= dwDiff;
1127 dwStart = dwNow;
1129 if (!bPeeked) {
1130 // Raise our priority to prevent our message queue
1131 // building up
1132 dwThreadPriority = GetThreadPriority(GetCurrentThread());
1133 if (dwThreadPriority < THREAD_PRIORITY_HIGHEST) {
1134 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
1136 bPeeked = TRUE;
1138 } else {
1139 break;
1142 if (bPeeked) {
1143 SetThreadPriority(GetCurrentThread(), dwThreadPriority);
1144 if (HIWORD(GetQueueStatus(QS_POSTMESSAGE)) & QS_POSTMESSAGE) {
1145 if (uMsgId == 0) {
1146 uMsgId = RegisterWindowMessage(TEXT("AMUnblock"));
1148 if (uMsgId != 0) {
1149 MSG msg;
1150 // Remove old ones
1151 while (PeekMessage(&msg, (HWND)-1, uMsgId, uMsgId, PM_REMOVE)) {
1154 PostThreadMessage(GetCurrentThreadId(), uMsgId, 0, 0);
1157 return dwResult;
1160 HRESULT AmGetLastErrorToHResult()
1162 DWORD dwLastError = GetLastError();
1163 if(dwLastError != 0)
1165 return HRESULT_FROM_WIN32(dwLastError);
1167 else
1169 return E_FAIL;
1173 IUnknown* QzAtlComPtrAssign(IUnknown** pp, IUnknown* lp)
1175 if (lp != NULL)
1176 lp->AddRef();
1177 if (*pp)
1178 (*pp)->Release();
1179 *pp = lp;
1180 return 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.
1191 Parameters:
1192 - The same parameters as timeSetEvent(). See timeSetEvent()'s documentation in
1193 the Platform SDK for more information.
1195 Return Value:
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
1231 // in Windows XP.
1232 if( (osverinfo.dwMajorVersion > 5) ||
1233 ( (osverinfo.dwMajorVersion == 5) && (osverinfo.dwMinorVersion >= 1) ) ) {
1234 return true;
1238 return false;