[ // no object here. Not a COM interface!
uuid(4d9f4ab8-7d1c-11cf-861e-0020af6e7c57),
pointer_default(unique)
]
interface IRemoteActivation
{
const unsigned long MODE_GET_CLASS_OBJECT = 0xffffffff;
HRESULT RemoteActivation(
[in] handle_t hRpc,
[in] ORPCTHIS *ORPCthis,
[out] ORPCTHAT *ORPCthat,
[in] const GUID *Clsid,
[in, string, unique] WCHAR *pwszObjectName,
[in, unique] MInterfacePointer *pObjectStorage,
[in] DWORD ClientImpLevel,
[in] DWORD Mode,
[in] DWORD Interfaces,
[in, unique, size_is(Interfaces)] IID *pIIDs,
[in] unsigned short cRequestedProtseqs,
[in, size_is(cRequestedProtseqs)]
unsigned short RequestedProtseqs[],
[out] OXID *pOxid,
[out] DUALSTRINGARRAY **ppdsaOxidBindings,
[out] IPID *pipidRemUnknown,
[out] DWORD *pAuthnHint,
[out] COMVERSION *pServerVersion,
[out] HRESULT *phr,
[out, size_is(Interfaces)]
MInterfacePointer **ppInterfaceData,
[out, size_is(Interfaces)] HRESULT *pResults
);
}
Figure 7 SCM Endpoints
Protocol String | Description | Endpoint |
Ncadg_ip_udp | Connectionless over UDP | 135 |
Ncacn_ip_tcp | Connection-oriented over TCP | 135 |
Ncacn_nb_tcp | Connection-oriented using NetBIOS over TCP | 135 |
Ncacn_http | Connection-oriented over HTTP | 80 |
Figure 9 PDU Types
PDU Type | Protocol | Type Value |
Request | CO/CL | 0 |
Ping | CL | 1 |
Response | CO/CL | 2 |
Fault | CO/CL | 3 |
Working | CL | 4 |
Nocall | CL | 5 |
Reject | CL | 6 |
Ack | CL | 7 |
Cl_cancel | CL | 8 |
Fack | CL | 9 |
Cancel_ack | CL | 10 |
Bind | CO | 11 |
Bind_ack | CO | 12 |
Bind_nak | CO | 13 |
Alter_context | CO | 14 |
Alter_context_resp | CO | 15 |
Shutdown | CO | 17 |
Co_cancel | CO | 18 |
Orphaned | CO | 19 |
Figure 10 PDU Header
typedef struct
{
unsigned small rpc_vers = 4; // RPC protocol major version
unsigned small ptype; // packet type
unsigned small flags1; // packet flags
unsigned small flags2; // packet flags
byte drep[3]; // data representation format label
unsigned small serial_hi; // high byte of serial number
GUID object; // object identifier (Contains the IPID)
GUID if_id; // interface identifier (IID)
GUID act_id; // activity identifier
unsigned long server_boot; // server boot time
unsigned long if_vers; // interface version
unsigned long seqnum; // sequence number
unsigned short opnum; // operation number
unsigned short ihint; // interface hint
unsigned short ahint; // activity hint
unsigned short len; // length of packey body
unsigned short fragnum; // fragment number
unsigned small auth_proto; // authentication protocol id
unsigned small serial_lo; // low byte of serial number
} dc_rpc_cl_pkt_hdr_t;
Figure 11 OBJREF Structure
// Although this structure is conformant, it is always
// marshaled in little-endian byte-order.
typedef struct tagOBJREF {
unsigned long signature; // Always MEOW
unsigned long flags; // OBJREF flags
GUID iid; // interface identifier
union { // [switch_is(flags), switch_type(unsigned long)]
struct { // [case(OBJREF_STANDARD)]
STDOBJREF std; // standard objref
DUALSTRINGARRAY saResAddr; // resolver address
} u_standard;
struct { // [case(OBJREF_HANDLER)]
STDOBJREF std; // standard objref
CLSID clsid; // Clsid of handler code
DUALSTRINGARRAY saResAddr; // resolver address
} u_handler;
struct { // [case(OBJREF_CUSTOM)]
CLSID clsid; // Clsid of unmarshaling code
unsigned long cbExtension; // size of extension data
unsigned long size; // size of data that follows
byte *pData; // extension + class specific data
// [size_is(size), ref]
} u_custom;
} u_objref;
} OBJREF;
Figure 13 Tower Identifiers
Tower Identifier | Value | Description |
NCADG_IP_UDP | 0x08 |
Connectionless User Datagram Protocol |
NCACN_IP_TCP | 0x07 |
Connection-oriented Transmission Control Protocol |
NCADG_IPX | 0x0E |
Connectionless Internetwork Exchange Protocol |
NCACN_SPX | 0x0C |
Connection-oriented Sequenced Exchange Protocol |
NCACN_NB_NB | 0x12 | Connection-oriented NetBIOS |
NCACN_NB_IPX | 0x0D |
Connection-oriented NetBIOS over IPX |
NCACN_HTTP | 0x1F | Connection-oriented over HTTP |
Figure 14 IRemUnknown IDL
// The remote version of IUnknown. It is used by clients to
// query for new interfaces, get additional references (for
// marshaling), and release outstanding references.
[
object,
uuid(00000131-0000-0000-C000-000000000046)
]
interface IRemUnknown : IUnknown
{
HRESULT RemQueryInterface
(
[in] REFIPID ripid, // interface to QI on
[in] unsigned long cRefs, // count of AddRefs requested
[in] unsigned short cIids, // count of IIDs that follow
[in, size_is(cIids)] IID* iids, // IIDs to QI for
[out, size_is(,cIids)]
REMQIRESULT** ppQIResults // results returned
);
HRESULT RemAddRef
(
[in] unsigned short cInterfaceRefs,
[in, size_is(cInterfaceRefs)]
REMINTERFACEREF InterfaceRefs[],
[out, size_is(cInterfaceRefs)]
HRESULT* pResults
);
HRESULT RemRelease
(
[in] unsigned short cInterfaceRefs,
[in, size_is(cInterfaceRefs)]
REMINTERFACEREF InterfaceRefs[]
);
}
Figure 17 IOXIDResolver IDL
[ // no object here. Not a COM interface!
uuid(99fcfec4-5260-101b-bbcb-00aa0021347a),
pointer_default(unique)
]
interface IOXIDResolver
{
// Method to get the protocol sequences, string bindings
// and machine id for an object server given its OXID.
[idempotent] error_status_t ResolveOxid
(
[in] handle_t hRpc,
[in] OXID *pOxid,
[in] unsigned short cRequestedProtseqs,
[in, ref, size_is(cRequestedProtseqs)]
unsigned short arRequestedProtseqs[],
[out, ref] DUALSTRINGARRAY **ppdsaOxidBindings,
[out, ref] IPID *pipidRemUnknown,
[out, ref] DWORD *pAuthnHint
);
// Simple ping is used to ping a Set. Client machines use
// this to inform the Object exporter that it is still
// using the members of the set. Returns S_TRUE if the
// SetId is known by the Object exporter, S_FALSE if not.
[idempotent] error_status_t SimplePing
(
[in] handle_t hRpc,
[in] SETID *pSetId // Must not be zero
);
// Complex ping is used to create sets of OIDs to ping. The
// whole set can subsequently be pinged using SimplePing,
// thus reducing network traffic.
[idempotent] error_status_t ComplexPing
(
[in] handle_t hRpc,
[in, out] SETID *pSetId, // In of 0 on first
// call for new set.
[in] unsigned short SequenceNum,
[in] unsigned short cAddToSet,
[in] unsigned short cDelFromSet,
[in, unique, size_is(cAddToSet)] OID AddToSet[],
// add the Se OIDs to the set
[in, unique, size_is(cDelFromSet)] OID DelFromSet[],
// remove the Se OIDs from the set
[out] unsigned short *pPingBackoffFactor
// 2^factor = multipler
);
// In some cases the client may be unsure that a particular
// binding will reach the server. For example, when the
// oxid bindings have more then one TCP/IP binding. This
// call can be used to validate the binding from the
// client.
[idempotent] error_status_t ServerAlive
(
[in] handle_t hRpc
);
}
Figure 18 Use of MSHLFLAGS_NOPING
IMarshal* pMarshal = NULL;
HRESULT CFactory::CreateInstance(IUnknown *pUnknownOuter, REFIID riid, void** ppv)
{
if(pUnknownOuter != NULL)
return CLASS_E_NOAGGREGATION;
CObject *pObject = new CObject;
if(pObject == NULL)
return E_OUTOFMEMORY;
IUnknown* pUnknown;
pObject->QueryInterface(IID_IUnknown, (void**)&pUnknown);
CoGetStandardMarshal(riid, pUnknown, 0, NULL,
MSHLFLAGS_NOPING|MSHLFLAGS_NORMAL, &pMarshal);
pUnknown->Release();
// QueryInterface probably for IID_IUNKNOWN
HRESULT hr = pObject->QueryInterface(riid, ppv);
pObject->Release();
return hr;
}