diff options
Diffstat (limited to 'source4/build/pidl')
-rw-r--r-- | source4/build/pidl/README | 24 | ||||
-rw-r--r-- | source4/build/pidl/com_header.pm | 131 | ||||
-rw-r--r-- | source4/build/pidl/dcom_proxy.pm (renamed from source4/build/pidl/proxy.pm) | 146 | ||||
-rw-r--r-- | source4/build/pidl/dcom_stub.pm (renamed from source4/build/pidl/stub.pm) | 10 | ||||
-rw-r--r-- | source4/build/pidl/ndr_header.pm (renamed from source4/build/pidl/header.pm) | 31 | ||||
-rwxr-xr-x | source4/build/pidl/pidl.pl | 118 |
6 files changed, 302 insertions, 158 deletions
diff --git a/source4/build/pidl/README b/source4/build/pidl/README index c6432a8c0e..4b675ce210 100644 --- a/source4/build/pidl/README +++ b/source4/build/pidl/README @@ -13,20 +13,32 @@ After a parse tree is present, pidl will call one of it's backends (which one depends on the options given on the command-line). Here is a list of current backends: -client.pm - Generates client call functions in C +-- Generic -- dump.pm - Converts the parse tree back to an IDL file -eparser.pm - Generates a parser for the ethereal network sniffer +validator.pm - Validates the parse tree + +-- DCE/RPC+NDR -- +client.pm - Generates client call functions in C +eparser.pm - Generates a parser for the ethereal network sniffer by + applying regexes to the output of parser.pm +swig.pm - Generates SWIG interface files (.i) header.pm - Generates a header file with structures parser.pm - Generates pull/push functions for parsing server.pm - Generates server side implementation in C template.pm - Generates stubs in C for server implementation -validator.pm - Validates the parse tree -proxy.pm - Generates proxy object for DCOM (client-side) -stub.pm - Generates stub call handler for DCOM (server-side) -Other files in this directory are: +-- COM / DCOM -- +odl.pm - Generates IDL structures from ODL structures for use in + the NDR parser generator +dcom_proxy.pm - Generates proxy object for DCOM (client-side) +dcom_stub.pm - Generates stub call handler for DCOM (server-side) +com_header.pm - Generates header file for COM interface(s) + +-- Utility modules -- tables.pl - Generates a table of available interfaces from a list of IDL files util.pm - Misc utility functions used by *.pm and pidl.pl +typelist.pm - Utility functions for keeping track of known types and their + representation in C Tips for hacking on pidl: - Look at the pidl's parse tree by using the --keep option and looking diff --git a/source4/build/pidl/com_header.pm b/source4/build/pidl/com_header.pm new file mode 100644 index 0000000000..b0523c935a --- /dev/null +++ b/source4/build/pidl/com_header.pm @@ -0,0 +1,131 @@ +# COM Header generation +# (C) 2005 Jelmer Vernooij <jelmer@samba.org> + +package COMHeader; + +use typelist; + +use strict; + +sub GetArgumentProtoList($) +{ + my $f = shift; + my $res = ""; + + foreach my $a (@{$f->{ELEMENTS}}) { + + $res .= ", " . typelist::mapType($a) . " "; + + my $l = $a->{POINTERS}; + $l-- if ($a->{TYPE} eq "string"); + foreach my $i (1..$l) { + $res .= "*"; + } + + if (defined $a->{ARRAY_LEN} && + !util::is_constant($a->{ARRAY_LEN}) && + !$a->{POINTERS}) { + $res .= "*"; + } + $res .= $a->{NAME}; + if (defined $a->{ARRAY_LEN} && util::is_constant($a->{ARRAY_LEN})) { + $res .= "[$a->{ARRAY_LEN}]"; + } + } + + return $res; +} + +sub GetArgumentList($) +{ + my $f = shift; + my $res = ""; + + foreach my $a (@{$f->{ELEMENTS}}) { + $res .= ", $a->{NAME}"; + } + + return $res; +} + +##################################################################### +# generate vtable structure for COM interface +sub HeaderVTable($) +{ + my $interface = shift; + my $res; + $res .= "#define " . uc($interface->{NAME}) . "_METHODS \\\n"; + if (defined($interface->{BASE})) { + $res .= "\t" . uc($interface->{BASE} . "_METHODS") . "\\\n"; + } + + my $data = $interface->{DATA}; + foreach my $d (@{$data}) { + $res .= "\t" . typelist::mapScalarType($d->{RETURN_TYPE}) . " (*$d->{NAME}) (struct $interface->{NAME} *d, TALLOC_CTX *mem_ctx" . GetArgumentProtoList($d) . ");\\\n" if ($d->{TYPE} eq "FUNCTION"); + } + $res .= "\n"; + $res .= "struct $interface->{NAME}_vtable {\n"; + $res .= "\t" . uc($interface->{NAME}) . "_METHODS\n"; + $res .= "};\n\n"; + + return $res; +} + +sub ParseInterface($) +{ + my $if = shift; + my $res; + + $res .="\n\n/* $if->{NAME} */\n"; + + $res .="#define COM_" . uc($if->{NAME}) . "_UUID $if->{PROPERTIES}->{uuid}\n\n"; + + $res .="struct $if->{NAME}_vtable;\n\n"; + + $res .="struct $if->{NAME} { + struct com_context *ctx; + struct $if->{NAME}_vtable *vtable; + void *object_data; +};\n\n"; + + $res.=HeaderVTable($if); + + foreach my $d (@{$if->{DATA}}) { + next if ($d->{TYPE} ne "FUNCTION"); + + $res .= "#define $if->{NAME}_$d->{NAME}(interface, mem_ctx" . GetArgumentList($d) . ") "; + + $res .= "((interface)->vtable->$d->{NAME}(interface, mem_ctx" . GetArgumentList($d) . "))"; + + $res .="\n"; + } + + return $res; +} + +sub ParseCoClass($) +{ + my $c = shift; + return "#define CLSID_$c->{NAME} $c->{PROPERTIES}->{uuid}\n\n"; +} + +sub Parse($) +{ + my $idl = shift; + my $res = ""; + + foreach my $x (@{$idl}) + { + if ($x->{TYPE} eq "INTERFACE" && util::has_property($x, "object")) { + $res.=ParseInterface($x); + } + + if ($x->{TYPE} eq "COCLASS") { + $res.=ParseCoClass($x); + } + } + + return $res; +} + +1; diff --git a/source4/build/pidl/proxy.pm b/source4/build/pidl/dcom_proxy.pm index 1eef131a6c..1a1b8de064 100644 --- a/source4/build/pidl/proxy.pm +++ b/source4/build/pidl/dcom_proxy.pm @@ -1,9 +1,12 @@ ################################################### -# DCOM proxy generator -# Copyright jelmer@samba.org 2003 +# DCOM parser for Samba +# Basically the glue between COM and DCE/RPC with NDR +# Copyright jelmer@samba.org 2003-2005 # released under the GNU GPL -package IdlProxy; +package DCOMProxy; + +use com_header; use strict; @@ -15,7 +18,7 @@ sub ParseVTable($$) my $name = shift; # Generate the vtable - $res .="\tstruct dcom_$interface->{NAME}_vtable $name = {"; + $res .="\tstruct $interface->{NAME}_vtable $name = {"; if (defined($interface->{BASE})) { $res .= "\n\t\t{},"; @@ -37,36 +40,38 @@ sub ParseRegFunc($) { my $interface = shift; - $res .= "static NTSTATUS dcom_$interface->{NAME}_init(void) + $res .= "static NTSTATUS dcom_proxy_$interface->{NAME}_init(void) { - struct dcom_interface iface; -"; - - ParseVTable($interface, "proxy"); + struct GUID base_iid; + struct GUID iid; + struct $interface->{NAME}_vtable proxy_vtable;"; if (defined($interface->{BASE})) { $res.= " const void *base_vtable; - GUID_from_string(DCERPC_" . (uc $interface->{BASE}) . "_UUID, &iface.base_iid); + GUID_from_string(DCERPC_" . (uc $interface->{BASE}) . "_UUID, &base_iid); - base_vtable = dcom_proxy_vtable_by_iid(&iface.base_iid); + base_vtable = dcom_proxy_vtable_by_iid(&base_iid); if (base_vtable == NULL) { + DEBUG(0, (\"No proxy registered for base interface\n\")); return NT_STATUS_FOOBAR; } + + memcpy(&proxy_vtable, base_vtable, sizeof(struct $interface->{BASE}_vtable)); + +"; + } + foreach my $x (@{$interface->{DATA}}) { + next unless ($x->{TYPE} eq "FUNCTION"); - proxy.base = *((const struct dcom_$interface->{BASE}_vtable *)base_vtable); - "; - } else { - $res .= "\tZERO_STRUCT(iface.base_iid);\n"; + $res .= "\tproxy_vtable.$x->{NAME} = dcom_proxy_$interface->{NAME}_$x->{NAME};\n"; } $res.= " - iface.num_methods = DCERPC_" . (uc $interface->{NAME}) . "_CALL_COUNT; - GUID_from_string(DCERPC_" . (uc $interface->{NAME}) . "_UUID, &iface.iid); - iface.proxy_vtable = talloc_memdup(talloc_autofree_context(), &proxy, sizeof(struct dcom_$interface->{NAME}_vtable)); + GUID_from_string(DCERPC_" . (uc $interface->{NAME}) . "_UUID, &iid); - return dcom_register_interface(&iface); + return dcom_register_proxy(&iid, &proxy_vtable); }\n\n"; } @@ -79,86 +84,67 @@ sub ParseFunction($$) my $name = $fn->{NAME}; my $uname = uc $name; - if (util::has_property($fn, "local")) { - $res .= " -static NTSTATUS dcom_proxy_$interface->{NAME}_$name(struct dcom_interface_p *d, TALLOC_CTX *mem_ctx, struct $name *r) -{ - /* FIXME */ - return NT_STATUS_NOT_SUPPORTED; -}\n"; - } else { - $res .= " -static struct rpc_request *dcom_proxy_$interface->{NAME}_$name\_send(struct dcom_interface_p *d, TALLOC_CTX *mem_ctx, struct $name *r) + $res.=" +static $fn->{RETURN_TYPE} dcom_proxy_$interface->{NAME}_$name(struct $interface->{NAME} *d, TALLOC_CTX *mem_ctx" . COMHeader::GetArgumentProtoList($fn) . ") { struct dcerpc_pipe *p; NTSTATUS status = dcom_get_pipe(d, &p); + struct $name r; + struct rpc_request *req; if (NT_STATUS_IS_ERR(status)) { - return NULL; + return status; } - ZERO_STRUCT(r->in.ORPCthis); - r->in.ORPCthis.version.MajorVersion = COM_MAJOR_VERSION; - r->in.ORPCthis.version.MinorVersion = COM_MINOR_VERSION; + ZERO_STRUCT(r.in.ORPCthis); + r.in.ORPCthis.version.MajorVersion = COM_MAJOR_VERSION; + r.in.ORPCthis.version.MinorVersion = COM_MINOR_VERSION; +"; + + # Put arguments into r + foreach my $a (@{$fn->{DATA}}) { + next if ($a->{NAME} eq "ORPCthis"); + next unless (util::has_property($a, "in")); + $res .= "\tr.in.$a->{NAME} = $a->{NAME};\n"; + } + $res .=" if (p->conn->flags & DCERPC_DEBUG_PRINT_IN) { - NDR_PRINT_IN_DEBUG($name, r); + NDR_PRINT_IN_DEBUG($name, &r); } - return dcerpc_ndr_request_send(p, &d->ipid, &dcerpc_table_$interface->{NAME}, DCERPC_$uname, mem_ctx, r); -} - -static NTSTATUS dcom_proxy_$interface->{NAME}_$name(struct dcom_interface_p *d, TALLOC_CTX *mem_ctx, struct $name *r) -{ - struct dcerpc_pipe *p; - NTSTATUS status = dcom_get_pipe(d, &p); - struct rpc_request *req; + status = dcerpc_ndr_request(p, &d->ipid, &dcerpc_table_$interface->{NAME}, DCERPC_$uname, mem_ctx, &r); - if (NT_STATUS_IS_ERR(status)) { - return status; + if (NT_STATUS_IS_OK(status) && (p->conn->flags & DCERPC_DEBUG_PRINT_OUT)) { + NDR_PRINT_OUT_DEBUG($name, r); } - req = dcom_proxy_$interface->{NAME}_$name\_send(d, mem_ctx, r); - if (req == NULL) return NT_STATUS_NO_MEMORY; - - status = dcerpc_ndr_request_recv(req); +"; - if (NT_STATUS_IS_OK(status) && (p->conn->flags & DCERPC_DEBUG_PRINT_OUT)) { - NDR_PRINT_OUT_DEBUG($name, r); + # Put r info back into arguments + foreach my $a (@{$fn->{DATA}}) { + next if ($a->{NAME} eq "ORPCthat"); + next unless (util::has_property($a, "out")); + $res .= "\t*$a->{NAME} = r.out.$a->{NAME};\n"; } - "; + if ($fn->{RETURN_TYPE} eq "NTSTATUS") { - $res .= "\tif (NT_STATUS_IS_OK(status)) status = r->out.result;\n"; + $res .= "\tif (NT_STATUS_IS_OK(status)) status = r.out.result;\n"; } + $res .= " - return status; -}"; - } - - $res .=" -NTSTATUS dcom_$interface->{NAME}_$name (struct dcom_interface_p *d, TALLOC_CTX *mem_ctx, struct $name *r) -{ - const struct dcom_$interface->{NAME}_vtable *table = d->vtable; - - if (table->$name == NULL) { - DEBUG(0, (\"Object does not implement $name of interface $interface->{NAME}\\n\")); - return NT_STATUS_NOT_IMPLEMENTED; - } - - return table->$name (d, mem_ctx, r); -} -"; + return r.out.result; +}\n\n"; } - ##################################################################### # parse the interface definitions sub ParseInterface($) { my($interface) = shift; my($data) = $interface->{DATA}; - $res = "/* DCOM proxy generated by pidl */\n\n"; + $res = "/* DCOM proxy for $interface->{NAME} generated by pidl */\n\n"; foreach my $d (@{$data}) { ($d->{TYPE} eq "FUNCTION") && ParseFunction($interface, $d); @@ -172,7 +158,7 @@ sub RegistrationFunction($$) my $idl = shift; my $basename = shift; - my $res = "NTSTATUS dcom_$basename\_init(void)\n"; + my $res = "\n\nNTSTATUS dcom_$basename\_init(void)\n"; $res .= "{\n"; $res .="\tNTSTATUS status = NT_STATUS_OK;\n"; foreach my $interface (@{$idl}) { @@ -198,4 +184,20 @@ sub RegistrationFunction($$) return $res; } +sub Parse($) +{ + my $pidl = shift; + my $res = ""; + + foreach my $x (@{$pidl}) { + next if ($x->{TYPE} ne "INTERFACE"); + next if util::has_property($x, "local"); + next unless util::has_property($x, "object"); + + $res .= ParseInterface($x); + } + + return $res; +} + 1; diff --git a/source4/build/pidl/stub.pm b/source4/build/pidl/dcom_stub.pm index 53be35b216..024037e2e8 100644 --- a/source4/build/pidl/stub.pm +++ b/source4/build/pidl/dcom_stub.pm @@ -1,11 +1,11 @@ ################################################### -# stub boilerplate generator -# Copyright jelmer@samba.org 2004 +# DCOM stub boilerplate generator +# Copyright jelmer@samba.org 2004-2005 # Copyright tridge@samba.org 2003 # Copyright metze@samba.org 2004 # released under the GNU GPL -package IdlStub; +package DCOMStub; use strict; @@ -16,7 +16,6 @@ sub pidl($) $res .= shift; } - ##################################################### # generate the switch statement for function dispatch sub gen_dispatch_switch($) @@ -290,6 +289,9 @@ NTSTATUS dcerpc_server_$name\_init(void) sub ParseInterface($) { my($interface) = shift; + + return "" if util::has_property($interface, "local"); + my($data) = $interface->{DATA}; my $count = 0; diff --git a/source4/build/pidl/header.pm b/source4/build/pidl/ndr_header.pm index eeb2886bce..c928ee1db3 100644 --- a/source4/build/pidl/header.pm +++ b/source4/build/pidl/ndr_header.pm @@ -3,7 +3,7 @@ # Copyright tridge@samba.org 2000 # released under the GNU GPL -package IdlHeader; +package NdrHeader; use strict; use needed; @@ -337,30 +337,10 @@ sub HeaderFnProto($$) pidl "void ndr_print_$name(struct ndr_print *ndr, const char *name, int flags, struct $name *r);\n"; - if (util::has_property($interface, "object")) { - pidl "NTSTATUS dcom_$interface->{NAME}_$name (struct dcom_interface_p *d, TALLOC_CTX *mem_ctx, struct $name *r);\n"; - } else { - pidl "NTSTATUS dcerpc_$name(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct $name *r);\n"; - pidl "struct rpc_request *dcerpc_$name\_send(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct $name *r);\n"; - } - pidl "\n"; -} - -##################################################################### -# generate vtable structure for DCOM interface -sub HeaderVTable($) -{ - my $interface = shift; - pidl "struct dcom_$interface->{NAME}_vtable {\n"; - if (defined($interface->{BASE})) { - pidl "\tstruct dcom_$interface->{BASE}\_vtable base;\n"; - } + pidl "NTSTATUS dcerpc_$name(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct $name *r);\n"; + pidl "struct rpc_request *dcerpc_$name\_send(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct $name *r);\n"; - my $data = $interface->{DATA}; - foreach my $d (@{$data}) { - pidl "\tNTSTATUS (*$d->{NAME}) (struct dcom_interface_p *d, TALLOC_CTX *mem_ctx, struct $d->{NAME} *r);\n" if ($d->{TYPE} eq "FUNCTION"); - } - pidl "};\n\n"; + pidl "\n"; } ##################################################################### @@ -439,9 +419,6 @@ sub HeaderInterface($) HeaderFnProto($interface, $d); } - (util::has_property($interface, "object")) && - HeaderVTable($interface); - pidl "#endif /* _HEADER_NDR_$interface->{NAME} */\n"; } diff --git a/source4/build/pidl/pidl.pl b/source4/build/pidl/pidl.pl index b535215d03..f7b213dcb0 100755 --- a/source4/build/pidl/pidl.pl +++ b/source4/build/pidl/pidl.pl @@ -15,12 +15,13 @@ use Getopt::Long; use File::Basename; use idl; use dump; -use header; +use ndr_header; +use ndr; use server; use client; -use proxy; -use stub; -use ndr; +use dcom_proxy; +use dcom_stub; +use com_header; use odl; use eparser; use validator; @@ -41,6 +42,8 @@ my($opt_parser) = 0; my($opt_eparser) = 0; my($opt_keep) = 0; my($opt_swig) = 0; +my($opt_dcom_proxy) = 0; +my($opt_com_header) = 0; my($opt_odl) = 0; my($opt_output); @@ -62,27 +65,29 @@ sub IdlParse($) sub ShowHelp() { print " - perl IDL parser and code generator - Copyright (C) tridge\@samba.org - - Usage: pidl.pl [options] <idlfile> - - Options: - --help this help page - --output OUTNAME put output in OUTNAME.* - --parse parse a idl file to a .pidl file - --dump dump a pidl file back to idl - --header create a C header file - --parser create a C NDR parser - --client create a C client - --server create server boilerplate - --template print a template for a pipe - --eparser create an ethereal parser - --swig create swig wrapper file - --diff run diff on the idl and dumped output - --keep keep the .pidl file - --odl accept ODL input - \n"; + perl IDL parser and code generator + Copyright (C) tridge\@samba.org + + Usage: pidl.pl [options] <idlfile> + + Options: + --help this help page + --output OUTNAME put output in OUTNAME.* + --parse parse a idl file to a .pidl file + --dump dump a pidl file back to idl + --header create a C header file + --parser create a C NDR parser + --client create a C client + --server create server boilerplate + --template print a template for a pipe + --eparser create an ethereal parser + --swig create swig wrapper file + --diff run diff on the idl and dumped output + --keep keep the .pidl file + --odl accept ODL input + --dcom-proxy create DCOM proxy (implies --odl) + --com-header create header for COM interfaces (implies --odl) + \n"; exit(0); } @@ -101,7 +106,9 @@ GetOptions ( 'diff' => \$opt_diff, 'odl' => \$opt_odl, 'keep' => \$opt_keep, - 'swig' => \$opt_swig + 'swig' => \$opt_swig, + 'dcom-proxy' => \$opt_dcom_proxy, + 'com-header' => \$opt_com_header ); if ($opt_help) { @@ -113,7 +120,6 @@ sub process_file($) { my $idl_file = shift; my $output; - my $podl; my $pidl; my $basename = basename($idl_file, ".idl"); @@ -144,18 +150,48 @@ sub process_file($) print IdlDump::Dump($pidl); } - if ($opt_header || $opt_parser) { + if ($opt_diff) { + my($tempfile) = util::ChangeExtension($output, ".tmp"); + util::FileSave($tempfile, IdlDump::Dump($pidl)); + system("diff -wu $idl_file $tempfile"); + unlink($tempfile); + } + + if ($opt_header || $opt_parser || $opt_com_header || $opt_dcom_proxy) { typelist::LoadIdl($pidl); } + if ($opt_com_header) { + my $res = COMHeader::Parse($pidl); + if ($res) { + my $h_filename = dirname($output) . "/com_$basename.h"; + util::FileSave($h_filename, + "#include \"librpc/gen_ndr/ndr_orpc.h\"\n" . + "#include \"librpc/gen_ndr/ndr_$basename.h\"\n" . + $res); + } + $opt_odl = 1; + } + + if ($opt_dcom_proxy) { + my $res = DCOMProxy::Parse($pidl); + if ($res) { + my ($client) = util::ChangeExtension($output, "_p.c"); + util::FileSave($client, + "#include \"includes.h\"\n" . + "#include \"librpc/gen_ndr/com_$basename.h\"\n" . + "#include \"lib/dcom/common/orpc.h\"\n". $res); + } + $opt_odl = 1; + } + if ($opt_odl) { - $podl = $pidl; - $pidl = ODL::ODL2IDL($podl); + $pidl = ODL::ODL2IDL($pidl); } if ($opt_header) { my($header) = util::ChangeExtension($output, ".h"); - util::FileSave($header, IdlHeader::Parse($pidl)); + util::FileSave($header, NdrHeader::Parse($pidl)); if ($opt_eparser) { my($eparserhdr) = dirname($output) . "/packet-dcerpc-$basename.h"; IdlEParser::RewriteHeader($pidl, $header, $eparserhdr); @@ -172,23 +208,14 @@ sub process_file($) my ($client) = util::ChangeExtension($output, "_c.c"); my $res = ""; my $h_filename = util::ChangeExtension($output, ".h"); - my $need_dcom_register = 0; $res .= "#include \"includes.h\"\n"; $res .= "#include \"$h_filename\"\n\n"; foreach my $x (@{$pidl}) { - if (util::has_property($x, "object")) { - $res .= IdlProxy::ParseInterface($x); - $need_dcom_register = 1; - } else { - $res .= IdlClient::ParseInterface($x); - } + $res .= IdlClient::ParseInterface($x); } - if ($need_dcom_register) { - $res .= IdlProxy::RegistrationFunction($pidl, $basename); - } util::FileSave($client, $res); } @@ -201,7 +228,7 @@ sub process_file($) next if ($x->{TYPE} ne "INTERFACE"); if (util::has_property($x, "object")) { - $dcom .= IdlStub::ParseInterface($x); + $dcom .= DCOMStub::ParseInterface($x); } else { $plain .= IdlServer::ParseInterface($x); } @@ -233,13 +260,6 @@ $dcom } } - if ($opt_diff) { - my($tempfile) = util::ChangeExtension($output, ".tmp"); - util::FileSave($tempfile, IdlDump::Dump($pidl)); - system("diff -wu $idl_file $tempfile"); - unlink($tempfile); - } - if ($opt_template) { print IdlTemplate::Parse($pidl); } |