[
local, object,
uuid(D5F569D0-593B-101A-B569-08002B2DBF7A)
]
interface IPSFactoryBuffer : IUnknown
{
// called by Proxy Manager to
// create/aggregate interface proxy
HRESULT CreateProxy(
[in] IUnknown *pUnkOuter, // ptr to proxy manager
[in] REFIID riid, // IID requested
[out] IRpcProxyBuffer **ppProxy, // ptr to itf proxy
[out] void **ppv // ptr to itf proxy for client
);
// called by Stub Manager to
// create interface stub
HRESULT CreateStub(
[in] REFIID riid, // IID requested
[in] IUnknown *pUnkServer, // ptr to real object
[out] IRpcStubBuffer **ppStub // ptr to itf stub
);
}
Figure 4 Creating an Interface Proxy
// lookup interface's ProxyStubClsid32
CLSID psclsid
HRESULT hr = CoGetPSClsid(IID_ISomeInterface,
&psclsid);
if (SUCCEEDED(hr)) {
// load proxy/stub code
IPSFactoryBuffer *psfb = 0;
hr = CoGetClassObject(psclsid,CLSCTX_INPROC,
0, IID_IPSFactoryBuffer, (void**)&psfb);
if (SUCCEEDED(hr)) {
// ask proxy/stub code to create interface proxy
hr = psfb->CreateProxy(this,
IID_ISomeInterface, &m_pProxy,
(void**)&pClientPtr);
pfsb->Release();
}
}
Figure 7 Proxy/Stub Size Savings
|
Minimum IDL |
5 Itf Sample |
10 Itf Sample |
ADO 2.0 |
/Oicf |
24KB |
29KB |
29KB |
36KB |
No /Oicf |
24KB |
78KB |
135KB |
208KB |
Figure 8 MIDL_PROC_FORMAT_STRING
static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString =
{
0,
{
/* Procedure Eat */
0x33, /* FC_AUTO_HANDLE */
0x6c, /* Old Flags: object, Oi2 */
/* 2 */ NdrFcLong( 0x0 ), /* 0 */
/* 6 */ NdrFcShort( 0x3 ), /* 3 */
/* 8 */ NdrFcShort( 0xc ), /* x86, MIPS, PPC Stack size/offset = 12 */
/* 10 */ NdrFcShort( 0x0 ), /* 0 */
/* 12 */ NdrFcShort( 0x10 ), /* 16 */
/* 14 */ 0x4, /* Oi2 Flags: has return, */
0x2, /* 2 */
/* Parameter pn */
/* 16 */ NdrFcShort( 0x2150 ), /* Flags: out, base type,
simple ref, srv alloc size=8 */
/* 18 */ NdrFcShort( 0x4 ), /* x86, MIPS, PPC Stack size/offset = 4 */
/* 20 */ 0x8, /* FC_LONG */
0x0, /* 0 */
/* Return value */
/* 22 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */
/* 24 */ NdrFcShort( 0x8 ), /* x86, MIPS, PPC Stack size/offset = 8 */
/* 26 */ 0x8, /* FC_LONG */
0x0, /* 0 */
/* Procedure Sleep */
/* 28 */ 0x33, /* FC_AUTO_HANDLE */
0x6c, /* Old Flags: object, Oi2 */
/* 30 */ NdrFcLong( 0x0 ), /* 0 */
/* 34 */ NdrFcShort( 0x4 ), /* 4 */
/* 36 */ NdrFcShort( 0x10 ), /* x86, MIPS, PPC Stack size/offset = 16 */
/* 38 */ NdrFcShort( 0x10 ), /* 16 */
/* 40 */ NdrFcShort( 0x10 ), /* 16 */
/* 42 */ 0x4, /* Oi2 Flags: has return, */
0x3, /* 3 */
/* Parameter pBob */
/* 44 */ NdrFcShort( 0x10a ), /* Flags: must free, in, simple ref, */
/* 46 */ NdrFcShort( 0x4 ), /* x86, MIPS, PPC Stack size/offset = 4 */
/* 48 */ NdrFcShort( 0xa ), /* Type Offset=10 */
/* Parameter pn */
/* 50 */ NdrFcShort( 0x2150 ), /* Flags: out, base type,
simple ref, srv alloc size=8 */
/* 52 */ NdrFcShort( 0x8 ), /* x86, MIPS, PPC Stack size/offset = 8 */
/* 54 */ 0x8, /* FC_LONG */
0x0, /* 0 */
/* Return value */
/* 56 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */
/* 58 */ NdrFcShort( 0xc ), /* x86, MIPS, PPC Stack size/offset = 12 */
/* 60 */ 0x8, /* FC_LONG */
0x0, /* 0 */
/* Procedure Drink */
/* 62 */ 0x33, /* FC_AUTO_HANDLE */
0x6c, /* Old Flags: object, Oi2 */
/* 64 */ NdrFcLong( 0x0 ), /* 0 */
/* 68 */ NdrFcShort( 0x5 ), /* 5 */
/* 70 */ NdrFcShort( 0x10 ), /* x86, MIPS, PPC Stack size/offset = 16 */
/* 72 */ NdrFcShort( 0x10 ), /* 16 */
/* 74 */ NdrFcShort( 0x10 ), /* 16 */
/* 76 */ 0x4, /* Oi2 Flags: has return, */
0x3, /* 3 */
/* Parameter pBob */
/* 78 */ NdrFcShort( 0x10a ), /* Flags: must free, in, simple ref, */
/* 80 */ NdrFcShort( 0x4 ), /* x86, MIPS, PPC Stack size/offset = 4 */
/* 82 */ NdrFcShort( 0xa ), /* Type Offset=10 */
/* Parameter pn */
/* 84 */ NdrFcShort( 0x2150 ), /* Flags: out, base type,
simple ref, srv alloc size=8 */
/* 86 */ NdrFcShort( 0x8 ), /* x86, MIPS, PPC Stack size/offset = 8 */
/* 88 */ 0x8, /* FC_LONG */
0x0, /* 0 */
/* Return value */
/* 90 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */
/* 92 */ NdrFcSi2rt( 0xc ), /* x86, MIPS, PPC Stack size/offset = 12 */
/* 94 */ 0x8, /* FC_LONG */
0x0, /* 0 */
0x0
}
};
Figure 9 MIDL_TYPE_FORMAT_STRING
static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString =
{
0,
{
NdrFcShort( 0x0 ), /* 0 */
/* 2 */
0x11, 0xc, /* FC_RP [alloced_on_stack] [simple_pointer] */
/* 4 */ 0x8, /* FC_LONG */
0x5c, /* FC_PAD */
/* 6 */
0x11, 0x0, /* FC_RP */
/* 8 */ NdrFcShort( 0x2 ), /* Offset= 2 (10) */
/* 10 */
0x15, /* FC_STRUCT */
0x3, /* 3 */
/* 12 */ NdrFcShort( 0x8 ), /* 8 */
/* 14 */ 0x8, /* FC_LONG */
0x8, /* FC_LONG */
/* 16 */ 0x5c, /* FC_PAD */
0x5b, /* FC_END */
0x0
}
};
Figure 12 Create Proxy/Stub Pseudocode
// this is an approximation of the class factory returned by
// OLEAUT32.DLL's DllGetClassObject({00020424-0000-0000-C000-000000000046})
struct PSTypeLibFactoryBuffer : IPSFactoryBuffer,
CComObjectRootEx<CComMultiThreadModel>
{
BEGIN_COM_MAP(PSTypeLibFactoryBuffer)
COM_INTERFACE_ENTRY(IPSFactoryBuffer)
END_COM_MAP()
STDMETHODIMP CreateProxy(IUnknown *pUnkOuter, REFIID riid,
IRpcProxyBuffer **ppProxy, void **ppv)
{
*ppv = *ppProxy = 0;
// grab the type description of this interface from the registry
ITypeLib *ptl = 0;
HRESULT hr = LoadCachedTypeLibFromIID(riid, &ptl);
if (SUCCEEDED(hr))
{
ITypeInfo *pti = 0;
hr = ptl->GetTypeInfoOfGuid(riid, &pti);
if (SUCCEEDED(hr))
{
// ask RPCRT4 to cook up an /Oicf proxy from the ITypeInfo
hr = CreateProxyFromTypeInfo(pti, pUnkOuter, riid,
ppProxy, ppv);
pti->Release();
}
ptl->Release();
}
return hr;
}
STDMETHODIMP CreateStub(
REFIID riid,
IUnknown *pUnkServer,
IRpcStubBuffer **ppStub)
{
*ppStub = 0;
// grab the type description of this interface from the registry
ITypeLib *ptl = 0;
HRESULT hr = LoadCachedTypeLibFromIID(riid, &ptl);
if (SUCCEEDED(hr))
{
ITypeInfo *pti = 0;
hr = ptl->GetTypeInfoOfGuid(riid, &pti);
if (SUCCEEDED(hr))
{
// ask RPCRT4 to cook up an /Oicf stub from the ITypeInfo
hr = CreateStubFromTypeInfo(pti, riid, pUnkServer, ppStub);
pti->Release();
}
ptl->Release();
}
return hr;
}
};
Figure 13 Marshaler Tradeoffs
|
Non-/Oicf Proxy/Stub DLLs |
/Oicf Proxy/Stub DLLs |
TypeLib Marshaler |
Supports 16-bit tasks |
No |
No |
Yes |
Supports Windows NT 3.51 or Windows 95 (no DCOM) |
Yes |
No |
Yes
|
Memory footprint |
Large |
Small |
Small |
Structure support |
Full |
Full |
Limited (SP4)/None (SP3) |
[iid_is]/[size_is] support |
Full |
Full |
None |
[call_as]/[transmit_as] support |
Full |
Full |
None |
[wire_marshal] support |
Full (requires DCOM) |
Full (requires DCOM) |
None |
Requires registration on client and server |
Yes |
Yes |
Yes |
Can be bundled with executable |
Yes |
Yes |
Yes |