⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ndrtypes.cpp

📁 VXWORKS源代码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
/* NdrTypes.cpp - VxDCOM NDR marshaling types *//* Copyright (c) 1999 Wind River Systems, Inc. *//*modification history--------------------02p,10jan02,nel  Conditional define out old sytle double handling for ARM for                 Veloce.02o,09jan02,nel  Fix duplicate double definition in ARM specific code.02n,17dec01,nel  Add include symbol for diab.02m,12oct01,nel  Add extra padding to other VARIANT types.02l,01oct01,nel  SPR#69557. Add extra padding bytes to make VT_BOOL type work.02k,02aug01,dbs  add [v1_enum] support02j,24jul01,dbs  take fix for SPR#65311, unnecessary align() in struct                 marshal202i,19jul01,dbs  fix include path of vxdcomGlobals.h02h,13jul01,dbs  fix up includes02g,30mar01,nel  SPR#35873. Modify extra pading bytes on the end of a                 SAFEARRAY.02f,08feb01,nel  SPR#63885. SAFEARRAYs added.   02e,19sep00,nel  Make widlMarshal match dcomProxy def.02d,24aug00,dbs  fix many OPC-related SPRs, copied over from T2 VxDCOM02c,26jul00,dbs  add enum_t descriptor02b,18jul00,dbs  add CV-array NDR type02a,28feb00,dbs  fix (properly) pointer-unmarshaling bug01z,28feb00,dbs  fix nasty bug when unmarshaling arrays of pointers01y,18feb00,dbs  change signature of widlMarshal() to take const void*01x,07feb00,dbs  simplify NdrType classes, enhance marshaling of arrays to                 support all kinds01w,14oct99,dbs  apply fix for ARM double format01v,23sep99,dbs  add final parts of VARIANT marshaling01u,16sep99,dbs  marshaling enhancements, part 201t,14sep99,dbs  add VARIANT, pointer and string types - first stage01s,25aug99,dbs  correct marshaling of interface ptrs01r,19aug99,aim  changed assert to VXDCOM_ASSERT01q,16aug99,dbs  add variant and string support01p,13aug99,aim  include vxdcomGlobals01o,12aug99,dbs  improve struct support01n,05aug99,dbs  fix warnings01m,30jul99,dbs  tighten up type-safety of NDR types01l,29jul99,dbs  make cstruct pointer bindings same for mshl and unmshl01k,17jun99,aim  changed assert to assert01j,17jun99,dbs  change to COM_MEM_ALLOC01i,25may99,dbs  dynamically allocate IStream for marshaling                 interfaces, remove NDRTYPES::alloc/free01h,24may99,dbs  add BSTR marshaling policy variable01g,24may99,dbs  fix interface-ptr marshaling01f,20may99,dbs  fix BSTR marshaling functions for improved BSTR format01e,20may99,dbs  improve documentation01d,18may99,dbs  optimise unmarshaling by copying only pointers when possible01c,17may99,dbs  remove dummy-msg object, add documentation01b,14may99,dbs  fix alignment of array counts01a,12may99,dbs  created*//*  DESCRIPTION: NdrTypes.cpp  NDR Type Descriptors  --------------------    This module implements the 'type descriptor' system for NDR  marshaling, in conjunction with the NdrMarshalStream and  NdrUnmarshalStream classes.  The NDR stream classes are unidirectional streams that can either be  marshaled into, or can be unmarshaled from. The type-descriptor  system described here implements some classes which know about  marshaling one specific IDL or C++ type into one of those  streams. In fact, each type-descriptor know about marshaling either  one complex type (like GUID) or one or more simple types, all of  which are the same size, for example, 'short' and 'unsigned short'  are handled by the same type descriptor class.  All type descriptors are subclasses of the abstract base class  'NdrType' and the WIDL (un)marshaling functions widlMarshal() and  widlUnmarshal() require a pointer to the appropriate kind of stream,  and a pointer to an NdrType which describes the item to be  (un)marshaled. All user-level marshaling (i.e. that which appears in  the generated proxy/stub code) uses these 2 functions.  Each proxy or stub function must include a local variable of type  NDRTYPES. This object functions as a 'factory' for the type  descriptors, and implements a fast allocation strategy using  placement new. Whenever a variable needs to be marshaled, then one  of the methods of the NDRTYPES factory class is called, to generate  a type descriptor. The descriptors are 'nestable' in that recursive  data types can be described, such as structures or arrays. The set  of type descriptor classes covers arrays (both fixed-size and  conformant) and structures (again, fixed or conformant) even though  WIDL doesn't currently cope with these complex types.  Each type descriptor can be 'bound' to a particular instance  variable, by passing the variable's address into the factory  method. Only the top-level descriptor needs to be bound to the  variable, and it will propogate down to nested descriptors. The  value that needs to be bound to the descriptor is usually the  address of the variable to be (un)marshaled. Arrays and structures  require the descriptor to be bound to the start-address, e.g. for an  array of T, the descriptor would be:-  T* aT;  array_t (aT, ...);  and for a structure (conformant or normal) of type T, it would be  like this:-  struct T t;  struct_t (&t, ...);    Generally, the factory methods (of the NDRTYPES class) require the  address of a variable to bind to. This precludes marshaling  immediate values, but this is not generally a problem. However,  there are exceptions, which must be coded carefully (and will be  handled by WIDL in future).  IDL Syntax and its meaning  --------------------------  DCE IDL allows many ways of achieving the same thing, and is  particularly confusing when it comes to args which are pointers or  arrays. There are three kinds of pointer-attributes, namely [ref],  [unique] and [ptr] (which is know as 'full' also). The [ref] pointer  type is effectively a pass-by-reference pointer, which can never be  NULL (like a C++ reference type) and so does not require any  marshaling. However, both [unique] and [ptr] pointers can be NULL  and so must be marshaled (the marshaled value is known as a  'referent' and is usually the value of the pointer itself, but  effectively only conveys the NULL-ness or otherwise of the  pointer). Top-level pointers (i.e. those in method arguments, at the  outermost level) default to [ref] unless a specific attribute is  given in the IDL. Lower level pointers (i.e. those inside structures  or arrays, or even the 2nd level of indirection in method args)  default to [unique] and so require marshaling. The pointer_t  descriptor represents these kinds of pointers, and so it appears  frequently.  Pointers, as well as having one the above three attributes, can also  be 'sized' -- i.e. can represent arrays as they can in C. For  example, if the IDL says:-  typedef struct    {    long a;    char b;    } FOO;      HRESULT FooBar ([in] long nFoos, [in, size_is(nFoos)] FOO* foos);  then the variable 'foos' is a 'conformant array' whose length is  given (at runtime) in the arg 'nFoos'. DCE IDL also allows for  returning conformant arrays, but the syntax for arrays of simple  types, and arrays of complex types, is different.  To return an array of simple types, the IDL would be something like  this:-  HRESULT Quz ([in] long nBytes, [out, size_is(nBytes)] char* bytes);    To return an array of fixed-size structures, like FOO defined above,  then the syntax is different, like so:-    HRESULT Func ([in] long num, [out, size_is(,num)] FOO** ppFoos);  In this case, the first pointer (rightmost *) defaults to [ref], and  the 2nd or inner pointer defaults to [unique], so this declaration  should be read as:-  (ref-ptr to (unique-array of dimension 'num' of (FOO)))    In this case, the proxy allocates memory to hold the array of FOOs  and stores the address of this block in the pointer pointed-to by  the argument 'ppFoos'. The strange syntax size_is(,num) indicates  that the size_is value binds to the second star, and so this means a  'pointer to an array of FOOs'. Calling the function in C would look  like this:-  FOO* foos;  Func (3, &foos);  COM_MEM_FREE (foos);  where Func() is actually calling the proxy, which makes the ORPC and  returns the array of 3 FOO structures directly into the caller's  address space.  The final cases cover returning conformant structures, that is a  structure whose final member is a conformant array. To return a  single conformant structure, the IDL will be something like:-  typedef struct    {    long                    nBytes;    [size_is(nBytes)] char  data[];    } BAR;  HRESULT BarBaz ([out] BAR** ppBar);  where ppBar is a ref-ptr to a unique-ptr to BAR. There is a subtle  difference between this case and the case where the out-arg is an  array of conformant-structures, like the BAR structure defined  above. If the signature were:-  HRESULT Func ([in] long num, [out, size_is(num)] BAR** ppBars);  then this would mean 'ref-array of unique-pointer to BAR'  and the size_is attribute applies to the top-level * declarator,  i.e. ppBar is itself an array.    NDR Phases  ----------  There are 4 phases of marshaling in ORPC : firstly, marshaling all  the [in] args at the proxy; secondly, unmarshaling all the [in] args  at the stub; thirdly, marshaling all the [out] args and the return  value at the stub; and finally unmarshaling all the [out] args and  the return value at the proxy.  In each of these phases there are different requirements on the type  descriptors in order to optimise the unmarshaling process,  minimising dynamic memory allocations. Also, at the stub side, the  stub function must provide the actual arguments to the real  stub-function when it is invoked - this requires making a temporary  local for each argument (whether [in] or [out]) and unmarshaling  into (and then marshaling from) those variables.  It can be seen from the descriptions of the IDL syntax above that  the possibilities are numerous, and the right type of allocation  strategy must be performed for each variant of the syntax. This is  why the job should ideally be performed by an IDL compiler, and  in future WIDL will do just that.  This description will document the behaviour of the type-descriptor  classes in each of the above cases, and recommend how they should be  handled by the generated proxy/stub code.    The 'conformant array' Type Descriptor  --------------------------------------  The factory method NDRTYPES::carray_t() returns a type descriptor  designed to cope with conformant arrays. Marshaling conformant  arrays is always the same, in both the PROXY_MSHL and STUB_MSHL  phases. However, unmarshaling is a different matter.    At the STUB_UNMSHL phase, unmarshaling can be optimised by letting  the temporary variable in the stub-function point into the  unmarshaling stream's buffer. To achieve this, the type-descriptor  must be bound to the address of the pointer-variable, so it  manipulate the contents.  Unmarshaling at the PROXY_UNMSHL stage is the most complex. If the  array-element type is a simple type, then the descriptor should be  bound to the start-address of the array, and should just unmarshal  directly into the caller-provided space. If the array-element is a  fixed-size structure and the size_is(,num) IDL syntax is being used,  then the type-descriptor must allocate dynamic memory to hold the  unmarshaled data, which the caller must eventually free (by calling  the CoTaskMemFree() function). This functionality is encoded in  NdrConfArray::unmarshal(), which makes the distinction between  simple types and others.  However, if the [out] array is an array of pointers to conformant  structures (see the Func(long,BAR**) example above) then the  complexity increases. The array is marshaled differently (the array  of pointer-referents is marshaled first, then each of the conformant  structures follows, in order, and NULL referents may be present) and  hence unmarshaling is different.  Currently, the type descriptors do not support this case -- it must  be hand-coded (by human hands, or by WIDL concocting the right  sequence of elements) -- and so only cope with the 2 cases outlined  earlier.  Variable-Binding Rules  ----------------------  Most of the NDR type-descriptors bind to the address of a variable,  whether marshaling or unmarshaling. The only exception is the  'array' type (class NdrArray) which binds to the start of the array,  i.e. the address of the first element. Note that conformant arrays  don't -- they follow the usual rules and bind to the address of a  variable holding the pointer to the first element of the array.  Pointer Types  -------------    MIDL/WIDL supports 3 kinds of pointer-attributes, namely [ref],  [unique] and [ptr] (known as 'full') pointers. The difference  between unique and full pointers is that unique pointers must  literally be unique, i.e. there must be no aliasing between any 2  pointers within the context of a marshaling operation.  The [ref] pointer type indicates 'pass by reference' semantics, thus  a ref-pointer can never be NULL, and so [ref] pointers are not  marshaled. However, [unique] pointers can be NULL, and so do have to  be marshaled. Thus the type-descriptors for the pointer type (and  associated array and string types) are only used when the IDL  indicates a [unique] (or full) pointer. The pointer_t() descriptor  is generated by WIDL when a simple [unique] pointer is required,  i.e. an unsized, non-string pointer. If a dimension is supplied, or  the [string] attribute is used, then WIDL will generate a call to  either the carray_t() or wstring_t() descriptor, respectively.  In all cases where a [unique] pointer is utilised, the binding for  the descriptor is the address of the pointer variable. Only if a  [ref] string or fixed-size array is used as a method-arg is there a  potential problem.  Also, WIDL only supports conformant arrays, and not varying, or  conformant varying arrays. In IDL terms, this means the size_is  attribute is recognised, but max_is, length_is, etc, are not.  */#include <stdlib.h>#include "private/comMisc.h"#include "NdrTypes.h"#include "MemoryStream.h"#include "orpcLib.h"#include "private/vxdcomGlobals.h"#include "TraceCall.h"/* Include symbol for diab */extern "C" int include_vxdcom_NdrTypes (void)    {    return 0;    }////////////////////////////////////////////////////////////////////////////// ARM-specific code for (un)marshaling doubles...//#if defined (CPU_FAMILY) && (CPU_FAMILY == ARM) && \    defined (VXDCOM_PLATFORM_VXWORKS) && (VXDCOM_PLATFORM_VXWORKS != 5)#ifdef __GNUC__template class NdrSimple<double>;#endifunion armDouble    {    double        doubleValue;    struct        {        long        msw;        long        lsw;        }        txValue;    };static HRESULT marshalDouble (NdrMarshalStream * pStrm, double * value)    {    pStrm->align (sizeof (double));    armDouble d;    d.doubleValue = *value;    pStrm->insert (sizeof (long), &d.txValue.lsw, true);    return pStrm->insert (sizeof (long), &d.txValue.msw, true);    }HRESULT NdrSimple<double>::marshal1 (NdrMarshalStream* pStrm)    {    return marshalDouble(pStrm, m_pValue);    }static HRESULT unmarshalDouble (NdrUnmarshalStream * pStrm, double * value)    {    pStrm->align (sizeof (double));    armDouble d;    pStrm->extract (sizeof (long), &d.txValue.lsw, true);    HRESULT hr = pStrm->extract (sizeof (long), &d.txValue.msw, true);    if (SUCCEEDED (hr))        *value = d.doubleValue;    return hr;    }    HRESULT NdrSimple<double>::unmarshal1 (NdrUnmarshalStream* pStrm)    {    return unmarshalDouble(pStrm, m_pValue);    }#elsestatic HRESULT marshalDouble (NdrMarshalStream * pStrm, double * value)    {    pStrm->align (sizeof (double));    return pStrm->insert (sizeof (double), value, true);    }static HRESULT unmarshalDouble (NdrUnmarshalStream * pStrm, double * value)    {    pStrm->align (sizeof (double));    return pStrm->extract (sizeof (double), value, true);    }#endif////////////////////////////////////////////////////////////////////////////// (un)marshaling methods for enum types.//size_t NdrEnum::alignment () const    {    return (m_bV1Enum ? sizeof (DWORD) : sizeof (short));    }HRESULT NdrEnum::marshal1 (NdrMarshalStream* pStrm)    {    HRESULT hr = S_OK;        if (m_bV1Enum)        {        // New-style 32-bit enum...        DWORD val = *m_pValue;        pStrm->align (alignment ());        hr = pStrm->insert (sizeof (val), &val, true);        }    else        {        // Old-style 16-bit enum...        short val = *m_pValue;        pStrm->align (alignment ());        hr = pStrm->insert (sizeof (val), &val, true);        }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -