WXUTIL.H
//==========================================================================; 
// 
//  THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY 
//  KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE 
//  IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR 
//  PURPOSE. 
// 
//  Copyright (c) 1992 - 1997  Microsoft Corporation.  All Rights Reserved. 
// 
//--------------------------------------------------------------------------; 
 
// 
// helper classes and functions for building multimedia filters 
// 
 
#ifndef __WXUTIL__ 
#define __WXUTIL__ 
 
// eliminate spurious "statement has no effect" warnings. 
#pragma warning(disable: 4705) 
 
// wrapper for whatever critical section we have 
class CCritSec { 
 
    // make copy constructor and assignment operator inaccessible 
 
    CCritSec(const CCritSec &refCritSec); 
    CCritSec &operator=(const CCritSec &refCritSec); 
 
    CRITICAL_SECTION m_CritSec; 
 
#ifdef DEBUG 
public: 
    DWORD   m_currentOwner; 
    DWORD   m_lockCount; 
    BOOL    m_fTrace;        // Trace this one 
public: 
    CCritSec(); 
    ~CCritSec(); 
    void Lock(); 
    void Unlock(); 
#else 
 
public: 
    CCritSec() { 
InitializeCriticalSection(&m_CritSec); 
    }; 
 
    ~CCritSec() { 
DeleteCriticalSection(&m_CritSec); 
    }; 
 
    void Lock() { 
EnterCriticalSection(&m_CritSec); 
    }; 
 
    void Unlock() { 
LeaveCriticalSection(&m_CritSec); 
    }; 
#endif 
}; 
 
// 
// To make deadlocks easier to track it is useful to insert in the 
// code an assertion that says whether we own a critical section or 
// not.  We make the routines that do the checking globals to avoid 
// having different numbers of member functions in the debug and 
// retail class implementations of CCritSec.  In addition we provide 
// a routine that allows usage of specific critical sections to be 
// traced.  This is NOT on by default - there are far too many. 
// 
 
#ifdef DEBUG 
    BOOL WINAPI CritCheckIn(CCritSec * pcCrit); 
    BOOL WINAPI CritCheckOut(CCritSec * pcCrit); 
    void WINAPI DbgLockTrace(BOOL fTrace); 
#else 
    #define CritCheckIn(x) TRUE 
    #define CritCheckOut(x) TRUE 
    #define DbgLockTrace(pc, fT) 
#endif 
 
 
// locks a critical section, and unlocks it automatically 
// when the lock goes out of scope 
class CAutoLock { 
 
    // make copy constructor and assignment operator inaccessible 
 
    CAutoLock(const CAutoLock &refAutoLock); 
    CAutoLock &operator=(const CAutoLock &refAutoLock); 
 
protected: 
    CCritSec * m_pLock; 
 
public: 
    CAutoLock(CCritSec * plock) 
    { 
        m_pLock = plock; 
        m_pLock->Lock(); 
    }; 
 
    ~CAutoLock() { 
        m_pLock->Unlock(); 
    }; 
}; 
 
 
 
// wrapper for event objects 
class CAMEvent 
{ 
 
    // make copy constructor and assignment operator inaccessible 
 
    CAMEvent(const CAMEvent &refEvent); 
    CAMEvent &operator=(const CAMEvent &refEvent); 
 
protected: 
    HANDLE m_hEvent; 
public: 
    CAMEvent(BOOL fManualReset = FALSE); 
    ~CAMEvent(); 
 
    // Cast to HANDLE - we don't support this as an lvalue 
    operator HANDLE () const { return m_hEvent; }; 
 
    void Set() { SetEvent(m_hEvent); }; 
    BOOL Wait(DWORD dwTimeout = INFINITE) { 
return (WaitForSingleObject(m_hEvent, dwTimeout) == WAIT_OBJECT_0); 
    }; 
    void Reset() { ResetEvent(m_hEvent); }; 
    BOOL Check() { return Wait(0); }; 
}; 
 
 
// wrapper for event objects that do message processing 
// This adds ONE method to the CAMEvent object to allow sent 
// messages to be processed while waiting 
 
class CAMMsgEvent : public CAMEvent 
{ 
 
public: 
 
    // Allow SEND messages to be processed while waiting 
    BOOL WaitMsg(DWORD dwTimeout = INFINITE); 
}; 
 
// old name supported for the time being 
#define CTimeoutEvent CAMEvent 
 
// support for a worker thread 
 
// simple thread class supports creation of worker thread, synchronization 
// and communication. Can be derived to simplify parameter passing 
class AM_NOVTABLE CAMThread { 
 
    // make copy constructor and assignment operator inaccessible 
 
    CAMThread(const CAMThread &refThread); 
    CAMThread &operator=(const CAMThread &refThread); 
 
    CAMEvent m_EventSend; 
    CAMEvent m_EventComplete; 
 
    DWORD m_dwParam; 
    DWORD m_dwReturnVal; 
 
protected: 
    HANDLE m_hThread; 
 
    // thread will run this function on startup 
    // must be supplied by derived class 
    virtual DWORD ThreadProc() = 0; 
 
 
public: 
    CAMThread(); 
    ~CAMThread(); 
 
    CCritSec m_AccessLock;// locks access by client threads 
    CCritSec m_WorkerLock;// locks access to shared objects 
 
    // thread initially runs this. param is actually 'this'. function 
    // just gets this and calls ThreadProc 
    static DWORD WINAPI InitialThreadProc(LPVOID pv); 
 
    // start thread running  - error if already running 
    BOOL Create(); 
 
    // signal the thread, and block for a response 
    // 
    DWORD CallWorker(DWORD); 
 
    // accessor thread calls this when done with thread (having told thread 
    // to exit) 
    void Close() { 
        HANDLE hThread = (HANDLE)InterlockedExchange((LONG *)&m_hThread, 0); 
        if (hThread) { 
            WaitForSingleObject(hThread, INFINITE); 
            CloseHandle(hThread); 
        } 
    }; 
 
    // ThreadExists 
    // Return TRUE if the thread exists. FALSE otherwise 
    BOOL ThreadExists(void) const 
    { 
        if (m_hThread == 0) { 
            return FALSE; 
        } else { 
            return TRUE; 
        } 
    } 
 
    // wait for the next request 
    DWORD GetRequest(); 
 
    // is there a request? 
    BOOL CheckRequest(DWORD * pParam); 
 
    // reply to the request 
    void Reply(DWORD); 
 
    // If you want to do WaitForMultipleObjects you'll need to include 
    // this handle in your wait list or you won't be responsive 
    HANDLE GetRequestHandle() const { return m_EventSend; }; 
 
    // Find out what the request was 
    DWORD GetRequestParam() const { return m_dwParam; }; 
}; 
 
 
// CQueue 
// 
// Implements a simple Queue ADT.  The queue contains a finite number of 
// objects, access to which is controlled by a semaphore.  The semaphore 
// is created with an initial count (N).  Each time an object is added 
// a call to WaitForSingleObject is made on the semaphore's handle.  When 
// this function returns a slot has been reserved in the queue for the new 
// object.  If no slots are available the function blocks until one becomes 
// available.  Each time an object is removed from the queue ReleaseSemaphore 
// is called on the semaphore's handle, thus freeing a slot in the queue. 
// If no objects are present in the queue the function blocks until an 
// object has been added. 
 
#define DEFAULT_QUEUESIZE   2 
 
template <class T> class CQueue { 
private: 
    HANDLE          hSemPut;        // Semaphore controlling queue "putting" 
    HANDLE          hSemGet;        // Semaphore controlling queue "getting" 
    CRITICAL_SECTION CritSect;      // Thread seriallization 
    int             nMax;           // Max objects allowed in queue 
    int             iNextPut;       // Array index of next "PutMsg" 
    int             iNextGet;       // Array index of next "GetMsg" 
    T              *QueueObjects;   // Array of objects (ptr's to void) 
 
    void Initialize(int n) { 
        iNextPut = iNextGet = 0; 
        nMax = n; 
        InitializeCriticalSection(&CritSect); 
        hSemPut = CreateSemaphore(NULL, n, n, NULL); 
        hSemGet = CreateSemaphore(NULL, 0, n, NULL); 
        QueueObjects = new T[n]; 
    } 
 
 
public: 
    CQueue(int n) { 
        Initialize(n); 
    } 
 
    CQueue() { 
        Initialize(DEFAULT_QUEUESIZE); 
    } 
 
    ~CQueue() { 
        delete [] QueueObjects; 
        DeleteCriticalSection(&CritSect); 
        CloseHandle(hSemPut); 
        CloseHandle(hSemGet); 
    } 
 
    T GetQueueObject() { 
        int iSlot; 
        T Object; 
        LONG lPrevious; 
 
        // Wait for someone to put something on our queue, returns straight 
        // away is there is already an object on the queue. 
        // 
        WaitForSingleObject(hSemGet, INFINITE); 
 
        EnterCriticalSection(&CritSect); 
        iSlot = iNextGet++ % nMax; 
        Object = QueueObjects[iSlot]; 
        LeaveCriticalSection(&CritSect); 
 
        // Release anyone waiting to put an object onto our queue as there 
        // is now space available in the queue. 
        // 
        ReleaseSemaphore(hSemPut, 1L, &lPrevious); 
        return Object; 
    } 
 
    void PutQueueObject(T Object) { 
        int iSlot; 
        LONG lPrevious; 
 
        // Wait for someone to get something from our queue, returns straight 
        // away is there is already an empty slot on the queue. 
        // 
        WaitForSingleObject(hSemPut, INFINITE); 
 
        EnterCriticalSection(&CritSect); 
        iSlot = iNextPut++ % nMax; 
        QueueObjects[iSlot] = Object; 
        LeaveCriticalSection(&CritSect); 
 
        // Release anyone waiting to remove an object from our queue as there 
        // is now an object available to be removed. 
        // 
        ReleaseSemaphore(hSemGet, 1L, &lPrevious); 
    } 
}; 
 
// miscellaneous string conversion functions 
// NOTE: as we need to use the same binaries on Win95 as on NT this code should 
// be compiled WITHOUT unicode being defined.  Otherwise we will not pick up 
// these internal routines and the binary will not run on Win95. 
 
#ifndef UNICODE 
#define wsprintfW wsprintfWInternal 
int WINAPIV wsprintfWInternal(LPWSTR, LPCWSTR, ...); 
 
#define lstrcpyW lstrcpyWInternal 
LPWSTR 
WINAPI 
lstrcpyWInternal( 
    LPWSTR lpString1, 
    LPCWSTR lpString2 
    ); 
#define lstrcpynW lstrcpynWInternal 
LPWSTR 
WINAPI 
lstrcpynWInternal( 
    LPWSTR lpString1, 
    LPCWSTR lpString2, 
    int     iMaxLength 
    ); 
#define lstrcmpW lstrcmpWInternal 
int 
WINAPI 
lstrcmpWInternal( 
    LPCWSTR lpString1, 
    LPCWSTR lpString2 
    ); 
#define lstrcmpiW lstrcmpiWInternal 
int 
WINAPI 
lstrcmpiWInternal( 
    LPCWSTR lpString1, 
    LPCWSTR lpString2 
    ); 
#define lstrlenW lstrlenWInternal 
int 
WINAPI 
lstrlenWInternal( 
    LPCWSTR lpString 
    ); 
#endif 
 
extern "C" 
void * __stdcall memmoveInternal(void *, const void *, size_t); 
 
inline void * __cdecl memchrInternal(const void *buf, int chr, size_t cnt) 
{ 
#ifdef _X86_ 
    void *pRet = NULL; 
 
    _asm { 
        cld                 // make sure we get the direction right 
        mov     ecx, cnt    // num of bytes to scan 
        mov     edi, buf    // pointer byte stream 
        mov     eax, chr    // byte to scan for 
        repne   scasb       // look for the byte in the byte stream 
        jnz     exit_memchr // Z flag set if byte found 
        dec     edi         // scasb always increments edi even when it 
                            // finds the required byte 
        mov     pRet, edi 
exit_memchr: 
    } 
    return pRet; 
 
#else 
    while ( cnt && (*(unsigned char *)buf != (unsigned char)chr) ) { 
        buf = (unsigned char *)buf + 1; 
        cnt--; 
    } 
 
    return(cnt ? (void *)buf : NULL); 
#endif 
} 
 
void WINAPI IntToWstr(int i, LPWSTR wstr); 
 
#define WstrToInt(sz) atoiW(sz) 
 
inline int atoiW(const WCHAR *sz) 
{ 
    int i = 0; 
 
    while (*sz && *sz >= L'0' && *sz <= L'9') 
    i = i*10 + *sz++ - L'0'; 
     
    return i;     
} 
 
inline int WINAPI atoiA(const CHAR *sz) 
{ 
    int i = 0; 
 
    while (*sz && *sz >= '0' && *sz <= '9') 
    i = i*10 + *sz++ - '0'; 
     
    return i;     
} 
 
#ifdef UNICODE 
#define atoi    atoiW 
#else 
#define atoi    atoiA 
#endif 
 
 
 
// These are available to help managing bitmap VIDEOINFOHEADER media structures 
 
extern const DWORD bits555[3]; 
extern const DWORD bits565[3]; 
extern const DWORD bits888[3]; 
 
// These help convert between VIDEOINFOHEADER and BITMAPINFO structures 
 
STDAPI_(const GUID) GetTrueColorType(const BITMAPINFOHEADER *pbmiHeader); 
STDAPI_(const GUID) GetBitmapSubtype(const BITMAPINFOHEADER *pbmiHeader); 
STDAPI_(WORD) GetBitCount(const GUID *pSubtype); 
STDAPI_(TCHAR *) GetSubtypeName(const GUID *pSubtype); 
STDAPI_(LONG) GetBitmapFormatSize(const BITMAPINFOHEADER *pHeader); 
STDAPI_(DWORD) GetBitmapSize(const BITMAPINFOHEADER *pHeader); 
STDAPI_(BOOL) ContainsPalette(const VIDEOINFOHEADER *pVideoInfo); 
STDAPI_(const RGBQUAD *) GetBitmapPalette(const VIDEOINFOHEADER *pVideoInfo); 
 
 
// Compares two interfaces and returns TRUE if they are on the same object 
BOOL WINAPI IsEqualObject(IUnknown *pFirst, IUnknown *pSecond); 
 
// This is for comparing pins 
#define EqualPins(pPin1, pPin2) IsEqualObject(pPin1, pPin2) 
 
 
// Arithmetic helper functions 
 
// Compute (a * b + rnd) / c 
LONGLONG WINAPI llMulDiv(LONGLONG a, LONGLONG b, LONGLONG c, LONGLONG rnd); 
LONGLONG WINAPI Int64x32Div32(LONGLONG a, LONG b, LONG c, LONG rnd); 
 
 
// Avoids us dyna-linking to SysAllocString to copy BSTR strings 
STDAPI WriteBSTR(BSTR * pstrDest, LPCWSTR szSrc); 
STDAPI FreeBSTR(BSTR* pstr); 
 
// Return a wide string - allocating memory for it 
// Returns: 
//    S_OK          - no error 
//    E_POINTER     - ppszReturn == NULL 
//    E_OUTOFMEMORY - can't allocate memory for returned string 
STDAPI AMGetWideString(LPCWSTR pszString, LPWSTR *ppszReturn); 
 
// Special wait for objects owning windows 
DWORD WINAPI WaitDispatchingMessages(HANDLE hObject, DWORD dwWait, HWND hwnd = NULL, UINT uMsg = 0); 
#endif /* __WXUTIL__ */