summaryrefslogtreecommitdiff
path: root/source4/build
diff options
context:
space:
mode:
Diffstat (limited to 'source4/build')
-rw-r--r--source4/build/pidl/README2
-rw-r--r--source4/build/pidl/client.pm79
-rw-r--r--source4/build/pidl/header.pm45
-rw-r--r--source4/build/pidl/parser.pm9
-rwxr-xr-xsource4/build/pidl/pidl.pl13
-rw-r--r--source4/build/pidl/proxy.pm166
-rw-r--r--source4/build/pidl/server.pm13
-rw-r--r--source4/build/pidl/stub.pm221
8 files changed, 455 insertions, 93 deletions
diff --git a/source4/build/pidl/README b/source4/build/pidl/README
index 17a214cd58..c6432a8c0e 100644
--- a/source4/build/pidl/README
+++ b/source4/build/pidl/README
@@ -21,6 +21,8 @@ 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:
tables.pl - Generates a table of available interfaces from a list of IDL files
diff --git a/source4/build/pidl/client.pm b/source4/build/pidl/client.pm
index 549a5d0dd3..015ac05223 100644
--- a/source4/build/pidl/client.pm
+++ b/source4/build/pidl/client.pm
@@ -11,82 +11,33 @@ my($res);
#####################################################################
# parse a function
-sub ParseFunction($)
+sub ParseFunction($$)
{
+ my $interface = shift;
my $fn = shift;
my $name = $fn->{NAME};
my $uname = uc $name;
- return if (util::has_property($fn, "local"));
-
- my $objarg;
- if (util::has_property($fn, "object")) {
- $objarg = "&d->objref->u_objref.u_standard.std.ipid";
- # FIXME: Support custom marshalling
-
- $res .= "
-struct rpc_request *dcerpc_$name\_send(struct dcom_interface *d, TALLOC_CTX *mem_ctx, struct $name *r)
-{
- struct dcerpc_pipe *p;
- NTSTATUS status = dcom_get_pipe(d, &p);
-
- if (NT_STATUS_IS_ERR(status)) {
- return NULL;
- }
-
- ZERO_STRUCT(r->in.ORPCthis);
- r->in.ORPCthis.version.MajorVersion = COM_MAJOR_VERSION;
- r->in.ORPCthis.version.MinorVersion = COM_MINOR_VERSION;
-
-";
- } else {
- $objarg = "NULL";
- $res .= "
+ $res .= "
struct rpc_request *dcerpc_$name\_send(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct $name *r)
-{";
- }
+{
- $res.="
if (p->flags & DCERPC_DEBUG_PRINT_IN) {
NDR_PRINT_IN_DEBUG($name, r);
}
- return dcerpc_ndr_request_send(p, $objarg, DCERPC_$uname, mem_ctx,
+ return dcerpc_ndr_request_send(p, NULL, DCERPC_$uname, mem_ctx,
(ndr_push_flags_fn_t) ndr_push_$name,
(ndr_pull_flags_fn_t) ndr_pull_$name,
r, sizeof(*r));
}
-";
-
- if (util::has_property($fn, "object")) {
- $res .=
-"
-NTSTATUS dcerpc_$name(struct dcom_interface *d, TALLOC_CTX *mem_ctx, struct $name *r)
-{
- struct dcerpc_pipe *p;
- NTSTATUS status = dcom_get_pipe(d, &p);
- struct rpc_request *req;
-
- if (NT_STATUS_IS_ERR(status)) {
- return status;
- }
-
- ";
- $objarg = "d";
- } else {
- $res .=
-"
NTSTATUS dcerpc_$name(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct $name *r)
{
struct rpc_request *req;
NTSTATUS status;
- ";
- $objarg = "p";
- }
-
- $res .= "
- req = dcerpc_$name\_send($objarg, mem_ctx, r);
+
+ req = dcerpc_$name\_send(p, mem_ctx, r);
if (req == NULL) return NT_STATUS_NO_MEMORY;
status = dcerpc_ndr_request_recv(req);
@@ -112,22 +63,10 @@ sub ParseInterface($)
{
my($interface) = shift;
my($data) = $interface->{DATA};
+ $res = "/* Client functions generated by pidl */\n\n";
foreach my $d (@{$data}) {
($d->{TYPE} eq "FUNCTION") &&
- ParseFunction($d);
- }
-}
-
-
-#####################################################################
-# parse a parsed IDL structure back into an IDL file
-sub Parse($)
-{
- my($idl) = shift;
- $res = "/* dcerpc client calls generated by pidl */\n\n";
- foreach my $x (@{$idl}) {
- ($x->{TYPE} eq "INTERFACE") &&
- ParseInterface($x);
+ ParseFunction($interface, $d);
}
return $res;
}
diff --git a/source4/build/pidl/header.pm b/source4/build/pidl/header.pm
index b981200781..188fdd4f72 100644
--- a/source4/build/pidl/header.pm
+++ b/source4/build/pidl/header.pm
@@ -298,22 +298,42 @@ sub HeaderFunction($)
#####################################################################
# output prototypes for a IDL function
-sub HeaderFnProto($)
+sub HeaderFnProto($$)
{
+ my $interface = shift;
my $fn = shift;
my $name = $fn->{NAME};
- my $firstarg = "dcerpc_pipe";
- if (util::has_property($fn, "object")) {
- $firstarg = "dcom_interface";
- }
-
$res .= "void ndr_print_$name(struct ndr_print *, const char *, int, struct $name *);\n";
- $res .= "struct rpc_request *dcerpc_$name\_send(struct $firstarg *, TALLOC_CTX *, struct $name *);\n";
- $res .= "NTSTATUS dcerpc_$name(struct $firstarg *, TALLOC_CTX *, struct $name *);\n";
+
+ if (util::has_property($interface, "object")) {
+ $res .= "NTSTATUS dcom_$interface->{NAME}_$name (struct dcom_interface_p *, TALLOC_CTX *mem_ctx, struct $name *);\n";
+ } else {
+ $res .= "NTSTATUS dcerpc_$name(struct dcerpc_pipe *, TALLOC_CTX *, struct $name *);\n";
+ $res .= "struct rpc_request *dcerpc_$name\_send(struct dcerpc_pipe *, TALLOC_CTX *, struct $name *);\n";
+ }
$res .= "\n";
}
+
+#####################################################################
+# generate vtable structure for DCOM interface
+sub HeaderVTable($)
+{
+ my $interface = shift;
+ $res .= "struct dcom_$interface->{NAME}_vtable {\n";
+ if (defined($interface->{BASE})) {
+ $res .= "\tstruct dcom_$interface->{BASE}\_vtable base;\n";
+ }
+
+ my $data = $interface->{DATA};
+ foreach my $d (@{$data}) {
+ $res .= "\tNTSTATUS (*$d->{NAME}) (struct dcom_interface_p *, TALLOC_CTX *mem_ctx, struct $d->{NAME} *);\n" if ($d->{TYPE} eq "FUNCTION");
+ }
+ $res .= "};\n\n";
+}
+
+
#####################################################################
# parse the interface definitions
sub HeaderInterface($)
@@ -379,11 +399,14 @@ sub HeaderInterface($)
HeaderTypedef($d);
($d->{TYPE} eq "TYPEDEF") &&
HeaderTypedefProto($d);
- ($d->{TYPE} eq "FUNCTION") &&
+ ($d->{TYPE} eq "FUNCTION") &&
HeaderFunction($d);
- ($d->{TYPE} eq "FUNCTION") &&
- HeaderFnProto($d);
+ ($d->{TYPE} eq "FUNCTION") &&
+ HeaderFnProto($interface, $d);
}
+
+ (util::has_property($interface, "object")) &&
+ HeaderVTable($interface);
$res .= "#endif /* _HEADER_NDR_$interface->{NAME} */\n";
}
diff --git a/source4/build/pidl/parser.pm b/source4/build/pidl/parser.pm
index fd95f91665..e55e5ecd9c 100644
--- a/source4/build/pidl/parser.pm
+++ b/source4/build/pidl/parser.pm
@@ -9,6 +9,7 @@ package IdlParser;
use strict;
use client;
+use proxy;
use needed;
# the list of needed functions
@@ -1594,11 +1595,15 @@ sub Parse($$)
if ($x->{TYPE} eq "INTERFACE") {
needed::BuildNeeded($x);
ParseInterface($x);
+
+ if (util::has_property($x, "object")) {
+ pidl IdlProxy::ParseInterface($x);
+ } else {
+ pidl IdlClient::ParseInterface($x);
+ }
}
}
- pidl IdlClient::Parse($idl);
-
close(OUT);
}
diff --git a/source4/build/pidl/pidl.pl b/source4/build/pidl/pidl.pl
index fcd189d8cd..bb7f1f8ed6 100755
--- a/source4/build/pidl/pidl.pl
+++ b/source4/build/pidl/pidl.pl
@@ -17,6 +17,7 @@ use idl;
use dump;
use header;
use server;
+use stub;
use parser;
use eparser;
use validator;
@@ -139,7 +140,17 @@ sub process_file($)
if ($opt_server) {
my($server) = util::ChangeExtension($output, "_s.c");
- util::FileSave($server, IdlServer::Parse($pidl));
+ my $res = "";
+ foreach my $x (@{$pidl}) {
+ next if ($x->{TYPE} ne "INTERFACE");
+
+ if (util::has_property($x, "object")) {
+ $res .= IdlStub::ParseInterface($x);
+ } else {
+ $res .= IdlServer::ParseInterface($x);
+ }
+ }
+ util::FileSave($server, $res);
}
if ($opt_parser) {
diff --git a/source4/build/pidl/proxy.pm b/source4/build/pidl/proxy.pm
new file mode 100644
index 0000000000..b6d9733419
--- /dev/null
+++ b/source4/build/pidl/proxy.pm
@@ -0,0 +1,166 @@
+###################################################
+# DCOM proxy generator
+# Copyright jelmer@samba.org 2003
+# released under the GNU GPL
+
+package IdlProxy;
+
+use strict;
+
+my($res);
+
+sub ParseVTable($$)
+{
+ my $interface = shift;
+ my $name = shift;
+
+ # Generate the vtable
+ $res .="\tstruct dcom_$interface->{NAME}_vtable $name = {";
+
+ if (defined($interface->{BASE})) {
+ $res .= "\n\t\t{},";
+ }
+
+ my $data = $interface->{DATA};
+
+ foreach my $d (@{$data}) {
+ if ($d->{TYPE} eq "FUNCTION") {
+ $res .= "\n\t\tdcom_proxy_$interface->{NAME}_$d->{NAME}";
+ $res .= ",";
+ }
+ }
+
+ $res .= "\n\t};\n\n";
+}
+
+sub ParseRegFunc($)
+{
+ my $interface = shift;
+
+ $res .= "NTSTATUS dcom_$interface->{NAME}_init(void)
+{
+ struct dcom_interface iface;
+";
+
+ ParseVTable($interface, "proxy");
+
+ if (defined($interface->{BASE})) {
+ $res.= "
+ const void *base_vtable;
+
+ GUID_from_string(DCERPC_" . (uc $interface->{BASE}) . "_UUID, &iface.base_iid);
+
+ base_vtable = dcom_proxy_vtable_by_iid(&iface.base_iid);
+ if (base_vtable == NULL) {
+ return NT_STATUS_FOOBAR;
+ }
+
+ proxy.base = *((const struct dcom_$interface->{BASE}_vtable *)base_vtable);
+ ";
+ } else {
+ $res .= "\tZERO_STRUCT(iface.base_iid);\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(NULL, &proxy, sizeof(struct dcom_$interface->{NAME}_vtable));
+
+ return register_backend(\"dcom_interface\", &iface);
+}\n\n";
+}
+
+#####################################################################
+# parse a function
+sub ParseFunction($$)
+{
+ my $interface = shift;
+ my $fn = shift;
+ 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)
+{
+ struct dcerpc_pipe *p;
+ NTSTATUS status = dcom_get_pipe(d, &p);
+
+ if (NT_STATUS_IS_ERR(status)) {
+ return NULL;
+ }
+
+ ZERO_STRUCT(r->in.ORPCthis);
+ r->in.ORPCthis.version.MajorVersion = COM_MAJOR_VERSION;
+ r->in.ORPCthis.version.MinorVersion = COM_MINOR_VERSION;
+
+ if (p->flags & DCERPC_DEBUG_PRINT_IN) {
+ NDR_PRINT_IN_DEBUG($name, r);
+ }
+
+ return dcerpc_ndr_request_send(p, &d->ipid, DCERPC_$uname, mem_ctx,
+ (ndr_push_flags_fn_t) ndr_push_$name,
+ (ndr_pull_flags_fn_t) ndr_pull_$name,
+ r, sizeof(*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;
+
+ if (NT_STATUS_IS_ERR(status)) {
+ return status;
+ }
+
+ 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->flags & DCERPC_DEBUG_PRINT_OUT)) {
+ NDR_PRINT_OUT_DEBUG($name, r);
+ }
+ ";
+ if ($fn->{RETURN_TYPE} eq "NTSTATUS") {
+ $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)
+{
+ return ((const struct dcom_$interface->{NAME}_vtable *)d->vtable)->$name (d, mem_ctx, r);
+}
+";
+}
+
+
+#####################################################################
+# parse the interface definitions
+sub ParseInterface($)
+{
+ my($interface) = shift;
+ my($data) = $interface->{DATA};
+ $res = "/* DCOM stubs generated by pidl */\n\n";
+ foreach my $d (@{$data}) {
+ ($d->{TYPE} eq "FUNCTION") &&
+ ParseFunction($interface, $d);
+ }
+
+ ParseRegFunc($interface);
+}
+
+1;
diff --git a/source4/build/pidl/server.pm b/source4/build/pidl/server.pm
index 01c5adacb4..6a9ea157a9 100644
--- a/source4/build/pidl/server.pm
+++ b/source4/build/pidl/server.pm
@@ -203,19 +203,14 @@ NTSTATUS dcerpc_server_$name\_init(void)
";
}
-
#####################################################################
# parse a parsed IDL structure back into an IDL file
-sub Parse($)
+sub ParseInterface($)
{
- my($idl) = shift;
+ my($interface) = shift;
$res = "/* dcerpc server boilerplate generated by pidl */\n\n";
- foreach my $x (@{$idl}) {
- if ($x->{TYPE} eq "INTERFACE") {
- Boilerplate_Iface($x);
- Boilerplate_Ep_Server($x);
- }
- }
+ Boilerplate_Iface($interface);
+ Boilerplate_Ep_Server($interface);
return $res;
}
diff --git a/source4/build/pidl/stub.pm b/source4/build/pidl/stub.pm
new file mode 100644
index 0000000000..1cfb3cb11e
--- /dev/null
+++ b/source4/build/pidl/stub.pm
@@ -0,0 +1,221 @@
+###################################################
+# stub boilerplate generator
+# Copyright jelmer@samba.org 2004
+# Copyright tridge@samba.org 2003
+# released under the GNU GPL
+
+package IdlStub;
+
+use strict;
+
+my($res);
+
+sub pidl($)
+{
+ $res .= shift;
+}
+
+
+#####################################################
+# generate the switch statement for function dispatch
+sub gen_dispatch_switch($)
+{
+ my $data = shift;
+
+ my $count = 0;
+ foreach my $d (@{$data}) {
+ next if ($d->{TYPE} ne "FUNCTION");
+
+ pidl "\tcase $count: {\n";
+ pidl "\t\tstruct $d->{NAME} *r2 = r;\n";
+ pidl "\t\tif (DEBUGLEVEL > 10) {\n";
+ pidl "\t\t\tNDR_PRINT_FUNCTION_DEBUG($d->{NAME}, NDR_IN, r2);\n";
+ pidl "\t\t}\n";
+ if ($d->{RETURN_TYPE} && $d->{RETURN_TYPE} ne "void") {
+ pidl "\t\tr2->out.result = vtable->$d->{NAME}(iface, mem_ctx, r2);\n";
+ } else {
+ pidl "\t\tvtable->$d->{NAME}(iface, mem_ctx, r2);\n";
+ }
+ pidl "\t\tif (DEBUGLEVEL > 10 && dce_call->fault_code == 0) {\n";
+ pidl "\t\t\tNDR_PRINT_FUNCTION_DEBUG($d->{NAME}, NDR_OUT | NDR_SET_VALUES, r2);\n";
+ pidl "\t\t}\n";
+ pidl "\t\tif (dce_call->fault_code != 0) {\n";
+ pidl "\t\t\tDEBUG(2,(\"dcerpc_fault 0x%x in $d->{NAME}\\n\", dce_call->fault_code));\n";
+ pidl "\t\t}\n";
+ pidl "\t\tbreak;\n\t}\n";
+ $count++;
+ }
+}
+
+
+#####################################################################
+# produce boilerplate code for a interface
+sub Boilerplate_Iface($)
+{
+ my($interface) = shift;
+ my($data) = $interface->{DATA};
+ my $count = 0;
+ my $name = $interface->{NAME};
+ my $uname = uc $name;
+
+ foreach my $d (@{$data}) {
+ if ($d->{TYPE} eq "FUNCTION") { $count++; }
+ }
+
+ if ($count == 0) {
+ return;
+ }
+
+ pidl "
+static NTSTATUS $name\__op_bind(struct dcesrv_call_state *dce_call, const struct dcesrv_interface *iface)
+{
+#ifdef DCESRV_INTERFACE_$uname\_BIND
+ return DCESRV_INTERFACE_$uname\_BIND(dce_call,iface);
+#else
+ return NT_STATUS_OK;
+#endif
+}
+
+static void $name\__op_unbind(struct dcesrv_connection *dce_conn, const struct dcesrv_interface *iface)
+{
+#ifdef DCESRV_INTERFACE_$uname\_UNBIND
+ DCESRV_INTERFACE_$uname\_UNBIND(dce_conn,iface);
+#else
+ return;
+#endif
+}
+
+static NTSTATUS $name\__op_dispatch(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, void *r)
+{
+ uint16 opnum = dce_call->pkt.u.request.opnum;
+ struct GUID ipid = dce_call->pkt.u.request.object.object;
+ struct dcom_interface_p *iface = dcoms_get_ifacep(&ipid);
+ struct dcom_$name\_vtable *vtable = if->vtable;
+
+ dce_call->fault_code = 0;
+
+ switch (opnum) {
+";
+ gen_dispatch_switch($data);
+
+pidl "
+ default:
+ dce_call->fault_code = DCERPC_FAULT_OP_RNG_ERROR;
+ break;
+ }
+
+ if (dce_call->fault_code != 0) {
+ return NT_STATUS_NET_WRITE_FAULT;
+ }
+ return NT_STATUS_OK;
+}
+
+static const struct dcesrv_interface $name\_interface = {
+ &dcerpc_table_$name,
+ $name\__op_bind,
+ $name\__op_unbind,
+ $name\__op_dispatch
+};
+
+";
+}
+
+#####################################################################
+# produce boilerplate code for an endpoint server
+sub Boilerplate_Ep_Server($)
+{
+ my($interface) = shift;
+ my($data) = $interface->{DATA};
+ my $count = 0;
+ my $name = $interface->{NAME};
+ my $uname = uc $name;
+
+ foreach my $d (@{$data}) {
+ if ($d->{TYPE} eq "FUNCTION") { $count++; }
+ }
+
+ if ($count == 0) {
+ return;
+ }
+
+ pidl "
+static NTSTATUS $name\__op_init_server(struct dcesrv_context *dce_ctx, const struct dcesrv_endpoint_server *ep_server)
+{
+ int i;
+
+ for (i=0;i<$name\_interface.ndr->endpoints->count;i++) {
+ NTSTATUS ret;
+ const char *name = $name\_interface.ndr->endpoints->names[i];
+
+ ret = dcesrv_interface_register(dce_ctx, name, &$name\_interface, NULL);
+ if (!NT_STATUS_IS_OK(ret)) {
+ DEBUG(1,(\"$name\_op_init_server: failed to register endpoint \'%s\'\\n\",name));
+ return ret;
+ }
+ }
+
+ return NT_STATUS_OK;
+}
+
+static BOOL $name\__op_interface_by_uuid(struct dcesrv_interface *iface, const char *uuid, uint32 if_version)
+{
+ if ($name\_interface.ndr->if_version == if_version &&
+ strcmp($name\_interface.ndr->uuid, uuid)==0) {
+ memcpy(iface,&$name\_interface, sizeof(*iface));
+ return True;
+ }
+
+ return False;
+}
+
+static BOOL $name\__op_interface_by_name(struct dcesrv_interface *iface, const char *name)
+{
+ if (strcmp($name\_interface.ndr->name, name)==0) {
+ memcpy(iface,&$name\_interface, sizeof(*iface));
+ return True;
+ }
+
+ return False;
+}
+
+NTSTATUS dcerpc_server_$name\_init(void)
+{
+ NTSTATUS ret;
+ struct dcesrv_endpoint_server ep_server;
+
+ /* fill in our name */
+ ep_server.name = \"$name\";
+
+ /* fill in all the operations */
+ ep_server.init_server = $name\__op_init_server;
+
+ ep_server.interface_by_uuid = $name\__op_interface_by_uuid;
+ ep_server.interface_by_name = $name\__op_interface_by_name;
+
+ /* register ourselves with the DCERPC subsystem. */
+ ret = register_backend(\"dcerpc\", &ep_server);
+
+ if (!NT_STATUS_IS_OK(ret)) {
+ DEBUG(0,(\"Failed to register \'$name\' endpoint server!\\n\"));
+ return ret;
+ }
+
+ return ret;
+}
+
+";
+}
+
+sub ParseInterface($)
+{
+ my($interface) = shift;
+ $res = "/* dcerpc server boilerplate generated by pidl */\n\n";
+
+ Boilerplate_Iface($interface);
+ Boilerplate_Ep_Server($interface);
+
+ return $res;
+}
+
+1;
+