294 lines
7.1 KiB
C
294 lines
7.1 KiB
C
|
/*****************************************************************************
|
||
|
*
|
||
|
* (C) COPYRIGHT MICROSOFT CORPORATION, 2000
|
||
|
*
|
||
|
* TITLE: w32utils.h
|
||
|
*
|
||
|
* VERSION: 1.0
|
||
|
*
|
||
|
* AUTHOR: LazarI
|
||
|
*
|
||
|
* DATE: 23-Dec-2000
|
||
|
*
|
||
|
* DESCRIPTION: Win32 templates & utilities
|
||
|
*
|
||
|
*****************************************************************************/
|
||
|
|
||
|
#ifndef _W32UTILS_H
|
||
|
#define _W32UTILS_H
|
||
|
|
||
|
// the generic smart pointers & handles
|
||
|
#include "gensph.h"
|
||
|
|
||
|
////////////////////////////////////////////////
|
||
|
//
|
||
|
// class CSimpleWndSubclass
|
||
|
//
|
||
|
// class implementing simple window subclassing
|
||
|
// (Windows specific classes)
|
||
|
//
|
||
|
typedef LRESULT type_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||
|
template <class inheritorClass>
|
||
|
class CSimpleWndSubclass
|
||
|
{
|
||
|
WNDPROC m_wndDefProc;
|
||
|
static LRESULT CALLBACK _ThunkWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||
|
public:
|
||
|
CSimpleWndSubclass(): m_hwnd(NULL), m_wndDefProc(NULL) { }
|
||
|
CSimpleWndSubclass(HWND hwnd): m_hwnd(NULL), m_wndDefProc(NULL) { Attach(hwnd); }
|
||
|
~CSimpleWndSubclass() { Detach(); }
|
||
|
|
||
|
// attach/detach
|
||
|
BOOL IsAttached() const;
|
||
|
BOOL Attach(HWND hwnd);
|
||
|
BOOL Detach();
|
||
|
|
||
|
// default subclass proc
|
||
|
LRESULT WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||
|
|
||
|
// default proc(s)
|
||
|
LRESULT DefWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||
|
LRESULT DefDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||
|
|
||
|
HWND m_hwnd;
|
||
|
};
|
||
|
|
||
|
////////////////////////////////////////////////
|
||
|
//
|
||
|
// class COleComInitializer
|
||
|
//
|
||
|
// smart OLE2, COM initializer - just declare
|
||
|
// an instance wherever need to use COM, OLE2
|
||
|
//
|
||
|
class COleComInitializer
|
||
|
{
|
||
|
public:
|
||
|
COleComInitializer(BOOL bOleInit = FALSE);
|
||
|
~COleComInitializer();
|
||
|
operator BOOL () const;
|
||
|
|
||
|
private:
|
||
|
HRESULT m_hr;
|
||
|
BOOL m_bOleInit;
|
||
|
};
|
||
|
|
||
|
////////////////////////////////////////////////
|
||
|
//
|
||
|
// class CDllLoader
|
||
|
//
|
||
|
// smart DLL loader - calls LoadLibrary
|
||
|
// FreeLibrary for you.
|
||
|
//
|
||
|
class CDllLoader
|
||
|
{
|
||
|
public:
|
||
|
CDllLoader(LPCTSTR pszDllName);
|
||
|
~CDllLoader();
|
||
|
operator BOOL () const;
|
||
|
FARPROC GetProcAddress( LPCSTR lpProcName );
|
||
|
FARPROC GetProcAddress( WORD wProcOrd );
|
||
|
|
||
|
private:
|
||
|
HMODULE m_hLib;
|
||
|
};
|
||
|
|
||
|
////////////////////////////////////////////////
|
||
|
// class CCookiesHolder
|
||
|
//
|
||
|
// this a utility class which allows us to pass more
|
||
|
// than one pointer through a single cookie (pointer).
|
||
|
//
|
||
|
class CCookiesHolder
|
||
|
{
|
||
|
public:
|
||
|
// construction/destruction
|
||
|
CCookiesHolder();
|
||
|
CCookiesHolder(UINT nCount);
|
||
|
~CCookiesHolder();
|
||
|
|
||
|
// sets the count
|
||
|
BOOL SetCount(UINT uCount);
|
||
|
|
||
|
// returns the number of cookies here
|
||
|
UINT GetCount() const
|
||
|
{ return m_uCount; }
|
||
|
|
||
|
// returns the cookie at this position
|
||
|
template <class pType>
|
||
|
pType GetCookie(UINT iIndex) const
|
||
|
{
|
||
|
ASSERT(iIndex < m_uCount);
|
||
|
return reinterpret_cast<pType>(m_pCookies[iIndex]);
|
||
|
}
|
||
|
|
||
|
// returns the previous cookie at this position
|
||
|
template <class pType>
|
||
|
pType SetCookie(UINT iIndex, pType pCookie)
|
||
|
{
|
||
|
ASSERT(iIndex < m_uCount);
|
||
|
pType pReturn = reinterpret_cast<pType>(m_pCookies[iIndex]);
|
||
|
m_pCookies[iIndex] = reinterpret_cast<LPVOID>(pCookie);
|
||
|
return pReturn;
|
||
|
}
|
||
|
|
||
|
// const & non-const operators []
|
||
|
LPVOID operator [] (UINT iIndex) const
|
||
|
{
|
||
|
ASSERT(iIndex < m_uCount);
|
||
|
return m_pCookies[iIndex];
|
||
|
}
|
||
|
LPVOID& operator [] (UINT iIndex)
|
||
|
{
|
||
|
ASSERT(iIndex < m_uCount);
|
||
|
return m_pCookies[iIndex];
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
UINT m_uCount;
|
||
|
LPVOID *m_pCookies;
|
||
|
};
|
||
|
|
||
|
////////////////////////////////////////////////
|
||
|
//
|
||
|
// template class CScopeLocker<TLOCK>
|
||
|
//
|
||
|
template <class TLOCK>
|
||
|
class CScopeLocker
|
||
|
{
|
||
|
public:
|
||
|
CScopeLocker(TLOCK &lock):
|
||
|
m_Lock(lock), m_bLocked(false)
|
||
|
{ m_bLocked = (m_Lock && m_Lock.Lock()); }
|
||
|
|
||
|
~CScopeLocker()
|
||
|
{ if (m_bLocked) m_Lock.Unlock(); }
|
||
|
|
||
|
operator bool () const
|
||
|
{ return m_bLocked; }
|
||
|
|
||
|
private:
|
||
|
bool m_bLocked;
|
||
|
TLOCK &m_Lock;
|
||
|
};
|
||
|
|
||
|
////////////////////////////////////////////////
|
||
|
//
|
||
|
// class CCSLock - win32 critical section lock.
|
||
|
//
|
||
|
class CCSLock
|
||
|
{
|
||
|
public:
|
||
|
// CCSLock::Locker should be used as locker class.
|
||
|
typedef CScopeLocker<CCSLock> Locker;
|
||
|
|
||
|
CCSLock(): m_bInitialized(false)
|
||
|
{
|
||
|
for (;;)
|
||
|
{
|
||
|
__try
|
||
|
{
|
||
|
// InitializeCriticalSection may rise STATUS_NO_MEMORY exception
|
||
|
// in low memory conditions (according the SDK)
|
||
|
InitializeCriticalSection(&m_CS);
|
||
|
m_bInitialized = true;
|
||
|
return;
|
||
|
}
|
||
|
__except(EXCEPTION_EXECUTE_HANDLER) {}
|
||
|
Sleep(100);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
~CCSLock()
|
||
|
{
|
||
|
if (m_bInitialized)
|
||
|
{
|
||
|
// delete the critical section only if initialized successfully
|
||
|
DeleteCriticalSection(&m_CS);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
operator bool () const
|
||
|
{
|
||
|
return m_bInitialized;
|
||
|
}
|
||
|
|
||
|
bool Lock()
|
||
|
{
|
||
|
for (;;)
|
||
|
{
|
||
|
__try
|
||
|
{
|
||
|
// EnterCriticalSection may rise STATUS_NO_MEMORY exception
|
||
|
// in low memory conditions (this may happen if there is contention
|
||
|
// and ntdll can't allocate the wait semaphore)
|
||
|
EnterCriticalSection(&m_CS);
|
||
|
return true;
|
||
|
}
|
||
|
__except(EXCEPTION_EXECUTE_HANDLER) {}
|
||
|
Sleep(100);
|
||
|
}
|
||
|
|
||
|
// we should never end up here either way
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
void Unlock()
|
||
|
{
|
||
|
// Unlock() should be called *ONLY* if the corresponding
|
||
|
// Lock() call has succeeded.
|
||
|
LeaveCriticalSection(&m_CS);
|
||
|
}
|
||
|
|
||
|
#if DBG
|
||
|
// debug code...
|
||
|
bool bInside() const
|
||
|
{
|
||
|
return (m_bInitialized && m_CS.OwningThread == DWORD2PTR(GetCurrentThreadId(), HANDLE));
|
||
|
}
|
||
|
bool bOutside() const
|
||
|
{
|
||
|
return (m_bInitialized && m_CS.OwningThread != DWORD2PTR(GetCurrentThreadId(), HANDLE));
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
private:
|
||
|
bool m_bInitialized;
|
||
|
CRITICAL_SECTION m_CS;
|
||
|
};
|
||
|
|
||
|
////////////////////////////////////////////////
|
||
|
//
|
||
|
// class CSemaphoreLock - simple semaphore lock.
|
||
|
//
|
||
|
class CSemaphoreLock
|
||
|
{
|
||
|
public:
|
||
|
typedef CScopeLocker<CSemaphoreLock> Locker;
|
||
|
|
||
|
CSemaphoreLock() { }
|
||
|
~CSemaphoreLock() { }
|
||
|
|
||
|
void Lock() { ASSERT(m_shSemaphore); WaitForSingleObject(m_shSemaphore, INFINITE); }
|
||
|
void Unlock() { ASSERT(m_shSemaphore); ReleaseSemaphore(m_shSemaphore, 1, NULL); }
|
||
|
|
||
|
HRESULT Create(
|
||
|
LONG lInitialCount, // initial count
|
||
|
LONG lMaximumCount, // maximum count
|
||
|
LPCTSTR lpName = NULL, // object name
|
||
|
LPSECURITY_ATTRIBUTES lpSemaphoreAttributes = NULL // SD
|
||
|
)
|
||
|
{
|
||
|
m_shSemaphore = CreateSemaphore(lpSemaphoreAttributes, lInitialCount, lMaximumCount, lpName);
|
||
|
return m_shSemaphore ? S_OK : E_OUTOFMEMORY;
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
CAutoHandleNT m_shSemaphore;
|
||
|
};
|
||
|
|
||
|
// include the implementation of the template classes here
|
||
|
#include "w32utils.inl"
|
||
|
|
||
|
#endif // endif _W32UTILS_H
|
||
|
|