Figure 3   IPSFactoryBuffer IDL

[
    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