1/*
2 * Copyright (c) 2010 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1.  Redistributions of source code must retain the above copyright
11 *     notice, this list of conditions and the following disclaimer.
12 * 2.  Redistributions in binary form must reproduce the above copyright
13 *     notice, this list of conditions and the following disclaimer in the
14 *     documentation and/or other materials provided with the distribution.
15 * 3.  Neither the name of Apple Inc. ("Apple") nor the names of its
16 *     contributors may be used to endorse or promote products derived from
17 *     this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
20 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 *
30 * Portions of this software have been released under the following terms:
31 *
32 * (c) Copyright 1989-1993 OPEN SOFTWARE FOUNDATION, INC.
33 * (c) Copyright 1989-1993 HEWLETT-PACKARD COMPANY
34 * (c) Copyright 1989-1993 DIGITAL EQUIPMENT CORPORATION
35 *
36 * To anyone who acknowledges that this file is provided "AS IS"
37 * without any express or implied warranty:
38 * permission to use, copy, modify, and distribute this file for any
39 * purpose is hereby granted without fee, provided that the above
40 * copyright notices and this notice appears in all source code copies,
41 * and that none of the names of Open Software Foundation, Inc., Hewlett-
42 * Packard Company or Digital Equipment Corporation be used
43 * in advertising or publicity pertaining to distribution of the software
44 * without specific, written prior permission.  Neither Open Software
45 * Foundation, Inc., Hewlett-Packard Company nor Digital
46 * Equipment Corporation makes any representations about the suitability
47 * of this software for any purpose.
48 *
49 * Copyright (c) 2007, Novell, Inc. All rights reserved.
50 * Redistribution and use in source and binary forms, with or without
51 * modification, are permitted provided that the following conditions
52 * are met:
53 *
54 * 1.  Redistributions of source code must retain the above copyright
55 *     notice, this list of conditions and the following disclaimer.
56 * 2.  Redistributions in binary form must reproduce the above copyright
57 *     notice, this list of conditions and the following disclaimer in the
58 *     documentation and/or other materials provided with the distribution.
59 * 3.  Neither the name of Novell Inc. nor the names of its contributors
60 *     may be used to endorse or promote products derived from this
61 *     this software without specific prior written permission.
62 *
63 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
64 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
65 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
66 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY
67 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
68 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
69 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
70 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
71 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
72 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
73 *
74 * @APPLE_LICENSE_HEADER_END@
75 */
76
77/*
78**
79**      pickling.c
80**
81**  FACILITY:
82**
83**      Interface Definition Language (IDL) Compiler
84**
85**  ABSTRACT:
86**
87**      Routines for IDL encoding services
88**
89*/
90#if HAVE_CONFIG_H
91#include <config.h>
92#endif
93
94#include <assert.h>
95
96#include <dce/idlddefs.h>
97#include <ndrmi.h>
98#include <ndrui.h>
99#include <dce/rpcsts.h>
100#include <lsysdep.h>
101
102static rpc_syntax_id_t ndr_transfer_syntax_id = {
103    {0x8a885d04, 0x1ceb, 0x11c9, 0x9f, 0xe8, {0x8, 0x0, 0x2b, 0x10, 0x48,
1040x60}},
105    2};
106
107/******************************************************************************/
108/*                                                                            */
109/*  idl_es_add_state_to_handle - local routine                                */
110/*  Allocate an IDL_ms_t block, initialize it, and attach it to an encoding   */
111/*      handle                                                                */
112/*  Also mark the state block's copy of the pickle header as invalid          */
113/*  Returns error_status_ok or rpc_s_no_memory                                */
114/*                                                                            */
115/******************************************************************************/
116static error_status_t idl_es_add_state_to_handle
117(
118    IDL_es_state_t *p_es_state
119)
120{
121    IDL_msp_t IDL_msp;
122
123    IDL_msp = (IDL_msp_t)malloc(sizeof(IDL_ms_t));
124    if (IDL_msp == NULL)
125        return(rpc_s_no_memory);
126    /* Initialize state block, except stub must fill in type vector */
127    rpc_ss_init_marsh_state(NULL, IDL_msp);
128    IDL_msp->IDL_pickling_handle = (rpc_void_p_t)p_es_state;
129    p_es_state->IDL_msp = IDL_msp;
130    p_es_state->IDL_pickle_header.IDL_op_num = IDL_INVALID_OP_NUM;
131    return(error_status_ok);
132}
133
134/******************************************************************************/
135/*                                                                            */
136/*  idl_es_encode_incremental - API routine                                   */
137/*  Return an encoding handle for incremental encoding                        */
138/*                                                                            */
139/******************************************************************************/
140void idl_es_encode_incremental
141(
142    idl_void_p_t	    state,  /* [in] user state */
143    idl_es_allocate_fn_t    alloc,  /* [in] alloc routine */
144    idl_es_write_fn_t	    writefn,  /* [in] write routine */
145    idl_es_handle_t	    *h,	    /* [out] encoding handle */
146    error_status_t	    *st	    /* [out] status */
147)
148{
149    IDL_es_state_t *p_es_state;
150
151    p_es_state = (IDL_es_state_t *)malloc(sizeof(IDL_es_state_t));
152    if (p_es_state == NULL)
153    {
154        *st = rpc_s_no_memory;
155        return;
156    }
157
158    p_es_state->IDL_version = IDL_ES_STATE_VERSION;
159    p_es_state->IDL_action = IDL_encoding_k;
160    p_es_state->IDL_style = IDL_incremental_k;
161    /* Set transfer syntax null to indicate "not yet determined" */
162    uuid_create_nil(&(p_es_state->IDL_pickle_header.IDL_syntax_id.id), st);
163    p_es_state->IDL_pickle_header.IDL_syntax_id.version = 0;
164    p_es_state->IDL_state = state;
165    p_es_state->IDL_alloc = alloc;
166    p_es_state->IDL_write = writefn;
167    p_es_state->IDL_es_flags = 0;
168
169    *st = idl_es_add_state_to_handle(p_es_state);
170    if (*st == error_status_ok)
171        *h = (idl_es_handle_t)p_es_state;
172    else
173        free(p_es_state);
174}
175
176/******************************************************************************/
177/*                                                                            */
178/*  idl_es_encode_fixed_buffer - API routine                                  */
179/*  Return an encoding handle for fixed buffer encoding                       */
180/*                                                                            */
181/******************************************************************************/
182void idl_es_encode_fixed_buffer
183(
184    idl_byte		    *ep,    /* [out] buffer to   */
185				    /* receive the encoding (must   */
186				    /* be 8-byte aligned).	    */
187    idl_ulong_int	    bsize,  /* [in] size of buffer provided */
188    idl_ulong_int	    *esize, /* [out] size of the resulting  */
189				    /* encoding	(set after	    */
190				    /* execution of the stub)	    */
191    idl_es_handle_t	    *h,	    /* [out] encoding handle */
192    error_status_t	    *st	    /* [out] status */
193)
194{
195    IDL_es_state_t *p_es_state;
196
197    p_es_state = (IDL_es_state_t *)malloc(sizeof(IDL_es_state_t));
198    if (p_es_state == NULL)
199    {
200        *st = rpc_s_no_memory;
201        return;
202    }
203
204    p_es_state->IDL_version = IDL_ES_STATE_VERSION;
205    p_es_state->IDL_action = IDL_encoding_k;
206    p_es_state->IDL_style = IDL_fixed_k;
207    /* Set transfer syntax null to indicate "not yet determined" */
208    uuid_create_nil(&(p_es_state->IDL_pickle_header.IDL_syntax_id.id), st);
209    p_es_state->IDL_pickle_header.IDL_syntax_id.version = 0;
210    if (((ep - (idl_byte *)0) & 7) != 0)
211    {
212        /* User buffer is not 8-byte aligned */
213        free(p_es_state);
214        *st = rpc_s_ss_bad_buffer;
215        return;
216    }
217    p_es_state->IDL_buff_addr = ep;
218    if ((bsize & 7) != 0)
219    {
220        /* User buffer is not multiple of 8 bytes */
221        free(p_es_state);
222        *st = rpc_s_ss_bad_buffer;
223        return;
224    }
225    p_es_state->IDL_bsize = bsize;
226    p_es_state->IDL_esize = esize;
227    p_es_state->IDL_es_flags = 0;
228
229    *st = idl_es_add_state_to_handle(p_es_state);
230    if (*st == error_status_ok)
231    {
232        *h = (idl_es_handle_t)p_es_state;
233        p_es_state->IDL_msp->IDL_mp = ep;
234        p_es_state->IDL_msp->IDL_buff_addr = ep;
235        p_es_state->IDL_msp->IDL_data_addr = ep;
236        p_es_state->IDL_msp->IDL_left_in_buff = bsize;
237    }
238    else
239        free(p_es_state);
240}
241
242/******************************************************************************/
243/*                                                                            */
244/*  idl_es_encode_dyn_buffer - API routine                                    */
245/*  Return an encoding handle for dynamic buffer encoding                     */
246/*                                                                            */
247/******************************************************************************/
248void idl_es_encode_dyn_buffer
249(
250    idl_byte		    **ep,   /* [out] pointer to receive the */
251				    /* dynamically allocated buffer */
252				    /* which contains the encoding  */
253    idl_ulong_int	    *esize, /* [out] size of the resulting  */
254				    /* encoding (set after	    */
255				    /* execution of the stub)	    */
256    idl_es_handle_t	    *h,	    /* [out] decoding handle */
257    error_status_t	    *st	    /* [out] status */
258)
259{
260    IDL_es_state_t *p_es_state;
261
262    p_es_state = (IDL_es_state_t *)malloc(sizeof(IDL_es_state_t));
263    if (p_es_state == NULL)
264    {
265        *st = rpc_s_no_memory;
266        return;
267    }
268
269    p_es_state->IDL_version = IDL_ES_STATE_VERSION;
270    p_es_state->IDL_action = IDL_encoding_k;
271    p_es_state->IDL_style = IDL_dynamic_k;
272    /* Set transfer syntax null to indicate "not yet determined" */
273    uuid_create_nil(&(p_es_state->IDL_pickle_header.IDL_syntax_id.id), st);
274    p_es_state->IDL_pickle_header.IDL_syntax_id.version = 0;
275    p_es_state->IDL_p_buff_addr = ep;
276    *ep = NULL;     /* Marker to indicate that no encoding call has yet been
277                        made using this handle */
278    p_es_state->IDL_esize = esize;
279    p_es_state->IDL_dyn_buff_chain_head = NULL;
280    p_es_state->IDL_dyn_buff_chain_tail = NULL;
281    p_es_state->IDL_es_flags = 0;
282
283    *st = idl_es_add_state_to_handle(p_es_state);
284    if (*st == error_status_ok)
285        *h = (idl_es_handle_t)p_es_state;
286    else
287        free(p_es_state);
288}
289
290/******************************************************************************/
291/*                                                                            */
292/*  idl_es_decode_incremental - API routine                                   */
293/*  Return an encoding handle for incremental decoding                        */
294/*                                                                            */
295/******************************************************************************/
296void idl_es_decode_incremental
297(
298    idl_void_p_t	    state,  /* [in] user state */
299    idl_es_read_fn_t	    readfn,   /* [in] routine to supply buffers */
300    idl_es_handle_t	    *h,	    /* [out] decoding handle */
301    error_status_t	    *st	    /* [out] status */
302)
303{
304    IDL_es_state_t *p_es_state;
305    IDL_msp_t IDL_msp;
306
307    p_es_state = (IDL_es_state_t *)malloc(sizeof(IDL_es_state_t));
308    if (p_es_state == NULL)
309    {
310        *st = rpc_s_no_memory;
311        return;
312    }
313
314    p_es_state->IDL_version = IDL_ES_STATE_VERSION;
315    p_es_state->IDL_action = IDL_decoding_k;
316    p_es_state->IDL_style = IDL_incremental_k;
317    p_es_state->IDL_state = state;
318    p_es_state->IDL_read = readfn;
319    p_es_state->IDL_pickle_header_read = idl_false;
320    p_es_state->IDL_es_flags = 0;
321
322    *st = idl_es_add_state_to_handle(p_es_state);
323    if (*st == error_status_ok)
324    {
325        *h = (idl_es_handle_t)p_es_state;
326        IDL_msp = p_es_state->IDL_msp;
327        IDL_msp->IDL_left_in_buff = 0;
328    }
329    else
330        free(p_es_state);
331}
332
333/******************************************************************************/
334/*                                                                            */
335/*  idl_es_decode_buffer - API routine                                        */
336/*  Return an encoding handle for fixed decoding                              */
337/*                                                                            */
338/******************************************************************************/
339void idl_es_decode_buffer
340(
341    idl_byte		    *ep,    /* [in] pointer to buffer	    */
342				    /* containing the encoding	    */
343    idl_ulong_int	    size,   /* [in] size of buffer provided */
344    idl_es_handle_t	    *h,	    /* [out] decoding handle */
345    error_status_t	    *st	    /* [out] status */
346)
347{
348    IDL_es_state_t *p_es_state;
349    IDL_msp_t IDL_msp;
350
351    p_es_state = (IDL_es_state_t *)malloc(sizeof(IDL_es_state_t));
352    if (p_es_state == NULL)
353    {
354        *st = rpc_s_no_memory;
355        return;
356    }
357
358    p_es_state->IDL_version = IDL_ES_STATE_VERSION;
359    p_es_state->IDL_action = IDL_decoding_k;
360    p_es_state->IDL_style = IDL_fixed_k;
361    p_es_state->IDL_bsize = size;
362    p_es_state->IDL_buff_addr = ep;
363    p_es_state->IDL_pickle_header_read = idl_false;
364    p_es_state->IDL_es_flags = 0;
365
366    *st = idl_es_add_state_to_handle(p_es_state);
367    if (*st == error_status_ok)
368        *h = (idl_es_handle_t)p_es_state;
369    else
370    {
371        free(p_es_state);
372        return;
373    }
374
375    /* Set up buffer management state */
376    IDL_msp = p_es_state->IDL_msp;
377    if (((p_es_state->IDL_buff_addr - (idl_byte *)0) & 7) != 0)
378    {
379        /* User buffer is not 8-byte aligned. Copy data to an area
380                    that is */
381        p_es_state->IDL_align_buff_addr = (idl_byte *)
382                                            malloc(p_es_state->IDL_bsize + 7);
383        if (p_es_state->IDL_align_buff_addr == NULL)
384        {
385            free(p_es_state);
386            *st = rpc_s_no_memory;
387            return;
388        }
389        IDL_msp->IDL_data_addr = (idl_byte *)
390               (((p_es_state->IDL_align_buff_addr - (idl_byte *)0) + 7) & (~7));
391        memcpy(IDL_msp->IDL_data_addr, p_es_state->IDL_buff_addr,
392                                                        p_es_state->IDL_bsize);
393    }
394    else
395    {
396        p_es_state->IDL_align_buff_addr = NULL;
397        IDL_msp->IDL_data_addr = p_es_state->IDL_buff_addr;
398    }
399    IDL_msp->IDL_mp = IDL_msp->IDL_data_addr;
400    IDL_msp->IDL_left_in_buff = p_es_state->IDL_bsize;
401}
402
403/******************************************************************************/
404/*                                                                            */
405/*  idl_es_set_transfer_syntax - API routine                                  */
406/*  Set a transfer syntax (user must call this before encoding using a stub   */
407/*      which supports more than one transfer syntax)                         */
408/*                                                                            */
409/******************************************************************************/
410void idl_es_set_transfer_syntax
411(
412    idl_es_handle_t h,      /* [in,out] User's encoding handle */
413    idl_es_transfer_syntax_t es_transfer_syntax,
414                            /* [in] requested transfer syntax */
415    error_status_t *st
416)
417{
418    IDL_es_state_t *p_es_state;
419
420    p_es_state = (IDL_es_state_t *)h;
421    switch (es_transfer_syntax)
422    {
423        case idl_es_transfer_syntax_ndr:
424            p_es_state->IDL_pickle_header.IDL_syntax_id
425                                                     = ndr_transfer_syntax_id;
426            *st = error_status_ok;
427            break;
428        default:
429            *st = rpc_s_tsyntaxes_unsupported;
430            break;
431    }
432}
433
434/******************************************************************************/
435/*                                                                            */
436/*  idl_es_check_transfer_syntax - local routine                              */
437/*  Check the stub supports the transfer syntax and return the appropriate    */
438/*      enumeration value                                                     */
439/*                                                                            */
440/******************************************************************************/
441static void idl_es_check_transfer_syntax
442(
443    rpc_if_rep_t *p_if_spec,    /* [in] Pointer to stub's if_spec */
444    IDL_es_state_t *p_es_state, /* [in] State block containing transfer syntax
445                                        to be checked */
446    idl_es_transfer_syntax_t *p_es_transfer_syntax,
447                            /* [out] Transfer syntax to use for encoding */
448    IDL_msp_t IDL_msp
449)
450{
451    unsigned32 i;
452
453    /* Check the stub supports the transfer syntax */
454    for (i=0; i<p_if_spec->syntax_vector.count; i++)
455    {
456        if ( uuid_equal(&(p_es_state->IDL_pickle_header.IDL_syntax_id.id),
457                        &(p_if_spec->syntax_vector.syntax_id[i].id),
458                        (error_status_t *)&IDL_msp->IDL_status)
459            && (p_es_state->IDL_pickle_header.IDL_syntax_id.version
460                            == p_if_spec->syntax_vector.syntax_id[i].version) )
461        {
462            break;
463        }
464    }
465    if ( i >= p_if_spec->syntax_vector.count )
466    {
467        /* No match found in list in stub's ifspec */
468        IDL_msp->IDL_status = rpc_s_tsyntaxes_unsupported;
469        DCETHREAD_RAISE(rpc_x_ss_pipe_comm_error);
470    }
471
472    /* Return the enumeration value for the transfer syntax */
473        *p_es_transfer_syntax = idl_es_transfer_syntax_ndr;
474}
475
476/******************************************************************************/
477/*                                                                            */
478/*  idl_es_encode_get_xfer_syntax - local routine                             */
479/*  Get the transfer syntax to be used for the encoding                       */
480/*                                                                            */
481/******************************************************************************/
482static void idl_es_encode_get_xfer_syntax
483(
484    idl_es_handle_t h,      /* [in] User's encoding handle */
485    rpc_if_handle_t ifp,    /* [in] Pointer to stub's ifspec */
486    idl_es_transfer_syntax_t *p_es_transfer_syntax,
487                            /* [out] Transfer syntax to use for encoding */
488    IDL_msp_t IDL_msp
489)
490{
491    IDL_es_state_t *p_es_state;
492    rpc_if_rep_t *p_if_spec;
493
494    p_es_state = (IDL_es_state_t *)h;
495    p_if_spec = (rpc_if_rep_t *)ifp;
496    if ( uuid_is_nil(&(p_es_state->IDL_pickle_header.IDL_syntax_id.id),
497                     (error_status_t *)&IDL_msp->IDL_status) )
498    {
499        /* No transfer syntax specified in the handle,
500            so can the transfer syntax to use be determined from the stub? */
501        if (p_if_spec->syntax_vector.count != 1)
502        {
503            /* Transfer syntax not adequately specified by stub */
504            IDL_msp->IDL_status = rpc_s_tsyntaxes_unsupported;
505            DCETHREAD_RAISE(rpc_x_ss_pipe_comm_error);
506        }
507        else
508        {
509            /* Copy the transfer syntax into the encoding state block */
510            p_es_state->IDL_pickle_header.IDL_syntax_id =
511                                        *(p_if_spec->syntax_vector.syntax_id);
512        }
513    }
514
515    /* Check the stub supports the transfer syntax the user chose */
516    idl_es_check_transfer_syntax(p_if_spec, p_es_state, p_es_transfer_syntax,
517                                 IDL_msp);
518}
519
520/******************************************************************************/
521/*                                                                            */
522/*  idl_es_encode_new_dyn_buff - Called locally and from MIA/BER support      */
523/*  Create new intermediate buffer list element                               */
524/*  Returns error_status_ok or rpc_s_no_memory                                */
525/*  Does not raise exceptions because it can be called from below DDIS        */
526/*                                                                            */
527/******************************************************************************/
528error_status_t idl_es_encode_new_dyn_buff
529(
530    idl_ulong_int *p_buff_size,     /* [out] Size of buffer returned */
531    IDL_msp_t IDL_msp
532)
533{
534    IDL_dyn_buff_link_t *p_new_link;
535    rpc_iovector_elt_t *p_new_iovec_elt;
536    IDL_es_state_t *p_es_state;
537
538    p_es_state = (IDL_es_state_t *)(IDL_msp->IDL_pickling_handle);
539
540    if ( (*(p_es_state->IDL_p_buff_addr) != NULL)
541            && (p_es_state->IDL_dyn_buff_chain_head == NULL) )
542    {
543        /* A previous encoding operation was called using the current
544            encoding handle (signified by IDL_p_buff_addr not NULL)
545            and this is the first intermediate buffer needed by the
546            current operation (signified by IDL_dyn_buff_chain_head == NULL).
547            Make the output from the preceding operation(s) be the first element
548            of the list of intermediate buffers */
549        p_new_link = (IDL_dyn_buff_link_t *)malloc
550                                        (sizeof(IDL_dyn_buff_link_t));
551        if (p_new_link == NULL)
552        {
553	    rpc_allocator_free(&IDL_msp->IDL_allocator,
554		    *(p_es_state->IDL_p_buff_addr));
555            return(rpc_s_no_memory);
556        }
557        p_new_link->IDL_p_iovec_elt = NULL;
558        p_new_link->IDL_next = NULL;
559        p_es_state->IDL_dyn_buff_chain_head = p_new_link;
560        p_es_state->IDL_dyn_buff_chain_tail = p_new_link;
561        /* Create an rpc_iovector_elt to describe the buffer */
562        p_new_iovec_elt = (rpc_iovector_elt_t *)malloc
563                                        (sizeof(rpc_iovector_elt_t));
564        if (p_new_iovec_elt == NULL)
565        {
566	    rpc_allocator_free(&IDL_msp->IDL_allocator,
567		    *(p_es_state->IDL_p_buff_addr));
568            return(rpc_s_no_memory);
569        }
570        p_new_link->IDL_p_iovec_elt = p_new_iovec_elt;
571        p_new_iovec_elt->buff_addr = *(p_es_state->IDL_p_buff_addr);
572        p_new_iovec_elt->data_addr = *(p_es_state->IDL_p_buff_addr);
573        p_new_iovec_elt->data_len = *(p_es_state->IDL_esize);
574    }
575
576    p_new_link = (IDL_dyn_buff_link_t *)malloc
577                                        (sizeof(IDL_dyn_buff_link_t));
578    if (p_new_link == NULL)
579        return(rpc_s_no_memory);
580    p_new_link->IDL_p_iovec_elt = NULL;
581    p_new_link->IDL_next = NULL;
582    /* Connect it to the state block */
583    if (p_es_state->IDL_dyn_buff_chain_head == NULL)
584        p_es_state->IDL_dyn_buff_chain_head = p_new_link;
585    else
586        p_es_state->IDL_dyn_buff_chain_tail->IDL_next = p_new_link;
587    p_es_state->IDL_dyn_buff_chain_tail = p_new_link;
588    /* Create an rpc_iovector_elt to describe the buffer */
589    p_new_iovec_elt = (rpc_iovector_elt_t *)malloc
590                                        (sizeof(rpc_iovector_elt_t));
591    if (p_new_iovec_elt == NULL)
592        return(rpc_s_no_memory);
593    p_new_iovec_elt->buff_addr = NULL;
594    /* Attach the rpc_iovector_elt to the chain */
595    p_new_link->IDL_p_iovec_elt = p_new_iovec_elt;
596    /* Create the buffer */
597    IDL_msp->IDL_buff_addr = (idl_byte *)
598	rpc_allocator_allocate(&IDL_msp->IDL_allocator, IDL_BUFF_SIZE);
599    if (IDL_msp->IDL_buff_addr == NULL)
600        return(rpc_s_no_memory);
601    memset(IDL_msp->IDL_buff_addr, 0, IDL_BUFF_SIZE);
602    /* Attach the buffer to the rpc_iovector_elt */
603    p_new_iovec_elt->buff_addr = IDL_msp->IDL_buff_addr;
604    *p_buff_size = IDL_BUFF_SIZE;
605    return(error_status_ok);
606}
607
608/******************************************************************************/
609/*                                                                            */
610/*  idl_es_encode_init_buffer - called from NDR marshalling interpreter       */
611/*  Action to be taken by rpc_ss_marsh_init_buffer when used for encoding     */
612/*                                                                            */
613/******************************************************************************/
614void idl_es_encode_init_buffer
615(
616    idl_ulong_int *p_buff_size,     /* [out] Size of buffer returned */
617    IDL_msp_t IDL_msp
618)
619{
620    IDL_es_state_t *p_es_state;
621
622    p_es_state = (IDL_es_state_t *)(IDL_msp->IDL_pickling_handle);
623    switch (p_es_state->IDL_style)
624    {
625        case IDL_incremental_k:
626            *p_buff_size = IDL_BUFF_SIZE;
627            (*(p_es_state->IDL_alloc))(p_es_state->IDL_state,
628                                         &IDL_msp->IDL_buff_addr, p_buff_size);
629            if (((IDL_msp->IDL_buff_addr - (idl_byte *)0) & 7) != 0)
630            {
631                /* User buffer is not 8-byte aligned */
632                IDL_msp->IDL_status = rpc_s_ss_bad_buffer;
633                DCETHREAD_RAISE(rpc_x_ss_pipe_comm_error);
634            }
635            if (((*p_buff_size & 7) != 0) || (*p_buff_size < 8))
636            {
637                /* User buffer is not multiple of 8 bytes */
638                IDL_msp->IDL_status = rpc_s_ss_bad_buffer;
639                DCETHREAD_RAISE(rpc_x_ss_pipe_comm_error);
640            }
641            break;
642        case IDL_fixed_k:
643            /* Ran out of buffer space with data still to be marshalled */
644            DCETHREAD_RAISE(rpc_x_no_memory);
645            break;
646        case IDL_dynamic_k:
647            /* Create new intermediate buffer list element */
648            if (idl_es_encode_new_dyn_buff(p_buff_size, IDL_msp)
649                                                            != error_status_ok)
650                DCETHREAD_RAISE(rpc_x_no_memory);
651            break;
652        default:
653#ifdef DEBUG_INTERP
654            printf("idl_es_encode_init_buffer - unknown encoding style\n");
655            exit(0);
656#endif
657            DCETHREAD_RAISE(rpc_x_coding_error);
658    }
659}
660
661/******************************************************************************/
662/*                                                                            */
663/*  idl_es_encode_attach_buff - called from NDR marshalling interpreter       */
664/*  Action to be taken by rpc_ss_attach_buff_to_iovec when used for encoding  */
665/*                                                                            */
666/******************************************************************************/
667void idl_es_encode_attach_buff
668(
669    IDL_msp_t IDL_msp
670)
671{
672    IDL_es_state_t *p_es_state;
673    rpc_iovector_elt_t *p_iovec_elt;
674
675    p_es_state = (IDL_es_state_t *)(IDL_msp->IDL_pickling_handle);
676    switch (p_es_state->IDL_style)
677    {
678        case IDL_incremental_k:
679            (*(p_es_state->IDL_write))(p_es_state->IDL_state,
680                                      IDL_msp->IDL_buff_addr,
681                                      IDL_msp->IDL_mp - IDL_msp->IDL_data_addr);
682            break;
683        case IDL_fixed_k:
684            /* Can only happen at end of operation - do nothing */
685            break;
686        case IDL_dynamic_k:
687            p_iovec_elt = p_es_state->IDL_dyn_buff_chain_tail->IDL_p_iovec_elt;
688            p_iovec_elt->data_addr = (byte_p_t)IDL_msp->IDL_data_addr;
689            p_iovec_elt->data_len = IDL_msp->IDL_mp - IDL_msp->IDL_data_addr;
690            break;
691        default:
692#ifdef DEBUG_INTERP
693            printf("idl_es_encode_attach_buff - unknown encoding style\n");
694            exit(0);
695#endif
696            DCETHREAD_RAISE(rpc_x_coding_error);
697    }
698}
699
700/******************************************************************************/
701/*                                                                            */
702/*  idl_es_put_encoding_uuid - local routine                                  */
703/*  Write a UUID in the header for a pickle                                   */
704/*                                                                            */
705/******************************************************************************/
706static void idl_es_put_encoding_uuid
707(
708    idl_uuid_t *p_uuid,     /* [in] Address of UUID */
709    IDL_msp_t IDL_msp
710)
711{
712    int i;
713
714    IDL_MARSH_ULONG(&p_uuid->time_low);
715    IDL_MARSH_USHORT(&p_uuid->time_mid);
716    IDL_MARSH_USHORT(&p_uuid->time_hi_and_version);
717    IDL_MARSH_USMALL(&p_uuid->clock_seq_hi_and_reserved);
718    IDL_MARSH_USMALL(&p_uuid->clock_seq_low);
719    for (i=0; i<6; i++)
720    {
721        IDL_MARSH_BYTE(&p_uuid->node[i]);
722    }
723}
724
725/******************************************************************************/
726/*                                                                            */
727/*  idl_es_put_encoding_header - local routine                                */
728/*  Write the header for this pickle                                          */
729/*                                                                            */
730/******************************************************************************/
731static void idl_es_put_encoding_header
732(
733    rpc_if_handle_t ifp,    /* [in] Pointer to stub's ifspec */
734    idl_ulong_int op_num,   /* [in] operation number */
735    idl_es_transfer_syntax_t es_transfer_syntax,
736                         /* [in] Transfer syntax user data will be encoded in */
737    IDL_msp_t IDL_msp
738)
739{
740    idl_usmall_int version = IDL_ES_HEADER_VERSION;
741    idl_usmall_int fill = 0;
742    IDL_es_state_t *p_es_state;
743    rpc_if_rep_t *p_if_spec;
744    int i;
745    idl_ushort_int vers_field;
746
747    p_es_state = (IDL_es_state_t *)(IDL_msp->IDL_pickling_handle);
748    p_if_spec = (rpc_if_rep_t *)ifp;
749
750    IDL_MARSH_USMALL(&version);
751    IDL_MARSH_USMALL(&ndr_g_local_drep.int_rep);
752    IDL_MARSH_USMALL(&fill);
753    IDL_MARSH_USMALL(&fill);
754    idl_es_put_encoding_uuid(&p_es_state->IDL_pickle_header.IDL_syntax_id.id,
755                                                                     IDL_msp);
756    IDL_MARSH_ULONG(&p_es_state->IDL_pickle_header.IDL_syntax_id.version);
757    idl_es_put_encoding_uuid(&p_if_spec->id, IDL_msp);
758    vers_field = p_if_spec->vers / 65536;   /* Major version */
759    IDL_MARSH_USHORT(&vers_field);
760    vers_field = p_if_spec->vers % 65536;   /* Minor version */
761    IDL_MARSH_USHORT(&vers_field);
762    IDL_MARSH_ULONG(&op_num);
763    if (es_transfer_syntax == idl_es_transfer_syntax_ndr)
764    {
765        IDL_MARSH_USMALL(&ndr_g_local_drep.int_rep);
766        IDL_MARSH_USMALL(&ndr_g_local_drep.char_rep);
767        IDL_MARSH_USMALL(&ndr_g_local_drep.float_rep);
768        IDL_MARSH_BYTE(&ndr_g_local_drep.reserved);
769        /* Four filler bytes to make the user data start at (0 mod 8) */
770        for (i=0; i<4; i++)
771        {
772            IDL_MARSH_USMALL(&fill);
773        }
774    }
775
776    /* Store interface ID and operation number in state block */
777    p_es_state->IDL_pickle_header.IDL_if_id.uuid = p_if_spec->id;
778    p_es_state->IDL_pickle_header.IDL_if_id.vers_major
779                                                     = p_if_spec->vers / 65536;
780    p_es_state->IDL_pickle_header.IDL_if_id.vers_minor
781                                                     = p_if_spec->vers % 65536;
782    p_es_state->IDL_pickle_header.IDL_op_num = op_num;
783}
784
785/******************************************************************************/
786/*                                                                            */
787/*  idl_es_get_encoding_uuid - local routine                                  */
788/*  Read a UUID in the header for a pickle                                    */
789/*                                                                            */
790/******************************************************************************/
791static void idl_es_get_encoding_uuid
792(
793    idl_uuid_t *p_uuid,     /* [in] Address of UUID */
794    IDL_msp_t IDL_msp
795)
796{
797    int i;
798
799    IDL_UNMAR_ULONG(&p_uuid->time_low);
800    IDL_UNMAR_USHORT(&p_uuid->time_mid);
801    IDL_UNMAR_USHORT(&p_uuid->time_hi_and_version);
802    IDL_UNMAR_USMALL(&p_uuid->clock_seq_hi_and_reserved);
803    IDL_UNMAR_USMALL(&p_uuid->clock_seq_low);
804    for (i=0; i<6; i++)
805    {
806        IDL_UNMAR_BYTE(&p_uuid->node[i]);
807    }
808}
809
810/******************************************************************************/
811/*                                                                            */
812/*  idl_es_get_encoding_header - local routine                                */
813/*  Read pickle header into local storage                                     */
814/*                                                                            */
815/******************************************************************************/
816static void idl_es_get_encoding_header
817(
818    idl_es_pvt_header_t *p_pickle_header,       /* [out] local copy of pickle
819                                                         header */
820    IDL_msp_t IDL_msp
821)
822{
823    IDL_es_state_t *p_es_state = NULL;
824
825    p_es_state = (IDL_es_state_t *)(IDL_msp->IDL_pickling_handle);
826
827    IDL_UNMAR_USMALL(&p_pickle_header->IDL_version);
828    if (p_pickle_header->IDL_version != IDL_ES_HEADER_VERSION)
829    {
830        IDL_msp->IDL_status = rpc_s_ss_wrong_es_version;
831        DCETHREAD_RAISE(rpc_x_ss_pipe_comm_error);
832    }
833    IDL_UNMAR_USMALL(&p_pickle_header->IDL_int_drep);
834    /* This drep is needed to control decoding the rest of header */
835    IDL_msp->IDL_drep.int_rep = p_pickle_header->IDL_int_drep;
836    /* Called rtn will do an alignment operation, discarding the filler bytes */
837    idl_es_get_encoding_uuid(&p_pickle_header->IDL_syntax_id.id, IDL_msp);
838    IDL_UNMAR_ULONG(&p_pickle_header->IDL_syntax_id.version);
839    idl_es_get_encoding_uuid(&p_pickle_header->IDL_if_id.uuid, IDL_msp);
840    IDL_UNMAR_USHORT(&p_pickle_header->IDL_if_id.vers_major);
841    IDL_UNMAR_USHORT(&p_pickle_header->IDL_if_id.vers_minor);
842    IDL_UNMAR_ULONG(&p_pickle_header->IDL_op_num);
843
844    /* If the pickle uses NDR encoding, get its drep's */
845    if (uuid_equal(&p_pickle_header->IDL_syntax_id.id,
846                   &ndr_transfer_syntax_id.id,
847                   (error_status_t *)&IDL_msp->IDL_status))
848    {
849        IDL_UNMAR_USMALL(&IDL_msp->IDL_drep.int_rep);
850        IDL_UNMAR_USMALL(&IDL_msp->IDL_drep.char_rep);
851        IDL_UNMAR_USMALL(&IDL_msp->IDL_drep.float_rep);
852        /* And align to 8 bytes */
853        IDL_UNMAR_ALIGN_MP(IDL_msp, 8);
854    }
855    assert(p_es_state != NULL);
856    p_es_state->IDL_pickle_header_read = idl_true;
857}
858
859/*
860 * Support for Microsoft Encoding Services (MES).
861 */
862static void idl_mes_put_encoding_header
863(
864    IDL_msp_t IDL_msp
865)
866{
867    idl_es_type_pvt_header_t common_header;
868    int i;
869    idl_usmall_int hdr_length_low, hdr_length_high;
870    idl_byte length_pad = 0;
871
872    common_header.IDL_version = IDL_ES_HEADER_VERSION;
873    common_header.IDL_endianness = (ndr_g_local_drep.int_rep << 4);
874    common_header.IDL_common_header_length = IDL_ES_TYPE_COMMON_HEADER_LEN;
875    memset(common_header.IDL_fill, 0xcc, 4);
876
877    IDL_MARSH_USMALL(&common_header.IDL_version);
878    IDL_MARSH_USMALL(&common_header.IDL_endianness);
879
880    hdr_length_low  = (common_header.IDL_common_header_length >> 0) & 0xff;
881    hdr_length_high = (common_header.IDL_common_header_length >> 8) & 0xff;
882
883    IDL_MARSH_USMALL(&hdr_length_low);
884    IDL_MARSH_USMALL(&hdr_length_high);
885
886    for (i = 0; i < 4; i++)
887    {
888        IDL_MARSH_BYTE(&common_header.IDL_fill[i]);
889    }
890
891    for (i = 0; i < 8; i++)
892    {
893        IDL_MARSH_BYTE(&length_pad);
894    }
895}
896
897static void idl_mes_get_encoding_header
898(
899    idl_es_pvt_header_t *p_pickle_header,
900    IDL_msp_t IDL_msp
901)
902{
903    idl_es_type_pvt_header_t common_header;
904    IDL_es_state_t *p_es_state;
905    int i;
906    idl_uhyper_int length;
907    idl_usmall_int hdr_length_low, hdr_length_high;
908    unsigned32 status;
909
910    p_es_state = (IDL_es_state_t *)(IDL_msp->IDL_pickling_handle);
911
912    IDL_UNMAR_USMALL(&common_header.IDL_version);
913    if (common_header.IDL_version != IDL_ES_HEADER_VERSION)
914    {
915        IDL_msp->IDL_status = rpc_s_ss_wrong_es_version;
916        DCETHREAD_RAISE(rpc_x_ss_pipe_comm_error);
917    }
918    p_pickle_header->IDL_version = common_header.IDL_version;
919
920    IDL_UNMAR_USMALL(&common_header.IDL_endianness);
921
922    IDL_msp->IDL_drep.int_rep  = (common_header.IDL_endianness >> 4) & 0xF;
923
924    IDL_UNMAR_USMALL(&hdr_length_low);
925    IDL_UNMAR_USMALL(&hdr_length_high);
926
927    common_header.IDL_common_header_length = (hdr_length_low  << 0) |
928                                             (hdr_length_high << 8);
929
930    if (common_header.IDL_common_header_length != IDL_ES_TYPE_COMMON_HEADER_LEN)
931    {
932        IDL_msp->IDL_status = rpc_s_ss_wrong_es_version;
933        DCETHREAD_RAISE(rpc_x_ss_pipe_comm_error);
934    }
935
936    for (i = 0; i < common_header.IDL_common_header_length - 4; i++)
937    {
938        IDL_UNMAR_BYTE(&common_header.IDL_fill[i]);
939    }
940
941    IDL_UNMAR_HYPER(&length);
942
943    p_pickle_header->IDL_syntax_id = ndr_transfer_syntax_id;
944    uuid_create_nil(&p_pickle_header->IDL_if_id.uuid, &status);
945    if (status != rpc_s_ok)
946    {
947        IDL_msp->IDL_status = status;
948        DCETHREAD_RAISE(rpc_x_ss_pipe_comm_error);
949    }
950    p_pickle_header->IDL_if_id.vers_major = 0;
951    p_pickle_header->IDL_if_id.vers_minor = 0;
952    p_pickle_header->IDL_op_num = 0;
953
954    IDL_msp->IDL_drep.char_rep = ndr_c_char_ascii;
955    IDL_msp->IDL_drep.float_rep = ndr_c_float_ieee;
956
957    p_es_state->IDL_pickle_header_read = idl_true;
958}
959
960static void idl_mes_forge_encoding_header
961(
962    idl_es_pvt_header_t *p_pickle_header,
963    IDL_msp_t IDL_msp
964)
965{
966    IDL_es_state_t *p_es_state;
967    unsigned32 status;
968
969    p_es_state = (IDL_es_state_t *)(IDL_msp->IDL_pickling_handle);
970
971    IDL_msp->IDL_drep.int_rep = ndr_c_int_little_endian;
972
973    p_pickle_header->IDL_syntax_id = ndr_transfer_syntax_id;
974    uuid_create_nil(&p_pickle_header->IDL_if_id.uuid, &status);
975    if (status != rpc_s_ok)
976    {
977        IDL_msp->IDL_status = status;
978        DCETHREAD_RAISE(rpc_x_ss_pipe_comm_error);
979    }
980    p_pickle_header->IDL_if_id.vers_major = 0;
981    p_pickle_header->IDL_if_id.vers_minor = 0;
982    p_pickle_header->IDL_op_num = 0;
983
984    IDL_msp->IDL_drep.int_rep = ndr_c_int_little_endian;
985    IDL_msp->IDL_drep.char_rep = ndr_c_char_ascii;
986    IDL_msp->IDL_drep.float_rep = ndr_c_float_ieee;
987
988    p_es_state->IDL_pickle_header_read = idl_true;
989}
990
991/******************************************************************************/
992/*                                                                            */
993/*  idl_es_before_interp_call - SPI routine                                   */
994/*  Set up for interpreter call to encode/decode user data                    */
995/*                                                                            */
996/******************************************************************************/
997void idl_es_before_interp_call
998(
999    idl_es_handle_t h,      /* [in] User's encoding handle */
1000    rpc_if_handle_t ifp,    /* [in] Pointer to stub's ifspec */
1001    idl_byte IDL_type_vec[],    /* [in] Stub's type vector */
1002    idl_ulong_int op_num,   /* [in] operation number */
1003    IDL_es_action_type_k_t stub_action, /* [in] Is this operation labelled
1004                                            [encode], [decode] */
1005    idl_es_transfer_syntax_t *p_es_transfer_syntax,
1006                            /* [out] Transfer syntax to use for encoding */
1007    IDL_msp_t IDL_msp
1008)
1009{
1010    IDL_es_state_t * volatile p_es_state;
1011    rpc_if_rep_t *p_if_spec;
1012
1013    //DO_NOT_CLOBBER(p_es_state);
1014    p_es_state = NULL;
1015
1016    /* If we get any abnormal condition we need to cope with the situation
1017        where this is a dynamic encoding and the operation is not the first
1018        that used the handle. In this case we need to release the encoding
1019        resulting from the preceding operations */
1020    DCETHREAD_TRY
1021        /* Complete initialization of state block */
1022        IDL_msp->IDL_type_vec = IDL_type_vec;
1023        rpc_ss_type_vec_vers_check( IDL_msp );
1024
1025        p_es_state = (IDL_es_state_t *)h;
1026        /* Was operation specified to support action? */
1027        if (stub_action != IDL_both_k)
1028        {
1029            if (stub_action != p_es_state->IDL_action)
1030            {
1031                IDL_msp->IDL_status = rpc_s_ss_bad_es_action;
1032                DCETHREAD_RAISE(rpc_x_ss_pipe_comm_error);
1033            }
1034        }
1035
1036        if (p_es_state->IDL_action == IDL_encoding_k)
1037        {
1038            idl_es_encode_get_xfer_syntax(h, ifp, p_es_transfer_syntax, IDL_msp);
1039            if (p_es_state->IDL_style == IDL_dynamic_k)
1040            {
1041                /* Need user allocator for intermediate and final buffers */
1042                rpc_ss_mts_client_estab_alloc(IDL_msp);
1043            }
1044            if ((p_es_state->IDL_es_flags & IDL_ES_NO_HEADER) == 0)
1045            {
1046                if (p_es_state->IDL_es_flags & IDL_ES_MIDL_COMPAT)
1047                    idl_mes_put_encoding_header(IDL_msp);
1048                else
1049                    idl_es_put_encoding_header(ifp, op_num, *p_es_transfer_syntax, IDL_msp);
1050            }
1051        }
1052        else    /* decoding */
1053        {
1054            if ( ! p_es_state->IDL_pickle_header_read )
1055            {
1056                if (p_es_state->IDL_es_flags & IDL_ES_NO_HEADER)
1057                    idl_mes_forge_encoding_header(&p_es_state->IDL_pickle_header, IDL_msp);
1058                else if (p_es_state->IDL_es_flags & IDL_ES_MIDL_COMPAT)
1059                    idl_mes_get_encoding_header(&p_es_state->IDL_pickle_header, IDL_msp);
1060                else
1061                    idl_es_get_encoding_header(&p_es_state->IDL_pickle_header, IDL_msp);
1062            }
1063            p_if_spec = (rpc_if_rep_t *)ifp;
1064
1065            /*
1066             * Don't check interface uuid's or version number if the user
1067             * doesn't want to.
1068             */
1069            if ( ! (p_es_state->IDL_es_flags & ( IDL_ES_NO_ENCODING_CHECK
1070                                               | IDL_ES_MIDL_COMPAT
1071                                               | IDL_ES_NO_HEADER
1072                                               ) ) )
1073            {
1074                if ( ! uuid_equal(&p_es_state->IDL_pickle_header.IDL_if_id.uuid,
1075                                  &p_if_spec->id,
1076                                  (error_status_t *)&IDL_msp->IDL_status) )
1077                {
1078                    /* Wrong interface */
1079                    IDL_msp->IDL_status = rpc_s_unknown_if;
1080                    DCETHREAD_RAISE(rpc_x_ss_pipe_comm_error);
1081                }
1082                if (p_if_spec->vers != (unsigned32)
1083							 (p_es_state->IDL_pickle_header.IDL_if_id.vers_major * 65536
1084                        + p_es_state->IDL_pickle_header.IDL_if_id.vers_minor))
1085                {
1086                    /* Wrong version */
1087                    IDL_msp->IDL_status = rpc_s_unknown_if;
1088                    DCETHREAD_RAISE(rpc_x_ss_pipe_comm_error);
1089                }
1090            }
1091
1092            /* Check the stub supports the transfer syntax of the pickle */
1093            idl_es_check_transfer_syntax(p_if_spec, p_es_state,
1094                                         p_es_transfer_syntax, IDL_msp);
1095            /* Now at a point where we won't test for "pickle header read" again
1096            for this operation. Reset it in case user has another operation in
1097            the pickle */
1098            p_es_state->IDL_pickle_header_read = idl_false;
1099        }
1100        DCETHREAD_CATCH_ALL(exc)
1101        assert(p_es_state != NULL);
1102        if ( (p_es_state->IDL_action == IDL_encoding_k)
1103            && (p_es_state->IDL_style == IDL_dynamic_k)
1104            && (*(p_es_state->IDL_p_buff_addr) != NULL) )
1105        {
1106	    rpc_allocator_free(&IDL_msp->IDL_allocator,
1107		*(p_es_state->IDL_p_buff_addr));
1108        }
1109        DCETHREAD_RERAISE;
1110    DCETHREAD_ENDTRY
1111}
1112
1113/******************************************************************************/
1114/*                                                                            */
1115/*  idl_es_encode_dyn_size - local routine                                    */
1116/*  Get the total size of a dynamic encoding                                  */
1117/*                                                                            */
1118/******************************************************************************/
1119static void idl_es_encode_dyn_size
1120(
1121    IDL_dyn_buff_link_t *p_list_elt,    /* [in] pointer to list of
1122                                                    intermediate buffers */
1123    idl_ulong_int *p_dyn_size           /* [out] size of encoding */
1124)
1125{
1126    idl_ulong_int dyn_size = 0;
1127
1128    for ( ; p_list_elt != NULL; p_list_elt = p_list_elt->IDL_next)
1129    {
1130        dyn_size += p_list_elt->IDL_p_iovec_elt->data_len;
1131    }
1132    *p_dyn_size = dyn_size;
1133}
1134
1135/******************************************************************************/
1136/*                                                                            */
1137/*  idl_es_encode_dyn_copy_rel - local routine                                */
1138/*  Copy the intermediate buffers for a dynamic encoding to the buffer to be  */
1139/*      delivered to the user, and release the intermediate buffer chain      */
1140/*                                                                            */
1141/******************************************************************************/
1142static void idl_es_encode_dyn_copy_rel
1143(
1144    IDL_dyn_buff_link_t *p_list_elt,    /* [in] pointer to list of
1145                                                    intermediate buffers */
1146    idl_byte *dyn_buff,      /* [out] location to copy intermediate buffer to */
1147    IDL_msp_t IDL_msp
1148)
1149{
1150    rpc_iovector_elt_t *p_iovec_elt;
1151    idl_ulong_int inter_data_len;   /* Length of data in intermediate buffer */
1152    IDL_dyn_buff_link_t *p_old_list_elt;
1153
1154    while (p_list_elt != NULL)
1155    {
1156        p_iovec_elt = p_list_elt->IDL_p_iovec_elt;
1157        /* Copy data */
1158        inter_data_len = p_iovec_elt->data_len;
1159        memcpy(dyn_buff, p_iovec_elt->data_addr, inter_data_len);
1160        dyn_buff += inter_data_len;
1161        /* Release head of chain */
1162	rpc_allocator_free(&IDL_msp->IDL_allocator, p_iovec_elt->buff_addr);
1163        free(p_iovec_elt);
1164        p_old_list_elt = p_list_elt;
1165        p_list_elt = p_list_elt->IDL_next;
1166        free(p_old_list_elt);
1167    }
1168}
1169
1170/******************************************************************************/
1171/*                                                                            */
1172/*  idl_es_after_interp_call - SPI routine                                    */
1173/*  Tidy up after normal return from interpreter call to encode/decode user   */
1174/*      data                                                                  */
1175/*                                                                            */
1176/******************************************************************************/
1177void idl_es_after_interp_call
1178(
1179    IDL_msp_t IDL_msp
1180)
1181{
1182    IDL_es_state_t *p_es_state;
1183    rpc_iovector_elt_t *p_iovec_elt;
1184    idl_ulong_int dyn_size;     /* Size of dynamic encoding */
1185    idl_byte *dyn_buff;         /* Dynamic buffer delivered to user */
1186
1187    p_es_state = (IDL_es_state_t *)(IDL_msp->IDL_pickling_handle);
1188
1189    if (p_es_state->IDL_action == IDL_encoding_k)
1190    {
1191        switch (p_es_state->IDL_style)
1192        {
1193            case IDL_incremental_k:
1194                /* Last part of pickle already handed to user */
1195                /* There may be another operation using the same handle
1196                    - reset state */
1197                if (IDL_msp->IDL_mem_handle.memory)
1198                {
1199                    rpc_ss_mem_free(&IDL_msp->IDL_mem_handle);
1200                }
1201                rpc_ss_init_marsh_state(NULL, IDL_msp);
1202                IDL_msp->IDL_pickling_handle = (rpc_void_p_t)p_es_state;
1203                break;
1204            case IDL_fixed_k:
1205                /* Set size of pickle for user */
1206                *(p_es_state->IDL_esize) = IDL_msp->IDL_mp
1207                                                     - IDL_msp->IDL_data_addr;
1208                break;
1209            case IDL_dynamic_k:
1210                if ( (p_es_state->IDL_dyn_buff_chain_head->IDL_next == NULL)
1211                    && (IDL_msp->IDL_data_addr == IDL_msp->IDL_buff_addr) )
1212                {
1213                    /* Intermediate buffer can be handed off to user */
1214                    p_iovec_elt =
1215                           p_es_state->IDL_dyn_buff_chain_head->IDL_p_iovec_elt;
1216                    *(p_es_state->IDL_p_buff_addr) = (idl_byte *)
1217                                                    (p_iovec_elt->buff_addr);
1218                    *(p_es_state->IDL_esize) = p_iovec_elt->data_len;
1219                    /* Release chain machinery */
1220                    free(p_iovec_elt);
1221                    free(p_es_state->IDL_dyn_buff_chain_head);
1222                }
1223                else
1224                {
1225                    idl_es_encode_dyn_size(p_es_state->IDL_dyn_buff_chain_head,
1226                                                                     &dyn_size);
1227                    *(p_es_state->IDL_esize) = dyn_size;
1228                    dyn_buff = (idl_byte *)
1229			rpc_allocator_allocate(
1230                                        &IDL_msp->IDL_allocator, dyn_size);
1231                    if (dyn_buff == NULL)
1232                        DCETHREAD_RAISE(rpc_x_no_memory);
1233		    memset(dyn_buff, 0, dyn_size);
1234                    idl_es_encode_dyn_copy_rel(
1235                                            p_es_state->IDL_dyn_buff_chain_head,
1236                                            dyn_buff, IDL_msp);
1237                    *(p_es_state->IDL_p_buff_addr) = dyn_buff;
1238                }
1239                p_es_state->IDL_dyn_buff_chain_head = NULL;
1240                /* There may be another operation using the same handle
1241                    - reset state */
1242                if (IDL_msp->IDL_mem_handle.memory)
1243                {
1244                    rpc_ss_mem_free(&IDL_msp->IDL_mem_handle);
1245                }
1246                rpc_ss_init_marsh_state(NULL, IDL_msp);
1247                IDL_msp->IDL_pickling_handle = (rpc_void_p_t)p_es_state;
1248                break;
1249            default:
1250#ifdef DEBUG_INTERP
1251                printf(
1252                  "idl_es_after_normal_interp_call - unknown encoding style\n");
1253                exit(0);
1254#endif
1255                DCETHREAD_RAISE(rpc_x_coding_error);
1256        }
1257
1258        if (p_es_state->IDL_es_flags & IDL_ES_MIDL_COMPAT)
1259        {
1260            idl_byte *mp;
1261            idl_ulong_int length; /* length without header */
1262
1263            length = *(p_es_state->IDL_esize) - IDL_ES_TYPE_HEADER_LEN;
1264
1265            if (p_es_state->IDL_style == IDL_fixed_k)
1266                mp = p_es_state->IDL_buff_addr;
1267            else if (p_es_state->IDL_style == IDL_dynamic_k)
1268                mp = *(p_es_state->IDL_p_buff_addr);
1269            else
1270                mp = NULL;
1271
1272            if (mp != NULL)
1273            {
1274                mp += IDL_ES_TYPE_COMMON_HEADER_LEN;
1275
1276                mp[0] = (length >> 0)  & 0xff;
1277                mp[1] = (length >> 8)  & 0xff;
1278                mp[2] = (length >> 16) & 0xff;
1279                mp[3] = (length >> 24) & 0xff;
1280
1281                memset(&mp[4], 0, 4);
1282            }
1283        }
1284    }
1285}
1286
1287/******************************************************************************/
1288/*                                                                            */
1289/*  idl_es_clean_up - SPI routine                                             */
1290/*  Tidy up after un/pickling action                                          */
1291/*                                                                            */
1292/******************************************************************************/
1293void idl_es_clean_up
1294(
1295    IDL_msp_t IDL_msp
1296)
1297{
1298    IDL_es_state_t *p_es_state;
1299    IDL_dyn_buff_link_t *p_list_elt;
1300    IDL_dyn_buff_link_t *p_old_list_elt;
1301    rpc_iovector_elt_t *p_iovec_elt;
1302
1303    p_es_state = (IDL_es_state_t *)(IDL_msp->IDL_pickling_handle);
1304
1305    /* Tidy up if abnormal end during incremental encoding */
1306    if (p_es_state->IDL_action == IDL_encoding_k)
1307    {
1308        if (p_es_state->IDL_style == IDL_dynamic_k)
1309        {
1310            p_list_elt = p_es_state->IDL_dyn_buff_chain_head;
1311            /* Release chain of intermediate buffers */
1312            while (p_list_elt != NULL)
1313            {
1314                p_iovec_elt = p_list_elt->IDL_p_iovec_elt;
1315                if (p_iovec_elt != NULL)
1316                {
1317                    if (p_iovec_elt->buff_addr != NULL)
1318		    {
1319			rpc_allocator_free(&IDL_msp->IDL_allocator,
1320				p_iovec_elt->buff_addr);
1321		    }
1322                    free(p_iovec_elt);
1323                }
1324                p_old_list_elt = p_list_elt;
1325                p_list_elt = p_list_elt->IDL_next;
1326                free(p_old_list_elt);
1327            }
1328            p_es_state->IDL_dyn_buff_chain_head = NULL;
1329        }
1330    }
1331    /* Release memory allocated by interpreter */
1332    if (IDL_msp->IDL_mem_handle.memory)
1333    {
1334        rpc_ss_mem_free(&IDL_msp->IDL_mem_handle);
1335    }
1336}
1337
1338/******************************************************************************/
1339/*                                                                            */
1340/*  idl_es_decode_check_buffer - called from NDR unmarshalling interpreter    */
1341/*  Called when interpreter has exhausted current buffer                      */
1342/*                                                                            */
1343/******************************************************************************/
1344void idl_es_decode_check_buffer
1345(
1346    IDL_msp_t IDL_msp
1347)
1348{
1349    IDL_es_state_t *p_es_state;
1350
1351    p_es_state = (IDL_es_state_t *)(IDL_msp->IDL_pickling_handle);
1352    if (p_es_state->IDL_style == IDL_incremental_k)
1353    {
1354        (*(p_es_state->IDL_read))(p_es_state->IDL_state,
1355                                  &IDL_msp->IDL_data_addr,
1356                                  &IDL_msp->IDL_left_in_buff);
1357        if (((IDL_msp->IDL_data_addr - (idl_byte *)0) & 7) != 0)
1358        {
1359            /* User buffer is not 8-byte aligned */
1360            IDL_msp->IDL_status = rpc_s_ss_bad_buffer;
1361            DCETHREAD_RAISE(rpc_x_ss_pipe_comm_error);
1362        }
1363        IDL_msp->IDL_mp = IDL_msp->IDL_data_addr;
1364    }
1365    else    /* Exhausted fixed buffer */
1366    {
1367        IDL_msp->IDL_status = rpc_s_ss_bad_buffer;
1368        DCETHREAD_RAISE(rpc_x_ss_pipe_comm_error);
1369    }
1370}
1371
1372/******************************************************************************/
1373/*                                                                            */
1374/*  idl_es_inq_encoding_id - API routine                                      */
1375/*  Give interface ID and operation number to user                            */
1376/*                                                                            */
1377/******************************************************************************/
1378void idl_es_inq_encoding_id
1379(
1380    idl_es_handle_t	    h,	    /* [in] decoding handle */
1381    rpc_if_id_t		    * volatile if_id, /* [out] RPC interface	    */
1382				    /* identifier (including	    */
1383				    /* version information)	    */
1384    idl_ulong_int	    *op,    /* [out] operation number */
1385    error_status_t	    *st	    /* [out] status */
1386)
1387{
1388    IDL_es_state_t *p_es_state;
1389
1390    *st = error_status_ok;
1391    p_es_state = (IDL_es_state_t *)h;
1392    if ( (p_es_state->IDL_action == IDL_decoding_k)
1393        && ( ! p_es_state->IDL_pickle_header_read ) )
1394    {
1395        /* User wants operation number before decoding pickle body */
1396        DCETHREAD_TRY
1397            idl_es_get_encoding_header(&p_es_state->IDL_pickle_header,
1398                                                         p_es_state->IDL_msp);
1399        DCETHREAD_CATCH(rpc_x_ss_pipe_comm_error)
1400            *st = p_es_state->IDL_msp->IDL_status;
1401        DCETHREAD_ENDTRY
1402        if (*st != error_status_ok)
1403            return;
1404    }
1405    else if (p_es_state->IDL_pickle_header.IDL_op_num == IDL_INVALID_OP_NUM)
1406    {
1407        /* Encoding, and no operation has yet been invoked */
1408        *st = rpc_s_ss_bad_es_action;
1409        return;
1410    }
1411    *if_id = p_es_state->IDL_pickle_header.IDL_if_id;
1412    *op = p_es_state->IDL_pickle_header.IDL_op_num;
1413}
1414
1415/******************************************************************************/
1416/*                                                                            */
1417/*  idl_es_handle_free - API routine                                          */
1418/*  Frees a idl_es_handle_t and its associated resources                      */
1419/*                                                                            */
1420/******************************************************************************/
1421void idl_es_handle_free
1422(
1423    idl_es_handle_t	*h,	    /* [in,out] handle to free */
1424    error_status_t	*st	    /* [out] status */
1425)
1426{
1427    IDL_es_state_t *p_es_state;
1428
1429    p_es_state = (IDL_es_state_t *)(*h);
1430    free(p_es_state->IDL_msp);
1431    if ((p_es_state->IDL_action == IDL_decoding_k)
1432        && (p_es_state->IDL_style == IDL_fixed_k)
1433        && (p_es_state->IDL_align_buff_addr != NULL))
1434    {
1435        free(p_es_state->IDL_align_buff_addr);
1436    }
1437    free(p_es_state);
1438    *h = NULL;
1439    *st = error_status_ok;
1440}
1441
1442/******************************************************************************/
1443/*                                                                            */
1444/*  idl_es_set_attrs - API routine                                            */
1445/*  Set attribute flags in a idl_es_handle_t                                  */
1446/*                                                                            */
1447/******************************************************************************/
1448void idl_es_set_attrs(
1449	idl_es_handle_t h,
1450	unsigned32 flags,
1451	error_status_t *st)
1452{
1453	IDL_es_state_t *p_es_state = (IDL_es_state_t *)h;
1454
1455	p_es_state->IDL_es_flags = flags;
1456	*st = error_status_ok;
1457	return;
1458}
1459
1460/******************************************************************************/
1461/*                                                                            */
1462/*  idl_es_inq_attrs - API routine                                            */
1463/*  Get the flags from a idl_es_handle_t                                      */
1464/*                                                                            */
1465/******************************************************************************/
1466void idl_es_inq_attrs(
1467	idl_es_handle_t h,
1468	unsigned32 *flags,
1469	error_status_t *st)
1470{
1471	IDL_es_state_t *p_es_state = (IDL_es_state_t *)h;
1472
1473	*flags = p_es_state->IDL_es_flags;
1474	*st = error_status_ok;
1475	return;
1476}
1477