Leaked source code of windows server 2003
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
|
|
/*++
Copyright (c) 1998-2000 Microsoft Corporation
Module Name:
drobjmgr
Abstract:
DrObjectMgr manages a list of client-side RDP objects.
Author:
Joy Chik 11/30/99
Revision History:
--*/
#ifndef __DROBJMGR_H__
#define __DROBJMGR_H__
#include <rdpdr.h>
#include "drobject.h"
#include "drdev.h"
#include "drfile.h"
template <class T> class DrObjectMgr; class DrDevice; class DrFile;
///////////////////////////////////////////////////////////////
//
// DrObjectMgr
//
// Locking: Member functions will implicitly lock the state
// of the list. External explicit locking is also
// available and recommended when iterating through
// devices.
//
// GetFirstObject/GetNextObject:
// Used in conjunction to iterate through the list
// of objects. Any changes to the contents of list
// resets the current object pointer.
//
template<class T> class DrObjectMgr : public DrObject {
private: ///////////////////////////////////////////////////////////////
//
// Typedefs
//
typedef struct _DROBJECTLIST_NODE { ULONG magicNo; T *object; _DROBJECTLIST_NODE *next; _DROBJECTLIST_NODE *prev; } DROBJECTLIST_NODE, *PDROBJECTLIST_NODE;
//
// Private Data
//
BOOL _initialized;
// Linked list of object instances.
PDROBJECTLIST_NODE _listHead;
// Global (to an instance of this class) monotonically
// increasing object identifer.
ULONG _objectID;
// Current object for GetFirst/GetNext routines.
PDROBJECTLIST_NODE _currentNode;
// The lock.
CRITICAL_SECTION _cs;
//
// Monitor the lock count in checked builds.
//
#if DBG
LONG _lockCount; #endif
// Object Count
ULONG _count;
// Remember if we are in the middle of checking the integrity of an
// instance of this class.
#if DBG
BOOL _integrityCheckInProgress; #endif
//
// Private Methods
//
VOID deleteNode(PDROBJECTLIST_NODE node);
PDROBJECTLIST_NODE FindNode(DRSTRING name, ULONG objectType);
PDROBJECTLIST_NODE FindNode(ULONG id);
//
// Periodically, check the integrity of the list in debug builds.
//
#if DBG
VOID CheckListIntegrity(); #endif
public: //
// Public Methods
//
// Constructor/Destructor
DrObjectMgr(); virtual ~DrObjectMgr();
// Initialize
DWORD Initialize();
// Lock/unlock the list of objects for multithreaded access.
// Member functions that require that the list of objects be locked
// will do implicitly.
VOID Lock(); VOID Unlock();
// Add/remove an object.
DWORD AddObject(T *object); T *RemoveObject(const DRSTRING name, ULONG objectType); T *RemoveObject(ULONG id);
// Test for existence of an object.
BOOL ObjectExists(const DRSTRING name); BOOL ObjectExists(const DRSTRING name, ULONG deviceType); BOOL ObjectExists(ULONG id);
// Return an object.
T *GetObject(const DRSTRING name); T *GetObject(const DRSTRING name, ULONG objectType); T *GetObject(ULONG id);
//
// Iterate through objects, sequentially.
//
ULONG GetCount() { return _count; } T *GetObjectByOffset(ULONG ofs); T *GetFirstObject(); T *GetNextObject();
// Return whether this class instance is valid.
#if DBG
virtual BOOL IsValid() { CheckListIntegrity(); return DrObject::IsValid(); } #endif
// Get a unique object ID ... assuming that this function is the
// clearinghouse for all objects associated with an instance of this
// class.
ULONG GetUniqueObjectID();
// Return the class name.
virtual DRSTRING ClassName() { return TEXT("DrObjectMgr"); } };
///////////////////////////////////////////////////////////////
//
// DrObjectMgr Inline Functions
//
//
//
// lock
//
template<class T> inline VOID DrObjectMgr<T>::Lock() { DC_BEGIN_FN("DrObjectMgr::Lock"); EnterCriticalSection(&_cs); #if DBG
InterlockedIncrement(&_lockCount); #endif
DC_END_FN(); }
//
// unlock
//
template<class T> inline VOID DrObjectMgr<T>::Unlock() { DC_BEGIN_FN("DrObjectMgr::Unlock"); #if DBG
if (InterlockedDecrement(&_lockCount) < 0) { ASSERT(FALSE); } #endif
LeaveCriticalSection(&_cs); DC_END_FN(); }
//
// GetUniqueObjectID
//
template<class T> inline ULONG DrObjectMgr<T>::GetUniqueObjectID() { ULONG tmp;
Lock(); tmp = ++_objectID; Unlock();
return tmp; }
//
// deleteNode
//
template<class T> inline VOID DrObjectMgr<T>::deleteNode(PDROBJECTLIST_NODE node) { if (node == _listHead) { _listHead = _listHead->next;
} else { node->prev->next = node->next; if (node->next != NULL) { node->next->prev = node->prev; } } //
// Delete the node.
//
delete node; }
//
// Constructor
//
template<class T> DrObjectMgr<T>::DrObjectMgr() {
//
// Initialize the lock count for debug builds.
//
#if DBG
_lockCount = 0; #endif
//
// Not valid until initialized.
//
_initialized = FALSE; SetValid(FALSE);
//
// Initialize the list head.
//
_listHead = NULL;
//
// Initialize the unique device ID counter.
//
_objectID = 0;
//
// Initialize the device count.
//
_count = 0;
//
// Initialize the GetFirst/GetNext device pointer.
//
_currentNode = NULL; }
//
// Destructor
//
template<class T> DrObjectMgr<T>::~DrObjectMgr() {
DC_BEGIN_FN("DrObjectMgr::~DrObjectMgr");
//
// Can't do anything if we are not initialized.
//
if (!_initialized) { return; }
Lock();
//
// The lock count should be one if we are being cleaned up.
//
ASSERT(_lockCount == 1);
//
// Release the object list.
//
if (_listHead != NULL) { //
// Assert that the device list is empty. All device instances
// should have been removed by the time this function is called.
//
ASSERT(_listHead->next == NULL);
delete _listHead; }
Unlock();
//
// Clean up the critical section object.
//
DeleteCriticalSection(&_cs);
DC_END_FN(); }
//
// Initialize
//
template<class T> DWORD DrObjectMgr<T>::Initialize() { DC_BEGIN_FN("DrObjectMgr::Initialize");
DWORD result = ERROR_SUCCESS;
//
// Initialize the critical section.
//
__try { InitializeCriticalSection(&_cs); _initialized = TRUE; SetValid(TRUE); } __except(EXCEPTION_EXECUTE_HANDLER) { result = GetExceptionCode(); }
return result; }
//
// FindNode
//
template<class T> __TYPENAME DrObjectMgr<T>::PDROBJECTLIST_NODE DrObjectMgr<T>::FindNode(DRSTRING name, ULONG objectType) {
PDROBJECTLIST_NODE cur;
cur = _listHead; while (cur != NULL) { T *obj = cur->object; if (!STRICMP(name, obj->GetName()) && (obj->GetDeviceType() == objectType)) { break; } else { cur = cur->next; } } return cur; }
//
// FindNode
//
template<class T> __TYPENAME DrObjectMgr<T>::PDROBJECTLIST_NODE DrObjectMgr<T>::FindNode(ULONG id) { PDROBJECTLIST_NODE cur;
DC_BEGIN_FN("DrObjectMgr::FindNode");
cur = _listHead; while (cur != NULL) { T *obj = cur->object; if (id == obj->GetID()) { break; } else { cur = cur->next; } }
DC_END_FN();
return cur; } //
// AddObject
//
template<class T> DWORD DrObjectMgr<T>::AddObject(T *object) {
DWORD ret = ERROR_SUCCESS; PDROBJECTLIST_NODE newNode;
DC_BEGIN_FN("DrObjectMgr::AddObject");
ASSERT(IsValid());
//
// Make sure that the object doesn't already exist in the
// list.
//
ASSERT(FindNode(object->GetID()) == NULL);
//
// Allocate the node.
//
newNode = new DROBJECTLIST_NODE; if (newNode != NULL) {
#if DBG
newNode->magicNo = GOODMEMMAGICNUMBER; #endif
newNode->object = object;
//
// Add the node to the list.
//
Lock(); _count++; if (_listHead == NULL) { _listHead = newNode; _listHead->next = NULL; _listHead->prev = NULL; } else { _listHead->prev = newNode; newNode->prev = NULL; newNode->next = _listHead; _listHead = newNode; } Unlock(); } else { TRC_ERR((TB, _T("Failed to alloc device."))); ret = ERROR_NOT_ENOUGH_MEMORY; }
ASSERT(IsValid());
DC_END_FN(); return ret; }
//
// RemoveObject
//
template<class T> T *DrObjectMgr<T>::RemoveObject( const DRSTRING name, ULONG objectType ) {
PDROBJECTLIST_NODE node; T *object;
DC_BEGIN_FN("DrObjectMgr::RemoveObject");
ASSERT(IsValid());
//
// Find the object.
//
Lock(); if ((node = FindNode(name, deviceType)) != NULL) { object = node->object; deleteNode(node); //
// Decrement the count.
//
_count--; } else { object = NULL; }
Unlock();
ASSERT(IsValid());
DC_END_FN(); return object; }
//
// RemoveObject
//
template<class T> T *DrObjectMgr<T>::RemoveObject(ULONG id) { PDROBJECTLIST_NODE node; T *object;
DC_BEGIN_FN("DrObjectMgr::RemoveObject");
ASSERT(IsValid());
//
// Find the object.
//
Lock(); if ((node = FindNode(id)) != NULL) { object = node->object; deleteNode(node);
//
// Decrement the count.
//
_count--; } else { object = NULL; }
Unlock();
ASSERT(IsValid());
DC_END_FN(); return object; }
//
// ObjectExists
//
template<class T> BOOL DrObjectMgr<T>::ObjectExists(const DRSTRING name, ULONG objectType) { PDROBJECTLIST_NODE node;
DC_BEGIN_FN("DrObjectMgr::ObjectExists");
ASSERT(IsValid());
Lock(); node = FindNode(name, objectType); Unlock();
ASSERT(IsValid());
DC_END_FN(); return node != NULL; }
//
// ObjectExists
//
template<class T> BOOL DrObjectMgr<T>::ObjectExists(ULONG id) { PDROBJECTLIST_NODE node;
DC_BEGIN_FN("DrObjectMgr::ObjectExists");
ASSERT(IsValid());
Lock(); node = FindNode(id); Unlock();
ASSERT(IsValid());
DC_END_FN(); return node != NULL; }
//
// Return an object.
//
template<class T> T *DrObjectMgr<T>::GetObject(const DRSTRING name, ULONG objectType) { PDROBJECTLIST_NODE node; T *object;
DC_BEGIN_FN("DrObjectMgr::GetObject");
ASSERT(IsValid());
Lock(); if ((node = FindNode(name, objectType)) != NULL) { object = node->object; } else { object = NULL; } Unlock();
ASSERT(IsValid());
DC_END_FN(); return object; }
//
// Return an object.
//
template<class T> T *DrObjectMgr<T>::GetObject(ULONG id) { PDROBJECTLIST_NODE node; T *object;
DC_BEGIN_FN("DrObjectMgr::GetObject");
ASSERT(IsValid());
Lock(); if ((node = FindNode(id)) != NULL) { object = node->object; } else { object = NULL; } Unlock();
ASSERT(IsValid());
DC_END_FN(); return object; }
//
// Get object at the specified offset.
//
template<class T> T *DrObjectMgr<T>::GetObjectByOffset(ULONG ofs) { PDROBJECTLIST_NODE cur; ULONG cnt = 0;
DC_BEGIN_FN("DrObjectMgr::GetObjectByOffset");
ASSERT(IsValid());
Lock(); for (cur=_listHead, cnt=0; (cur!=NULL) && (cnt != ofs); cnt++) { ASSERT(cur->magicNo == GOODMEMMAGICNUMBER); cur = cur->next; } Unlock();
ASSERT(IsValid());
DC_END_FN(); return cur->object; }
//
// Return the first object and set the internal current object
// pointer to the beginning of the list. Returns NULL at the end
// of the list.
//
template<class T> T *DrObjectMgr<T>::GetFirstObject() { T *object;
DC_BEGIN_FN("DrObjectMgr::GetFirstObject");
ASSERT(IsValid());
Lock(); _currentNode = _listHead; if (_currentNode != NULL) { object = _currentNode->object; } else { object = NULL; } Unlock();
ASSERT(IsValid());
DC_END_FN(); return object; }
//
// Return the next object and update the internal current object
// pointer. Returns NULL at the end of the list.
//
template<class T> T *DrObjectMgr<T>::GetNextObject() { T *object;
DC_BEGIN_FN("DrObjectMgr::GetNextObject");
ASSERT(IsValid());
Lock(); if (_currentNode != NULL) { _currentNode = _currentNode->next; } if (_currentNode != NULL) { object = _currentNode->object; ASSERT(_currentNode->magicNo == GOODMEMMAGICNUMBER); } else { object = NULL; } Unlock();
ASSERT(IsValid());
DC_END_FN(); return object; }
//
// Check the integrity of the list.
//
#if DBG
template<class T> VOID DrObjectMgr<T>::CheckListIntegrity() { ULONG cnt; ULONG i;
DC_BEGIN_FN("DrObjectMgr::CheckListIntegrity");
Lock();
//
// Make sure we don't re-enter ourselves.
//
if (!_integrityCheckInProgress) { _integrityCheckInProgress = TRUE; } else { Unlock(); DC_END_FN(); return; }
//
// Use offsets to iterate throught the list of objects.
//
cnt = GetCount(); for (i=0; i<cnt; i++) { T *object = GetObjectByOffset(i); ASSERT(object != NULL); ASSERT(object->_magicNo == GOODMEMMAGICNUMBER); }
_integrityCheckInProgress = FALSE; Unlock();
DC_END_FN(); } #endif
typedef DrObjectMgr<DrDevice> DrDeviceMgr; typedef DrObjectMgr<DrFile> DrFileMgr;
#endif
|