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.

279 lines
5.8 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name :
  4. wtblobj.c
  5. Abstract:
  6. Manage a list of waitable objects and associated callbacks.
  7. Author:
  8. TadB
  9. Revision History:
  10. --*/
  11. #include <RemoteDesktop.h>
  12. #include <RemoteDesktopDBG.h>
  13. #include "wtblobj.h"
  14. ////////////////////////////////////////////////////////
  15. //
  16. // Define
  17. //
  18. #define WTBLOBJMGR_MAGICNO 0x57575757
  19. ////////////////////////////////////////////////////////
  20. //
  21. // Local Typedefs
  22. //
  23. typedef struct tagWAITABLEOBJECTMGR
  24. {
  25. #if DBG
  26. DWORD magicNo;
  27. #endif
  28. WTBLOBJ_ClientFunc funcs[MAXIMUM_WAIT_OBJECTS];
  29. HANDLE objects[MAXIMUM_WAIT_OBJECTS];
  30. PVOID clientData[MAXIMUM_WAIT_OBJECTS];
  31. ULONG objectCount;
  32. } WAITABLEOBJECTMGR, *PWAITABLEOBJECTMGR;
  33. WTBLOBJMGR
  34. WTBLOBJ_CreateWaitableObjectMgr()
  35. /*++
  36. Routine Description:
  37. Create a new instance of the Waitable Object Manager.
  38. Arguments:
  39. Return Value:
  40. NULL on error. Otherwise, a new Waitable Object Manager is
  41. returned.
  42. --*/
  43. {
  44. PWAITABLEOBJECTMGR objMgr;
  45. objMgr = ALLOCMEM(sizeof(WAITABLEOBJECTMGR));
  46. if (objMgr != NULL) {
  47. #if DBG
  48. objMgr->magicNo = WTBLOBJMGR_MAGICNO;
  49. #endif
  50. objMgr->objectCount = 0;
  51. memset(&objMgr->objects[0], 0, sizeof(objMgr->objects));
  52. memset(&objMgr->funcs[0], 0, sizeof(objMgr->funcs));
  53. memset(&objMgr->clientData[0], 0, sizeof(objMgr->clientData));
  54. }
  55. return objMgr;
  56. }
  57. VOID
  58. WTBLOBJ_DeleteWaitableObjectMgr(
  59. IN WTBLOBJMGR mgr
  60. )
  61. /*++
  62. Routine Description:
  63. Release an instance of the Waitable Object Manager that was
  64. created via a call to WTBLOBJ_CreateWaitableObjectMgr.
  65. Arguments:
  66. mgr - Waitable object manager.
  67. Return Value:
  68. NULL on error. Otherwise, a new Waitable Object Manager is
  69. returned.
  70. --*/
  71. {
  72. PWAITABLEOBJECTMGR objMgr = (PWAITABLEOBJECTMGR)mgr;
  73. #if DBG
  74. objMgr->magicNo = 0xcccccccc;
  75. #endif
  76. FREEMEM(objMgr);
  77. }
  78. DWORD
  79. WTBLOBJ_AddWaitableObject(
  80. IN WTBLOBJMGR mgr,
  81. IN PVOID clientData,
  82. IN HANDLE waitableObject,
  83. IN WTBLOBJ_ClientFunc func
  84. )
  85. /*++
  86. Routine Description:
  87. Add a new waitable object to an existing Waitable Object Manager.
  88. Arguments:
  89. mgr - Waitable object manager.
  90. clientData - Associated client data.
  91. waitableObject - Associated waitable object.
  92. func - Completion callback function.
  93. Return Value:
  94. ERROR_SUCCESS on success. Otherwise, a Windows error code is
  95. returned.
  96. --*/
  97. {
  98. ULONG objectCount;
  99. DWORD retCode = ERROR_SUCCESS;
  100. PWAITABLEOBJECTMGR objMgr = (PWAITABLEOBJECTMGR)mgr;
  101. objectCount = objMgr->objectCount;
  102. //
  103. // Make sure we don't run out of waitable objects. This version
  104. // only supports MAXIMUM_WAIT_OBJECTS waitable objects.
  105. //
  106. if (objectCount < MAXIMUM_WAIT_OBJECTS) {
  107. objMgr->funcs[objectCount] = func;
  108. objMgr->objects[objectCount] = waitableObject;
  109. objMgr->clientData[objectCount] = clientData;
  110. objMgr->objectCount++;
  111. }
  112. else {
  113. retCode = ERROR_INSUFFICIENT_BUFFER;
  114. }
  115. return retCode;
  116. }
  117. VOID
  118. WTBLOBJ_RemoveWaitableObject(
  119. IN WTBLOBJMGR mgr,
  120. IN HANDLE waitableObject
  121. )
  122. /*++
  123. Routine Description:
  124. Remove a waitable object via a call to WTBLOBJ_AddWaitableObject.
  125. Arguments:
  126. mgr - Waitable object manager.
  127. waitableObject - Associated waitable object.
  128. Return Value:
  129. NA
  130. --*/
  131. {
  132. ULONG offset;
  133. PWAITABLEOBJECTMGR objMgr = (PWAITABLEOBJECTMGR)mgr;
  134. //
  135. // Find the waitable object in the list, using a linear search.
  136. //
  137. for (offset=0; offset<objMgr->objectCount; offset++) {
  138. if (objMgr->objects[offset] == waitableObject) {
  139. break;
  140. }
  141. }
  142. if (offset < objMgr->objectCount) {
  143. //
  144. // Move the last items to the now vacant spot and decrement the count.
  145. //
  146. objMgr->objects[offset] = objMgr->objects[objMgr->objectCount - 1];
  147. objMgr->funcs[offset] = objMgr->funcs[objMgr->objectCount - 1];
  148. objMgr->clientData[offset] = objMgr->clientData[objMgr->objectCount - 1];
  149. //
  150. // Clear the unused spot.
  151. //
  152. objMgr->objects[objMgr->objectCount - 1] = NULL;
  153. objMgr->funcs[objMgr->objectCount - 1] = NULL;
  154. objMgr->clientData[objMgr->objectCount - 1] = NULL;
  155. objMgr->objectCount--;
  156. }
  157. }
  158. DWORD
  159. WTBLOBJ_PollWaitableObjects(
  160. WTBLOBJMGR mgr
  161. )
  162. /*++
  163. Routine Description:
  164. Poll the list of waitable objects associated with a
  165. Waitable Object manager, until the next waitable object
  166. is signaled.
  167. Arguments:
  168. waitableObject - Associated waitable object.
  169. Return Value:
  170. ERROR_SUCCESS on success. Otherwise, a Windows error status
  171. is returned.
  172. --*/
  173. {
  174. DWORD waitResult, objectOffset;
  175. DWORD ret = ERROR_SUCCESS;
  176. HANDLE obj;
  177. WTBLOBJ_ClientFunc func;
  178. PVOID clientData;
  179. PWAITABLEOBJECTMGR objMgr = (PWAITABLEOBJECTMGR)mgr;
  180. //
  181. // Wait for all the waitable objects.
  182. //
  183. waitResult = WaitForMultipleObjectsEx(
  184. objMgr->objectCount,
  185. objMgr->objects,
  186. FALSE,
  187. INFINITE,
  188. FALSE
  189. );
  190. if (waitResult != WAIT_FAILED) {
  191. objectOffset = waitResult - WAIT_OBJECT_0;
  192. //
  193. // Call the associated callback.
  194. //
  195. clientData = objMgr->clientData[objectOffset];
  196. func = objMgr->funcs[objectOffset];
  197. obj = objMgr->objects[objectOffset];
  198. func(obj, clientData);
  199. }
  200. else {
  201. ret = GetLastError();
  202. }
  203. return ret;
  204. }