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.

772 lines
15 KiB

  1. /*++
  2. Copyright (c) 1998-2000 Microsoft Corporation
  3. Module Name:
  4. drobjmgr
  5. Abstract:
  6. DrObjectMgr manages a list of client-side RDP objects.
  7. Author:
  8. Joy Chik 11/30/99
  9. Revision History:
  10. --*/
  11. #ifndef __DROBJMGR_H__
  12. #define __DROBJMGR_H__
  13. #include <rdpdr.h>
  14. #include "drobject.h"
  15. #include "drdev.h"
  16. #include "drfile.h"
  17. template <class T>
  18. class DrObjectMgr;
  19. class DrDevice;
  20. class DrFile;
  21. ///////////////////////////////////////////////////////////////
  22. //
  23. // DrObjectMgr
  24. //
  25. // Locking: Member functions will implicitly lock the state
  26. // of the list. External explicit locking is also
  27. // available and recommended when iterating through
  28. // devices.
  29. //
  30. // GetFirstObject/GetNextObject:
  31. // Used in conjunction to iterate through the list
  32. // of objects. Any changes to the contents of list
  33. // resets the current object pointer.
  34. //
  35. template<class T>
  36. class DrObjectMgr : public DrObject
  37. {
  38. private:
  39. ///////////////////////////////////////////////////////////////
  40. //
  41. // Typedefs
  42. //
  43. typedef struct _DROBJECTLIST_NODE {
  44. ULONG magicNo;
  45. T *object;
  46. _DROBJECTLIST_NODE *next;
  47. _DROBJECTLIST_NODE *prev;
  48. } DROBJECTLIST_NODE, *PDROBJECTLIST_NODE;
  49. //
  50. // Private Data
  51. //
  52. BOOL _initialized;
  53. // Linked list of object instances.
  54. PDROBJECTLIST_NODE _listHead;
  55. // Global (to an instance of this class) monotonically
  56. // increasing object identifer.
  57. ULONG _objectID;
  58. // Current object for GetFirst/GetNext routines.
  59. PDROBJECTLIST_NODE _currentNode;
  60. // The lock.
  61. CRITICAL_SECTION _cs;
  62. //
  63. // Monitor the lock count in checked builds.
  64. //
  65. #if DBG
  66. LONG _lockCount;
  67. #endif
  68. // Object Count
  69. ULONG _count;
  70. // Remember if we are in the middle of checking the integrity of an
  71. // instance of this class.
  72. #if DBG
  73. BOOL _integrityCheckInProgress;
  74. #endif
  75. //
  76. // Private Methods
  77. //
  78. VOID deleteNode(PDROBJECTLIST_NODE node);
  79. PDROBJECTLIST_NODE FindNode(DRSTRING name,
  80. ULONG objectType);
  81. PDROBJECTLIST_NODE FindNode(ULONG id);
  82. //
  83. // Periodically, check the integrity of the list in debug builds.
  84. //
  85. #if DBG
  86. VOID CheckListIntegrity();
  87. #endif
  88. public:
  89. //
  90. // Public Methods
  91. //
  92. // Constructor/Destructor
  93. DrObjectMgr();
  94. virtual ~DrObjectMgr();
  95. // Initialize
  96. DWORD Initialize();
  97. // Lock/unlock the list of objects for multithreaded access.
  98. // Member functions that require that the list of objects be locked
  99. // will do implicitly.
  100. VOID Lock();
  101. VOID Unlock();
  102. // Add/remove an object.
  103. DWORD AddObject(T *object);
  104. T *RemoveObject(const DRSTRING name, ULONG objectType);
  105. T *RemoveObject(ULONG id);
  106. // Test for existence of an object.
  107. BOOL ObjectExists(const DRSTRING name);
  108. BOOL ObjectExists(const DRSTRING name, ULONG deviceType);
  109. BOOL ObjectExists(ULONG id);
  110. // Return an object.
  111. T *GetObject(const DRSTRING name);
  112. T *GetObject(const DRSTRING name, ULONG objectType);
  113. T *GetObject(ULONG id);
  114. //
  115. // Iterate through objects, sequentially.
  116. //
  117. ULONG GetCount() { return _count; }
  118. T *GetObjectByOffset(ULONG ofs);
  119. T *GetFirstObject();
  120. T *GetNextObject();
  121. // Return whether this class instance is valid.
  122. #if DBG
  123. virtual BOOL IsValid()
  124. {
  125. CheckListIntegrity();
  126. return DrObject::IsValid();
  127. }
  128. #endif
  129. // Get a unique object ID ... assuming that this function is the
  130. // clearinghouse for all objects associated with an instance of this
  131. // class.
  132. ULONG GetUniqueObjectID();
  133. // Return the class name.
  134. virtual DRSTRING ClassName() { return TEXT("DrObjectMgr"); }
  135. };
  136. ///////////////////////////////////////////////////////////////
  137. //
  138. // DrObjectMgr Inline Functions
  139. //
  140. //
  141. //
  142. // lock
  143. //
  144. template<class T>
  145. inline VOID DrObjectMgr<T>::Lock() {
  146. DC_BEGIN_FN("DrObjectMgr::Lock");
  147. EnterCriticalSection(&_cs);
  148. #if DBG
  149. InterlockedIncrement(&_lockCount);
  150. #endif
  151. DC_END_FN();
  152. }
  153. //
  154. // unlock
  155. //
  156. template<class T>
  157. inline VOID DrObjectMgr<T>::Unlock() {
  158. DC_BEGIN_FN("DrObjectMgr::Unlock");
  159. #if DBG
  160. if (InterlockedDecrement(&_lockCount) < 0) {
  161. ASSERT(FALSE);
  162. }
  163. #endif
  164. LeaveCriticalSection(&_cs);
  165. DC_END_FN();
  166. }
  167. //
  168. // GetUniqueObjectID
  169. //
  170. template<class T>
  171. inline ULONG DrObjectMgr<T>::GetUniqueObjectID() {
  172. ULONG tmp;
  173. Lock();
  174. tmp = ++_objectID;
  175. Unlock();
  176. return tmp;
  177. }
  178. //
  179. // deleteNode
  180. //
  181. template<class T>
  182. inline
  183. VOID DrObjectMgr<T>::deleteNode(PDROBJECTLIST_NODE node) {
  184. if (node == _listHead) {
  185. _listHead = _listHead->next;
  186. }
  187. else {
  188. node->prev->next = node->next;
  189. if (node->next != NULL) {
  190. node->next->prev = node->prev;
  191. }
  192. }
  193. //
  194. // Delete the node.
  195. //
  196. delete node;
  197. }
  198. //
  199. // Constructor
  200. //
  201. template<class T>
  202. DrObjectMgr<T>::DrObjectMgr() {
  203. //
  204. // Initialize the lock count for debug builds.
  205. //
  206. #if DBG
  207. _lockCount = 0;
  208. #endif
  209. //
  210. // Not valid until initialized.
  211. //
  212. _initialized = FALSE;
  213. SetValid(FALSE);
  214. //
  215. // Initialize the list head.
  216. //
  217. _listHead = NULL;
  218. //
  219. // Initialize the unique device ID counter.
  220. //
  221. _objectID = 0;
  222. //
  223. // Initialize the device count.
  224. //
  225. _count = 0;
  226. //
  227. // Initialize the GetFirst/GetNext device pointer.
  228. //
  229. _currentNode = NULL;
  230. }
  231. //
  232. // Destructor
  233. //
  234. template<class T>
  235. DrObjectMgr<T>::~DrObjectMgr() {
  236. DC_BEGIN_FN("DrObjectMgr::~DrObjectMgr");
  237. //
  238. // Can't do anything if we are not initialized.
  239. //
  240. if (!_initialized) {
  241. return;
  242. }
  243. Lock();
  244. //
  245. // The lock count should be one if we are being cleaned up.
  246. //
  247. ASSERT(_lockCount == 1);
  248. //
  249. // Release the object list.
  250. //
  251. if (_listHead != NULL) {
  252. //
  253. // Assert that the device list is empty. All device instances
  254. // should have been removed by the time this function is called.
  255. //
  256. ASSERT(_listHead->next == NULL);
  257. delete _listHead;
  258. }
  259. Unlock();
  260. //
  261. // Clean up the critical section object.
  262. //
  263. DeleteCriticalSection(&_cs);
  264. DC_END_FN();
  265. }
  266. //
  267. // Initialize
  268. //
  269. template<class T>
  270. DWORD DrObjectMgr<T>::Initialize() {
  271. DC_BEGIN_FN("DrObjectMgr::Initialize");
  272. DWORD result = ERROR_SUCCESS;
  273. //
  274. // Initialize the critical section.
  275. //
  276. __try {
  277. InitializeCriticalSection(&_cs);
  278. _initialized = TRUE;
  279. SetValid(TRUE);
  280. }
  281. __except(EXCEPTION_EXECUTE_HANDLER) {
  282. result = GetExceptionCode();
  283. }
  284. return result;
  285. }
  286. //
  287. // FindNode
  288. //
  289. template<class T>
  290. __TYPENAME DrObjectMgr<T>::PDROBJECTLIST_NODE DrObjectMgr<T>::FindNode(DRSTRING name, ULONG objectType) {
  291. PDROBJECTLIST_NODE cur;
  292. cur = _listHead;
  293. while (cur != NULL) {
  294. T *obj = cur->object;
  295. if (!STRICMP(name, obj->GetName())
  296. && (obj->GetDeviceType() == objectType)) {
  297. break;
  298. }
  299. else {
  300. cur = cur->next;
  301. }
  302. }
  303. return cur;
  304. }
  305. //
  306. // FindNode
  307. //
  308. template<class T>
  309. __TYPENAME DrObjectMgr<T>::PDROBJECTLIST_NODE DrObjectMgr<T>::FindNode(ULONG id) {
  310. PDROBJECTLIST_NODE cur;
  311. DC_BEGIN_FN("DrObjectMgr::FindNode");
  312. cur = _listHead;
  313. while (cur != NULL) {
  314. T *obj = cur->object;
  315. if (id == obj->GetID()) {
  316. break;
  317. }
  318. else {
  319. cur = cur->next;
  320. }
  321. }
  322. DC_END_FN();
  323. return cur;
  324. }
  325. //
  326. // AddObject
  327. //
  328. template<class T>
  329. DWORD DrObjectMgr<T>::AddObject(T *object) {
  330. DWORD ret = ERROR_SUCCESS;
  331. PDROBJECTLIST_NODE newNode;
  332. DC_BEGIN_FN("DrObjectMgr::AddObject");
  333. ASSERT(IsValid());
  334. //
  335. // Make sure that the object doesn't already exist in the
  336. // list.
  337. //
  338. ASSERT(FindNode(object->GetID()) == NULL);
  339. //
  340. // Allocate the node.
  341. //
  342. newNode = new DROBJECTLIST_NODE;
  343. if (newNode != NULL) {
  344. #if DBG
  345. newNode->magicNo = GOODMEMMAGICNUMBER;
  346. #endif
  347. newNode->object = object;
  348. //
  349. // Add the node to the list.
  350. //
  351. Lock();
  352. _count++;
  353. if (_listHead == NULL) {
  354. _listHead = newNode;
  355. _listHead->next = NULL;
  356. _listHead->prev = NULL;
  357. }
  358. else {
  359. _listHead->prev = newNode;
  360. newNode->prev = NULL;
  361. newNode->next = _listHead;
  362. _listHead = newNode;
  363. }
  364. Unlock();
  365. }
  366. else {
  367. TRC_ERR((TB, _T("Failed to alloc device.")));
  368. ret = ERROR_NOT_ENOUGH_MEMORY;
  369. }
  370. ASSERT(IsValid());
  371. DC_END_FN();
  372. return ret;
  373. }
  374. //
  375. // RemoveObject
  376. //
  377. template<class T>
  378. T *DrObjectMgr<T>::RemoveObject(
  379. const DRSTRING name,
  380. ULONG objectType
  381. ) {
  382. PDROBJECTLIST_NODE node;
  383. T *object;
  384. DC_BEGIN_FN("DrObjectMgr::RemoveObject");
  385. ASSERT(IsValid());
  386. //
  387. // Find the object.
  388. //
  389. Lock();
  390. if ((node = FindNode(name, deviceType)) != NULL) {
  391. object = node->object;
  392. deleteNode(node);
  393. //
  394. // Decrement the count.
  395. //
  396. _count--;
  397. }
  398. else {
  399. object = NULL;
  400. }
  401. Unlock();
  402. ASSERT(IsValid());
  403. DC_END_FN();
  404. return object;
  405. }
  406. //
  407. // RemoveObject
  408. //
  409. template<class T>
  410. T *DrObjectMgr<T>::RemoveObject(ULONG id) {
  411. PDROBJECTLIST_NODE node;
  412. T *object;
  413. DC_BEGIN_FN("DrObjectMgr::RemoveObject");
  414. ASSERT(IsValid());
  415. //
  416. // Find the object.
  417. //
  418. Lock();
  419. if ((node = FindNode(id)) != NULL) {
  420. object = node->object;
  421. deleteNode(node);
  422. //
  423. // Decrement the count.
  424. //
  425. _count--;
  426. }
  427. else {
  428. object = NULL;
  429. }
  430. Unlock();
  431. ASSERT(IsValid());
  432. DC_END_FN();
  433. return object;
  434. }
  435. //
  436. // ObjectExists
  437. //
  438. template<class T>
  439. BOOL DrObjectMgr<T>::ObjectExists(const DRSTRING name,
  440. ULONG objectType) {
  441. PDROBJECTLIST_NODE node;
  442. DC_BEGIN_FN("DrObjectMgr::ObjectExists");
  443. ASSERT(IsValid());
  444. Lock();
  445. node = FindNode(name, objectType);
  446. Unlock();
  447. ASSERT(IsValid());
  448. DC_END_FN();
  449. return node != NULL;
  450. }
  451. //
  452. // ObjectExists
  453. //
  454. template<class T>
  455. BOOL DrObjectMgr<T>::ObjectExists(ULONG id) {
  456. PDROBJECTLIST_NODE node;
  457. DC_BEGIN_FN("DrObjectMgr::ObjectExists");
  458. ASSERT(IsValid());
  459. Lock();
  460. node = FindNode(id);
  461. Unlock();
  462. ASSERT(IsValid());
  463. DC_END_FN();
  464. return node != NULL;
  465. }
  466. //
  467. // Return an object.
  468. //
  469. template<class T>
  470. T *DrObjectMgr<T>::GetObject(const DRSTRING name,
  471. ULONG objectType) {
  472. PDROBJECTLIST_NODE node;
  473. T *object;
  474. DC_BEGIN_FN("DrObjectMgr::GetObject");
  475. ASSERT(IsValid());
  476. Lock();
  477. if ((node = FindNode(name, objectType)) != NULL) {
  478. object = node->object;
  479. }
  480. else {
  481. object = NULL;
  482. }
  483. Unlock();
  484. ASSERT(IsValid());
  485. DC_END_FN();
  486. return object;
  487. }
  488. //
  489. // Return an object.
  490. //
  491. template<class T>
  492. T *DrObjectMgr<T>::GetObject(ULONG id) {
  493. PDROBJECTLIST_NODE node;
  494. T *object;
  495. DC_BEGIN_FN("DrObjectMgr::GetObject");
  496. ASSERT(IsValid());
  497. Lock();
  498. if ((node = FindNode(id)) != NULL) {
  499. object = node->object;
  500. }
  501. else {
  502. object = NULL;
  503. }
  504. Unlock();
  505. ASSERT(IsValid());
  506. DC_END_FN();
  507. return object;
  508. }
  509. //
  510. // Get object at the specified offset.
  511. //
  512. template<class T>
  513. T *DrObjectMgr<T>::GetObjectByOffset(ULONG ofs) {
  514. PDROBJECTLIST_NODE cur;
  515. ULONG cnt = 0;
  516. DC_BEGIN_FN("DrObjectMgr::GetObjectByOffset");
  517. ASSERT(IsValid());
  518. Lock();
  519. for (cur=_listHead, cnt=0; (cur!=NULL) && (cnt != ofs); cnt++) {
  520. ASSERT(cur->magicNo == GOODMEMMAGICNUMBER);
  521. cur = cur->next;
  522. }
  523. Unlock();
  524. ASSERT(IsValid());
  525. DC_END_FN();
  526. return cur->object;
  527. }
  528. //
  529. // Return the first object and set the internal current object
  530. // pointer to the beginning of the list. Returns NULL at the end
  531. // of the list.
  532. //
  533. template<class T>
  534. T *DrObjectMgr<T>::GetFirstObject() {
  535. T *object;
  536. DC_BEGIN_FN("DrObjectMgr::GetFirstObject");
  537. ASSERT(IsValid());
  538. Lock();
  539. _currentNode = _listHead;
  540. if (_currentNode != NULL) {
  541. object = _currentNode->object;
  542. }
  543. else {
  544. object = NULL;
  545. }
  546. Unlock();
  547. ASSERT(IsValid());
  548. DC_END_FN();
  549. return object;
  550. }
  551. //
  552. // Return the next object and update the internal current object
  553. // pointer. Returns NULL at the end of the list.
  554. //
  555. template<class T>
  556. T *DrObjectMgr<T>::GetNextObject() {
  557. T *object;
  558. DC_BEGIN_FN("DrObjectMgr::GetNextObject");
  559. ASSERT(IsValid());
  560. Lock();
  561. if (_currentNode != NULL) {
  562. _currentNode = _currentNode->next;
  563. }
  564. if (_currentNode != NULL) {
  565. object = _currentNode->object;
  566. ASSERT(_currentNode->magicNo == GOODMEMMAGICNUMBER);
  567. }
  568. else {
  569. object = NULL;
  570. }
  571. Unlock();
  572. ASSERT(IsValid());
  573. DC_END_FN();
  574. return object;
  575. }
  576. //
  577. // Check the integrity of the list.
  578. //
  579. #if DBG
  580. template<class T>
  581. VOID DrObjectMgr<T>::CheckListIntegrity() {
  582. ULONG cnt;
  583. ULONG i;
  584. DC_BEGIN_FN("DrObjectMgr::CheckListIntegrity");
  585. Lock();
  586. //
  587. // Make sure we don't re-enter ourselves.
  588. //
  589. if (!_integrityCheckInProgress) {
  590. _integrityCheckInProgress = TRUE;
  591. }
  592. else {
  593. Unlock();
  594. DC_END_FN();
  595. return;
  596. }
  597. //
  598. // Use offsets to iterate throught the list of objects.
  599. //
  600. cnt = GetCount();
  601. for (i=0; i<cnt; i++) {
  602. T *object = GetObjectByOffset(i);
  603. ASSERT(object != NULL);
  604. ASSERT(object->_magicNo == GOODMEMMAGICNUMBER);
  605. }
  606. _integrityCheckInProgress = FALSE;
  607. Unlock();
  608. DC_END_FN();
  609. }
  610. #endif
  611. typedef DrObjectMgr<DrDevice> DrDeviceMgr;
  612. typedef DrObjectMgr<DrFile> DrFileMgr;
  613. #endif