home *** CD-ROM | disk | FTP | other *** search
/ The Net: Ultimate Internet Guide / WWLCD1.ISO / mac / SiteBldr / AMOVIE / SDK / _SETUP / COMMON.Z / wxutil.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1996-04-20  |  21.9 KB  |  898 lines

  1. //==========================================================================;
  2. //
  3. //  THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  4. //  KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  5. //  IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  6. //  PURPOSE.
  7. //
  8. //  Copyright (c) 1992 - 1996  Microsoft Corporation.  All Rights Reserved.
  9. //
  10. //--------------------------------------------------------------------------;
  11.  
  12. //
  13. // helper classes for building multimedia filters
  14. //
  15.  
  16. #include <streams.h>
  17.  
  18. //
  19. //  Declare function from largeint.h we need so that PPC can build
  20. //
  21.  
  22. //
  23. // Enlarged integer divide - 64-bits / 32-bits > 32-bits
  24. //
  25.  
  26. #ifndef _X86_
  27.  
  28. #define LLtoU64(x) (*(unsigned __int64*)(void*)(&(x)))
  29.  
  30. __inline
  31. ULONG
  32. WINAPI
  33. EnlargedUnsignedDivide (
  34.     IN ULARGE_INTEGER Dividend,
  35.     IN ULONG Divisor,
  36.     IN PULONG Remainder
  37.     )
  38. {
  39.         // return remainder if necessary
  40.         if (Remainder != NULL)
  41.                 *Remainder = (ULONG)(LLtoU64(Dividend) % Divisor);
  42.         return (ULONG)(LLtoU64(Dividend) / Divisor);
  43. }
  44.  
  45. #else
  46. __inline
  47. ULONG
  48. WINAPI
  49. EnlargedUnsignedDivide (
  50.     IN ULARGE_INTEGER Dividend,
  51.     IN ULONG Divisor,
  52.     IN PULONG Remainder
  53.     )
  54. {
  55.     ULONG ulResult;
  56.     _asm {
  57.         mov eax,Dividend.LowPart
  58.         mov edx,Dividend.HighPart
  59.         mov ecx,Remainder
  60.         div Divisor
  61.         or  ecx,ecx
  62.         jz  short label
  63.         mov [ecx],edx
  64. label:
  65.         mov ulResult,eax
  66.     }
  67.     return ulResult;
  68. }
  69. #endif
  70.  
  71. // --- CAMEvent -----------------------
  72. CAMEvent::CAMEvent(BOOL fManualReset)
  73. {
  74.     m_hEvent = CreateEvent(NULL, fManualReset, FALSE, NULL);
  75. }
  76.  
  77. CAMEvent::~CAMEvent()
  78. {
  79.     if (m_hEvent) {
  80.     EXECUTE_ASSERT(CloseHandle(m_hEvent));
  81.     }
  82. }
  83.  
  84. // --- CThread ----------------------
  85.  
  86.  
  87. CThread::CThread()
  88.     : m_EventSend(TRUE)     // must be manual-reset for CheckRequest()
  89. {
  90.     m_hThread = NULL;
  91. }
  92.  
  93. CThread::~CThread() {
  94.  
  95.     if (ThreadExists()) {
  96.  
  97.     // can't kill the thread, we just have to block until it exits.
  98.  
  99.     // wait for termination and close handle
  100.     Close();
  101.     }
  102. }
  103.  
  104.  
  105. // ThreadExists
  106. // Return TRUE if the thread exists. FALSE otherwise
  107. BOOL
  108. CThread::ThreadExists(void)
  109. {
  110.  
  111.     if (m_hThread == 0) {
  112.         return FALSE;
  113.     }
  114.  
  115.     DWORD    dwExitCode;
  116.  
  117.     BOOL fErr = GetExitCodeThread(m_hThread, &dwExitCode);
  118.     if (!fErr) {
  119.         return FALSE;    // Assuming the error was caused by a bad
  120.             // handle or similar
  121.     }
  122.     if (dwExitCode == STILL_ACTIVE) {
  123.         return TRUE;
  124.     }
  125.     else {
  126.         return FALSE;
  127.     }
  128. }
  129.  
  130.  
  131. // when the thread starts, it calls this function. We unwrap the 'this'
  132. //pointer and call ThreadProc.
  133. DWORD WINAPI
  134. CThread::InitialThreadProc(LPVOID pv)
  135. {
  136.     CThread * pThread = (CThread *) pv;
  137.  
  138.     return pThread->ThreadProc();
  139. }
  140.  
  141. BOOL
  142. CThread::Create()
  143. {
  144.     DWORD threadid;
  145.  
  146.     CAutoLock lock(&m_AccessLock);
  147.  
  148.     if (ThreadExists()) {
  149.     return FALSE;
  150.     }
  151.  
  152.     m_hThread = CreateThread(
  153.             NULL,
  154.             0,
  155.             CThread::InitialThreadProc,
  156.             this,
  157.             0,
  158.             &threadid);
  159.  
  160.     if (!m_hThread) {
  161.     return FALSE;
  162.     }
  163.  
  164.     return TRUE;
  165. }
  166.  
  167. DWORD
  168. CThread::CallWorker(DWORD dwParam)
  169. {
  170.     // lock access to the worker thread for scope of this object
  171.     CAutoLock lock(&m_AccessLock);
  172.  
  173.     if (!ThreadExists()) {
  174.     return E_FAIL;
  175.     }
  176.  
  177.     // set the parameter
  178.     m_dwParam = dwParam;
  179.  
  180.     // signal the worker thread
  181.     m_EventSend.Set();
  182.  
  183.     // wait for the completion to be signalled
  184.     m_EventComplete.Wait();
  185.  
  186.     // done - this is the thread's return value
  187.     return m_dwReturnVal;
  188. }
  189.  
  190. // Wait for a request from the client
  191. DWORD
  192. CThread::GetRequest()
  193. {
  194.     m_EventSend.Wait();
  195.     return m_dwParam;
  196. }
  197.  
  198. // is there a request?
  199. BOOL
  200. CThread::CheckRequest(DWORD * pParam)
  201. {
  202.     if (!m_EventSend.Check()) {
  203.     return FALSE;
  204.     } else {
  205.     if (pParam) {
  206.         *pParam = m_dwParam;
  207.     }
  208.     return TRUE;
  209.     }
  210. }
  211.  
  212. // reply to the request
  213. void
  214. CThread::Reply(DWORD dw)
  215. {
  216.     m_dwReturnVal = dw;
  217.  
  218.     // The request is now complete so CheckRequest should fail from
  219.     // now on
  220.     //
  221.     // This event should be reset BEFORE we signal the client or
  222.     // the client may Set it before we reset it and we'll then
  223.     // reset it (!)
  224.  
  225.     m_EventSend.Reset();
  226.  
  227.     // Tell the client we're finished
  228.  
  229.     m_EventComplete.Set();
  230. }
  231.  
  232.  
  233. // destructor for CMsgThread  - cleans up any messages left in the
  234. // queue when the thread exited
  235. CMsgThread::~CMsgThread()
  236. {
  237.     if (m_hThread != NULL) {
  238.         WaitForSingleObject(m_hThread, INFINITE);
  239.         EXECUTE_ASSERT(CloseHandle(m_hThread));
  240.     }
  241.  
  242.     POSITION pos = m_ThreadQueue.GetHeadPosition();
  243.     while (pos) {
  244.         CMsg * pMsg = m_ThreadQueue.GetNext(pos);
  245.         delete pMsg;
  246.     }
  247.     m_ThreadQueue.RemoveAll();
  248.  
  249.     if (m_hSem != NULL) {
  250.         EXECUTE_ASSERT(CloseHandle(m_hSem));
  251.     }
  252. }
  253.  
  254. BOOL
  255. CMsgThread::CreateThread(
  256.     )
  257. {
  258.     m_hSem = CreateSemaphore(NULL, 0, 0x7FFFFFFF, NULL);
  259.     if (m_hSem == NULL) {
  260.         return FALSE;
  261.     }
  262.  
  263.     m_hThread = ::CreateThread(NULL, 0, DefaultThreadProc,
  264.                    (LPVOID)this, 0, &m_ThreadId);
  265.     return m_hThread != NULL;
  266. }
  267.  
  268.  
  269. // This is the threads message pump.  Here we get and dispatch messages to
  270. // clients thread proc until the client refuses to process a message.
  271. // The client returns a non-zero value to stop the message pump, this
  272. // value becomes the threads exit code.
  273.  
  274. DWORD WINAPI
  275. CMsgThread::DefaultThreadProc(
  276.     LPVOID lpParam
  277.     )
  278. {
  279.     CMsgThread *lpThis = (CMsgThread *)lpParam;
  280.     CMsg msg;
  281.     LRESULT lResult;
  282.  
  283.     // !!!
  284.     CoInitialize(NULL);
  285.  
  286.     // allow a derived class to handle thread startup
  287.     lpThis->OnThreadInit();
  288.  
  289.     do {
  290.     lpThis->GetThreadMsg(&msg);
  291.     lResult = lpThis->ThreadMessageProc(msg.uMsg,msg.dwFlags,
  292.                         msg.lpParam, msg.pEvent);
  293.     } while (lResult == 0L);
  294.  
  295.     // !!!
  296.     CoUninitialize();
  297.  
  298.     return (DWORD)lResult;
  299. }
  300.  
  301.  
  302. // Block until the next message is placed on the list m_ThreadQueue.
  303. // copies the message to the message pointed to by *pmsg
  304. void
  305. CMsgThread::GetThreadMsg(CMsg *msg)
  306. {
  307.     CMsg * pmsg = NULL;
  308.  
  309.     // keep trying until a message appears
  310.     while (TRUE) {
  311.         {
  312.             CAutoLock lck(&m_Lock);
  313.             pmsg = m_ThreadQueue.RemoveHead();
  314.             if (pmsg == NULL) {
  315.                 m_lWaiting++;
  316.             } else {
  317.                 break;
  318.             }
  319.         }
  320.         // the semaphore will be signalled when it is non-empty
  321.         WaitForSingleObject(m_hSem, INFINITE);
  322.     }
  323.     // copy fields to caller's CMsg
  324.     *msg = *pmsg;
  325.  
  326.     // this CMsg was allocated by the 'new' in PutThreadMsg
  327.     delete pmsg;
  328.  
  329. }
  330.  
  331.  
  332. #ifndef UNICODE
  333. // NOTE: as we need to use the same binaries on Win95 as on NT this code should
  334. // be compiled WITHOUT unicode being defined.  Otherwise we will not pick up
  335. // these internal routines and the binary will not run on Win95.
  336.  
  337. // Windows 95 doesn't implement this, so we provide an implementation.
  338. LPWSTR
  339. WINAPI
  340. lstrcpyWInternal(
  341.     LPWSTR lpString1,
  342.     LPCWSTR lpString2
  343.     )
  344. {
  345.     LPWSTR  lpReturn = lpString1;
  346.     while (*lpString1++ = *lpString2++);
  347.  
  348.     return lpReturn;
  349. }
  350.  
  351. // Windows 95 doesn't implement this, so we provide an implementation.
  352. LPWSTR
  353. WINAPI
  354. lstrcpynWInternal(
  355.     LPWSTR lpString1,
  356.     LPCWSTR lpString2,
  357.     int     iMaxLength
  358.     )
  359. {
  360.     ASSERT(iMaxLength);
  361.     LPWSTR  lpReturn = lpString1;
  362.     if (iMaxLength) {
  363.         while (--iMaxLength && (*lpString1++ = *lpString2++));
  364.  
  365.         // If we ran out of room (which will be the case if
  366.         // iMaxLength is now 0) we still need to terminate the
  367.         // string.
  368.         if (!iMaxLength) *lpString1 = L'\0';
  369.     }
  370.     return lpReturn;
  371. }
  372.  
  373. int
  374. WINAPI
  375. lstrcmpWInternal(
  376.     LPCWSTR lpString1,
  377.     LPCWSTR lpString2
  378.     )
  379. {
  380.     do {
  381.     WCHAR c1 = *lpString1;
  382.     WCHAR c2 = *lpString2;
  383.     if (c1 != c2)
  384.         return (int) c1 - (int) c2;
  385.     } while (*lpString1++ && *lpString2++);
  386.     return 0;
  387. }
  388.  
  389.  
  390. int
  391. WINAPI
  392. lstrcmpiWInternal(
  393.     LPCWSTR lpString1,
  394.     LPCWSTR lpString2
  395.     )
  396. {
  397.     do {
  398.     WCHAR c1 = *lpString1;
  399.     WCHAR c2 = *lpString2;
  400.     if (c1 >= L'A' && c1 <= L'Z')
  401.         c1 -= (WCHAR) (L'A' - L'a');
  402.     if (c2 >= L'A' && c2 <= L'Z')
  403.         c2 -= (WCHAR) (L'A' - L'a');
  404.     
  405.     if (c1 != c2)
  406.         return (int) c1 - (int) c2;
  407.     } while (*lpString1++ && *lpString2++);
  408.  
  409.     return 0;
  410. }
  411.  
  412.  
  413. int
  414. WINAPI
  415. lstrlenWInternal(
  416.     LPCWSTR lpString
  417.     )
  418. {
  419.     int i = -1;
  420.     while (*(lpString+(++i)))
  421.         ;
  422.     return i;
  423. }
  424.  
  425. #endif // NOT UNICODE
  426.  
  427.  
  428. #ifndef UNICODE
  429. int WINAPIV wsprintfWInternal(LPWSTR wszOut, LPCWSTR pszFmt, ...)
  430. {
  431.     char fmt[256]; // !!!
  432.     char ach[256]; // !!!
  433.     int i;
  434.  
  435.     va_list va;
  436.     va_start(va, pszFmt);
  437.     WideCharToMultiByte(GetACP(), 0, pszFmt, -1, fmt, 256, NULL, NULL);
  438.     i = wvsprintf(ach, fmt, va);
  439.     va_end(va);
  440.  
  441.     MultiByteToWideChar(CP_ACP, 0, ach, -1, wszOut, i+1);
  442.  
  443.     return i;
  444. }
  445. #endif
  446.  
  447. // Helper function - convert int to WSTR
  448. void WINAPI IntToWstr(int i, LPWSTR wstr)
  449. {
  450. #ifdef UNICODE
  451.     wsprintf(wstr, L"%d", i);
  452. #else
  453.     TCHAR temp[32];
  454.     wsprintf(temp, "%d", i);
  455.     MultiByteToWideChar(CP_ACP, 0, temp, -1, wstr, 32);
  456. #endif
  457. } // IntToWstr
  458.  
  459.  
  460.  
  461. void * __cdecl memchrInternal(const void *pv, int c, size_t sz)
  462. {
  463.     BYTE *pb = (BYTE *) pv;
  464.     while (sz--) {
  465.     if (*pb == c)
  466.         return (void *) pb;
  467.     pb++;
  468.     }
  469.     return NULL;
  470. }
  471.  
  472. /*  Arithmetic functions to help with time format conversions
  473. */
  474.  
  475. /*   Compute (a * b + d) / c */
  476. LONGLONG llMulDiv(LONGLONG a, LONGLONG b, LONGLONG c, LONGLONG d)
  477. {
  478.     /*  Compute the absolute values to avoid signed arithmetic problems */
  479.     ULARGE_INTEGER ua, ub;
  480.     DWORDLONG uc;
  481.  
  482.     ua.QuadPart = (DWORDLONG)(a >= 0 ? a : -a);
  483.     ub.QuadPart = (DWORDLONG)(b >= 0 ? b : -b);
  484.     uc          = (DWORDLONG)(c >= 0 ? c : -c);
  485.     BOOL bSign = (a < 0) ^ (b < 0);
  486.  
  487.     /*  Do long multiplication */
  488.     ULARGE_INTEGER p[2];
  489.     p[0].QuadPart  = UInt32x32To64(ua.LowPart, ub.LowPart);
  490.  
  491.     /*  This next computation cannot overflow into p[1].HighPart because
  492.         the max number we can compute here is:
  493.  
  494.                  (2 ** 32 - 1) * (2 ** 32 - 1) +  // ua.LowPart * ub.LowPart
  495.     (2 ** 32) *  (2 ** 31) * (2 ** 32 - 1) * 2    // x.LowPart * y.HighPart * 2
  496.  
  497.     == 2 ** 96 - 2 ** 64 + (2 ** 64 - 2 ** 33 + 1)
  498.     == 2 ** 96 - 2 ** 33 + 1
  499.     < 2 ** 96
  500.     */
  501.  
  502.     ULARGE_INTEGER x;
  503.     x.QuadPart     = UInt32x32To64(ua.LowPart, ub.HighPart) +
  504.                      UInt32x32To64(ua.HighPart, ub.LowPart) +
  505.                      p[0].HighPart;
  506.     p[0].HighPart  = x.LowPart;
  507.     p[1].QuadPart  = UInt32x32To64(ua.HighPart, ub.HighPart) + x.HighPart;
  508.  
  509.     if (d != 0) {
  510.         ULARGE_INTEGER ud[2];
  511.         if (bSign) {
  512.             ud[0].QuadPart = (DWORDLONG)(-d);
  513.             if (d > 0) {
  514.                 /*  -d < 0 */
  515.                 ud[1].QuadPart = (DWORDLONG)(LONGLONG)-1;
  516.             } else {
  517.                 ud[1].QuadPart = (DWORDLONG)0;
  518.             }
  519.         } else {
  520.             ud[0].QuadPart = (DWORDLONG)d;
  521.             if (d < 0) {
  522.                 ud[1].QuadPart = (DWORDLONG)(LONGLONG)-1;
  523.             } else {
  524.                 ud[1].QuadPart = (DWORDLONG)0;
  525.             }
  526.         }
  527.         /*  Now do extended addition */
  528.         ULARGE_INTEGER uliTotal;
  529.  
  530.         /*  Add ls DWORDs */
  531.         uliTotal.QuadPart  = (DWORDLONG)ud[0].LowPart + p[0].LowPart;
  532.         p[0].LowPart       = uliTotal.LowPart;
  533.  
  534.         /*  Propagate carry */
  535.         uliTotal.LowPart   = uliTotal.HighPart;
  536.         uliTotal.HighPart  = 0;
  537.  
  538.         /*  Add 2nd most ls DWORDs */
  539.         uliTotal.QuadPart += (DWORDLONG)ud[0].HighPart + p[0].HighPart;
  540.         p[0].HighPart      = uliTotal.LowPart;
  541.  
  542.         /*  Propagate carry */
  543.         uliTotal.LowPart   = uliTotal.HighPart;
  544.         uliTotal.HighPart  = 0;
  545.  
  546.         /*  Add MS DWORDLONGs - no carry expected */
  547.         p[1].QuadPart     += ud[1].QuadPart + uliTotal.QuadPart;
  548.  
  549.         /*  Now see if we got a sign change from the addition */
  550.         if ((LONG)p[1].HighPart < 0) {
  551.             bSign = !bSign;
  552.  
  553.             /*  Negate the current value (ugh!) */
  554.             p[0].QuadPart  = ~p[0].QuadPart;
  555.             p[1].QuadPart  = ~p[1].QuadPart;
  556.             p[0].QuadPart += 1;
  557.             p[1].QuadPart += (p[0].QuadPart == 0);
  558.         }
  559.     }
  560.  
  561.     /*  Now for the division */
  562.     if (c < 0) {
  563.         bSign = !bSign;
  564.     }
  565.  
  566.  
  567.     /*  This will catch c == 0 and overflow */
  568.     if (uc <= p[1].QuadPart) {
  569.         return bSign ? (LONGLONG)0x8000000000000000 :
  570.                        (LONGLONG)0x7FFFFFFFFFFFFFFF;
  571.     }
  572.  
  573.     DWORDLONG ullResult;
  574.  
  575.     /*  Do the division */
  576.     /*  If the dividend is a DWORD_LONG use the compiler */
  577.     if (p[1].QuadPart == 0) {
  578.         ullResult = p[0].QuadPart / uc;
  579.         return bSign ? -(LONGLONG)ullResult : (LONGLONG)ullResult;
  580.     }
  581.  
  582.     /*  If the divisor is a DWORD then its simpler */
  583.     ULARGE_INTEGER ulic;
  584.     ulic.QuadPart = uc;
  585.     if (ulic.HighPart == 0) {
  586.         ULARGE_INTEGER uliDividend;
  587.         ULARGE_INTEGER uliResult;
  588.         DWORD dwDivisor = (DWORD)uc;
  589.         // ASSERT(p[1].HighPart == 0 && p[1].LowPart < dwDivisor);
  590.         uliDividend.HighPart = p[1].LowPart;
  591.         uliDividend.LowPart = p[0].HighPart;
  592. #ifndef USE_LARGEINT
  593.         uliResult.HighPart = (DWORD)(uliDividend.QuadPart / dwDivisor);
  594.         p[0].HighPart = (DWORD)(uliDividend.QuadPart % dwDivisor);
  595.         uliResult.LowPart = 0;
  596.         uliResult.QuadPart = p[0].QuadPart / dwDivisor + uliResult.QuadPart;
  597. #else
  598.         /*  NOTE - this routine will take exceptions if
  599.             the result does not fit in a DWORD
  600.         */
  601.         if (uliDividend.QuadPart >= (DWORDLONG)dwDivisor) {
  602.             uliResult.HighPart = EnlargedUnsignedDivide(
  603.                                      uliDividend,
  604.                                      dwDivisor,
  605.                                      &p[0].HighPart);
  606.         } else {
  607.             uliResult.HighPart = 0;
  608.         }
  609.         uliResult.LowPart = EnlargedUnsignedDivide(
  610.                                  p[0],
  611.                                  dwDivisor,
  612.                                  NULL);
  613. #endif
  614.         return bSign ? -(LONGLONG)uliResult.QuadPart :
  615.                         (LONGLONG)uliResult.QuadPart;
  616.     }
  617.  
  618.  
  619.     ullResult = 0;
  620.  
  621.     /*  OK - do long division */
  622.     for (int i = 0; i < 64; i++) {
  623.         ullResult <<= 1;
  624.  
  625.         /*  Shift 128 bit p left 1 */
  626.         p[1].QuadPart <<= 1;
  627.         if ((p[0].HighPart & 0x80000000) != 0) {
  628.             p[1].LowPart++;
  629.         }
  630.         p[0].QuadPart <<= 1;
  631.  
  632.         /*  Compare */
  633.         if (uc <= p[1].QuadPart) {
  634.             p[1].QuadPart -= uc;
  635.             ullResult += 1;
  636.         }
  637.     }
  638.  
  639.     return bSign ? - (LONGLONG)ullResult : (LONGLONG)ullResult;
  640. }
  641.  
  642.  
  643. LONGLONG Int64x32Div32(LONGLONG a, LONG b, LONG c, LONG d)
  644. {
  645.     ULARGE_INTEGER ua;
  646.     DWORD ub;
  647.     DWORD uc;
  648.  
  649.     /*  Compute the absolute values to avoid signed arithmetic problems */
  650.     ua.QuadPart = (DWORDLONG)(a >= 0 ? a : -a);
  651.     ub = (DWORD)(b >= 0 ? b : -b);
  652.     uc = (DWORD)(c >= 0 ? c : -c);
  653.     BOOL bSign = (a < 0) ^ (b < 0);
  654.  
  655.     /*  Do long multiplication */
  656.     ULARGE_INTEGER p0;
  657.     DWORD p1;
  658.     p0.QuadPart  = UInt32x32To64(ua.LowPart, ub);
  659.  
  660.     if (ua.HighPart != 0) {
  661.         ULARGE_INTEGER x;
  662.         x.QuadPart     = UInt32x32To64(ua.HighPart, ub) + p0.HighPart;
  663.         p0.HighPart  = x.LowPart;
  664.         p1   = x.HighPart;
  665.     } else {
  666.         p1 = 0;
  667.     }
  668.  
  669.     if (d != 0) {
  670.         ULARGE_INTEGER ud0;
  671.         DWORD ud1;
  672.  
  673.         if (bSign) {
  674.             //
  675.             //  Cast d to LONGLONG first otherwise -0x80000000 sign extends
  676.             //  incorrectly
  677.             //
  678.             ud0.QuadPart = (DWORDLONG)(-(LONGLONG)d);
  679.             if (d > 0) {
  680.                 /*  -d < 0 */
  681.                 ud1 = (DWORD)-1;
  682.             } else {
  683.                 ud1 = (DWORD)0;
  684.             }
  685.         } else {
  686.             ud0.QuadPart = (DWORDLONG)d;
  687.             if (d < 0) {
  688.                 ud1 = (DWORD)-1;
  689.             } else {
  690.                 ud1 = (DWORD)0;
  691.             }
  692.         }
  693.         /*  Now do extended addition */
  694.         ULARGE_INTEGER uliTotal;
  695.  
  696.         /*  Add ls DWORDs */
  697.         uliTotal.QuadPart  = (DWORDLONG)ud0.LowPart + p0.LowPart;
  698.         p0.LowPart       = uliTotal.LowPart;
  699.  
  700.         /*  Propagate carry */
  701.         uliTotal.LowPart   = uliTotal.HighPart;
  702.         uliTotal.HighPart  = 0;
  703.  
  704.         /*  Add 2nd most ls DWORDs */
  705.         uliTotal.QuadPart += (DWORDLONG)ud0.HighPart + p0.HighPart;
  706.         p0.HighPart      = uliTotal.LowPart;
  707.  
  708.         /*  Add MS DWORDLONGs - no carry expected */
  709.         p1 += ud1 + uliTotal.HighPart;
  710.  
  711.         /*  Now see if we got a sign change from the addition */
  712.         if ((LONG)p1 < 0) {
  713.             bSign = !bSign;
  714.  
  715.             /*  Negate the current value (ugh!) */
  716.             p0.QuadPart  = ~p0.QuadPart;
  717.             p1 = ~p1;
  718.             p0.QuadPart += 1;
  719.             p1 += (p0.QuadPart == 0);
  720.         }
  721.     }
  722.  
  723.     /*  Now for the division */
  724.     if (c < 0) {
  725.         bSign = !bSign;
  726.     }
  727.  
  728.  
  729.     /*  This will catch c == 0 and overflow */
  730.     if (uc <= p1) {
  731.         return bSign ? (LONGLONG)0x8000000000000000 :
  732.                        (LONGLONG)0x7FFFFFFFFFFFFFFF;
  733.     }
  734.  
  735.     /*  Do the division */
  736.  
  737.     /*  If the divisor is a DWORD then its simpler */
  738.     ULARGE_INTEGER uliDividend;
  739.     ULARGE_INTEGER uliResult;
  740.     DWORD dwDivisor = uc;
  741.     uliDividend.HighPart = p1;
  742.     uliDividend.LowPart = p0.HighPart;
  743.     /*  NOTE - this routine will take exceptions if
  744.         the result does not fit in a DWORD
  745.     */
  746.     if (uliDividend.QuadPart >= (DWORDLONG)dwDivisor) {
  747.         uliResult.HighPart = EnlargedUnsignedDivide(
  748.                                  uliDividend,
  749.                                  dwDivisor,
  750.                                  &p0.HighPart);
  751.     } else {
  752.         uliResult.HighPart = 0;
  753.     }
  754.     uliResult.LowPart = EnlargedUnsignedDivide(
  755.                              p0,
  756.                              dwDivisor,
  757.                              NULL);
  758.     return bSign ? -(LONGLONG)uliResult.QuadPart :
  759.                     (LONGLONG)uliResult.QuadPart;
  760. }
  761.  
  762. #ifdef DEBUG
  763. /******************************Public*Routine******************************\
  764. * Debug CCritSec helpers
  765. *
  766. * We provide debug versions of the Constructor, destructor, Lock and Unlock
  767. * routines.  The debug code tracks who owns each critical section by
  768. * maintaining a depth count.
  769. *
  770. * History:
  771. *
  772. \**************************************************************************/
  773.  
  774. CCritSec::CCritSec()
  775. {
  776.     InitializeCriticalSection(&m_CritSec);
  777.     m_currentOwner = m_lockCount = 0;
  778.     m_fTrace = FALSE;
  779. }
  780.  
  781. CCritSec::~CCritSec()
  782. {
  783.     DeleteCriticalSection(&m_CritSec);
  784. }
  785.  
  786. void CCritSec::Lock()
  787. {
  788.     UINT tracelevel=3;
  789.     DWORD us = GetCurrentThreadId();
  790.     DWORD currentOwner = m_currentOwner;
  791.     if (currentOwner && (currentOwner != us)) {
  792.         // already owned, but not by us
  793.         if (m_fTrace) {
  794.             DbgLog((LOG_LOCKING, 2, "Thread %d about to wait for lock %x owned by %d",
  795.                 GetCurrentThreadId(), &m_CritSec, currentOwner));
  796.             tracelevel=2;
  797.         // if we saw the message about waiting for the critical
  798.         // section we ensure we see the message when we get the
  799.         // critical section
  800.         }
  801.     }
  802.     EnterCriticalSection(&m_CritSec);
  803.     if (0 == m_lockCount++) {
  804.         // we now own it for the first time.  Set owner information
  805.         m_currentOwner = us;
  806.     //ASSERT(((PRTL_CRITICAL_SECTION)&m_CritSec)->OwningThread == (HANDLE)m_currentOwner);
  807.     // only valid on NT
  808.         if (m_fTrace) {
  809.             DbgLog((LOG_LOCKING, tracelevel, "Thread %d now owns lock %x", m_currentOwner, &m_CritSec));
  810.         }
  811.     }
  812. }
  813.  
  814. void CCritSec::Unlock() {
  815.     if (0 == --m_lockCount) {
  816.         // about to be unowned
  817.         if (m_fTrace) {
  818.             DbgLog((LOG_LOCKING, 3, "Thread %d releasing lock %x", m_currentOwner, &m_CritSec));
  819.         //ASSERT(((PRTL_CRITICAL_SECTION)&m_CritSec)->OwningThread == (HANDLE)m_currentOwner);
  820.         // only valid on NT
  821.         }
  822.         m_currentOwner = 0;
  823.     }
  824.     LeaveCriticalSection(&m_CritSec);
  825. }
  826.  
  827. void DbgLockTrace(CCritSec * pcCrit, BOOL fTrace)
  828. {
  829.     pcCrit->m_fTrace = fTrace;
  830. }
  831.  
  832. BOOL CritCheckIn(CCritSec * pcCrit)
  833. {
  834.     return (GetCurrentThreadId() == pcCrit->m_currentOwner);
  835. }
  836.  
  837. BOOL CritCheckOut(CCritSec * pcCrit)
  838. {
  839.     return (GetCurrentThreadId() != pcCrit->m_currentOwner);
  840. }
  841. #endif
  842.  
  843.  
  844. // Avoids us dyna-linking to SysAllocString to copy BSTR strings
  845.  
  846. HRESULT WriteBSTR(BSTR *pstrDest, LPCWSTR szSrc)
  847. {
  848.     // count length + terminating null
  849.     int cch = lstrlenW(szSrc) + 1;
  850.  
  851.     // a BSTR is a DWORD length, then a null-terminated UNICODE string.
  852.     // the pointer points *after* the length at the string
  853.     // the length is in bytes, not including the null.
  854.  
  855.     DWORD* pLen = (DWORD*)CoTaskMemAlloc( sizeof(DWORD) + (cch * sizeof(OLECHAR)));
  856.     if (pLen == NULL) {
  857.         return E_OUTOFMEMORY;
  858.     }
  859.     // length (bytes, not chars) does not include terminating null.
  860.     *pLen = (DWORD) (cch-1) * sizeof(OLECHAR);
  861.  
  862.     // BSTR pointer points after the initial DWORD length
  863.     OLECHAR * str = (OLECHAR*) (pLen + 1);
  864.  
  865.     CopyMemory(str, szSrc, cch*sizeof(OLECHAR));
  866.     *pstrDest = str;
  867.  
  868.     return S_OK;
  869. }
  870.  
  871.  
  872. // Free an OLE BSTR through the task allocator
  873.  
  874. HRESULT FreeBSTR(BSTR* pstr)
  875. {
  876.     if (*pstr != NULL) {
  877.         // get pointer to string
  878.         DWORD* p = (DWORD*) (*pstr);
  879.  
  880.         // back up to point at DWORD length
  881.         p--;
  882.  
  883.         // set pointer to null
  884.         *pstr = NULL;
  885.  
  886.         // and free this
  887.         CoTaskMemFree(p);
  888.  
  889.         return S_OK;
  890.     } else {
  891.         return S_FALSE;
  892.     }
  893. }
  894.  
  895.  
  896.  
  897.  
  898.