1146 lines
67 KiB
Plaintext
1146 lines
67 KiB
Plaintext
|
|
|||
|
// This file is not used, but is retained so we can look and see what was here originally.
|
|||
|
|
|||
|
|
|||
|
/* Yes this file actually compiles!
|
|||
|
|
|||
|
CallObjects:A Suite of Interfaces forManipulatingCall Frames asObjects
|
|||
|
|
|||
|
Copyright (C) 1995-1999 Microsoft Corporation. All rights reserved.
|
|||
|
|
|||
|
Robert Atkinson
|
|||
|
05 February, 1999
|
|||
|
|
|||
|
This interface suite is an architecture for talking to an engine by which variousmanipulations can be performed on call
|
|||
|
frames, including marshalling, persistence, stack walking, and the like.
|
|||
|
|
|||
|
*/
|
|||
|
|
|||
|
import "oaidl.idl";
|
|||
|
|
|||
|
interface ICallInterceptor;
|
|||
|
interface ICallUnmarshal;
|
|||
|
interface ICallFrame;
|
|||
|
interface ICallFrameEvents;
|
|||
|
interface ICallFrameWalker;
|
|||
|
interface IMarshallingManager;
|
|||
|
interface IInterfaceRelated;
|
|||
|
|
|||
|
|
|||
|
/* Introduction
|
|||
|
The central interface throughwhichmanipulations of call frames (a.k.a. "activation records,"a..ka. "stack frames")is
|
|||
|
performed is ICallFrame. Once you get your hands on an ICallFrame instance, you can manipulate the underlying stack frame in
|
|||
|
severaldifferentways.Succinctlyput,ICallFrame provides theprimitive,basicbuildingblocksoutofwhich larger
|
|||
|
functionality such asmarshalling, call frame persistence, interface-pointer swizzling, and the like can be constructed. It
|
|||
|
would be conceivable, for example, to construct a generic implementation of interface proxies and stubs that operated by
|
|||
|
dispatching operations to an appropriate ICallFrame instance. Alternately, an infrastructure thatwished to build up method
|
|||
|
invocations into a queue to dispatch them at a later time could also be built out of the same primitives.
|
|||
|
|
|||
|
|
|||
|
Instances of ICallFramenever exist in an unbound state; rather, they are always attached to some activation record.
|
|||
|
Accordingly, they are not created directly with CoCreateInstance. Instead, clients get their hands on an instance of IClalFrame in
|
|||
|
one of two ways.
|
|||
|
|
|||
|
In the first instantiation technique, you create what is known as an interceptorimplementation of a given interface. Upon
|
|||
|
receipt of a call, the interceptor's implementation of the interface manufactures an appropriate ICallFrameobject and then
|
|||
|
delivers an ::OnCall notification to an instance ofICallFrameEventspreviously registeredwiththe interceptor using the
|
|||
|
ICallInterceptor interface.
|
|||
|
|
|||
|
The second technique by which instances of ICallFrame are obtained is that of unmarshalling themarshalled form of an
|
|||
|
incoming call. The incoming call comes in in the form of a bag 'o bytes in a buffer, but semantically tagged as belonging to a
|
|||
|
certain interface (a certain IID) and a certain method number therein. An instance of the appropriate unmarshalling class is
|
|||
|
created, and interface ICallUnmarshal can be used to turn the byte stream back into an activation record.
|
|||
|
|
|||
|
Creation of interceptors and unmarshallers is carried out in the same manner. Indeed, ICallInterceptorand ICallUnmarshalare
|
|||
|
usually both supported by the same object instance. To create an interceptor for a given interface or find its unmarshaller,
|
|||
|
instantiate the proxy-stub class for the object using CoCreateInstance (rather than the usual mechanism which uses IPsFactory-
|
|||
|
Buffer). Ask for the interface IInterfaceRelated, and set the appropriate IID. Then, query for ICallInterceptor or ICallUnmarshal and
|
|||
|
party on.
|
|||
|
*/
|
|||
|
|
|||
|
|
|||
|
/* ICallFrame
|
|||
|
ICallFrame is the workhorse interface through which manipulation of call frames is performed. An ICallFrameinstance never
|
|||
|
exits freely in an unbound state; rather an ICallFrame instance is always bound to some particular actual invocation, and so has
|
|||
|
an associated method number, a stack frame that can be walked, and so on. If the bound-to stack frame lies in user space, the
|
|||
|
call frame is a user mode call frame; this affects the behaviour of certain methods such as, e.g., ICallFrame::Copy,where only
|
|||
|
user space data may be copied from a user mode call frame.
|
|||
|
|
|||
|
An instance of ICallFrame canperform various interesting transformations on a call frame (a.k.a. stack frame, activation
|
|||
|
record). For example, the call can be marshalled, or it can bepersisted. The call frame can be walked, looking for various
|
|||
|
referenced data that might be of interest.
|
|||
|
|
|||
|
An appropriate ICallFrame could serve as the internal engine by which a COM interface proxy orinterface stub functioned.
|
|||
|
The interface proxy or stub would contain generic logic to drive the marshalling process, calling upon services in ICallFrame
|
|||
|
to actually carry out the interface-specific work. Different customers could use the same pieces to, say, persist a call frame
|
|||
|
instead of marshalling it. */
|
|||
|
[uuid(D573B4B0-894E-11d2-B8B6-00C04FB9618A), object, pointer_default(unique), local]
|
|||
|
interface ICallFrame : IUnknown
|
|||
|
{
|
|||
|
|
|||
|
/* Bookkeeping */
|
|||
|
|
|||
|
|
|||
|
typedef struct
|
|||
|
{
|
|||
|
ULONG iMethod; /* the method number within to which this information applies */
|
|||
|
BOOL fHasInValues; /* Are there any in-values (other than the receiver) */
|
|||
|
BOOL fHasInOutValues; /* Are there any in-out values */
|
|||
|
BOOL fHasOutValues; /* Are there any out-values other than an HRESULT or void return value */
|
|||
|
BOOL fDerivesFromIDispatch; /* whether this interface in question derived from IDispatch or not. */
|
|||
|
LONG cInInterfacesMax; /* If >= 0, is an absolute upper bound on the number in-interfaces; if < 0, the
|
|||
|
method may have an unbounded number of in-interfaces. Of course, if == 0,
|
|||
|
there are definitely no in-interfaces. */
|
|||
|
LONG cInOutInterfacesMax; /* If >= 0, is an absolute upper bound on the number in-out-interfaces; if <
|
|||
|
0, the method may have an unbounded number of in-out-interfaces Of course,
|
|||
|
if == 0, there are definitely no in-out-interfaces. */
|
|||
|
LONG cOutInterfacesMax; /* If >= 0, is an absolute upper bound on the number out-interfaces; if < 0,
|
|||
|
the method may have an unbounded number of out-interfaces Of course, if
|
|||
|
== 0, there are definitely no out-interfaces. */
|
|||
|
LONG cTopLevelInInterfaces; /* The number of parameters which are simply [in] interface pointers, and so
|
|||
|
are passed in the actual stack frame itself (this, of course, can never be
|
|||
|
unbounded).*/
|
|||
|
IID iid; /* the interface on which this is a call */
|
|||
|
ULONG cMethod; /* the total number of methods in that interface */
|
|||
|
ULONG cParams; /* the number of parameters in this method, NOT counting the receiver */
|
|||
|
} CALLFRAMEINFO;
|
|||
|
|
|||
|
typedef struct
|
|||
|
{
|
|||
|
BOOLEAN fIn; /* is this an in parameter */
|
|||
|
BOOLEAN fOut; /* is this an out parameter */
|
|||
|
ULONG stackOffset; /* offset in bytes from stack location of the frame to start of param */
|
|||
|
ULONG cbParam; /* size occupied by parameter on the stack */
|
|||
|
} CALLFRAMEPARAMINFO;
|
|||
|
|
|||
|
HRESULT GetInfo /*
|
|||
|
Return miscellaneous information about the call frame. The information returned is a static analysis of the method, not a dynamic one,
|
|||
|
in that it is based on an analysis of the method signature only, not the actual current contents of the call frame. For example, the static
|
|||
|
analysis might indicate that this method has the potential of having an in-interface, but because of, say, a union switch, a given call
|
|||
|
might not actually have any such interfaces.
|
|||
|
|
|||
|
Return value Meaning
|
|||
|
S_OK All is well
|
|||
|
E_UNEXPECTED An unexpected error occurred. */
|
|||
|
(
|
|||
|
[out] CALLFRAMEINFO* pInfo /* place at which interesting information about this call frame is returned */
|
|||
|
);
|
|||
|
|
|||
|
HRESULT GetIIDAndMethod /*
|
|||
|
Faster form of GetInfo that just returns the IID and /or the method number.
|
|||
|
|
|||
|
Return value Meaning
|
|||
|
S_OK All is well
|
|||
|
E_UNEXPECTED An unexpected error occurred. */
|
|||
|
(
|
|||
|
[out] IID* pIID, /* optional */
|
|||
|
[out] ULONG* piMethod /* optional */
|
|||
|
);
|
|||
|
|
|||
|
HRESULT GetNames /*
|
|||
|
Return a string representation of the method or interface name of this call, if such is available. If a requested name is not available,
|
|||
|
then a NULL string is returned.
|
|||
|
|
|||
|
Return value Meaning
|
|||
|
S_OK All is well
|
|||
|
E_UNEXPECTED An unexpected error occurred. */
|
|||
|
(
|
|||
|
[out] LPWSTR* pwszInterface, /* OPTIONAL: the place to return the interface name */
|
|||
|
[out] LPWSTR* pwszMethod /* OPTIONAL: the place to return the method name */
|
|||
|
);
|
|||
|
|
|||
|
PVOID GetStackLocation /*
|
|||
|
Return the stack location onto which this call frame is bound. Notice that this method is not HRESULT-returning; the return value is
|
|||
|
rather the requested stack location. */
|
|||
|
|
|||
|
(
|
|||
|
);
|
|||
|
|
|||
|
void SetStackLocation /*
|
|||
|
Set the stack location onto which this call frame is bound. This method is rarely used. Note that the stack frame provided must
|
|||
|
conform to the same IID and method number as that for which the call frame was initially created. */
|
|||
|
|
|||
|
(
|
|||
|
[in] PVOID pvStack /* The stack location for the frame. */
|
|||
|
);
|
|||
|
|
|||
|
void SetReturnValue /*
|
|||
|
Set the return value stored within this call frame. */
|
|||
|
|
|||
|
(
|
|||
|
[in] HRESULT hr /* The new return value. */
|
|||
|
);
|
|||
|
|
|||
|
HRESULT GetReturnValue /*
|
|||
|
Get the return value stored within this call frame. Note: the return value of this method is the requested return value stored in this call
|
|||
|
frame. It is not the success or failure of the request to retrieve said return value. */
|
|||
|
|
|||
|
(
|
|||
|
);
|
|||
|
|
|||
|
HRESULT GetParamInfo /*
|
|||
|
Return miscellaneous information a particular parameter in this invocation.
|
|||
|
|
|||
|
Return value Meaning
|
|||
|
S_OK All is well
|
|||
|
E_UNEXPECTED An unexpected error occurred. */
|
|||
|
(
|
|||
|
[in] ULONG iparam, /* zero-origin parameter number */
|
|||
|
[out] CALLFRAMEPARAMINFO* pInfo /* place at which interesting information about this call frame is returned */
|
|||
|
);
|
|||
|
|
|||
|
HRESULT SetParam /*
|
|||
|
Set the value of a particular parameter in this frame, if possible, given the data types involved.
|
|||
|
|
|||
|
Return value Meaning
|
|||
|
S_OK All is well
|
|||
|
E_UNEXPECTED An unexpected error occurred. */
|
|||
|
(
|
|||
|
[in] ULONG iparam, /* zero-origin parameter number */
|
|||
|
[in] VARIANT* pvar /* the new value for this parameter */
|
|||
|
);
|
|||
|
|
|||
|
HRESULT GetParam /*
|
|||
|
Return the value of a particular parameter in this frame, if possible, given the data types involved.
|
|||
|
|
|||
|
Return value Meaning
|
|||
|
S_OK All is well
|
|||
|
E_UNEXPECTED An unexpected error occurred. */
|
|||
|
(
|
|||
|
[in] ULONG iparam, /* zero-origin parameter number */
|
|||
|
[out] VARIANT* pvar /* the current value of this parameter */
|
|||
|
);
|
|||
|
|
|||
|
/* Copying& Freeing */
|
|||
|
|
|||
|
typedef enum /* flags used in ::Copy. Use exactly one value. */
|
|||
|
{
|
|||
|
CALLFRAME_COPY_NESTED = 1, /* Client guarantees that he will only use the copied call frame in a manner where its lifetime
|
|||
|
is properly nested in the lifetime of its parent frame. When this flag is used, very significant
|
|||
|
optimizations can be made and memory allocations avoided by cleverly sharing actual
|
|||
|
parameter data.
|
|||
|
Indeed, with this flag specified to a Copy operation, only the i nterface pointer s transitively
|
|||
|
reachable in the source frames are guaranteed to be deep copied and thus in the copy be
|
|||
|
stored in memory separate from that in which they are stored in the source frames; other
|
|||
|
data types may actually in the copied frame share memory with the source if the Copy
|
|||
|
operation is intelligent enough to do so
|
|||
|
A consequence is that whichever of these three CALLFRAME_COPY flags are passed to
|
|||
|
ICallFrame::Copy, the interface pointers see by optionally provided interface walkers (see
|
|||
|
the method specification) may always be modified if desired without consequence of
|
|||
|
disturbing the interface pointers residing in the parent frame. However, if
|
|||
|
CALL_FRAME_COPY_NESTED is used, then the same cannot be said of any other type
|
|||
|
data types. .*/
|
|||
|
CALLFRAME_COPY_INDEPENDENT = 2, /* Client requests that the copied call frame have a lifetime which is wholly independent
|
|||
|
from its parent */
|
|||
|
CALLFRAME_COPY_NONLOCAL = 3, /* Only significant when executing a frame copy operation in kernel mode. Requests that not
|
|||
|
only should the lifetime of the copied frame data be independent of its parent, but that the
|
|||
|
actual copied data should reside in the opposite memory space from that of the parent data:
|
|||
|
if the parent frame is a user mode frame, the copied frame will be a kernel mode frame, and
|
|||
|
visa versa */
|
|||
|
} CALLFRAME_COPY;
|
|||
|
|
|||
|
HRESULT Copy /*
|
|||
|
Create a deep copy of this call frame. A deep copy of a call frame copies the frame and all of the data that is reachable therefrom. It
|
|||
|
can be roughly conceptualized asmarshalling the frame, then immediately unmarshalling it; however, in practice it willbe
|
|||
|
significantly more efficient than actually carrying out these two steps. A copy of a call frame can only be made of the in-values in the
|
|||
|
'before-call' state of the frame; once the frame has been invoked, and thus contains out-values, it cannot be copied.
|
|||
|
|
|||
|
As data is copied, interface pointers in the copied data can be noted. If an ICallFrameWalkerimplementation is provided in the
|
|||
|
optional pWalker parameter, then pWalker->OnWalkInterface will be called for each interface pointer that is copied, just after the copy
|
|||
|
of the interface pointer value is made. The call frame implementation itself simply copies interface pointers as binary values.
|
|||
|
Specifically, no reference count adjustments of any form are performed. If some other behaviour is desired, the pWalker parameter
|
|||
|
must be used.
|
|||
|
|
|||
|
Recall that a "user mode" call frame is one whose underlying stack pointer resides in user mode. In the process of copying a user-
|
|||
|
mode call frame, kernel mode implementations of the Copy operation ensures that only user-mode addresses are used in the data
|
|||
|
transitively reachable from the frame. Should an illegal non-user mode address be provided, an HRESULT derived from the error
|
|||
|
ERROR_INVALID_ADDRESS is returned.
|
|||
|
|
|||
|
The copyControl parameter controls how much if any the data within the copied frame can be shared with data in the parent frame.
|
|||
|
See the CALLFRAME_COPY enumeration for details.
|
|||
|
|
|||
|
The successfully copied frame is returned to the caller through *ppFrame. The frame so returned has a (normal) indefinite lifetime.
|
|||
|
The caller is explicitly responsible for calling Free on the frame copy in order to clean up the copied data. This must always be done,
|
|||
|
or memory leakage will occur; the call frame does not clean up the copied data automatically by itself.
|
|||
|
|
|||
|
|
|||
|
Return value Meaning
|
|||
|
S_OK All is well
|
|||
|
HRESULT_FROM_WIN32(ERROR_INVALID_ADDRESS) An attempt was made to copy from a user mode stack frame data which itself did not lie in
|
|||
|
user space.
|
|||
|
CALLFRAME_E_ALREADYINVOKED An invocation has already been made from this frame.
|
|||
|
E_UNEXPECTED An unexpected error occurred. */
|
|||
|
(
|
|||
|
[in] CALLFRAME_COPY copyControl, /* Controls how much the child frame can share data with the parent frame */
|
|||
|
[in] ICallFrameWalker* pWalker, /* Optional. If provided, then OnWalkInterface is called for each copied
|
|||
|
interface pointer after the copy has been made. If a walker is not provided,
|
|||
|
then the any interface pointers encountered are AddRef'd. For kernel mode
|
|||
|
clients copying user mode frames, this is unlikely to be reasonable: such
|
|||
|
clients should almost certainly provide a walker to handle things safely. */
|
|||
|
[out] ICallFrame** ppFrame /* place at which new frame is returned */
|
|||
|
);
|
|||
|
|
|||
|
HRESULT Free /*
|
|||
|
First, optionally propagate the out-values of the frame to another destination frame, which is often a parent from which this frame was
|
|||
|
originally copied. This propagation is logically a deep copy, but if the source and destination frames are either both user mode or both
|
|||
|
kernel mode frames, then much actual allocation and deallocation can be avoided by simply transferring ownership of data from
|
|||
|
source to destination frames.
|
|||
|
|
|||
|
If there are any [in,out] parameters in the destination frame, then the propagation first requires that the existing values that reside in
|
|||
|
those [in,out] parameters be freed. For interface pointers found therein, the freeing action can be controlled by providing a callback
|
|||
|
object in pWalkerDestFree.
|
|||
|
|
|||
|
Once [in,out] parameters in the destination frame are freed, the propagation of out-values is (logically) carried out. If pWalkerCopy is
|
|||
|
provided, then it is called on each interface pointer contained in the propagated out-values.
|
|||
|
|
|||
|
Second, optionally free some or all of the remaining data accessible from the source frame. Whether in, in-out, and / or out parameters
|
|||
|
are to be freed are indicated by the particular flags that may be indicated in the flags parameter, see the enumeration CALL-
|
|||
|
FRAME_FLAGS for details.
|
|||
|
|
|||
|
Third, optionally, initialize out-parameters to appropriate NULL states, including the return value.
|
|||
|
|
|||
|
Return value Meaning
|
|||
|
S_OK All is well
|
|||
|
E_UNEXPECTED An unexpected error occurred. */
|
|||
|
(
|
|||
|
[in] ICallFrame* pframeArgsDest, /* Optional. If present, is the stack pointer of the call frame to which the
|
|||
|
out-values should be copied before freeing is carried out. */
|
|||
|
[in] ICallFrameWalker* pWalkerDestFree, /* Optional. Ignored unless pframeArgsDest is also non-NULL. Indicates
|
|||
|
a callback object which should be notified as interface pointers residing
|
|||
|
in in-out parameters of pframeArgsDest need be freed. If absent, then
|
|||
|
such interface pointers are simply Release()ed. */
|
|||
|
[in] ICallFrameWalker* pWalkerCopy, /* Optional. Ignored unless pframeArgsDest is also non-NULL. Indicates
|
|||
|
a call back object which should be notified as interfaces are copied
|
|||
|
during call frame copying. If absent, then interface pointers are
|
|||
|
AddRef()d as the copy is made. */
|
|||
|
[in] DWORD freeFlags, /* flags drawn from the enumeration CALLFRAME_FREE */
|
|||
|
|
|||
|
[in] ICallFrameWalker* pWalkerFree, /* Optional. If specified, then a call back will be made for each interface
|
|||
|
pointer encountered as freeing is carried out. If absent, then interface
|
|||
|
pointers encountered during freeing are Release()d.
|
|||
|
Note: when freeing a frame and specifying a pframeArgsDest which is in
|
|||
|
the same memory spa ce as that of the receiver frame, then o nl y
|
|||
|
pWalkerCopy is called on each interface pointer, not both pWalkerCopy
|
|||
|
and pWalkerFree as one might perhaps expect.
|
|||
|
Note to kernel mode users: If caller of Free is in kernel mode worried
|
|||
|
about the possibility of user mode malicious guy then he should either a)
|
|||
|
always provide a walker to deal with the callbacks, or b) make sure by
|
|||
|
the way that the frame got created in the first place that there aren't any
|
|||
|
user mode objects lying around. */
|
|||
|
[in] DWORD nullFlags /* Values drawn from the enumeration CALFRAME_NULL_FLAGS. If
|
|||
|
any bits are set herein, then once any freeing has been carried out, then
|
|||
|
out-values and-or in-out values which are pointers are to be set to NULL.
|
|||
|
If no bits are set, then this NULLing need not be carried out after the
|
|||
|
freeing, though it is legal for the implementation to NULL the freed
|
|||
|
pointers anyway.
|
|||
|
Note that it is legal to NULL the out values without first having freed
|
|||
|
them. This is commonly done on the client side in the situation where the
|
|||
|
server was not actually invoked so no unmarshalling of return values was
|
|||
|
attempted. */
|
|||
|
);
|
|||
|
|
|||
|
enum CALLFRAME_FREE /* a bitfield enumeration: use one or more values in ::Free */
|
|||
|
{
|
|||
|
CALLFRAME_FREE_NONE = 0,
|
|||
|
CALLFRAME_FREE_IN = 1, /* If TRUE, then in-values are to be freed. This includes both the data referenced
|
|||
|
therefrom an any top level pointer (should there be one).
|
|||
|
|
|||
|
If FALSE, in-values are to be left alone.
|
|||
|
|
|||
|
In a marshalling situation, this is typically set to TRUE on the s erve r side after clialng the
|
|||
|
object in order to free the in-parameters that were allocated by the system during
|
|||
|
unmarshalling of the in-values */
|
|||
|
CALLFRAME_FREE_INOUT = 2, /* If TRUE, then the data referenced in in-out-values is to be freed. The top-level pointer,
|
|||
|
which is the actual parameter value, is not, however freed. But see also
|
|||
|
CALLFRAME_FREE_TOP_INOUT below.
|
|||
|
|
|||
|
If FALSE, then in-out-values are not freed; existing contents thereof are ignored.
|
|||
|
|
|||
|
On the server side, this is typically used post-call, as in CALLFRAME_FREE_IN. On the
|
|||
|
client side, this is used in the situation where the sever was not actually invoked (and so
|
|||
|
unmarshalling of return values was not attempted) and in the situation where there was a
|
|||
|
failure during unmarshalling of the return values. */
|
|||
|
CALLFRAME_FREE_OUT = 4, /* If TRUE, then data referenced in out-values is to be freed. The top-level pointer, which
|
|||
|
is the actual parameter value, is not, however, freed.
|
|||
|
|
|||
|
If FALSE, then out-values are not freed; existing contents thereof are ignored.
|
|||
|
|
|||
|
On the server side, this is, again, used post call as in CALLFRAME_FREE_IN. On the
|
|||
|
client side, this is typically only use in the even of a failure during unmarshalling of return
|
|||
|
values. */
|
|||
|
CALLFRAME_FREE_TOP_INOUT = 8, /* If TRUE, then for [in,out] parameters, the top level pointer, which is the actual
|
|||
|
parameter value, is to be freed. */
|
|||
|
CALLFRAME_FREE_TOP_OUT = 16, /* If TRUE, then for [out] parameters, the top level pointer, which is the actual parameter
|
|||
|
value, is to be freed. */
|
|||
|
CALLFRAME_FREE_ALL = 31, /* Combination of all freeing flags */
|
|||
|
};
|
|||
|
|
|||
|
enum CALLFRAME_NULL /* a bitfield enumeration: use one or more values in ::Free */
|
|||
|
{
|
|||
|
CALLFRAME_NULL_NONE = 0, /* no values are to be NULLed */
|
|||
|
CALLFRAME_NULL_INOUT = 2, /* in-out values are to be NULLed */
|
|||
|
CALLFRAME_NULL_OUT = 4, /* out-values are to be NULLed */
|
|||
|
CALLFRAME_NULL_ALL = 6, /* combination of the above two flags */
|
|||
|
};
|
|||
|
|
|||
|
HRESULT FreeParam/*
|
|||
|
Free just a particular parameter in this frame. This method provides a proper subset of the effect that can be carried out by
|
|||
|
ICallFrame::Free. Specifically, ICallFrame::Free provides out-valuepropagation behaviour,which this method does not, and
|
|||
|
ICallFrame::Free acts on all the parameters in the method, whereas this method only acts on a particular method.
|
|||
|
|
|||
|
Return value Meaning
|
|||
|
S_OK All is well
|
|||
|
E_UNEXPECTED An unexpected error occurred. */
|
|||
|
(
|
|||
|
[in] ULONG iparam, /* the parameter number to be freed */
|
|||
|
[in] DWORD freeFlags, /* as in ICallFrame::Free */
|
|||
|
[in] ICallFrameWalker* pWalkerFree, /* as in ICallFrame::Free. */
|
|||
|
[in] DWORD nullFlags /* as in ICallFrame::Free. */
|
|||
|
);
|
|||
|
|
|||
|
|
|||
|
/*Walking */
|
|||
|
|
|||
|
HRESULT WalkFrame /*
|
|||
|
Walk this call frame, looking for interface pointers transitively reachable from the arguments of the frame.
|
|||
|
|
|||
|
Return value Meaning
|
|||
|
S_OK All is well
|
|||
|
E_UNEXPECTED An unexpected error occurred. */
|
|||
|
(
|
|||
|
[in] DWORD walkWhat, /* Values taken from CALLFRAME_WALK, indicating what combination of
|
|||
|
[in], [in,out], or [out] parameters are to be walked */
|
|||
|
[in] ICallFrameWalker* pWalker /* The call back through which we notify of interface pointers we have found.
|
|||
|
*/
|
|||
|
);
|
|||
|
|
|||
|
enum CALLFRAME_WALK /* a bitfield enumeration: use one or more values in ::WalkFrame */
|
|||
|
{
|
|||
|
CALLFRAME_WALK_IN = 1, /* in values are to be walked */
|
|||
|
CALLFRAME_WALK_INOUT = 2, /* in-out values are to be walked */
|
|||
|
CALLFRAME_WALK_OUT = 4, /* out-values are to be walked */
|
|||
|
};
|
|||
|
|
|||
|
/*Marshalling */
|
|||
|
|
|||
|
|
|||
|
/* CALLFRAME_MARSHALCONTEXT
|
|||
|
A structure used to pass about information about the context in which marshalling is to be carried out. */
|
|||
|
|
|||
|
typedef struct
|
|||
|
{
|
|||
|
BOOLEAN fIn; /* Whether we are to marshal the in-values or the out-values. In a
|
|||
|
marshalling situation, the in-values are marshalled on the client side,
|
|||
|
and the out-values are marshalled on the server side. */
|
|||
|
DWORD dwDestContext; /* <20> */
|
|||
|
LPVOID pvDestContext; /* <20> */
|
|||
|
IMarshallingManager* mshlmgr; /* Engine responsible for marshalling object interfaces */
|
|||
|
GUID guidTransferSyntax; /* The transfer syntax with which the marshalling should occur. */
|
|||
|
} CALLFRAME_MARSHALCONTEXT;
|
|||
|
|
|||
|
HRESULT GetMarshalSizeMax /*
|
|||
|
Return a reasonable upper limit on the amount of buffer size that would be needed were::Marshalto be called. Typically, a
|
|||
|
marshalling engine (such as an interface proxy) calls ::GetMarshalSizeMaxto learn how big of a buffer is need, talks to some other
|
|||
|
party (such as the channel) to allocate the buffer, then calls ::Marshal toactually carry out the marshalling.
|
|||
|
|
|||
|
Return value Meaning
|
|||
|
S_OK All is well
|
|||
|
E_UNEXPECTED An unexpected error occurred. */
|
|||
|
(
|
|||
|
[in] CALLFRAME_MARSHALCONTEXT* pmshlContext, /* Context information about how we'd go about marshalling */
|
|||
|
[in] MSHLFLAGS mshlflags, /* As in the IMarshal interface */
|
|||
|
[out] ULONG* pcbBufferNeeded /* Size of the buffer that will be needed */
|
|||
|
);
|
|||
|
|
|||
|
HRESULT Marshal /*
|
|||
|
Ask call frame to turn itself and its transitively-reachable data into a flat buffer.
|
|||
|
|
|||
|
The act of marshalling a call frame never disturbs the frame. When marshalling in-values, after a call to ::Marshal, whether successful
|
|||
|
or not, the in-versions of in-out values are still present, and out-only values are still undefined. When marshalling out-values, after a
|
|||
|
call to ::Marshal, whether successful or not, the out-parameters are still present and valid.
|
|||
|
|
|||
|
If this function fails (returns an error), then it is a no-op (or may as well be assumed to be, as nothing further can be done by the caller
|
|||
|
to clean up). Resources such as memory transiently allocated during the attempted marshalling have been freed, and so on.
|
|||
|
|
|||
|
The act of marshalling interfaces warrants special attention. Non-interface data which is marshalled is simply flattened in place into
|
|||
|
the output buffer in a standard way. Interface pointers are marshalled by asking the providedIMarshallingManager*to do the
|
|||
|
marshalling; should none be provided, CoMarshalInterface is used. Different marshalling behaviour, 'marshlialng' vs. 'persisting', can
|
|||
|
be achieved by using different IMarshallingManager* engines to carry out themarshalling operation. See the description of
|
|||
|
IMarshallingManager for further information.
|
|||
|
|
|||
|
Return value Meaning
|
|||
|
S_OK All is well
|
|||
|
E_UNEXPECTED An unexpected error occurred. */
|
|||
|
(
|
|||
|
[in] CALLFRAME_MARSHALCONTEXT* pmshlContext, /* Context information about how we'd go about marshalling */
|
|||
|
[in] MSHLFLAGS mshlflags, /* As in the IMarshal interface */
|
|||
|
[in,size_is(cbBuffer)] PVOID pBuffer, /* Buffer into which we should put the marshalled data */
|
|||
|
[in] ULONG cbBuffer, /* The size of the buffer in bytes */
|
|||
|
[out] ULONG* pcbBufferUsed, /* Optional. Size of the buffer that was actually used */
|
|||
|
|
|||
|
[out] RPCOLEDATAREP* pdataRep, /* Optional. If provided, then through here is returned the NDR
|
|||
|
data representation with which the data was marshalled. For
|
|||
|
Win32 machines, this is always 0X00000010L, which is 'little
|
|||
|
endian, ASCII characters, IEEE floats. See also IRpcChannel-
|
|||
|
Buffer::GetBuffer */
|
|||
|
[out] ULONG* prpcFlags /* Optional. If provided, then through here is returned RPC flags
|
|||
|
associated with the call. See also IRpcChannelBuffer::-
|
|||
|
GetBuffer */
|
|||
|
);
|
|||
|
|
|||
|
HRESULT Unmarshal /*
|
|||
|
Unmarshal a packet of data containing the previously marshalled out-vuales of a call into this already-extiisng activation record.
|
|||
|
|
|||
|
As a side effect of the unmarshalling, the in-versions of any in-out values are freed (interface pointers are released) in order that they
|
|||
|
may be replaced with their out-versions.
|
|||
|
|
|||
|
On exit, all the in-out-values and out-values will always be set to reasonable values, either (a) an in-version of an in-out-value, (b) an
|
|||
|
out-value successfully unmarshalled from the returned data, or (c) a value explicitly initialized to NULL. On failure return, the caller
|
|||
|
will typically want to call ::Free in order to clean up those values which are not in fact NULL.
|
|||
|
|
|||
|
Return value Meaning
|
|||
|
S_OK All is well
|
|||
|
E_UNEXPECTED An unexpected error occurred. */
|
|||
|
(
|
|||
|
[in,size_is(cbBuffer)] PVOID pBuffer, /* Buffer containing the marshalled out-values */
|
|||
|
[in] ULONG cbBuffer, /* The size of the buffer in bytes */
|
|||
|
[in] RPCOLEDATAREP dataRep, /* The data representation with which the data was marshalled
|
|||
|
*/
|
|||
|
[in] CALLFRAME_MARSHALCONTEXT* pcontext, /* Manager etc responsible for unmarshalling interface
|
|||
|
references */
|
|||
|
[out] ULONG* pcbUnmarshalled /* Optional. Is the number of bytes that were successfully
|
|||
|
unmarshalled. This parameter is returned even in error
|
|||
|
situations */
|
|||
|
);
|
|||
|
|
|||
|
HRESULT ReleaseMarshalData /*
|
|||
|
Release resources that may be being held by interface pointers residing in a packet of marshalled data. This method finds all interface
|
|||
|
pointers in the packet, and, in effect, calls CoReleaseMarshalData on each one.
|
|||
|
|
|||
|
Logically speaking, ReleaseMarshalData must alwaysbe ultimately called exactly once to clean up the resources held in the
|
|||
|
marshalled buffer, though typically (in the MRSHLFLAGS_NORMALcase) this is done as a side effect of the act of unmarshalling and
|
|||
|
so need not be carried out explicitly.
|
|||
|
|
|||
|
This method can function correctly on both marshalled in-parameters and marshalled out-parameters.
|
|||
|
|
|||
|
Return value Meaning
|
|||
|
S_OK All is well
|
|||
|
E_UNEXPECTED An unexpected error occurred. */
|
|||
|
(
|
|||
|
[in,size_is(cbBuffer)] PVOID pBuffer, /* Buffer containing the marshalled out-values */
|
|||
|
[in] ULONG cbBuffer, /* The size of the buffer in bytes */
|
|||
|
[in] ULONG ibFirstRelease, /* The first byte in the buffer which is to actually be released; a
|
|||
|
value of zero implies interface pointers in the whole buffer are to
|
|||
|
be released. The idea is that marshalled interface pointers prior
|
|||
|
to the indicated byte are assumed to have already been released
|
|||
|
by some other mechanism */
|
|||
|
[in] RPCOLEDATAREP dataRep, /* The data representation with which the data was marshalled
|
|||
|
*/
|
|||
|
[in] CALLFRAME_MARSHALCONTEXT* pcontext /* Manager etc responsible for unmarshalling interface
|
|||
|
references */
|
|||
|
);
|
|||
|
|
|||
|
/* Invocation */
|
|||
|
|
|||
|
HRESULT Invoke /*
|
|||
|
Apply this activation record to an object. In a marshalling situation, typically this is carried out on the server side, and is the means by
|
|||
|
which the work of the actual object is accomplished.
|
|||
|
|
|||
|
Generally speaking, carrying out the invocation involves allocating a new stack frame, shallow-copying down the data in the original
|
|||
|
frame, then calling the appropriate method in the indicated object. The object invoked may then chose to modify out-parameters
|
|||
|
which are reachable from the copied frame, according to the appropriate semantics of the invocation. When the invocation returns
|
|||
|
from the object, the call frame automatically captures the return value <20> la ICallFrame::SetReturnValue.
|
|||
|
|
|||
|
Return value Meaning
|
|||
|
S_OK All is well
|
|||
|
CALLFRAME_E_ALREADYINVOKED An invocation has already been made from this frame.
|
|||
|
E_UNEXPECTED An unexpected error occurred. */
|
|||
|
(
|
|||
|
[in] void* pvReceiver, /* The interface on which the invocation is to occur. Caller is responsible for ensuring that
|
|||
|
this interface is in fact of the appropriate IID; the ::Invoke implementation will simply do a
|
|||
|
cast and assume that that is the case. */
|
|||
|
... /* This is a VARARGS function. Additional parameters, if any, are used to fill unbound
|
|||
|
values in the activation record other than the receiver, if any should be present. At present,
|
|||
|
no known methods require this. */
|
|||
|
|
|||
|
);
|
|||
|
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
/* ICallIndirect
|
|||
|
ICallIndirect is an interface by which an invocation can be caused to be carried out on an object with an i ndirec t reference to the
|
|||
|
invocation's arguments, rather than the traditional direct call. A given instance of ICallIndirect supports indirect invocations for
|
|||
|
just one IID.
|
|||
|
|
|||
|
The actual detailed semantics of how to carry out an indirect call are independent of the ICallIndirect interface itself; they are
|
|||
|
instead specific to the implementation of the interface. For example, implementations of ICallIndirect found in call interceptors
|
|||
|
(see below) carry out the call by constructing and appropriate IaCllFrame instance and then invoking IClalFrameEvents::OnCall in
|
|||
|
the registered sink. Other implementations might do some appropriate munging of the invocation's arguments, then forward
|
|||
|
thecallon tosomeactualspecificobject,presumablyonepreviously registeredwith theICallIndirectusingsome
|
|||
|
implementation-specific means.
|
|||
|
|
|||
|
*/
|
|||
|
[uuid(D573B4B1-894E-11d2-B8B6-00C04FB9618A), object, pointer_default(unique), local]
|
|||
|
interface ICallIndirect : IUnknown
|
|||
|
{
|
|||
|
|
|||
|
HRESULT CallIndirect /*
|
|||
|
Invoke one of the methods in the interface that this interceptor intercepts, but with an indirect reference to the arguments of the
|
|||
|
invocation.
|
|||
|
|
|||
|
Return value Meaning
|
|||
|
S_OK All is well
|
|||
|
E_UNEXPECTED An unexpected error occurred. */
|
|||
|
(
|
|||
|
[out] HRESULT* phrReturn, /* the value returned from the invocation of the method */
|
|||
|
[in] ULONG iMethod, /* the method number which should be invoked */
|
|||
|
[in] void* pvArgs, /* pointer to the stack frame with which to make the invocation. Details of the exact
|
|||
|
representation of this stack frame are processor-architecture specific */
|
|||
|
[out] ULONG* cbArgs /* on exit, the number of bytes which should be popped from the stack in order to clear the
|
|||
|
stack of the arguments to this invocation */
|
|||
|
);
|
|||
|
|
|||
|
|
|||
|
HRESULT GetMethodInfo /*
|
|||
|
Return miscellaneous information about the a method in this interface. The information returned is a static analysis of the method, not
|
|||
|
a dynamic one, in that it is based on an analysis of the method signature only, not the actual current contents of the call frame. For
|
|||
|
example, the static analysis might indicate that this method has the potential of having an in-interface, but because of, say, a union
|
|||
|
switch, a given call might not actually have any such interfaces.
|
|||
|
|
|||
|
This method is equivalent to the GetInfo and GetNames methods in ICallFrame, but avoids the need to actually make any invocation to
|
|||
|
get the information.
|
|||
|
|
|||
|
Return value Meaning
|
|||
|
S_OK All is well
|
|||
|
E_UNEXPECTED An unexpected error occurred. */
|
|||
|
(
|
|||
|
[in] ULONG iMethod, /* the method number which should be considered */
|
|||
|
[out] CALLFRAMEINFO* pInfo, /* place at which interesting information about said method is returned */
|
|||
|
[out] LPWSTR* pwszMethod /* OPTIONAL: the place to return the method name, if available */
|
|||
|
);
|
|||
|
|
|||
|
|
|||
|
HRESULT GetStackSize /*
|
|||
|
Return the number of bytes which should be popped from the stack in order to return from an invocation of the indicated method.
|
|||
|
This is equivalent to the value returned via the cbArgs parameter to CallIndirect, but avoids the need to actually make any invocation
|
|||
|
to get the information.
|
|||
|
|
|||
|
Return value Meaning
|
|||
|
S_OK All is well
|
|||
|
E_UNEXPECTED An unexpected error occurred. */
|
|||
|
(
|
|||
|
[in] ULONG iMethod, /* the method number which should be considered */
|
|||
|
[out] ULONG* cbArgs /* on exit, the number of bytes which should be popped from the stack in order to clear the stack
|
|||
|
of the arguments to an invocation of this method number */
|
|||
|
);
|
|||
|
|
|||
|
|
|||
|
HRESULT GetIID /*
|
|||
|
Return the (most derived) interface id supported by this ICallIndirect implementation.
|
|||
|
|
|||
|
Return value Meaning
|
|||
|
S_OK All is well
|
|||
|
E_UNEXPECTED An unexpected error occurred. */
|
|||
|
(
|
|||
|
[out] IID* piid, /* Optional: the interface in question */
|
|||
|
[out] BOOL* pfDerivesFromIDispatch, /* Optional: whether said interface ultimately derives frrom IDispatch */
|
|||
|
|
|||
|
[out] ULONG* pcMethod, /* Optional: the number of methods in that interface */
|
|||
|
[out] LPWSTR* pwszInterface /* OPTIONAL: the place to return the interface name, if available */
|
|||
|
);
|
|||
|
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
|
|||
|
/* ICallInterceptor
|
|||
|
ICallInterceptor thecentral interfacesupportedby interface interceptors.This interfacesupports theregistrationand
|
|||
|
unregistration of sinks wishing to be notified of calls made directly on the interface in the normal way. In addition, this
|
|||
|
interface provides ameans bywhich an invocation can be caused to be carried outwith an indirect reference to the
|
|||
|
invocation's arguments.
|
|||
|
|
|||
|
All implementations of ICallInterceptor also implement the interface that they intercept.
|
|||
|
|
|||
|
Notice that the ICallInterceptor interface derives from ICallIndirect.
|
|||
|
|
|||
|
*/
|
|||
|
[uuid(60C7CA75-896D-11d2-B8B6-00C04FB9618A), object, pointer_default(unique), local]
|
|||
|
interface ICallInterceptor : ICallIndirect
|
|||
|
{
|
|||
|
|
|||
|
HRESULT RegisterSink /*
|
|||
|
Register a sink for receiving notifications of method calls. Only a single sink may be registered with an interceptor at any given time.
|
|||
|
Registering a sink of NULL is legal, and causes the interceptor to release any previously registered sink that it might be holding on to.
|
|||
|
|
|||
|
Return value Meaning
|
|||
|
S_OK All is well
|
|||
|
E_UNEXPECTED An unexpected error occurred. */
|
|||
|
(
|
|||
|
[in] ICallFrameEvents* psink
|
|||
|
);
|
|||
|
|
|||
|
HRESULT GetRegisteredSink /*
|
|||
|
Return the presently registered event sink, if any.
|
|||
|
|
|||
|
Return value Meaning
|
|||
|
S_OK All is well; the registered sink, if any, is returned.
|
|||
|
CO_E_OBJNOTREG There is no sink presently registered with this interceptor.
|
|||
|
E_UNEXPECTED An unexpected error occurred. */
|
|||
|
(
|
|||
|
[out] ICallFrameEvents** ppsink
|
|||
|
);
|
|||
|
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
/* ICallFrameEvents
|
|||
|
ICallFrameEvents is the interface on which method call notifications are delivered.
|
|||
|
|
|||
|
*/
|
|||
|
[uuid(FD5E0843-FC91-11d0-97D7-00C04FB9618A), object, pointer_default(unique), local]
|
|||
|
interface ICallFrameEvents : IUnknown
|
|||
|
{
|
|||
|
|
|||
|
HRESULT OnCall /*
|
|||
|
Informs the sink of the receipt of a method call on the interceptor. The sink is provided with an ICallFrame instance which is bound to
|
|||
|
the intercepted incoming method invocation. Through that sink the call frame can be manipulated in various ways.
|
|||
|
|
|||
|
On return from OnCall, the interceptor assumes that by some means the out-values of the method have been appropriately initialized
|
|||
|
as needed, if any; the interceptor does not itself manipulate the call frame further in any way. Typically, the OnCall implementation
|
|||
|
will have set the out-values by somemeans, either by invoking the call frame on an object, successfully unmarshalling some
|
|||
|
previously marshaled out-values, or NULLing them with ICallFrame::Free.
|
|||
|
|
|||
|
The return value should also have been appropriately set during the call in a similar manner. See also ICallFrame::SetReturnValue.
|
|||
|
|
|||
|
Return value Meaning
|
|||
|
S_OK All is well
|
|||
|
E_UNEXPECTED An unexpected error occurred. */
|
|||
|
(
|
|||
|
[in] ICallFrame* pFrame /* A call frame bound to the just-received invocation */
|
|||
|
);
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
/*ICallUnmarshal
|
|||
|
ICallUnmarshal is typically used on the server (receiving) side of a remote invocation. An appropriate instance of ICallUnmarshal
|
|||
|
can be used to transform back into an call frame a method invocation previously marshalled by a call to IClalFrame::Marshal on
|
|||
|
the client (sending) side. Once such a reconstituted call frame is obtained, the call can be (e.g.) carried out on an actual object
|
|||
|
using ICallFrame::Invoke.
|
|||
|
|
|||
|
ICallUnmarshal is typically implemented by the interceptor for a given interface.
|
|||
|
*/
|
|||
|
[uuid(5333B003-2E42-11d2-B89D-00C04FB9618A), object, pointer_default(unique), local]
|
|||
|
interface ICallUnmarshal : IUnknown
|
|||
|
{
|
|||
|
|
|||
|
HRESULT Unmarshal /*
|
|||
|
Turn a marshalled packet of data back into an activation record in preparation to being able to actually carry out an invocation or
|
|||
|
other manipulation of the activation record. It must always be the case that the packet of data passed here toICallUnmar-
|
|||
|
shal::Unmarshal contains the in-values of a call; see also ICallFrame::Unmarshal which deals with out-values.
|
|||
|
|
|||
|
Return value Meaning
|
|||
|
S_OK All is well
|
|||
|
E_UNEXPECTED An unexpected error occurred. */
|
|||
|
(
|
|||
|
[in] ULONG iMethod, /* The method number which is to be unmarshalled. A value of 0xFFFFFFFF
|
|||
|
indicates that the caller instead expects the method number to be determined
|
|||
|
from the data to be unmarshalled. Which of these two is appropriate depends
|
|||
|
on the protocol used to transfer the marshalling packet from client to server. */
|
|||
|
[in,size_is(cbBuffer)]
|
|||
|
PVOID pBuffer, /* Buffer from which the activation record is to be reconstituted */
|
|||
|
[in] ULONG cbBuffer, /* Size of the buffer in bytes */
|
|||
|
[in] BOOL fForceBufferCopy, /* If true, then during the unmarshal process the engine will copy and retain
|
|||
|
the passed-in buffer so long as it needs it. If false, however, then caller
|
|||
|
promises that the buffer passed in will remain valid for at least as long as the
|
|||
|
ICallFrame returned herefrom is still alive */
|
|||
|
[in] RPCOLEDATAREP dataRep, /* The data representation with which the data was marshalled */
|
|||
|
[in] CALLFRAME_MARSHALCONTEXT *
|
|||
|
pcontext, /* Manager etc responsible for unmarshalling interface references */
|
|||
|
[out] ULONG* pcbUnmarshalled, /* Optional. Is the number of bytes that were successfully unmarshalled. This
|
|||
|
parameter is returned even in error situations. */
|
|||
|
[out] ICallFrame** ppFrame /* A call frame bound to the just-unmarshalled invocation */
|
|||
|
);
|
|||
|
|
|||
|
HRESULT ReleaseMarshalData /*
|
|||
|
Release resources that may be being held by interface pointers residing in a packet of marshalled data. This method finds all interface
|
|||
|
pointers in the packet, and, in effect, calls CoReleaseMarshalData on each one.
|
|||
|
|
|||
|
Logically speaking, ReleaseMarshalData must alwaysbe ultimately called exactly once to clean up the resources held in the
|
|||
|
marshalled buffer, though typically (in the MRSHLFLAGS_NORMALcase) this is done as a side effect of the act of unmarshalling and
|
|||
|
so need not be carried out explicitly.
|
|||
|
|
|||
|
This method can function correctly on both marshalled in-parameters and marshalled out-parameters.
|
|||
|
|
|||
|
Return value Meaning
|
|||
|
S_OK All is well
|
|||
|
E_UNEXPECTED An unexpected error occurred. */
|
|||
|
(
|
|||
|
[in] ULONG iMethod, /* the method number whose data is to be released */
|
|||
|
[in,size_is(cbBuffer)] PVOID pBuffer, /* Buffer containing the marshalled out-values */
|
|||
|
[in] ULONG cbBuffer, /* The size of the buffer in bytes */
|
|||
|
[in] ULONG ibFirstRelease, /* The first byte in the buffer which is to actually be released; a
|
|||
|
value of zero implies interface pointers in the whole buffer are to
|
|||
|
be released. The idea is that marshalled interface pointers prior
|
|||
|
to the indicated byte are assumed to have already been released
|
|||
|
by some other mechanism */
|
|||
|
[in] RPCOLEDATAREP dataRep, /* The data representation with which the data was marshalled
|
|||
|
*/
|
|||
|
[in] CALLFRAME_MARSHALCONTEXT* pcontext /* Manager etc responsible for unmarshalling interface
|
|||
|
references */
|
|||
|
);
|
|||
|
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
/* ICallFrameWalker
|
|||
|
ICallFrameWalker is the callback interface used to walk a stack frame, looking for interesting values. See ICallFrame::WalkFrame.
|
|||
|
|
|||
|
*/
|
|||
|
[uuid(08B23919-392D-11d2-B8A4-00C04FB9618A), object, pointer_default(unique), local]
|
|||
|
interface ICallFrameWalker : IUnknown
|
|||
|
{
|
|||
|
|
|||
|
HRESULT OnWalkInterface /*
|
|||
|
The walker has discovered an interface in the call frame. We are informed of its IID and its location; we can manipulate the interface,
|
|||
|
and we may replace it if desired, being careful to get the reference counting right.
|
|||
|
|
|||
|
Return value Meaning
|
|||
|
S_OK All is well
|
|||
|
E_UNEXPECTED An unexpected error occurred. */
|
|||
|
(
|
|||
|
[in] REFIID iid, /* the IID of the interface that has been found */
|
|||
|
[in] PVOID* ppvInterface, /* Buffer from which the activation record is to be reconstituted */
|
|||
|
[in] BOOL fIn, /* is this an interface inside an in- or in-out-parameter? */
|
|||
|
[in] BOOL fOut /* is this an interface inside an out- or in-out-parameter? */
|
|||
|
);
|
|||
|
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
/* IMarshalSomeone
|
|||
|
IMarshalSomeone is an interface by which a client can request that some implicitly-specified object be marshalled.
|
|||
|
|
|||
|
The functionality in the interface is similar to that of IMarshal. However, the data returned by IMarshalSomone::Marshal is a full
|
|||
|
OBJREF, just as would be returned by CoMarshalInterface. This contrasts with IMarshal, wherein IMarshal::Marshal returns just
|
|||
|
the custom-marshalling-data part of an object reference.
|
|||
|
|
|||
|
*/
|
|||
|
[uuid(174F4929-53EC-11d2-B8AC-00C04FB9618A), object, pointer_default(unique), local]
|
|||
|
interface IMarshalSomeone : IUnknown
|
|||
|
{
|
|||
|
|
|||
|
HRESULT GetMarshalSizeMax /*
|
|||
|
Similar to IMarshal::GetMarshalSizeMax.
|
|||
|
|
|||
|
Return value Meaning
|
|||
|
S_OK All is well
|
|||
|
E_UNEXPECTED An unexpected error occurred. */
|
|||
|
(
|
|||
|
[in] REFIID iid,
|
|||
|
[in] void* pv,
|
|||
|
[in] DWORD dwDestContext,
|
|||
|
[in,unique] void* pvDestContext,
|
|||
|
[in] DWORD mshlflags,
|
|||
|
[out] DWORD* pSize
|
|||
|
);
|
|||
|
|
|||
|
HRESULT MarshalInterface /*
|
|||
|
Similar to IMarshal::MarshalInterface.
|
|||
|
|
|||
|
Return value Meaning
|
|||
|
S_OK All is well
|
|||
|
E_UNEXPECTED An unexpected error occurred. */
|
|||
|
(
|
|||
|
[in,unique] IStream* pstm,
|
|||
|
[in] REFIID iid,
|
|||
|
[in] void* pv,
|
|||
|
[in] DWORD dwDestContext,
|
|||
|
[in,unique] void* pvDestContext,
|
|||
|
[in] DWORD mshlflags
|
|||
|
);
|
|||
|
|
|||
|
HRESULT UnmarshalInterface /*
|
|||
|
Similar to IMarshal::UnmarshalInterface.
|
|||
|
|
|||
|
Return value Meaning
|
|||
|
S_OK All is well
|
|||
|
E_UNEXPECTED An unexpected error occurred. */
|
|||
|
(
|
|||
|
[in,unique] IStream* pstm,
|
|||
|
[in] REFIID iid,
|
|||
|
[out] void** ppv
|
|||
|
);
|
|||
|
|
|||
|
HRESULT ReleaseMarshalData /*
|
|||
|
Similar to IMarshal::ReleaseMarshalData.
|
|||
|
|
|||
|
Return value Meaning
|
|||
|
S_OK All is well
|
|||
|
E_UNEXPECTED An unexpected error occurred. */
|
|||
|
(
|
|||
|
[in,unique] IStream* pstm
|
|||
|
);
|
|||
|
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
/* IMarshallingManager
|
|||
|
IMarshallingManager instances are used as themechanismbywhich call frames actually carry out themarshalling and
|
|||
|
unmarshalling of an interface pointer.
|
|||
|
|
|||
|
*/
|
|||
|
[uuid(F6EBEB2B-C8DE-11d1-B88E-00C04FB9618A), object, pointer_default(unique), local]
|
|||
|
interface IMarshallingManager : IUnknown
|
|||
|
{
|
|||
|
|
|||
|
HRESULT GetMarshallerFor /*
|
|||
|
Return an IMarshal instance that can then be used to marshal the indicated interface on this object. Typically, the marshaller returned
|
|||
|
is implemented by the marshalling manager itself. Internally, it usually refers to either the object's IMarshal implementation, if it
|
|||
|
custom marshals itself, or a marshalling-manager-provided 'standard' IMarshal implementation.
|
|||
|
|
|||
|
Return value Meaning
|
|||
|
S_OK All is well
|
|||
|
E_UNEXPECTED An unexpected error occurred. */
|
|||
|
(
|
|||
|
[in] REFIID iidToMarshal, /* the IID of the interface to be marshalled */
|
|||
|
[in] PVOID pvInterface, /* the interface iid on the object which is to be marshalled */
|
|||
|
[out] IMarshalSomeone** ppMarshal /* a marshaller appropriate for this object */
|
|||
|
);
|
|||
|
|
|||
|
HRESULT GetStandardMarshallerFor /*
|
|||
|
Similar to GetMarshallerFor, but is guaranteed to never reference the object's IMarshal implementation, but rather always use the
|
|||
|
marshalling-manager-provided 'standard' IMarshal implementation. In this respect, this method is similar to the CoGetStnadadrMar-
|
|||
|
shal API.
|
|||
|
|
|||
|
Return value Meaning
|
|||
|
S_OK All is well
|
|||
|
E_UNEXPECTED An unexpected error occurred. */
|
|||
|
(
|
|||
|
[in] REFIID iidToMarshal, /* the IID of the interface to be marshalled */
|
|||
|
[in] PVOID pvInterface, /* the interface iid on the object which is to be marshalled */
|
|||
|
[in] LPUNKNOWN punkOuter, /* controlling unknown for the marshaller */
|
|||
|
[in] REFIID iid, /* iid sought on the returned marshaller */
|
|||
|
[out] void** ppv /* place at which marshaller is to be returned */
|
|||
|
);
|
|||
|
|
|||
|
HRESULT GetUnmarshaller /*
|
|||
|
Return an IMarshal instance whose UnmarshalInterface can be used to unmarshal an interface pointer that was marshalled previously
|
|||
|
with a the IMarshal returned from a call to GetMarshallerFor or GetStandardMarshallerFor.
|
|||
|
|
|||
|
Return value Meaning
|
|||
|
S_OK All is well
|
|||
|
E_UNEXPECTED An unexpected error occurred. */
|
|||
|
(
|
|||
|
[in] REFIID iidHint, /* The iid for which unmarshalling is required. May legally be
|
|||
|
IID_NULL, in which case the iid in question must be determined from the
|
|||
|
later unmarshalled data; this is common. */
|
|||
|
[out] IMarshalSomeone** ppMarshal /* place at which the unmarshaller is to be returned */
|
|||
|
);
|
|||
|
};
|
|||
|
|
|||
|
/* IInterfaceRelated
|
|||
|
This interface is used to provide an IID parameter required in some initialization contexts.
|
|||
|
|
|||
|
*/
|
|||
|
[uuid(D1FB5A79-7706-11d1-ADBA-00C04FC2ADC0), object, pointer_default(unique), local]
|
|||
|
interface IInterfaceRelated : IUnknown
|
|||
|
{
|
|||
|
|
|||
|
HRESULT SetIID /*
|
|||
|
Set the required IID parameter.
|
|||
|
|
|||
|
Return value Meaning
|
|||
|
S_OK All is well
|
|||
|
E_UNEXPECTED An unexpected error occurred. */
|
|||
|
(
|
|||
|
[in] REFIID iid
|
|||
|
);
|
|||
|
|
|||
|
HRESULT GetIID /*
|
|||
|
Return the underlying IID.
|
|||
|
|
|||
|
Return value Meaning
|
|||
|
S_OK All is well
|
|||
|
E_UNEXPECTED An unexpected error occurred. */
|
|||
|
(
|
|||
|
[out] IID* piid
|
|||
|
);
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
/* Error Codes
|
|||
|
We define some new error codes intended for use with the interfaces defined here.
|
|||
|
|
|||
|
*/
|
|||
|
|
|||
|
cpp_quote("#define CALLFRAME_E_ALREADYINVOKED _HRESULT_TYPEDEF_( 0x8004d090 )") /* An invocation has already been made on this call frame
|
|||
|
*/
|
|||
|
cpp_quote("#define CALLFRAME_E_COULDNTMAKECALL _HRESULT_TYPEDEF_( 0x8004d091 )") /*A requested invocation could not be carried out */
|
|||
|
|
|||
|
|
|||
|
/* APIs
|
|||
|
This architecture also defines some new top-level APIs.
|
|||
|
|
|||
|
*/
|
|||
|
[uuid(15B51D8B-9BF6-11d1-B888-00C04FB9618A), local] interface ICallFrameAPIs {
|
|||
|
|
|||
|
HRESULT __stdcall CoGetInterceptor /*
|
|||
|
Instantiate the appropriate interceptor for the indicated interface which is to be intercepted and return the newly created interceptor.
|
|||
|
|
|||
|
Return value Meaning
|
|||
|
S_OK All is well
|
|||
|
E_UNEXPECTED An unexpected error occurred. */
|
|||
|
(
|
|||
|
[in] REFIID iidIntercepted, /* the interface for which an interceptor is sought */
|
|||
|
[in] IUnknown* punkOuter, /* controlling unknown, if any, with which the interceptor is to be
|
|||
|
aggregated */
|
|||
|
[in] REFIID iid, /* the IID desired on the interceptor */
|
|||
|
[out] void** ppv /* place at which the interceptor is returned */
|
|||
|
);
|
|||
|
|
|||
|
|
|||
|
HRESULT __stdcall CoGetInterceptorFromTypeInfo /*
|
|||
|
Instantiate the appropriate interceptor for the indicated interface which is to be intercepted and return the newly created interceptor.
|
|||
|
The meta data for this interface is to be extracted from the provided typeinfo.
|
|||
|
|
|||
|
Return value Meaning
|
|||
|
S_OK All is well
|
|||
|
E_UNEXPECTED An unexpected error occurred. */
|
|||
|
(
|
|||
|
[in] REFIID iidIntercepted, /* the interface for which an interceptor is sought */
|
|||
|
[in] IUnknown* punkOuter, /* controlling unknown, if any, with which the interceptor is to be
|
|||
|
aggregated */
|
|||
|
[in] ITypeInfo* typeInfo, /* an ITypeInfo describing iidIntercepted */
|
|||
|
[in] REFIID iid, /* the IID desired on the interceptor */
|
|||
|
[out] void** ppv /* place at which the interceptor is returned */
|
|||
|
);
|
|||
|
|
|||
|
HRESULT __stdcall CoGetInterceptorForOle32 /*
|
|||
|
Instantiate the appropriate interceptor for the indicated interface which is to be intercepted and return the newly created interceptor.
|
|||
|
|
|||
|
Return value Meaning
|
|||
|
S_OK All is well
|
|||
|
E_UNEXPECTED An unexpected error occurred. */
|
|||
|
(
|
|||
|
[in] REFIID iidIntercepted, /* the interface for which an interceptor is sought */
|
|||
|
[in] IUnknown* punkOuter, /* controlling unknown, if any, with which the interceptor is to be
|
|||
|
aggregated */
|
|||
|
[in] REFIID iid, /* the IID desired on the interceptor */
|
|||
|
[out] void** ppv /* place at which the interceptor is returned */
|
|||
|
);
|
|||
|
|
|||
|
};
|
|||
|
|
|||
|
#if 0
|
|||
|
|
|||
|
|
|||
|
|
|||
|
RevisionHistory
|
|||
|
|
|||
|
1997-07-15 First draft for limited review.
|
|||
|
|
|||
|
1997-11-10 Added ICallIndirect; rearrange ICallInterceptor. Add pvDatumAux to ICallFrameWalker::OnWalkData.
|
|||
|
|
|||
|
1997-11-25 Significant minor edits and clarifications. Changed the way that return values are returned via a call frame.
|
|||
|
Reordered the presentation of some of the interfaces. Made compilable.
|
|||
|
|
|||
|
1997-12-17 Tweaked ICallFrame::Copy. Changed policy of management of class ids.
|
|||
|
|
|||
|
1998-01-07 Added ICallIndirect::GetStackSize. Added ICallFrame::GetIIDAndMethod.
|
|||
|
|
|||
|
1998-01-15 Clarified user vs. kernel mode call frames; tweaked ICallFrame::Copyaccordingly. Added ICallFrame::Get-
|
|||
|
StackLocation.Modified ICallFrame::Free to aid in copying out values back to parent call frames. Changed
|
|||
|
SetReturnValue to work only for HRESULTs. Added some error code returns. Added HRESULT out-parameter
|
|||
|
to ICallFarme::Invoke.
|
|||
|
|
|||
|
1998-01-21 Removed the funky lifetime management stuff from ICallFrame::Copy. Now it just returns you the new call
|
|||
|
frame, period. Added explicit share-if-you can parameter.
|
|||
|
|
|||
|
1998-01-24 Removed the phReturnValue parameter to ICallFrame::Invoke. Instead, invoke will set the return value in the
|
|||
|
call frame, retrievablewithGetReturnValue.ChangedICallFrame::Free's parent frameparameter tobe
|
|||
|
ICallFrame* instead of void*.
|
|||
|
|
|||
|
1998-01-27 Separated the 'walker' variables to ICallFrame::Free.
|
|||
|
|
|||
|
1998-01-30 Removed ICallFrame::Unmarshal. Moved ReleaseMarshalData from ICallFrame to ICallUnmarshal.
|
|||
|
|
|||
|
1998-02-03 Added top-level APIs. Renamed IObjectMarshaller to IMarshallingManager; enhanced same interface. Restored
|
|||
|
and fixed ICallFrame::Unmarshal.
|
|||
|
|
|||
|
1998-02-05 Added ibFirstRelease parameter to ReleaseMarshalData. Changed ICaFllrame::Freeto allow separate NULLing
|
|||
|
of out vs. in-out parameters. Added ReleaseMarshalData to ICallFrame.
|
|||
|
|
|||
|
1998-02-19 Fix CoGetInterceptor's parameters.
|
|||
|
|
|||
|
1998-03-27 Extend IMarshallingManager.
|
|||
|
|
|||
|
1998-08-04 Add comments as to when walkers are called duringICallFrame::Free. Added ICallFrame::SetStackLocation.
|
|||
|
Allowed retention of frames beyond the ICallFrameEvents::OnCallnotification. Added buffer management
|
|||
|
control to ICallUnmarshal::Unmarshal.
|
|||
|
|
|||
|
1998-08-14 Separated freeing of data referenced by out-parameters from the freeing of the actual out pointer parameter
|
|||
|
itself.
|
|||
|
|
|||
|
1998-08-26 Added third walker in Free case to free the in-out's in the parent frame. Changed OnWalkInterface to inform
|
|||
|
as to directionality of interface in question. Removed OnWalkData method. Allowed more careful control in
|
|||
|
ICallFrame::WalkFrame as to whether in-out vs. just plain in or just plain out interfaces are walked. Add in-out
|
|||
|
information toCALLFRAMEINFO.Rearrangedmethodorder inICallFrame. AddedcParamsmember to
|
|||
|
CALLFRAMEINFO; distinguished in-out information therein; renamed othermembers for clarity.Added
|
|||
|
ICallFrame::GetParamInfomethod.AddedICallFrame::FreeParammethod.AddedICallFrame::SetParamand
|
|||
|
ICallFrame::GetParam methods.
|
|||
|
|
|||
|
1998-09-15 SimplifyGetStackLocation,SetReturnValue,andGetReturnValuebasedonperformancemeasurements.
|
|||
|
Enhanced CALLFRAMEINFO with cInInterfacesMax etc. Added ICallIndirect::GetInfo.
|
|||
|
|
|||
|
1998-10-1 Removeconfusingre-useofIMarshalinterface.DefineIMarshalSomeoneinstead.Enhance
|
|||
|
CALLFRAME_MARSHALCONTEXT to include requested transfer syntax.
|
|||
|
|
|||
|
1998-11-13 Added interfaceandmethodnameretrievalmethods.ChangedIIDsofICallFrame,IllICandirect,and
|
|||
|
ICallInterceptor.
|
|||
|
|
|||
|
1998-12-01 Added mechanism to indicate whether interface derives from IDispatch.
|
|||
|
|
|||
|
1999-02-05 Call CoGetInterceptorFromTypeInfo.
|
|||
|
|
|||
|
|
|||
|
|
|||
|
Index
|
|||
|
ReleaseMarshalData...3 RegisterSink......8
|
|||
|
Free..........4 GetRegisteredSink....8
|
|||
|
C
|
|||
|
SetReturnValue.....5 ICallUnmarshal..........9
|
|||
|
CALLFRAME_COPY........6
|
|||
|
GetReturnValue.....5 Unmarshal.......9
|
|||
|
CALLFRAME_FREE........5
|
|||
|
Invoke.........5 ReleaseMarshalData...9
|
|||
|
CALLFRAME_MARSHALCONTEXT.2
|
|||
|
Copy.........6 IInterfaceRelated.........10
|
|||
|
CALLFRAME_NULL........5
|
|||
|
WalkFrame.......6 SetIID........10
|
|||
|
CoGetInterceptor.........11
|
|||
|
ICallFrameEvents.........8 GetIID........10
|
|||
|
OnCall.........8 IMarshallingManager.......10
|
|||
|
ICallFrameWalker.........9 GetMarshallerFor...10
|
|||
|
I
|
|||
|
OnWalkInterface.....9 interceptor............1
|
|||
|
ICallFrame............1
|
|||
|
OnWalkData.....10
|
|||
|
GetInfo........2
|
|||
|
ICallIndirect
|
|||
|
GetIIDAndMethod....2
|
|||
|
U
|
|||
|
CallIndirect.......7
|
|||
|
GetStackLocation....2
|
|||
|
user mode...........1, 6
|
|||
|
GetStackSize......7
|
|||
|
GetMarshalSizeMax...2
|
|||
|
GetIID.........7
|
|||
|
Marshal........3
|
|||
|
ICallInterceptor..........8
|
|||
|
Unmarshal.......3
|
|||
|
|
|||
|
#endif
|