widl: Implement support for ref pointers to strings.
This commit is contained in:
parent
ea42bb7703
commit
12d4d9c229
|
@ -87,30 +87,44 @@ static void print_message_buffer_size(const func_t *func)
|
|||
fprintf(client, " %u", total_size);
|
||||
}
|
||||
|
||||
|
||||
static int has_out_arg_or_return(const func_t *func)
|
||||
static void check_pointers(const func_t *func)
|
||||
{
|
||||
var_t *var;
|
||||
|
||||
if (!is_void(func->def->type, NULL))
|
||||
return 1;
|
||||
int pointer_type;
|
||||
|
||||
if (!func->args)
|
||||
return 0;
|
||||
return;
|
||||
|
||||
var = func->args;
|
||||
while (NEXT_LINK(var)) var = NEXT_LINK(var);
|
||||
while (var)
|
||||
{
|
||||
if (is_attr(var->attrs, ATTR_OUT))
|
||||
return 1;
|
||||
pointer_type = get_attrv(var->attrs, ATTR_POINTERTYPE);
|
||||
if (!pointer_type)
|
||||
pointer_type = RPC_FC_RP;
|
||||
|
||||
if (pointer_type == RPC_FC_RP)
|
||||
{
|
||||
if (var->ptr_level == 1)
|
||||
{
|
||||
print_client("if (!%s)\n", var->name);
|
||||
print_client("{\n");
|
||||
indent++;
|
||||
print_client("RpcRaiseException(RPC_X_NULL_REF_POINTER);\n");
|
||||
indent--;
|
||||
print_client("}\n\n");
|
||||
}
|
||||
else if (var->ptr_level > 1)
|
||||
{
|
||||
error("Pointer level %d not supported!\n", var->ptr_level);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
var = PREV_LINK(var);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void write_function_stubs(type_t *iface)
|
||||
{
|
||||
const func_t *func = iface->funcs;
|
||||
|
@ -177,6 +191,10 @@ static void write_function_stubs(type_t *iface)
|
|||
print_client("RPC_MESSAGE _RpcMessage;\n");
|
||||
print_client("MIDL_STUB_MESSAGE _StubMsg;\n");
|
||||
fprintf(client, "\n");
|
||||
|
||||
/* check pointers */
|
||||
check_pointers(func);
|
||||
|
||||
print_client("RpcTryFinally\n");
|
||||
print_client("{\n");
|
||||
indent++;
|
||||
|
@ -206,6 +224,9 @@ static void write_function_stubs(type_t *iface)
|
|||
print_message_buffer_size(func);
|
||||
fprintf(client, ";\n");
|
||||
|
||||
type_offset_func = type_offset;
|
||||
write_remoting_arguments(client, indent, func, &type_offset_func, PASS_IN, PHASE_BUFFERSIZE);
|
||||
|
||||
print_client("NdrGetBuffer(\n");
|
||||
indent++;
|
||||
print_client("(PMIDL_STUB_MESSAGE)&_StubMsg,\n");
|
||||
|
|
|
@ -518,6 +518,28 @@ const var_t* get_explicit_handle_var(const func_t* func)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
int has_out_arg_or_return(const func_t *func)
|
||||
{
|
||||
var_t *var;
|
||||
|
||||
if (!is_void(func->def->type, NULL))
|
||||
return 1;
|
||||
|
||||
if (!func->args)
|
||||
return 0;
|
||||
|
||||
var = func->args;
|
||||
while (NEXT_LINK(var)) var = NEXT_LINK(var);
|
||||
while (var)
|
||||
{
|
||||
if (is_attr(var->attrs, ATTR_OUT))
|
||||
return 1;
|
||||
|
||||
var = PREV_LINK(var);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/********** INTERFACES **********/
|
||||
|
||||
|
|
|
@ -44,6 +44,7 @@ extern void write_externdef(const var_t *v);
|
|||
extern void write_library(const char *name, const attr_t *attr);
|
||||
extern void write_user_types(void);
|
||||
extern const var_t* get_explicit_handle_var(const func_t* func);
|
||||
extern int has_out_arg_or_return(const func_t *func);
|
||||
|
||||
static inline int is_string_type(const attr_t *attrs, int ptr_level, const expr_t *array)
|
||||
{
|
||||
|
|
|
@ -106,7 +106,7 @@ static void declare_args(const func_t *func)
|
|||
if (!out_attr && !in_attr)
|
||||
in_attr = 1;
|
||||
|
||||
if (!in_attr)
|
||||
if (!in_attr && !is_attr(var->attrs, ATTR_STRING))
|
||||
{
|
||||
print_server("");
|
||||
write_type(server, var->type, NULL, var->tname);
|
||||
|
@ -130,6 +130,8 @@ static void assign_out_args(const func_t *func)
|
|||
int in_attr, out_attr;
|
||||
int i = 0, sep = 0;
|
||||
var_t *var;
|
||||
const expr_t *size_is;
|
||||
int has_size;
|
||||
|
||||
if (!func->args)
|
||||
return;
|
||||
|
@ -138,6 +140,8 @@ static void assign_out_args(const func_t *func)
|
|||
while (NEXT_LINK(var)) var = NEXT_LINK(var);
|
||||
while (var)
|
||||
{
|
||||
size_is = get_attrp(var->attrs, ATTR_SIZEIS);
|
||||
has_size = size_is && (size_is->type != EXPR_VOID);
|
||||
in_attr = is_attr(var->attrs, ATTR_IN);
|
||||
out_attr = is_attr(var->attrs, ATTR_OUT);
|
||||
if (!out_attr && !in_attr)
|
||||
|
@ -147,7 +151,22 @@ static void assign_out_args(const func_t *func)
|
|||
{
|
||||
print_server("");
|
||||
write_name(server, var);
|
||||
fprintf(server, " = &_W%u;\n", i++);
|
||||
|
||||
if (has_size)
|
||||
{
|
||||
type_t *type = var->type;
|
||||
while (type->type == 0 && type->ref)
|
||||
type = type->ref;
|
||||
|
||||
fprintf(server, " = NdrAllocate(&_StubMsg, ");
|
||||
write_expr(server, size_is, 1);
|
||||
fprintf(server, " * %u);\n", get_type_memsize(type));
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(server, " = &_W%u;\n", i++);
|
||||
}
|
||||
|
||||
sep = 1;
|
||||
}
|
||||
|
||||
|
@ -342,10 +361,14 @@ static void write_function_stubs(type_t *iface)
|
|||
buffer_size += alignment;
|
||||
}
|
||||
|
||||
if (buffer_size)
|
||||
if (has_out_arg_or_return(func))
|
||||
{
|
||||
fprintf(server, "\n");
|
||||
print_server("_StubMsg.BufferLength = %uU;\n", buffer_size);
|
||||
print_server("_StubMsg.BufferLength = %u;\n", buffer_size);
|
||||
|
||||
type_offset_func = type_offset;
|
||||
write_remoting_arguments(server, indent, func, &type_offset_func, PASS_OUT, PHASE_BUFFERSIZE);
|
||||
|
||||
print_server("_pRpcMessage->BufferLength = _StubMsg.BufferLength;\n");
|
||||
fprintf(server, "\n");
|
||||
print_server("_Status = I_RpcGetBuffer(_pRpcMessage);\n");
|
||||
|
@ -358,6 +381,8 @@ static void write_function_stubs(type_t *iface)
|
|||
fprintf(server, "\n");
|
||||
}
|
||||
|
||||
type_offset_func = type_offset;
|
||||
|
||||
/* marshall arguments */
|
||||
write_remoting_arguments(server, indent, func, &type_offset, PASS_OUT, PHASE_MARSHAL);
|
||||
|
||||
|
@ -380,6 +405,11 @@ static void write_function_stubs(type_t *iface)
|
|||
print_server("}\n");
|
||||
print_server("RpcFinally\n");
|
||||
print_server("{\n");
|
||||
indent++;
|
||||
|
||||
write_remoting_arguments(server, indent, func, &type_offset_func, PASS_OUT, PHASE_FREE);
|
||||
|
||||
indent--;
|
||||
print_server("}\n");
|
||||
print_server("RpcEndFinally\n");
|
||||
|
||||
|
|
|
@ -576,6 +576,11 @@ static size_t type_memsize(const type_t *t, int ptr_level, const expr_t *array)
|
|||
return size;
|
||||
}
|
||||
|
||||
size_t get_type_memsize(const type_t *type)
|
||||
{
|
||||
return type_memsize(type, 0, NULL);
|
||||
}
|
||||
|
||||
static int write_pointers(FILE *file, const attr_t *attrs,
|
||||
const type_t *type, int ptr_level,
|
||||
const expr_t *array, int level,
|
||||
|
@ -690,6 +695,13 @@ static size_t write_string_tfs(FILE *file, const attr_t *attrs,
|
|||
const expr_t *size_is = get_attrp(attrs, ATTR_SIZEIS);
|
||||
int has_size = size_is && (size_is->type != EXPR_VOID);
|
||||
size_t start_offset = *typestring_offset;
|
||||
unsigned char flags = 0;
|
||||
int pointer_type = get_attrv(attrs, ATTR_POINTERTYPE);
|
||||
if (!pointer_type)
|
||||
pointer_type = RPC_FC_RP;
|
||||
|
||||
if (!get_attrp(attrs, ATTR_SIZEIS))
|
||||
flags |= RPC_FC_P_SIMPLEPOINTER;
|
||||
|
||||
if ((type->type != RPC_FC_BYTE) && (type->type != RPC_FC_CHAR) && (type->type != RPC_FC_WCHAR))
|
||||
{
|
||||
|
@ -697,6 +709,18 @@ static size_t write_string_tfs(FILE *file, const attr_t *attrs,
|
|||
return start_offset;
|
||||
}
|
||||
|
||||
print_file(file, 2,"0x%x, 0x%x, /* %s%s */\n",
|
||||
pointer_type, flags,
|
||||
pointer_type == RPC_FC_FP ? "FC_FP" : (pointer_type == RPC_FC_UP ? "FC_UP" : "FC_RP"),
|
||||
(flags & RPC_FC_P_SIMPLEPOINTER) ? " [simple_pointer]" : "");
|
||||
*typestring_offset += 2;
|
||||
|
||||
if (!(flags & RPC_FC_P_SIMPLEPOINTER))
|
||||
{
|
||||
print_file(file, 2, "NdrFcShort(0x2);\n");
|
||||
*typestring_offset += 2;
|
||||
}
|
||||
|
||||
if (array && array->is_const)
|
||||
{
|
||||
if (array->cval > USHRT_MAX)
|
||||
|
@ -1335,13 +1359,30 @@ static unsigned int get_required_buffer_size_type(
|
|||
}
|
||||
if (ptr_level == 0 && type_has_ref(type))
|
||||
return get_required_buffer_size_type(type->ref, 0 /* FIXME */, array, name, alignment);
|
||||
if (ptr_level == 1)
|
||||
return 25; /* FIXME: Only 'in' pointers need this */
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int get_required_buffer_size(const var_t *var, unsigned int *alignment)
|
||||
{
|
||||
int in_attr = is_attr(var->attrs, ATTR_IN);
|
||||
int out_attr = is_attr(var->attrs, ATTR_OUT);
|
||||
|
||||
if (!in_attr && !out_attr)
|
||||
in_attr = 1;
|
||||
|
||||
if ((!out_attr || in_attr) && !is_attr(var->attrs, ATTR_STRING) && !var->array)
|
||||
{
|
||||
if (var->ptr_level > 0 || (var->ptr_level == 0 && type_has_ref(var->type)))
|
||||
{
|
||||
type_t *type = var->type;
|
||||
while (type->type == 0 && type->ref)
|
||||
type = type->ref;
|
||||
|
||||
if (is_base_type(type->type))
|
||||
return 25;
|
||||
}
|
||||
}
|
||||
|
||||
return get_required_buffer_size_type(var->type, var->ptr_level, var->array, var->name, alignment);
|
||||
}
|
||||
|
||||
|
@ -1365,6 +1406,9 @@ void write_remoting_arguments(FILE *file, int indent, const func_t *func,
|
|||
unsigned int *type_offset, enum pass pass,
|
||||
enum remoting_phase phase)
|
||||
{
|
||||
const expr_t *length_is;
|
||||
const expr_t *size_is;
|
||||
int in_attr, out_attr, has_length, has_size, pointer_type;
|
||||
var_t *var;
|
||||
|
||||
if (!func->args)
|
||||
|
@ -1374,9 +1418,17 @@ void write_remoting_arguments(FILE *file, int indent, const func_t *func,
|
|||
while (NEXT_LINK(var)) var = NEXT_LINK(var);
|
||||
for (; var; *type_offset += get_size_typeformatstring_var(var), var = PREV_LINK(var))
|
||||
{
|
||||
int in_attr = is_attr(var->attrs, ATTR_IN);
|
||||
int out_attr = is_attr(var->attrs, ATTR_OUT);
|
||||
length_is = get_attrp(var->attrs, ATTR_LENGTHIS);
|
||||
size_is = get_attrp(var->attrs, ATTR_SIZEIS);
|
||||
has_length = length_is && (length_is->type != EXPR_VOID);
|
||||
has_size = (size_is && (size_is->type != EXPR_VOID)) || (var->array && !var->array->is_const);
|
||||
|
||||
pointer_type = get_attrv(var->attrs, ATTR_POINTERTYPE);
|
||||
if (!pointer_type)
|
||||
pointer_type = RPC_FC_RP;
|
||||
|
||||
in_attr = is_attr(var->attrs, ATTR_IN);
|
||||
out_attr = is_attr(var->attrs, ATTR_OUT);
|
||||
if (!in_attr && !out_attr)
|
||||
in_attr = 1;
|
||||
|
||||
|
@ -1401,17 +1453,42 @@ void write_remoting_arguments(FILE *file, int indent, const func_t *func,
|
|||
"NdrNonConformantString%s(&_StubMsg, (unsigned char *)%s, &__MIDL_TypeFormatString.Format[%d]);\n",
|
||||
function_from_phase(phase), var->name, *type_offset);
|
||||
else
|
||||
print_file(file, indent,
|
||||
"NdrConformantString%s(&_StubMsg, (unsigned char *)%s, &__MIDL_TypeFormatString.Format[%d]);\n",
|
||||
function_from_phase(phase), var->name, *type_offset);
|
||||
{
|
||||
if (size_is && phase != PHASE_UNMARSHAL)
|
||||
{
|
||||
print_file(file, indent, "_StubMsg.MaxCount = (unsigned long)");
|
||||
write_expr(file, size_is, 1);
|
||||
fprintf(file, ";\n");
|
||||
}
|
||||
|
||||
if (phase == PHASE_FREE)
|
||||
{
|
||||
print_file(file, indent, "NdrPointerFree(\n");
|
||||
indent++;
|
||||
print_file(file, indent, "&_StubMsg,\n");
|
||||
print_file(file, indent, "(unsigned char *)%s,\n", var->name);
|
||||
print_file(file, indent, "&__MIDL_TypeFormatString.Format[%d]);\n",
|
||||
*type_offset);
|
||||
indent--;
|
||||
}
|
||||
else
|
||||
{
|
||||
print_file(file, indent, "NdrConformantString%s(\n", function_from_phase(phase));
|
||||
indent++;
|
||||
print_file(file, indent, "(PMIDL_STUB_MESSAGE)&_StubMsg,\n");
|
||||
print_file(file, indent, "(unsigned char *)%s,\n", var->name);
|
||||
print_file(file, indent, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]%s\n",
|
||||
*type_offset + (has_size ? 4 : 2),
|
||||
(phase == PHASE_MARSHAL) ? ");" : ",");
|
||||
if (phase == PHASE_UNMARSHAL)
|
||||
print_file(file, indent, "(unsigned char)0);\n");
|
||||
indent--;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (is_array_type(var->attrs, var->ptr_level, var->array))
|
||||
{
|
||||
const expr_t *length_is = get_attrp(var->attrs, ATTR_LENGTHIS);
|
||||
const expr_t *size_is = get_attrp(var->attrs, ATTR_SIZEIS);
|
||||
const char *array_type;
|
||||
int has_length = length_is && (length_is->type != EXPR_VOID);
|
||||
int has_size = (size_is && (size_is->type != EXPR_VOID)) || !var->array->is_const;
|
||||
|
||||
if (var->array && NEXT_LINK(var->array)) /* multi-dimensional array */
|
||||
array_type = "ComplexArray";
|
||||
|
@ -1506,31 +1583,34 @@ void write_remoting_arguments(FILE *file, int indent, const func_t *func,
|
|||
size = 0;
|
||||
}
|
||||
|
||||
print_file(file, indent, "_StubMsg.Buffer += (unsigned char *)(((long)_StubMsg.Buffer + %u) & ~0x%x);\n",
|
||||
alignment - 1, alignment - 1);
|
||||
|
||||
if (phase == PHASE_MARSHAL)
|
||||
if (phase == PHASE_MARSHAL || phase == PHASE_UNMARSHAL)
|
||||
{
|
||||
print_file(file, indent, "*(");
|
||||
write_type(file, var->type, var, var->tname);
|
||||
fprintf(file, " *)_StubMsg.Buffer = ");
|
||||
write_name(file, var);
|
||||
fprintf(file, ";\n");
|
||||
}
|
||||
else if (phase == PHASE_UNMARSHAL)
|
||||
{
|
||||
print_file(file, indent, "");
|
||||
write_name(file, var);
|
||||
fprintf(file, " = *(");
|
||||
write_type(file, var->type, var, var->tname);
|
||||
fprintf(file, " *)_StubMsg.Buffer;\n");
|
||||
}
|
||||
else
|
||||
error("write_remoting_arguments: Unimplemented for base types for phase %d\n", phase);
|
||||
print_file(file, indent, "_StubMsg.Buffer += (unsigned char *)(((long)_StubMsg.Buffer + %u) & ~0x%x);\n",
|
||||
alignment - 1, alignment - 1);
|
||||
|
||||
print_file(file, indent, "_StubMsg.Buffer += sizeof(");
|
||||
write_type(file, var->type, var, var->tname);
|
||||
fprintf(file, ");\n");
|
||||
if (phase == PHASE_MARSHAL)
|
||||
{
|
||||
print_file(file, indent, "*(");
|
||||
write_type(file, var->type, var, var->tname);
|
||||
fprintf(file, " *)_StubMsg.Buffer = ");
|
||||
write_name(file, var);
|
||||
fprintf(file, ";\n");
|
||||
}
|
||||
else if (phase == PHASE_UNMARSHAL)
|
||||
{
|
||||
print_file(file, indent, "");
|
||||
write_name(file, var);
|
||||
fprintf(file, " = *(");
|
||||
write_type(file, var->type, var, var->tname);
|
||||
fprintf(file, " *)_StubMsg.Buffer;\n");
|
||||
}
|
||||
else
|
||||
error("write_remoting_arguments: Unimplemented for base types for phase %d\n", phase);
|
||||
|
||||
print_file(file, indent, "_StubMsg.Buffer += sizeof(");
|
||||
write_type(file, var->type, var, var->tname);
|
||||
fprintf(file, ");\n");
|
||||
}
|
||||
}
|
||||
else if (var->ptr_level == 0)
|
||||
{
|
||||
|
@ -1563,10 +1643,6 @@ void write_remoting_arguments(FILE *file, int indent, const func_t *func,
|
|||
}
|
||||
else
|
||||
{
|
||||
int pointer_type = get_attrv(var->attrs, ATTR_POINTERTYPE);
|
||||
if (!pointer_type)
|
||||
pointer_type = RPC_FC_RP;
|
||||
|
||||
if (pointer_type == RPC_FC_RP)
|
||||
{
|
||||
unsigned int size;
|
||||
|
|
|
@ -37,6 +37,7 @@ enum remoting_phase
|
|||
|
||||
void write_procformatstring(FILE *file, type_t *iface);
|
||||
void write_typeformatstring(FILE *file, type_t *iface);
|
||||
size_t get_type_memsize(const type_t *type);
|
||||
unsigned int get_required_buffer_size(const var_t *var, unsigned int *alignment);
|
||||
void write_remoting_arguments(FILE *file, int indent, const func_t *func, unsigned int *type_offset, enum pass pass, enum remoting_phase phase);
|
||||
size_t get_size_procformatstring_var(const var_t *var);
|
||||
|
|
Loading…
Reference in New Issue