home *** CD-ROM | disk | FTP | other *** search
/ Visual Basic Game Programming for Teens / VBGPFT.cdr / DirectX8 / dx8a_sdk.exe / samples / multimedia / directshow / baseclasses / wxutil.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-10-02  |  29.8 KB  |  1,184 lines

  1. //------------------------------------------------------------------------------
  2. // File: WXUtil.cpp
  3. //
  4. // Desc: DirectShow base classes - implements helper classes for building
  5. //       multimedia filters.
  6. //
  7. // Copyright (c) 1992 - 2000, Microsoft Corporation.  All rights reserved.
  8. //------------------------------------------------------------------------------
  9.  
  10.  
  11. #include <streams.h>
  12.  
  13. //
  14. //  Declare function from largeint.h we need so that PPC can build
  15. //
  16.  
  17. //
  18. // Enlarged integer divide - 64-bits / 32-bits > 32-bits
  19. //
  20.  
  21. #ifndef _X86_
  22.  
  23. #define LLtoU64(x) (*(unsigned __int64*)(void*)(&(x)))
  24.  
  25. __inline
  26. ULONG
  27. WINAPI
  28. EnlargedUnsignedDivide (
  29.     IN ULARGE_INTEGER Dividend,
  30.     IN ULONG Divisor,
  31.     IN PULONG Remainder
  32.     )
  33. {
  34.         // return remainder if necessary
  35.         if (Remainder != NULL)
  36.                 *Remainder = (ULONG)(LLtoU64(Dividend) % Divisor);
  37.         return (ULONG)(LLtoU64(Dividend) / Divisor);
  38. }
  39.  
  40. #else
  41. __inline
  42. ULONG
  43. WINAPI
  44. EnlargedUnsignedDivide (
  45.     IN ULARGE_INTEGER Dividend,
  46.     IN ULONG Divisor,
  47.     IN PULONG Remainder
  48.     )
  49. {
  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
  61.     }
  62.     return ulResult;
  63. }
  64. #endif
  65.  
  66. // --- CAMEvent -----------------------
  67. CAMEvent::CAMEvent(BOOL fManualReset)
  68. {
  69.     m_hEvent = CreateEvent(NULL, fManualReset, FALSE, NULL);
  70.     ASSERT(m_hEvent);
  71. }
  72.  
  73. CAMEvent::~CAMEvent()
  74. {
  75.     if (m_hEvent) {
  76.     EXECUTE_ASSERT(CloseHandle(m_hEvent));
  77.     }
  78. }
  79.  
  80.  
  81. // --- CAMMsgEvent -----------------------
  82. // One routine.  The rest is handled in CAMEvent
  83.  
  84. BOOL CAMMsgEvent::WaitMsg(DWORD dwTimeout)
  85. {
  86.     // wait for the event to be signalled, or for the
  87.     // timeout (in MS) to expire.  allow SENT messages
  88.     // to be processed while we wait
  89.     DWORD dwWait;
  90.     DWORD dwStartTime;
  91.  
  92.     // set the waiting period.
  93.     DWORD dwWaitTime = dwTimeout;
  94.  
  95.     // the timeout will eventually run down as we iterate
  96.     // processing messages.  grab the start time so that
  97.     // we can calculate elapsed times.
  98.     if (dwWaitTime != INFINITE) {
  99.         dwStartTime = timeGetTime();
  100.     }
  101.  
  102.     do {
  103.         dwWait = MsgWaitForMultipleObjects(1,&m_hEvent,FALSE, dwWaitTime, QS_SENDMESSAGE);
  104.         if (dwWait == WAIT_OBJECT_0 + 1) {
  105.         MSG Message;
  106.             PeekMessage(&Message,NULL,0,0,PM_NOREMOVE);
  107.  
  108.         // If we have an explicit length of time to wait calculate
  109.         // the next wake up point - which might be now.
  110.         // If dwTimeout is INFINITE, it stays INFINITE
  111.         if (dwWaitTime != INFINITE) {
  112.  
  113.         DWORD dwElapsed = timeGetTime()-dwStartTime;
  114.  
  115.         dwWaitTime =
  116.             (dwElapsed >= dwTimeout)
  117.             ? 0  // wake up with WAIT_TIMEOUT
  118.             : dwTimeout-dwElapsed;
  119.         }
  120.         }
  121.     } while (dwWait == WAIT_OBJECT_0 + 1);
  122.  
  123.     // return TRUE if we woke on the event handle,
  124.     //        FALSE if we timed out.
  125.     return (dwWait == WAIT_OBJECT_0);
  126. }
  127.  
  128. // --- CAMThread ----------------------
  129.  
  130.  
  131. CAMThread::CAMThread()
  132.     : m_EventSend(TRUE)     // must be manual-reset for CheckRequest()
  133. {
  134.     m_hThread = NULL;
  135. }
  136.  
  137. CAMThread::~CAMThread() {
  138.     Close();
  139. }
  140.  
  141.  
  142. // when the thread starts, it calls this function. We unwrap the 'this'
  143. //pointer and call ThreadProc.
  144. DWORD WINAPI
  145. CAMThread::InitialThreadProc(LPVOID pv)
  146. {
  147.     HRESULT hrCoInit = CAMThread::CoInitializeHelper();
  148.     if(FAILED(hrCoInit)) {
  149.         DbgLog((LOG_ERROR, 1, TEXT("CoInitializeEx failed.")));
  150.     }
  151.  
  152.     CAMThread * pThread = (CAMThread *) pv;
  153.  
  154.     HRESULT hr = pThread->ThreadProc();
  155.  
  156.     if(SUCCEEDED(hrCoInit)) {
  157.         CoUninitialize();
  158.     }
  159.  
  160.     return hr;
  161. }
  162.  
  163. BOOL
  164. CAMThread::Create()
  165. {
  166.     DWORD threadid;
  167.  
  168.     CAutoLock lock(&m_AccessLock);
  169.  
  170.     if (ThreadExists()) {
  171.     return FALSE;
  172.     }
  173.  
  174.     m_hThread = CreateThread(
  175.             NULL,
  176.             0,
  177.             CAMThread::InitialThreadProc,
  178.             this,
  179.             0,
  180.             &threadid);
  181.  
  182.     if (!m_hThread) {
  183.     return FALSE;
  184.     }
  185.  
  186.     return TRUE;
  187. }
  188.  
  189. DWORD
  190. CAMThread::CallWorker(DWORD dwParam)
  191. {
  192.     // lock access to the worker thread for scope of this object
  193.     CAutoLock lock(&m_AccessLock);
  194.  
  195.     if (!ThreadExists()) {
  196.     return (DWORD) E_FAIL;
  197.     }
  198.  
  199.     // set the parameter
  200.     m_dwParam = dwParam;
  201.  
  202.     // signal the worker thread
  203.     m_EventSend.Set();
  204.  
  205.     // wait for the completion to be signalled
  206.     m_EventComplete.Wait();
  207.  
  208.     // done - this is the thread's return value
  209.     return m_dwReturnVal;
  210. }
  211.  
  212. // Wait for a request from the client
  213. DWORD
  214. CAMThread::GetRequest()
  215. {
  216.     m_EventSend.Wait();
  217.     return m_dwParam;
  218. }
  219.  
  220. // is there a request?
  221. BOOL
  222. CAMThread::CheckRequest(DWORD * pParam)
  223. {
  224.     if (!m_EventSend.Check()) {
  225.     return FALSE;
  226.     } else {
  227.     if (pParam) {
  228.         *pParam = m_dwParam;
  229.     }
  230.     return TRUE;
  231.     }
  232. }
  233.  
  234. // reply to the request
  235. void
  236. CAMThread::Reply(DWORD dw)
  237. {
  238.     m_dwReturnVal = dw;
  239.  
  240.     // The request is now complete so CheckRequest should fail from
  241.     // now on
  242.     //
  243.     // This event should be reset BEFORE we signal the client or
  244.     // the client may Set it before we reset it and we'll then
  245.     // reset it (!)
  246.  
  247.     m_EventSend.Reset();
  248.  
  249.     // Tell the client we're finished
  250.  
  251.     m_EventComplete.Set();
  252. }
  253.  
  254. HRESULT CAMThread::CoInitializeHelper()
  255. {
  256.     // call CoInitializeEx and tell OLE not to create a window (this
  257.     // thread probably won't dispatch messages and will hang on
  258.     // broadcast msgs o/w).
  259.     //
  260.     // If CoInitEx is not available, threads that don't call CoCreate
  261.     // aren't affected. Threads that do will have to handle the
  262.     // failure. Perhaps we should fall back to CoInitialize and risk
  263.     // hanging?
  264.     //
  265.  
  266.     // older versions of ole32.dll don't have CoInitializeEx
  267.  
  268.     HRESULT hr = E_FAIL;
  269.     HINSTANCE hOle = GetModuleHandle(TEXT("ole32.dll"));
  270.     if(hOle)
  271.     {
  272.         typedef HRESULT (STDAPICALLTYPE *PCoInitializeEx)(
  273.             LPVOID pvReserved, DWORD dwCoInit);
  274.         PCoInitializeEx pCoInitializeEx =
  275.             (PCoInitializeEx)(GetProcAddress(hOle, "CoInitializeEx"));
  276.         if(pCoInitializeEx)
  277.         {
  278.             hr = (*pCoInitializeEx)(0, COINIT_DISABLE_OLE1DDE );
  279.         }
  280.     }
  281.     else
  282.     {
  283.         // caller must load ole32.dll
  284.         DbgBreak("couldn't locate ole32.dll");
  285.     }
  286.  
  287.     return hr;
  288. }
  289.  
  290.  
  291. // destructor for CMsgThread  - cleans up any messages left in the
  292. // queue when the thread exited
  293. CMsgThread::~CMsgThread()
  294. {
  295.     if (m_hThread != NULL) {
  296.         WaitForSingleObject(m_hThread, INFINITE);
  297.         EXECUTE_ASSERT(CloseHandle(m_hThread));
  298.     }
  299.  
  300.     POSITION pos = m_ThreadQueue.GetHeadPosition();
  301.     while (pos) {
  302.         CMsg * pMsg = m_ThreadQueue.GetNext(pos);
  303.         delete pMsg;
  304.     }
  305.     m_ThreadQueue.RemoveAll();
  306.  
  307.     if (m_hSem != NULL) {
  308.         EXECUTE_ASSERT(CloseHandle(m_hSem));
  309.     }
  310. }
  311.  
  312. BOOL
  313. CMsgThread::CreateThread(
  314.     )
  315. {
  316.     m_hSem = CreateSemaphore(NULL, 0, 0x7FFFFFFF, NULL);
  317.     if (m_hSem == NULL) {
  318.         return FALSE;
  319.     }
  320.  
  321.     m_hThread = ::CreateThread(NULL, 0, DefaultThreadProc,
  322.                    (LPVOID)this, 0, &m_ThreadId);
  323.     return m_hThread != NULL;
  324. }
  325.  
  326.  
  327. // This is the threads message pump.  Here we get and dispatch messages to
  328. // clients thread proc until the client refuses to process a message.
  329. // The client returns a non-zero value to stop the message pump, this
  330. // value becomes the threads exit code.
  331.  
  332. DWORD WINAPI
  333. CMsgThread::DefaultThreadProc(
  334.     LPVOID lpParam
  335.     )
  336. {
  337.     CMsgThread *lpThis = (CMsgThread *)lpParam;
  338.     CMsg msg;
  339.     LRESULT lResult;
  340.  
  341.     // !!!
  342.     CoInitialize(NULL);
  343.  
  344.     // allow a derived class to handle thread startup
  345.     lpThis->OnThreadInit();
  346.  
  347.     do {
  348.     lpThis->GetThreadMsg(&msg);
  349.     lResult = lpThis->ThreadMessageProc(msg.uMsg,msg.dwFlags,
  350.                         msg.lpParam, msg.pEvent);
  351.     } while (lResult == 0L);
  352.  
  353.     // !!!
  354.     CoUninitialize();
  355.  
  356.     return (DWORD)lResult;
  357. }
  358.  
  359.  
  360. // Block until the next message is placed on the list m_ThreadQueue.
  361. // copies the message to the message pointed to by *pmsg
  362. void
  363. CMsgThread::GetThreadMsg(CMsg *msg)
  364. {
  365.     CMsg * pmsg = NULL;
  366.  
  367.     // keep trying until a message appears
  368.     while (TRUE) {
  369.         {
  370.             CAutoLock lck(&m_Lock);
  371.             pmsg = m_ThreadQueue.RemoveHead();
  372.             if (pmsg == NULL) {
  373.                 m_lWaiting++;
  374.             } else {
  375.                 break;
  376.             }
  377.         }
  378.         // the semaphore will be signalled when it is non-empty
  379.         WaitForSingleObject(m_hSem, INFINITE);
  380.     }
  381.     // copy fields to caller's CMsg
  382.     *msg = *pmsg;
  383.  
  384.     // this CMsg was allocated by the 'new' in PutThreadMsg
  385.     delete pmsg;
  386.  
  387. }
  388.  
  389.  
  390. // NOTE: as we need to use the same binaries on Win95 as on NT this code should
  391. // be compiled WITHOUT unicode being defined.  Otherwise we will not pick up
  392. // these internal routines and the binary will not run on Win95.
  393.  
  394. #ifndef UNICODE
  395. // Windows 95 doesn't implement this, so we provide an implementation.
  396. LPWSTR
  397. WINAPI
  398. lstrcpyWInternal(
  399.     LPWSTR lpString1,
  400.     LPCWSTR lpString2
  401.     )
  402. {
  403.     LPWSTR  lpReturn = lpString1;
  404.     while (*lpString1++ = *lpString2++);
  405.  
  406.     return lpReturn;
  407. }
  408.  
  409. // Windows 95 doesn't implement this, so we provide an implementation.
  410. LPWSTR
  411. WINAPI
  412. lstrcpynWInternal(
  413.     LPWSTR lpString1,
  414.     LPCWSTR lpString2,
  415.     int     iMaxLength
  416.     )
  417. {
  418.     ASSERT(iMaxLength);
  419.     LPWSTR  lpReturn = lpString1;
  420.     if (iMaxLength) {
  421.         while (--iMaxLength && (*lpString1++ = *lpString2++));
  422.  
  423.         // If we ran out of room (which will be the case if
  424.         // iMaxLength is now 0) we still need to terminate the
  425.         // string.
  426.         if (!iMaxLength) *lpString1 = L'\0';
  427.     }
  428.     return lpReturn;
  429. }
  430.  
  431. int
  432. WINAPI
  433. lstrcmpWInternal(
  434.     LPCWSTR lpString1,
  435.     LPCWSTR lpString2
  436.     )
  437. {
  438.     do {
  439.     WCHAR c1 = *lpString1;
  440.     WCHAR c2 = *lpString2;
  441.     if (c1 != c2)
  442.         return (int) c1 - (int) c2;
  443.     } while (*lpString1++ && *lpString2++);
  444.     return 0;
  445. }
  446.  
  447.  
  448. int
  449. WINAPI
  450. lstrcmpiWInternal(
  451.     LPCWSTR lpString1,
  452.     LPCWSTR lpString2
  453.     )
  454. {
  455.     do {
  456.     WCHAR c1 = *lpString1;
  457.     WCHAR c2 = *lpString2;
  458.     if (c1 >= L'A' && c1 <= L'Z')
  459.         c1 -= (WCHAR) (L'A' - L'a');
  460.     if (c2 >= L'A' && c2 <= L'Z')
  461.         c2 -= (WCHAR) (L'A' - L'a');
  462.     
  463.     if (c1 != c2)
  464.         return (int) c1 - (int) c2;
  465.     } while (*lpString1++ && *lpString2++);
  466.  
  467.     return 0;
  468. }
  469.  
  470.  
  471. int
  472. WINAPI
  473. lstrlenWInternal(
  474.     LPCWSTR lpString
  475.     )
  476. {
  477.     int i = -1;
  478.     while (*(lpString+(++i)))
  479.         ;
  480.     return i;
  481. }
  482.  
  483.  
  484. int WINAPIV wsprintfWInternal(LPWSTR wszOut, LPCWSTR pszFmt, ...)
  485. {
  486.     char fmt[256]; // !!!
  487.     char ach[256]; // !!!
  488.     int i;
  489.  
  490.     va_list va;
  491.     va_start(va, pszFmt);
  492.     WideCharToMultiByte(GetACP(), 0, pszFmt, -1, fmt, 256, NULL, NULL);
  493.     i = wvsprintfA(ach, fmt, va);
  494.     va_end(va);
  495.  
  496.     MultiByteToWideChar(CP_ACP, 0, ach, -1, wszOut, i+1);
  497.  
  498.     return i;
  499. }
  500. #else
  501.  
  502. // need to provide the implementations in unicode for non-unicode
  503. // builds linking with the unicode strmbase.lib
  504. LPWSTR WINAPI lstrcpyWInternal(
  505.     LPWSTR lpString1,
  506.     LPCWSTR lpString2
  507.     )
  508. {
  509.     return lstrcpyW(lpString1, lpString2);
  510. }
  511.  
  512. LPWSTR WINAPI lstrcpynWInternal(
  513.     LPWSTR lpString1,
  514.     LPCWSTR lpString2,
  515.     int     iMaxLength
  516.     )
  517. {
  518.     return lstrcpynW(lpString1, lpString2, iMaxLength);
  519. }
  520.  
  521. int WINAPI lstrcmpWInternal(
  522.     LPCWSTR lpString1,
  523.     LPCWSTR lpString2
  524.     )
  525. {
  526.     return lstrcmpW(lpString1, lpString2);
  527. }
  528.  
  529.  
  530. int WINAPI lstrcmpiWInternal(
  531.     LPCWSTR lpString1,
  532.     LPCWSTR lpString2
  533.     )
  534. {
  535.     return lstrcmpiW(lpString1, lpString2);
  536. }
  537.  
  538.  
  539. int WINAPI lstrlenWInternal(
  540.     LPCWSTR lpString
  541.     )
  542. {
  543.     return lstrlenW(lpString);
  544. }
  545.  
  546.  
  547. int WINAPIV wsprintfWInternal(
  548.     LPWSTR wszOut, LPCWSTR pszFmt, ...)
  549. {
  550.     va_list va;
  551.     va_start(va, pszFmt);
  552.     int i = wvsprintfW(wszOut, pszFmt, va);
  553.     va_end(va);
  554.     return i;
  555. }
  556. #endif
  557.  
  558.  
  559. // Helper function - convert int to WSTR
  560. void WINAPI IntToWstr(int i, LPWSTR wstr)
  561. {
  562. #ifdef UNICODE
  563.     wsprintf(wstr, L"%d", i);
  564. #else
  565.     TCHAR temp[32];
  566.     wsprintf(temp, "%d", i);
  567.     MultiByteToWideChar(CP_ACP, 0, temp, -1, wstr, 32);
  568. #endif
  569. } // IntToWstr
  570.  
  571.  
  572. #if 0
  573. void * memchrInternal(const void *pv, int c, size_t sz)
  574. {
  575.     BYTE *pb = (BYTE *) pv;
  576.     while (sz--) {
  577.     if (*pb == c)
  578.         return (void *) pb;
  579.     pb++;
  580.     }
  581.     return NULL;
  582. }
  583. #endif
  584.  
  585.  
  586. #define MEMORY_ALIGNMENT        4
  587. #define MEMORY_ALIGNMENT_LOG2   2
  588. #define MEMORY_ALIGNMENT_MASK   MEMORY_ALIGNMENT - 1
  589.  
  590. void * __stdcall memmoveInternal(void * dst, const void * src, size_t count)
  591. {
  592.     void * ret = dst;
  593.  
  594. #ifdef _X86_
  595.     if (dst <= src || (char *)dst >= ((char *)src + count)) {
  596.  
  597.         /*
  598.          * Non-Overlapping Buffers
  599.          * copy from lower addresses to higher addresses
  600.          */
  601.         _asm {
  602.             mov     esi,src
  603.             mov     edi,dst
  604.             mov     ecx,count
  605.             cld
  606.             mov     edx,ecx
  607.             and     edx,MEMORY_ALIGNMENT_MASK
  608.             shr     ecx,MEMORY_ALIGNMENT_LOG2
  609.             rep     movsd
  610.             or      ecx,edx
  611.             jz      memmove_done
  612.             rep     movsb
  613. memmove_done:
  614.         }
  615.     }
  616.     else {
  617.  
  618.         /*
  619.          * Overlapping Buffers
  620.          * copy from higher addresses to lower addresses
  621.          */
  622.         _asm {
  623.             mov     esi,src
  624.             mov     edi,dst
  625.             mov     ecx,count
  626.             std
  627.             add     esi,ecx
  628.             add     edi,ecx
  629.             dec     esi
  630.             dec     edi
  631.             rep     movsb
  632.             cld
  633.         }
  634.     }
  635. #else
  636.     MoveMemory(dst, src, count);
  637. #endif
  638.  
  639.     return ret;
  640. }
  641.  
  642. /*  Arithmetic functions to help with time format conversions
  643. */
  644.  
  645. #ifdef _M_ALPHA
  646. // work around bug in version 12.00.8385 of the alpha compiler where
  647. // UInt32x32To64 sign-extends its arguments (?)
  648. #undef UInt32x32To64
  649. #define UInt32x32To64(a, b) (((ULONGLONG)((ULONG)(a)) & 0xffffffff) * ((ULONGLONG)((ULONG)(b)) & 0xffffffff))
  650. #endif
  651.  
  652. /*   Compute (a * b + d) / c */
  653. LONGLONG WINAPI llMulDiv(LONGLONG a, LONGLONG b, LONGLONG c, LONGLONG d)
  654. {
  655.     /*  Compute the absolute values to avoid signed arithmetic problems */
  656.     ULARGE_INTEGER ua, ub;
  657.     DWORDLONG uc;
  658.  
  659.     ua.QuadPart = (DWORDLONG)(a >= 0 ? a : -a);
  660.     ub.QuadPart = (DWORDLONG)(b >= 0 ? b : -b);
  661.     uc          = (DWORDLONG)(c >= 0 ? c : -c);
  662.     BOOL bSign = (a < 0) ^ (b < 0);
  663.  
  664.     /*  Do long multiplication */
  665.     ULARGE_INTEGER p[2];
  666.     p[0].QuadPart  = UInt32x32To64(ua.LowPart, ub.LowPart);
  667.  
  668.     /*  This next computation cannot overflow into p[1].HighPart because
  669.         the max number we can compute here is:
  670.  
  671.                  (2 ** 32 - 1) * (2 ** 32 - 1) +  // ua.LowPart * ub.LowPart
  672.     (2 ** 32) *  (2 ** 31) * (2 ** 32 - 1) * 2    // x.LowPart * y.HighPart * 2
  673.  
  674.     == 2 ** 96 - 2 ** 64 + (2 ** 64 - 2 ** 33 + 1)
  675.     == 2 ** 96 - 2 ** 33 + 1
  676.     < 2 ** 96
  677.     */
  678.  
  679.     ULARGE_INTEGER x;
  680.     x.QuadPart     = UInt32x32To64(ua.LowPart, ub.HighPart) +
  681.                      UInt32x32To64(ua.HighPart, ub.LowPart) +
  682.                      p[0].HighPart;
  683.     p[0].HighPart  = x.LowPart;
  684.     p[1].QuadPart  = UInt32x32To64(ua.HighPart, ub.HighPart) + x.HighPart;
  685.  
  686.     if (d != 0) {
  687.         ULARGE_INTEGER ud[2];
  688.         if (bSign) {
  689.             ud[0].QuadPart = (DWORDLONG)(-d);
  690.             if (d > 0) {
  691.                 /*  -d < 0 */
  692.                 ud[1].QuadPart = (DWORDLONG)(LONGLONG)-1;
  693.             } else {
  694.                 ud[1].QuadPart = (DWORDLONG)0;
  695.             }
  696.         } else {
  697.             ud[0].QuadPart = (DWORDLONG)d;
  698.             if (d < 0) {
  699.                 ud[1].QuadPart = (DWORDLONG)(LONGLONG)-1;
  700.             } else {
  701.                 ud[1].QuadPart = (DWORDLONG)0;
  702.             }
  703.         }
  704.         /*  Now do extended addition */
  705.         ULARGE_INTEGER uliTotal;
  706.  
  707.         /*  Add ls DWORDs */
  708.         uliTotal.QuadPart  = (DWORDLONG)ud[0].LowPart + p[0].LowPart;
  709.         p[0].LowPart       = uliTotal.LowPart;
  710.  
  711.         /*  Propagate carry */
  712.         uliTotal.LowPart   = uliTotal.HighPart;
  713.         uliTotal.HighPart  = 0;
  714.  
  715.         /*  Add 2nd most ls DWORDs */
  716.         uliTotal.QuadPart += (DWORDLONG)ud[0].HighPart + p[0].HighPart;
  717.         p[0].HighPart      = uliTotal.LowPart;
  718.  
  719.         /*  Propagate carry */
  720.         uliTotal.LowPart   = uliTotal.HighPart;
  721.         uliTotal.HighPart  = 0;
  722.  
  723.         /*  Add MS DWORDLONGs - no carry expected */
  724.         p[1].QuadPart     += ud[1].QuadPart + uliTotal.QuadPart;
  725.  
  726.         /*  Now see if we got a sign change from the addition */
  727.         if ((LONG)p[1].HighPart < 0) {
  728.             bSign = !bSign;
  729.  
  730.             /*  Negate the current value (ugh!) */
  731.             p[0].QuadPart  = ~p[0].QuadPart;
  732.             p[1].QuadPart  = ~p[1].QuadPart;
  733.             p[0].QuadPart += 1;
  734.             p[1].QuadPart += (p[0].QuadPart == 0);
  735.         }
  736.     }
  737.  
  738.     /*  Now for the division */
  739.     if (c < 0) {
  740.         bSign = !bSign;
  741.     }
  742.  
  743.  
  744.     /*  This will catch c == 0 and overflow */
  745.     if (uc <= p[1].QuadPart) {
  746.         return bSign ? (LONGLONG)0x8000000000000000 :
  747.                        (LONGLONG)0x7FFFFFFFFFFFFFFF;
  748.     }
  749.  
  750.     DWORDLONG ullResult;
  751.  
  752.     /*  Do the division */
  753.     /*  If the dividend is a DWORD_LONG use the compiler */
  754.     if (p[1].QuadPart == 0) {
  755.         ullResult = p[0].QuadPart / uc;
  756.         return bSign ? -(LONGLONG)ullResult : (LONGLONG)ullResult;
  757.     }
  758.  
  759.     /*  If the divisor is a DWORD then its simpler */
  760.     ULARGE_INTEGER ulic;
  761.     ulic.QuadPart = uc;
  762.     if (ulic.HighPart == 0) {
  763.         ULARGE_INTEGER uliDividend;
  764.         ULARGE_INTEGER uliResult;
  765.         DWORD dwDivisor = (DWORD)uc;
  766.         // ASSERT(p[1].HighPart == 0 && p[1].LowPart < dwDivisor);
  767.         uliDividend.HighPart = p[1].LowPart;
  768.         uliDividend.LowPart = p[0].HighPart;
  769. #ifndef USE_LARGEINT
  770.         uliResult.HighPart = (DWORD)(uliDividend.QuadPart / dwDivisor);
  771.         p[0].HighPart = (DWORD)(uliDividend.QuadPart % dwDivisor);
  772.         uliResult.LowPart = 0;
  773.         uliResult.QuadPart = p[0].QuadPart / dwDivisor + uliResult.QuadPart;
  774. #else
  775.         /*  NOTE - this routine will take exceptions if
  776.             the result does not fit in a DWORD
  777.         */
  778.         if (uliDividend.QuadPart >= (DWORDLONG)dwDivisor) {
  779.             uliResult.HighPart = EnlargedUnsignedDivide(
  780.                                      uliDividend,
  781.                                      dwDivisor,
  782.                                      &p[0].HighPart);
  783.         } else {
  784.             uliResult.HighPart = 0;
  785.         }
  786.         uliResult.LowPart = EnlargedUnsignedDivide(
  787.                                  p[0],
  788.                                  dwDivisor,
  789.                                  NULL);
  790. #endif
  791.         return bSign ? -(LONGLONG)uliResult.QuadPart :
  792.                         (LONGLONG)uliResult.QuadPart;
  793.     }
  794.  
  795.  
  796.     ullResult = 0;
  797.  
  798.     /*  OK - do long division */
  799.     for (int i = 0; i < 64; i++) {
  800.         ullResult <<= 1;
  801.  
  802.         /*  Shift 128 bit p left 1 */
  803.         p[1].QuadPart <<= 1;
  804.         if ((p[0].HighPart & 0x80000000) != 0) {
  805.             p[1].LowPart++;
  806.         }
  807.         p[0].QuadPart <<= 1;
  808.  
  809.         /*  Compare */
  810.         if (uc <= p[1].QuadPart) {
  811.             p[1].QuadPart -= uc;
  812.             ullResult += 1;
  813.         }
  814.     }
  815.  
  816.     return bSign ? - (LONGLONG)ullResult : (LONGLONG)ullResult;
  817. }
  818.  
  819. LONGLONG WINAPI Int64x32Div32(LONGLONG a, LONG b, LONG c, LONG d)
  820. {
  821.     ULARGE_INTEGER ua;
  822.     DWORD ub;
  823.     DWORD uc;
  824.  
  825.     /*  Compute the absolute values to avoid signed arithmetic problems */
  826.     ua.QuadPart = (DWORDLONG)(a >= 0 ? a : -a);
  827.     ub = (DWORD)(b >= 0 ? b : -b);
  828.     uc = (DWORD)(c >= 0 ? c : -c);
  829.     BOOL bSign = (a < 0) ^ (b < 0);
  830.  
  831.     /*  Do long multiplication */
  832.     ULARGE_INTEGER p0;
  833.     DWORD p1;
  834.     p0.QuadPart  = UInt32x32To64(ua.LowPart, ub);
  835.  
  836.     if (ua.HighPart != 0) {
  837.         ULARGE_INTEGER x;
  838.         x.QuadPart     = UInt32x32To64(ua.HighPart, ub) + p0.HighPart;
  839.         p0.HighPart  = x.LowPart;
  840.         p1   = x.HighPart;
  841.     } else {
  842.         p1 = 0;
  843.     }
  844.  
  845.     if (d != 0) {
  846.         ULARGE_INTEGER ud0;
  847.         DWORD ud1;
  848.  
  849.         if (bSign) {
  850.             //
  851.             //  Cast d to LONGLONG first otherwise -0x80000000 sign extends
  852.             //  incorrectly
  853.             //
  854.             ud0.QuadPart = (DWORDLONG)(-(LONGLONG)d);
  855.             if (d > 0) {
  856.                 /*  -d < 0 */
  857.                 ud1 = (DWORD)-1;
  858.             } else {
  859.                 ud1 = (DWORD)0;
  860.             }
  861.         } else {
  862.             ud0.QuadPart = (DWORDLONG)d;
  863.             if (d < 0) {
  864.                 ud1 = (DWORD)-1;
  865.             } else {
  866.                 ud1 = (DWORD)0;
  867.             }
  868.         }
  869.         /*  Now do extended addition */
  870.         ULARGE_INTEGER uliTotal;
  871.  
  872.         /*  Add ls DWORDs */
  873.         uliTotal.QuadPart  = (DWORDLONG)ud0.LowPart + p0.LowPart;
  874.         p0.LowPart       = uliTotal.LowPart;
  875.  
  876.         /*  Propagate carry */
  877.         uliTotal.LowPart   = uliTotal.HighPart;
  878.         uliTotal.HighPart  = 0;
  879.  
  880.         /*  Add 2nd most ls DWORDs */
  881.         uliTotal.QuadPart += (DWORDLONG)ud0.HighPart + p0.HighPart;
  882.         p0.HighPart      = uliTotal.LowPart;
  883.  
  884.         /*  Add MS DWORDLONGs - no carry expected */
  885.         p1 += ud1 + uliTotal.HighPart;
  886.  
  887.         /*  Now see if we got a sign change from the addition */
  888.         if ((LONG)p1 < 0) {
  889.             bSign = !bSign;
  890.  
  891.             /*  Negate the current value (ugh!) */
  892.             p0.QuadPart  = ~p0.QuadPart;
  893.             p1 = ~p1;
  894.             p0.QuadPart += 1;
  895.             p1 += (p0.QuadPart == 0);
  896.         }
  897.     }
  898.  
  899.     /*  Now for the division */
  900.     if (c < 0) {
  901.         bSign = !bSign;
  902.     }
  903.  
  904.  
  905.     /*  This will catch c == 0 and overflow */
  906.     if (uc <= p1) {
  907.         return bSign ? (LONGLONG)0x8000000000000000 :
  908.                        (LONGLONG)0x7FFFFFFFFFFFFFFF;
  909.     }
  910.  
  911.     /*  Do the division */
  912.  
  913.     /*  If the divisor is a DWORD then its simpler */
  914.     ULARGE_INTEGER uliDividend;
  915.     ULARGE_INTEGER uliResult;
  916.     DWORD dwDivisor = uc;
  917.     uliDividend.HighPart = p1;
  918.     uliDividend.LowPart = p0.HighPart;
  919.     /*  NOTE - this routine will take exceptions if
  920.         the result does not fit in a DWORD
  921.     */
  922.     if (uliDividend.QuadPart >= (DWORDLONG)dwDivisor) {
  923.         uliResult.HighPart = EnlargedUnsignedDivide(
  924.                                  uliDividend,
  925.                                  dwDivisor,
  926.                                  &p0.HighPart);
  927.     } else {
  928.         uliResult.HighPart = 0;
  929.     }
  930.     uliResult.LowPart = EnlargedUnsignedDivide(
  931.                              p0,
  932.                              dwDivisor,
  933.                              NULL);
  934.     return bSign ? -(LONGLONG)uliResult.QuadPart :
  935.                     (LONGLONG)uliResult.QuadPart;
  936. }
  937.  
  938. #ifdef DEBUG
  939. /******************************Public*Routine******************************\
  940. * Debug CCritSec helpers
  941. *
  942. * We provide debug versions of the Constructor, destructor, Lock and Unlock
  943. * routines.  The debug code tracks who owns each critical section by
  944. * maintaining a depth count.
  945. *
  946. * History:
  947. *
  948. \**************************************************************************/
  949.  
  950. CCritSec::CCritSec()
  951. {
  952.     InitializeCriticalSection(&m_CritSec);
  953.     m_currentOwner = m_lockCount = 0;
  954.     m_fTrace = FALSE;
  955. }
  956.  
  957. CCritSec::~CCritSec()
  958. {
  959.     DeleteCriticalSection(&m_CritSec);
  960. }
  961.  
  962. void CCritSec::Lock()
  963. {
  964.     UINT tracelevel=3;
  965.     DWORD us = GetCurrentThreadId();
  966.     DWORD currentOwner = m_currentOwner;
  967.     if (currentOwner && (currentOwner != us)) {
  968.         // already owned, but not by us
  969.         if (m_fTrace) {
  970.             DbgLog((LOG_LOCKING, 2, TEXT("Thread %d about to wait for lock %x owned by %d"),
  971.                 GetCurrentThreadId(), &m_CritSec, currentOwner));
  972.             tracelevel=2;
  973.             // if we saw the message about waiting for the critical
  974.             // section we ensure we see the message when we get the
  975.             // critical section
  976.         }
  977.     }
  978.     EnterCriticalSection(&m_CritSec);
  979.     if (0 == m_lockCount++) {
  980.         // we now own it for the first time.  Set owner information
  981.         m_currentOwner = us;
  982.  
  983.         if (m_fTrace) {
  984.             DbgLog((LOG_LOCKING, tracelevel, TEXT("Thread %d now owns lock %x"), m_currentOwner, &m_CritSec));
  985.         }
  986.     }
  987. }
  988.  
  989. void CCritSec::Unlock() {
  990.     if (0 == --m_lockCount) {
  991.         // about to be unowned
  992.         if (m_fTrace) {
  993.             DbgLog((LOG_LOCKING, 3, TEXT("Thread %d releasing lock %x"), m_currentOwner, &m_CritSec));
  994.         }
  995.  
  996.         m_currentOwner = 0;
  997.     }
  998.     LeaveCriticalSection(&m_CritSec);
  999. }
  1000.  
  1001. void WINAPI DbgLockTrace(CCritSec * pcCrit, BOOL fTrace)
  1002. {
  1003.     pcCrit->m_fTrace = fTrace;
  1004. }
  1005.  
  1006. BOOL WINAPI CritCheckIn(CCritSec * pcCrit)
  1007. {
  1008.     return (GetCurrentThreadId() == pcCrit->m_currentOwner);
  1009. }
  1010.  
  1011. BOOL WINAPI CritCheckIn(const CCritSec * pcCrit)
  1012. {
  1013.     return (GetCurrentThreadId() == pcCrit->m_currentOwner);
  1014. }
  1015.  
  1016. BOOL WINAPI CritCheckOut(CCritSec * pcCrit)
  1017. {
  1018.     return (GetCurrentThreadId() != pcCrit->m_currentOwner);
  1019. }
  1020.  
  1021. BOOL WINAPI CritCheckOut(const CCritSec * pcCrit)
  1022. {
  1023.     return (GetCurrentThreadId() != pcCrit->m_currentOwner);
  1024. }
  1025. #endif
  1026.  
  1027.  
  1028. STDAPI WriteBSTR(BSTR *pstrDest, LPCWSTR szSrc)
  1029. {
  1030.     *pstrDest = SysAllocString( szSrc );
  1031.     if( !(*pstrDest) ) return E_OUTOFMEMORY;
  1032.     return NOERROR;
  1033. }
  1034.  
  1035.  
  1036. STDAPI FreeBSTR(BSTR* pstr)
  1037. {
  1038.     if( *pstr == NULL ) return S_FALSE;
  1039.     SysFreeString( *pstr );
  1040.     return NOERROR;
  1041. }
  1042.  
  1043.  
  1044. // Return a wide string - allocating memory for it
  1045. // Returns:
  1046. //    S_OK          - no error
  1047. //    E_POINTER     - ppszReturn == NULL
  1048. //    E_OUTOFMEMORY - can't allocate memory for returned string
  1049. STDAPI AMGetWideString(LPCWSTR psz, LPWSTR *ppszReturn)
  1050. {
  1051.     CheckPointer(ppszReturn, E_POINTER);
  1052.     ValidateReadWritePtr(ppszReturn, sizeof(LPWSTR));
  1053.     DWORD nameLen = sizeof(WCHAR) * (lstrlenW(psz)+1);
  1054.     *ppszReturn = (LPWSTR)CoTaskMemAlloc(nameLen);
  1055.     if (*ppszReturn == NULL) {
  1056.        return E_OUTOFMEMORY;
  1057.     }
  1058.     CopyMemory(*ppszReturn, psz, nameLen);
  1059.     return NOERROR;
  1060. }
  1061.  
  1062. // Waits for the HANDLE hObject.  While waiting messages sent
  1063. // to windows on our thread by SendMessage will be processed.
  1064. // Using this function to do waits and mutual exclusion
  1065. // avoids some deadlocks in objects with windows.
  1066. // Return codes are the same as for WaitForSingleObject
  1067. DWORD WINAPI WaitDispatchingMessages(
  1068.     HANDLE hObject,
  1069.     DWORD dwWait,
  1070.     HWND hwnd,
  1071.     UINT uMsg,
  1072.     HANDLE hEvent)
  1073. {
  1074.     BOOL bPeeked = FALSE;
  1075.     DWORD dwResult;
  1076.     DWORD dwStart;
  1077.     DWORD dwThreadPriority;
  1078.  
  1079.     static UINT uMsgId = 0;
  1080.  
  1081.     HANDLE hObjects[2] = { hObject, hEvent };
  1082.     if (dwWait != INFINITE && dwWait != 0) {
  1083.         dwStart = GetTickCount();
  1084.     }
  1085.     for (; ; ) {
  1086.         DWORD nCount = NULL != hEvent ? 2 : 1;
  1087.  
  1088.         //  Minimize the chance of actually dispatching any messages
  1089.         //  by seeing if we can lock immediately.
  1090.         dwResult = WaitForMultipleObjects(nCount, hObjects, FALSE, 0);
  1091.         if (dwResult < WAIT_OBJECT_0 + nCount) {
  1092.             return dwResult;
  1093.         }
  1094.  
  1095.         DWORD dwTimeOut = dwWait;
  1096.         if (dwTimeOut > 10) {
  1097.             dwTimeOut = 10;
  1098.         }
  1099.         dwResult = MsgWaitForMultipleObjects(
  1100.                              nCount,
  1101.                              hObjects,
  1102.                              FALSE,
  1103.                              dwTimeOut,
  1104.                              hwnd == NULL ? QS_SENDMESSAGE :
  1105.                                             QS_SENDMESSAGE + QS_POSTMESSAGE);
  1106.         if (dwResult == WAIT_OBJECT_0 + nCount ||
  1107.             dwResult == WAIT_TIMEOUT && dwTimeOut != dwWait) {
  1108.             MSG msg;
  1109.             if (hwnd != NULL) {
  1110.                 while (PeekMessage(&msg, hwnd, uMsg, uMsg, PM_REMOVE)) {
  1111.                     DispatchMessage(&msg);
  1112.                 }
  1113.             }
  1114.             // Do this anyway - the previous peek doesn't flush out the
  1115.             // messages
  1116.             PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE);
  1117.  
  1118.             if (dwWait != INFINITE && dwWait != 0) {
  1119.                 DWORD dwNow = GetTickCount();
  1120.  
  1121.                 // Working with differences handles wrap-around
  1122.                 DWORD dwDiff = dwNow - dwStart;
  1123.                 if (dwDiff > dwWait) {
  1124.                     dwWait = 0;
  1125.                 } else {
  1126.                     dwWait -= dwDiff;
  1127.                 }
  1128.                 dwStart = dwNow;
  1129.             }
  1130.             if (!bPeeked) {
  1131.                 //  Raise our priority to prevent our message queue
  1132.                 //  building up
  1133.                 dwThreadPriority = GetThreadPriority(GetCurrentThread());
  1134.                 if (dwThreadPriority < THREAD_PRIORITY_HIGHEST) {
  1135.                     SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
  1136.                 }
  1137.                 bPeeked = TRUE;
  1138.             }
  1139.         } else {
  1140.             break;
  1141.         }
  1142.     }
  1143.     if (bPeeked) {
  1144.         SetThreadPriority(GetCurrentThread(), dwThreadPriority);
  1145.         if (HIWORD(GetQueueStatus(QS_POSTMESSAGE)) & QS_POSTMESSAGE) {
  1146.             if (uMsgId == 0) {
  1147.                 uMsgId = RegisterWindowMessage(TEXT("AMUnblock"));
  1148.             }
  1149.             if (uMsgId != 0) {
  1150.                 MSG msg;
  1151.                 //  Remove old ones
  1152.                 while (PeekMessage(&msg, (HWND)-1, uMsgId, uMsgId, PM_REMOVE)) {
  1153.                 }
  1154.             }
  1155.             PostThreadMessage(GetCurrentThreadId(), uMsgId, 0, 0);
  1156.         }
  1157.     }
  1158.     return dwResult;
  1159. }
  1160.  
  1161. HRESULT AmGetLastErrorToHResult()
  1162. {
  1163.     DWORD dwLastError = GetLastError();
  1164.     if(dwLastError != 0)
  1165.     {
  1166.         return HRESULT_FROM_WIN32(dwLastError);
  1167.     }
  1168.     else
  1169.     {
  1170.         return E_FAIL;
  1171.     }
  1172. }
  1173.  
  1174. IUnknown* QzAtlComPtrAssign(IUnknown** pp, IUnknown* lp)
  1175. {
  1176.     if (lp != NULL)
  1177.         lp->AddRef();
  1178.     if (*pp)
  1179.         (*pp)->Release();
  1180.     *pp = lp;
  1181.     return lp;
  1182. }
  1183.  
  1184.