Example #1
0
        private void GenerateClient(string name, CodeNamespace ns, int complex_type_count)
        {
            CodeTypeDeclaration type = ns.AddType(name);

            type.IsClass        = true;
            type.TypeAttributes = TypeAttributes.Public | TypeAttributes.Sealed;
            type.BaseTypes.Add(typeof(RpcAlpcClientBase));

            CodeConstructor constructor = type.AddConstructor(MemberAttributes.Public | MemberAttributes.Final);

            constructor.BaseConstructorArgs.Add(CodeGenUtils.GetPrimitive(_server.InterfaceId.ToString()));
            constructor.BaseConstructorArgs.Add(CodeGenUtils.GetPrimitive(_server.InterfaceVersion.Major));
            constructor.BaseConstructorArgs.Add(CodeGenUtils.GetPrimitive(_server.InterfaceVersion.Minor));

            foreach (var proc in _server.Procedures)
            {
                string proc_name = proc.Name;
                if (!_proc_names.Add(proc_name))
                {
                    proc_name = $"{proc_name}_{proc.ProcNum}";
                    if (!_proc_names.Add(proc_name))
                    {
                        throw new ArgumentException($"Duplicate name {proc.Name}");
                    }
                }

                var method = type.AddMethod(proc_name, MemberAttributes.Public | MemberAttributes.Final);
                RpcTypeDescriptor return_type = GetTypeDescriptor(proc.ReturnValue.Type);
                if (return_type == null)
                {
                    method.ThrowNotImplemented("Return type unsupported.");
                    continue;
                }

                var offset_to_name =
                    proc.Params.Select(p => Tuple.Create(p.Offset, p.Name)).ToList();

                method.ReturnType = return_type.CodeType;
                method.CreateMarshalObject(MARSHAL_NAME);
                foreach (var p in proc.Params)
                {
                    if (p == proc.Handle)
                    {
                        continue;
                    }
                    RpcTypeDescriptor p_type = GetTypeDescriptor(p.Type);

                    List <RpcMarshalArgument> extra_marshal_args = new List <RpcMarshalArgument>();
                    if (p_type.VarianceDescriptor.IsValid)
                    {
                        extra_marshal_args.Add(p_type.VarianceDescriptor.CalculateCorrelationArgument(p.Offset, offset_to_name));
                    }

                    var p_obj = method.AddParam(p_type.GetParameterType(), p.Name);
                    p_obj.Direction = p.GetDirection();
                    if (!p.IsIn)
                    {
                        continue;
                    }
                    if (p_type.Pointer)
                    {
                        if (p_type.PointerType == RpcPointerType.Reference)
                        {
                            method.AddNullCheck(MARSHAL_NAME, p.Name);
                        }
                        else
                        {
                            method.AddWriteReferent(MARSHAL_NAME, p.Name);
                        }
                    }
                    else if (!p_type.ValueType)
                    {
                        method.AddNullCheck(MARSHAL_NAME, p.Name);
                    }
                    method.AddMarshalCall(p_type, MARSHAL_NAME, p.Name, extra_marshal_args.ToArray());
                    // If it's a constructed type then ensure any deferred writes are flushed.
                    if (p_type.Constructed)
                    {
                        method.AddFlushDeferredWrites(MARSHAL_NAME);
                    }
                }

                method.SendReceive(MARSHAL_NAME, UNMARSHAL_NAME, proc.ProcNum);

                foreach (var p in proc.Params.Where(x => x.IsOut))
                {
                    if (p == proc.Handle)
                    {
                        continue;
                    }

                    RpcTypeDescriptor p_type = GetTypeDescriptor(p.Type);
                    if (p_type.Pointer)
                    {
                        method.AddPointerUnmarshalCall(p_type, UNMARSHAL_NAME, p.Name);
                    }
                    else
                    {
                        method.AddUnmarshalCall(p_type, UNMARSHAL_NAME, p.Name);
                    }
                    if (p_type.Constructed)
                    {
                        method.AddPopluateDeferredPointers(UNMARSHAL_NAME);
                    }
                }

                method.AddUnmarshalReturn(return_type, UNMARSHAL_NAME);
            }

            if (complex_type_count > 0 && HasFlag(RpcClientBuilderFlags.GenerateConstructorProperties))
            {
                var constructor_type = new CodeTypeReference(CodeGenUtils.MakeIdentifier(CONSTRUCTOR_STRUCT_NAME));
                var prop             = type.AddProperty("New", constructor_type, MemberAttributes.Public | MemberAttributes.Final,
                                                        new CodeMethodReturnStatement(new CodeObjectCreateExpression(constructor_type)));
                constructor_type = new CodeTypeReference(CodeGenUtils.MakeIdentifier(ARRAY_CONSTRUCTOR_STRUCT_NAME));
                type.AddProperty("NewArray", constructor_type, MemberAttributes.Public | MemberAttributes.Final,
                                 new CodeMethodReturnStatement(new CodeObjectCreateExpression(constructor_type)));
            }
        }
Example #2
0
        private RpcTypeDescriptor GetTypeDescriptorInternal(NdrBaseTypeReference type)
        {
            if (type is NdrSimpleTypeReference)
            {
                switch (type.Format)
                {
                case NdrFormatCharacter.FC_BYTE:
                case NdrFormatCharacter.FC_USMALL:
                    return(new RpcTypeDescriptor(typeof(byte), "ReadByte", false, "WriteByte", type, null, null));

                case NdrFormatCharacter.FC_SMALL:
                case NdrFormatCharacter.FC_CHAR:
                    return(new RpcTypeDescriptor(typeof(sbyte), "ReadSByte", false, "WriteSByte", type, null, null));

                case NdrFormatCharacter.FC_WCHAR:
                    return(new RpcTypeDescriptor(typeof(char), "ReadChar", false, "WriteChar", type, null, null));

                case NdrFormatCharacter.FC_SHORT:
                    return(new RpcTypeDescriptor(typeof(short), "ReadInt16", false, "WriteInt16", type, null, null));

                case NdrFormatCharacter.FC_USHORT:
                    return(new RpcTypeDescriptor(typeof(ushort), "ReadUInt16", false, "WriteUInt16", type, null, null));

                case NdrFormatCharacter.FC_LONG:
                case NdrFormatCharacter.FC_ENUM16:
                case NdrFormatCharacter.FC_ENUM32:
                    return(new RpcTypeDescriptor(typeof(int), "ReadInt32", false, "WriteInt32", type, null, null));

                case NdrFormatCharacter.FC_ULONG:
                case NdrFormatCharacter.FC_ERROR_STATUS_T:
                    return(new RpcTypeDescriptor(typeof(uint), "ReadUInt32", false, "WriteUInt32", type, null, null));

                case NdrFormatCharacter.FC_FLOAT:
                    return(new RpcTypeDescriptor(typeof(float), "ReadFloat", false, "WriteFloat", type, null, null));

                case NdrFormatCharacter.FC_HYPER:
                    return(new RpcTypeDescriptor(typeof(long), "ReadInt64", false, "WriteInt64", type, null, null));

                case NdrFormatCharacter.FC_DOUBLE:
                    return(new RpcTypeDescriptor(typeof(double), "ReadDouble", false, "WriteDouble", type, null, null));

                case NdrFormatCharacter.FC_INT3264:
                    return(new RpcTypeDescriptor(typeof(NdrInt3264), "ReadInt3264", false, "WriteInt3264", type, null, null));

                case NdrFormatCharacter.FC_UINT3264:
                    return(new RpcTypeDescriptor(typeof(NdrUInt3264), "ReadUInt3264", false, "WriteUInt3264", type, null, null));

                case NdrFormatCharacter.FC_C_WSTRING:
                    return(new RpcTypeDescriptor(typeof(string), "ReadConformantString", false, "WriteConformantString", type, null, null));

                case NdrFormatCharacter.FC_C_CSTRING:
                    return(new RpcTypeDescriptor(typeof(string), "ReadAnsiConformantString", false, "WriteAnsiConformantString", type, null, null));

                case NdrFormatCharacter.FC_CSTRING:
                case NdrFormatCharacter.FC_WSTRING:
                    break;
                }
            }
            else if (type is NdrKnownTypeReference known_type)
            {
                switch (known_type.KnownType)
                {
                case NdrKnownTypes.GUID:
                    return(new RpcTypeDescriptor(typeof(Guid), "ReadGuid", false, "WriteGuid", type, null, null));

                case NdrKnownTypes.BSTR:
                case NdrKnownTypes.HSTRING:
                    // Implement these custom marshallers.
                    break;
                }
            }
            else if (type is NdrBaseStringTypeReference)
            {
                if (type is NdrConformantStringTypeReference conformant_str)
                {
                    if (conformant_str.Format == NdrFormatCharacter.FC_C_CSTRING)
                    {
                        return(new RpcTypeDescriptor(typeof(string), "ReadAnsiConformantString", false, "WriteAnsiConformantString", type, null, null));
                    }
                    return(new RpcTypeDescriptor(typeof(string), "ReadConformantString", false, "WriteConformantString", type, null, null));
                }
            }
            else if (type is NdrSystemHandleTypeReference system_handle)
            {
                return(new RpcTypeDescriptor(system_handle.GetSystemHandleType(),
                                             "ReadSystemHandle", true, "WriteSystemHandle", type, null, null));
            }
            else if (type is NdrSimpleArrayTypeReference simple_array)
            {
                RpcTypeDescriptor  element_type = GetTypeDescriptor(simple_array.ElementType);
                RpcMarshalArgument arg          = new RpcMarshalArgument
                {
                    CodeType   = new CodeTypeReference(typeof(int)),
                    Expression = CodeGenUtils.GetPrimitive(simple_array.ElementCount)
                };
                if (element_type.BuiltinType == typeof(char))
                {
                    return(new RpcTypeDescriptor(typeof(string), "ReadFixedString", false, "WriteFixedString", type, null, null, arg)
                    {
                        FixedCount = simple_array.ElementCount
                    });
                }
                else if (element_type.BuiltinType == typeof(byte))
                {
                    return(new RpcTypeDescriptor(typeof(byte[]), "ReadBytes", false, "WriteFixedBytes", type, null, null, arg)
                    {
                        FixedCount = simple_array.ElementCount
                    });
                }
            }
            else if (type is NdrPointerTypeReference pointer)
            {
                var            desc         = GetTypeDescriptor(pointer.Type);
                RpcPointerType pointer_type = RpcPointerType.None;
                switch (pointer.Format)
                {
                case NdrFormatCharacter.FC_UP:
                    pointer_type = RpcPointerType.Unique;
                    break;

                case NdrFormatCharacter.FC_RP:
                    pointer_type = RpcPointerType.Reference;
                    break;

                default:
                    pointer_type = RpcPointerType.Full;
                    break;
                }
                return(new RpcTypeDescriptor(desc, pointer_type));
            }
            else if (type is NdrSupplementTypeReference supp)
            {
                return(GetTypeDescriptor(supp.SupplementType));
            }
            else if (type is NdrHandleTypeReference handle)
            {
                if (handle.Format == NdrFormatCharacter.FC_BIND_CONTEXT)
                {
                    return(new RpcTypeDescriptor(typeof(NdrContextHandle), "ReadContextHandle", false, "WriteContextHandle", type, null, null));
                }
            }
            else if (type is NdrRangeTypeReference range)
            {
                return(GetTypeDescriptor(range.RangeType));
            }
            else if (type is NdrBogusArrayTypeReference bogus_array)
            {
                RpcTypeDescriptor element_type = GetTypeDescriptor(bogus_array.ElementType);
                if (bogus_array.VarianceDescriptor.IsValid && bogus_array.VarianceDescriptor.ValidateCorrelation() &&
                    !bogus_array.ConformanceDescriptor.IsValid && element_type.Constructed)
                {
                    // For now we only support constructed types with variance and no conformance.
                    // The variance also needs to be a constant or a normal correlation.
                    return(new RpcTypeDescriptor(new CodeTypeReference(element_type.CodeType, 1), false,
                                                 "ReadVaryingBogusArrayStruct", true, "WriteVaryingBogusArrayStruct",
                                                 type, null, bogus_array.VarianceDescriptor)
                    {
                        FixedCount = bogus_array.ElementCount
                    });
                }
            }

            var type_name_arg = new RpcMarshalArgument()
            {
                CodeType   = new CodeTypeReference(typeof(string)),
                Expression = new CodePrimitiveExpression(type.Format.ToString())
            };

            return(new RpcTypeDescriptor(typeof(NdrUnsupported), "ReadUnsupported", false, "WriteUnsupported", type, null, null, type_name_arg));
        }
Example #3
0
        private int GenerateComplexTypes(CodeNamespace ns)
        {
            int type_count = 0;

            // First populate the type cache.
            foreach (var complex_type in _server.ComplexTypes)
            {
                if (complex_type is NdrBaseStructureTypeReference struct_type)
                {
                    _type_descriptors[complex_type] = new RpcTypeDescriptor(complex_type.Name, true,
                                                                            "ReadStruct", true, "WriteStruct", complex_type, null, null);
                    type_count++;
                }
            }

            if (type_count == 0)
            {
                return(0);
            }

            bool create_constructor_properties         = HasFlag(RpcClientBuilderFlags.GenerateConstructorProperties);
            CodeTypeDeclaration constructor_type       = null;
            CodeTypeDeclaration array_constructor_type = null;

            if (create_constructor_properties)
            {
                constructor_type                = ns.AddType(CONSTRUCTOR_STRUCT_NAME);
                constructor_type.IsStruct       = true;
                array_constructor_type          = ns.AddType(ARRAY_CONSTRUCTOR_STRUCT_NAME);
                array_constructor_type.IsStruct = true;
            }

            // Now generate the complex types.
            foreach (var complex_type in _server.ComplexTypes)
            {
                if (!(complex_type is NdrBaseStructureTypeReference struct_type))
                {
                    ns.Comments.Add(new CodeCommentStatement($"Unsupported type {complex_type.GetType()} {complex_type.Name}"));
                    continue;
                }

                var s_type = ns.AddType(complex_type.Name);
                s_type.IsStruct = true;
                s_type.BaseTypes.Add(new CodeTypeReference(typeof(INdrStructure)));

                var marshal_method = s_type.AddMarshalMethod(MARSHAL_NAME);
                marshal_method.AddAlign(MARSHAL_NAME, struct_type.Alignment + 1);
                var unmarshal_method = s_type.AddUnmarshalMethod(UNMARSHAL_NAME);
                unmarshal_method.AddAlign(UNMARSHAL_NAME, struct_type.Alignment + 1);

                var offset_to_name =
                    struct_type.Members.Select(m => Tuple.Create(m.Offset, m.Name)).ToList();
                var default_initialize_expr = new Dictionary <string, CodeExpression>();
                var member_parameters       = new List <Tuple <CodeTypeReference, string> >();

                foreach (var member in struct_type.Members)
                {
                    var f_type = GetTypeDescriptor(member.MemberType);
                    s_type.AddField(f_type.GetStructureType(), member.Name, MemberAttributes.Public);
                    member_parameters.Add(Tuple.Create(f_type.GetParameterType(), member.Name));

                    List <RpcMarshalArgument> extra_marshal_args = new List <RpcMarshalArgument>();
                    if (f_type.VarianceDescriptor.IsValid)
                    {
                        extra_marshal_args.Add(f_type.VarianceDescriptor.CalculateCorrelationArgument(member.Offset, offset_to_name));
                    }

                    if (f_type.Pointer)
                    {
                        marshal_method.AddDeferredMarshalCall(f_type, MARSHAL_NAME, member.Name, extra_marshal_args.ToArray());
                        unmarshal_method.AddDeferredEmbeddedUnmarshalCall(f_type, UNMARSHAL_NAME, member.Name);
                    }
                    else
                    {
                        if (!f_type.ValueType)
                        {
                            marshal_method.AddNullCheck(MARSHAL_NAME, member.Name);
                        }

                        marshal_method.AddMarshalCall(f_type, MARSHAL_NAME, member.Name, extra_marshal_args.ToArray());
                        unmarshal_method.AddUnmarshalCall(f_type, UNMARSHAL_NAME, member.Name);
                    }

                    if (!f_type.Pointer || f_type.PointerType == RpcPointerType.Reference)
                    {
                        if (f_type.CodeType.ArrayRank > 0)
                        {
                            default_initialize_expr.Add(member.Name, new CodeArrayCreateExpression(f_type.CodeType, CodeGenUtils.GetPrimitive(f_type.FixedCount)));
                        }
                        else if (f_type.BuiltinType == typeof(string) && f_type.FixedCount > 0)
                        {
                            default_initialize_expr.Add(member.Name, new CodeObjectCreateExpression(f_type.CodeType, CodeGenUtils.GetPrimitive('\0'),
                                                                                                    CodeGenUtils.GetPrimitive(f_type.FixedCount)));
                        }
                    }
                }

                var p_type = _type_descriptors[complex_type];

                if (!create_constructor_properties)
                {
                    s_type.AddDefaultConstructorMethod("CreateDefault", MemberAttributes.Public | MemberAttributes.Static, p_type, default_initialize_expr);
                    s_type.AddConstructorMethod(p_type, member_parameters);
                }
                else
                {
                    constructor_type.AddDefaultConstructorMethod(complex_type.Name, MemberAttributes.Public | MemberAttributes.Final, p_type, default_initialize_expr);
                    constructor_type.AddConstructorMethod(complex_type.Name, p_type, member_parameters);
                    array_constructor_type.AddArrayConstructorMethod(complex_type.Name, p_type);
                }
            }

            return(type_count);
        }