From 5bed4857d562e827c21de553748fe0dd7ae1de3a Mon Sep 17 00:00:00 2001 From: Eric Kohl Date: Wed, 23 Feb 2005 20:31:07 +0000 Subject: [PATCH] - Add basic support for creating client and server stub files. - Support implicit_handle attribute in IDL files. - Build mixed-mode stub files. --- tools/widl/Makefile.in | 2 + tools/widl/client.c | 451 ++++++++++++++++++++++++++++++++++++++++ tools/widl/header.c | 7 +- tools/widl/parser.l | 3 +- tools/widl/parser.y | 11 +- tools/widl/server.c | 460 +++++++++++++++++++++++++++++++++++++++++ tools/widl/widl.c | 63 +++++- tools/widl/widl.h | 9 + tools/widl/widltypes.h | 3 + 9 files changed, 995 insertions(+), 14 deletions(-) create mode 100644 tools/widl/client.c create mode 100644 tools/widl/server.c diff --git a/tools/widl/Makefile.in b/tools/widl/Makefile.in index df682580cd7..3cfcfe17015 100644 --- a/tools/widl/Makefile.in +++ b/tools/widl/Makefile.in @@ -10,9 +10,11 @@ PROGRAMS = widl$(EXEEXT) MODULE = none C_SRCS = \ + client.c \ hash.c \ header.c \ proxy.c \ + server.c \ typelib.c \ utils.c \ widl.c \ diff --git a/tools/widl/client.c b/tools/widl/client.c new file mode 100644 index 00000000000..0f1e8efd024 --- /dev/null +++ b/tools/widl/client.c @@ -0,0 +1,451 @@ +/* + * IDL Compiler + * + * Copyright 2005 Eric Kohl + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" +#include "wine/port.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "windef.h" + +#include "widl.h" +#include "utils.h" +#include "parser.h" +#include "header.h" + +#include "widltypes.h" +#include "typelib.h" +#include "typelib_struct.h" + +#define END_OF_LIST(list) \ + do { \ + if (list) { \ + while (NEXT_LINK(list)) \ + list = NEXT_LINK(list); \ + } \ + } while(0) + +static FILE* client; +static int indent = 0; + +static int print_client( const char *format, ... ) +{ + va_list va; + int i, r; + + va_start(va, format); + for (i = 0; i < indent; i++) + fprintf(client, " "); + r = vfprintf(client, format, va); + va_end(va); + return r; +} + + +static void write_procformatstring(type_t *iface) +{ + func_t *cur = iface->funcs; + + print_client("static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString =\n"); + print_client("{\n"); + indent++; + print_client("0,\n"); + print_client("{\n"); + indent++; + + while (NEXT_LINK(cur)) cur = NEXT_LINK(cur); + while (cur) + { + var_t *def = cur->def; + + if (is_void(def->type, NULL)) + { + print_client("0x5b, /* FC_END */\n"); + print_client("0x5c, /* FC_PAD */\n"); + } + else + { + print_client("0x53, /* FC_RETURN_PARAM_BASETYPE */\n"); + print_client("0x%02x, /* */\n", def->type->type); + } + + cur = PREV_LINK(cur); + } + + print_client("0x0\n"); + indent--; + print_client("}\n"); + indent--; + print_client("};\n"); + print_client("\n"); +} + + +static void write_typeformatstring(void) +{ + print_client("static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString =\n"); + print_client("{\n"); + indent++; + print_client("0,\n"); + print_client("{\n"); + indent++; + print_client("NdrFcShort(0x0),\n"); + print_client("0x0\n"); + indent--; + print_client("}\n"); + indent--; + print_client("};\n"); + print_client("\n"); +} + + +static void write_function_stubs(type_t *iface) +{ + func_t *cur = iface->funcs; + char *handle_name = get_attrp(iface->attrs, ATTR_IMPLICIT_HANDLE); + int method_count = 0; + unsigned int proc_offset = 0; + + while (NEXT_LINK(cur)) cur = NEXT_LINK(cur); + while (cur) + { + var_t *def = cur->def; + + write_type(client, def->type, def, def->tname); + fprintf(client, " "); + write_name(client, def); + fprintf(client, "(\n"); + indent++; + if (cur->args) + write_args(client, cur->args, iface->name, 0, TRUE); + else + print_client("void"); + fprintf(client, ")\n"); + indent--; + + /* write the functions body */ + fprintf(client, "{\n"); + indent++; + + /* declare return value '_RetVal' */ + if (!is_void(def->type, NULL)) + { + print_client(""); + write_type(client, def->type, def, def->tname); + fprintf(client, " _RetVal;\n"); + } + + if (handle_name) + print_client("RPC_BINDING_HANDLE _Handle = 0;\n"); + + print_client("RPC_MESSAGE _RpcMessage;\n"); + print_client("MIDL_STUB_MESSAGE _StubMsg;\n"); + fprintf(client, "\n"); + print_client("RpcTryFinally\n"); + print_client("{\n"); + indent++; + + print_client("NdrClientInitializeNew(\n"); + indent++; + print_client("(PRPC_MESSAGE)&_RpcMessage,\n"); + print_client("(PMIDL_STUB_MESSAGE)&_StubMsg,\n"); + print_client("(PMIDL_STUB_DESC)&%s_StubDesc,\n", iface->name); + print_client("%d);\n", method_count); + indent--; + fprintf(client, "\n"); + + if (handle_name) + print_client("_Handle = %s;\n", handle_name); + + /* FIXME: marshal arguments */ + print_client("_StubMsg.BufferLength = 0UL;\n"); + /* print_client("NdrNsGetBuffer(\n"); */ + print_client("NdrGetBuffer(\n"); + indent++; + print_client("(PMIDL_STUB_MESSAGE)&_StubMsg,\n"); + print_client("_StubMsg.BufferLength,\n"); + if (handle_name) + print_client("%_Handle);\n"); + else + print_client("%s__MIDL_AutoBindHandle);\n", iface->name); + indent--; + fprintf(client, "\n"); + + + /* send/recieve message */ + /* print_client("NdrNsSendReceive(\n"); */ + print_client("NdrSendReceive(\n"); + indent++; + print_client("(PMIDL_STUB_MESSAGE)&_StubMsg,\n"); + print_client("(unsigned char __RPC_FAR *)_StubMsg.Buffer);\n"); + /* print_client("(unsigned char __RPC_FAR *)_StubMsg.Buffer,\n"); */ + /* print_client("(RPC_BINDING_HANDLE __RPC_FAR *) &%s__MIDL_AutoBindHandle);\n", iface->name); */ + indent--; + + /* unmarshal return value */ + if (is_void(def->type, NULL)) + { + proc_offset += 2; + } + else + { + fprintf(client, "\n"); + + print_client("if ((_RpcMessage.DataRepresentation & 0x0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION)\n"); + indent++; + print_client("NdrConvert(\n"); + indent++; + print_client("(PMIDL_STUB_MESSAGE)&_StubMsg,\n"); + print_client("(PFORMAT_STRING)&__MIDL_ProcFormatString[%u]);\n", proc_offset); + indent -= 2; + fprintf(client, "\n"); + + print_client("_RetVal = *(("); + write_type(client, def->type, def, def->tname); + fprintf(client, " __RPC_FAR *)_StubMsg.Buffer)++;\n"); + + /* FIXME: update proc_offset */ + proc_offset += 2; + } + + indent--; + print_client("}\n"); + print_client("RpcFinally\n"); + print_client("{\n"); + indent++; + + + /* FIXME: emit client finally code */ + + print_client("NdrFreeBuffer((PMIDL_STUB_MESSAGE)&_StubMsg);\n"); + + indent--; + print_client("}\n"); + print_client("RpcEndFinally\n"); + + + /* emit return code */ + if (!is_void(def->type, NULL)) + { + fprintf(client, "\n"); + print_client("return _RetVal;\n"); + } + + indent--; + fprintf(client, "}\n"); + fprintf(client, "\n"); + + method_count++; + cur = PREV_LINK(cur); + } +} + + +static void write_bindinghandledecl(type_t *iface) +{ + print_client("static RPC_BINDING_HANDLE %s__MIDL_AutoBindHandle;\n", iface->name); + fprintf(client, "\n"); +} + + +static void write_stubdescdecl(type_t *iface) +{ + print_client("extern const MIDL_STUB_DESC %s_StubDesc;\n", iface->name); + fprintf(client, "\n"); +} + + +static void write_stubdescriptor(type_t *iface) +{ + char *handle_name = get_attrp(iface->attrs, ATTR_IMPLICIT_HANDLE); + + print_client("static const MIDL_STUB_DESC %s_StubDesc =\n", iface->name); + print_client("{\n"); + indent++; + print_client("(void __RPC_FAR *)& %s___RpcClientInterface,\n", iface->name); + print_client("MIDL_user_allocate,\n"); + print_client("MIDL_user_free,\n"); + if (handle_name) + print_client("&%s,\n", handle_name); + else + print_client("&%s__MIDL_AutoBindHandle,\n", iface->name); + print_client("0,\n"); + print_client("0,\n"); + print_client("0,\n"); + print_client("0,\n"); + print_client("__MIDL_TypeFormatString.Format,\n"); + print_client("1, /* -error bounds_check flag */\n"); + print_client("0x10001, /* Ndr library version */\n"); + print_client("0,\n"); + print_client("0x50100a4, /* MIDL Version 5.1.164 */\n"); + print_client("0,\n"); + print_client("0,\n"); + print_client("0, /* notify & notify_flag routine table */\n"); + print_client("1, /* Flags */\n"); + print_client("0, /* Reserved3 */\n"); + print_client("0, /* Reserved4 */\n"); + print_client("0 /* Reserved5 */\n"); + indent--; + print_client("};\n"); + fprintf(client, "\n"); +} + + +static void write_clientinterfacedecl(type_t *iface) +{ + unsigned long ver = get_attrv(iface->attrs, ATTR_VERSION); + UUID *uuid = get_attrp(iface->attrs, ATTR_UUID); + + print_client("static const RPC_CLIENT_INTERFACE %s___RpcClientInterface =\n", iface->name ); + print_client("{\n"); + indent++; + print_client("sizeof(RPC_CLIENT_INTERFACE),\n"); + print_client("{{0x%08lx,0x%04x,0x%04x,{0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x}},{%d,%d}},\n", + uuid->Data1, uuid->Data2, uuid->Data3, uuid->Data4[0], uuid->Data4[1], + uuid->Data4[2], uuid->Data4[3], uuid->Data4[4], uuid->Data4[5], uuid->Data4[6], + uuid->Data4[7], LOWORD(ver), HIWORD(ver)); + print_client("{{0x8a885d04,0x1ceb,0x11c9,{0x9f,0xe8,0x08,0x00,0x2b,0x10,0x48,0x60}},{2,0}},\n"); /* FIXME */ + print_client("0,\n"); + print_client("0,\n"); + print_client("0,\n"); + print_client("0,\n"); + print_client("0,\n"); + print_client("0,\n"); + indent--; + print_client("};\n"); + print_client("RPC_IF_HANDLE %s_v%d_%d_c_ifspec = (RPC_IF_HANDLE)& %s___RpcClientInterface;\n", + iface->name, LOWORD(ver), HIWORD(ver), iface->name); + fprintf(client, "\n"); +} + + +static void write_formatdesc( const char *str ) +{ + print_client("typedef struct _MIDL_%s_FORMAT_STRING\n", str ); + print_client("{\n"); + indent++; + print_client("short Pad;\n"); + print_client("unsigned char Format[%s_FORMAT_STRING_SIZE];\n", str); + indent--; + print_client("} MIDL_%s_FORMAT_STRING;\n", str); + print_client("\n"); +} + + +static void write_formatstringsdecl(type_t *iface) +{ + func_t *cur; + int byte_count = 1; + + print_client("#define TYPE_FORMAT_STRING_SIZE %d\n", 3); /* FIXME */ + + /* determine the proc format string size */ + cur = iface->funcs; + while (NEXT_LINK(cur)) cur = NEXT_LINK(cur); + while (cur) + { + byte_count += 2; /* FIXME: determine real size */ + cur = PREV_LINK(cur); + } + print_client("#define PROC_FORMAT_STRING_SIZE %d\n", byte_count); + + fprintf(client, "\n"); + write_formatdesc("TYPE"); + write_formatdesc("PROC"); + fprintf(client, "\n"); + print_client("extern const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString;\n"); + print_client("extern const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString;\n"); + print_client("\n"); +} + + +static void write_implicithandledecl(type_t *iface) +{ + char *var = get_attrp(iface->attrs, ATTR_IMPLICIT_HANDLE); + + if (var) + { + fprintf(client, "handle_t %s;\n", var); + fprintf(client, "\n"); + } +} + + +static void init_client(void) +{ + if (client) return; + if (!(client = fopen(client_name, "w"))) + error("Could not open %s for output\n", client_name); + + print_client("/*** Autogenerated by WIDL %s from %s - Do not edit ***/\n", WIDL_FULLVERSION, input_name); + print_client("#include\n"); + print_client("#ifdef _ALPHA_\n"); + print_client("#include\n"); + print_client("#endif\n"); + fprintf(client, "\n"); + print_client("#include\"%s\"\n", header_name); + fprintf(client, "\n"); +} + + +void write_client(ifref_t *ifaces) +{ + ifref_t *lcur = ifaces; + char *file_id = client_token; + int c; + + if (!do_client) + return; + if (!lcur) + return; + END_OF_LIST(lcur); + + init_client(); + if (!client) + return; + + write_formatstringsdecl(lcur->iface); + write_implicithandledecl(lcur->iface); + + write_clientinterfacedecl(lcur->iface); + write_stubdescdecl(lcur->iface); + write_bindinghandledecl(lcur->iface); + + write_function_stubs(lcur->iface); + write_stubdescriptor(lcur->iface); + + print_client("#if !defined(__RPC_WIN32__)\n"); + print_client("#error Invalid build platform for this stub.\n"); + print_client("#endif\n"); + fprintf(client, "\n"); + + write_procformatstring(lcur->iface); + write_typeformatstring(); + + fprintf(client, "\n"); + + fclose(client); +} diff --git a/tools/widl/header.c b/tools/widl/header.c index 67ea841dbdb..fb00566cec9 100644 --- a/tools/widl/header.c +++ b/tools/widl/header.c @@ -669,7 +669,10 @@ static void write_function_proto(type_t *iface) fprintf(header, " "); write_name(header, def); fprintf(header, "(\n"); - write_args(header, cur->args, iface->name, 0, TRUE); + if (cur->args) + write_args(header, cur->args, iface->name, 0, TRUE); + else + fprintf(header, " void"); fprintf(header, ");\n"); cur = PREV_LINK(cur); @@ -784,6 +787,7 @@ void write_com_interface(type_t *iface) void write_rpc_interface(type_t *iface) { unsigned long ver = get_attrv(iface->attrs, ATTR_VERSION); + char *var = get_attrp(iface->attrs, ATTR_IMPLICIT_HANDLE); if (!iface->funcs) return; @@ -791,6 +795,7 @@ void write_rpc_interface(type_t *iface) fprintf(header, " * %s interface (v%d.%d)\n", iface->name, LOWORD(ver), HIWORD(ver)); fprintf(header, " */\n"); write_iface_guid(iface); + if (var) fprintf(header, "extern handle_t %s;\n", var); fprintf(header, "extern RPC_IF_HANDLE %s_v%d_%d_c_ifspec;\n", iface->name, LOWORD(ver), HIWORD(ver)); fprintf(header, "extern RPC_IF_HANDLE %s_v%d_%d_s_ifspec;\n", iface->name, LOWORD(ver), HIWORD(ver)); write_function_proto(iface); diff --git a/tools/widl/parser.l b/tools/widl/parser.l index 340322cc15c..addb2ecdad9 100644 --- a/tools/widl/parser.l +++ b/tools/widl/parser.l @@ -218,7 +218,7 @@ static struct keyword { {"entry", tENTRY}, {"enum", tENUM}, {"error_status_t", tERRORSTATUST}, -/* ... */ + {"explicit_handle", tEXPLICITHANDLE}, {"extern", tEXTERN}, /* ... */ {"float", tFLOAT}, @@ -239,6 +239,7 @@ static struct keyword { /* ... */ {"iid_is", tIIDIS}, /* ... */ + {"implicit_handle", tIMPLICITHANDLE}, {"import", tIMPORT}, {"importlib", tIMPORTLIB}, {"in", tIN}, diff --git a/tools/widl/parser.y b/tools/widl/parser.y index 80b78155977..54896b9df83 100644 --- a/tools/widl/parser.y +++ b/tools/widl/parser.y @@ -138,7 +138,7 @@ static type_t std_uhyper = { "MIDL_uhyper" }; %token tDLLNAME tDOUBLE tDUAL %token tENDPOINT %token tENTRY tENUM tERRORSTATUST -%token tEXTERN +%token tEXPLICITHANDLE tEXTERN %token tFLOAT %token tHANDLE %token tHANDLET @@ -147,6 +147,7 @@ static type_t std_uhyper = { "MIDL_uhyper" }; %token tHIDDEN %token tHYPER tID tIDEMPOTENT %token tIIDIS +%token tIMPLICITHANDLE %token tIMPORT tIMPORTLIB %token tIN tINCLUDE tINLINE %token tINPUTSYNC @@ -224,7 +225,7 @@ static type_t std_uhyper = { "MIDL_uhyper" }; %% -input: gbl_statements { write_proxies($1); } +input: gbl_statements { write_proxies($1); write_client($1); write_server($1); } ; gbl_statements: { $$ = NULL; } @@ -333,6 +334,7 @@ attrib_list: attribute attribute: tASYNC { $$ = make_attr(ATTR_ASYNC); } + | tAUTOHANDLE { $$ = make_attr(ATTR_AUTO_HANDLE); } | tCALLAS '(' ident ')' { $$ = make_attrp(ATTR_CALLAS, $3); } | tCASE '(' expr_list_const ')' { $$ = make_attrp(ATTR_CASE, $3); } | tCONTEXTHANDLE { $$ = make_attrv(ATTR_CONTEXTHANDLE, 0); } @@ -347,6 +349,7 @@ attribute: | tENDPOINT '(' aSTRING ')' { $$ = make_attrp(ATTR_ENDPOINT, $3); } | tENTRY '(' aSTRING ')' { $$ = make_attrp(ATTR_ENTRY_STRING, $3); } | tENTRY '(' expr_const ')' { $$ = make_attrp(ATTR_ENTRY_ORDINAL, $3); } + | tEXPLICITHANDLE { $$ = make_attr(ATTR_EXPLICIT_HANDLE); } | tHANDLE { $$ = make_attr(ATTR_HANDLE); } | tHELPCONTEXT '(' expr_const ')' { $$ = make_attrp(ATTR_HELPCONTEXT, $3); } | tHELPFILE '(' aSTRING ')' { $$ = make_attrp(ATTR_HELPFILE, $3); } @@ -357,6 +360,7 @@ attribute: | tID '(' expr_const ')' { $$ = make_attrp(ATTR_ID, $3); } | tIDEMPOTENT { $$ = make_attr(ATTR_IDEMPOTENT); } | tIIDIS '(' ident ')' { $$ = make_attrp(ATTR_IIDIS, $3); } + | tIMPLICITHANDLE '(' tHANDLET aIDENTIFIER ')' { $$ = make_attrp(ATTR_IMPLICIT_HANDLE, $4); } | tIN { $$ = make_attr(ATTR_IN); } | tINPUTSYNC { $$ = make_attr(ATTR_INPUTSYNC); } | tLENGTHIS '(' m_exprs ')' { $$ = make_attrp(ATTR_LENGTHIS, $3); } @@ -490,7 +494,8 @@ expr_list_const: expr_const ; expr_const: expr { $$ = $1; - if (!$$->is_const) yyerror("expression is not constant\n"); + if (!$$->is_const) + yyerror("expression is not constant\n"); } ; diff --git a/tools/widl/server.c b/tools/widl/server.c new file mode 100644 index 00000000000..f0cd03b6bf2 --- /dev/null +++ b/tools/widl/server.c @@ -0,0 +1,460 @@ +/* + * IDL Compiler + * + * Copyright 2005 Eric Kohl + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" +#include "wine/port.h" + +#include +#include +#ifdef HAVE_UNISTD_H +# include +#endif +#include +#include +#include +#include + +#include "widl.h" +#include "utils.h" +#include "parser.h" +#include "header.h" +#include "windef.h" + +#include "widl.h" +#include "typelib.h" +#include "typelib_struct.h" + +#define END_OF_LIST(list) \ + do { \ + if (list) { \ + while (NEXT_LINK(list)) \ + list = NEXT_LINK(list); \ + } \ + } while(0) + +static FILE* server; +static int indent = 0; + + +static int print_server(const char *format, ...) +{ + va_list va; + int i, r; + + va_start(va, format); + for (i = 0; i < indent; i++) + fprintf(server, " "); + r = vfprintf(server, format, va); + va_end(va); + return r; +} + + +static void write_procformatstring(type_t *iface) +{ + func_t *cur = iface->funcs; + + print_server("static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString =\n"); + print_server("{\n"); + indent++; + print_server("0,\n"); + print_server("{\n"); + indent++; + + while (NEXT_LINK(cur)) cur = NEXT_LINK(cur); + while (cur) + { + var_t *def = cur->def; + + if (is_void(def->type, NULL)) + { + print_server("0x5b, /* FC_END */\n"); + print_server("0x5c, /* FC_PAD */\n"); + } + else + { + print_server("0x53, /* FC_RETURN_PARAM_BASETYPE */\n"); + print_server("0x%02x, /* */\n", def->type->type); + } + + cur = PREV_LINK(cur); + } + + print_server("0x0\n"); + indent--; + print_server("}\n"); + indent--; + print_server("};\n"); + print_server("\n"); +} + + +static void write_typeformatstring(void) +{ + print_server("static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString =\n"); + print_server("{\n"); + indent++; + print_server("0,\n"); + print_server("{\n"); + indent++; + print_server("NdrFcShort(0x0),\n"); + print_server("0x0\n"); + indent--; + print_server("}\n"); + indent--; + print_server("};\n"); + print_server("\n"); +} + + +unsigned int get_required_stack_size(type_t *type) +{ + switch(type->type) + { + case RPC_FC_BYTE: + case RPC_FC_CHAR: + case RPC_FC_WCHAR: + case RPC_FC_USHORT: + case RPC_FC_SHORT: + case RPC_FC_ULONG: + case RPC_FC_LONG: + return 4; + + case RPC_FC_HYPER: + return 8; + + default: + error("Unknown/unsupported type: %s\n", type->name); + } +} + + +static void write_function_stubs(type_t *iface) +{ + func_t *cur = iface->funcs; + while (NEXT_LINK(cur)) cur = NEXT_LINK(cur); + while (cur) + { + var_t *def = cur->def; + + write_type(server, def->type, def, def->tname); + fprintf(server, " __RPC_STUB\n"); + fprintf(server, "%s_", iface->name); + write_name(server, def); + fprintf(server, "(\n"); + indent++; + print_server("PRPC_MESSAGE _pRpcMessage)\n"); + indent--; + + /* write the functions body */ + fprintf(server, "{\n"); + indent++; + + /* declare return value '_RetVal' */ + if (!is_void(def->type, NULL)) + { + print_server(""); + write_type(server, def->type, def, def->tname); + fprintf(server, " _RetVal;\n"); + } + + print_server("MIDL_STUB_MESSAGE _StubMsg;\n"); + print_server("RPC_STATUS _Status;\n"); + fprintf(server, "\n"); + print_server("((void)(_Status));\n"); + print_server("NdrServerInitializeNew(\n"); + indent++; + print_server("_pRpcMessage,\n"); + print_server("&_StubMsg,\n"); + print_server("&%s_StubDesc);\n", iface->name); + indent--; + fprintf(server, "\n"); + + print_server("RpcTryFinally\n"); + print_server("{\n"); + indent++; + print_server("RpcTryExcept\n"); + print_server("{\n"); + indent++; + print_server("if (_StubMsg.Buffer > _StubMsg.BufferEnd)\n"); + print_server("{\n"); + indent++; + print_server("RpcRaiseException(RPC_X_BAD_STUB_DATA);\n"); + indent--; + print_server("}\n"); + indent--; + print_server("}\n"); + print_server("RpcExcept(RPC_BAD_STUB_DATA_EXCEPTION_FILTER)\n"); + print_server("{\n"); + indent++; + print_server("RpcRaiseException(RPC_X_BAD_STUB_DATA);\n"); + indent--; + print_server("}\n"); + print_server("RpcEndExcept\n"); + fprintf(server, "\n"); + + + /* Call the real server function */ + if (!is_void(def->type, NULL)) + print_server("_RetVal = "); + else + print_server(""); + write_name(server, def); + + /* FIXME: handle argument list */ + fprintf(server, "();\n"); + + /* FIXME: Marshall the return value */ + if (!is_void(def->type, NULL)) + { + fprintf(server, "\n"); + print_server("_StubMsg.BufferLength = %uU;\n", get_required_stack_size(def->type)); + print_server("_pRpcMessage->BufferLength = _StubMsg.BufferLength;\n"); + fprintf(server, "\n"); + print_server("_Status = I_RpcGetBuffer(_pRpcMessage);\n"); + print_server("if (_Status)\n"); + indent++; + print_server("RpcRaiseException(_Status);\n"); + indent--; + fprintf(server, "\n"); + print_server("_StubMsg.Buffer = (unsigned char __RPC_FAR *)_pRpcMessage->Buffer;\n"); + fprintf(server, "\n"); + + print_server("*(("); + write_type(server, def->type, def, def->tname); + fprintf(server, " __RPC_FAR *)_StubMsg.Buffer)++ = _RetVal;\n"); + } + + indent--; + print_server("}\n"); + print_server("RpcFinally\n"); + print_server("{\n"); + print_server("}\n"); + print_server("RpcEndFinally\n"); + + /* calculate buffer length */ + fprintf(server, "\n"); + print_server("_pRpcMessage->BufferLength =\n"); + indent++; + print_server("(unsigned int)((long)_StubMsg.Buffer - (long)_pRpcMessage->Buffer);\n"); + indent--; + indent--; + fprintf(server, "}\n"); + fprintf(server, "\n"); + + cur = PREV_LINK(cur); + } +} + + +static void write_dispatchtable(type_t *iface) +{ + unsigned long ver = get_attrv(iface->attrs, ATTR_VERSION); + unsigned long method_count = 0; + func_t *cur = iface->funcs; + + print_server("static RPC_DISPATCH_FUNCTION %s_table[] =\n", iface->name); + print_server("{\n"); + indent++; + while (NEXT_LINK(cur)) cur = NEXT_LINK(cur); + while (cur) + { + var_t *def = cur->def; + + print_server("%s_", iface->name); + write_name(server, def); + fprintf(server, ",\n"); + + method_count++; + cur = PREV_LINK(cur); + } + print_server("0\n"); + indent--; + print_server("};\n"); + print_server("RPC_DISPATCH_TABLE %s_v%d_%d_DispatchTable =\n", iface->name, LOWORD(ver), HIWORD(ver)); + print_server("{\n"); + indent++; + print_server("%u,\n", method_count); + print_server("%s_table\n", iface->name); + indent--; + print_server("};\n"); + fprintf(server, "\n"); +} + + +static void write_stubdescdecl(type_t *iface) +{ + print_server("extern const MIDL_STUB_DESC %s_StubDesc;\n", iface->name); + fprintf(server, "\n"); +} + + +static void write_stubdescriptor(type_t *iface) +{ + print_server("static const MIDL_STUB_DESC %s_StubDesc =\n", iface->name); + print_server("{\n"); + indent++; + print_server("(void __RPC_FAR *)& %s___RpcServerInterface,\n", iface->name); + print_server("MIDL_user_allocate,\n"); + print_server("MIDL_user_free,\n"); + print_server("0,\n"); + print_server("0,\n"); + print_server("0,\n"); + print_server("0,\n"); + print_server("0,\n"); + print_server("__MIDL_TypeFormatString.Format,\n"); + print_server("1, /* -error bounds_check flag */\n"); + print_server("0x10001, /* Ndr library version */\n"); + print_server("0,\n"); + print_server("0x50100a4, /* MIDL Version 5.1.164 */\n"); + print_server("0,\n"); + print_server("0,\n"); + print_server("0, /* notify & notify_flag routine table */\n"); + print_server("1, /* Flags */\n"); + print_server("0, /* Reserved3 */\n"); + print_server("0, /* Reserved4 */\n"); + print_server("0 /* Reserved5 */\n"); + indent--; + print_server("};\n"); + fprintf(server, "\n"); +} + + +static void write_serverinterfacedecl(type_t *iface) +{ + unsigned long ver = get_attrv(iface->attrs, ATTR_VERSION); + UUID *uuid = get_attrp(iface->attrs, ATTR_UUID); + + print_server("extern RPC_DISPATCH_TABLE %s_v%d_%d_DispatchTable;\n", iface->name, LOWORD(ver), HIWORD(ver)); + fprintf(server, "\n"); + print_server("static const RPC_SERVER_INTERFACE %s___RpcServerInterface =\n", iface->name ); + print_server("{\n"); + indent++; + print_server("sizeof(RPC_SERVER_INTERFACE),\n"); + print_server("{{0x%08lx,0x%04x,0x%04x,{0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x}},{%d,%d}},\n", + uuid->Data1, uuid->Data2, uuid->Data3, uuid->Data4[0], uuid->Data4[1], + uuid->Data4[2], uuid->Data4[3], uuid->Data4[4], uuid->Data4[5], uuid->Data4[6], + uuid->Data4[7], LOWORD(ver), HIWORD(ver)); + print_server("{{0x8a885d04,0x1ceb,0x11c9,{0x9f,0xe8,0x08,0x00,0x2b,0x10,0x48,0x60}},{2,0}},\n"); /* FIXME */ + print_server("&%s_v%d_%d_DispatchTable,\n", iface->name, LOWORD(ver), HIWORD(ver)); + print_server("0,\n"); + print_server("0,\n"); + print_server("0,\n"); + print_server("0,\n"); + print_server("0,\n"); + indent--; + print_server("};\n"); + print_server("RPC_IF_HANDLE %s_v%d_%d_s_ifspec = (RPC_IF_HANDLE)& %s___RpcServerInterface;\n", + iface->name, LOWORD(ver), HIWORD(ver), iface->name); + fprintf(server, "\n"); +} + +static void write_formatdesc( const char *str ) +{ + print_server("typedef struct _MIDL_%s_FORMAT_STRING\n", str ); + print_server("{\n"); + indent++; + print_server("short Pad;\n"); + print_server("unsigned char Format[%s_FORMAT_STRING_SIZE];\n", str); + indent--; + print_server("} MIDL_%s_FORMAT_STRING;\n", str); + print_server("\n"); +} + + +static void write_formatstringsdecl(type_t *iface) +{ + func_t *cur; + int byte_count = 1; + + print_server("#define TYPE_FORMAT_STRING_SIZE %d\n", 3); /* FIXME */ + + /* determine the proc format string size */ + cur = iface->funcs; + while (NEXT_LINK(cur)) cur = NEXT_LINK(cur); + while (cur) + { + byte_count += 2; /* FIXME: determine real size */ + cur = PREV_LINK(cur); + } + print_server("#define PROC_FORMAT_STRING_SIZE %d\n", byte_count); + + fprintf(server, "\n"); + write_formatdesc("TYPE"); + write_formatdesc("PROC"); + fprintf(server, "\n"); + print_server("extern const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString;\n"); + print_server("extern const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString;\n"); + print_server("\n"); +} + + +static void init_server(void) +{ + if (server) + return; + if (!(server = fopen(server_name, "w"))) + error("Could not open %s for output\n", server_name); + + print_server("/*** Autogenerated by WIDL %s from %s - Do not edit ***/\n", WIDL_FULLVERSION, input_name); + print_server("#include\n"); + fprintf(server, "\n"); + print_server("#include\"%s\"\n", header_name); + fprintf(server, "\n"); +} + + +void write_server(ifref_t *ifaces) +{ + ifref_t *lcur = ifaces; + char *file_id = server_token; + int c; + + if (!do_server) + return; + if (!lcur) + return; + END_OF_LIST(lcur); + + init_server(); + if (!server) + return; + + write_formatstringsdecl(lcur->iface); + write_serverinterfacedecl(lcur->iface); + write_stubdescdecl(lcur->iface); + + write_function_stubs(lcur->iface); + + write_stubdescriptor(lcur->iface); + write_dispatchtable(lcur->iface); + + print_server("#if !defined(__RPC_WIN32__)\n"); + print_server("#error Invalid build platform for this stub.\n"); + print_server("#endif\n"); + fprintf(server, "\n"); + + write_procformatstring(lcur->iface); + write_typeformatstring(); + + fprintf(server, "\n"); + + fclose(server); +} diff --git a/tools/widl/widl.c b/tools/widl/widl.c index 973522d0830..be5d9da08f5 100644 --- a/tools/widl/widl.c +++ b/tools/widl/widl.c @@ -42,20 +42,16 @@ /* future options to reserve characters for: */ /* a = alignment of structures */ /* A = ACF input filename */ -/* c = client stub only? */ -/* C = client stub filename */ /* J = do not search standard include path */ /* O = generate interpreted stubs */ -/* p = proxy only? */ -/* P = proxy filename */ -/* s = server stub only? */ -/* S = server stub filename */ /* u = UUID file only? */ /* U = UUID filename */ /* w = select win16/win32 output (?) */ static char usage[] = "Usage: widl [options...] infile.idl\n" +" -c Generate client stub\n" +" -C file Name of client stub file (default is infile_c.c)\n" " -d n Set debug level to 'n'\n" " -D id[=val] Define preprocessor identifier id=val\n" " -E Preprocess only\n" @@ -63,6 +59,10 @@ static char usage[] = " -H file Name of header file (default is infile.h)\n" " -I path Set include search dir to path (multiple -I allowed)\n" " -N Do not preprocess input\n" +" -p Generate proxy\n" +" -P file Name of proxy file (default is infile_p.c)\n" +" -s Generate server stub\n" +" -S file Name of server stub file (default is infile_s.c)\n" " -t Generate typelib\n" " -T file Name of typelib file (default is infile.tlb)\n" " -V Print version and exit\n" @@ -88,6 +88,8 @@ int preprocess_only = 0; int do_header = 0; int do_typelib = 0; int do_proxies = 0; +int do_client = 0; +int do_server = 0; int no_preprocess = 0; char *input_name; @@ -96,6 +98,10 @@ char *header_token; char *typelib_name; char *proxy_name; char *proxy_token; +char *client_name; +char *client_token; +char *server_name; +char *server_token; char *temp_name; int line_number = 1; @@ -137,8 +143,15 @@ int main(int argc,char *argv[]) now = time(NULL); - while((optc = getopt(argc, argv, "d:D:EhH:I:NtT:VW")) != EOF) { + while((optc = getopt(argc, argv, "cC:d:D:EhH:I:NpP:sS:tT:VW")) != EOF) { switch(optc) { + case 'c': + do_everything = 0; + do_client = 1; + break; + case 'C': + client_name = strdup(optarg); + break; case 'd': debuglevel = strtol(optarg, NULL, 0); break; @@ -162,6 +175,20 @@ int main(int argc,char *argv[]) case 'N': no_preprocess = 1; break; + case 'p': + do_everything = 0; + do_proxies = 1; + break; + case 'P': + proxy_name = strdup(optarg); + break; + case 's': + do_everything = 0; + do_server = 1; + break; + case 'S': + server_name = strdup(optarg); + break; case 't': do_everything = 0; do_typelib = 1; @@ -182,7 +209,7 @@ int main(int argc,char *argv[]) } if(do_everything) { - do_header = do_typelib = do_proxies = 1; + do_header = do_typelib = do_proxies = do_client = do_server = 1; } if(optind < argc) { input_name = xstrdup(argv[optind]); @@ -221,6 +248,18 @@ int main(int argc,char *argv[]) strcat(proxy_name, "_p.c"); } + if (!client_name && do_client) { + client_name = dup_basename(input_name, ".idl"); + client_token = xstrdup(client_name); + strcat(client_name, "_c.c"); + } + + if (!server_name && do_server) { + server_name = dup_basename(input_name, ".idl"); + server_token = xstrdup(server_name); + strcat(server_name, "_s.c"); + } + wpp_add_cmdline_define("__WIDL__"); atexit(rm_tempfile); @@ -284,6 +323,8 @@ int main(int argc,char *argv[]) exit(1); } header_name = NULL; + client_name = NULL; + server_name = NULL; return 0; } @@ -293,7 +334,11 @@ static void rm_tempfile(void) if(temp_name) unlink(temp_name); if (header_name) - unlink( header_name ); + unlink(header_name); + if (client_name) + unlink(client_name); + if (server_name) + unlink(server_name); } static void segvhandler(int sig) diff --git a/tools/widl/widl.h b/tools/widl/widl.h index e951699ba98..670d4ff225d 100644 --- a/tools/widl/widl.h +++ b/tools/widl/widl.h @@ -41,12 +41,18 @@ extern int pedantic; extern int do_header; extern int do_typelib; extern int do_proxies; +extern int do_client; +extern int do_server; extern char *input_name; extern char *header_name; extern char *typelib_name; extern char *proxy_name; extern char *proxy_token; +extern char *client_name; +extern char *client_token; +extern char *server_name; +extern char *server_token; extern time_t now; extern int line_number; @@ -54,4 +60,7 @@ extern int char_number; extern FILE* header; +extern void write_client(ifref_t *ifaces); +extern void write_server(ifref_t *ifaces); + #endif diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h index 5f142225e37..028c596eab3 100644 --- a/tools/widl/widltypes.h +++ b/tools/widl/widltypes.h @@ -57,6 +57,7 @@ typedef struct _typelib_t typelib_t; enum attr_type { ATTR_ASYNC, + ATTR_AUTO_HANDLE, ATTR_CALLAS, ATTR_CASE, ATTR_CONTEXTHANDLE, @@ -69,6 +70,7 @@ enum attr_type ATTR_ENDPOINT, ATTR_ENTRY_STRING, ATTR_ENTRY_ORDINAL, + ATTR_EXPLICIT_HANDLE, ATTR_HANDLE, ATTR_HELPCONTEXT, ATTR_HELPFILE, @@ -79,6 +81,7 @@ enum attr_type ATTR_ID, ATTR_IDEMPOTENT, ATTR_IIDIS, + ATTR_IMPLICIT_HANDLE, ATTR_IN, ATTR_INPUTSYNC, ATTR_LENGTHIS,