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.

309 lines
7.1 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. marshal.c
  5. Abstract:
  6. Implements some common GUM apis for marshalling and unmarshalling
  7. arguments to GUM update procedures.
  8. Author:
  9. John Vert (jvert) 8/27/1996
  10. Revision History:
  11. --*/
  12. #include "gump.h"
  13. PVOID
  14. GumpMarshallArgs(
  15. IN DWORD ArgCount,
  16. IN va_list ArgList,
  17. OUT DWORD *pBufferSize
  18. )
  19. /*++
  20. Routine Description:
  21. Helper routine for marshalling up a bunch of arguments into
  22. a single buffer.
  23. Arguments:
  24. ArgCount - Supplies the number of arguments.
  25. ArgList - Supplies the variable length arguments. These must come
  26. in pairs, so there must be 2*ArgCount additional arguments.
  27. pBufferSize - Returns the length of the allocated buffer.
  28. Return Value:
  29. A pointer to the allocated buffer. The caller must free this.
  30. NULL on failure.
  31. --*/
  32. {
  33. DWORD i;
  34. DWORD BufSize;
  35. DWORD Length;
  36. LPDWORD Buffer;
  37. PUCHAR Pointer;
  38. PUCHAR Source;
  39. va_list OriginalList;
  40. OriginalList = ArgList;
  41. //
  42. // round ArgCount to an even number. This causes the first data area to be
  43. // quadword aligned
  44. //
  45. BufSize = (( ArgCount + 1 ) & ~1 ) * sizeof(DWORD);
  46. //
  47. // the va_list is a set of (length, pointer) tuples.
  48. //
  49. for (i=0; i < ArgCount; i++) {
  50. Length = va_arg(ArgList, DWORD);
  51. //
  52. // Round up to architecture appropriate boundary.
  53. //
  54. Length = (Length + (sizeof(DWORD_PTR) - 1 )) & ~( sizeof(DWORD_PTR) - 1 );
  55. BufSize += Length;
  56. va_arg(ArgList, PUCHAR);
  57. }
  58. Buffer = LocalAlloc(LMEM_FIXED, BufSize);
  59. if (Buffer == NULL) {
  60. return(NULL);
  61. }
  62. *pBufferSize = BufSize;
  63. //
  64. // Now copy in all the arguments
  65. //
  66. // Set Pointer to point after the array of offsets.
  67. //
  68. Pointer = (PUCHAR)(Buffer + (( ArgCount + 1 ) & ~1 ));
  69. for (i=0; i < ArgCount; i++) {
  70. //
  71. // Set offset of argument in array
  72. //
  73. // Since this is an offset in a buffer where BufSize < 2^32 then it
  74. // is reasonable that Pointer - Buffer should be < 2^32
  75. //
  76. Buffer[i] = (DWORD)(Pointer - (PUCHAR)Buffer);
  77. Length = va_arg(OriginalList, DWORD);
  78. Source = va_arg(OriginalList, PUCHAR);
  79. CopyMemory(Pointer, Source, Length);
  80. //
  81. // Round up to architecture appropriate boundary.
  82. //
  83. Length = (Length + (sizeof(DWORD_PTR) - 1 )) & ~( sizeof(DWORD_PTR) - 1 );
  84. //
  85. // Adjust pointer for next argument.
  86. //
  87. Pointer += Length;
  88. }
  89. return(Buffer);
  90. }
  91. DWORD
  92. GumSendUpdateEx(
  93. IN GUM_UPDATE_TYPE UpdateType,
  94. IN DWORD DispatchIndex,
  95. IN DWORD ArgCount,
  96. ...
  97. )
  98. /*++
  99. Routine Description:
  100. Sends an update to all active nodes in the cluster. All
  101. registered update handlers for the specified UpdateType
  102. are called on each node. Any registered update handlers
  103. for the current node will be called on the same thread.
  104. This is useful for correct synchronization of the data
  105. structures to be updated.
  106. This is different than GumSendUpdate in that it takes a
  107. variable number of arguments. The number of variable
  108. arguments is specified by the ArgCount argument. The format
  109. is pairs of length/pointer arguments. For example:
  110. GumSendUpdateEx(UpdateType,
  111. MyContext,
  112. 3,
  113. Length1, Pointer1,
  114. Length2, Pointer2,
  115. Length3, Pointer3);
  116. Arguments:
  117. UpdateType - Supplies the type of update. This determines
  118. which update handlers will be called and the sequence
  119. number to be used.
  120. DispatchIndex - Supplies an index into the dispatch table
  121. for the specified update type. The receiving side will
  122. unmarshall the arguments and call the update routine
  123. for this dispatch index.
  124. ArgCount - Supplies the number of arguments.
  125. Return Value:
  126. ERROR_SUCCESS if the request is successful.
  127. Win32 error code on failure.
  128. --*/
  129. {
  130. PVOID Buffer;
  131. DWORD BufLength;
  132. DWORD Status;
  133. va_list arglist;
  134. //
  135. // Make sure there is really a handler for this dispatch routine.
  136. //
  137. if (GumTable[UpdateType].Receivers != NULL) {
  138. CL_ASSERT(DispatchIndex < GumTable[UpdateType].Receivers->DispatchCount);
  139. }
  140. //
  141. // Format the arguments into a common buffer.
  142. //
  143. va_start(arglist, ArgCount);
  144. Buffer = GumpMarshallArgs(ArgCount, arglist, &BufLength);
  145. va_end(arglist);
  146. if (Buffer == NULL) {
  147. return(ERROR_NOT_ENOUGH_MEMORY);
  148. }
  149. Status = GumSendUpdate(UpdateType,
  150. DispatchIndex,
  151. BufLength,
  152. Buffer);
  153. LocalFree(Buffer);
  154. return(Status);
  155. }
  156. PVOID GumMarshallArgs(
  157. OUT LPDWORD lpdwBufLength,
  158. IN DWORD dwArgCount,
  159. ...)
  160. {
  161. PVOID Buffer=NULL;
  162. va_list arglist;
  163. va_start(arglist, dwArgCount);
  164. Buffer = GumpMarshallArgs(dwArgCount, arglist, lpdwBufLength);
  165. va_end(arglist);
  166. return (Buffer);
  167. }
  168. #ifdef GUM_POST_SUPPORT
  169. John Vert (jvert) 11/18/1996
  170. POST is disabled for now since nobody uses it.
  171. DWORD
  172. GumPostUpdateEx(
  173. IN GUM_UPDATE_TYPE UpdateType,
  174. IN DWORD DispatchIndex,
  175. IN DWORD ArgCount,
  176. ...
  177. )
  178. /*++
  179. Routine Description:
  180. Posts an update to all active nodes in the cluster. All
  181. registered update handlers for the specified UpdateType
  182. are called on each node. Any registered update handlers
  183. for the current node will be called on the same thread.
  184. This is useful for correct synchronization of the data
  185. structures to be updated.
  186. This is different than GumPostUpdate in that it takes a
  187. variable number of arguments. The number of variable
  188. arguments is specified by the ArgCount argument. The format
  189. is pairs of length/pointer arguments. For example:
  190. GumPostUpdateEx(UpdateType,
  191. MyContext,
  192. 3,
  193. Length1, Pointer1,
  194. Length2, Pointer2,
  195. Length3, Pointer3);
  196. Arguments:
  197. UpdateType - Supplies the type of update. This determines
  198. which update handlers will be called and the sequence
  199. number to be used.
  200. DispatchIndex - Supplies an index into the dispatch table
  201. for the specified update type. The receiving side will
  202. unmarshall the arguments and call the update routine
  203. for this dispatch index.
  204. ArgCount - Supplies the number of arguments.
  205. Return Value:
  206. ERROR_SUCCESS if the request is successful.
  207. Win32 error code on failure.
  208. --*/
  209. {
  210. PVOID Buffer;
  211. DWORD BufLength;
  212. DWORD Status;
  213. va_list arglist;
  214. //
  215. // Format the arguments into a common buffer.
  216. //
  217. va_start(arglist, ArgCount);
  218. Buffer = GumpMarshallArgs(ArgCount, arglist, &BufLength);
  219. va_end(arglist);
  220. if (Buffer == NULL) {
  221. return(ERROR_NOT_ENOUGH_MEMORY);
  222. }
  223. Status = GumPostUpdate(UpdateType,
  224. DispatchIndex,
  225. BufLength,
  226. Buffer);
  227. return(Status);
  228. }
  229. #endif