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.

780 lines
11 KiB

  1. /*++
  2. Copyright (c) 1994-1999 Microsoft Corporation
  3. Module Name :
  4. objplus.cpp
  5. Abstract:
  6. Base object classes
  7. Author:
  8. Ronald Meijer (ronaldm)
  9. Project:
  10. Internet Services Manager (cluster edition)
  11. Revision History:
  12. --*/
  13. //
  14. // Include Files
  15. //
  16. #include "stdafx.h"
  17. #include "common.h"
  18. #include <stdlib.h>
  19. #include <memory.h>
  20. #include <ctype.h>
  21. #ifdef _DEBUG
  22. #undef THIS_FILE
  23. static char BASED_CODE THIS_FILE[] = __FILE__;
  24. #endif
  25. #define new DEBUG_NEW
  26. CObjHelper::CObjHelper()
  27. /*++
  28. Routine Description:
  29. Constructor for super object help class
  30. Arguments:
  31. None
  32. Return Value:
  33. N/A
  34. --*/
  35. : m_ctor_err(ERROR_SUCCESS),
  36. m_api_err(ERROR_SUCCESS),
  37. m_fDirty(FALSE),
  38. m_time_created(::GetCurrentTime())
  39. {
  40. }
  41. void
  42. CObjHelper::ReportError(
  43. IN LONG errInConstruction
  44. )
  45. /*++
  46. Routine Description:
  47. Set the constructor error code, and dump the error message to
  48. the debugging context.
  49. Arguments:
  50. LONG errInConstruction : Error code
  51. Return Value:
  52. None
  53. --*/
  54. {
  55. TRACEEOLID("CObjectPlus construction failure, error = "
  56. << errInConstruction);
  57. m_ctor_err = errInConstruction;
  58. }
  59. LONG
  60. CObjHelper::SetApiErr(
  61. IN LONG errApi
  62. )
  63. /*++
  64. Routine Description:
  65. Set the API error code.
  66. Arguments:
  67. LONG errApi : API error code
  68. Return Value:
  69. The API error code
  70. --*/
  71. {
  72. return m_api_err = errApi;
  73. }
  74. BOOL
  75. CObjHelper::IsValid() const
  76. /*++
  77. Routine Description:
  78. Determine if the object is in a valid state
  79. Arguments:
  80. LONG errApi : API error code
  81. Return Value:
  82. TRUE if the the object is in a valid state, FALSE otherwise
  83. --*/
  84. {
  85. return QueryError() == 0;
  86. }
  87. DWORD
  88. CObjHelper::QueryAge() const
  89. /*++
  90. Routine Description:
  91. Determine the age of the object.
  92. Arguments:
  93. None
  94. Return Value:
  95. time_t value indicating the age of the object.
  96. --*/
  97. {
  98. DWORD dwTime = ::GetCurrentTime(),
  99. dwDiff;
  100. if (dwTime < m_time_created)
  101. {
  102. dwDiff = dwTime + (((DWORD)-1) - (m_time_created - 1));
  103. }
  104. else
  105. {
  106. dwDiff = dwTime - m_time_created;
  107. }
  108. return dwDiff;
  109. }
  110. #ifdef _DEBUG
  111. void
  112. CObjHelper::AssertValid() const
  113. /*++
  114. Routine Description:
  115. Assert the object if the object is in a valid state
  116. Arguments:
  117. None
  118. Return Value:
  119. None
  120. --*/
  121. {
  122. ASSERT(IsValid());
  123. }
  124. #endif // _DEBUG
  125. CObjectPlus::CObjectPlus()
  126. /*++
  127. Routine Description:
  128. Constructor of extended object
  129. Arguments:
  130. None
  131. Return Value:
  132. N/A
  133. --*/
  134. {
  135. }
  136. int
  137. CObjectPlus::Compare(
  138. IN const CObjectPlus * pob
  139. ) const
  140. /*++
  141. Routine Description:
  142. Compare one object with another: default implementation orders objects
  143. by creation time. Return -1, 0 or 1.
  144. Arguments:
  145. const CObjectPlus * pob : Object to be compared against
  146. Return Value:
  147. -1 if this object is < than the compared object
  148. 0 if this object is == to the compared object
  149. +1 if this object is > than the compared object
  150. --*/
  151. {
  152. return QueryCreationTime() < pob->QueryCreationTime()
  153. ? -1
  154. : QueryCreationTime() != pob->QueryCreationTime();
  155. }
  156. CObListPlus::CObListPlus(
  157. IN int nBlockSize
  158. )
  159. /*++
  160. Routine Description:
  161. Subclass of CObList whose default behavior is to destroy its
  162. contents during its own destruction
  163. Arguments:
  164. int nBlockSize : Initial block size
  165. Return Value:
  166. None
  167. --*/
  168. : CObList(nBlockSize),
  169. m_fOwned(TRUE)
  170. {
  171. }
  172. CObListPlus::~CObListPlus()
  173. /*++
  174. Routine Description:
  175. Destructor. If the objects are owned, clean them up.
  176. Arguments:
  177. N/A
  178. Return Value:
  179. N/A
  180. --*/
  181. {
  182. RemoveAll();
  183. }
  184. void
  185. CObListPlus::RemoveAll()
  186. /*++
  187. Routine Description:
  188. Remove all the objects in the list if the list owns its objects
  189. Arguments:
  190. None
  191. Return Value:
  192. None
  193. --*/
  194. {
  195. if (m_fOwned)
  196. {
  197. //
  198. // Remove and discard all the objects
  199. //
  200. while (!IsEmpty())
  201. {
  202. CObject * pob = RemoveHead();
  203. delete pob ;
  204. }
  205. }
  206. else
  207. {
  208. //
  209. // Just remove the object pointers
  210. //
  211. CObList::RemoveAll();
  212. }
  213. }
  214. CObject *
  215. CObListPlus::Index(
  216. IN int index
  217. )
  218. /*++
  219. Routine Description:
  220. Get object by index
  221. Arguments:
  222. int index : The index of the object to be returned
  223. Return Value:
  224. The object, or NULL if the index is invalid
  225. --*/
  226. {
  227. CObListIter obli(*this);
  228. CObject * pob = NULL;
  229. for (int i = 0; (NULL != (pob = obli.Next())) && i++ < index; /**/ );
  230. return pob;
  231. }
  232. BOOL
  233. CObListPlus::RemoveIndex(
  234. IN int index
  235. )
  236. /*++
  237. Routine Description:
  238. Remove object by index
  239. Arguments:
  240. int index : The index of the object to be removed
  241. Return Value:
  242. The object, or NULL if the index is invalid
  243. --*/
  244. {
  245. int i;
  246. POSITION pos;
  247. CObListIter obli(*this);
  248. CObject * pob;
  249. for (i = 0, pos = obli.QueryPosition();
  250. (NULL != (pob = obli.Next())) && i < index;
  251. i++, pos = obli.QueryPosition());
  252. if (pob && i == index)
  253. {
  254. RemoveAt(pos);
  255. return TRUE;
  256. }
  257. return FALSE;
  258. }
  259. BOOL
  260. CObListPlus::Remove(
  261. IN CObject * pob
  262. )
  263. /*++
  264. Routine Description:
  265. Remove the first (and hopefully only) occurrence of an object
  266. pointer from this list.
  267. Arguments:
  268. CObject * pob : The object to be removed
  269. Return Value:
  270. TRUE if the object was found and succesfully removed, FALSE otherwise
  271. --*/
  272. {
  273. POSITION pos = Find(pob);
  274. if (pos == NULL)
  275. {
  276. return FALSE;
  277. }
  278. RemoveAt(pos);
  279. return TRUE;
  280. }
  281. void
  282. CObListPlus::RemoveAt(
  283. IN POSITION & pos
  284. )
  285. /*++
  286. Routine Description:
  287. Override of RemoveAt to delete the pointer at the position
  288. given
  289. Arguments:
  290. POSITION pos : Position of item to delete
  291. Return Value:
  292. None.
  293. Notes:
  294. The item will only be deleted if this is an "owned" list.
  295. --*/
  296. {
  297. CObject * pItem = GetAt(pos);
  298. CObList::RemoveAt(pos);
  299. if (m_fOwned)
  300. {
  301. delete pItem;
  302. }
  303. }
  304. BOOL
  305. CObListPlus::SetAll(
  306. IN BOOL fDirty
  307. )
  308. /*++
  309. Routine Description:
  310. Set all elements to dirty or clean. Return TRUE if any element was dirty.
  311. Arguments:
  312. BOOL fDirty : Dirty flag to set the objects with
  313. Return Value:
  314. TRUE if any element was dirty.
  315. --*/
  316. {
  317. int cDirtyItems = 0;
  318. CObjectPlus * pob;
  319. CObListIter obli(*this);
  320. while (NULL != (pob = (CObjectPlus *)obli.Next()))
  321. {
  322. cDirtyItems += pob->IsDirty();
  323. pob->SetDirty(fDirty);
  324. }
  325. SetDirty(fDirty);
  326. return cDirtyItems > 0;
  327. }
  328. int
  329. CObListPlus::FindElement(
  330. IN CObject * pobSought
  331. ) const
  332. /*++
  333. Routine Description:
  334. Find the object in the list.
  335. Arguments:
  336. CObject * pobSought : Object to be looked for
  337. Return Value:
  338. The index of the object, or -1 if it wasn't found.
  339. --*/
  340. {
  341. CObject * pob;
  342. CObListIter obli(*this);
  343. for (int i = 0;
  344. (NULL != (pob = obli.Next())) && pob != pobSought;
  345. i++);
  346. return pob
  347. ? i
  348. : -1;
  349. }
  350. //
  351. // Sorting structure
  352. //
  353. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  354. typedef struct
  355. {
  356. CObjectPlus * pObj; // Pointer to object to be sorted
  357. CObjectPlus::PCOBJPLUS_ORDER_FUNC pFunc; // Pointer to ordering function
  358. } CBOWNEDLIST_SORT_HELPER;
  359. int _cdecl
  360. CObListPlus::SortHelper(
  361. IN const void * pa,
  362. IN const void * pb
  363. )
  364. /*++
  365. Routine Description:
  366. This static member function is used to quick sort an array of structures
  367. as declared above. Each element contains the object pointer and a
  368. pointer to the object's member function to be invoked for comparison.
  369. Arguments:
  370. const void * pa : Sorting help struct 1
  371. const void * pb : Sorting help struct 2
  372. Return Value:
  373. Sort return code
  374. --*/
  375. {
  376. CBOWNEDLIST_SORT_HELPER *pHelp1 = (CBOWNEDLIST_SORT_HELPER *)pa,
  377. *pHelp2 = (CBOWNEDLIST_SORT_HELPER *)pb;
  378. return (pHelp1->pObj->*pHelp1->pFunc)(pHelp2->pObj);
  379. }
  380. DWORD
  381. CObListPlus::Sort(
  382. IN CObjectPlus::PCOBJPLUS_ORDER_FUNC pOrderFunc
  383. )
  384. /*++
  385. Routine Description:
  386. Sort the list by recreating it entirely.
  387. Arguments:
  388. CObjectPlus::PCOBJPLUS_ORDER_FUNC pOrderFunc : Ordering function
  389. Return Value:
  390. Error code
  391. --*/
  392. {
  393. DWORD err = ERROR_SUCCESS;
  394. int cItems = (int)GetCount();
  395. if (cItems < 2)
  396. {
  397. return err;
  398. }
  399. CObjectPlus * pObNext;
  400. CObListIter obli(*this);
  401. BOOL fOwned = SetOwnership(FALSE);
  402. int i;
  403. CBOWNEDLIST_SORT_HELPER * paSortHelpers = NULL;
  404. //
  405. // Allocate the helper array
  406. //
  407. paSortHelpers = AllocMemByType(cItems, CBOWNEDLIST_SORT_HELPER);
  408. if (paSortHelpers == NULL)
  409. {
  410. return ERROR_NOT_ENOUGH_MEMORY;
  411. }
  412. //
  413. // Fill the helper array.
  414. //
  415. for (i = 0; NULL != (pObNext = (CObjectPlus *)obli.Next()); i++)
  416. {
  417. paSortHelpers[i].pFunc = pOrderFunc;
  418. paSortHelpers[i].pObj = pObNext;
  419. }
  420. //
  421. // Release all object pointer references. Note that we
  422. // forced "owned" to FALSE above.
  423. //
  424. RemoveAll();
  425. ASSERT(GetCount() == 0);
  426. //
  427. // Sort the helper array
  428. //
  429. ::qsort( (void *) paSortHelpers,
  430. cItems,
  431. sizeof(paSortHelpers[0]),
  432. SortHelper
  433. );
  434. //
  435. // Refill the list from the helper array.
  436. //
  437. for (i = 0; i < cItems; i++ )
  438. {
  439. AddTail(paSortHelpers[i].pObj);
  440. }
  441. ASSERT(GetCount() == cItems);
  442. //
  443. // Delete the working array
  444. //
  445. FreeMem(paSortHelpers);
  446. //
  447. // Restore the object ownership state
  448. //
  449. SetOwnership(fOwned);
  450. return err;
  451. }
  452. CObListIter::CObListIter(
  453. IN const CObListPlus & obList
  454. )
  455. /*++
  456. Routine Description:
  457. Constructor of ObOwnedList iterator
  458. Arguments:
  459. const CObListPlus & obList : List to be iterated
  460. Return Value:
  461. N/A
  462. --*/
  463. : m_obList(obList)
  464. {
  465. Reset();
  466. }
  467. void
  468. CObListIter::Reset()
  469. /*++
  470. Routine Description:
  471. Reset the iterator
  472. Arguments:
  473. None
  474. Return Value:
  475. None
  476. --*/
  477. {
  478. m_pos = m_obList.GetCount()
  479. ? m_obList.GetHeadPosition()
  480. : NULL;
  481. }
  482. CObject * CObListIter::Next()
  483. /*++
  484. Routine Description:
  485. Get the next object in the list, or NULL
  486. Arguments:
  487. None
  488. Return Value:
  489. The next object in the list, or NULL
  490. --*/
  491. {
  492. return m_pos == NULL
  493. ? NULL
  494. : m_obList.GetNext(m_pos);
  495. }