1
0

wxutil.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532
  1. //------------------------------------------------------------------------------
  2. // File: WXUtil.h
  3. //
  4. // Desc: DirectShow base classes - defines helper classes and functions for
  5. // building multimedia filters.
  6. //
  7. // Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
  8. //------------------------------------------------------------------------------
  9. #ifndef __WXUTIL__
  10. #define __WXUTIL__
  11. // eliminate spurious "statement has no effect" warnings.
  12. #pragma warning(disable: 4705)
  13. // wrapper for whatever critical section we have
  14. class CCritSec {
  15. // make copy constructor and assignment operator inaccessible
  16. CCritSec(const CCritSec &refCritSec);
  17. CCritSec &operator=(const CCritSec &refCritSec);
  18. CRITICAL_SECTION m_CritSec;
  19. #ifdef DEBUG
  20. public:
  21. DWORD m_currentOwner;
  22. DWORD m_lockCount;
  23. BOOL m_fTrace; // Trace this one
  24. public:
  25. CCritSec();
  26. ~CCritSec();
  27. void Lock();
  28. void Unlock();
  29. #else
  30. public:
  31. CCritSec() {
  32. InitializeCriticalSection(&m_CritSec);
  33. };
  34. ~CCritSec() {
  35. DeleteCriticalSection(&m_CritSec);
  36. };
  37. void Lock() {
  38. EnterCriticalSection(&m_CritSec);
  39. };
  40. void Unlock() {
  41. LeaveCriticalSection(&m_CritSec);
  42. };
  43. #endif
  44. };
  45. //
  46. // To make deadlocks easier to track it is useful to insert in the
  47. // code an assertion that says whether we own a critical section or
  48. // not. We make the routines that do the checking globals to avoid
  49. // having different numbers of member functions in the debug and
  50. // retail class implementations of CCritSec. In addition we provide
  51. // a routine that allows usage of specific critical sections to be
  52. // traced. This is NOT on by default - there are far too many.
  53. //
  54. #ifdef DEBUG
  55. BOOL WINAPI CritCheckIn(CCritSec * pcCrit);
  56. BOOL WINAPI CritCheckIn(const CCritSec * pcCrit);
  57. BOOL WINAPI CritCheckOut(CCritSec * pcCrit);
  58. BOOL WINAPI CritCheckOut(const CCritSec * pcCrit);
  59. void WINAPI DbgLockTrace(CCritSec * pcCrit, BOOL fTrace);
  60. #else
  61. #define CritCheckIn(x) TRUE
  62. #define CritCheckOut(x) TRUE
  63. #define DbgLockTrace(pc, fT)
  64. #endif
  65. // locks a critical section, and unlocks it automatically
  66. // when the lock goes out of scope
  67. class CAutoLock {
  68. // make copy constructor and assignment operator inaccessible
  69. CAutoLock(const CAutoLock &refAutoLock);
  70. CAutoLock &operator=(const CAutoLock &refAutoLock);
  71. protected:
  72. CCritSec * m_pLock;
  73. public:
  74. CAutoLock(CCritSec * plock)
  75. {
  76. m_pLock = plock;
  77. m_pLock->Lock();
  78. };
  79. ~CAutoLock() {
  80. m_pLock->Unlock();
  81. };
  82. };
  83. // wrapper for event objects
  84. class CAMEvent
  85. {
  86. // make copy constructor and assignment operator inaccessible
  87. CAMEvent(const CAMEvent &refEvent);
  88. CAMEvent &operator=(const CAMEvent &refEvent);
  89. protected:
  90. HANDLE m_hEvent;
  91. public:
  92. CAMEvent(BOOL fManualReset = FALSE, __inout_opt HRESULT *phr = NULL);
  93. CAMEvent(__inout_opt HRESULT *phr);
  94. ~CAMEvent();
  95. // Cast to HANDLE - we don't support this as an lvalue
  96. operator HANDLE () const { return m_hEvent; };
  97. void Set() {EXECUTE_ASSERT(SetEvent(m_hEvent));};
  98. BOOL Wait(DWORD dwTimeout = INFINITE) {
  99. return (WaitForSingleObject(m_hEvent, dwTimeout) == WAIT_OBJECT_0);
  100. };
  101. void Reset() { ResetEvent(m_hEvent); };
  102. BOOL Check() { return Wait(0); };
  103. };
  104. // wrapper for event objects that do message processing
  105. // This adds ONE method to the CAMEvent object to allow sent
  106. // messages to be processed while waiting
  107. class CAMMsgEvent : public CAMEvent
  108. {
  109. public:
  110. CAMMsgEvent(__inout_opt HRESULT *phr = NULL);
  111. // Allow SEND messages to be processed while waiting
  112. BOOL WaitMsg(DWORD dwTimeout = INFINITE);
  113. };
  114. // old name supported for the time being
  115. #define CTimeoutEvent CAMEvent
  116. // support for a worker thread
  117. #ifdef AM_NOVTABLE
  118. // simple thread class supports creation of worker thread, synchronization
  119. // and communication. Can be derived to simplify parameter passing
  120. class AM_NOVTABLE CAMThread {
  121. // make copy constructor and assignment operator inaccessible
  122. CAMThread(const CAMThread &refThread);
  123. CAMThread &operator=(const CAMThread &refThread);
  124. CAMEvent m_EventSend;
  125. CAMEvent m_EventComplete;
  126. DWORD m_dwParam;
  127. DWORD m_dwReturnVal;
  128. protected:
  129. HANDLE m_hThread;
  130. // thread will run this function on startup
  131. // must be supplied by derived class
  132. virtual DWORD ThreadProc() = 0;
  133. public:
  134. CAMThread(__inout_opt HRESULT *phr = NULL);
  135. virtual ~CAMThread();
  136. CCritSec m_AccessLock; // locks access by client threads
  137. CCritSec m_WorkerLock; // locks access to shared objects
  138. // thread initially runs this. param is actually 'this'. function
  139. // just gets this and calls ThreadProc
  140. static DWORD WINAPI InitialThreadProc(__inout LPVOID pv);
  141. // start thread running - error if already running
  142. BOOL Create();
  143. // signal the thread, and block for a response
  144. //
  145. DWORD CallWorker(DWORD);
  146. // accessor thread calls this when done with thread (having told thread
  147. // to exit)
  148. void Close() {
  149. // Disable warning: Conversion from LONG to PVOID of greater size
  150. #pragma warning(push)
  151. #pragma warning(disable: 4312)
  152. HANDLE hThread = (HANDLE)InterlockedExchangePointer(&m_hThread, 0);
  153. #pragma warning(pop)
  154. if (hThread) {
  155. WaitForSingleObject(hThread, INFINITE);
  156. CloseHandle(hThread);
  157. }
  158. };
  159. // ThreadExists
  160. // Return TRUE if the thread exists. FALSE otherwise
  161. BOOL ThreadExists(void) const
  162. {
  163. if (m_hThread == 0) {
  164. return FALSE;
  165. } else {
  166. return TRUE;
  167. }
  168. }
  169. // wait for the next request
  170. DWORD GetRequest();
  171. // is there a request?
  172. BOOL CheckRequest(__out_opt DWORD * pParam);
  173. // reply to the request
  174. void Reply(DWORD);
  175. // If you want to do WaitForMultipleObjects you'll need to include
  176. // this handle in your wait list or you won't be responsive
  177. HANDLE GetRequestHandle() const { return m_EventSend; };
  178. // Find out what the request was
  179. DWORD GetRequestParam() const { return m_dwParam; };
  180. // call CoInitializeEx (COINIT_DISABLE_OLE1DDE) if
  181. // available. S_FALSE means it's not available.
  182. static HRESULT CoInitializeHelper();
  183. };
  184. #endif // AM_NOVTABLE
  185. // CQueue
  186. //
  187. // Implements a simple Queue ADT. The queue contains a finite number of
  188. // objects, access to which is controlled by a semaphore. The semaphore
  189. // is created with an initial count (N). Each time an object is added
  190. // a call to WaitForSingleObject is made on the semaphore's handle. When
  191. // this function returns a slot has been reserved in the queue for the new
  192. // object. If no slots are available the function blocks until one becomes
  193. // available. Each time an object is removed from the queue ReleaseSemaphore
  194. // is called on the semaphore's handle, thus freeing a slot in the queue.
  195. // If no objects are present in the queue the function blocks until an
  196. // object has been added.
  197. #define DEFAULT_QUEUESIZE 2
  198. template <class T> class CQueue {
  199. private:
  200. HANDLE hSemPut; // Semaphore controlling queue "putting"
  201. HANDLE hSemGet; // Semaphore controlling queue "getting"
  202. CRITICAL_SECTION CritSect; // Thread seriallization
  203. int nMax; // Max objects allowed in queue
  204. int iNextPut; // Array index of next "PutMsg"
  205. int iNextGet; // Array index of next "GetMsg"
  206. T *QueueObjects; // Array of objects (ptr's to void)
  207. void Initialize(int n) {
  208. iNextPut = iNextGet = 0;
  209. nMax = n;
  210. InitializeCriticalSection(&CritSect);
  211. hSemPut = CreateSemaphore(NULL, n, n, NULL);
  212. hSemGet = CreateSemaphore(NULL, 0, n, NULL);
  213. QueueObjects = new T[n];
  214. }
  215. public:
  216. CQueue(int n) {
  217. Initialize(n);
  218. }
  219. CQueue() {
  220. Initialize(DEFAULT_QUEUESIZE);
  221. }
  222. ~CQueue() {
  223. delete [] QueueObjects;
  224. DeleteCriticalSection(&CritSect);
  225. CloseHandle(hSemPut);
  226. CloseHandle(hSemGet);
  227. }
  228. T GetQueueObject() {
  229. int iSlot;
  230. T Object;
  231. LONG lPrevious;
  232. // Wait for someone to put something on our queue, returns straight
  233. // away is there is already an object on the queue.
  234. //
  235. WaitForSingleObject(hSemGet, INFINITE);
  236. EnterCriticalSection(&CritSect);
  237. iSlot = iNextGet++ % nMax;
  238. Object = QueueObjects[iSlot];
  239. LeaveCriticalSection(&CritSect);
  240. // Release anyone waiting to put an object onto our queue as there
  241. // is now space available in the queue.
  242. //
  243. ReleaseSemaphore(hSemPut, 1L, &lPrevious);
  244. return Object;
  245. }
  246. void PutQueueObject(T Object) {
  247. int iSlot;
  248. LONG lPrevious;
  249. // Wait for someone to get something from our queue, returns straight
  250. // away is there is already an empty slot on the queue.
  251. //
  252. WaitForSingleObject(hSemPut, INFINITE);
  253. EnterCriticalSection(&CritSect);
  254. iSlot = iNextPut++ % nMax;
  255. QueueObjects[iSlot] = Object;
  256. LeaveCriticalSection(&CritSect);
  257. // Release anyone waiting to remove an object from our queue as there
  258. // is now an object available to be removed.
  259. //
  260. ReleaseSemaphore(hSemGet, 1L, &lPrevious);
  261. }
  262. };
  263. // Ensures that memory is not read past the length source buffer
  264. // and that memory is not written past the length of the dst buffer
  265. // dst - buffer to copy to
  266. // dst_size - total size of destination buffer
  267. // cb_dst_offset - offset, first byte copied to dst+cb_dst_offset
  268. // src - buffer to copy from
  269. // src_size - total size of source buffer
  270. // cb_src_offset - offset, first byte copied from src+cb_src_offset
  271. // count - number of bytes to copy
  272. //
  273. // Returns:
  274. // S_OK - no error
  275. // E_INVALIDARG - values passed would lead to overrun
  276. HRESULT AMSafeMemMoveOffset(
  277. __in_bcount(dst_size) void * dst,
  278. __in size_t dst_size,
  279. __in DWORD cb_dst_offset,
  280. __in_bcount(src_size) const void * src,
  281. __in size_t src_size,
  282. __in DWORD cb_src_offset,
  283. __in size_t count);
  284. extern "C"
  285. void * __stdcall memmoveInternal(void *, const void *, size_t);
  286. inline void * __cdecl memchrInternal(const void *buf, int chr, size_t cnt)
  287. {
  288. #ifdef _X86_
  289. void *pRet = NULL;
  290. _asm {
  291. cld // make sure we get the direction right
  292. mov ecx, cnt // num of bytes to scan
  293. mov edi, buf // pointer byte stream
  294. mov eax, chr // byte to scan for
  295. repne scasb // look for the byte in the byte stream
  296. jnz exit_memchr // Z flag set if byte found
  297. dec edi // scasb always increments edi even when it
  298. // finds the required byte
  299. mov pRet, edi
  300. exit_memchr:
  301. }
  302. return pRet;
  303. #else
  304. while ( cnt && (*(unsigned char *)buf != (unsigned char)chr) ) {
  305. buf = (unsigned char *)buf + 1;
  306. cnt--;
  307. }
  308. return(cnt ? (void *)buf : NULL);
  309. #endif
  310. }
  311. void WINAPI IntToWstr(int i, __out_ecount(12) LPWSTR wstr);
  312. #define WstrToInt(sz) _wtoi(sz)
  313. #define atoiW(sz) _wtoi(sz)
  314. #define atoiA(sz) atoi(sz)
  315. // These are available to help managing bitmap VIDEOINFOHEADER media structures
  316. extern const DWORD bits555[3];
  317. extern const DWORD bits565[3];
  318. extern const DWORD bits888[3];
  319. // These help convert between VIDEOINFOHEADER and BITMAPINFO structures
  320. STDAPI_(const GUID) GetTrueColorType(const BITMAPINFOHEADER *pbmiHeader);
  321. STDAPI_(const GUID) GetBitmapSubtype(const BITMAPINFOHEADER *pbmiHeader);
  322. STDAPI_(WORD) GetBitCount(const GUID *pSubtype);
  323. // strmbase.lib implements this for compatibility with people who
  324. // managed to link to this directly. we don't want to advertise it.
  325. //
  326. // STDAPI_(/* T */ CHAR *) GetSubtypeName(const GUID *pSubtype);
  327. STDAPI_(CHAR *) GetSubtypeNameA(const GUID *pSubtype);
  328. STDAPI_(WCHAR *) GetSubtypeNameW(const GUID *pSubtype);
  329. #ifdef UNICODE
  330. #define GetSubtypeName GetSubtypeNameW
  331. #else
  332. #define GetSubtypeName GetSubtypeNameA
  333. #endif
  334. STDAPI_(LONG) GetBitmapFormatSize(const BITMAPINFOHEADER *pHeader);
  335. STDAPI_(DWORD) GetBitmapSize(const BITMAPINFOHEADER *pHeader);
  336. #ifdef __AMVIDEO__
  337. STDAPI_(BOOL) ContainsPalette(const VIDEOINFOHEADER *pVideoInfo);
  338. STDAPI_(const RGBQUAD *) GetBitmapPalette(const VIDEOINFOHEADER *pVideoInfo);
  339. #endif // __AMVIDEO__
  340. // Compares two interfaces and returns TRUE if they are on the same object
  341. BOOL WINAPI IsEqualObject(IUnknown *pFirst, IUnknown *pSecond);
  342. // This is for comparing pins
  343. #define EqualPins(pPin1, pPin2) IsEqualObject(pPin1, pPin2)
  344. // Arithmetic helper functions
  345. // Compute (a * b + rnd) / c
  346. LONGLONG WINAPI llMulDiv(LONGLONG a, LONGLONG b, LONGLONG c, LONGLONG rnd);
  347. LONGLONG WINAPI Int64x32Div32(LONGLONG a, LONG b, LONG c, LONG rnd);
  348. // Avoids us dyna-linking to SysAllocString to copy BSTR strings
  349. STDAPI WriteBSTR(__deref_out BSTR * pstrDest, LPCWSTR szSrc);
  350. STDAPI FreeBSTR(__deref_in BSTR* pstr);
  351. // Return a wide string - allocating memory for it
  352. // Returns:
  353. // S_OK - no error
  354. // E_POINTER - ppszReturn == NULL
  355. // E_OUTOFMEMORY - can't allocate memory for returned string
  356. STDAPI AMGetWideString(LPCWSTR pszString, __deref_out LPWSTR *ppszReturn);
  357. // Special wait for objects owning windows
  358. DWORD WINAPI WaitDispatchingMessages(
  359. HANDLE hObject,
  360. DWORD dwWait,
  361. HWND hwnd = NULL,
  362. UINT uMsg = 0,
  363. HANDLE hEvent = NULL);
  364. // HRESULT_FROM_WIN32 converts ERROR_SUCCESS to a success code, but in
  365. // our use of HRESULT_FROM_WIN32, it typically means a function failed
  366. // to call SetLastError(), and we still want a failure code.
  367. //
  368. #define AmHresultFromWin32(x) (MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, x))
  369. // call GetLastError and return an HRESULT value that will fail the
  370. // SUCCEEDED() macro.
  371. HRESULT AmGetLastErrorToHResult(void);
  372. // duplicate of ATL's CComPtr to avoid linker conflicts.
  373. IUnknown* QzAtlComPtrAssign(__deref_inout_opt IUnknown** pp, __in_opt IUnknown* lp);
  374. template <class T>
  375. class QzCComPtr
  376. {
  377. public:
  378. typedef T _PtrClass;
  379. QzCComPtr() {p=NULL;}
  380. QzCComPtr(T* lp)
  381. {
  382. if ((p = lp) != NULL)
  383. p->AddRef();
  384. }
  385. QzCComPtr(const QzCComPtr<T>& lp)
  386. {
  387. if ((p = lp.p) != NULL)
  388. p->AddRef();
  389. }
  390. ~QzCComPtr() {if (p) p->Release();}
  391. void Release() {if (p) p->Release(); p=NULL;}
  392. operator T*() {return (T*)p;}
  393. T& operator*() {ASSERT(p!=NULL); return *p; }
  394. //The assert on operator& usually indicates a bug. If this is really
  395. //what is needed, however, take the address of the p member explicitly.
  396. T** operator&() { ASSERT(p==NULL); return &p; }
  397. T* operator->() { ASSERT(p!=NULL); return p; }
  398. T* operator=(T* lp){return (T*)QzAtlComPtrAssign((IUnknown**)&p, lp);}
  399. T* operator=(const QzCComPtr<T>& lp)
  400. {
  401. return (T*)QzAtlComPtrAssign((IUnknown**)&p, lp.p);
  402. }
  403. #if _MSC_VER>1020
  404. bool operator!(){return (p == NULL);}
  405. #else
  406. BOOL operator!(){return (p == NULL) ? TRUE : FALSE;}
  407. #endif
  408. T* p;
  409. };
  410. MMRESULT CompatibleTimeSetEvent( UINT uDelay, UINT uResolution, __in LPTIMECALLBACK lpTimeProc, DWORD_PTR dwUser, UINT fuEvent );
  411. bool TimeKillSynchronousFlagAvailable( void );
  412. // Helper to replace lstrcpmi
  413. __inline int lstrcmpiLocaleIndependentW(LPCWSTR lpsz1, LPCWSTR lpsz2)
  414. {
  415. return CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, lpsz1, -1, lpsz2, -1) - CSTR_EQUAL;
  416. }
  417. __inline int lstrcmpiLocaleIndependentA(LPCSTR lpsz1, LPCSTR lpsz2)
  418. {
  419. return CompareStringA(LOCALE_INVARIANT, NORM_IGNORECASE, lpsz1, -1, lpsz2, -1) - CSTR_EQUAL;
  420. }
  421. #endif /* __WXUTIL__ */