📄 kmisc.h
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// This source code is licensed under Microsoft Shared Source License
// Version 1.0 for Windows CE.
// For a copy of the license visit http://go.microsoft.com/fwlink/?LinkId=3223.
//
/*++
Module Name:
Kmisc.h
Abstract:
This module contains misc kernel classes like lists, queues, spinlocks...
Husni Roukbi
Notes:
Environment:
Kernel mode only
Revision History:
--*/
#ifndef __KMISC_H__
#define __KMISC_H__
///////////////////////////////
// Defines
///////////////////////////////
#if ! (defined (UNDER_CE) || defined (WINCE_EMULATION))
#define IRP_LE_OFFSET ((ULONG_PTR) ( & ((IRP* ) 0)->Tail.Overlay.ListEntry)) // IRP list entry filed offset is 88 bytes
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// CBaseObj class will be the base class for objects queued in the CxList classes.
//
// Rules for using this base obeject:
// 1) derived object should use SELF_DESTRUCT.
// 2) Use AddRef() right after you reference an object and Release(0 when you are done with the object reference.
// 3) Never delete this object or its derived objects directly. RefCount is incremented to one in constructor.
// Hence, a call to Release() that has no match to AddRef() will trigger deletion
// of this object and its derived objects.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class CBaseObj
{
public:
virtual SELF_DESTRUCT
CBaseObj() {m_RefCount = 1; m_pEvent = NULL;}
virtual LONG AddRef() ;
virtual LONG Release();
private:
LONG m_RefCount; // reference count
protected:
virtual ~CBaseObj(); // will be called only from selfdestruct().
PKEVENT m_pEvent; // cache an event ptr waiting for this object to be deleted.
};
inline CBaseObj::~CBaseObj()
{
ASSERT (m_RefCount == 0);
// _DbgPrintF(DBG_PNP_INFO,("Deleting CBaseObj"));
}
inline LONG CBaseObj::AddRef()
{
return InterlockedIncrement(&m_RefCount);
}
inline LONG CBaseObj::Release()
{
LONG RefCount;
if ((RefCount = InterlockedDecrement(&m_RefCount)) == 0) {
// ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
//
// Cache the event pointer is case something is blocked on
// object deletion.
//
PKEVENT pEvent = m_pEvent;
//
// Call destructor on the parent object.
//
SelfDestruct();
//
// Set the close event if there is one.
//
if (pEvent) {
KeSetEvent(pEvent,IO_NO_INCREMENT,FALSE);
}
}
return RefCount;
}
//
// Smart pointer class. This class makes the assumptiont that the T* being
// assigned to it ALREADY has an AddRef called against it. This means that this
// class will only call T::Release() on pT, never T::AddRef(). This is especially
// important to remember when doing an assinment or contructing this ptr;
//
template<class T> class SmartPtr {
public:
SmartPtr() : pT(NULL) {}
SmartPtr(T* pT) : pT(pT) {}
~SmartPtr()
{
if (pT != NULL) {
pT->Release();
}
}
operator T*() { return pT; }
T* operator ->() const { return pT; }
T& operator *() { return *pT; }
T** operator &() { return &pT; }
bool operator!=(const T* pRightT) const { return pT != pRightT; }
bool operator! (void) const { return pT == NULL; }
bool operator==(const T* pRightT) const { return pT == pRightT; }
bool operator< (const T* pRightT) const { return pT < pRightT; }
T*& operator= (T* pNewT)
{
if (pT != NULL) {
pT->Release();
}
pT = pNewT;
return pT;
}
T* Detach()
{
T* p = pT;
pT = NULL;
return p;
}
protected:
//
// do not want these functions to be invoked
//
SmartPtr(const SmartPtr<T>& lp) { ASSERT(FALSE); }
T*& operator=(const SmartPtr<T>& pNewT)
{
ASSERT(FALSE);
return pT;
}
T* pT;
};
#endif // UNDER_CE
template<class T> class NoRefObject {
public:
void AddRef(T* pT) {}
void Release(T* pT) {}
};
template<class T> class RefObject {
public:
void AddRef(T* pT) { pT->AddRef(); }
void Release(T* pT) { pT->Release(); }
};
#if ! (defined (UNDER_CE) || defined (WINCE_EMULATION))
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// CKSpinLock wraps around spinlocks and hides dispatch level vs. passive level issues..
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class CKSpinLock
{
public:
SELF_DESTRUCT
CKSpinLock(void);
~CKSpinLock(void);
void Lock() { AcquireSpinLock();}
void Unlock() { ReleaseSpinLock();}
KIRQL _AcquireSpinLock(void);
void AcquireSpinLock(void);
void ReleaseSpinLock(void);
operator PKSPIN_LOCK () { return &m_SpinLock; }
private:
KSPIN_LOCK m_SpinLock;
KIRQL m_OldIrql;
};
//
// inline functions for CKSpinLock
//
inline CKSpinLock::CKSpinLock(void)
{
KeInitializeSpinLock(&m_SpinLock);
}
inline CKSpinLock::~CKSpinLock(void)
{
}
inline void CKSpinLock::AcquireSpinLock(void)
{
m_OldIrql = _AcquireSpinLock();
}
inline KIRQL CKSpinLock::_AcquireSpinLock(void)
{
if (KeGetCurrentIrql() < DISPATCH_LEVEL) {
KIRQL Irql;
KeAcquireSpinLock(&m_SpinLock, &Irql);
return Irql;
}
else {
KeAcquireSpinLockAtDpcLevel(&m_SpinLock);
return DISPATCH_LEVEL;
}
}
inline void CKSpinLock::ReleaseSpinLock(void)
{
if (m_OldIrql < DISPATCH_LEVEL) {
KeReleaseSpinLock(&m_SpinLock, m_OldIrql);
}
else {
KeReleaseSpinLockFromDpcLevel(&m_SpinLock);
}
}
////////////////////////////////////////////////////////////////////////////////////////////
class CFastMutex
{
public:
SELF_DESTRUCT
CFastMutex() { ExInitializeFastMutex(&m_FastMutex); }
~CFastMutex() {}
void Lock() { AcquireMutex(); }
void Unlock() { ReleaseMutex(); }
void AcquireMutex();
void ReleaseMutex();
private:
FAST_MUTEX m_FastMutex;
};
inline void CFastMutex::AcquireMutex()
{
KeEnterCriticalRegion();
ExAcquireFastMutexUnsafe(&m_FastMutex);
}
inline void CFastMutex::ReleaseMutex()
{
ExReleaseFastMutexUnsafe(&m_FastMutex);
KeLeaveCriticalRegion();
}
////////////////////////////////////////////////////////////////////////////////////////////
class CSemaphore
{
public:
SELF_DESTRUCT
CSemaphore(LONG Count = 1, LONG Limit = MAXLONG) ;
~CSemaphore() {}
BOOLEAN ReleaseSem(KPRIORITY Increment = 0,LONG Adjustment = 1, BOOLEAN bWait = FALSE);
void AcquireSem();
BOOLEAN ReadState();
void Lock() { AcquireSem(); }
void Unlock() { ReleaseSem(); }
private:
KSEMAPHORE m_Semaphore;
};
inline CSemaphore::CSemaphore(LONG Count , LONG Limit)
{
KeInitializeSemaphore(&m_Semaphore, Count, Limit);
}
inline void CSemaphore::AcquireSem()
{
ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
KeWaitForSingleObject((PVOID) &m_Semaphore,Executive,KernelMode,FALSE,NULL);
}
inline BOOLEAN CSemaphore::ReleaseSem(KPRIORITY Increment, LONG Adjustment, BOOLEAN bWait)
{
if ( bWait) {
ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
}
else {
ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
}
return (BOOLEAN) KeReleaseSemaphore(&m_Semaphore,Increment, Adjustment, bWait);
}
inline BOOLEAN CSemaphore::ReadState()
{
return (BOOLEAN) KeReadStateSemaphore( &m_Semaphore );
}
#endif // defined (UNDER_CE) || defined (WINCE_EMULATION)
class NoRealLock {
public:
SELF_DESTRUCT
void Lock();
void Unlock();
};
#if (defined (UNDER_CE) || defined (WINCE_EMULATION))
class CSemaphore
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -