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))); } }
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)); }
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); }