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.

403 lines
10 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. DWORD
  157. GumSendUpdateExReturnInfo(
  158. IN GUM_UPDATE_TYPE UpdateType,
  159. IN DWORD DispatchIndex,
  160. OUT PGUM_NODE_UPDATE_HANDLER_STATUS ReturnStatusBuffer,
  161. IN DWORD ArgCount,
  162. ...
  163. )
  164. /*++
  165. Routine Description:
  166. Sends an update to all active nodes in the cluster. All
  167. registered update handlers for the specified UpdateType
  168. are called on each node. Any registered update handlers
  169. for the current node will be called on the same thread.
  170. This is useful for correct synchronization of the data
  171. structures to be updated.
  172. This is different than GumSendUpdate in that it takes a
  173. variable number of arguments. The number of variable
  174. arguments is specified by the ArgCount argument. The format
  175. is pairs of length/pointer arguments. For example:
  176. GumSendUpdateExReturnInfo(UpdateType,
  177. MyContext,
  178. MyReturnStatusBuffer
  179. 3,
  180. Length1, Pointer1,
  181. Length2, Pointer2,
  182. Length3, Pointer3);
  183. Arguments:
  184. UpdateType - Supplies the type of update. This determines
  185. which update handlers will be called and the sequence
  186. number to be used.
  187. DispatchIndex - Supplies an index into the dispatch table
  188. for the specified update type. The receiving side will
  189. unmarshall the arguments and call the update routine
  190. for this dispatch index.
  191. ReturnStatusBuffer - Return buffer recording the execution status of
  192. the handler invoked on each node during an update.
  193. ArgCount - Supplies the number of arguments.
  194. Return Value:
  195. ERROR_SUCCESS if the request is successful.
  196. Win32 error code on failure.
  197. Remarks:
  198. The code in this function and the code in function GumSendUpdateEx()
  199. must be in sync.
  200. --*/
  201. {
  202. PVOID Buffer;
  203. DWORD BufLength;
  204. DWORD Status;
  205. va_list arglist;
  206. //
  207. // Make sure there is really a handler for this dispatch routine.
  208. //
  209. if (GumTable[UpdateType].Receivers != NULL) {
  210. CL_ASSERT(DispatchIndex < GumTable[UpdateType].Receivers->DispatchCount);
  211. }
  212. //
  213. // Format the arguments into a common buffer.
  214. //
  215. va_start(arglist, ArgCount);
  216. Buffer = GumpMarshallArgs(ArgCount, arglist, &BufLength);
  217. va_end(arglist);
  218. if (Buffer == NULL) {
  219. return(ERROR_NOT_ENOUGH_MEMORY);
  220. }
  221. Status = GumSendUpdateReturnInfo(UpdateType,
  222. DispatchIndex,
  223. ReturnStatusBuffer,
  224. BufLength,
  225. Buffer);
  226. LocalFree(Buffer);
  227. return(Status);
  228. }
  229. PVOID GumMarshallArgs(
  230. OUT LPDWORD lpdwBufLength,
  231. IN DWORD dwArgCount,
  232. ...)
  233. {
  234. PVOID Buffer=NULL;
  235. va_list arglist;
  236. va_start(arglist, dwArgCount);
  237. Buffer = GumpMarshallArgs(dwArgCount, arglist, lpdwBufLength);
  238. va_end(arglist);
  239. return (Buffer);
  240. }
  241. #ifdef GUM_POST_SUPPORT
  242. John Vert (jvert) 11/18/1996
  243. POST is disabled for now since nobody uses it.
  244. DWORD
  245. GumPostUpdateEx(
  246. IN GUM_UPDATE_TYPE UpdateType,
  247. IN DWORD DispatchIndex,
  248. IN DWORD ArgCount,
  249. ...
  250. )
  251. /*++
  252. Routine Description:
  253. Posts an update to all active nodes in the cluster. All
  254. registered update handlers for the specified UpdateType
  255. are called on each node. Any registered update handlers
  256. for the current node will be called on the same thread.
  257. This is useful for correct synchronization of the data
  258. structures to be updated.
  259. This is different than GumPostUpdate in that it takes a
  260. variable number of arguments. The number of variable
  261. arguments is specified by the ArgCount argument. The format
  262. is pairs of length/pointer arguments. For example:
  263. GumPostUpdateEx(UpdateType,
  264. MyContext,
  265. 3,
  266. Length1, Pointer1,
  267. Length2, Pointer2,
  268. Length3, Pointer3);
  269. Arguments:
  270. UpdateType - Supplies the type of update. This determines
  271. which update handlers will be called and the sequence
  272. number to be used.
  273. DispatchIndex - Supplies an index into the dispatch table
  274. for the specified update type. The receiving side will
  275. unmarshall the arguments and call the update routine
  276. for this dispatch index.
  277. ArgCount - Supplies the number of arguments.
  278. Return Value:
  279. ERROR_SUCCESS if the request is successful.
  280. Win32 error code on failure.
  281. --*/
  282. {
  283. PVOID Buffer;
  284. DWORD BufLength;
  285. DWORD Status;
  286. va_list arglist;
  287. //
  288. // Format the arguments into a common buffer.
  289. //
  290. va_start(arglist, ArgCount);
  291. Buffer = GumpMarshallArgs(ArgCount, arglist, &BufLength);
  292. va_end(arglist);
  293. if (Buffer == NULL) {
  294. return(ERROR_NOT_ENOUGH_MEMORY);
  295. }
  296. Status = GumPostUpdate(UpdateType,
  297. DispatchIndex,
  298. BufLength,
  299. Buffer);
  300. return(Status);
  301. }
  302. #endif