Source code of Windows XP (NT5)
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.

373 lines
7.5 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. RegState.c
  5. Abstract:
  6. This module contains helper functions for maintaining
  7. user mode state for registry objects
  8. Author:
  9. Adam Edwards (adamed) 06-May-1998
  10. Key Functions:
  11. StateObjectInit
  12. StateObjectListInit
  13. StateObjectListIsEmpty
  14. StateObjectListRemove
  15. StateObjectListFind
  16. StateObjectListAdd
  17. StateObjectListClear
  18. Notes:
  19. The StateObjectList stores the most frequently accessed
  20. objects at the head of the list for quick retrieval. All
  21. objects in the list must inherit from StateObject, and must
  22. be distinguishable by a unique 32-bit key. Duplicate
  23. objects are not supported, so the client must take care
  24. not to store duplicates (two objects with the same key) in
  25. the list.
  26. --*/
  27. #ifdef LOCAL
  28. #include <rpc.h>
  29. #include "regrpc.h"
  30. #include "localreg.h"
  31. #include "regstate.h"
  32. #include <malloc.h>
  33. VOID StateObjectInit(
  34. StateObject* pObject,
  35. PVOID pvKey)
  36. /*++
  37. Routine Description:
  38. This function will initialize a StateObject. All objects
  39. which inherit from this must call this function before doing
  40. any custom initialization.
  41. Arguments:
  42. pObject -- the object to initialize.
  43. pvKey -- a unique key for the object used for searches and comparisons
  44. between objects.
  45. Return Value:
  46. None -- the function does nothing which could fail.
  47. --*/
  48. {
  49. RtlZeroMemory(pObject, sizeof(*pObject));
  50. pObject->pvKey = pvKey;
  51. }
  52. VOID StateObjectListInit(
  53. StateObjectList* pList,
  54. PVOID pvKey)
  55. /*++
  56. Routine Description:
  57. This function will initialize a StateObjectList. All objects
  58. which inherit from this must call this function before doing
  59. any custom initialization.
  60. Arguments:
  61. pList -- pointer to list to initialize.
  62. pvKey -- a unique key that identifies the list. This parameter is
  63. necessary since the list itself is a StateObject, which requires a
  64. key. It can be set to 0 if this list will not be searched for
  65. as part of another list, but should be set otherwise to a unique
  66. value.
  67. Return Value:
  68. None -- the function does nothing which could fail.
  69. --*/
  70. {
  71. StateObjectInit(
  72. (StateObject*) pList,
  73. pvKey);
  74. pList->pHead = NULL;
  75. }
  76. BOOL StateObjectListIsEmpty(StateObjectList* pList)
  77. /*++
  78. Routine Description:
  79. This function returns information on whether or not this
  80. list is empty.
  81. Arguments:
  82. pList -- pointer to list in question
  83. Return Value:
  84. TRUE if the list is empty,
  85. FALSE if not.
  86. --*/
  87. {
  88. return NULL == pList->pHead;
  89. }
  90. StateObject* StateObjectListRemove(
  91. StateObjectList* pList,
  92. PVOID pvKey)
  93. /*++
  94. Routine Description:
  95. This function will remove an object from the list --
  96. it does *not* destroy the object.
  97. Arguments:
  98. pList -- the list to remove the object from
  99. pvKey -- a unique key identifying the object to remove
  100. Return Value:
  101. a pointer to the removed object if successful,
  102. NULL otherwise
  103. --*/
  104. {
  105. StateObject* pObject;
  106. //
  107. // First, we need to find an object with the desired key
  108. //
  109. pObject = StateObjectListFind(
  110. pList,
  111. pvKey);
  112. if (!pObject) {
  113. return NULL;
  114. }
  115. //
  116. // Now that we've executed the find, the object is at the front
  117. // of the list -- we can remove it by setting the head to the
  118. // next object in the list
  119. //
  120. pList->pHead = (StateObject*) (pObject->Links.Flink);
  121. //
  122. // Make sure the new head's previous pointer is NULL since it
  123. // has no predecessor
  124. //
  125. if (pList->pHead) {
  126. pList->pHead->Links.Blink = NULL;
  127. }
  128. return pObject;
  129. }
  130. StateObject* StateObjectListFind(
  131. StateObjectList* pList,
  132. PVOID pvKey)
  133. /*++
  134. Routine Description:
  135. This function will find an object in the list
  136. Arguments:
  137. pList -- the list in which to search
  138. pvKey -- a unique key identifying the object sought
  139. Return Value:
  140. a pointer to the object if an object with a key matching pvKey is found,
  141. NULL otherwise
  142. --*/
  143. {
  144. StateObject* pCurrent;
  145. //
  146. // Loop through all objects in the list until we get to the end
  147. //
  148. for (pCurrent = pList->pHead;
  149. pCurrent != NULL;
  150. pCurrent = (StateObject*) pCurrent->Links.Flink)
  151. {
  152. //
  153. // See if this object's key matches the desired key
  154. //
  155. if (pvKey == pCurrent->pvKey) {
  156. PLIST_ENTRY pFlink;
  157. PLIST_ENTRY pBlink;
  158. //
  159. // If the desired object is at the front, this is a no op --
  160. // we don't have to move anything, just return the object
  161. //
  162. if (pCurrent == pList->pHead) {
  163. return pCurrent;
  164. }
  165. //
  166. // We need to move the found object to the front of the list
  167. //
  168. //
  169. // Remove the object from its current position
  170. // by severing its links
  171. //
  172. pBlink = pCurrent->Links.Blink;
  173. pFlink = pCurrent->Links.Flink;
  174. if (pBlink) {
  175. pBlink->Flink = pFlink;
  176. }
  177. if (pFlink) {
  178. pFlink->Blink = pBlink;
  179. }
  180. //
  181. // Re-add it to the front
  182. //
  183. StateObjectListAdd(
  184. pList,
  185. pCurrent);
  186. return pCurrent;
  187. }
  188. }
  189. //
  190. // We never found an object with the desired key above, so its
  191. // not in the list
  192. //
  193. return NULL;
  194. }
  195. VOID StateObjectListAdd(
  196. StateObjectList* pList,
  197. StateObject* pObject)
  198. /*++
  199. Routine Description:
  200. This function will add an object to the list
  201. Arguments:
  202. pList -- the list in which to add the object
  203. pObject -- pointer to an object which has been initialized
  204. with StateObjectInit; this object will be stored in the list.
  205. Return Value:
  206. None -- this function does nothing which could fail.
  207. Note:
  208. Only one object with a particular key should exist in the list. This
  209. requirement is not enforced by this function or the list itself, so
  210. clients need to ensure that they follow this rule.
  211. --*/
  212. {
  213. //
  214. // Create the links between the object and what's currently
  215. // at the front of the list
  216. //
  217. if (pList->pHead) {
  218. pObject->Links.Flink = (PLIST_ENTRY) pList->pHead;
  219. pList->pHead->Links.Blink = (PLIST_ENTRY) pObject;
  220. }
  221. //
  222. // Put the object at the front of the list
  223. //
  224. pList->pHead = pObject;
  225. pList->pHead->Links.Blink = NULL;
  226. }
  227. VOID StateObjectListClear(
  228. StateObjectList* pList,
  229. PFNDestroyObject pfnDestroy)
  230. /*++
  231. Routine Description:
  232. This function will remove and destroy all objects
  233. in the list.
  234. Arguments:
  235. pList -- the list to clear
  236. pfnDestroy -- pointer to a function which will be called for
  237. each object in order to destroy (free resources such as memory,
  238. kernel objects, etc) it.
  239. Return Value:
  240. None -- this function does nothing which could fail.
  241. --*/
  242. {
  243. StateObject* pCurrent;
  244. //
  245. // Keep removing objects until the list is empty
  246. //
  247. while (!StateObjectListIsEmpty(pList))
  248. {
  249. StateObject* pObject;
  250. //
  251. // Remove whatever's at the front of the list
  252. //
  253. pObject = StateObjectListRemove(
  254. pList,
  255. pList->pHead->pvKey);
  256. ASSERT(pObject);
  257. //
  258. // Destroy the removed object
  259. //
  260. pfnDestroy(pObject);
  261. }
  262. }
  263. #endif // LOCAL