wxutil.cpp
上传用户:liguizhu
上传日期:2015-11-01
资源大小:2422k
文件大小:32k
源码类别:

P2P编程

开发平台:

Visual C++

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