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

/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
marshal.c
Abstract:
Implements some common GUM apis for marshalling and unmarshalling
arguments to GUM update procedures.
Author:
John Vert (jvert) 8/27/1996
Revision History:
--*/
#include "gump.h"
PVOID
GumpMarshallArgs(
IN DWORD ArgCount,
IN va_list ArgList,
OUT DWORD *pBufferSize
)
/*++
Routine Description:
Helper routine for marshalling up a bunch of arguments into
a single buffer.
Arguments:
ArgCount - Supplies the number of arguments.
ArgList - Supplies the variable length arguments. These must come
in pairs, so there must be 2*ArgCount additional arguments.
pBufferSize - Returns the length of the allocated buffer.
Return Value:
A pointer to the allocated buffer. The caller must free this.
NULL on failure.
--*/
{
DWORD i;
DWORD BufSize;
DWORD Length;
LPDWORD Buffer;
PUCHAR Pointer;
PUCHAR Source;
va_list OriginalList;
OriginalList = ArgList;
//
// round ArgCount to an even number. This causes the first data area to be
// quadword aligned
//
BufSize = (( ArgCount + 1 ) & ~1 ) * sizeof(DWORD);
//
// the va_list is a set of (length, pointer) tuples.
//
for (i=0; i < ArgCount; i++) {
Length = va_arg(ArgList, DWORD);
//
// Round up to architecture appropriate boundary.
//
Length = (Length + (sizeof(DWORD_PTR) - 1 )) & ~( sizeof(DWORD_PTR) - 1 );
BufSize += Length;
va_arg(ArgList, PUCHAR);
}
Buffer = LocalAlloc(LMEM_FIXED, BufSize);
if (Buffer == NULL) {
return(NULL);
}
*pBufferSize = BufSize;
//
// Now copy in all the arguments
//
// Set Pointer to point after the array of offsets.
//
Pointer = (PUCHAR)(Buffer + (( ArgCount + 1 ) & ~1 ));
for (i=0; i < ArgCount; i++) {
//
// Set offset of argument in array
//
// Since this is an offset in a buffer where BufSize < 2^32 then it
// is reasonable that Pointer - Buffer should be < 2^32
//
Buffer[i] = (DWORD)(Pointer - (PUCHAR)Buffer);
Length = va_arg(OriginalList, DWORD);
Source = va_arg(OriginalList, PUCHAR);
CopyMemory(Pointer, Source, Length);
//
// Round up to architecture appropriate boundary.
//
Length = (Length + (sizeof(DWORD_PTR) - 1 )) & ~( sizeof(DWORD_PTR) - 1 );
//
// Adjust pointer for next argument.
//
Pointer += Length;
}
return(Buffer);
}
DWORD
GumSendUpdateEx(
IN GUM_UPDATE_TYPE UpdateType,
IN DWORD DispatchIndex,
IN DWORD ArgCount,
...
)
/*++
Routine Description:
Sends an update to all active nodes in the cluster. All
registered update handlers for the specified UpdateType
are called on each node. Any registered update handlers
for the current node will be called on the same thread.
This is useful for correct synchronization of the data
structures to be updated.
This is different than GumSendUpdate in that it takes a
variable number of arguments. The number of variable
arguments is specified by the ArgCount argument. The format
is pairs of length/pointer arguments. For example:
GumSendUpdateEx(UpdateType,
MyContext,
3,
Length1, Pointer1,
Length2, Pointer2,
Length3, Pointer3);
Arguments:
UpdateType - Supplies the type of update. This determines
which update handlers will be called and the sequence
number to be used.
DispatchIndex - Supplies an index into the dispatch table
for the specified update type. The receiving side will
unmarshall the arguments and call the update routine
for this dispatch index.
ArgCount - Supplies the number of arguments.
Return Value:
ERROR_SUCCESS if the request is successful.
Win32 error code on failure.
--*/
{
PVOID Buffer;
DWORD BufLength;
DWORD Status;
va_list arglist;
//
// Make sure there is really a handler for this dispatch routine.
//
if (GumTable[UpdateType].Receivers != NULL) {
CL_ASSERT(DispatchIndex < GumTable[UpdateType].Receivers->DispatchCount);
}
//
// Format the arguments into a common buffer.
//
va_start(arglist, ArgCount);
Buffer = GumpMarshallArgs(ArgCount, arglist, &BufLength);
va_end(arglist);
if (Buffer == NULL) {
return(ERROR_NOT_ENOUGH_MEMORY);
}
Status = GumSendUpdate(UpdateType,
DispatchIndex,
BufLength,
Buffer);
LocalFree(Buffer);
return(Status);
}
PVOID GumMarshallArgs(
OUT LPDWORD lpdwBufLength,
IN DWORD dwArgCount,
...)
{
PVOID Buffer=NULL;
va_list arglist;
va_start(arglist, dwArgCount);
Buffer = GumpMarshallArgs(dwArgCount, arglist, lpdwBufLength);
va_end(arglist);
return (Buffer);
}
#ifdef GUM_POST_SUPPORT
John Vert (jvert) 11/18/1996
POST is disabled for now since nobody uses it.
DWORD
GumPostUpdateEx(
IN GUM_UPDATE_TYPE UpdateType,
IN DWORD DispatchIndex,
IN DWORD ArgCount,
...
)
/*++
Routine Description:
Posts an update to all active nodes in the cluster. All
registered update handlers for the specified UpdateType
are called on each node. Any registered update handlers
for the current node will be called on the same thread.
This is useful for correct synchronization of the data
structures to be updated.
This is different than GumPostUpdate in that it takes a
variable number of arguments. The number of variable
arguments is specified by the ArgCount argument. The format
is pairs of length/pointer arguments. For example:
GumPostUpdateEx(UpdateType,
MyContext,
3,
Length1, Pointer1,
Length2, Pointer2,
Length3, Pointer3);
Arguments:
UpdateType - Supplies the type of update. This determines
which update handlers will be called and the sequence
number to be used.
DispatchIndex - Supplies an index into the dispatch table
for the specified update type. The receiving side will
unmarshall the arguments and call the update routine
for this dispatch index.
ArgCount - Supplies the number of arguments.
Return Value:
ERROR_SUCCESS if the request is successful.
Win32 error code on failure.
--*/
{
PVOID Buffer;
DWORD BufLength;
DWORD Status;
va_list arglist;
//
// Format the arguments into a common buffer.
//
va_start(arglist, ArgCount);
Buffer = GumpMarshallArgs(ArgCount, arglist, &BufLength);
va_end(arglist);
if (Buffer == NULL) {
return(ERROR_NOT_ENOUGH_MEMORY);
}
Status = GumPostUpdate(UpdateType,
DispatchIndex,
BufLength,
Buffer);
return(Status);
}
#endif