Leaked source code of windows server 2003
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.

1165 lines
30 KiB

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