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