Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1239 lines
30 KiB

  1. //------------------------------------------------------------------------------
  2. // File: WXUtil.cpp
  3. //
  4. // Desc: DirectShow base classes - implements helper classes for building
  5. // multimedia filters.
  6. //
  7. // Copyright (c) 1992-2001 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. return lpReturn;
  330. }
  331. // Windows 95 doesn't implement this, so we provide an implementation.
  332. LPWSTR
  333. WINAPI
  334. lstrcpynWInternal(
  335. LPWSTR lpString1,
  336. LPCWSTR lpString2,
  337. int iMaxLength
  338. )
  339. {
  340. ASSERT(iMaxLength);
  341. LPWSTR lpReturn = lpString1;
  342. if (iMaxLength) {
  343. while (--iMaxLength && (*lpString1++ = *lpString2++));
  344. // If we ran out of room (which will be the case if
  345. // iMaxLength is now 0) we still need to terminate the
  346. // string.
  347. if (!iMaxLength) *lpString1 = L'\0';
  348. }
  349. return lpReturn;
  350. }
  351. int
  352. WINAPI
  353. lstrcmpWInternal(
  354. LPCWSTR lpString1,
  355. LPCWSTR lpString2
  356. )
  357. {
  358. do {
  359. WCHAR c1 = *lpString1;
  360. WCHAR c2 = *lpString2;
  361. if (c1 != c2)
  362. return (int) c1 - (int) c2;
  363. } while (*lpString1++ && *lpString2++);
  364. return 0;
  365. }
  366. int
  367. WINAPI
  368. lstrcmpiWInternal(
  369. LPCWSTR lpString1,
  370. LPCWSTR lpString2
  371. )
  372. {
  373. do {
  374. WCHAR c1 = *lpString1;
  375. WCHAR c2 = *lpString2;
  376. if (c1 >= L'A' && c1 <= L'Z')
  377. c1 -= (WCHAR) (L'A' - L'a');
  378. if (c2 >= L'A' && c2 <= L'Z')
  379. c2 -= (WCHAR) (L'A' - L'a');
  380. if (c1 != c2)
  381. return (int) c1 - (int) c2;
  382. } while (*lpString1++ && *lpString2++);
  383. return 0;
  384. }
  385. int
  386. WINAPI
  387. lstrlenWInternal(
  388. LPCWSTR lpString
  389. )
  390. {
  391. int i = -1;
  392. while (*(lpString+(++i)))
  393. ;
  394. return i;
  395. }
  396. int WINAPIV wsprintfWInternal(LPWSTR wszOut, LPCWSTR pszFmt, ...)
  397. {
  398. char fmt[256]; // !!!
  399. char ach[256]; // !!!
  400. int i;
  401. va_list va;
  402. va_start(va, pszFmt);
  403. WideCharToMultiByte(GetACP(), 0, pszFmt, -1, fmt, 256, NULL, NULL);
  404. i = wvsprintfA(ach, fmt, va);
  405. va_end(va);
  406. MultiByteToWideChar(CP_ACP, 0, ach, -1, wszOut, i+1);
  407. return i;
  408. }
  409. #else
  410. // need to provide the implementations in unicode for non-unicode
  411. // builds linking with the unicode strmbase.lib
  412. LPWSTR WINAPI lstrcpyWInternal(
  413. LPWSTR lpString1,
  414. LPCWSTR lpString2
  415. )
  416. {
  417. return lstrcpyW(lpString1, lpString2);
  418. }
  419. LPWSTR WINAPI lstrcpynWInternal(
  420. LPWSTR lpString1,
  421. LPCWSTR lpString2,
  422. int iMaxLength
  423. )
  424. {
  425. return lstrcpynW(lpString1, lpString2, iMaxLength);
  426. }
  427. int WINAPI lstrcmpWInternal(
  428. LPCWSTR lpString1,
  429. LPCWSTR lpString2
  430. )
  431. {
  432. return lstrcmpW(lpString1, lpString2);
  433. }
  434. int WINAPI lstrcmpiWInternal(
  435. LPCWSTR lpString1,
  436. LPCWSTR lpString2
  437. )
  438. {
  439. return lstrcmpiW(lpString1, lpString2);
  440. }
  441. int WINAPI lstrlenWInternal(
  442. LPCWSTR lpString
  443. )
  444. {
  445. return lstrlenW(lpString);
  446. }
  447. int WINAPIV wsprintfWInternal(
  448. LPWSTR wszOut, LPCWSTR pszFmt, ...)
  449. {
  450. va_list va;
  451. va_start(va, pszFmt);
  452. int i = wvsprintfW(wszOut, pszFmt, va);
  453. va_end(va);
  454. return i;
  455. }
  456. #endif
  457. // Helper function - convert int to WSTR
  458. void WINAPI IntToWstr(int i, LPWSTR wstr)
  459. {
  460. #ifdef UNICODE
  461. wsprintf(wstr, L"%d", i);
  462. #else
  463. TCHAR temp[32];
  464. wsprintf(temp, "%d", i);
  465. MultiByteToWideChar(CP_ACP, 0, temp, -1, wstr, 32);
  466. #endif
  467. } // IntToWstr
  468. #if 0
  469. void * memchrInternal(const void *pv, int c, size_t sz)
  470. {
  471. BYTE *pb = (BYTE *) pv;
  472. while (sz--) {
  473. if (*pb == c)
  474. return (void *) pb;
  475. pb++;
  476. }
  477. return NULL;
  478. }
  479. #endif
  480. #define MEMORY_ALIGNMENT 4
  481. #define MEMORY_ALIGNMENT_LOG2 2
  482. #define MEMORY_ALIGNMENT_MASK MEMORY_ALIGNMENT - 1
  483. void * __stdcall memmoveInternal(void * dst, const void * src, size_t count)
  484. {
  485. void * ret = dst;
  486. #ifdef _X86_
  487. if (dst <= src || (char *)dst >= ((char *)src + count)) {
  488. /*
  489. * Non-Overlapping Buffers
  490. * copy from lower addresses to higher addresses
  491. */
  492. _asm {
  493. mov esi,src
  494. mov edi,dst
  495. mov ecx,count
  496. cld
  497. mov edx,ecx
  498. and edx,MEMORY_ALIGNMENT_MASK
  499. shr ecx,MEMORY_ALIGNMENT_LOG2
  500. rep movsd
  501. or ecx,edx
  502. jz memmove_done
  503. rep movsb
  504. memmove_done:
  505. }
  506. }
  507. else {
  508. /*
  509. * Overlapping Buffers
  510. * copy from higher addresses to lower addresses
  511. */
  512. _asm {
  513. mov esi,src
  514. mov edi,dst
  515. mov ecx,count
  516. std
  517. add esi,ecx
  518. add edi,ecx
  519. dec esi
  520. dec edi
  521. rep movsb
  522. cld
  523. }
  524. }
  525. #else
  526. MoveMemory(dst, src, count);
  527. #endif
  528. return ret;
  529. }
  530. /* Arithmetic functions to help with time format conversions
  531. */
  532. #ifdef _M_ALPHA
  533. // work around bug in version 12.00.8385 of the alpha compiler where
  534. // UInt32x32To64 sign-extends its arguments (?)
  535. #undef UInt32x32To64
  536. #define UInt32x32To64(a, b) (((ULONGLONG)((ULONG)(a)) & 0xffffffff) * ((ULONGLONG)((ULONG)(b)) & 0xffffffff))
  537. #endif
  538. /* Compute (a * b + d) / c */
  539. LONGLONG WINAPI llMulDiv(LONGLONG a, LONGLONG b, LONGLONG c, LONGLONG d)
  540. {
  541. /* Compute the absolute values to avoid signed arithmetic problems */
  542. ULARGE_INTEGER ua, ub;
  543. DWORDLONG uc;
  544. ua.QuadPart = (DWORDLONG)(a >= 0 ? a : -a);
  545. ub.QuadPart = (DWORDLONG)(b >= 0 ? b : -b);
  546. uc = (DWORDLONG)(c >= 0 ? c : -c);
  547. BOOL bSign = (a < 0) ^ (b < 0);
  548. /* Do long multiplication */
  549. ULARGE_INTEGER p[2];
  550. p[0].QuadPart = UInt32x32To64(ua.LowPart, ub.LowPart);
  551. /* This next computation cannot overflow into p[1].HighPart because
  552. the max number we can compute here is:
  553. (2 ** 32 - 1) * (2 ** 32 - 1) + // ua.LowPart * ub.LowPart
  554. (2 ** 32) * (2 ** 31) * (2 ** 32 - 1) * 2 // x.LowPart * y.HighPart * 2
  555. == 2 ** 96 - 2 ** 64 + (2 ** 64 - 2 ** 33 + 1)
  556. == 2 ** 96 - 2 ** 33 + 1
  557. < 2 ** 96
  558. */
  559. ULARGE_INTEGER x;
  560. x.QuadPart = UInt32x32To64(ua.LowPart, ub.HighPart) +
  561. UInt32x32To64(ua.HighPart, ub.LowPart) +
  562. p[0].HighPart;
  563. p[0].HighPart = x.LowPart;
  564. p[1].QuadPart = UInt32x32To64(ua.HighPart, ub.HighPart) + x.HighPart;
  565. if (d != 0) {
  566. ULARGE_INTEGER ud[2];
  567. if (bSign) {
  568. ud[0].QuadPart = (DWORDLONG)(-d);
  569. if (d > 0) {
  570. /* -d < 0 */
  571. ud[1].QuadPart = (DWORDLONG)(LONGLONG)-1;
  572. } else {
  573. ud[1].QuadPart = (DWORDLONG)0;
  574. }
  575. } else {
  576. ud[0].QuadPart = (DWORDLONG)d;
  577. if (d < 0) {
  578. ud[1].QuadPart = (DWORDLONG)(LONGLONG)-1;
  579. } else {
  580. ud[1].QuadPart = (DWORDLONG)0;
  581. }
  582. }
  583. /* Now do extended addition */
  584. ULARGE_INTEGER uliTotal;
  585. /* Add ls DWORDs */
  586. uliTotal.QuadPart = (DWORDLONG)ud[0].LowPart + p[0].LowPart;
  587. p[0].LowPart = uliTotal.LowPart;
  588. /* Propagate carry */
  589. uliTotal.LowPart = uliTotal.HighPart;
  590. uliTotal.HighPart = 0;
  591. /* Add 2nd most ls DWORDs */
  592. uliTotal.QuadPart += (DWORDLONG)ud[0].HighPart + p[0].HighPart;
  593. p[0].HighPart = uliTotal.LowPart;
  594. /* Propagate carry */
  595. uliTotal.LowPart = uliTotal.HighPart;
  596. uliTotal.HighPart = 0;
  597. /* Add MS DWORDLONGs - no carry expected */
  598. p[1].QuadPart += ud[1].QuadPart + uliTotal.QuadPart;
  599. /* Now see if we got a sign change from the addition */
  600. if ((LONG)p[1].HighPart < 0) {
  601. bSign = !bSign;
  602. /* Negate the current value (ugh!) */
  603. p[0].QuadPart = ~p[0].QuadPart;
  604. p[1].QuadPart = ~p[1].QuadPart;
  605. p[0].QuadPart += 1;
  606. p[1].QuadPart += (p[0].QuadPart == 0);
  607. }
  608. }
  609. /* Now for the division */
  610. if (c < 0) {
  611. bSign = !bSign;
  612. }
  613. /* This will catch c == 0 and overflow */
  614. if (uc <= p[1].QuadPart) {
  615. return bSign ? (LONGLONG)0x8000000000000000 :
  616. (LONGLONG)0x7FFFFFFFFFFFFFFF;
  617. }
  618. DWORDLONG ullResult;
  619. /* Do the division */
  620. /* If the dividend is a DWORD_LONG use the compiler */
  621. if (p[1].QuadPart == 0) {
  622. ullResult = p[0].QuadPart / uc;
  623. return bSign ? -(LONGLONG)ullResult : (LONGLONG)ullResult;
  624. }
  625. /* If the divisor is a DWORD then its simpler */
  626. ULARGE_INTEGER ulic;
  627. ulic.QuadPart = uc;
  628. if (ulic.HighPart == 0) {
  629. ULARGE_INTEGER uliDividend;
  630. ULARGE_INTEGER uliResult;
  631. DWORD dwDivisor = (DWORD)uc;
  632. // ASSERT(p[1].HighPart == 0 && p[1].LowPart < dwDivisor);
  633. uliDividend.HighPart = p[1].LowPart;
  634. uliDividend.LowPart = p[0].HighPart;
  635. #ifndef USE_LARGEINT
  636. uliResult.HighPart = (DWORD)(uliDividend.QuadPart / dwDivisor);
  637. p[0].HighPart = (DWORD)(uliDividend.QuadPart % dwDivisor);
  638. uliResult.LowPart = 0;
  639. uliResult.QuadPart = p[0].QuadPart / dwDivisor + uliResult.QuadPart;
  640. #else
  641. /* NOTE - this routine will take exceptions if
  642. the result does not fit in a DWORD
  643. */
  644. if (uliDividend.QuadPart >= (DWORDLONG)dwDivisor) {
  645. uliResult.HighPart = EnlargedUnsignedDivide(
  646. uliDividend,
  647. dwDivisor,
  648. &p[0].HighPart);
  649. } else {
  650. uliResult.HighPart = 0;
  651. }
  652. uliResult.LowPart = EnlargedUnsignedDivide(
  653. p[0],
  654. dwDivisor,
  655. NULL);
  656. #endif
  657. return bSign ? -(LONGLONG)uliResult.QuadPart :
  658. (LONGLONG)uliResult.QuadPart;
  659. }
  660. ullResult = 0;
  661. /* OK - do long division */
  662. for (int i = 0; i < 64; i++) {
  663. ullResult <<= 1;
  664. /* Shift 128 bit p left 1 */
  665. p[1].QuadPart <<= 1;
  666. if ((p[0].HighPart & 0x80000000) != 0) {
  667. p[1].LowPart++;
  668. }
  669. p[0].QuadPart <<= 1;
  670. /* Compare */
  671. if (uc <= p[1].QuadPart) {
  672. p[1].QuadPart -= uc;
  673. ullResult += 1;
  674. }
  675. }
  676. return bSign ? - (LONGLONG)ullResult : (LONGLONG)ullResult;
  677. }
  678. LONGLONG WINAPI Int64x32Div32(LONGLONG a, LONG b, LONG c, LONG d)
  679. {
  680. ULARGE_INTEGER ua;
  681. DWORD ub;
  682. DWORD uc;
  683. /* Compute the absolute values to avoid signed arithmetic problems */
  684. ua.QuadPart = (DWORDLONG)(a >= 0 ? a : -a);
  685. ub = (DWORD)(b >= 0 ? b : -b);
  686. uc = (DWORD)(c >= 0 ? c : -c);
  687. BOOL bSign = (a < 0) ^ (b < 0);
  688. /* Do long multiplication */
  689. ULARGE_INTEGER p0;
  690. DWORD p1;
  691. p0.QuadPart = UInt32x32To64(ua.LowPart, ub);
  692. if (ua.HighPart != 0) {
  693. ULARGE_INTEGER x;
  694. x.QuadPart = UInt32x32To64(ua.HighPart, ub) + p0.HighPart;
  695. p0.HighPart = x.LowPart;
  696. p1 = x.HighPart;
  697. } else {
  698. p1 = 0;
  699. }
  700. if (d != 0) {
  701. ULARGE_INTEGER ud0;
  702. DWORD ud1;
  703. if (bSign) {
  704. //
  705. // Cast d to LONGLONG first otherwise -0x80000000 sign extends
  706. // incorrectly
  707. //
  708. ud0.QuadPart = (DWORDLONG)(-(LONGLONG)d);
  709. if (d > 0) {
  710. /* -d < 0 */
  711. ud1 = (DWORD)-1;
  712. } else {
  713. ud1 = (DWORD)0;
  714. }
  715. } else {
  716. ud0.QuadPart = (DWORDLONG)d;
  717. if (d < 0) {
  718. ud1 = (DWORD)-1;
  719. } else {
  720. ud1 = (DWORD)0;
  721. }
  722. }
  723. /* Now do extended addition */
  724. ULARGE_INTEGER uliTotal;
  725. /* Add ls DWORDs */
  726. uliTotal.QuadPart = (DWORDLONG)ud0.LowPart + p0.LowPart;
  727. p0.LowPart = uliTotal.LowPart;
  728. /* Propagate carry */
  729. uliTotal.LowPart = uliTotal.HighPart;
  730. uliTotal.HighPart = 0;
  731. /* Add 2nd most ls DWORDs */
  732. uliTotal.QuadPart += (DWORDLONG)ud0.HighPart + p0.HighPart;
  733. p0.HighPart = uliTotal.LowPart;
  734. /* Add MS DWORDLONGs - no carry expected */
  735. p1 += ud1 + uliTotal.HighPart;
  736. /* Now see if we got a sign change from the addition */
  737. if ((LONG)p1 < 0) {
  738. bSign = !bSign;
  739. /* Negate the current value (ugh!) */
  740. p0.QuadPart = ~p0.QuadPart;
  741. p1 = ~p1;
  742. p0.QuadPart += 1;
  743. p1 += (p0.QuadPart == 0);
  744. }
  745. }
  746. /* Now for the division */
  747. if (c < 0) {
  748. bSign = !bSign;
  749. }
  750. /* This will catch c == 0 and overflow */
  751. if (uc <= p1) {
  752. return bSign ? (LONGLONG)0x8000000000000000 :
  753. (LONGLONG)0x7FFFFFFFFFFFFFFF;
  754. }
  755. /* Do the division */
  756. /* If the divisor is a DWORD then its simpler */
  757. ULARGE_INTEGER uliDividend;
  758. ULARGE_INTEGER uliResult;
  759. DWORD dwDivisor = uc;
  760. uliDividend.HighPart = p1;
  761. uliDividend.LowPart = p0.HighPart;
  762. /* NOTE - this routine will take exceptions if
  763. the result does not fit in a DWORD
  764. */
  765. if (uliDividend.QuadPart >= (DWORDLONG)dwDivisor) {
  766. uliResult.HighPart = EnlargedUnsignedDivide(
  767. uliDividend,
  768. dwDivisor,
  769. &p0.HighPart);
  770. } else {
  771. uliResult.HighPart = 0;
  772. }
  773. uliResult.LowPart = EnlargedUnsignedDivide(
  774. p0,
  775. dwDivisor,
  776. NULL);
  777. return bSign ? -(LONGLONG)uliResult.QuadPart :
  778. (LONGLONG)uliResult.QuadPart;
  779. }
  780. #ifdef DEBUG
  781. /******************************Public*Routine******************************\
  782. * Debug CCritSec helpers
  783. *
  784. * We provide debug versions of the Constructor, destructor, Lock and Unlock
  785. * routines. The debug code tracks who owns each critical section by
  786. * maintaining a depth count.
  787. *
  788. * History:
  789. *
  790. \**************************************************************************/
  791. CCritSec::CCritSec()
  792. {
  793. InitializeCriticalSection(&m_CritSec);
  794. m_currentOwner = m_lockCount = 0;
  795. m_fTrace = FALSE;
  796. }
  797. CCritSec::~CCritSec()
  798. {
  799. DeleteCriticalSection(&m_CritSec);
  800. }
  801. void CCritSec::Lock()
  802. {
  803. UINT tracelevel=3;
  804. DWORD us = GetCurrentThreadId();
  805. DWORD currentOwner = m_currentOwner;
  806. if (currentOwner && (currentOwner != us)) {
  807. // already owned, but not by us
  808. if (m_fTrace) {
  809. DbgLog((LOG_LOCKING, 2, TEXT("Thread %d about to wait for lock %x owned by %d"),
  810. GetCurrentThreadId(), &m_CritSec, currentOwner));
  811. tracelevel=2;
  812. // if we saw the message about waiting for the critical
  813. // section we ensure we see the message when we get the
  814. // critical section
  815. }
  816. }
  817. EnterCriticalSection(&m_CritSec);
  818. if (0 == m_lockCount++) {
  819. // we now own it for the first time. Set owner information
  820. m_currentOwner = us;
  821. if (m_fTrace) {
  822. DbgLog((LOG_LOCKING, tracelevel, TEXT("Thread %d now owns lock %x"), m_currentOwner, &m_CritSec));
  823. }
  824. }
  825. }
  826. void CCritSec::Unlock() {
  827. if (0 == --m_lockCount) {
  828. // about to be unowned
  829. if (m_fTrace) {
  830. DbgLog((LOG_LOCKING, 3, TEXT("Thread %d releasing lock %x"), m_currentOwner, &m_CritSec));
  831. }
  832. m_currentOwner = 0;
  833. }
  834. LeaveCriticalSection(&m_CritSec);
  835. }
  836. void WINAPI DbgLockTrace(CCritSec * pcCrit, BOOL fTrace)
  837. {
  838. pcCrit->m_fTrace = fTrace;
  839. }
  840. BOOL WINAPI CritCheckIn(CCritSec * pcCrit)
  841. {
  842. return (GetCurrentThreadId() == pcCrit->m_currentOwner);
  843. }
  844. BOOL WINAPI CritCheckIn(const CCritSec * pcCrit)
  845. {
  846. return (GetCurrentThreadId() == pcCrit->m_currentOwner);
  847. }
  848. BOOL WINAPI CritCheckOut(CCritSec * pcCrit)
  849. {
  850. return (GetCurrentThreadId() != pcCrit->m_currentOwner);
  851. }
  852. BOOL WINAPI CritCheckOut(const CCritSec * pcCrit)
  853. {
  854. return (GetCurrentThreadId() != pcCrit->m_currentOwner);
  855. }
  856. #endif
  857. STDAPI WriteBSTR(BSTR *pstrDest, LPCWSTR szSrc)
  858. {
  859. *pstrDest = SysAllocString( szSrc );
  860. if( !(*pstrDest) ) return E_OUTOFMEMORY;
  861. return NOERROR;
  862. }
  863. STDAPI FreeBSTR(BSTR* pstr)
  864. {
  865. if( *pstr == NULL ) return S_FALSE;
  866. SysFreeString( *pstr );
  867. return NOERROR;
  868. }
  869. // Return a wide string - allocating memory for it
  870. // Returns:
  871. // S_OK - no error
  872. // E_POINTER - ppszReturn == NULL
  873. // E_OUTOFMEMORY - can't allocate memory for returned string
  874. STDAPI AMGetWideString(LPCWSTR psz, LPWSTR *ppszReturn)
  875. {
  876. CheckPointer(ppszReturn, E_POINTER);
  877. ValidateReadWritePtr(ppszReturn, sizeof(LPWSTR));
  878. DWORD nameLen = sizeof(WCHAR) * (lstrlenW(psz)+1);
  879. *ppszReturn = (LPWSTR)CoTaskMemAlloc(nameLen);
  880. if (*ppszReturn == NULL) {
  881. return E_OUTOFMEMORY;
  882. }
  883. CopyMemory(*ppszReturn, psz, nameLen);
  884. return NOERROR;
  885. }
  886. // Waits for the HANDLE hObject. While waiting messages sent
  887. // to windows on our thread by SendMessage will be processed.
  888. // Using this function to do waits and mutual exclusion
  889. // avoids some deadlocks in objects with windows.
  890. // Return codes are the same as for WaitForSingleObject
  891. DWORD WINAPI WaitDispatchingMessages(
  892. HANDLE hObject,
  893. DWORD dwWait,
  894. HWND hwnd,
  895. UINT uMsg,
  896. HANDLE hEvent)
  897. {
  898. BOOL bPeeked = FALSE;
  899. DWORD dwResult;
  900. DWORD dwStart;
  901. DWORD dwThreadPriority;
  902. static UINT uMsgId = 0;
  903. HANDLE hObjects[2] = { hObject, hEvent };
  904. if (dwWait != INFINITE && dwWait != 0) {
  905. dwStart = GetTickCount();
  906. }
  907. for (; ; ) {
  908. DWORD nCount = NULL != hEvent ? 2 : 1;
  909. // Minimize the chance of actually dispatching any messages
  910. // by seeing if we can lock immediately.
  911. dwResult = WaitForMultipleObjects(nCount, hObjects, FALSE, 0);
  912. if (dwResult < WAIT_OBJECT_0 + nCount) {
  913. break;
  914. }
  915. DWORD dwTimeOut = dwWait;
  916. if (dwTimeOut > 10) {
  917. dwTimeOut = 10;
  918. }
  919. dwResult = MsgWaitForMultipleObjects(
  920. nCount,
  921. hObjects,
  922. FALSE,
  923. dwTimeOut,
  924. hwnd == NULL ? QS_SENDMESSAGE :
  925. QS_SENDMESSAGE + QS_POSTMESSAGE);
  926. if (dwResult == WAIT_OBJECT_0 + nCount ||
  927. dwResult == WAIT_TIMEOUT && dwTimeOut != dwWait) {
  928. MSG msg;
  929. if (hwnd != NULL) {
  930. while (PeekMessage(&msg, hwnd, uMsg, uMsg, PM_REMOVE)) {
  931. DispatchMessage(&msg);
  932. }
  933. }
  934. // Do this anyway - the previous peek doesn't flush out the
  935. // messages
  936. PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE);
  937. if (dwWait != INFINITE && dwWait != 0) {
  938. DWORD dwNow = GetTickCount();
  939. // Working with differences handles wrap-around
  940. DWORD dwDiff = dwNow - dwStart;
  941. if (dwDiff > dwWait) {
  942. dwWait = 0;
  943. } else {
  944. dwWait -= dwDiff;
  945. }
  946. dwStart = dwNow;
  947. }
  948. if (!bPeeked) {
  949. // Raise our priority to prevent our message queue
  950. // building up
  951. dwThreadPriority = GetThreadPriority(GetCurrentThread());
  952. if (dwThreadPriority < THREAD_PRIORITY_HIGHEST) {
  953. SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
  954. }
  955. bPeeked = TRUE;
  956. }
  957. } else {
  958. break;
  959. }
  960. }
  961. if (bPeeked) {
  962. SetThreadPriority(GetCurrentThread(), dwThreadPriority);
  963. if (HIWORD(GetQueueStatus(QS_POSTMESSAGE)) & QS_POSTMESSAGE) {
  964. if (uMsgId == 0) {
  965. uMsgId = RegisterWindowMessage(TEXT("AMUnblock"));
  966. }
  967. if (uMsgId != 0) {
  968. MSG msg;
  969. // Remove old ones
  970. while (PeekMessage(&msg, (HWND)-1, uMsgId, uMsgId, PM_REMOVE)) {
  971. }
  972. }
  973. PostThreadMessage(GetCurrentThreadId(), uMsgId, 0, 0);
  974. }
  975. }
  976. return dwResult;
  977. }
  978. HRESULT AmGetLastErrorToHResult()
  979. {
  980. DWORD dwLastError = GetLastError();
  981. if(dwLastError != 0)
  982. {
  983. return HRESULT_FROM_WIN32(dwLastError);
  984. }
  985. else
  986. {
  987. return E_FAIL;
  988. }
  989. }
  990. IUnknown* QzAtlComPtrAssign(IUnknown** pp, IUnknown* lp)
  991. {
  992. if (lp != NULL)
  993. lp->AddRef();
  994. if (*pp)
  995. (*pp)->Release();
  996. *pp = lp;
  997. return lp;
  998. }
  999. /******************************************************************************
  1000. CompatibleTimeSetEvent
  1001. CompatibleTimeSetEvent() sets the TIME_KILL_SYNCHRONOUS flag before calling
  1002. timeSetEvent() if the current operating system supports it. TIME_KILL_SYNCHRONOUS
  1003. is supported on Windows XP and later operating systems.
  1004. Parameters:
  1005. - The same parameters as timeSetEvent(). See timeSetEvent()'s documentation in
  1006. the Platform SDK for more information.
  1007. Return Value:
  1008. - The same return value as timeSetEvent(). See timeSetEvent()'s documentation in
  1009. the Platform SDK for more information.
  1010. ******************************************************************************/
  1011. MMRESULT CompatibleTimeSetEvent( UINT uDelay, UINT uResolution, LPTIMECALLBACK lpTimeProc, DWORD_PTR dwUser, UINT fuEvent )
  1012. {
  1013. #if WINVER >= 0x0501
  1014. {
  1015. static bool fCheckedVersion = false;
  1016. static bool fTimeKillSynchronousFlagAvailable = false;
  1017. if( !fCheckedVersion ) {
  1018. fTimeKillSynchronousFlagAvailable = TimeKillSynchronousFlagAvailable();
  1019. fCheckedVersion = true;
  1020. }
  1021. if( fTimeKillSynchronousFlagAvailable ) {
  1022. fuEvent = fuEvent | TIME_KILL_SYNCHRONOUS;
  1023. }
  1024. }
  1025. #endif // WINVER >= 0x0501
  1026. return timeSetEvent( uDelay, uResolution, lpTimeProc, dwUser, fuEvent );
  1027. }
  1028. bool TimeKillSynchronousFlagAvailable( void )
  1029. {
  1030. OSVERSIONINFO osverinfo;
  1031. osverinfo.dwOSVersionInfoSize = sizeof(osverinfo);
  1032. if( GetVersionEx( &osverinfo ) ) {
  1033. // Windows XP's major version is 5 and its' minor version is 1.
  1034. // timeSetEvent() started supporting the TIME_KILL_SYNCHRONOUS flag
  1035. // in Windows XP.
  1036. if( (osverinfo.dwMajorVersion > 5) ||
  1037. ( (osverinfo.dwMajorVersion == 5) && (osverinfo.dwMinorVersion >= 1) ) ) {
  1038. return true;
  1039. }
  1040. }
  1041. return false;
  1042. }