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**      interpsh.c
79**
80**  FACILITY:
81**
82**      Interface Definition Language (IDL) Compiler
83**
84**  ABSTRACT:
85**
86**      Procedures shared between interpreters
87**
88*/
89#if HAVE_CONFIG_H
90#include <config.h>
91#endif
92
93#include <dce/idlddefs.h>
94#include <lsysdep.h>
95
96/******************************************************************************/
97/*                                                                            */
98/*  General comments about interpreter structure, variable name, etc.         */
99/*                                                                            */
100/******************************************************************************/
101
102/*
103 *  For a description of the layout of the vectors on which the interpreters
104 *  rely, see the MTS*.SDML documents in the RPC$ROOT:[DOC.CMS] CMS library
105 */
106
107/*
108    A range list is a set of [A, A+B] pairs for a varying array.
109*/
110
111/*
112    p_...   Signifies a pointer to an object
113
114    IDL_msp         Pointer to the marshalling state block
115    add_null        TRUE => marshalling a string to which a null terminator
116                        must be explicitly added
117    arm_type_ptr    Pointer to union arm type definition
118    array_addr      Address of an array
119    array_defn_index Index into definition vector for array definition
120    array_defn_ptr  Pointer to array definition in definition vector
121    array_has_pointers TRUE if the base type of the array includes pointers
122    bounds_list     List of lower and upper bounds for an array
123    contiguous      TRUE if no gaps in set of array elements
124    cs_type_defn_index Index into definition vector for [cs_char] type defn
125    cs_type_defn_ptr Pointer to [cs_char] type definition in definition vector
126    defn_index      Index into definition vector
127    defn_vec_ptr    Pointer to current byte in definition vector
128    dimensionality  Number of dimensions of an array
129    element_count   Number of elements in an array or array portion
130    element_defn_index Index into definition vector for description of array
131                                                element which has complex type
132    element_defn_ptr  Pointer to description in definition vector of array
133                                                element which has complex type
134    element_offset_vec_ptr Pointer to the start of the offset vector entries
135                            for an array element of complex type
136    element_size    Size of an array element
137    field_defn_index Index into definition vector for description of field
138                                                        which has complex type
139    field_defn_ptr  Pointer to description in definition vector of field
140                                                        which has complex type
141    marshall_by_pointing TRUE if array can be marshalled by pointing
142    normal_...      Storage used for array description unless array has more
143                        than IDL_NORMAL_DIMS dimensions
144    offset_index    Index into offset vector
145    offset_vec_ptr  Pointer to current element in offset vector
146    param_addr      Address of parameter
147    param_index     Index of parameter address in parameter vector
148    range_list      List of (A,A+B) pairs determining an array's data limits
149    pointee_defn_index Index into definition vector for pointee definition
150    pointee_defn_ptr  Pointer to pointee definition in definition vector
151    struct_addr     Address of a structure
152    struct_defn_index Index into definition vector for structure definition
153    struct_defn_ptr Pointer to structure definition in definition vector
154    struct_offset_index Index of start of structure offsets in offset vector
155    struct_offset_vec_ptr Pointer to the start of the offset vector entries
156                            for a structure
157    struct_size     Size of a structure
158    switch_value    Value of union discriminant
159    type_byte       Byte describing type of datum currently being handled
160    type_is_modified TRUE if a modifier byte occurred before a type byte
161    type_vec_ptr    Pointer to parameter type in type/definition vector
162    unmarshall_by_copying TRUE if array can be unmarshalled by copying
163    Z_values        List of dimension sizes for conformant array
164*/
165
166/******************************************************************************/
167/*                                                                            */
168/*  Function returning the local size of an object of a specified type        */
169/*  For [transmit_as] returns the size of the presented type                  */
170/*  For a varying array returns the storage size of the array                 */
171/*  For a type which does not have a fixed size, returns 0                    */
172/*                                                                            */
173/******************************************************************************/
174idl_ulong_int rpc_ss_type_size
175(
176    /* [in] */  idl_byte *defn_vec_ptr, /* Pointer to start of type
177                                        specification in definition vector */
178    IDL_msp_t IDL_msp
179)
180{
181    idl_byte type;
182    idl_ulong_int complex_defn_index; /* Index to description of complex type */
183    idl_byte *complex_defn_ptr;     /* Pointer to description of complex type */
184    idl_ulong_int offset_index;
185    idl_ulong_int array_defn_index;
186    idl_byte *array_defn_ptr;
187    idl_ulong_int dimensionality;
188    idl_ulong_int i;
189    idl_ulong_int array_element_count;
190    idl_long_int lower_bound;
191    idl_long_int upper_bound;
192
193    type = *defn_vec_ptr;
194    switch (type)
195    {
196        case IDL_DT_BOOLEAN:
197            return(sizeof(idl_boolean));
198        case IDL_DT_BYTE:
199            return(sizeof(idl_byte));
200        case IDL_DT_CHAR:
201            return(sizeof(idl_char));
202        case IDL_DT_DOUBLE:
203            return(sizeof(idl_long_float));
204        case IDL_DT_ENUM:
205        case IDL_DT_V1_ENUM:
206            return(sizeof(int));
207        case IDL_DT_FLOAT:
208            return(sizeof(idl_short_float));
209        case IDL_DT_SMALL:
210                return(sizeof(idl_small_int));
211        case IDL_DT_SHORT:
212            return(sizeof(idl_short_int));
213        case IDL_DT_LONG:
214            return(sizeof(idl_long_int));
215        case IDL_DT_HYPER:
216            return(sizeof(idl_hyper_int));
217        case IDL_DT_USMALL:
218                return(sizeof(idl_usmall_int));
219        case IDL_DT_USHORT:
220                return(sizeof(idl_ushort_int));
221        case IDL_DT_ULONG:
222        case IDL_DT_ERROR_STATUS:
223            return(sizeof(idl_ulong_int));
224        case IDL_DT_UHYPER:
225            return(sizeof(idl_uhyper_int));
226        case IDL_DT_FIXED_STRUCT:
227        case IDL_DT_ENC_UNION:
228        case IDL_DT_TRANSMIT_AS:
229        case IDL_DT_REPRESENT_AS:
230        case IDL_DT_CS_TYPE:
231            defn_vec_ptr += 2;      /* After properties byte */
232            IDL_GET_LONG_FROM_VECTOR(complex_defn_index, defn_vec_ptr);
233            complex_defn_ptr = IDL_msp->IDL_type_vec + complex_defn_index;
234            IDL_GET_LONG_FROM_VECTOR(offset_index, complex_defn_ptr);
235            return(*(IDL_msp->IDL_offset_vec + offset_index));
236        case IDL_DT_N_E_UNION:
237            defn_vec_ptr += 2;      /* After properties byte */
238            IDL_DISCARD_LONG_FROM_VECTOR(defn_vec_ptr);  /* Switch index */
239            IDL_GET_LONG_FROM_VECTOR(complex_defn_index, defn_vec_ptr);
240            complex_defn_ptr = IDL_msp->IDL_type_vec + complex_defn_index;
241            IDL_GET_LONG_FROM_VECTOR(offset_index, complex_defn_ptr);
242            return(*(IDL_msp->IDL_offset_vec + offset_index));
243        case IDL_DT_STRING:
244        case IDL_DT_V1_STRING:
245            defn_vec_ptr++;
246            /* Next byte is DT_VARYING_ARRAY or DT_OPEN_ARRAY */
247            type = *defn_vec_ptr;
248            /* If it is not DT_OPEN_ARRAY drop through to process it */
249            if (type == IDL_DT_OPEN_ARRAY)
250                return 0;
251        case IDL_DT_FIXED_ARRAY:
252        case IDL_DT_VARYING_ARRAY:
253            defn_vec_ptr += 2;      /* After properties byte */
254            IDL_DISCARD_LONG_FROM_VECTOR(defn_vec_ptr);
255            /* Ignore the full array definition and look at the flattened one */
256            IDL_GET_LONG_FROM_VECTOR(array_defn_index, defn_vec_ptr);
257            array_defn_ptr = IDL_msp->IDL_type_vec + array_defn_index;
258            dimensionality = (idl_ulong_int)*array_defn_ptr;
259            array_defn_ptr++;
260            array_element_count = 1;
261            for (i=0; i<dimensionality; i++)
262            {
263                IDL_GET_LONG_FROM_VECTOR(lower_bound, array_defn_ptr);
264                IDL_GET_LONG_FROM_VECTOR(upper_bound, array_defn_ptr);
265                array_element_count *= (upper_bound - lower_bound + 1);
266            }
267            if (type == IDL_DT_VARYING_ARRAY)
268                array_defn_ptr += dimensionality * IDL_DATA_LIMIT_PAIR_WIDTH;
269            return(array_element_count
270                    * rpc_ss_type_size(array_defn_ptr, IDL_msp));
271        case IDL_DT_FULL_PTR:
272        case IDL_DT_UNIQUE_PTR:
273        case IDL_DT_REF_PTR:
274            return(sizeof(rpc_void_p_t));
275        case IDL_DT_CS_ARRAY:
276            /* The size of the array this modifier is attached to */
277            return(rpc_ss_type_size(defn_vec_ptr + 1, IDL_msp));
278        default:
279            return 0;
280    }
281}
282
283static idl_long_int
284interpsh_apply_func_code(byte func_code, idl_long_int size)
285{
286	idl_long_int calc_size;
287
288	switch(func_code)	{
289		/* only "extended" simple expressions for now */
290		case IDL_FC_DIV_8:
291			calc_size = size / 8;
292			break;
293		case IDL_FC_MUL_8:
294			calc_size = size * 8;
295			break;
296		case IDL_FC_DIV_4:
297			calc_size = size / 4;
298			break;
299		case IDL_FC_MUL_4:
300			calc_size = size * 4;
301			break;
302		case IDL_FC_DIV_2:
303			calc_size = size / 2;
304			break;
305		case IDL_FC_MUL_2:
306			calc_size = size * 2;
307			break;
308		case IDL_FC_SUB_1:
309			calc_size = size - 1;
310			break;
311		case IDL_FC_ADD_1:
312			calc_size = size + 1;
313			break;
314		case IDL_FC_ALIGN_2:
315			calc_size = (size+1) & ~1;
316			break;
317		case IDL_FC_ALIGN_4:
318			calc_size = (size+3) & ~3;
319			break;
320		case IDL_FC_ALIGN_8:
321			calc_size = (size+7) & ~7;
322			break;
323		case IDL_FC_NONE:
324		default:
325			calc_size = size;
326			break;
327	}
328	return calc_size;
329}
330
331/******************************************************************************/
332/*                                                                            */
333/*  Clean up after NDR marshalling                                            */
334/*                                                                            */
335/******************************************************************************/
336void rpc_ss_ndr_clean_up
337(
338    IDL_ms_t *IDL_msp
339)
340{
341    unsigned32 i;
342
343    /* Clean up marshalling state */
344    if (IDL_msp->IDL_buff_addr != NULL
345        && IDL_msp->IDL_stack_packet_status != IDL_stack_packet_in_use_k)
346    {
347        free(IDL_msp->IDL_buff_addr);
348        IDL_msp->IDL_buff_addr = NULL;
349    }
350    for (i=0; i<IDL_msp->IDL_elts_in_use; i++)
351    {
352        if (IDL_msp->IDL_iovec.elt[i].buff_dealloc != NULL)
353        {
354            (*IDL_msp->IDL_iovec.elt[i].buff_dealloc)
355                                (IDL_msp->IDL_iovec.elt[i].buff_addr);
356            IDL_msp->IDL_iovec.elt[i].buff_dealloc = NULL;
357        }
358    }
359
360    /* Clean up unmarshalling state */
361    if (IDL_msp->IDL_elt_p != NULL)
362    {
363        if ((IDL_msp->IDL_elt_p->buff_dealloc != NULL)
364                && (IDL_msp->IDL_elt_p->data_len != 0))
365            (*IDL_msp->IDL_elt_p->buff_dealloc)(IDL_msp->IDL_elt_p->buff_addr);
366        IDL_msp->IDL_elt_p = NULL;
367    }
368}
369
370/******************************************************************************/
371/*                                                                            */
372/*  Create a set of Z values from a list of bounds values                     */
373/*                                                                            */
374/******************************************************************************/
375void rpc_ss_Z_values_from_bounds
376(
377    /* [in] */  IDL_bound_pair_t *bounds_list,
378    /* [in] */  idl_ulong_int dimensionality,
379    /* [out] */ idl_ulong_int **p_Z_values,
380    IDL_msp_t IDL_msp
381)
382{
383    idl_ulong_int *Z_values;
384    unsigned32 i;
385
386    if (*p_Z_values == NULL)
387    {
388        Z_values = (idl_ulong_int *)rpc_ss_mem_alloc
389             (&IDL_msp->IDL_mem_handle, dimensionality * sizeof(idl_ulong_int));
390        *p_Z_values = Z_values;
391    }
392    else
393        Z_values = *p_Z_values;
394    for (i=0; i<dimensionality; i++)
395    {
396        if (bounds_list[i].upper >= bounds_list[i].lower)
397            Z_values[i] = bounds_list[i].upper - bounds_list[i].lower + 1;
398        else
399            Z_values[i] = 0;
400    }
401}
402
403/******************************************************************************/
404/*                                                                            */
405/*  Determine whether the elements of a varying or conformant array to be     */
406/*  un/marshalled are contiguous. If they are, also return the total number   */
407/*  of elements, and their starting address                                   */
408/*                                                                            */
409/******************************************************************************/
410void rpc_ss_ndr_contiguous_elt
411(
412    /* [in] */  idl_ulong_int dimensionality,
413    /* [in] */  idl_ulong_int *Z_values,
414    /* [in] */  IDL_bound_pair_t *range_list,
415    /* [in] */  idl_ulong_int element_size,
416    /* [out] */ idl_boolean *p_contiguous,
417    /* [out] */ idl_ulong_int *p_element_count,
418    /* [out] */ rpc_void_p_t *p_array_addr
419)
420{
421    unsigned i;
422    idl_ulong_int element_count;
423
424    element_count = 1;
425
426    for (i=1; i<dimensionality; i++)
427    {
428        if ( (unsigned32)(range_list[i].upper - range_list[i].lower) != Z_values[i] )
429        {
430            *p_contiguous = idl_false;
431            return;
432        }
433        element_count *= Z_values[i];
434    }
435
436    *p_contiguous = idl_true;
437    *p_array_addr = (rpc_void_p_t)((idl_byte *)*p_array_addr
438                         + range_list[0].lower * element_count * element_size);
439    *p_element_count = element_count
440                             * (range_list[0].upper - range_list[0].lower);
441}
442
443/******************************************************************************/
444/*                                                                            */
445/*  Alignment operations and optimizing flag for array un/marshalling         */
446/*                                                                            */
447/******************************************************************************/
448void rpc_ss_ndr_arr_align_and_opt
449(
450    /* [in] */  IDL_mar_or_unmar_k_t marsh_or_unmar,
451    /* [in] */  idl_ulong_int dimensionality ATTRIBUTE_UNUSED,
452    /* [out] */ idl_byte *p_base_type,
453    /* [in] */ idl_byte *defn_vec_ptr,   /* Points to array base info */
454    /* [out] */ idl_boolean *p_optimize,
455    IDL_msp_t IDL_msp
456)
457{
458    idl_byte base_type;
459    idl_ulong_int defn_index;
460    idl_ulong_int pipe_arr_dims;
461                /* Number of dims of array which is base type of a pipe */
462    idl_ulong_int struct_defn_index;
463    idl_byte *struct_defn_ptr;
464
465    *p_optimize = idl_false;
466    *p_base_type = *defn_vec_ptr;
467
468    base_type = *p_base_type;
469    if (base_type == IDL_DT_FIXED_ARRAY)
470    {
471        /* Base type of a pipe is an array. Find its base type */
472        IDL_DISCARD_LONG_FROM_VECTOR( defn_vec_ptr );    /* Full array defn */
473        IDL_GET_LONG_FROM_VECTOR( defn_index, defn_vec_ptr );
474        defn_vec_ptr = IDL_msp->IDL_type_vec + defn_index;
475        pipe_arr_dims = (idl_ulong_int)*defn_vec_ptr;
476        defn_vec_ptr++;     /* By design this achieves 4-byte alignment */
477        defn_vec_ptr += pipe_arr_dims * IDL_FIXED_BOUND_PAIR_WIDTH;
478        base_type = *defn_vec_ptr;
479    }
480
481    switch( base_type )
482    {
483#ifdef PACKED_BYTE_ARRAYS
484        case IDL_DT_BYTE:
485            *p_optimize = idl_true;
486            break;
487#endif
488#ifdef PACKED_CHAR_ARRAYS
489        case IDL_DT_CHAR:
490            if (marsh_or_unmar == IDL_marshalling_k)
491                *p_optimize = idl_true;
492            else
493                *p_optimize =
494                     (IDL_msp->IDL_drep.char_rep == ndr_g_local_drep.char_rep);
495            break;
496#endif
497#ifdef PACKED_SCALAR_ARRAYS
498        case IDL_DT_BOOLEAN:
499            *p_optimize = idl_true;
500            break;
501        case IDL_DT_DOUBLE:
502            if (marsh_or_unmar == IDL_marshalling_k)
503            {
504                IDL_MARSH_ALIGN_MP(IDL_msp, 8);
505                *p_optimize = idl_true;
506            }
507            else
508            {
509                IDL_UNMAR_ALIGN_MP(IDL_msp, 8);
510                *p_optimize =
511                    ((IDL_msp->IDL_drep.float_rep == ndr_g_local_drep.float_rep)
512                    && (IDL_msp->IDL_drep.int_rep == ndr_g_local_drep.int_rep));
513            }
514            break;
515        case IDL_DT_FLOAT:
516            if (marsh_or_unmar == IDL_marshalling_k)
517            {
518                IDL_MARSH_ALIGN_MP(IDL_msp, 4);
519                *p_optimize = idl_true;
520            }
521            else
522            {
523                IDL_UNMAR_ALIGN_MP(IDL_msp, 4);
524                *p_optimize =
525                    ((IDL_msp->IDL_drep.float_rep == ndr_g_local_drep.float_rep)
526                    && (IDL_msp->IDL_drep.int_rep == ndr_g_local_drep.int_rep));
527            }
528            break;
529        case IDL_DT_SMALL:
530        case IDL_DT_USMALL:
531            if (marsh_or_unmar == IDL_marshalling_k)
532                *p_optimize = idl_true;
533            else
534                *p_optimize =
535                     (IDL_msp->IDL_drep.int_rep == ndr_g_local_drep.int_rep);
536            break;
537        case IDL_DT_USHORT:
538            /* If language is C, drop through */
539        case IDL_DT_SHORT:
540            if (marsh_or_unmar == IDL_marshalling_k)
541            {
542                IDL_MARSH_ALIGN_MP(IDL_msp, 2);
543                *p_optimize = idl_true;
544            }
545            else
546            {
547                IDL_UNMAR_ALIGN_MP(IDL_msp, 2);
548                *p_optimize =
549                    (IDL_msp->IDL_drep.int_rep == ndr_g_local_drep.int_rep);
550            }
551            break;
552        case IDL_DT_ERROR_STATUS:
553            /* If ifdef not active, drop through to next case */
554#ifdef IDL_ENABLE_STATUS_MAPPING
555            if (marsh_or_unmar == IDL_marshalling_k)
556            {
557                IDL_MARSH_ALIGN_MP(IDL_msp, 4);
558            }
559            else
560            {
561                IDL_UNMAR_ALIGN_MP(IDL_msp, 4);
562            }
563            break;
564#endif
565        case IDL_DT_LONG:
566        case IDL_DT_ULONG:
567            if (marsh_or_unmar == IDL_marshalling_k)
568            {
569                IDL_MARSH_ALIGN_MP(IDL_msp, 4);
570                *p_optimize = idl_true;
571            }
572            else
573            {
574                IDL_UNMAR_ALIGN_MP(IDL_msp, 4);
575                *p_optimize =
576                    (IDL_msp->IDL_drep.int_rep == ndr_g_local_drep.int_rep);
577            }
578            break;
579        case IDL_DT_HYPER:
580        case IDL_DT_UHYPER:
581            if (marsh_or_unmar == IDL_marshalling_k)
582            {
583                IDL_MARSH_ALIGN_MP(IDL_msp, 8);
584                *p_optimize = idl_true;
585            }
586            else
587            {
588                IDL_UNMAR_ALIGN_MP(IDL_msp, 8);
589                *p_optimize =
590                    (IDL_msp->IDL_drep.int_rep == ndr_g_local_drep.int_rep);
591            }
592            break;
593        case IDL_DT_ENUM:
594            if (marsh_or_unmar == IDL_marshalling_k)
595            {
596                IDL_MARSH_ALIGN_MP(IDL_msp, 2);
597                *p_optimize = (sizeof(int) == sizeof(idl_short_int));
598            }
599            else
600            {
601                IDL_UNMAR_ALIGN_MP(IDL_msp, 2);
602                *p_optimize = (sizeof(int) == sizeof(idl_short_int)) &&
603                    (IDL_msp->IDL_drep.int_rep == ndr_g_local_drep.int_rep);
604            }
605            break;
606        case IDL_DT_V1_ENUM:
607            if (marsh_or_unmar == IDL_marshalling_k)
608            {
609                IDL_MARSH_ALIGN_MP(IDL_msp, 4);
610                *p_optimize = (sizeof(int) == sizeof(idl_long_int));
611            }
612            else
613            {
614                IDL_UNMAR_ALIGN_MP(IDL_msp, 4);
615                *p_optimize = (sizeof(int) == sizeof(idl_long_int)) &&
616                    (IDL_msp->IDL_drep.int_rep == ndr_g_local_drep.int_rep);
617            }
618            break;
619#endif
620        case IDL_DT_FIXED_STRUCT:
621            defn_vec_ptr++;     /* Point at properties byte */
622            /* Could the structure be relied to be correctly laid out
623                in memory on some architecture? */
624            if ( ! IDL_PROP_TEST(*defn_vec_ptr, IDL_PROP_MAYBE_WIRE_ALIGNED))
625                break;
626            if (marsh_or_unmar == IDL_unmarshalling_k)
627            {
628                /* Can only unmarshall by copying if the drep's for all the
629                    fields match */
630                if ( IDL_PROP_TEST(*defn_vec_ptr, IDL_PROP_DEP_CHAR)
631                        && (IDL_msp->IDL_drep.char_rep
632                                                 != ndr_g_local_drep.char_rep) )
633                    break;
634                if ( IDL_PROP_TEST(*defn_vec_ptr, IDL_PROP_DEP_INT)
635                        && (IDL_msp->IDL_drep.int_rep
636                                                 != ndr_g_local_drep.int_rep) )
637                    break;
638                /* For floating point numbers we need the same encoding
639                        and the same endianness */
640                if ( IDL_PROP_TEST(*defn_vec_ptr, IDL_PROP_DEP_FLOAT)
641                        && ((IDL_msp->IDL_drep.float_rep
642                                                 != ndr_g_local_drep.float_rep)
643                            || (IDL_msp->IDL_drep.int_rep
644                                                != ndr_g_local_drep.int_rep)) )
645                    break;
646            }
647            defn_vec_ptr++;     /* Point after properties byte */
648            IDL_GET_LONG_FROM_VECTOR(struct_defn_index, defn_vec_ptr);
649            struct_defn_ptr = IDL_msp->IDL_type_vec + struct_defn_index;
650            IDL_DISCARD_LONG_FROM_VECTOR(struct_defn_ptr);
651                                          /* Discard index into offset vector */
652            /* Because we can't get here for a [v1_struct], the next byte
653                    is an alignment byte unless all the fields are 1-byte */
654            switch (*struct_defn_ptr)
655            {
656                case IDL_DT_NDR_ALIGN_8:
657#ifdef IDL_NATURAL_ALIGN_8
658                    if (marsh_or_unmar == IDL_marshalling_k)
659                    {
660                        IDL_MARSH_ALIGN_MP(IDL_msp, 8);
661                    }
662                    else
663                    {
664                        IDL_UNMAR_ALIGN_MP(IDL_msp, 8);
665                    }
666                    *p_optimize = idl_true;
667#endif
668                    break;
669                case IDL_DT_NDR_ALIGN_4:
670#if defined(IDL_NATURAL_ALIGN_8) || defined(IDL_NATURAL_ALIGN_4)
671                    if (marsh_or_unmar == IDL_marshalling_k)
672                    {
673                        IDL_MARSH_ALIGN_MP(IDL_msp, 4);
674                    }
675                    else
676                    {
677                        IDL_UNMAR_ALIGN_MP(IDL_msp, 4);
678                    }
679                    *p_optimize = idl_true;
680#endif
681                    break;
682                case IDL_DT_NDR_ALIGN_2:
683#if defined(IDL_NATURAL_ALIGN_8) || defined(IDL_NATURAL_ALIGN_4)
684                    if (marsh_or_unmar == IDL_marshalling_k)
685                    {
686                        IDL_MARSH_ALIGN_MP(IDL_msp, 2);
687                    }
688                    else
689                    {
690                        IDL_UNMAR_ALIGN_MP(IDL_msp, 2);
691                    }
692                    *p_optimize = idl_true;
693#endif
694                    break;
695                default:
696#if defined(IDL_NATURAL_ALIGN_8) || defined(IDL_NATURAL_ALIGN_4) || defined(IDL_NATURAL_ALIGN_1)
697                    *p_optimize = idl_true;
698#endif
699                    break;
700            }
701            break;
702        default:
703            break;
704    }
705}
706
707/******************************************************************************/
708/*                                                                            */
709/*  Function whose result is the integer that is of the given type at the     */
710/*   given address. For use in unions, boolean's, char's and enum's are       */
711/*   treated as integers.                                                     */
712/*                                                                            */
713/******************************************************************************/
714idl_long_int rpc_ss_get_typed_integer
715(
716    /* [in] */  idl_byte type,
717    /* [in] */  rpc_void_p_t address,
718    IDL_msp_t IDL_msp ATTRIBUTE_UNUSED
719)
720{
721    switch (type)
722    {
723        case IDL_DT_BOOLEAN:
724            return( (idl_long_int)(*(idl_boolean *)address) );
725        case IDL_DT_CHAR:
726            return( (idl_long_int)(*(idl_char *)address) );
727        case IDL_DT_ENUM:
728        case IDL_DT_V1_ENUM:
729            return( (idl_long_int)(*(int *)address) );
730        case IDL_DT_SMALL:
731                return( (idl_long_int)(*(idl_small_int *)address) );
732        case IDL_DT_SHORT:
733            return( (idl_long_int)(*(idl_short_int *)address) );
734        case IDL_DT_LONG:
735            return( (idl_long_int)(*(idl_long_int *)address) );
736        case IDL_DT_USMALL:
737                return( (idl_long_int)(*(idl_usmall_int *)address) );
738        case IDL_DT_USHORT:
739                return( (idl_long_int)(*(idl_ushort_int *)address) );
740        case IDL_DT_ERROR_STATUS:
741        case IDL_DT_ULONG:
742            /* !!! Overflow here if value > 2**31 - 1 !!! */
743            return( (idl_long_int)(*(idl_ulong_int *)address) );
744        default:
745            DCETHREAD_RAISE( rpc_x_coding_error );
746    }
747}
748
749/******************************************************************************/
750/*                                                                            */
751/*  Build a bounds list for a conformant or open array                        */
752/*                                                                            */
753/******************************************************************************/
754void rpc_ss_build_bounds_list
755(
756    /* [in,out] */ idl_byte **p_defn_vec_ptr,
757                        /* On entry defn_vec_ptr points to bounds info */
758                        /* On exit it points at
759                                    conformant array - base type info
760                                    open array - data limit info */
761    /* [in] */  rpc_void_p_t array_addr,    /* NULL when building bounds list
762                                                for a conformant structure */
763    /* [in] */  rpc_void_p_t struct_addr,   /* Address of structure that array
764                                   is field of. NULL if array is a parameter */
765    /* [in] */  idl_ulong_int *struct_offset_vec_ptr,
766                                           /*  NULL if array is a parameter */
767    /* [in] */  idl_ulong_int dimensionality,
768    /* [out] */ IDL_bound_pair_t **p_bounds_list,
769    IDL_msp_t IDL_msp
770)
771{
772    return rpc_ss_build_bounds_list_2(p_defn_vec_ptr, array_addr, struct_addr,
773                                      struct_offset_vec_ptr, dimensionality,
774                                      NULL, p_bounds_list, IDL_msp);
775}
776
777/******************************************************************************/
778/*                                                                            */
779/*  Build a bounds list for a conformant or open array, with an optional      */
780/*  bitmap indicating whether correlated arguments are yet to be unmarshalled */
781/*                                                                            */
782/******************************************************************************/
783void rpc_ss_build_bounds_list_2
784(
785    /* [in,out] */ idl_byte **p_defn_vec_ptr,
786                        /* On entry defn_vec_ptr points to bounds info */
787                        /* On exit it points at
788                                    conformant array - base type info
789                                    open array - data limit info */
790    /* [in] */  rpc_void_p_t array_addr,    /* NULL when building bounds list
791                                                for a conformant structure */
792    /* [in] */  rpc_void_p_t struct_addr,   /* Address of structure that array
793                                   is field of. NULL if array is a parameter */
794    /* [in] */  idl_ulong_int *struct_offset_vec_ptr,
795                                           /*  NULL if array is a parameter */
796    /* [in] */  idl_ulong_int dimensionality,
797    /* [in] */  idl_boolean *unmarshalled_list, /* NULL if marshalling */
798    /* [out] */ IDL_bound_pair_t **p_bounds_list,
799    IDL_msp_t IDL_msp
800)
801{
802    IDL_bound_pair_t *bounds_list;
803    idl_byte *defn_vec_ptr = *p_defn_vec_ptr;
804    idl_byte bound_kind, bound_type;
805    unsigned32 i;
806    idl_long_int size;
807    idl_ulong_int element_size;     /* Size of base type of string */
808    idl_ulong_int attribute_index;
809    rpc_void_p_t bound_addr;
810    idl_ulong_int string_field_offset;  /* Offset index for string field */
811	byte func_code = 0;
812
813    if (*p_bounds_list == NULL)
814    {
815        bounds_list = (IDL_bound_pair_t *)rpc_ss_mem_alloc
816          (&IDL_msp->IDL_mem_handle, dimensionality * sizeof(IDL_bound_pair_t));
817        *p_bounds_list = bounds_list;
818    }
819    else
820        bounds_list = *p_bounds_list;
821
822    for (i = 0; i < dimensionality; i++)
823    {
824        /* Get lower bound */
825        bound_kind = (*defn_vec_ptr & IDL_BOUND_TYPE_MASK);
826        defn_vec_ptr++;
827        if (bound_kind == IDL_BOUND_FIXED)
828        {
829            IDL_GET_LONG_FROM_VECTOR(bounds_list[i].lower, defn_vec_ptr);
830        }
831        else
832        {
833            /* Lower bound is [min_is] */
834            bound_type = *defn_vec_ptr;
835            defn_vec_ptr++;
836            IDL_GET_LONG_FROM_VECTOR(attribute_index, defn_vec_ptr);
837            if (unmarshalled_list == NULL || unmarshalled_list[i])
838            {
839                if (struct_addr == NULL)
840                    bound_addr = IDL_msp->IDL_param_vec[attribute_index];
841                else
842                {
843                    bound_addr = (rpc_void_p_t)
844                            ((idl_byte *)struct_addr
845                                     + struct_offset_vec_ptr[attribute_index]);
846                }
847                bounds_list[i].lower =
848                             rpc_ss_get_typed_integer( bound_type, bound_addr,
849                                                         IDL_msp );
850            }
851            else
852                bounds_list[i].lower = -1;
853        }
854
855        /* Get upper bound */
856        bound_kind = (*defn_vec_ptr & IDL_BOUND_TYPE_MASK);
857        defn_vec_ptr++;
858        if (bound_kind == IDL_BOUND_FIXED)
859        {
860            IDL_GET_LONG_FROM_VECTOR(bounds_list[i].upper, defn_vec_ptr);
861        }
862        else if (bound_kind == IDL_BOUND_STRING)
863        {
864            element_size = (idl_ulong_int)*defn_vec_ptr;
865            defn_vec_ptr++;
866            IDL_GET_LONG_FROM_VECTOR(string_field_offset, defn_vec_ptr);
867                        /* Value is only used in conformant struct size case */
868            if (unmarshalled_list == NULL || unmarshalled_list[i])
869            {
870                if (array_addr == NULL)
871                {
872                    /* Conformant field of conformant structure
873                        has size determined by [string] */
874                    array_addr = (rpc_void_p_t)((idl_byte *)struct_addr
875                                                    + *(struct_offset_vec_ptr
876                                                            + string_field_offset));
877                }
878                if (element_size == 1)
879                    bounds_list[i].upper = bounds_list[i].lower
880                                                             + (idl_long_int) strlen(array_addr);
881                else
882                {
883                    size = rpc_ss_strsiz( (idl_char *)array_addr, element_size );
884                    bounds_list[i].upper = bounds_list[i].lower + size - 1;
885                }
886            }
887            else
888                bounds_list[i].upper = -1;
889        }
890        else
891        {
892            if (bound_kind == IDL_BOUND_SIZE_IS)
893            {
894                func_code = *defn_vec_ptr;
895                defn_vec_ptr++;
896            }
897            /* Upper bound is [max_is] or [size_is] */
898            bound_type = *defn_vec_ptr;
899            defn_vec_ptr++;
900            IDL_GET_LONG_FROM_VECTOR(attribute_index, defn_vec_ptr);
901            if (unmarshalled_list == NULL || unmarshalled_list[i])
902            {
903                if (struct_addr == NULL)
904                    bound_addr = IDL_msp->IDL_param_vec[attribute_index];
905                else
906                {
907                    bound_addr = (rpc_void_p_t)
908                            ((idl_byte *)struct_addr
909                                     + struct_offset_vec_ptr[attribute_index]);
910                }
911                if (bound_kind == IDL_BOUND_MAX_IS)
912                    bounds_list[i].upper =
913                             rpc_ss_get_typed_integer( bound_type, bound_addr,
914                                                        IDL_msp );
915                else /* IDL_BOUND_SIZE_IS */
916                {
917                    size = rpc_ss_get_typed_integer( bound_type, bound_addr,
918                                                        IDL_msp );
919
920                    bounds_list[i].upper = bounds_list[i].lower +
921                             interpsh_apply_func_code(func_code, size) - 1;
922                }
923            }
924            else
925                bounds_list[i].upper = -1;
926        }
927        /* Inside out bounds mean "no elements". Store value which will
928            yield 0 in subsequent calculations */
929        if (bounds_list[i].upper < bounds_list[i].lower)
930            bounds_list[i].upper = bounds_list[i].lower - 1;
931    }
932
933    *p_defn_vec_ptr = defn_vec_ptr;
934}
935
936/******************************************************************************/
937/*                                                                            */
938/*  A range list is a set of [A, A+B] pairs for a varying array. Build one.   */
939/*  Note that A is the difference between the lower bound and the index of    */
940/*  the first element in the dimension to be shipped. B is the number of      */
941/*  elements in that dimension to be shipped.                                 */
942/*                                                                            */
943/******************************************************************************/
944void rpc_ss_build_range_list
945(
946    /* [in,out] */ idl_byte **p_defn_vec_ptr,
947    /* [in] */  rpc_void_p_t array_addr,  /* Only used if [string] data limit */
948    /* [in] */  rpc_void_p_t struct_addr,   /* Address of structure array is a
949                                 field of. NULL if array is a parameter */
950    /* [in] */  idl_ulong_int *struct_offset_vec_ptr,
951                                           /*  NULL if array is a parameter */
952    /* [in] */  idl_ulong_int dimensionality,
953    /* [in] */  IDL_bound_pair_t *bounds_list,
954    /* [out] */ IDL_bound_pair_t **p_range_list,
955    /* [out] */ idl_boolean *p_add_null,
956    IDL_msp_t IDL_msp
957)
958{
959    return rpc_ss_build_range_list_2(p_defn_vec_ptr, array_addr, struct_addr,
960                                     struct_offset_vec_ptr, dimensionality,
961                                     bounds_list, NULL, p_range_list, p_add_null,
962                                     IDL_msp);
963}
964
965/******************************************************************************/
966/*                                                                            */
967/*  A range list is a set of [A, A+B] pairs for a varying array. Build one,   */
968/*  with an optoinal bitmap indicating whether correlated arguments are yet   */
969/*  to be unmarshalled.                                                       */
970/*  Note that A is the difference between the lower bound and the index of    */
971/*  the first element in the dimension to be shipped. B is the number of      */
972/*  elements in that dimension to be shipped.                                 */
973/*                                                                            */
974/******************************************************************************/
975void rpc_ss_build_range_list_2
976(
977    /* [in,out] */ idl_byte **p_defn_vec_ptr,
978    /* [in] */  rpc_void_p_t array_addr,  /* Only used if [string] data limit */
979    /* [in] */  rpc_void_p_t struct_addr,   /* Address of structure array is a
980                                 field of. NULL if array is a parameter */
981    /* [in] */  idl_ulong_int *struct_offset_vec_ptr,
982                                           /*  NULL if array is a parameter */
983    /* [in] */  idl_ulong_int dimensionality,
984    /* [in] */  IDL_bound_pair_t *bounds_list,
985    /* [in] */  idl_boolean *unmarshalled_list, /* NULL if marshalling */
986    /* [out] */ IDL_bound_pair_t **p_range_list,
987    /* [out] */ idl_boolean *p_add_null,
988    IDL_msp_t IDL_msp
989)
990{
991    IDL_bound_pair_t *range_list;
992    idl_byte *defn_vec_ptr = *p_defn_vec_ptr;
993    idl_byte limit_kind, limit_type;
994    unsigned32 i;
995    idl_long_int data_limit;
996    idl_ulong_int element_size;     /* Size of base type of string */
997    idl_ulong_int attribute_index;
998    rpc_void_p_t limit_addr;
999    byte func_code = 0;
1000
1001    *p_add_null = idl_false;
1002    if (*p_range_list == NULL)
1003    {
1004        range_list = (IDL_bound_pair_t *)rpc_ss_mem_alloc
1005          (&IDL_msp->IDL_mem_handle, dimensionality * sizeof(IDL_bound_pair_t));
1006        *p_range_list = range_list;
1007    }
1008    else
1009        range_list = *p_range_list;
1010
1011    for (i=0; i<dimensionality; i++)
1012    {
1013        /* Get lower data limit */
1014        limit_kind = (*defn_vec_ptr & IDL_LIMIT_TYPE_MASK);
1015        defn_vec_ptr++;
1016        if (limit_kind == IDL_LIMIT_FIXED)
1017        {
1018            IDL_GET_LONG_FROM_VECTOR(data_limit, defn_vec_ptr);
1019        }
1020        else
1021        {
1022            /* Lower data limit is [first_is] */
1023            limit_type = *defn_vec_ptr;
1024            defn_vec_ptr++;
1025            IDL_GET_LONG_FROM_VECTOR(attribute_index, defn_vec_ptr);
1026            if (unmarshalled_list == NULL || unmarshalled_list[i])
1027            {
1028                if (struct_addr == NULL)
1029                    limit_addr = IDL_msp->IDL_param_vec[attribute_index];
1030                else
1031                {
1032                    limit_addr = (rpc_void_p_t)
1033                            ((idl_byte *)struct_addr
1034                                     + struct_offset_vec_ptr[attribute_index]);
1035                }
1036                data_limit = rpc_ss_get_typed_integer( limit_type, limit_addr,
1037                                                        IDL_msp );
1038            }
1039        }
1040
1041        if (unmarshalled_list == NULL || unmarshalled_list[i])
1042        {
1043            range_list[i].lower = data_limit - bounds_list[i].lower;
1044            if (range_list[i].lower < 0)
1045                DCETHREAD_RAISE( rpc_x_invalid_bound );
1046        }
1047        else
1048            range_list[i].lower = -1;
1049
1050        /* Get upper data limit */
1051        limit_kind = (*defn_vec_ptr & IDL_LIMIT_TYPE_MASK);
1052        defn_vec_ptr++;
1053        if (limit_kind == IDL_LIMIT_FIXED)
1054        {
1055            IDL_GET_LONG_FROM_VECTOR(data_limit, defn_vec_ptr);
1056            range_list[i].upper = data_limit + 1 - bounds_list[i].lower;
1057        }
1058        else if (limit_kind == IDL_LIMIT_STRING)
1059        {
1060            element_size = (idl_ulong_int)*defn_vec_ptr;
1061            /* Element size byte is discarded as we align to discard dummy
1062                longword */
1063            IDL_DISCARD_LONG_FROM_VECTOR(defn_vec_ptr);
1064            if (unmarshalled_list == NULL || unmarshalled_list[i])
1065            {
1066                if (element_size == 1)
1067                    data_limit = (idl_long_int) strlen(array_addr) + 1;
1068                else
1069                    data_limit = rpc_ss_strsiz( (idl_char *)array_addr,
1070                                                                 element_size );
1071                range_list[i].upper = range_list[i].lower + data_limit;
1072                if ( ! (*p_add_null) )
1073                {
1074                    if ( range_list[i].upper > (bounds_list[i].upper
1075                                            - bounds_list[i].lower + 1) )
1076                        DCETHREAD_RAISE( rpc_x_invalid_bound );
1077                }
1078            }
1079            else
1080                range_list[i].upper = -1;
1081        }
1082        else if (limit_kind == IDL_LIMIT_UPPER_CONF)
1083        {
1084            /* Dummy type byte is discarded as we align to discard dummy
1085                longword */
1086            IDL_DISCARD_LONG_FROM_VECTOR( defn_vec_ptr );
1087            range_list[i].upper =
1088                                bounds_list[i].upper - bounds_list[i].lower + 1;
1089        }
1090        else
1091        {
1092            /* Upper data limit is [last_is] or [length_is] */
1093            if (limit_kind == IDL_LIMIT_LENGTH_IS)
1094            {
1095                func_code = *defn_vec_ptr;
1096                defn_vec_ptr++;
1097            }
1098
1099            limit_type = *defn_vec_ptr;
1100            defn_vec_ptr++;
1101            IDL_GET_LONG_FROM_VECTOR(attribute_index, defn_vec_ptr);
1102            if (unmarshalled_list == NULL || unmarshalled_list[i])
1103            {
1104                if (struct_addr == NULL)
1105                    limit_addr = IDL_msp->IDL_param_vec[attribute_index];
1106                else
1107                {
1108                    limit_addr = (rpc_void_p_t)
1109                            ((idl_byte *)struct_addr
1110                                     + struct_offset_vec_ptr[attribute_index]);
1111                }
1112                data_limit = rpc_ss_get_typed_integer( limit_type, limit_addr,
1113                                                       IDL_msp );
1114                if (limit_kind == IDL_LIMIT_LENGTH_IS)
1115                {
1116                    range_list[i].upper = range_list[i].lower + interpsh_apply_func_code(func_code, data_limit);
1117                }
1118                else
1119                {
1120                    range_list[i].upper = data_limit - bounds_list[i].lower + 1;
1121                }
1122                if ( range_list[i].upper > (bounds_list[i].upper
1123                                            - bounds_list[i].lower + 1) )
1124                    DCETHREAD_RAISE( rpc_x_invalid_bound );
1125            }
1126            else
1127                range_list[i].upper = -1;
1128        }
1129#ifdef DEBUG_INTERP
1130        if (unmarshalled_list == NULL || unmarshalled_list[i])
1131            printf("dim %lu range upr: %ld lwr: %ld func: %d\n", i,
1132                   range_list[i].upper, range_list[i].lower, func_code);
1133#endif
1134        /* Inside out limits mean "transmit no elements" */
1135        if (range_list[i].upper < range_list[i].lower)
1136            range_list[i].upper = range_list[i].lower;
1137    }
1138
1139    *p_defn_vec_ptr = defn_vec_ptr;
1140}
1141
1142/******************************************************************************/
1143/*                                                                            */
1144/*  Get the size of string storage for the base type of an array of string    */
1145/*  and the index value of the start of the string's array description        */
1146/*                                                                            */
1147/******************************************************************************/
1148void rpc_ss_get_string_base_desc
1149(
1150    /* [in] */  idl_byte *defn_vec_ptr, /* Pointer to DT_STRING in base type
1151                                        specification in definition vector */
1152    /* [out] */ idl_ulong_int *p_array_size,
1153    /* [out] */ idl_ulong_int *p_array_defn_index,
1154    IDL_msp_t IDL_msp
1155)
1156{
1157    idl_byte *array_defn_ptr;
1158    idl_long_int string_lower_bound, string_upper_bound;
1159    idl_ulong_int array_element_count;
1160
1161    defn_vec_ptr += 3;  /* DT_STRING, DT_VARYING_ARRAY, properties */
1162    IDL_DISCARD_LONG_FROM_VECTOR(defn_vec_ptr);
1163    /* Ignore the full array definition and look at the flattened one */
1164    IDL_GET_LONG_FROM_VECTOR(*p_array_defn_index, defn_vec_ptr);
1165    array_defn_ptr = IDL_msp->IDL_type_vec + *p_array_defn_index;
1166    array_defn_ptr++;   /* Discard dimensionality */
1167    IDL_GET_LONG_FROM_VECTOR(string_lower_bound, array_defn_ptr);
1168    IDL_GET_LONG_FROM_VECTOR(string_upper_bound, array_defn_ptr);
1169    array_element_count = string_upper_bound - string_lower_bound + 1;
1170    *p_array_size =
1171            array_element_count * IDL_DATA_LIMIT_PAIR_CHAR_SIZE(array_defn_ptr);
1172}
1173
1174/******************************************************************************/
1175/*                                                                            */
1176/*  Point at the union arm definition for the supplied switch value           */
1177/*  Returns FALSE if there is no match, TRUE otherwise                        */
1178/*                                                                            */
1179/******************************************************************************/
1180idl_boolean rpc_ss_find_union_arm_defn
1181(
1182    /* [in] */ idl_byte *defn_vec_ptr,    /* Points at first union arm defn */
1183    /* [in] */ idl_ulong_int arm_count,   /* Number of non-default arms */
1184    /* [in] */ idl_ulong_int switch_value,  /* to be matched */
1185    /* [out] */ idl_byte **p_arm_type_ptr,
1186                    /* Pointer to type part of arm with matching switch value */
1187    /* [in] */ IDL_msp_t IDL_msp
1188                    /* marshall state ptr needed for IDL_ARM macro */
1189)
1190{
1191    idl_long_int low, mid, high;         /* Element indices */
1192    idl_ulong_int arm_switch_value;       /* To test supplied value against */
1193
1194    /* If there are no elements to search, then return no match found. */
1195
1196    if (arm_count == 0)
1197        return(idl_false);
1198
1199    /* Initialize the search interval to include all elements. */
1200
1201    low = 0;
1202    high = arm_count - 1;
1203
1204    /*  Loop, computing the midpoint element and comparing it to the desired
1205         element until a match is found or all elements are exhausted.
1206         Note that the midpoint index by convention is always
1207         rounded down if there is a remainder after division.
1208     */
1209    do {
1210        mid = (low + high) / 2;         /* Compute midpoint element */
1211        arm_switch_value = IDL_ARM_SWITCH_VALUE(defn_vec_ptr, mid);
1212        if (switch_value > arm_switch_value)
1213        {
1214            /* If element is beyond the midpoint */
1215            low = mid + 1;              /*  adjust low index past midpoint */
1216        }
1217        else if (switch_value < arm_switch_value)
1218        {
1219            /* If element is prior to the midpoint */
1220            high = mid - 1;         /*  adjust high index below midpoint */
1221        }
1222        else
1223            break;                  /* Otherwise, element was found! */
1224    } while (high >= low);
1225
1226    if (high >= low)
1227    {
1228        /* Match was found - point at arm that matched */
1229        *p_arm_type_ptr = defn_vec_ptr + mid * IDL_UNION_ARM_DESC_WIDTH;
1230        /* Advance pointer over switch value */
1231        IDL_DISCARD_LONG_FROM_VECTOR( *p_arm_type_ptr );
1232        return(idl_true);
1233    }
1234    else
1235        return(idl_false);
1236}
1237
1238/******************************************************************************/
1239/*                                                                            */
1240/*  Get, from data in memory, the value of the discriminant of a              */
1241/*      non-encapsulated union                                                */
1242/*                                                                            */
1243/******************************************************************************/
1244void rpc_ss_get_switch_from_data
1245(
1246    /* [in] */ idl_ulong_int switch_index,
1247                /* If union is parameter, index in param list of discriminant */
1248                /* If union is field, index in offset list for discriminant */
1249    /* [in] */ idl_byte switch_type,
1250    /* [in] */ rpc_void_p_t struct_addr,     /* Address of structure union is
1251                                        field of. NULL if union is parameter */
1252    /* [in] */ idl_ulong_int *struct_offset_vec_ptr,
1253                                                /* NULL if union is parameter */
1254    /* [out] */ idl_ulong_int *p_switch_value,
1255    IDL_msp_t IDL_msp
1256)
1257{
1258    rpc_void_p_t switch_addr;
1259
1260    if ( struct_addr == NULL )
1261        switch_addr = IDL_msp->IDL_param_vec[switch_index];
1262    else
1263        switch_addr = (rpc_void_p_t)((idl_byte *)struct_addr
1264                                       + struct_offset_vec_ptr[switch_index]);
1265
1266    *p_switch_value = rpc_ss_get_typed_integer( switch_type, switch_addr,
1267                                                    IDL_msp );
1268}
1269
1270/******************************************************************************/
1271/*                                                                            */
1272/*  Return TRUE if a -bug flag in the range 1-31 is set                       */
1273/*                                                                            */
1274/******************************************************************************/
1275idl_boolean rpc_ss_bug_1_thru_31
1276(
1277    /* [in] */ idl_ulong_int bug_mask,
1278    IDL_msp_t IDL_msp
1279)
1280{
1281    idl_byte *defn_vec_ptr;
1282    idl_ulong_int defn_index;
1283    idl_ulong_int flags;
1284
1285    /* Get position of bug flags */
1286    defn_vec_ptr = IDL_msp->IDL_type_vec + 40;
1287    IDL_GET_LONG_FROM_VECTOR( defn_index, defn_vec_ptr );
1288
1289    /* Get flags longword for bugs 1-31 */
1290    defn_vec_ptr = IDL_msp->IDL_type_vec + defn_index;
1291    IDL_GET_LONG_FROM_VECTOR( flags, defn_vec_ptr );
1292
1293    return( (flags & bug_mask) != 0 );
1294}
1295
1296/******************************************************************************/
1297/*                                                                            */
1298/*  If -bug 1 is set and we are marshalling a [v1_array] with no elements,    */
1299/*  alignment must be forced to the last scalar that would have been          */
1300/*  marshalled if we had marshalled an array element.                         */
1301/*  This function returns the alignment to be applied.                        */
1302/*                                                                            */
1303/******************************************************************************/
1304idl_ulong_int rpc_ss_ndr_bug_1_align
1305(
1306    /* [in] */ idl_byte *defn_vec_ptr,     /* Points at array base type unless
1307                        in recursive call. In recursive call, points at defn
1308                        of structure field, union arm, or transmitted type */
1309    IDL_msp_t IDL_msp
1310)
1311{
1312    idl_ulong_int defn_index;
1313    idl_byte *struct_defn_ptr;
1314    idl_byte *last_field_defn_ptr = NULL;  /* Points to the definition of the last
1315                                        field of a structure */
1316    idl_byte type_byte;
1317    idl_ulong_int array_defn_index;
1318    idl_byte *array_defn_ptr;
1319    idl_ulong_int dimensionality;
1320    idl_byte *union_defn_ptr;
1321    idl_ulong_int arm_count;
1322    idl_ulong_int min_union_align;  /* Minimum alignment forced by any
1323                                                                union arm */
1324    idl_ulong_int arm_align;       /* Alignment for last field of current arm */
1325    unsigned32 i;
1326
1327    type_byte = *defn_vec_ptr;
1328    switch (type_byte)
1329    {
1330        case IDL_DT_BYTE:
1331        case IDL_DT_CHAR:
1332        case IDL_DT_BOOLEAN:
1333        case IDL_DT_SMALL:
1334        case IDL_DT_USMALL:
1335            return 1;
1336        case IDL_DT_SHORT:
1337        case IDL_DT_USHORT:
1338            return 2;
1339        case IDL_DT_FLOAT:
1340        case IDL_DT_LONG:
1341        case IDL_DT_ULONG:
1342        case IDL_DT_V1_ENUM:
1343        case IDL_DT_ERROR_STATUS:
1344            return 4;
1345        case IDL_DT_DOUBLE:
1346        case IDL_DT_HYPER:
1347        case IDL_DT_UHYPER:
1348            return 8;
1349        case IDL_DT_FIXED_STRUCT:
1350            /* Structure analysis follows switch statement */
1351            break;
1352        case IDL_DT_FIXED_ARRAY:
1353        case IDL_DT_VARYING_ARRAY:
1354        case IDL_DT_OPEN_ARRAY:
1355            /* Alignment forced by array base type */
1356            defn_vec_ptr += 2;   /* DT_ARRAY and properties byte */
1357            IDL_DISCARD_LONG_FROM_VECTOR( defn_vec_ptr );
1358                                            /* Full array definition */
1359            IDL_GET_LONG_FROM_VECTOR( array_defn_index, defn_vec_ptr );
1360            array_defn_ptr = IDL_msp->IDL_type_vec + array_defn_index;
1361            dimensionality = (idl_ulong_int)*array_defn_ptr;
1362            if (type_byte == IDL_DT_FIXED_ARRAY)
1363                array_defn_ptr += dimensionality * sizeof(IDL_bound_pair_t);
1364            else if (type_byte == IDL_DT_VARYING_ARRAY)
1365            {
1366                array_defn_ptr += dimensionality * IDL_FIXED_BOUND_PAIR_WIDTH;
1367                array_defn_ptr += dimensionality * IDL_DATA_LIMIT_PAIR_WIDTH;
1368            }
1369            else /* type_byte == IDL_OPEN_VARYING_ARRAY */
1370            {
1371                IDL_ADV_DEFN_PTR_OVER_BOUNDS( array_defn_ptr, dimensionality );
1372                array_defn_ptr += dimensionality * IDL_DATA_LIMIT_PAIR_WIDTH;
1373            }
1374            return rpc_ss_ndr_bug_1_align(array_defn_ptr, IDL_msp);
1375        case IDL_DT_V1_ARRAY:
1376        case IDL_DT_V1_STRING:
1377            /* Discard modiier - do array alignment */
1378            defn_vec_ptr++;
1379            return rpc_ss_ndr_bug_1_align(defn_vec_ptr, IDL_msp);
1380        case IDL_DT_ENC_UNION:
1381            /* Weakest alignment forced by any union arm */
1382            defn_vec_ptr += 2;   /* DT_ENC_UNION and properties byte */
1383            IDL_GET_LONG_FROM_VECTOR( defn_index, defn_vec_ptr );
1384            union_defn_ptr = IDL_msp->IDL_type_vec + defn_index;
1385            IDL_GET_LONG_FROM_VECTOR( arm_count, union_defn_ptr );
1386            IDL_DISCARD_LONG_FROM_VECTOR( union_defn_ptr );
1387                                            /* Point at type of first arm */
1388            min_union_align = 8;    /* Maximum alignment required by NDR */
1389            for (i=0; i<arm_count+1; i++)
1390            {
1391                if (*union_defn_ptr != IDL_DT_VOID)
1392                {
1393                    arm_align = rpc_ss_ndr_bug_1_align(union_defn_ptr, IDL_msp);
1394                    if (arm_align < min_union_align)
1395                        min_union_align = arm_align;
1396                }
1397                union_defn_ptr += IDL_UNION_ARM_DESC_WIDTH;
1398            }
1399            return min_union_align;
1400        case IDL_DT_TRANSMIT_AS:
1401            /* Resolve down to non-[transmit_as] type */
1402            while (*defn_vec_ptr == IDL_DT_TRANSMIT_AS)
1403            {
1404                defn_vec_ptr += 2;   /* DT_TRANSMIT_AS and properties byte */
1405                IDL_GET_LONG_FROM_VECTOR( defn_index, defn_vec_ptr );
1406                defn_vec_ptr = IDL_msp->IDL_type_vec + defn_index;
1407            }
1408            return rpc_ss_ndr_bug_1_align(defn_vec_ptr, IDL_msp);
1409        default:
1410            /* Other flags cannot occur in a [v1_struct] */
1411#ifdef DEBUG_INTERP
1412            printf(
1413               "rpc_ss_ndr_bug_1_struct_align:unrecognized alignment type %d\n",
1414                        type_byte);
1415            exit(0);
1416#endif
1417            DCETHREAD_RAISE(rpc_x_coding_error);
1418    }
1419
1420    /* Return alignment required for last field of structure */
1421    defn_vec_ptr += 2;     /* DT_FIXED_STRUCT and properties byte */
1422    IDL_GET_LONG_FROM_VECTOR(defn_index, defn_vec_ptr);
1423    struct_defn_ptr = IDL_msp->IDL_type_vec + defn_index;
1424
1425    /* Find the last field of the structure */
1426    do {
1427        type_byte = *struct_defn_ptr;
1428        if (type_byte != IDL_DT_EOL)
1429            last_field_defn_ptr = struct_defn_ptr;
1430        struct_defn_ptr++;
1431        switch(type_byte)
1432        {
1433            case IDL_DT_BYTE:
1434            case IDL_DT_CHAR:
1435            case IDL_DT_BOOLEAN:
1436            case IDL_DT_DOUBLE:
1437            case IDL_DT_FLOAT:
1438            case IDL_DT_SMALL:
1439            case IDL_DT_SHORT:
1440            case IDL_DT_LONG:
1441            case IDL_DT_HYPER:
1442            case IDL_DT_USMALL:
1443            case IDL_DT_USHORT:
1444            case IDL_DT_ULONG:
1445            case IDL_DT_UHYPER:
1446            case IDL_DT_V1_ENUM:
1447            case IDL_DT_ERROR_STATUS:
1448                break;
1449            case IDL_DT_FIXED_ARRAY:
1450                struct_defn_ptr++;     /* Skip over properties byte */
1451                IDL_DISCARD_LONG_FROM_VECTOR(struct_defn_ptr);
1452                                                    /* Full array definition */
1453                IDL_DISCARD_LONG_FROM_VECTOR(struct_defn_ptr);
1454                                                /* Flattened array definition */
1455                break;
1456            case IDL_DT_VARYING_ARRAY:
1457                struct_defn_ptr++;     /* Skip over properties byte */
1458                IDL_DISCARD_LONG_FROM_VECTOR(struct_defn_ptr);
1459                                                    /* Full array definition */
1460                IDL_DISCARD_LONG_FROM_VECTOR(struct_defn_ptr);
1461                                                /* Flattened array definition */
1462                break;
1463            case IDL_DT_OPEN_ARRAY:
1464                struct_defn_ptr++;     /* Skip over properties byte */
1465                IDL_DISCARD_LONG_FROM_VECTOR(struct_defn_ptr);
1466                                                    /* Full array definition */
1467                IDL_DISCARD_LONG_FROM_VECTOR(struct_defn_ptr);
1468                                                /* Flattened array definition */
1469                break;
1470            case IDL_DT_ENC_UNION:
1471                struct_defn_ptr++;     /* Skip over properties byte */
1472                IDL_DISCARD_LONG_FROM_VECTOR(struct_defn_ptr);
1473                                                /* Union definition */
1474                break;
1475            case IDL_DT_TRANSMIT_AS:
1476            case IDL_DT_REPRESENT_AS:
1477                struct_defn_ptr++;     /* Skip over properties byte */
1478                IDL_DISCARD_LONG_FROM_VECTOR(struct_defn_ptr);
1479                                                /* [transmit_as] definition */
1480                break;
1481            case IDL_DT_V1_ARRAY:
1482                break;
1483            case IDL_DT_V1_STRING:
1484                struct_defn_ptr += 2;  /* DT_VARYING_ARRAY and properties */
1485                IDL_DISCARD_LONG_FROM_VECTOR(struct_defn_ptr);
1486                                                        /* Full array defn */
1487                IDL_DISCARD_LONG_FROM_VECTOR(struct_defn_ptr);
1488                                                      /* Flattened array defn */
1489                break;
1490
1491            case IDL_DT_EOL:
1492                break;
1493            default:
1494                /* Other flags cannot occur in a [v1_struct] */
1495#ifdef DEBUG_INTERP
1496                printf(
1497                   "rpc_ss_ndr_bug_1_struct_align:unrecognized field type %d\n",
1498                        type_byte);
1499                exit(0);
1500#endif
1501                DCETHREAD_RAISE(rpc_x_coding_error);
1502        }
1503    } while (type_byte != IDL_DT_EOL);
1504
1505    /* Do alignment for last field */
1506    return rpc_ss_ndr_bug_1_align(last_field_defn_ptr, IDL_msp);
1507}
1508
1509/******************************************************************************/
1510/*                                                                            */
1511/*  Check type vector consistent with interpreter version                     */
1512/*                                                                            */
1513/******************************************************************************/
1514void rpc_ss_type_vec_vers_check
1515(
1516    IDL_msp_t IDL_msp
1517)
1518{
1519    idl_short_int interp_major_version, interp_minor_version;
1520
1521    interp_major_version = IDL_VERSION_NUMBER(IDL_INTERP_ENCODE_MAJOR);
1522    interp_minor_version = IDL_VERSION_NUMBER(IDL_INTERP_ENCODE_MINOR);
1523    if ((interp_major_version != 3) || (interp_minor_version > 2))
1524    {
1525#ifdef DEBUG_INTERP
1526        printf("Expecting data structure version 3.0, 3.1 or 3.2 - found %d.%d\n",
1527                interp_major_version, interp_minor_version);
1528        exit(0);
1529#endif
1530        DCETHREAD_RAISE( rpc_x_unknown_stub_rtl_if_vers );
1531    }
1532}
1533
1534static rpc_void_p_t
1535rpc_ss_default_alloc(idl_size_t size)
1536{
1537    return (rpc_void_p_t) malloc((size_t) size);
1538}
1539
1540static void
1541rpc_ss_default_free(rpc_void_p_t obj)
1542{
1543    free ((void*) obj);
1544}
1545
1546static void
1547rpc_ss_init_mem_handle(rpc_ss_mem_handle* handle)
1548{
1549    handle->memory = NULL;
1550    handle->node_table = NULL;
1551
1552    handle->alloc = rpc_ss_default_alloc;
1553    handle->free = rpc_ss_default_free;
1554}
1555
1556/******************************************************************************/
1557/*                                                                            */
1558/*  Initialize the marshalling state block                                    */
1559/*                                                                            */
1560/******************************************************************************/
1561void rpc_ss_init_marsh_state
1562(
1563    idl_byte IDL_type_vec[],
1564    IDL_msp_t IDL_msp
1565)
1566{
1567    rpc_ss_init_mem_handle(&IDL_msp->IDL_mem_handle);
1568    IDL_msp->IDL_status = error_status_ok;
1569    IDL_msp->IDL_elts_in_use = 0;
1570    IDL_msp->IDL_buff_addr = NULL;
1571    IDL_msp->IDL_left_in_buff = 0;
1572    IDL_msp->IDL_mp_start_offset = 0;
1573    IDL_msp->IDL_type_vec = IDL_type_vec;
1574    IDL_msp->IDL_pickling_handle = NULL;
1575    /* Protect against old stubs that haven't allocated a stack packet */
1576    IDL_msp->IDL_stack_packet_addr = NULL;
1577    IDL_msp->IDL_stack_packet_status = IDL_stack_packet_used_k;
1578
1579    if (IDL_type_vec == NULL)
1580    {
1581        /* Pickling call, version check will be done later */
1582        return;
1583    }
1584    rpc_ss_type_vec_vers_check( IDL_msp );
1585}
1586
1587/* always include these routines to read type vecs in either endian */
1588
1589/******************************************************************************/
1590/*                                                                            */
1591/*  Build a bounds list from fixed bounds in the definition vector            */
1592/*                                                                            */
1593/******************************************************************************/
1594void rpc_ss_fixed_bounds_from_vector
1595(
1596    /* [in] */  idl_ulong_int dimensionality,
1597    /* [in] */  idl_byte *array_defn_ptr,   /* Points at array bounds */
1598    /* [out] */ IDL_bound_pair_t **p_bounds_list,
1599    IDL_msp_t IDL_msp
1600)
1601{
1602    IDL_bound_pair_t *bounds_list;
1603    unsigned32 i;
1604
1605    bounds_list = (IDL_bound_pair_t *)rpc_ss_mem_alloc
1606        (&IDL_msp->IDL_mem_handle, (dimensionality * sizeof(IDL_bound_pair_t)));
1607    for (i=0; i<dimensionality; i++)
1608    {
1609        IDL_GET_LONG_FROM_VECTOR(bounds_list[i].lower,array_defn_ptr);
1610        IDL_GET_LONG_FROM_VECTOR(bounds_list[i].upper,array_defn_ptr);
1611    }
1612    *p_bounds_list = bounds_list;
1613}
1614
1615/******************************************************************************/
1616/*                                                                            */
1617/*  Return the switch value for the specified union arm                       */
1618/*                                                                            */
1619/******************************************************************************/
1620idl_ulong_int rpc_ss_arm_switch_value
1621(
1622    /* [in] */  idl_byte *defn_vec_ptr,     /* Points at first union arm defn */
1623    /* [in] */ idl_long_int index,          /* Index of union arm desc */
1624    /* [in] */ IDL_msp_t IDL_msp            /* Needed for GET_LONG macro */
1625)
1626{
1627    idl_byte *switch_value_ptr;     /* Points to switch value in defn vec */
1628    idl_ulong_int switch_value;
1629
1630    switch_value_ptr = defn_vec_ptr + index * IDL_UNION_ARM_DESC_WIDTH;
1631    IDL_GET_LONG_FROM_VECTOR(switch_value, switch_value_ptr);
1632    return(switch_value);
1633}
1634
1635/******************************************************************************/
1636/*                                                                            */
1637/*  Write an unsigned value of specified integer type to an untyped location  */
1638/*                                                                            */
1639/******************************************************************************/
1640void rpc_ss_put_typed_integer
1641(
1642    /* in */ idl_ulong_int value,
1643    /* in */ idl_byte type,
1644    /* in */ rpc_void_p_t address
1645)
1646{
1647    switch (type)
1648    {
1649        case IDL_DT_SMALL:
1650            *(idl_small_int *)address = (idl_small_int)value;
1651            break;
1652        case IDL_DT_USMALL:
1653            *(idl_usmall_int *)address = (idl_usmall_int)value;
1654            break;
1655        case IDL_DT_SHORT:
1656            *(idl_short_int *)address = (idl_short_int)value;
1657            break;
1658        case IDL_DT_USHORT:
1659            *(idl_ushort_int *)address = (idl_ushort_int)value;
1660            break;
1661        case IDL_DT_LONG:
1662            *(idl_long_int *)address = (idl_long_int)value;
1663            break;
1664        case IDL_DT_ULONG:
1665            *(idl_ulong_int *)address = (idl_ulong_int)value;
1666            break;
1667        default:
1668            DCETHREAD_RAISE(rpc_x_coding_error);
1669    }
1670}
1671