compiling test.idl with dceidl - bit lairy and archaic

Luke Kenneth Casson Leighton lkcl at lkcl.net
Wed Jan 19 18:05:33 CST 2005


On Wed, Jan 19, 2005 at 05:37:24PM -0600, Robert Shearman wrote:
> Luke Kenneth Casson Leighton wrote:
> 
> >On Wed, Jan 19, 2005 at 09:50:09PM +0000, Luke Kenneth Casson Leighton 
> >wrote:
> > 
> >
> >>4) case statements where the switch variable is a char i
> >>couldn't be bothered to find a way to let it be happy with case(1)
> >>it was bitching about 1 not being a char so i converted to
> >>a short and it stopped bitching.
> >>   
> >>
> >
> >
> >postscript:
> >
> >16) i enabled the "expressioning" stuff and got this:
> >
> >lkcl at highfield:~/src/wine-test/dcom-test/RpcTest$ /opt/dce/bin/dceidl 
> >test.idl Warning: Semantic checking prevented by other reported errors
> >idl: File test.idl, line 99:    void SubOneConformanceArrayIn([in] long
> >size, [in, length_is(size-1)] unsigned char Array[10]);
> >idl: Syntax error near "-1"
> >Syntax error in attribute list
> >idl: File test.idl, line 100:   void CallbackConformanceArrayIn([in]
> >long size, [in, length_is(size*2+1)] unsigned char Array[10]);
> >Only simple expressions allowed for now
> > 
> >
> 
> Yes, the function is named CallbackConformanceArrayIn because it is a 
> complicated expression and MIDL creates a callback function in C which 
> implements the complex expression, and then stores an index to execute 
> it at runtime.
 
 eek.

> >
> >all the things 1-16 are not insurmountable problems - they've just not
> >been necessary for the tasks to which dceidl has been put.
> >
> > 
> >
> 
> Of course, this is a purely academic test file. Many of those problems 
> would not be encountered or could be worked around with real IDL interfaces.
> 
> >... shall i carry on? :)
> > 
> >
> 
> While you have demonstrated to me that the dceidl IDL compiler is very 
> capable (and I did not doubt this), you still haven't demonstrated how 
> this can benefit the Wine project. Yes, we can generate our own 
> (probably) compatible client/server glue code (and this is ok for 
> library-implemented functions like the registry or service functions), 
> however we then lose focus on the applications for which we don't have 
> source code for and depend on rpcrt4 being implemented. This is the most 
> common use for Wine! 

 i understand.

 okay - i understand the need [and the distinction], i don't have
 any knowledge [detailed knowledge] of what rpcrt4 does, other than
 i believe it to be used to interpret the "type string" tables.

 would that be correct?


> If you have any ideas on how we can solve this, 
> please let me know.
 
 okay.  my initial feeling is that the APR team's example should be
 followed.


 is the list of functions that you have in the wine cvs tree for
 the rpcrt4 dll a complete list?

 things like RpcEpRegisterA in rpc_epmap.c, yes?

 the simplest and probably the most naive approach that springs to mind
 would be to call the functions available in FreeDCE.

 RpcEpRegisterA to call rpc_ep_register.

 RpcServerInqBindings to call rpc_server_inq_bindings.

 that sort of thing - just like they do in APR.

 naive?  almost certainly.


 damn.  if that's not easily done, you have a _really_ big
 job on your hands.  at least another 200,000 lines of code
 into Wine, to support DCE/RPC "a la microsoft".


 attached is an example - implementation of rpc_server_inq_bindings,
 in FreeDCE, for you to compare against RpcServerInqBindings.


 _why_ microsoft, _why_ why _why_???  

-------------- next part --------------

/*
**++
**
**  ROUTINE NAME:       rpc_server_inq_bindings
**
**  SCOPE:              PUBLIC - declared in rpc.idl
**
**  DESCRIPTION:
**      
**  Return the bindings for this server to which RPCs may be made.
**  Note that object UUIDs are not part of these bindings.
**
**  INPUTS:             none
**
**  INPUTS/OUTPUTS:     none
**
**  OUTPUTS:
**
**      binding_vector  The vector of valid bindings to this server.
**
**      status          The result of the operation. One of:
**                          rpc_s_ok
**                          rpc_s_no_bindings
**                          rpc_s_coding_error
**
**  IMPLICIT INPUTS:    none
**
**  IMPLICIT OUTPUTS:   none
**
**  FUNCTION VALUE:     void
**
**  SIDE EFFECTS:       none
**
**--
**/

PUBLIC void rpc_server_inq_bindings 
#ifdef _DCE_PROTO_
(
    rpc_binding_vector_p_t  *binding_vec,
    unsigned32              *status
)
#else
(binding_vec, status)
rpc_binding_vector_p_t  *binding_vec;
unsigned32              *status;
#endif
{
    unsigned int                     nd_index;       /* network info table index    */
    unsigned int                     bv_index;       /* binding vector index        */
    unsigned32                     av_index;       /* RPC Address vector index    */
    rpc_binding_vector_p_t  bvp, new_bvp;   /* local ptr to binding vector */
    rpc_naf_id_t            nafid;          /* network family id           */
    rpc_addr_vector_p_t     addr_vec;       /* rpc addrs of network desc   */
    rpc_binding_rep_p_t     binding_rep;
    unsigned int                     i;
    unsigned32              xstatus;


    CODING_ERROR (status);
    RPC_VERIFY_INIT ();

    *binding_vec = NULL;        /* assume the worst */

    /*
     * Allocate up an initial binding vector.  Note that we might need
     * to allocate up a larger one later if the one we get now turns out
     * to not be big enough
     */
    bv_alloc ((rpc_binding_vector_p_t) NULL, &bvp, status);

    if (*status != rpc_s_ok)
    {
        return;
    }

    bv_index = 0;

    /*
     * For each socket we know about...
     */
    for (nd_index = 0; nd_index < listener_state.high_water; nd_index++)
    {
        rpc_listener_sock_p_t lsock = &listener_state.socks[nd_index];

        /*
         * Consider only sockets that are in use and for server usage.
         */
        if (lsock->busy && lsock->is_server)
        {
            nafid = RPC_PROTSEQ_INQ_NAF_ID (lsock->protseq_id);

            /*
             * Get all the RPC Addresses represented by this descriptor.
             */
            (*RPC_NAF_INQ_EPV(nafid)->naf_desc_inq_addr)
                (lsock->protseq_id, lsock->desc, &addr_vec, status);

            if (*status != rpc_s_ok)
            {
                break;
            }

            /*
             * For each RPC Address...
             */
            for (av_index = 0; av_index < addr_vec->len; av_index++)
            {
                /*
                 * If we've exceeded the size of the current vector,
                 * allocate up a new one.
                 */
                if (bv_index >= bvp->count)
                {
                    bv_alloc (bvp, &new_bvp, status);

                    if (*status != rpc_s_ok)
                    {
                        break;
                    }

                    bvp = new_bvp;
                }

                /*
                 * Allocate a binding with this RPC Address.
                 */
                binding_rep =
                    rpc__binding_alloc (false, &uuid_g_nil_uuid, 
                        lsock->protocol_id, addr_vec->addrs[av_index], status);

                if (*status != rpc_s_ok)
                {
                    break;
                }

                /*
                 * The rpc_addr reference has been handed off to the
                 * binding, make sure that it isn't freed.
                 */
                addr_vec->addrs[av_index] = NULL;

                binding_rep->addr_is_dynamic = lsock->is_dynamic;
                bvp->binding_h[bv_index] = (rpc_binding_handle_t) binding_rep;

                bv_index++;     /* bump for next binding vector entry */
            }

            /*
             * Free up the allocated addr vector (and any addrs that
             * haven't been given to a binding).
             */
            rpc__naf_addr_vector_free (&addr_vec, &xstatus);

            /*
             * If there was previously an error we're done.
             */
            if (*status != rpc_s_ok)
                break;
        }
    }

    /*
     * Return with status if there aren't any bindings.
     */
    if (bv_index == 0 && *status == rpc_s_ok)
    {
        *status = rpc_s_no_bindings;
    }

    /*
     * If everything went fine, return the bindings.
     * Otherwise free resources before returning (retain the original error).
     */
    if (*status == rpc_s_ok)
    {
        bvp->count = bv_index;
        *binding_vec = bvp;
    }
    else
    {
        for (i = 0; i < bv_index; i++)
        {
            rpc_binding_free
                ((rpc_binding_handle_t *) &bvp->binding_h[i], &xstatus);
        }

        RPC_MEM_FREE (bvp, RPC_C_MEM_BINDING_VEC);
        *binding_vec = NULL;
    }
}


More information about the wine-devel mailing list